summaryrefslogtreecommitdiff
path: root/bfd/elflink.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-09-19 11:59:30 +0930
committerAlan Modra <amodra@gmail.com>2017-09-19 12:18:49 +0930
commit3d13f3e9bda5aada68915f5d958f731ae79ed41d (patch)
tree9b9e1b4f3dec04148c1008f06dd9a4aee4119181 /bfd/elflink.c
parentab502e635e78a6c6c9c8abf3072bfeedaca9c26f (diff)
PR22150, ld keeps a version reference for gc'd symbols
elf_gc_sweep_symbol should run after verdefs are calculated, since the verdef code creates symbols for the versions. However, elf_gc_sweep_symbol needs to run before verrefs so as to not emit useless verrefs for symbols that are gc'd. I've also removed a _bfd_elf_link_renumber_dynsyms calls added by Maciej after I fussed about it when reviewing. On further examination the call appears to be unnecessary. Looking at renumber_dynsyms also made me realize that the test to exclude .gnu.version has been wrong since 2016-04-26 (git commit d5486c4372), so fix that too. PR 22150 * elflink.c (bfd_elf_size_dynamic_sections): Garbage collect symbols before calculating verrefs. Don't renumber dynsyms after gc. Exclude .gnu.version when zero or one dynsym. Localize some vars and reindent.
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r--bfd/elflink.c227
1 files changed, 110 insertions, 117 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 58fb83b4b2..ee5c01fde7 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -6006,19 +6006,18 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
struct elf_info_failed asvinfo;
struct bfd_elf_version_tree *t;
struct bfd_elf_version_expr *d;
- struct elf_info_failed eif;
- bfd_boolean all_defined;
asection *s;
size_t soname_indx;
- eif.info = info;
- eif.failed = FALSE;
-
/* If we are supposed to export all symbols into the dynamic symbol
table (this is not the normal case), then do so. */
if (info->export_dynamic
|| (bfd_link_executable (info) && info->dynamic))
{
+ struct elf_info_failed eif;
+
+ eif.info = info;
+ eif.failed = FALSE;
elf_link_hash_traverse (elf_hash_table (info),
_bfd_elf_export_symbol,
&eif);
@@ -6102,7 +6101,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
if (!info->allow_undefined_version)
{
/* Check if all global versions have a definition. */
- all_defined = TRUE;
+ bfd_boolean all_defined = TRUE;
for (t = info->version_info; t != NULL; t = t->next)
for (d = t->globals.list; d != NULL; d = d->next)
if (d->literal && !d->symver && !d->script)
@@ -6355,134 +6354,128 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
elf_tdata (output_bfd)->cverdefs = cdefs;
}
+ }
+
+ bed = get_elf_backend_data (output_bfd);
+
+ if (info->gc_sections && bed->can_gc_sections)
+ {
+ struct elf_gc_sweep_symbol_info sweep_info;
+
+ /* Remove the symbols that were in the swept sections from the
+ dynamic symbol table. */
+ sweep_info.info = info;
+ sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
+ elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
+ &sweep_info);
+ }
+
+ if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
+ {
+ asection *s;
+ struct elf_find_verdep_info sinfo;
/* Work out the size of the version reference section. */
s = bfd_get_linker_section (dynobj, ".gnu.version_r");
BFD_ASSERT (s != NULL);
- {
- struct elf_find_verdep_info sinfo;
-
- sinfo.info = info;
- sinfo.vers = elf_tdata (output_bfd)->cverdefs;
- if (sinfo.vers == 0)
- sinfo.vers = 1;
- sinfo.failed = FALSE;
- elf_link_hash_traverse (elf_hash_table (info),
- _bfd_elf_link_find_version_dependencies,
- &sinfo);
- if (sinfo.failed)
- return FALSE;
+ sinfo.info = info;
+ sinfo.vers = elf_tdata (output_bfd)->cverdefs;
+ if (sinfo.vers == 0)
+ sinfo.vers = 1;
+ sinfo.failed = FALSE;
- if (elf_tdata (output_bfd)->verref == NULL)
- s->flags |= SEC_EXCLUDE;
- else
- {
- Elf_Internal_Verneed *vn;
- unsigned int size;
- unsigned int crefs;
- bfd_byte *p;
-
- /* Build the version dependency section. */
- size = 0;
- crefs = 0;
- for (vn = elf_tdata (output_bfd)->verref;
- vn != NULL;
- vn = vn->vn_nextref)
- {
- Elf_Internal_Vernaux *a;
+ elf_link_hash_traverse (elf_hash_table (info),
+ _bfd_elf_link_find_version_dependencies,
+ &sinfo);
+ if (sinfo.failed)
+ return FALSE;
- size += sizeof (Elf_External_Verneed);
- ++crefs;
- for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
- size += sizeof (Elf_External_Vernaux);
- }
+ if (elf_tdata (output_bfd)->verref == NULL)
+ s->flags |= SEC_EXCLUDE;
+ else
+ {
+ Elf_Internal_Verneed *vn;
+ unsigned int size;
+ unsigned int crefs;
+ bfd_byte *p;
- s->size = size;
- s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
- if (s->contents == NULL)
- return FALSE;
+ /* Build the version dependency section. */
+ size = 0;
+ crefs = 0;
+ for (vn = elf_tdata (output_bfd)->verref;
+ vn != NULL;
+ vn = vn->vn_nextref)
+ {
+ Elf_Internal_Vernaux *a;
- p = s->contents;
- for (vn = elf_tdata (output_bfd)->verref;
- vn != NULL;
- vn = vn->vn_nextref)
- {
- unsigned int caux;
- Elf_Internal_Vernaux *a;
- size_t indx;
-
- caux = 0;
- for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
- ++caux;
-
- vn->vn_version = VER_NEED_CURRENT;
- vn->vn_cnt = caux;
- indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
- elf_dt_name (vn->vn_bfd) != NULL
- ? elf_dt_name (vn->vn_bfd)
- : lbasename (vn->vn_bfd->filename),
- FALSE);
- if (indx == (size_t) -1)
- return FALSE;
- vn->vn_file = indx;
- vn->vn_aux = sizeof (Elf_External_Verneed);
- if (vn->vn_nextref == NULL)
- vn->vn_next = 0;
- else
- vn->vn_next = (sizeof (Elf_External_Verneed)
- + caux * sizeof (Elf_External_Vernaux));
+ size += sizeof (Elf_External_Verneed);
+ ++crefs;
+ for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+ size += sizeof (Elf_External_Vernaux);
+ }
- _bfd_elf_swap_verneed_out (output_bfd, vn,
- (Elf_External_Verneed *) p);
- p += sizeof (Elf_External_Verneed);
+ s->size = size;
+ s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
+ if (s->contents == NULL)
+ return FALSE;
- for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
- {
- a->vna_hash = bfd_elf_hash (a->vna_nodename);
- indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
- a->vna_nodename, FALSE);
- if (indx == (size_t) -1)
- return FALSE;
- a->vna_name = indx;
- if (a->vna_nextptr == NULL)
- a->vna_next = 0;
- else
- a->vna_next = sizeof (Elf_External_Vernaux);
+ p = s->contents;
+ for (vn = elf_tdata (output_bfd)->verref;
+ vn != NULL;
+ vn = vn->vn_nextref)
+ {
+ unsigned int caux;
+ Elf_Internal_Vernaux *a;
+ size_t indx;
- _bfd_elf_swap_vernaux_out (output_bfd, a,
- (Elf_External_Vernaux *) p);
- p += sizeof (Elf_External_Vernaux);
- }
- }
+ caux = 0;
+ for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+ ++caux;
- elf_tdata (output_bfd)->cverrefs = crefs;
- }
- }
- }
+ vn->vn_version = VER_NEED_CURRENT;
+ vn->vn_cnt = caux;
+ indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+ elf_dt_name (vn->vn_bfd) != NULL
+ ? elf_dt_name (vn->vn_bfd)
+ : lbasename (vn->vn_bfd->filename),
+ FALSE);
+ if (indx == (size_t) -1)
+ return FALSE;
+ vn->vn_file = indx;
+ vn->vn_aux = sizeof (Elf_External_Verneed);
+ if (vn->vn_nextref == NULL)
+ vn->vn_next = 0;
+ else
+ vn->vn_next = (sizeof (Elf_External_Verneed)
+ + caux * sizeof (Elf_External_Vernaux));
- bed = get_elf_backend_data (output_bfd);
+ _bfd_elf_swap_verneed_out (output_bfd, vn,
+ (Elf_External_Verneed *) p);
+ p += sizeof (Elf_External_Verneed);
- if (info->gc_sections && bed->can_gc_sections)
- {
- struct elf_gc_sweep_symbol_info sweep_info;
- unsigned long section_sym_count;
+ for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+ {
+ a->vna_hash = bfd_elf_hash (a->vna_nodename);
+ indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+ a->vna_nodename, FALSE);
+ if (indx == (size_t) -1)
+ return FALSE;
+ a->vna_name = indx;
+ if (a->vna_nextptr == NULL)
+ a->vna_next = 0;
+ else
+ a->vna_next = sizeof (Elf_External_Vernaux);
- /* Remove the symbols that were in the swept sections from the
- dynamic symbol table. GCFIXME: Anyone know how to get them
- out of the static symbol table as well? */
- sweep_info.info = info;
- sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
- elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
- &sweep_info);
+ _bfd_elf_swap_vernaux_out (output_bfd, a,
+ (Elf_External_Vernaux *) p);
+ p += sizeof (Elf_External_Vernaux);
+ }
+ }
- /* We need to reassign dynsym indices now that symbols may have
- been removed. See the call in `bfd_elf_size_dynsym_hash_dynstr'
- for the details of the conditions used here. */
- if (elf_hash_table (info)->dynamic_sections_created
- || bed->always_renumber_dynsyms)
- _bfd_elf_link_renumber_dynsyms (output_bfd, info, &section_sym_count);
+ elf_tdata (output_bfd)->cverrefs = crefs;
+ }
}
/* Any syms created from now on start with -1 in
@@ -6792,7 +6785,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
if ((elf_tdata (output_bfd)->cverrefs == 0
&& elf_tdata (output_bfd)->cverdefs == 0)
|| _bfd_elf_link_renumber_dynsyms (output_bfd, info,
- &section_sym_count) == 0)
+ &section_sym_count) <= 1)
{
asection *s;