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
- From: "H. J. Lu" <hjl at lucon dot org>
- To: binutils at sources dot redhat dot com
- Date: Sat, 9 Jun 2007 17:18:17 -0700
- Subject: Re: PATCH: PR ld/4590: String merging breaks ia64 linker
- References: <20070609182902.GA32046@lucon.org>
On Sat, Jun 09, 2007 at 11:29:02AM -0700, H. J. Lu wrote:
> When a string is merged with another one, we have to remove its
> addend from the array of addends. Otherwise, get_dyn_sym_info
> may return the entry whose addend has been merged. This patch
> calls sort_dyn_sym_info to remove the merged addends from the
> array.
>
The got entry may be allocated for the original or merged string.
This updated patch handles both cases.
H.J.
----
bfd/
2007-06-09 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.
ld/testsuite/
2007-06-09 H.J. Lu <hongjiu.lu@intel.com>
PR ld/4590
* ld-ia64/merge1.d: New.
* ld-ia64/merge1.s: Likewise.
* ld-ia64/merge2.d: Likewise.
* ld-ia64/merge2.s: Likewise.
--- binutils/bfd/elfxx-ia64.c.merged 2007-06-09 14:54:39.000000000 -0700
+++ binutils/bfd/elfxx-ia64.c 2007-06-09 17:09:07.000000000 -0700
@@ -2233,7 +2233,7 @@ 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;
@@ -2255,6 +2255,31 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn
{
/* We need to move a block of elements to here. */
dest = i++;
+
+ if (merged)
+ {
+ /* If a string is merged with another one, we need to
+ make sure that the kept entry has a valid got_offset. */
+ unsigned int kept = dest - 1;
+
+ if (info [kept].got_offset == (bfd_vma) -1)
+ {
+ unsigned int j;
+
+ for (j = dest; j < count; j++)
+ {
+ if (info [j].addend != curr)
+ break;
+
+ if (info [j].got_offset != (bfd_vma) -1)
+ {
+ info [kept].got_offset = info [j].got_offset;
+ break;
+ }
+ }
+ }
+ }
+
while (i < count)
{
curr = info [i].addend;
@@ -2442,6 +2467,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
@@ -2454,7 +2480,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;
}
@@ -4652,9 +4678,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 introduce a duplicated entry here. We need
+ to remove it 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;
}
--- binutils/ld/testsuite/ld-ia64/merge1.d.merged 2007-06-09 14:54:39.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge1.d 2007-06-09 14:54:39.000000000 -0700
@@ -0,0 +1,9 @@
+#source: merge1.s
+#as: -x
+#ld: -shared
+#objdump: -d
+
+#...
+[ ]*[a-f0-9]+: 0b 60 80 02 00 24 \[MMI\] addl r12=32,r1;;
+[ ]*[a-f0-9]+: c0 c0 04 00 48 00 addl r12=24,r1
+#pass
--- binutils/ld/testsuite/ld-ia64/merge1.s.merged 2007-06-09 14:54:39.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge1.s 2007-06-09 14:54:39.000000000 -0700
@@ -0,0 +1,12 @@
+ .section .rodata.str1.8,"aMS", 1
+.LC1: .string "foo"
+.LC2: .string "foo"
+ .section .data.rel.local,"aw"
+ .quad .LC2
+ .section .rodata,"a"
+.LC3: .string "bar"
+ .balign 8
+ .space 0x400000
+ .text
+ addl r12=@ltoffx(.LC1),r1 ;;
+ addl r12=@ltoffx(.LC3),r1 ;;
--- binutils/ld/testsuite/ld-ia64/merge2.d.merged 2007-06-09 16:55:11.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge2.d 2007-06-09 16:55:21.000000000 -0700
@@ -0,0 +1,9 @@
+#source: merge2.s
+#as: -x
+#ld: -shared
+#objdump: -d
+
+#...
+[ ]*[a-f0-9]+: 0b 60 80 02 00 24 \[MMI\] addl r12=32,r1;;
+[ ]*[a-f0-9]+: c0 c0 04 00 48 00 addl r12=24,r1
+#pass
--- binutils/ld/testsuite/ld-ia64/merge2.s.merged 2007-06-09 16:55:08.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge2.s 2007-06-09 16:55:25.000000000 -0700
@@ -0,0 +1,12 @@
+ .section .rodata.str1.8,"aMS", 1
+.LC2: .string "foo"
+.LC1: .string "foo"
+ .section .data.rel.local,"aw"
+ .quad .LC2
+ .section .rodata,"a"
+.LC3: .string "bar"
+ .balign 8
+ .space 0x400000
+ .text
+ addl r12=@ltoffx(.LC1),r1 ;;
+ addl r12=@ltoffx(.LC3),r1 ;;