re PR go/78628 (GO fails to build a translation unit decl)

2017-08-21  Richard Biener  <rguenther@suse.de>

	include/
	* simple-object.h (simple_object_copy_lto_debug_sections): New
	function.

	libiberty/
	* simple-object-common.h (struct simple_object_functions): Add
	copy_lto_debug_sections hook.
	* simple-object.c: Include fcntl.h.
	(handle_lto_debug_sections): New helper function.
	(simple_object_copy_lto_debug_sections): New function copying
	early LTO debug sections to regular debug sections in a new file.
	(simple_object_start_write): Handle NULL segment_name.
	* simple-object-coff.c (simple_object_coff_functions): Adjust
	for not implemented copy_lto_debug_sections hook.
	* simple-object-mach-o.c (simple_object_mach_o_functions): Likewise.
	* simple-object-xcoff.c (simple_object_xcoff_functions): Likewise.
	* simple-object-elf.c (SHT_NULL, SHT_SYMTAB, SHT_RELA, SHT_REL,
	SHT_GROUP): Add various sectopn header types.
	(SHF_EXCLUDE): Add flag.
	(Elf32_External_Sym, Elf64_External_Sym): Add symbol struct.
	(ELF_ST_BIND, ELF_ST_TYPE, ELF_ST_INFO): Add accessors.
	(STT_OBJECT, STT_FUNC, STT_TLS, STT_GNU_IFUNC): Add Symbol types.
	(STV_DEFAULT): Add symbol visibility.
	(SHN_COMMON): Add special section index name.
	(struct simple_object_elf_write): New.
	(simple_object_elf_start_write): Adjust for new private data.
	(simple_object_elf_write_shdr): Pass in values for all fields
	we write.
	(simple_object_elf_write_to_file): Adjust.  Copy from recorded
	section headers if requested.
	(simple_object_elf_release_write): Release private data.
	(simple_object_elf_copy_lto_debug_sections): Copy and rename sections
	as denoted by PFN and all their dependences, symbols and relocations
	to the empty destination file.
	(simple_object_elf_functions): Adjust for copy_lto_debug_sections hook.

        gcc/
        * debug.h (struct gcc_debug_hooks): Add die_ref_for_decl and
        register_external_die hooks.
        (debug_false_tree_charstarstar_uhwistar): Declare.
        (debug_nothing_tree_charstar_uhwi): Likewise.
        * debug.c (do_nothing_debug_hooks): Adjust.
        (debug_false_tree_charstarstar_uhwistar): New do nothing.
        (debug_nothing_tree_charstar_uhwi): Likewise.
        * dbxout.c (dbx_debug_hooks): Adjust.
        (xcoff_debug_hooks): Likewise.
        * sdbout.c (sdb_debug_hooks): Likewise.
        * vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
        * dwarf2out.c (macinfo_label_base): New global.
	(dwarf2out_register_external_die): New function for the
	register_external_die hook.
        (dwarf2out_die_ref_for_decl): Likewise for die_ref_for_decl.
        (dwarf2_debug_hooks): Use them.
        (dwarf2_lineno_debug_hooks): Adjust.
        (struct die_struct): Add with_offset flag.
        (DEBUG_LTO_DWO_INFO_SECTION, DEBUG_LTO_INFO_SECTION,
        DEBUG_LTO_DWO_ABBREV_SECTION, DEBUG_LTO_ABBREV_SECTION,
        DEBUG_LTO_DWO_MACINFO_SECTION, DEBUG_LTO_MACINFO_SECTION,
        DEBUG_LTO_DWO_MACRO_SECTION, DEBUG_LTO_MACRO_SECTION,
        DEBUG_LTO_LINE_SECTION, DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
        DEBUG_LTO_STR_DWO_SECTION, DEBUG_STR_LTO_SECTION): New macros
        defining section names for the early LTO debug variants.
	(reset_indirect_string): New helper.
        (add_AT_external_die_ref): Helper for dwarf2out_register_external_die.
        (print_dw_val): Add support for offsetted symbol references.
	(get_ultimate_context): Split out from is_cxx.
	(is_cxx): Use get_ultimate_context.
	(is_fortran): Add decl overload.
        (compute_comp_unit_symbol): Split out worker from
	compute_section_prefix.
        (compute_section_prefix): Call compute_comp_unit_symbol and
	set comdat_type_p here.
        (output_die): Skip DIE symbol output for the LTO added one.
        Handle DIE symbol references with offset.
        (output_comp_unit): Guard section name mangling properly.
        For LTO debug sections emit a symbol at the section beginning
        which we use to refer to its DIEs.
        (add_abstract_origin_attribute): For DIEs registered via
        dwarf2out_register_external_die directly refer to the early
        DIE rather than indirectly through the shadow one we created.
	Remove obsolete call to dwarf2out_abstract_function for
	non-function/block origins.
        (gen_array_type_die): When generating early LTO debug do
        not emit DW_AT_string_length.
        (gen_formal_parameter_die): Do not re-create DIEs for PARM_DECLs
        late when in LTO.  As suggested place a gcc_unreachable for
	the DECL_ABSTRACT_P case.
        (gen_subprogram_die): Avoid another specification DIE
        for early built declarations/definitions for the late LTO case.
        (gen_variable_die): Add type references for late duplicated VLA dies
        when in late LTO.
        (gen_inlined_subroutine_die): Do not call dwarf2out_abstract_function,
        we have the abstract instance already.
        (process_scope_var): Adjust decl DIE contexts in LTO which
        first puts them in limbo.
        (gen_decl_die): Do not generate type DIEs late apart from
        types for VLAs or for decls we do not yet have a DIE.  Do not
	call dwarf2out_abstract_function late.
        (dwarf2out_early_global_decl): Make sure to create DIEs
        for abstract instances of a decl first.
        (dwarf2out_late_global_decl): Adjust comment.
        (output_macinfo_op): With multiple macro sections use
	macinfo_label_base to distinguish labels.
        (output_macinfo): Likewise.  Update macinfo_label_base.
	Pass in the line info label.
	(note_variable_value_in_expr): When generating LTO resolve
	all variable values here by generating DIEs as needed.
        (init_sections_and_labels): Add early LTO debug flag parameter
        and generate different sections and names if set.  Add generation
        counter for the labels so we can have multiple of them.
        (reset_dies): Helper to allow DIEs to be output multiple times.
        (dwarf2out_finish): When outputting DIEs to the fat part of an
	LTO object first reset DIEs.
        (dwarf2out_early_finish): Output early DIEs when generating LTO.
	(modified_type_die): Check for decl_ultimate_origin being self
	before recursing.
	(gen_type_die_with_usage): Likewise.
	(gen_typedef_die): Allow decl_ultimate_origin being self.
        (set_decl_abstract_flags): Remove.
        (set_block_abstract_flags): Likewise.
        (dwarf2out_abstract_function): Treat the early generated DIEs
        as the abstract copy and only add DW_AT_inline and
        DW_AT_artificial here and call set_decl_origin_self.
	If the DIE has an abstract origin don't do anything.
	* tree.c (free_lang_data): Build a dummy TRANSLATION_UNIT_DECL
	if we have none yet (Go fails to build one, PR78628).
	(variably_modified_type_p): Prevent endless recursion for Ada
	cyclic pointer types.
        * lto-streamer-in.c: Include debug.h.
        (dref_queue): New global.
        (lto_read_tree_1): Stream in DIE references.
        (lto_input_tree): Register DIE references.
	(input_function): Stream DECL_DEBUG_ARGS.
        * lto-streamer-out.c: Include debug.h.
        (lto_write_tree_1): Output DIE references.
        (DFS::DFS_write_tree_body): Follow DECL_ABSTRACT_ORIGIN.
	Force a TRANSLATION_UNIT_DECL DECL_CONTEXT for file-scope decls.
	(output_function): Stream DECL_DEBUG_ARGS.
        * tree-streamer-in.c (lto_input_ts_decl_common_tree_pointers):
        Stream DECL_ABSTRACT_ORIGIN.
        * tree-streamer-out.c (write_ts_decl_common_tree_pointers): Likewise.
	(write_ts_decl_minimal_tree_pointers): Force a TRANSLATION_UNIT_DECL
	DECL_CONTEXT for file-scope decls.
        * lto-streamer.h (struct dref_entry): Declare.
        (dref_queue): Likewise.
	* cfgexpand.c (pass_expand::execute): Do not call the
	outlining_inline_function hook here.
        * lto-wrapper.c (debug_obj): New global.
        (tool_cleanup): Unlink it if required.
        (debug_objcopy): New function.
        (run_gcc): Handle early debug sections in the IL files by
        extracting them to separate files, partially linkin them and
        feeding the result back as result to the linker.

        * config/darwin.h (DEBUG_LTO_INFO_SECTION, DEBUG_LTO_ABBREV_SECTION,
        DEBUG_LTO_MACINFO_SECTION, DEBUG_LTO_LINE_SECTION,
        DEBUG_STR_LTO_SECTION, DEBUG_LTO_MACRO_SECTION): Put early debug
        sections into a separate segment.
        * config/darwin.c (darwin_asm_named_section): Handle __GNU_DWARF_LTO
        segments.
        (darwin_asm_dwarf_section): Likewise.
        (darwin_asm_output_dwarf_offset): Likewise.

	* config/i386/i386.c (make_resolver_func): Set DECL_IGNORED_P.

        lto/
        * lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
        (lto_read_decls): Process TRANSLATION_UNIT_DECLs.  Remove
        TYPE_DECL debug processing, register DIE references from
        prevailing SCCs with the debug machinery.
        (lto_section_with_id): Handle LTO debug sections.

	libstdc++/
	* testsuite/libstdc++-prettyprinters/prettyprinters.exp: Run all
	tests with -flto as well if supported.

        testsuite/
	* c-c++-common/asan/global-overflow-1.c: Adjust diagnostic location
	regex to handle the LTO case.
	* c-c++-common/asan/heap-overflow-1.c: Likewise.
	* c-c++-common/asan/misalign-1.c: Likewise.
	* c-c++-common/asan/misalign-2.c: Likewise.
	* c-c++-common/asan/null-deref-1.c: Likewise.
	* c-c++-common/asan/stack-overflow-1.c: Likewise.
	* c-c++-common/asan/strncpy-overflow-1.c: Likewise.
	* c-c++-common/asan/use-after-free-1.c: Likewise.
	* c-c++-common/asan/alloca_big_alignment.c: Likewise.
	* c-c++-common/asan/alloca_detect_custom_size.c: Likewise.
	* c-c++-common/asan/alloca_overflow_partial.c: Likewise.
	* c-c++-common/asan/alloca_overflow_right.c: Likewise.
	* c-c++-common/asan/alloca_underflow_left.c: Likewise.
	* g++.dg/asan/large-func-test-1.C: Likewise.
	* gfortran.dg/save_6.f90: Add -flto -g variant of save_5.f90.

