This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
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 11:29:02 -0700
- Subject: PATCH: PR ld/4590: String merging breaks ia64 linker
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.
H.J.
---
bfd/
2007-06-09 H.J. Lu <hongjiu.lu@intel.com>
PR ld/4590
* elfxx-ia64.c (elfNN_ia64_dyn_sym_info): Add addend_merged.
(addend_merged_compare): New.
(sort_dyn_sym_info): Call addend_merged_compare to sort array
of addend.
(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.
--- binutils/bfd/elfxx-ia64.c.merge 2007-06-09 07:31:50.000000000 -0700
+++ binutils/bfd/elfxx-ia64.c 2007-06-09 11:19:37.000000000 -0700
@@ -124,6 +124,9 @@ struct elfNN_ia64_dyn_sym_info
unsigned want_tprel : 1;
unsigned want_dtpmod : 1;
unsigned want_dtprel : 1;
+
+ /* TRUE if this addend is merged with another one. */
+ unsigned addend_merged: 1;
};
struct elfNN_ia64_local_hash_entry
@@ -2229,6 +2232,25 @@ addend_compare (const void *xp, const vo
return x->addend < y->addend ? -1 : x->addend > y->addend ? 1 : 0;
}
+/* This is similar to addend_compare. But it puts unmerged entry
+ before merged ones. It is used by sort_dyn_sym_info to remove
+ duplicated entries which have been merged. */
+
+static int
+addend_merged_compare (const void *xp, const void *yp)
+{
+ const struct elfNN_ia64_dyn_sym_info *x
+ = (const struct elfNN_ia64_dyn_sym_info *) xp;
+ const struct elfNN_ia64_dyn_sym_info *y
+ = (const struct elfNN_ia64_dyn_sym_info *) yp;
+
+ if (x->addend == y->addend)
+ return (x->addend_merged < y->addend_merged
+ ? -1 : x->addend_merged > y->addend_merged ? 1 : 0);
+ else
+ return x->addend < y->addend ? -1 : 1;
+}
+
/* Sort elfNN_ia64_dyn_sym_info array and remove duplicates. */
static unsigned int
@@ -2238,7 +2260,7 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn
bfd_vma curr, prev;
unsigned int i, dup, diff, dest, src, len;
- qsort (info, count, sizeof (*info), addend_compare);
+ qsort (info, count, sizeof (*info), addend_merged_compare);
/* Find the first duplicate. */
prev = info [0].addend;
@@ -4634,27 +4656,36 @@ elfNN_ia64_relocate_section (output_bfd,
{
struct elfNN_ia64_dyn_sym_info *dynent;
unsigned int count;
+ bfd_vma addend;
for (count = loc_h->count, dynent = loc_h->info;
count != 0;
count--, dynent++)
{
msec = sym_sec;
+ addend = dynent->addend;
dynent->addend =
_bfd_merged_section_offset (output_bfd, &msec,
elf_section_data (msec)->
sec_info,
sym->st_value
- + dynent->addend);
+ + addend);
dynent->addend -= sym->st_value;
dynent->addend += msec->output_section->vma
+ msec->output_offset
- sym_sec->output_section->vma
- sym_sec->output_offset;
+ dynent->addend_merged = dynent->addend != addend;
+ }
+
+ /* We may introduce a duplicated entry here. We need
+ to remove it properly. */
+ count = sort_dyn_sym_info (loc_h->info, loc_h->count);
+ if (count != loc_h->count)
+ {
+ loc_h->count = count;
+ loc_h->sorted_count = count;
}
-
- qsort (loc_h->info, loc_h->count,
- sizeof (*loc_h->info), addend_compare);
loc_h->sec_merge_done = 1;
}
--- binutils/ld/testsuite/ld-ia64/merge1.d.merge 2007-06-09 11:20:28.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge1.d 2007-06-09 11:22:27.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.merge 2007-06-09 11:20:31.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge1.s 2007-06-09 11:14:34.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 ;;