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.
This commit is contained in:
parent
ab502e635e
commit
3d13f3e9bd
|
@ -1,3 +1,11 @@
|
|||
2017-09-19 Alan Modra <amodra@gmail.com>
|
||||
|
||||
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.
|
||||
|
||||
2017-09-18 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/22148
|
||||
|
|
235
bfd/elflink.c
235
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,111 +6354,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
|
|||
|
||||
elf_tdata (output_bfd)->cverdefs = cdefs;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
|
||||
size += sizeof (Elf_External_Verneed);
|
||||
++crefs;
|
||||
for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
|
||||
size += sizeof (Elf_External_Vernaux);
|
||||
}
|
||||
|
||||
s->size = size;
|
||||
s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
|
||||
if (s->contents == NULL)
|
||||
return FALSE;
|
||||
|
||||
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));
|
||||
|
||||
_bfd_elf_swap_verneed_out (output_bfd, vn,
|
||||
(Elf_External_Verneed *) p);
|
||||
p += sizeof (Elf_External_Verneed);
|
||||
|
||||
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);
|
||||
|
||||
_bfd_elf_swap_vernaux_out (output_bfd, a,
|
||||
(Elf_External_Vernaux *) p);
|
||||
p += sizeof (Elf_External_Vernaux);
|
||||
}
|
||||
}
|
||||
|
||||
elf_tdata (output_bfd)->cverrefs = crefs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bed = get_elf_backend_data (output_bfd);
|
||||
|
@ -6467,22 +6361,121 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
|
|||
if (info->gc_sections && bed->can_gc_sections)
|
||||
{
|
||||
struct elf_gc_sweep_symbol_info sweep_info;
|
||||
unsigned long section_sym_count;
|
||||
|
||||
/* 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? */
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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, §ion_sym_count);
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
size += sizeof (Elf_External_Verneed);
|
||||
++crefs;
|
||||
for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
|
||||
size += sizeof (Elf_External_Vernaux);
|
||||
}
|
||||
|
||||
s->size = size;
|
||||
s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
|
||||
if (s->contents == NULL)
|
||||
return FALSE;
|
||||
|
||||
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));
|
||||
|
||||
_bfd_elf_swap_verneed_out (output_bfd, vn,
|
||||
(Elf_External_Verneed *) p);
|
||||
p += sizeof (Elf_External_Verneed);
|
||||
|
||||
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);
|
||||
|
||||
_bfd_elf_swap_vernaux_out (output_bfd, a,
|
||||
(Elf_External_Vernaux *) p);
|
||||
p += sizeof (Elf_External_Vernaux);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
§ion_sym_count) == 0)
|
||||
§ion_sym_count) <= 1)
|
||||
{
|
||||
asection *s;
|
||||
|
||||
|
|
Loading…
Reference in New Issue