From-SVN: r251220
This commit is contained in:
Richard Biener 2017-08-21 10:29:00 +00:00 committed by Richard Biener
parent 9f33a5d9ac
commit 1ea85365b4
47 changed files with 2106 additions and 404 deletions

View File

@ -1,3 +1,131 @@
2017-08-21 Richard Biener <rguenther@suse.de>
* debug.h (struct gcc_debug_hooks): Add die_ref_for_decl and
register_external_die hooks.
(debug_false_tree_charstarstar_uhwistar): Declare.
(debug_nothing_tree_charstar_uhwi): Likewise.
* debug.c (do_nothing_debug_hooks): Adjust.
(debug_false_tree_charstarstar_uhwistar): New do nothing.
(debug_nothing_tree_charstar_uhwi): Likewise.
* dbxout.c (dbx_debug_hooks): Adjust.
(xcoff_debug_hooks): Likewise.
* sdbout.c (sdb_debug_hooks): Likewise.
* vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
* dwarf2out.c (macinfo_label_base): New global.
(dwarf2out_register_external_die): New function for the
register_external_die hook.
(dwarf2out_die_ref_for_decl): Likewise for die_ref_for_decl.
(dwarf2_debug_hooks): Use them.
(dwarf2_lineno_debug_hooks): Adjust.
(struct die_struct): Add with_offset flag.
(DEBUG_LTO_DWO_INFO_SECTION, DEBUG_LTO_INFO_SECTION,
DEBUG_LTO_DWO_ABBREV_SECTION, DEBUG_LTO_ABBREV_SECTION,
DEBUG_LTO_DWO_MACINFO_SECTION, DEBUG_LTO_MACINFO_SECTION,
DEBUG_LTO_DWO_MACRO_SECTION, DEBUG_LTO_MACRO_SECTION,
DEBUG_LTO_LINE_SECTION, DEBUG_LTO_DWO_STR_OFFSETS_SECTION,
DEBUG_LTO_STR_DWO_SECTION, DEBUG_STR_LTO_SECTION): New macros
defining section names for the early LTO debug variants.
(reset_indirect_string): New helper.
(add_AT_external_die_ref): Helper for dwarf2out_register_external_die.
(print_dw_val): Add support for offsetted symbol references.
(get_ultimate_context): Split out from is_cxx.
(is_cxx): Use get_ultimate_context.
(is_fortran): Add decl overload.
(compute_comp_unit_symbol): Split out worker from
compute_section_prefix.
(compute_section_prefix): Call compute_comp_unit_symbol and
set comdat_type_p here.
(output_die): Skip DIE symbol output for the LTO added one.
Handle DIE symbol references with offset.
(output_comp_unit): Guard section name mangling properly.
For LTO debug sections emit a symbol at the section beginning
which we use to refer to its DIEs.
(add_abstract_origin_attribute): For DIEs registered via
dwarf2out_register_external_die directly refer to the early
DIE rather than indirectly through the shadow one we created.
Remove obsolete call to dwarf2out_abstract_function for
non-function/block origins.
(gen_array_type_die): When generating early LTO debug do
not emit DW_AT_string_length.
(gen_formal_parameter_die): Do not re-create DIEs for PARM_DECLs
late when in LTO. As suggested place a gcc_unreachable for
the DECL_ABSTRACT_P case.
(gen_subprogram_die): Avoid another specification DIE
for early built declarations/definitions for the late LTO case.
(gen_variable_die): Add type references for late duplicated VLA dies
when in late LTO.
(gen_inlined_subroutine_die): Do not call dwarf2out_abstract_function,
we have the abstract instance already.
(process_scope_var): Adjust decl DIE contexts in LTO which
first puts them in limbo.
(gen_decl_die): Do not generate type DIEs late apart from
types for VLAs or for decls we do not yet have a DIE. Do not
call dwarf2out_abstract_function late.
(dwarf2out_early_global_decl): Make sure to create DIEs
for abstract instances of a decl first.
(dwarf2out_late_global_decl): Adjust comment.
(output_macinfo_op): With multiple macro sections use
macinfo_label_base to distinguish labels.
(output_macinfo): Likewise. Update macinfo_label_base.
Pass in the line info label.
(note_variable_value_in_expr): When generating LTO resolve
all variable values here by generating DIEs as needed.
(init_sections_and_labels): Add early LTO debug flag parameter
and generate different sections and names if set. Add generation
counter for the labels so we can have multiple of them.
(reset_dies): Helper to allow DIEs to be output multiple times.
(dwarf2out_finish): When outputting DIEs to the fat part of an
LTO object first reset DIEs.
(dwarf2out_early_finish): Output early DIEs when generating LTO.
(modified_type_die): Check for decl_ultimate_origin being self
before recursing.
(gen_type_die_with_usage): Likewise.
(gen_typedef_die): Allow decl_ultimate_origin being self.
(set_decl_abstract_flags): Remove.
(set_block_abstract_flags): Likewise.
(dwarf2out_abstract_function): Treat the early generated DIEs
as the abstract copy and only add DW_AT_inline and
DW_AT_artificial here and call set_decl_origin_self.
If the DIE has an abstract origin don't do anything.
* tree.c (free_lang_data): Build a dummy TRANSLATION_UNIT_DECL
if we have none yet (Go fails to build one, PR78628).
(variably_modified_type_p): Prevent endless recursion for Ada
cyclic pointer types.
* lto-streamer-in.c: Include debug.h.
(dref_queue): New global.
(lto_read_tree_1): Stream in DIE references.
(lto_input_tree): Register DIE references.
(input_function): Stream DECL_DEBUG_ARGS.
* lto-streamer-out.c: Include debug.h.
(lto_write_tree_1): Output DIE references.
(DFS::DFS_write_tree_body): Follow DECL_ABSTRACT_ORIGIN.
Force a TRANSLATION_UNIT_DECL DECL_CONTEXT for file-scope decls.
(output_function): Stream DECL_DEBUG_ARGS.
* tree-streamer-in.c (lto_input_ts_decl_common_tree_pointers):
Stream DECL_ABSTRACT_ORIGIN.
* tree-streamer-out.c (write_ts_decl_common_tree_pointers): Likewise.
(write_ts_decl_minimal_tree_pointers): Force a TRANSLATION_UNIT_DECL
DECL_CONTEXT for file-scope decls.
* lto-streamer.h (struct dref_entry): Declare.
(dref_queue): Likewise.
* cfgexpand.c (pass_expand::execute): Do not call the
outlining_inline_function hook here.
* lto-wrapper.c (debug_obj): New global.
(tool_cleanup): Unlink it if required.
(debug_objcopy): New function.
(run_gcc): Handle early debug sections in the IL files by
extracting them to separate files, partially linkin them and
feeding the result back as result to the linker.
* config/darwin.h (DEBUG_LTO_INFO_SECTION, DEBUG_LTO_ABBREV_SECTION,
DEBUG_LTO_MACINFO_SECTION, DEBUG_LTO_LINE_SECTION,
DEBUG_STR_LTO_SECTION, DEBUG_LTO_MACRO_SECTION): Put early debug
sections into a separate segment.
* config/darwin.c (darwin_asm_named_section): Handle __GNU_DWARF_LTO
segments.
(darwin_asm_dwarf_section): Likewise.
(darwin_asm_output_dwarf_offset): Likewise.
* config/i386/i386.c (make_resolver_func): Set DECL_IGNORED_P.
2017-08-21 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>

View File

@ -6529,12 +6529,6 @@ pass_expand::execute (function *fun)
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (parent)) = 1;
}
/* We are now committed to emitting code for this function. Do any
preparation, such as emitting abstract debug info for the inline
before it gets mangled by optimization. */
if (cgraph_function_possibly_inlined_p (current_function_decl))
(*debug_hooks->outlining_inline_function) (current_function_decl);
TREE_ASM_WRITTEN (current_function_decl) = 1;
/* After expanding, the return labels are no longer needed. */

View File

