PR ld/14323

* elflink.c (elf_sort_symbol): Sort by size too.
	(elf_link_add_object_symbols <weakdefs>): Simplify binary search.
	Do not depend on ordering of symbol aliases.  Match largest size.
This commit is contained in:
Alan Modra 2012-07-09 08:17:34 +00:00
parent 2e515f7e37
commit 1416057852
2 changed files with 33 additions and 15 deletions

View File

@ -1,3 +1,10 @@
2012-07-09 Alan Modra <amodra@gmail.com>
PR ld/14323
* elflink.c (elf_sort_symbol): Sort by size too.
(elf_link_add_object_symbols <weakdefs>): Simplify binary search.
Do not depend on ordering of symbol aliases. Match largest size.
2012-07-03 H.J. Lu <hongjiu.lu@intel.com> 2012-07-03 H.J. Lu <hongjiu.lu@intel.com>
* elf.c (assign_section_numbers): Check if number of sections * elf.c (assign_section_numbers): Check if number of sections

View File

@ -3145,7 +3145,7 @@ on_needed_list (const char *soname, struct bfd_link_needed_list *needed)
return FALSE; return FALSE;
} }
/* Sort symbol by value and section. */ /* Sort symbol by value, section, and size. */
static int static int
elf_sort_symbol (const void *arg1, const void *arg2) elf_sort_symbol (const void *arg1, const void *arg2)
{ {
@ -3164,7 +3164,8 @@ elf_sort_symbol (const void *arg1, const void *arg2)
if (sdiff != 0) if (sdiff != 0)
return sdiff > 0 ? 1 : -1; return sdiff > 0 ? 1 : -1;
} }
return 0; vdiff = h1->size - h2->size;
return vdiff == 0 ? 0 : vdiff > 0 ? 1 : -1;
} }
/* This function is used to adjust offsets into .dynstr for /* This function is used to adjust offsets into .dynstr for
@ -4726,7 +4727,6 @@ error_free_dyn:
struct elf_link_hash_entry *hlook; struct elf_link_hash_entry *hlook;
asection *slook; asection *slook;
bfd_vma vlook; bfd_vma vlook;
long ilook;
size_t i, j, idx; size_t i, j, idx;
hlook = weaks; hlook = weaks;
@ -4740,14 +4740,13 @@ error_free_dyn:
slook = hlook->root.u.def.section; slook = hlook->root.u.def.section;
vlook = hlook->root.u.def.value; vlook = hlook->root.u.def.value;
ilook = -1;
i = 0; i = 0;
j = sym_count; j = sym_count;
while (i < j) while (i != j)
{ {
bfd_signed_vma vdiff; bfd_signed_vma vdiff;
idx = (i + j) / 2; idx = (i + j) / 2;
h = sorted_sym_hash [idx]; h = sorted_sym_hash[idx];
vdiff = vlook - h->root.u.def.value; vdiff = vlook - h->root.u.def.value;
if (vdiff < 0) if (vdiff < 0)
j = idx; j = idx;
@ -4761,24 +4760,36 @@ error_free_dyn:
else if (sdiff > 0) else if (sdiff > 0)
i = idx + 1; i = idx + 1;
else else
{ break;
ilook = idx;
break;
}
} }
} }
/* We didn't find a value/section match. */ /* We didn't find a value/section match. */
if (ilook == -1) if (i == j)
continue; continue;
for (i = ilook; i < sym_count; i++) /* With multiple aliases, or when the weak symbol is already
strongly defined, we have multiple matching symbols and
the binary search above may land on any of them. Step
one past the matching symbol(s). */
while (++idx != j)
{ {
h = sorted_sym_hash [i]; h = sorted_sym_hash[idx];
if (h->root.u.def.section != slook
|| h->root.u.def.value != vlook)
break;
}
/* Now look back over the aliases. Since we sorted by size
as well as value and section, we'll choose the one with
the largest size. */
while (idx-- != i)
{
h = sorted_sym_hash[idx];
/* Stop if value or section doesn't match. */ /* Stop if value or section doesn't match. */
if (h->root.u.def.value != vlook if (h->root.u.def.section != slook
|| h->root.u.def.section != slook) || h->root.u.def.value != vlook)
break; break;
else if (h != hlook) else if (h != hlook)
{ {