This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: PATCH: PR ld/4590: String merging breaks ia64 linker
"H. J. Lu" <hjl@lucon.org> writes:
> On Tue, Jun 12, 2007 at 04:02:00PM +0200, Andreas Schwab wrote:
>> "H. J. Lu" <hjl@lucon.org> writes:
>>
>> > Please try this one.
>> >
>> > Thanks.
>> >
>> > H.J.
>> > -----
>> > 2007-06-12 H.J. Lu <hongjiu.lu@intel.com>
>> >
>> > PR ld/4590
>> > * elfxx-ia64.c (sort_dyn_sym_info): Take a new argument for
>> > string merge. Keep the valid got_offset when removing
>> > duplicated entries for string merge
>> > (get_dyn_sym_info): Initialize the got_offset field to -1.
>> > Update call to sort_dyn_sym_info.
>> > (elfNN_ia64_relocate_section): Set addend_merged if the
>> > addend is merged with another one. Call sort_dyn_sym_info
>> > to sort array of addend and remove duplicates.
>>
>> Still getting the same assertion failures.
>>
>
> Can you try this one?
This works for me.
Index: elfxx-ia64.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-ia64.c,v
retrieving revision 1.198
diff -u -a -p -a -u -p -r1.198 elfxx-ia64.c
--- elfxx-ia64.c 26 Apr 2007 14:46:57 -0000 1.198
+++ elfxx-ia64.c 12 Jun 2007 17:14:52 -0000
@@ -2232,21 +2232,29 @@ addend_compare (const void *xp, const vo
static unsigned int
sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info,
- unsigned int count)
+ unsigned int count, bfd_boolean merged)
{
bfd_vma curr, prev;
- unsigned int i, dup, diff, dest, src, len;
+ unsigned int i, kept, dup, diff, dest, src, len;
qsort (info, count, sizeof (*info), addend_compare);
/* Find the first duplicate. */
- prev = info [0].addend;
+ kept = 0;
+ prev = info [kept].addend;
for (i = 1; i < count; i++)
{
curr = info [i].addend;
if (curr == prev)
- break;
+ {
+ /* If a string is merged with another one, we need to make
+ sure that KEPT has a valid got_offset. */
+ if (merged && info [kept].got_offset == (bfd_vma) -1)
+ info [kept].got_offset = info [i].got_offset;
+ break;
+ }
prev = curr;
+ kept++;
}
/* Remove duplicates. */
@@ -2262,9 +2270,19 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn
the previous. */
if (curr == prev)
{
+ bfd_vma got_offset = info [i].got_offset;
+
for (src = i + 1; src < count; src++)
- if (info [src].addend != curr)
- break;
+ {
+ if (info [src].addend != curr)
+ break;
+ if (merged && got_offset == (bfd_vma) -1)
+ got_offset = info [src].got_offset;
+ }
+ /* If a string is merged with another one, we need
+ to make sure that KEPT has a valid got_offset. */
+ if (merged && info [kept].got_offset == (bfd_vma) -1)
+ info [kept].got_offset = got_offset;
}
else
src = i;
@@ -2272,13 +2290,19 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn
if (src >= count)
break;
- /* Find the next duplicate. */
+ /* Find the next duplicate. SRC will be kept. */
prev = info [src].addend;
for (dup = src + 1; dup < count; dup++)
{
curr = info [dup].addend;
if (curr == prev)
- break;
+ {
+ /* If a string is merged with another one, we keep
+ the valid got_offset in the previous entry. */
+ if (merged && info [dup - 1].got_offset == (bfd_vma) -1)
+ info [dup - 1].got_offset = info [dup].got_offset;
+ break;
+ }
prev = curr;
}
@@ -2289,14 +2313,32 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn
if (len == 1 && dup < count)
{
/* If we only move 1 element, we combine it with the next
- one. Find the next different one. */
+ one. We will keep DUP instead of SRC. Make sure that
+ DUP has a valid got_offset. */
+
+ bfd_vma got_offset = info [src].got_offset;
+
+ kept = dup;
+
+ /* Find the next different one. */
for (diff = dup + 1, src++; diff < count; diff++, src++)
- if (info [diff].addend != curr)
- break;
+ {
+ if (info [diff].addend != curr)
+ break;
+ kept = diff;
+ /* DIFF may be kept. If a string is merged with
+ another one, we need to make sure that a valid
+ got_offset is kept. */
+ if (merged && got_offset == (bfd_vma) -1)
+ got_offset = info [diff].got_offset;
+ }
+
+ if (merged && info [kept].got_offset == (bfd_vma) -1)
+ info [kept].got_offset = got_offset;
if (diff < count)
{
- /* Find the next duplicate. */
+ /* Find the next duplicate. DIFF will be kept. */
prev = info [diff].addend;
for (dup = diff + 1; dup < count; dup++)
{
@@ -2315,6 +2357,9 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn
memmove (&info [dest], &info [src], len * sizeof (*info));
dest += len;
+
+ /* We will keep this one. */
+ kept = dest - 1;
}
count = dest;
@@ -2441,6 +2486,7 @@ has_space:
/* Append the new one to the array. */
dyn_i = info + count;
memset (dyn_i, 0, sizeof (*dyn_i));
+ dyn_i->got_offset = (bfd_vma) -1;
dyn_i->addend = addend;
/* We increment count only since the new ones are unsorted and
@@ -2453,7 +2499,7 @@ has_space:
array isn't sorted. */
if (count != sorted_count)
{
- count = sort_dyn_sym_info (info, count);
+ count = sort_dyn_sym_info (info, count, FALSE);
*count_p = count;
*sorted_count_p = count;
}
@@ -4651,9 +4697,16 @@ elfNN_ia64_relocate_section (output_bfd,
- sym_sec->output_section->vma
- sym_sec->output_offset;
}
-
- qsort (loc_h->info, loc_h->count,
- sizeof (*loc_h->info), addend_compare);
+
+ /* We may have introduced duplicated entries. We need
+ to remove them properly. */
+ count = sort_dyn_sym_info (loc_h->info, loc_h->count,
+ TRUE);
+ if (count != loc_h->count)
+ {
+ loc_h->count = count;
+ loc_h->sorted_count = count;
+ }
loc_h->sec_merge_done = 1;
}
Andreas.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."