@ -1960,7 +1960,8 @@ darwin_asm_lto_end (void)
}
static void
darwin_asm_dwarf_section (const char *name, unsigned int flags, tree decl);
darwin_asm_dwarf_section (const char *name, unsigned int flags,
tree decl, bool is_for_lto);
/* Called for the TARGET_ASM_NAMED_SECTION hook. */
@ -2002,7 +2003,9 @@ darwin_asm_named_section (const char *name,
vec_safe_push (lto_section_names, e);
}
else if (strncmp (name, "__DWARF,", 8) == 0)
darwin_asm_dwarf_section (name, flags, decl);
darwin_asm_dwarf_section (name, flags, decl, false);
else if (strncmp (name, "__GNU_DWARF_LTO,", 16) == 0)
darwin_asm_dwarf_section (name, flags, decl, true);
else
fprintf (asm_out_file, "\t.section %s\n", name);
}
@ -2784,19 +2787,37 @@ static GTY (()) vec<dwarf_sect_used_entry, va_gc> *dwarf_sect_names_table;
static void
darwin_asm_dwarf_section (const char *name, unsigned int flags,
tree ARG_UNUSED (decl))
tree ARG_UNUSED (decl), bool is_for_lto)
{
unsigned i;
int namelen;
const char * sname;
int namelen, extra = 0;
const char *sect, *lto_add = "";
char sname[64];
dwarf_sect_used_entry *ref;
bool found = false;
gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
== (SECTION_DEBUG | SECTION_NAMED));
/* We know that the name starts with __DWARF, */
sname = name + 8;
namelen = strchr (sname, ',') - sname;
gcc_assert (namelen);
gcc_checking_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
== (SECTION_DEBUG | SECTION_NAMED));
/* We know that the name starts with __DWARF, or __GNU_DAWRF_LTO */
sect = strchr (name, ',') + 1;
namelen = strchr (sect, ',') - sect;
gcc_checking_assert (namelen);
/* The section switch is output as written... */
fprintf (asm_out_file, "\t.section %s\n", name);
/* ... but the string we keep to make section start labels needs
adjustment for lto cases. */
if (is_for_lto)
{
lto_add = "_lto";
extra = 4;
}
snprintf (sname, 64, "%.*s%.*s", namelen, sect, extra, lto_add);
namelen += extra;
if (dwarf_sect_names_table == NULL)
vec_alloc (dwarf_sect_names_table, 16);
else
@ -2814,7 +2835,6 @@ darwin_asm_dwarf_section (const char *name, unsigned int flags,
}
}
fprintf (asm_out_file, "\t.section %s\n", name);
if (!found)
{
dwarf_sect_used_entry e;
@ -2867,14 +2887,24 @@ darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab,
HOST_WIDE_INT offset, section *base)
{
char sname[64];
int namelen;
int namelen, extra = 0;
bool is_for_lto;
const char *lto_add = "";
gcc_assert (base->common.flags & SECTION_NAMED);
gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
gcc_assert (strchr (base->named.name + 8, ','));
gcc_checking_assert (base->common.flags & SECTION_NAMED);
is_for_lto = strncmp (base->named.name, "__GNU_DWARF_LTO,", 16) == 0;
gcc_checking_assert (is_for_lto
|| strncmp (base->named.name, "__DWARF,", 8) == 0);
const char *name = strchr (base->named.name, ',') + 1;
gcc_checking_assert (name);
namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
namelen = strchr (name, ',') - (name);
if (is_for_lto)
{
lto_add = "_lto";
extra = 4;
}
snprintf (sname, 64, "*Lsection%.*s%.*s", namelen, name, extra, lto_add);
darwin_asm_output_dwarf_delta (file, size, lab, sname, offset);
}

View File

@ -445,7 +445,14 @@ extern GTY(()) int darwin_ms_struct;
#define DEBUG_PUBTYPES_SECTION "__DWARF,__debug_pubtypes,regular,debug"
#define DEBUG_STR_SECTION "__DWARF,__debug_str,regular,debug"
#define DEBUG_RANGES_SECTION "__DWARF,__debug_ranges,regular,debug"
#define DEBUG_MACRO_SECTION "__DWARF,__debug_macro,regular,debug"
#define DEBUG_MACRO_SECTION "__DWARF,__debug_macro,regular,debug"
#define DEBUG_LTO_INFO_SECTION "__GNU_DWARF_LTO,__debug_info,regular,debug"
#define DEBUG_LTO_ABBREV_SECTION "__GNU_DWARF_LTO,__debug_abbrev,regular,debug"
#define DEBUG_LTO_MACINFO_SECTION "__GNU_DWARF_LTO,__debug_macinfo,regular,debug"
#define DEBUG_LTO_LINE_SECTION "__GNU_DWARF_LTO,__debug_line,regular,debug"
#define DEBUG_LTO_STR_SECTION "__GNU_DWARF_LTO,__debug_str,regular,debug"
#define DEBUG_LTO_MACRO_SECTION "__GNU_DWARF_LTO,__debug_macro,regular,debug"
#define TARGET_WANT_DEBUG_PUB_SECTIONS true

View File

@ -33984,7 +33984,7 @@ make_resolver_func (const tree default_decl,
DECL_NAME (decl) = decl_name;
TREE_USED (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 0;
DECL_IGNORED_P (decl) = 1;
TREE_PUBLIC (decl) = 0;
DECL_UNINLINABLE (decl) = 1;

View File

@ -372,6 +372,8 @@ const struct gcc_debug_hooks dbx_debug_hooks =
dbxout_late_global_decl, /* late_global_decl */
dbxout_type_decl, /* type_decl */
debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
debug_nothing_tree_charstar_uhwi, /* register_external_die */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
debug_nothing_rtx_code_label, /* label */
@ -412,6 +414,8 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
dbxout_late_global_decl, /* late_global_decl */
dbxout_type_decl, /* type_decl */
debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
debug_nothing_tree_charstar_uhwi, /* register_external_die */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
debug_nothing_rtx_code_label, /* label */

View File

@ -48,6 +48,8 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
debug_nothing_tree, /* late_global_decl */
debug_nothing_tree_int, /* type_decl */
debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
debug_nothing_tree_charstar_uhwi, /* register_external_die */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
debug_nothing_rtx_code_label, /* label */
@ -147,3 +149,16 @@ debug_nothing_tree_int (tree decl ATTRIBUTE_UNUSED,
int local ATTRIBUTE_UNUSED)
{
}
bool
debug_false_tree_charstarstar_uhwistar (tree, const char **,
unsigned HOST_WIDE_INT *)
{
return false;
}
void
debug_nothing_tree_charstar_uhwi (tree, const char *,
unsigned HOST_WIDE_INT)
{
}

View File

@ -148,6 +148,14 @@ struct gcc_debug_hooks
tree context, bool child,
bool implicit);
/* Return true if a DIE for the tree is available and return a symbol
and offset that can be used to refer to it externally. */
bool (* die_ref_for_decl) (tree, const char **, unsigned HOST_WIDE_INT *);
/* Early debug information for the tree is available at symbol plus
offset externally. */
void (* register_external_die) (tree, const char *, unsigned HOST_WIDE_INT);
/* DECL is an inline function, whose body is present, but which is
not being output at this point. */
void (* deferred_inline_function) (tree decl);
@ -212,6 +220,10 @@ extern void debug_nothing_tree_tree_tree_bool_bool (tree, tree, tree,
extern bool debug_true_const_tree (const_tree);
extern void debug_nothing_rtx_insn (rtx_insn *);
extern void debug_nothing_rtx_code_label (rtx_code_label *);
extern bool debug_false_tree_charstarstar_uhwistar (tree, const char **,
unsigned HOST_WIDE_INT *);
extern void debug_nothing_tree_charstar_uhwi (tree, const char *,
unsigned HOST_WIDE_INT);
/* Hooks for various debug formats. */
extern const struct gcc_debug_hooks do_nothing_debug_hooks;

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see
#include "except.h"
#include "cgraph.h"
#include "cfgloop.h"
#include "debug.h"
struct freeing_string_slot_hasher : string_slot_hasher
@ -1038,6 +1039,16 @@ input_function (tree fn_decl, struct data_in *data_in,
DECL_RESULT (fn_decl) = stream_read_tree (ib, data_in);
DECL_ARGUMENTS (fn_decl) = streamer_read_chain (ib, data_in);
/* Read debug args if available. */
unsigned n_debugargs = streamer_read_uhwi (ib);
if (n_debugargs)
{
vec<tree, va_gc> **debugargs = decl_debug_args_insert (fn_decl);
vec_safe_grow (*debugargs, n_debugargs);
for (unsigned i = 0; i < n_debugargs; ++i)
(**debugargs)[i] = stream_read_tree (ib, data_in);
}
/* Read the tree of lexical scopes for the function. */
DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
unsigned block_leaf_count = streamer_read_uhwi (ib);
@ -1322,6 +1333,10 @@ lto_input_variable_constructor (struct lto_file_decl_data *file_data,
}
/* Queue of acummulated decl -> DIE mappings. Similar to locations those
are only applied to prevailing tree nodes during tree merging. */
vec<dref_entry> dref_queue;
/* Read the physical representation of a tree node EXPR from
input block IB using the per-file context in DATA_IN. */
@ -1341,6 +1356,23 @@ lto_read_tree_1 (struct lto_input_block *ib, struct data_in *data_in, tree expr)
&& TREE_CODE (expr) != FUNCTION_DECL
&& TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
DECL_INITIAL (expr) = stream_read_tree (ib, data_in);
/* Stream references to early generated DIEs. Keep in sync with the
trees handled in dwarf2out_register_external_die. */
if ((DECL_P (expr)
&& TREE_CODE (expr) != FIELD_DECL
&& TREE_CODE (expr) != DEBUG_EXPR_DECL
&& TREE_CODE (expr) != TYPE_DECL)
|| TREE_CODE (expr) == BLOCK)
{
const char *str = streamer_read_string (data_in, ib);
if (str)
{
unsigned HOST_WIDE_INT off = streamer_read_uhwi (ib);
dref_entry e = { expr, str, off };
dref_queue.safe_push (e);
}
}
}
/* Read the physical representation of a tree node with tag TAG from
@ -1486,6 +1518,13 @@ lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
{
unsigned len, entry_len;
lto_input_scc (ib, data_in, &len, &entry_len);
/* Register DECLs with the debuginfo machinery. */
while (!dref_queue.is_empty ())
{
dref_entry e = dref_queue.pop ();
debug_hooks->register_external_die (e.decl, e.sym, e.off);
}
}
return lto_input_tree_1 (ib, data_in, tag, 0);
}

