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.
This commit is contained in:
parent
a97fbc7e3c
commit
4153b6dbb0
6 changed files with 47 additions and 34 deletions
13
ld/ChangeLog
13
ld/ChangeLog
|
@ -1,3 +1,16 @@
|
|||
2016-03-22 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
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 <nickc@redhat.com>
|
||||
|
||||
* configure: Regenerate.
|
||||
|
|
49
ld/ldlang.c
49
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)
|
||||
|
|
|
@ -693,4 +693,7 @@ lang_ld_feature (char *);
|
|||
extern void
|
||||
lang_print_memory_usage (void);
|
||||
|
||||
extern void
|
||||
lang_add_gc_name (const char *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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] != '@')
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -8,7 +8,6 @@ DllMainCRTStartup:
|
|||
nop
|
||||
|
||||
.section .rdata,"dr"
|
||||
.globl _testval
|
||||
_testval:
|
||||
.long 1
|
||||
.long 2
|
||||
|
|
Loading…
Reference in a new issue