From: Nick Clifton Date: Tue, 22 Mar 2016 12:25:08 +0000 (+0000) Subject: Improve COFF/PE linker garbage collection by preventing the removal of sections conta... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4153b6dbb0f38a16fd5b583761aa811212fbb9a5;p=binutils-gdb.git Improve COFF/PE linker garbage collection by preventing the removal of sections containing exported symbols. PR ld/19803 * ldlang.c (lang_add_gc_name): New function. Adds the provided symbol name to the list of gc symbols. (lang_process): Call lang_add_gc_name with entry_symbol_default if entry_symbol.name is NULL. Use lang_add_gc_name to add the init and fini function names. * pe-dll.c (process_def_file_and_drectve): Add exported names to the gc symbol list. * testsuite/ld-pe/pr19803.s: Do not export _testval symbol. * testsuite/ld-pe/pr19803.d: Tweak expected output. --- diff --git a/ld/ChangeLog b/ld/ChangeLog index 92a71b71f62..0e16f80e99a 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,16 @@ +2016-03-22 Nick Clifton + + PR ld/19803 + * ldlang.c (lang_add_gc_name): New function. Adds the provided + symbol name to the list of gc symbols. + (lang_process): Call lang_add_gc_name with entry_symbol_default if + entry_symbol.name is NULL. Use lang_add_gc_name to add the init + and fini function names. + * pe-dll.c (process_def_file_and_drectve): Add exported names to + the gc symbol list. + * testsuite/ld-pe/pr19803.s: Do not export _testval symbol. + * testsuite/ld-pe/pr19803.d: Tweak expected output. + 2016-03-22 Nick Clifton * configure: Regenerate. diff --git a/ld/ldlang.c b/ld/ldlang.c index e6cc4244da8..2efab242c07 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -6699,6 +6699,23 @@ lang_list_remove_tail (lang_statement_list_type *destlist, } #endif /* ENABLE_PLUGINS */ +/* Add NAME to the list of garbage collection entry points. */ + +void +lang_add_gc_name (const char * name) +{ + struct bfd_sym_chain *sym; + + if (name == NULL) + return; + + sym = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym)); + + sym->next = link_info.gc_sym_list; + sym->name = name; + link_info.gc_sym_list = sym; +} + void lang_process (void) { @@ -6781,6 +6798,9 @@ lang_process (void) } #endif /* ENABLE_PLUGINS */ + /* Make sure that nobody has tried to add a symbol to this list before now. */ + ASSERT (link_info.gc_sym_list == NULL); + link_info.gc_sym_list = &entry_symbol; if (entry_symbol.name == NULL) @@ -6790,37 +6810,16 @@ lang_process (void) /* entry_symbol is normally initialied by a ENTRY definition in the linker script or the -e command line option. But if neither of these have been used, the target specific backend may still have - provided an entry symbol via a call to lang_default_entry()o. + provided an entry symbol via a call to lang_default_entry(). Unfortunately this value will not be processed until lang_end() is called, long after this function has finished. So detect this case here and add the target's entry symbol to the list of starting points for garbage collection resolution. */ - if (entry_symbol_default != NULL) - { - struct bfd_sym_chain *sym - = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym)); - sym->next = link_info.gc_sym_list; - sym->name = entry_symbol_default; - link_info.gc_sym_list = sym; - } + lang_add_gc_name (entry_symbol_default); } - if (link_info.init_function != NULL) - { - struct bfd_sym_chain *sym - = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym)); - sym->next = link_info.gc_sym_list; - sym->name = link_info.init_function; - link_info.gc_sym_list = sym; - } - if (link_info.fini_function != NULL) - { - struct bfd_sym_chain *sym - = (struct bfd_sym_chain *) stat_alloc (sizeof (*sym)); - sym->next = link_info.gc_sym_list; - sym->name = link_info.fini_function; - link_info.gc_sym_list = sym; - } + lang_add_gc_name (link_info.init_function); + lang_add_gc_name (link_info.fini_function); ldemul_after_open (); if (config.map_file != NULL) diff --git a/ld/ldlang.h b/ld/ldlang.h index c3d1185a244..65d768b0d2d 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -693,4 +693,7 @@ lang_ld_feature (char *); extern void lang_print_memory_usage (void); +extern void +lang_add_gc_name (const char *); + #endif diff --git a/ld/pe-dll.c b/ld/pe-dll.c index a2792e8f949..a2806473da0 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -897,6 +897,9 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info * char *int_name = pe_def_file->exports[i].internal_name; char *name; + /* PR 19803: Make sure that any exported symbol does not get garbage collected. */ + lang_add_gc_name (int_name); + name = xmalloc (strlen (int_name) + 2); if (pe_details->underscored && int_name[0] != '@') { diff --git a/ld/testsuite/ld-pe/pr19803.d b/ld/testsuite/ld-pe/pr19803.d index 1fc6daf17f6..d8d0c5547a2 100644 --- a/ld/testsuite/ld-pe/pr19803.d +++ b/ld/testsuite/ld-pe/pr19803.d @@ -1,17 +1,13 @@ #ld: -shared --out-implib dx.dll.a --gc-sections #objdump: --syms -#notarget: mcore-* arm-epoc-pe +#notarget: mcore-* # -# Check that the target specific entry symbol _DllMainCRTStartup is still +# The MCORE-PE target does not support -shared. +# +# Check that the target specific entry symbol *Startup is still # a defined (sec > 0), public (scl == 2) symbol, even after garbage # collection. -# -# Check that the symbol _testval is undefined (sec == 0) and hidden -# (scl == 106) in the output. It should have been changed to this state when -# garbage collection was performed. -#... -.*\(sec 0\)\(fl 0x00\)\(ty 0\)\(scl 106\) \(nx 0\) 0x0+000 _testval #... .*\(sec 1\)\(fl 0x00\)\(ty 0\)\(scl 2\) \(nx 0\) 0x0+000 .*Startup.* #pass diff --git a/ld/testsuite/ld-pe/pr19803.s b/ld/testsuite/ld-pe/pr19803.s index 290a698e9c2..cabb87e98c5 100644 --- a/ld/testsuite/ld-pe/pr19803.s +++ b/ld/testsuite/ld-pe/pr19803.s @@ -8,7 +8,6 @@ DllMainCRTStartup: nop .section .rdata,"dr" - .globl _testval _testval: .long 1 .long 2