View File

@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "cfgloop.h"
#include "builtins.h"
#include "gomp-constants.h"
#include "debug.h"
static void lto_write_tree (struct output_block*, tree, bool);
@ -406,6 +407,26 @@ lto_write_tree_1 (struct output_block *ob, tree expr, bool ref_p)
(ob->decl_state->symtab_node_encoder, expr);
stream_write_tree (ob, initial, ref_p);
}
/* Stream references to early generated DIEs. Keep in sync with the
trees handled in dwarf2out_die_ref_for_decl. */
if ((DECL_P (expr)
&& TREE_CODE (expr) != FIELD_DECL
&& TREE_CODE (expr) != DEBUG_EXPR_DECL
&& TREE_CODE (expr) != TYPE_DECL)
|| TREE_CODE (expr) == BLOCK)
{
const char *sym;
unsigned HOST_WIDE_INT off;
if (debug_info_level > DINFO_LEVEL_NONE
&& debug_hooks->die_ref_for_decl (expr, &sym, &off))
{
streamer_write_string (ob, ob->main_stream, sym, true);
streamer_write_uhwi (ob, off);
}
else
streamer_write_string (ob, ob->main_stream, NULL, true);
}
}
/* Write a physical representation of tree node EXPR to output block
@ -745,7 +766,11 @@ DFS::DFS_write_tree_body (struct output_block *ob,
;
else
DFS_follow_tree_edge (DECL_NAME (expr));
DFS_follow_tree_edge (DECL_CONTEXT (expr));
if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
&& ! DECL_CONTEXT (expr))
DFS_follow_tree_edge ((*all_translation_units)[0]);
else
DFS_follow_tree_edge (DECL_CONTEXT (expr));
}
if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
@ -765,6 +790,7 @@ DFS::DFS_write_tree_body (struct output_block *ob,
declarations which should be eliminated by decl merging. Be sure none
leaks to this point. */
gcc_assert (DECL_ABSTRACT_ORIGIN (expr) != error_mark_node);
DFS_follow_tree_edge (DECL_ABSTRACT_ORIGIN (expr));
if ((VAR_P (expr)
|| TREE_CODE (expr) == PARM_DECL)
@ -2057,6 +2083,17 @@ output_function (struct cgraph_node *node)
stream_write_tree (ob, DECL_RESULT (function), true);
streamer_write_chain (ob, DECL_ARGUMENTS (function), true);
/* Output debug args if available. */
vec<tree, va_gc> **debugargs = decl_debug_args_lookup (function);
if (! debugargs)
streamer_write_uhwi (ob, 0);
else
{
streamer_write_uhwi (ob, (*debugargs)->length ());
for (unsigned i = 0; i < (*debugargs)->length (); ++i)
stream_write_tree (ob, (**debugargs)[i], true);
}
/* Output DECL_INITIAL for the function, which contains the tree of
lexical scopes. */
stream_write_tree (ob, DECL_INITIAL (function), true);

View File

@ -1212,4 +1212,14 @@ DEFINE_DECL_STREAM_FUNCS (TYPE_DECL, type_decl)
DEFINE_DECL_STREAM_FUNCS (NAMESPACE_DECL, namespace_decl)
DEFINE_DECL_STREAM_FUNCS (LABEL_DECL, label_decl)
/* Entry for the delayed registering of decl -> DIE references. */
struct dref_entry {
tree decl;
const char *sym;
unsigned HOST_WIDE_INT off;
};
extern vec<dref_entry> dref_queue;
#endif /* GCC_LTO_STREAMER_H */

View File

@ -70,6 +70,7 @@ static char **output_names;
static char **offload_names;
static char *offload_objects_file_name;
static char *makefile;
static char *debug_obj;
const char tool_name[] = "lto-wrapper";
@ -88,6 +89,8 @@ tool_cleanup (bool)
maybe_unlink (offload_objects_file_name);
if (makefile)
maybe_unlink (makefile);
if (debug_obj)
maybe_unlink (debug_obj);
for (i = 0; i < nr; ++i)
{
maybe_unlink (input_names[i]);
@ -960,6 +963,67 @@ find_and_merge_options (int fd, off_t file_offset, const char *prefix,
return true;
}
/* Copy early debug info sections from INFILE to a new file whose name
is returned. Return NULL on error. */
const char *
debug_objcopy (const char *infile)
{
const char *outfile;
const char *errmsg;
int err;
const char *p;
off_t inoff = 0;
long loffset;
int consumed;
if ((p = strrchr (infile, '@'))
&& p != infile
&& sscanf (p, "@%li%n", &loffset, &consumed) >= 1
&& strlen (p) == (unsigned int) consumed)
{
char *fname = xstrdup (infile);
fname[p - infile] = '\0';
infile = fname;
inoff = (off_t) loffset;
}
int infd = open (infile, O_RDONLY);
if (infd == -1)
return NULL;
simple_object_read *inobj = simple_object_start_read (infd, inoff,
"__GNU_LTO",
&errmsg, &err);
if (!inobj)
return NULL;
off_t off, len;
if (simple_object_find_section (inobj, ".gnu.debuglto_.debug_info",
&off, &len, &errmsg, &err) != 1)
{
if (errmsg)
fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
simple_object_release_read (inobj);
close (infd);
return NULL;
}
outfile = make_temp_file ("debugobjtem");
errmsg = simple_object_copy_lto_debug_sections (inobj, outfile, &err);
if (errmsg)
{
unlink_if_ordinary (outfile);
fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
}
simple_object_release_read (inobj);
close (infd);
return outfile;
}
/* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
static void
@ -984,8 +1048,10 @@ run_gcc (unsigned argc, char *argv[])
int new_head_argc;
bool have_lto = false;
bool have_offload = false;
unsigned lto_argc = 0;
char **lto_argv;
unsigned lto_argc = 0, ltoobj_argc = 0;
char **lto_argv, **ltoobj_argv;
bool skip_debug = false;
unsigned n_debugobj;
/* Get the driver and options. */
collect_gcc = getenv ("COLLECT_GCC");
@ -1004,6 +1070,7 @@ run_gcc (unsigned argc, char *argv[])
/* Allocate array for input object files with LTO IL,
and for possible preceding arguments. */
lto_argv = XNEWVEC (char *, argc);
ltoobj_argv = XNEWVEC (char *, argc);
/* Look at saved options in the IL files. */
for (i = 1; i < argc; ++i)
@ -1046,7 +1113,7 @@ run_gcc (unsigned argc, char *argv[])
collect_gcc))
{
have_lto = true;
lto_argv[lto_argc++] = argv[i];
ltoobj_argv[ltoobj_argc++] = argv[i];
}
close (fd);
}
@ -1107,6 +1174,17 @@ run_gcc (unsigned argc, char *argv[])
}
}
/* Output lto-wrapper invocation command. */
if (verbose)
{
for (i = 0; i < argc; ++i)
{
fputs (argv[i], stderr);
fputc (' ', stderr);
}
fputc ('\n', stderr);
}
if (no_partition)
{
lto_mode = LTO_MODE_LTO;
@ -1296,18 +1374,105 @@ cont1:
obstack_ptr_grow (&argv_obstack, "-fwpa");
}
/* Append the input objects and possible preceding arguments. */
/* Append input arguments. */
for (i = 0; i < lto_argc; ++i)
obstack_ptr_grow (&argv_obstack, lto_argv[i]);
/* Append the input objects. */
for (i = 0; i < ltoobj_argc; ++i)
obstack_ptr_grow (&argv_obstack, ltoobj_argv[i]);
obstack_ptr_grow (&argv_obstack, NULL);
new_argv = XOBFINISH (&argv_obstack, const char **);
argv_ptr = &new_argv[new_head_argc];
fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true);
/* Handle early generated debug information. At compile-time
we output early DWARF debug info into .gnu.debuglto_ prefixed
sections. LTRANS object DWARF debug info refers to that.
So we need to transfer the .gnu.debuglto_ sections to the final
link. Ideally the linker plugin interface would allow us to
not claim those sections and instruct the linker to keep
them, renaming them in the process. For now we extract and
rename those sections via a simple-object interface to produce
regular objects containing only the early debug info. We
then partially link those to a single early debug info object
and pass that as additional output back to the linker plugin. */
/* Prepare the partial link to gather the compile-time generated
debug-info into a single input for the final link. */
debug_obj = make_temp_file ("debugobj");
obstack_ptr_grow (&argv_obstack, collect_gcc);
for (i = 1; i < decoded_options_count; ++i)
{
/* Retain linker choice and -B. */
if (decoded_options[i].opt_index == OPT_B
|| decoded_options[i].opt_index == OPT_fuse_ld_bfd
|| decoded_options[i].opt_index == OPT_fuse_ld_gold)
append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
/* Retain all target options, this preserves -m32 for example. */
if (cl_options[decoded_options[i].opt_index].flags & CL_TARGET)
append_linker_options (&argv_obstack, &decoded_options[i-1], 2);
/* Recognize -g0. */
if (decoded_options[i].opt_index == OPT_g
&& strcmp (decoded_options[i].arg, "0") == 0)
skip_debug = true;
}
obstack_ptr_grow (&argv_obstack, "-r");
obstack_ptr_grow (&argv_obstack, "-nostdlib");
obstack_ptr_grow (&argv_obstack, "-o");
obstack_ptr_grow (&argv_obstack, debug_obj);
/* Copy the early generated debug info from the objects to temporary
files and append those to the partial link commandline. */
n_debugobj = 0;
if (! skip_debug)
for (i = 0; i < ltoobj_argc; ++i)
{
const char *tem;
if ((tem = debug_objcopy (ltoobj_argv[i])))
{
obstack_ptr_grow (&argv_obstack, tem);
n_debugobj++;
}
}
/* Link them all into a single object. Ideally this would reduce
disk space usage mainly due to .debug_str merging but unfortunately
GNU ld doesn't perform this with -r. */
if (n_debugobj)
{
obstack_ptr_grow (&argv_obstack, NULL);
const char **debug_link_argv = XOBFINISH (&argv_obstack, const char **);
fork_execute (debug_link_argv[0],
CONST_CAST (char **, debug_link_argv), false);
/* And dispose the temporaries. */
for (i = 0; debug_link_argv[i]; ++i)
;
for (--i; i > 0; --i)
{
if (strcmp (debug_link_argv[i], debug_obj) == 0)
break;
maybe_unlink (debug_link_argv[i]);
}
}
else
{
unlink_if_ordinary (debug_obj);
free (debug_obj);
debug_obj = NULL;
skip_debug = true;
}
if (lto_mode == LTO_MODE_LTO)
{
printf ("%s\n", flto_out);
if (!skip_debug)
{
printf ("%s\n", debug_obj);
free (debug_obj);
debug_obj = NULL;
}
free (flto_out);
flto_out = NULL;
}
@ -1456,6 +1621,12 @@ cont:
for (i = 0; i < nr; ++i)
maybe_unlink (input_names[i]);
}
if (!skip_debug)
{
printf ("%s\n", debug_obj);
free (debug_obj);
debug_obj = NULL;
}
for (i = 0; i < nr; ++i)
{
fputs (output_names[i], stdout);

View File

@ -1,3 +1,11 @@
2017-08-21 Richard Biener <rguenther@suse.de>
* lto.c (unify_scc): Truncate DIE reference queue for dropped SCCs.
(lto_read_decls): Process TRANSLATION_UNIT_DECLs. Remove
TYPE_DECL debug processing, register DIE references from
prevailing SCCs with the debug machinery.
(lto_section_with_id): Handle LTO debug sections.
2017-08-16 Nathan Sidwell <nathan@acm.org>
* lto.c (mentions_vars_p_type): Use TYPE_LANG_SLOT_1.

View File

@ -1633,6 +1633,9 @@ unify_scc (struct data_in *data_in, unsigned from,
free_node (scc->entries[i]);
}
/* Drop DIE references. */
dref_queue.truncate (0);
break;
}
@ -1708,8 +1711,7 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
from);
if (len == 1
&& (TREE_CODE (first) == IDENTIFIER_NODE
|| TREE_CODE (first) == INTEGER_CST
|| TREE_CODE (first) == TRANSLATION_UNIT_DECL))
|| TREE_CODE (first) == INTEGER_CST))
continue;
/* Try to unify the SCC with already existing ones. */
@ -1748,16 +1750,6 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
if (TREE_CODE (t) == INTEGER_CST
&& !TREE_OVERFLOW (t))
cache_integer_cst (t);
/* Register TYPE_DECLs with the debuginfo machinery. */
if (!flag_wpa
&& TREE_CODE (t) == TYPE_DECL)
{
/* Dwarf2out needs location information.
TODO: Moving this out of the streamer loop may noticealy
improve ltrans linemap memory use. */
data_in->location_cache.apply_location_cache ();
debug_hooks->type_decl (t, !DECL_FILE_SCOPE_P (t));
}
if (!flag_ltrans)
{
/* Register variables and functions with the
@ -1773,6 +1765,14 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
vec_safe_push (tree_with_vars, t);
}
}
/* Register DECLs with the debuginfo machinery. */
while (!dref_queue.is_empty ())
{
dref_entry e = dref_queue.pop ();
debug_hooks->register_external_die (e.decl, e.sym, e.off);
}
if (seen_type)
num_type_scc_trees += len;
}
@ -1952,7 +1952,12 @@ lto_section_with_id (const char *name, unsigned HOST_WIDE_INT *id)
if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
return 0;
s = strrchr (name, '.');
return s && sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
if (!s)
return 0;
/* If the section is not suffixed with an ID return. */
if ((size_t)(s - name) == strlen (section_name_prefix))
return 0;
return sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
}
/* Create file_data of each sub file id */

View File

@ -302,6 +302,8 @@ const struct gcc_debug_hooks sdb_debug_hooks =
sdbout_late_global_decl, /* late_global_decl */
sdbout_symbol, /* type_decl */
debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
debug_nothing_tree_charstar_uhwi, /* register_external_die */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
sdbout_label, /* label */

View File

@ -1,3 +1,22 @@
2017-08-21 Richard Biener <rguenther@suse.de>
* c-c++-common/asan/global-overflow-1.c: Adjust diagnostic location
regex to handle the LTO case.
* c-c++-common/asan/heap-overflow-1.c: Likewise.
* c-c++-common/asan/misalign-1.c: Likewise.
* c-c++-common/asan/misalign-2.c: Likewise.
* c-c++-common/asan/null-deref-1.c: Likewise.
* c-c++-common/asan/stack-overflow-1.c: Likewise.
* c-c++-common/asan/strncpy-overflow-1.c: Likewise.
* c-c++-common/asan/use-after-free-1.c: Likewise.
* c-c++-common/asan/alloca_big_alignment.c: Likewise.
* c-c++-common/asan/alloca_detect_custom_size.c: Likewise.
* c-c++-common/asan/alloca_overflow_partial.c: Likewise.
* c-c++-common/asan/alloca_overflow_right.c: Likewise.
* c-c++-common/asan/alloca_underflow_left.c: Likewise.
* g++.dg/asan/large-func-test-1.C: Likewise.
* gfortran.dg/save_6.f90: Add -flto -g variant of save_5.f90.
2017-08-21 Richard Biener <rguenther@suse.de>
PR middle-end/81884

View File

@ -17,6 +17,6 @@ int main() {
}
/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_big_alignment.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_big_alignment.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r\]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
/* { dg-output "\[^\n\r]*in foo.*alloca_big_alignment.c.*(\n|\r\n|\r)" */

View File

@ -22,6 +22,6 @@ int main(int argc, char **argv) {
}
/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_detect_custom_size.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_detect_custom_size.c:16|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
/* { dg-output "\[^\n\r]*in foo.*alloca_detect_custom_size.c.*(\n|\r\n|\r)" */

View File

@ -17,6 +17,6 @@ int main(int argc, char **argv) {
}
/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_overflow_partial.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_overflow_partial.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
/* { dg-output "\[^\n\r]*in foo.*alloca_overflow_partial.c.*(\n|\r\n|\r)" */

View File

@ -17,6 +17,6 @@ int main(int argc, char **argv) {
}
/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_overflow_right.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_overflow_right.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
/* { dg-output "\[^\n\r]*in foo.*alloca_overflow_right.c.*(\n|\r\n|\r)" */

View File

@ -17,6 +17,6 @@ int main(int argc, char **argv) {
}
/* { dg-output "WRITE of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_underflow_left.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*alloca_underflow_left.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
/* { dg-output "\[^\n\r]*in foo.*alloca_underflow_left.c.*(\n|\r\n|\r)" */

View File

@ -23,6 +23,6 @@ int main() {
}
/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*global-overflow-1.c:20|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r).*" } */
/* { dg-output "0x\[0-9a-f\]+ is located 0 bytes to the right of global variable" } */
/* { dg-output ".*YYY\[^\n\r]* of size 10\[^\n\r]*(\n|\r\n|\r)" } */

View File

@ -24,8 +24,8 @@ int main(int argc, char **argv) {
}
/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:21|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 10-byte region\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*heap-overflow-1.c:19|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */

View File

@ -39,5 +39,5 @@ main ()
/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */

View File

@ -39,5 +39,5 @@ main ()
/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */
/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */

View File

@ -18,5 +18,5 @@ int main()
/* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
/* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */

View File

@ -18,6 +18,6 @@ int main() {
}
/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*stack-overflow-1.c:16|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*Address 0x\[0-9a-f\]+ is located in stack of thread T0.*(\n|\r\n|\r)" */
/* { dg-output "\[^\n\r]*in main.*stack-overflow-1.c.*(\n|\r\n|\r)" */

View File

@ -14,8 +14,8 @@ int main(int argc, char **argv) {
/* { dg-output "WRITE of size \[0-9\]* at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)strncpy|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:11|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 0 bytes to the right of 9-byte region\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*strncpy-overflow-1.c:10|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */

View File

@ -12,11 +12,11 @@ int main() {
/* { dg-output "ERROR: AddressSanitizer:? heap-use-after-free on address\[^\n\r]*" } */
/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*READ of size 1 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:9|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 5 bytes inside of 10-byte region .0x\[0-9a-f\]+,0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*freed by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)free|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:8|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*previously allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #0 0x\[0-9a-f\]+ +(in _*(interceptor_|wrap_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*use-after-free-1.c:7|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */

View File

@ -38,7 +38,7 @@ int main() {
// { dg-output "ERROR: AddressSanitizer:? heap-buffer-overflow on address\[^\n\r]*" }
// { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" }
// { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" }
// { dg-output " #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" }
// { dg-output " #0 0x\[0-9a-f\]+ +(in \[^\n\r]*LargeFunction\[^\n\r]*(large-func-test-1.C:18|\[^\n\r]*:0|\[^\n\r]*\\+0x\[0-9a-z\]*)|\[(\]).*(\n|\r\n|\r)" }
// { dg-output "\[^\n\r]*0x\[0-9a-f\]+ is located 44 bytes to the right of 400-byte region.*(\n|\r\n|\r)" }
// { dg-output "\[^\n\r]*allocated by thread T0 here:\[^\n\r]*(\n|\r\n|\r)" }
// { dg-output " #0( 0x\[0-9a-f\]+ +(in _*(interceptor_|)malloc|\[(\])\[^\n\r]*(\n|\r\n|\r)" }

View File

@ -0,0 +1,54 @@
! { dg-do run }
! { dg-require-effective-target lto }
! { dg-options "-fno-automatic -flto -g" }
!
! PR fortran/55733
!
! Check that -fno-automatic makes the local variable SAVEd
! Check that -flto -g works
!
! Scalar allocatable
subroutine foo(i)
integer :: i
integer, allocatable :: j
if (i == 1) j = 42
if (.not. allocated (j)) call abort ()
if (j /= 42) call abort ()
end
! Deferred-length string scalar
subroutine bar()
logical, save :: first = .true.
character(len=:), allocatable :: str
if (first) then
first = .false.
if (allocated (str)) call abort ()
str = "ABCDEF"
end if
if (.not. allocated (str)) call abort ()
if (len (str) /= 6) call abort ()
if (str(1:6) /= "ABCDEF") call abort ()
end subroutine bar
! Deferred-length string array
subroutine bar_array()
logical, save :: first = .true.
character(len=:), allocatable :: str
if (first) then
first = .false.
if (allocated (str)) call abort ()
str = "ABCDEF"
end if
if (.not. allocated (str)) call abort ()
if (len (str) /= 6) call abort ()
if (str(1:6) /= "ABCDEF") call abort ()
end subroutine bar_array
call foo(1)
call foo(2)
call bar()
call bar_array()
call bar()
call bar_array()
end

View File

@ -691,10 +691,7 @@ lto_input_ts_decl_common_tree_pointers (struct lto_input_block *ib,
DECL_SIZE (expr) = stream_read_tree (ib, data_in);
DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
/* Do not stream DECL_ABSTRACT_ORIGIN. We cannot handle debug information
for early inlining so drop it on the floor instead of ICEing in
dwarf2out.c. */
DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree (ib, data_in);
if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
&& DECL_HAS_VALUE_EXPR_P (expr))

View File

@ -566,7 +566,11 @@ write_ts_decl_minimal_tree_pointers (struct output_block *ob, tree expr,
stream_write_tree (ob, NULL_TREE, ref_p);
else
stream_write_tree (ob, DECL_NAME (expr), ref_p);
stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
&& ! DECL_CONTEXT (expr))
stream_write_tree (ob, (*all_translation_units)[0], ref_p);
else
stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
}
@ -585,10 +589,7 @@ write_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
special handling in LTO, it must be handled by streamer hooks. */
stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
/* Do not stream DECL_ABSTRACT_ORIGIN. We cannot handle debug information
for early inlining so drop it on the floor instead of ICEing in
dwarf2out.c. */
stream_write_tree (ob, DECL_ABSTRACT_ORIGIN (expr), ref_p);
if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
&& DECL_HAS_VALUE_EXPR_P (expr))

View File

@ -5662,6 +5662,10 @@ free_lang_data (void)
|| (!flag_generate_lto && !flag_generate_offload))
return 0;
/* Provide a dummy TRANSLATION_UNIT_DECL if the FE failed to provide one. */
if (vec_safe_is_empty (all_translation_units))
build_translation_unit_decl (NULL_TREE);
/* Allocate and assign alias sets to the standard integer types
while the slots are still in the way the frontends generated them. */
for (i = 0; i < itk_none; ++i)
@ -8598,8 +8602,16 @@ variably_modified_type_p (tree type, tree fn)
case POINTER_TYPE:
case REFERENCE_TYPE:
case VECTOR_TYPE:
/* Ada can have pointer types refering to themselves indirectly. */
if (TREE_VISITED (type))
return false;
TREE_VISITED (type) = true;
if (variably_modified_type_p (TREE_TYPE (type), fn))
return true;
{
TREE_VISITED (type) = false;
return true;
}
TREE_VISITED (type) = false;
break;
case FUNCTION_TYPE:

View File

@ -198,6 +198,8 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks
vmsdbgout_late_global_decl,
vmsdbgout_type_decl, /* type_decl */
debug_nothing_tree_tree_tree_bool_bool, /* imported_module_or_decl */
debug_false_tree_charstarstar_uhwistar, /* die_ref_for_decl */
debug_nothing_tree_charstar_uhwi, /* register_external_die */
debug_nothing_tree, /* deferred_inline_function */
vmsdbgout_abstract_function,
debug_nothing_rtx_code_label, /* label */

View File

@ -1,3 +1,8 @@
2017-08-21 Richard Biener <rguenther@suse.de>
* simple-object.h (simple_object_copy_lto_debug_sections): New
function.
2017-07-02 Jan Kratochvil <jan.kratochvil@redhat.com>
* dwarf2.def (DW_IDX_compile_unit, DW_IDX_type_unit, DW_IDX_die_offset)

View File

@ -197,6 +197,14 @@ simple_object_write_to_file (simple_object_write *simple_object,
extern void
simple_object_release_write (simple_object_write *);
/* Copy LTO debug sections from SRC_OBJECT to DEST.
If an error occurs, return the errno value in ERR and an error string. */
extern const char *
simple_object_copy_lto_debug_sections (simple_object_read *src_object,
const char *dest,
int *err);
#ifdef __cplusplus
}
#endif

View File

@ -1,3 +1,36 @@
2017-08-21 Richard Biener <rguenther@suse.de>
* simple-object-common.h (struct simple_object_functions): Add
copy_lto_debug_sections hook.
* simple-object.c: Include fcntl.h.
(handle_lto_debug_sections): New helper function.
(simple_object_copy_lto_debug_sections): New function copying
early LTO debug sections to regular debug sections in a new file.
(simple_object_start_write): Handle NULL segment_name.
* simple-object-coff.c (simple_object_coff_functions): Adjust
for not implemented copy_lto_debug_sections hook.
* simple-object-mach-o.c (simple_object_mach_o_functions): Likewise.
* simple-object-xcoff.c (simple_object_xcoff_functions): Likewise.
* simple-object-elf.c (SHT_NULL, SHT_SYMTAB, SHT_RELA, SHT_REL,
SHT_GROUP): Add various sectopn header types.
(SHF_EXCLUDE): Add flag.
(Elf32_External_Sym, Elf64_External_Sym): Add symbol struct.
(ELF_ST_BIND, ELF_ST_TYPE, ELF_ST_INFO): Add accessors.
(STT_OBJECT, STT_FUNC, STT_TLS, STT_GNU_IFUNC): Add Symbol types.
(STV_DEFAULT): Add symbol visibility.
(SHN_COMMON): Add special section index name.
(struct simple_object_elf_write): New.
(simple_object_elf_start_write): Adjust for new private data.
(simple_object_elf_write_shdr): Pass in values for all fields
we write.
(simple_object_elf_write_to_file): Adjust. Copy from recorded
section headers if requested.
(simple_object_elf_release_write): Release private data.
(simple_object_elf_copy_lto_debug_sections): Copy and rename sections
as denoted by PFN and all their dependences, symbols and relocations
to the empty destination file.
(simple_object_elf_functions): Adjust for copy_lto_debug_sections hook.
2017-07-02 Jan Kratochvil <jan.kratochvil@redhat.com>
* dwarfnames.c (DW_FIRST_IDX, DW_END_IDX, DW_IDX, DW_IDX_DUP): New.

View File

@ -800,5 +800,6 @@ const struct simple_object_functions simple_object_coff_functions =
simple_object_coff_release_attributes,
simple_object_coff_start_write,
simple_object_coff_write_to_file,
simple_object_coff_release_write
simple_object_coff_release_write,
NULL
};

View File

@ -141,6 +141,12 @@ struct simple_object_functions
/* Release the private data for an simple_object_write. */
void (*release_write) (void *);
/* Copy LTO debug sections. */
const char *(*copy_lto_debug_sections) (simple_object_read *sobj,
simple_object_write *dobj,
int (*pfn) (const char **),
int *err);
};
/* The known object file formats. */

View File

@ -122,9 +122,12 @@ typedef struct {
/* Special section index values. */
#define SHN_UNDEF 0 /* Undefined section */
#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */
#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
/* 32-bit ELF program header. */
typedef struct {
@ -183,8 +186,57 @@ typedef struct {
/* Values for sh_type field. */
#define SHT_NULL 0 /* Section header table entry unused */
#define SHT_PROGBITS 1 /* Program data */
#define SHT_SYMTAB 2 /* Link editing symbol table */
#define SHT_STRTAB 3 /* A string table */
#define SHT_RELA 4 /* Relocation entries with addends */
#define SHT_REL 9 /* Relocation entries, no addends */
#define SHT_GROUP 17 /* Section contains a section group */
/* Values for sh_flags field. */
#define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude this
section from executable and
shared library that it builds
when those objects are not to be
further relocated. */
/* Symbol table entry. */
typedef struct
{
unsigned char st_name[4]; /* Symbol name (string tbl index) */
unsigned char st_value[4]; /* Symbol value */
unsigned char st_size[4]; /* Symbol size */
unsigned char st_info; /* Symbol type and binding */
unsigned char st_other; /* Symbol visibility */
unsigned char st_shndx[2]; /* Section index */
} Elf32_External_Sym;
typedef struct
{
unsigned char st_name[4]; /* Symbol name (string tbl index) */
unsigned char st_info; /* Symbol type and binding */
unsigned char st_other; /* Symbol visibility */
unsigned char st_shndx[2]; /* Section index */
unsigned char st_value[8]; /* Symbol value */
unsigned char st_size[8]; /* Symbol size */
} Elf64_External_Sym;
#define ELF_ST_BIND(val) (((unsigned char) (val)) >> 4)
#define ELF_ST_TYPE(val) ((val) & 0xf)
#define ELF_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
#define STT_NOTYPE 0 /* Symbol type is unspecified */
#define STT_OBJECT 1 /* Symbol is a data object */
#define STT_FUNC 2 /* Symbol is a code object */
#define STT_TLS 6 /* Thread local data object */
#define STT_GNU_IFUNC 10 /* Symbol is an indirect code object */
#define STB_LOCAL 0 /* Local symbol */
#define STB_GLOBAL 1 /* Global symbol */
#define STV_DEFAULT 0 /* Visibility is specified by binding type */
/* Functions to fetch and store different ELF types, depending on the
endianness and size. */
@ -348,6 +400,14 @@ struct simple_object_elf_attributes
unsigned int flags;
};
/* Private data for an simple_object_write. */
struct simple_object_elf_write
{
struct simple_object_elf_attributes attrs;
unsigned char *shdrs;
};
/* See if we have an ELF file. */
static void *
@ -675,12 +735,13 @@ simple_object_elf_start_write (void *attributes_data,
{
struct simple_object_elf_attributes *attrs =
(struct simple_object_elf_attributes *) attributes_data;
struct simple_object_elf_attributes *ret;
struct simple_object_elf_write *ret;
/* We're just going to record the attributes, but we need to make a
copy because the user may delete them. */
ret = XNEW (struct simple_object_elf_attributes);
*ret = *attrs;
ret = XNEW (struct simple_object_elf_write);
ret->attrs = *attrs;
ret->shdrs = NULL;
return ret;
}
@ -766,8 +827,11 @@ static int
simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
off_t offset, unsigned int sh_name,
unsigned int sh_type, unsigned int sh_flags,
off_t sh_addr,
unsigned int sh_offset, unsigned int sh_size,
unsigned int sh_link, unsigned int sh_addralign,
unsigned int sh_link, unsigned int sh_info,
unsigned int sh_addralign,
unsigned int sh_entsize,
const char **errmsg, int *err)
{
struct simple_object_elf_attributes *attrs =
@ -788,12 +852,13 @@ simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addr, Elf_Addr, sh_addr);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_link, Elf_Word, sh_link);
/* sh_info left as zero. */
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_info, Elf_Word, sh_info);
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
/* sh_entsize left as zero. */
ELF_SET_FIELD (fns, cl, Shdr, buf, sh_entsize, Elf_Word, sh_entsize);
return simple_object_internal_write (descriptor, offset, buf, shdr_size,
errmsg, err);
@ -811,8 +876,9 @@ static const char *
simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
int *err)
{
struct simple_object_elf_attributes *attrs =
(struct simple_object_elf_attributes *) sobj->data;
struct simple_object_elf_write *eow =
(struct simple_object_elf_write *) sobj->data;
struct simple_object_elf_attributes *attrs = &eow->attrs;
unsigned char cl;
size_t ehdr_size;
size_t shdr_size;
@ -825,6 +891,7 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
unsigned int first_sh_link;
size_t sh_name;
unsigned char zero;
unsigned secnum;
if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
return errmsg;
@ -862,21 +929,54 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
else
first_sh_link = shnum - 1;
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
0, 0, 0, 0, first_sh_size, first_sh_link,
0, &errmsg, err))
0, 0, 0, 0, 0, first_sh_size, first_sh_link,
0, 0, 0, &errmsg, err))
return errmsg;
shdr_offset += shdr_size;
sh_name = 1;
secnum = 0;
for (section = sobj->sections; section != NULL; section = section->next)
{
size_t mask;
size_t new_sh_offset;
size_t sh_size;
struct simple_object_write_section_buffer *buffer;
unsigned int sh_type = SHT_PROGBITS;
unsigned int sh_flags = 0;
off_t sh_addr = 0;
unsigned int sh_link = 0;
unsigned int sh_info = 0;
unsigned int sh_addralign = 1U << section->align;
unsigned int sh_entsize = 0;
if (eow->shdrs)
{
sh_type = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_type, Elf_Word);
sh_flags = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_flags, Elf_Addr);
sh_addr = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_addr, Elf_Addr);
sh_link = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_link, Elf_Word);
sh_info = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_info, Elf_Word);
sh_addralign = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_addralign, Elf_Addr);
sh_entsize = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
eow->shdrs + secnum * shdr_size,
sh_entsize, Elf_Word);
secnum++;
}
mask = (1U << section->align) - 1;
mask = sh_addralign - 1;
new_sh_offset = sh_offset + mask;
new_sh_offset &= ~ mask;
while (new_sh_offset > sh_offset)
@ -906,8 +1006,10 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
}
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
sh_name, SHT_PROGBITS, 0, sh_offset,
sh_size, 0, 1U << section->align,
sh_name, sh_type, sh_flags,
sh_addr, sh_offset,
sh_size, sh_link, sh_info,
sh_addralign, sh_entsize,
&errmsg, err))
return errmsg;
@ -917,9 +1019,9 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
}
if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
sh_name, SHT_STRTAB, 0, sh_offset,
sh_name + strlen (".shstrtab") + 1, 0,
1, &errmsg, err))
sh_name, SHT_STRTAB, 0, 0, sh_offset,
sh_name + strlen (".shstrtab") + 1, 0, 0,
1, 0, &errmsg, err))
return errmsg;
/* .shstrtab has a leading zero byte. */
@ -954,9 +1056,354 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
static void
simple_object_elf_release_write (void *data)
{
struct simple_object_elf_write *eow = (struct simple_object_elf_write *) data;
if (eow->shdrs)
XDELETE (eow->shdrs);
XDELETE (data);
}
/* Copy all sections in an ELF file. */
static const char *
simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
simple_object_write *dobj,
int (*pfn) (const char **),
int *err)
{
struct simple_object_elf_read *eor =
(struct simple_object_elf_read *) sobj->data;
const struct elf_type_functions *type_functions = eor->type_functions;
struct simple_object_elf_write *eow =
(struct simple_object_elf_write *) dobj->data;
unsigned char ei_class = eor->ei_class;
size_t shdr_size;
unsigned int shnum;
unsigned char *shdrs;
const char *errmsg;
unsigned char *shstrhdr;
size_t name_size;
off_t shstroff;
unsigned char *names;
unsigned int i;
int *pfnret;
const char **pfnname;
shdr_size = (ei_class == ELFCLASS32
? sizeof (Elf32_External_Shdr)
: sizeof (Elf64_External_Shdr));
/* Read the section headers. We skip section 0, which is not a
useful section. */
shnum = eor->shnum;
shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
if (!simple_object_internal_read (sobj->descriptor,
sobj->offset + eor->shoff + shdr_size,
shdrs,
shdr_size * (shnum - 1),
&errmsg, err))
{
XDELETEVEC (shdrs);
return errmsg;
}
/* Read the section names. */
shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shstrhdr, sh_size, Elf_Addr);
shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shstrhdr, sh_offset, Elf_Addr);
names = XNEWVEC (unsigned char, name_size);
if (!simple_object_internal_read (sobj->descriptor,
sobj->offset + shstroff,
names, name_size, &errmsg, err))
{
XDELETEVEC (names);
XDELETEVEC (shdrs);
return errmsg;
}
eow->shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
pfnret = XNEWVEC (int, shnum);
pfnname = XNEWVEC (const char *, shnum);
/* First perform the callbacks to know which sections to preserve and
what name to use for those. */
for (i = 1; i < shnum; ++i)
{
unsigned char *shdr;
unsigned int sh_name;
const char *name;
int ret;
shdr = shdrs + (i - 1) * shdr_size;
sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_name, Elf_Word);
if (sh_name >= name_size)
{
*err = 0;
XDELETEVEC (names);
XDELETEVEC (shdrs);
return "ELF section name out of range";
}
name = (const char *) names + sh_name;
ret = (*pfn) (&name);
pfnret[i - 1] = ret == 1 ? 0 : -1;
pfnname[i - 1] = name;
}
/* Mark sections as preserved that are required by to be preserved
sections. */
for (i = 1; i < shnum; ++i)
{
unsigned char *shdr;
unsigned int sh_type, sh_info, sh_link;
off_t offset;
off_t length;
shdr = shdrs + (i - 1) * shdr_size;
sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_type, Elf_Word);
sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_info, Elf_Word);
sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_link, Elf_Word);
if (sh_type == SHT_GROUP)
{
/* Mark groups containing copied sections. */
unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_entsize, Elf_Addr);
unsigned char *ent, *buf;
int keep = 0;
offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_offset, Elf_Addr);
length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_size, Elf_Addr);
buf = XNEWVEC (unsigned char, length);
if (!simple_object_internal_read (sobj->descriptor,
sobj->offset + offset, buf,
(size_t) length, &errmsg, err))
{
XDELETEVEC (buf);
XDELETEVEC (names);
XDELETEVEC (shdrs);
return errmsg;
}
for (ent = buf + entsize; ent < buf + length; ent += entsize)
{
unsigned sec = type_functions->fetch_Elf_Word (ent);
if (pfnret[sec - 1] == 0)
keep = 1;
}
if (keep)
{
pfnret[sh_link - 1] = 0;
pfnret[i - 1] = 0;
}
}
if (sh_type == SHT_RELA
|| sh_type == SHT_REL)
{
/* Mark relocation sections and symtab of copied sections. */
if (pfnret[sh_info - 1] == 0)
{
pfnret[sh_link - 1] = 0;
pfnret[i - 1] = 0;
}
}
if (sh_type == SHT_SYMTAB)
{
/* Mark strings sections of copied symtabs. */
if (pfnret[i - 1] == 0)
pfnret[sh_link - 1] = 0;
}
}
/* Then perform the actual copying. */
for (i = 1; i < shnum; ++i)
{
unsigned char *shdr;
unsigned int sh_name, sh_type;
const char *name;
off_t offset;
off_t length;
int ret;
const char *errmsg;
simple_object_write_section *dest;
off_t flags;
unsigned char *buf;
shdr = shdrs + (i - 1) * shdr_size;
sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_name, Elf_Word);
if (sh_name >= name_size)
{
*err = 0;
XDELETEVEC (names);
XDELETEVEC (shdrs);
return "ELF section name out of range";
}
name = (const char *) names + sh_name;
offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_offset, Elf_Addr);
length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_size, Elf_Addr);
sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_type, Elf_Word);
ret = pfnret[i - 1];
name = ret == 0 ? pfnname[i - 1] : "";
dest = simple_object_write_create_section (dobj, name, 0, &errmsg, err);
if (dest == NULL)
{
XDELETEVEC (names);
XDELETEVEC (shdrs);
return errmsg;
}
/* Record the SHDR of the source. */
memcpy (eow->shdrs + (i - 1) * shdr_size, shdr, shdr_size);
shdr = eow->shdrs + (i - 1) * shdr_size;
/* Copy the data.
??? This is quite wasteful and ideally would be delayed until
write_to_file (). Thus it questions the interfacing
which eventually should contain destination creation plus
writing. */
/* Keep empty sections for sections we should discard. This avoids
the need to rewrite section indices in symtab and relocation
sections. */
if (ret == 0)
{
buf = XNEWVEC (unsigned char, length);
if (!simple_object_internal_read (sobj->descriptor,
sobj->offset + offset, buf,
(size_t) length, &errmsg, err))
{
XDELETEVEC (buf);
XDELETEVEC (names);
XDELETEVEC (shdrs);
return errmsg;
}
/* If we are processing .symtab purge __gnu_lto_v1 and
__gnu_lto_slim symbols from it. */
if (sh_type == SHT_SYMTAB)
{
unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_entsize, Elf_Addr);
unsigned strtab = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_link, Elf_Word);
unsigned char *strshdr = shdrs + (strtab - 1) * shdr_size;
off_t stroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
strshdr, sh_offset, Elf_Addr);
size_t strsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
strshdr, sh_size, Elf_Addr);
char *strings = XNEWVEC (char, strsz);
unsigned char *ent;
simple_object_internal_read (sobj->descriptor,
sobj->offset + stroff,
(unsigned char *)strings,
strsz, &errmsg, err);
for (ent = buf; ent < buf + length; ent += entsize)
{
unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
Sym, ent,
st_shndx, Elf_Half);
unsigned char *st_info;
unsigned char *st_other;
int discard = 0;
if (ei_class == ELFCLASS32)
{
st_info = &((Elf32_External_Sym *)ent)->st_info;
st_other = &((Elf32_External_Sym *)ent)->st_other;
}
else
{
st_info = &((Elf64_External_Sym *)ent)->st_info;
st_other = &((Elf64_External_Sym *)ent)->st_other;
}
/* Eliminate all COMMONs - this includes __gnu_lto_v1
and __gnu_lto_slim which otherwise cause endless
LTO plugin invocation. */
if (st_shndx == SHN_COMMON)
/* Setting st_name to "" seems to work to purge
COMMON symbols (in addition to setting their
size to zero). */
discard = 1;
/* We also need to remove symbols refering to sections
we'll eventually remove as with fat LTO objects
we otherwise get duplicate symbols at final link
(with GNU ld, gold is fine and ignores symbols in
sections marked as EXCLUDE). ld/20513 */
else if (st_shndx != SHN_UNDEF
&& st_shndx < shnum
&& pfnret[st_shndx - 1] == -1)
discard = 1;
if (discard)
{
/* Make discarded symbols undefined and unnamed. */
ELF_SET_FIELD (type_functions, ei_class, Sym,
ent, st_name, Elf_Word, 0);
ELF_SET_FIELD (type_functions, ei_class, Sym,
ent, st_value, Elf_Addr, 0);
ELF_SET_FIELD (type_functions, ei_class, Sym,
ent, st_size, Elf_Word, 0);
ELF_SET_FIELD (type_functions, ei_class, Sym,
ent, st_shndx, Elf_Half, SHN_UNDEF);
*st_info = ELF_ST_INFO (ELF_ST_BIND (*st_info),
STT_NOTYPE);
*st_other = STV_DEFAULT;
}
}
XDELETEVEC (strings);
}
errmsg = simple_object_write_add_data (dobj, dest,
buf, length, 1, err);
XDELETEVEC (buf);
if (errmsg)
{
XDELETEVEC (names);
XDELETEVEC (shdrs);
return errmsg;
}
}
else
{
/* For deleted sections mark the section header table entry as
unused. That allows the link editor to remove it in a partial
link. */
ELF_SET_FIELD (type_functions, ei_class, Shdr,
shdr, sh_type, Elf_Addr, SHT_NULL);
}
flags = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
shdr, sh_flags, Elf_Addr);
if (ret == 0)
flags &= ~SHF_EXCLUDE;
else if (ret == -1)
flags |= SHF_EXCLUDE;
ELF_SET_FIELD (type_functions, ei_class, Shdr,
shdr, sh_flags, Elf_Addr, flags);
}
XDELETEVEC (names);
XDELETEVEC (shdrs);
XDELETEVEC (pfnret);
XDELETEVEC (pfnname);
return NULL;
}
/* The ELF functions. */
const struct simple_object_functions simple_object_elf_functions =
@ -969,5 +1416,6 @@ const struct simple_object_functions simple_object_elf_functions =
simple_object_elf_release_attributes,
simple_object_elf_start_write,
simple_object_elf_write_to_file,
simple_object_elf_release_write
simple_object_elf_release_write,
simple_object_elf_copy_lto_debug_sections
};

View File

@ -1374,5 +1374,6 @@ const struct simple_object_functions simple_object_mach_o_functions =
simple_object_mach_o_release_attributes,
simple_object_mach_o_start_write,
simple_object_mach_o_write_to_file,
simple_object_mach_o_release_write
simple_object_mach_o_release_write,
NULL
};

View File

@ -1006,5 +1006,6 @@ const struct simple_object_functions simple_object_xcoff_functions =
simple_object_xcoff_release_attributes,
simple_object_xcoff_start_write,
simple_object_xcoff_write_to_file,
simple_object_xcoff_release_write
simple_object_xcoff_release_write,
NULL
};

View File

@ -22,6 +22,7 @@ Boston, MA 02110-1301, USA. */
#include "simple-object.h"
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@ -249,6 +250,86 @@ simple_object_find_section (simple_object_read *sobj, const char *name,
return 1;
}
/* Callback to identify and rename LTO debug sections by name.
Returns 1 if NAME is a LTO debug section, 0 if not. */
static int
handle_lto_debug_sections (const char **name)
{
/* ??? So we can't use .gnu.lto_ prefixed sections as the assembler
complains about bogus section flags. Which means we need to arrange
for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make
fat lto object tooling work for the fat part). */
/* ??? For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
sections. */
/* Copy LTO debug sections and rename them to their non-LTO name. */
if (strncmp (*name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
{
*name = *name + sizeof (".gnu.debuglto_") - 1;
return 1;
}
else if (strncmp (*name, ".gnu.lto_.debug_", sizeof (".gnu.lto_.debug_") -1) == 0)
{
*name = *name + sizeof (".gnu.lto_") - 1;
return 1;
}
return 0;
}
/* Copy LTO debug sections. */
const char *
simple_object_copy_lto_debug_sections (simple_object_read *sobj,
const char *dest, int *err)
{
const char *errmsg;
simple_object_write *dest_sobj;
simple_object_attributes *attrs;
int outfd;
if (! sobj->functions->copy_lto_debug_sections)
{
*err = EINVAL;
return "simple_object_copy_lto_debug_sections not implemented";
}
attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
if (! attrs)
return errmsg;
dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
simple_object_release_attributes (attrs);
if (! dest_sobj)
return errmsg;
errmsg = sobj->functions->copy_lto_debug_sections (sobj, dest_sobj,
handle_lto_debug_sections,
err);
if (errmsg)
{
simple_object_release_write (dest_sobj);
return errmsg;
}
outfd = creat (dest, 00777);
if (outfd == -1)
{
*err = errno;
simple_object_release_write (dest_sobj);
return "open failed";
}
errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
close (outfd);
if (errmsg)
{
simple_object_release_write (dest_sobj);
return errmsg;
}
simple_object_release_write (dest_sobj);
return NULL;
}
/* Fetch attributes. */
simple_object_attributes *
@ -315,7 +396,7 @@ simple_object_start_write (simple_object_attributes *attrs,
return NULL;
ret = XNEW (simple_object_write);
ret->functions = attrs->functions;
ret->segment_name = xstrdup (segment_name);
ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
ret->sections = NULL;
ret->last_section = NULL;
ret->data = data;

View File

@ -1,3 +1,8 @@
2017-08-21 Richard Biener <rguenther@suse.de>
* testsuite/libstdc++-prettyprinters/prettyprinters.exp: Run all
tests with -flto as well if supported.
2017-08-20 Martin Sebor <msebor@redhat.com>
PR c/81854

View File

@ -15,6 +15,7 @@
# <http://www.gnu.org/licenses/>.
load_lib gdb-test.exp
load_lib target-supports.exp
dg-init
v3-build_support
@ -46,6 +47,14 @@ global PCH_CXXFLAGS
gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
"" "$DEFAULT_CXXFLAGS $PCH_CXXFLAGS"
if { [check_effective_target_lto] } {
append cxxflags " -flto"
# work around sourceware.org 20882
regsub {^(.*)-Wl,--gc-sections(.*)$} $cxxldflags {\1\2} cxxldflags
gdb-dg-runtest [lsort [glob $srcdir/$subdir/*.cc]] \
"" "$DEFAULT_CXXFLAGS -flto $PCH_CXXFLAGS"
}
if [info exists guality_gdb_name] {
unsetenv GUALITY_GDB_NAME
}