From 668b8cbeee993cc49b28450386432f307345b7fd Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 19 Jun 2007 13:05:55 +0000 Subject: [PATCH] bfd/ 2007-06-19 H.J. Lu PR ld/4590 * elfxx-ia64.c (sort_dyn_sym_info): Keep the valid got_offset when removing duplicated entries. (get_dyn_sym_info): Initialize the got_offset field to -1. Update call to sort_dyn_sym_info. (elfNN_ia64_relocate_section): Call sort_dyn_sym_info to sort array of addend and remove duplicates. ld/testsuite/ 2007-06-19 H.J. Lu PR ld/4590 * ld-ia64/merge1.d: New. * ld-ia64/merge1.s: Likewise. * ld-ia64/merge2.d: Likewise. * ld-ia64/merge2.s: Likewise. * ld-ia64/merge3.d: Likewise. * ld-ia64/merge3.s: Likewise. * ld-ia64/merge4.d: Likewise. * ld-ia64/merge4.s: Likewise. * ld-ia64/merge5.d: Likewise. * ld-ia64/merge5.s: Likewise. --- bfd/ChangeLog | 10 ++++ bfd/elfxx-ia64.c | 112 +++++++++++++++++++++++++++++++++++------- ld/testsuite/ChangeLog | 14 ++++++ ld/testsuite/ld-ia64/merge1.d | 10 ++++ ld/testsuite/ld-ia64/merge1.s | 12 +++++ ld/testsuite/ld-ia64/merge2.d | 10 ++++ ld/testsuite/ld-ia64/merge2.s | 12 +++++ ld/testsuite/ld-ia64/merge3.d | 13 +++++ ld/testsuite/ld-ia64/merge3.s | 16 ++++++ ld/testsuite/ld-ia64/merge4.d | 13 +++++ ld/testsuite/ld-ia64/merge4.s | 21 ++++++++ ld/testsuite/ld-ia64/merge5.d | 16 ++++++ ld/testsuite/ld-ia64/merge5.s | 24 +++++++++ 13 files changed, 266 insertions(+), 17 deletions(-) create mode 100644 ld/testsuite/ld-ia64/merge1.d create mode 100644 ld/testsuite/ld-ia64/merge1.s create mode 100644 ld/testsuite/ld-ia64/merge2.d create mode 100644 ld/testsuite/ld-ia64/merge2.s create mode 100644 ld/testsuite/ld-ia64/merge3.d create mode 100644 ld/testsuite/ld-ia64/merge3.s create mode 100644 ld/testsuite/ld-ia64/merge4.d create mode 100644 ld/testsuite/ld-ia64/merge4.s create mode 100644 ld/testsuite/ld-ia64/merge5.d create mode 100644 ld/testsuite/ld-ia64/merge5.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index cf6669947b..e956197fdf 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2007-06-19 H.J. Lu + + PR ld/4590 + * elfxx-ia64.c (sort_dyn_sym_info): Keep the valid got_offset + when removing duplicated entries. + (get_dyn_sym_info): Initialize the got_offset field to -1. + Update call to sort_dyn_sym_info. + (elfNN_ia64_relocate_section): Call sort_dyn_sym_info to sort + array of addend and remove duplicates. + 2007-06-18 H.J. Lu * libpei.h (_bfd_XXi_final_link_postscript): Remove diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index f3674b4514..68f2010c61 100644 --- a/bfd/elfxx-ia64.c +++ b/bfd/elfxx-ia64.c @@ -2234,37 +2234,62 @@ static unsigned int sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, unsigned int count) { - bfd_vma curr, prev; - unsigned int i, dup, diff, dest, src, len; + bfd_vma curr, prev, got_offset; + unsigned int i, kept, dup, diff, dest, src, len; qsort (info, count, sizeof (*info), addend_compare); /* Find the first duplicate. */ prev = info [0].addend; + got_offset = info [0].got_offset; for (i = 1; i < count; i++) { curr = info [i].addend; if (curr == prev) - break; + { + /* For duplicates, make sure that GOT_OFFSET is valid. */ + if (got_offset == (bfd_vma) -1) + got_offset = info [i].got_offset; + break; + } + got_offset = info [i].got_offset; prev = curr; } + /* We may move a block of elements to here. */ + dest = i++; + /* Remove duplicates. */ if (i < count) { - /* We need to move a block of elements to here. */ - dest = i++; while (i < count) { + /* For duplicates, make sure that the kept one has a valid + got_offset. */ + kept = dest - 1; + if (got_offset != (bfd_vma) -1) + info [kept].got_offset = got_offset; + curr = info [i].addend; + got_offset = info [i].got_offset; /* Move a block of elements whose first one is different from the previous. */ if (curr == prev) { for (src = i + 1; src < count; src++) - if (info [src].addend != curr) - break; + { + if (info [src].addend != curr) + break; + /* For duplicates, make sure that GOT_OFFSET is + valid. */ + if (got_offset == (bfd_vma) -1) + got_offset = info [src].got_offset; + } + + /* Make sure that the kept one has a valid got_offset. */ + if (got_offset != (bfd_vma) -1) + info [kept].got_offset = got_offset; } else src = i; @@ -2272,13 +2297,25 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, if (src >= count) break; - /* Find the next duplicate. */ + /* Find the next duplicate. SRC will be kept. */ prev = info [src].addend; + got_offset = info [src].got_offset; for (dup = src + 1; dup < count; dup++) { curr = info [dup].addend; if (curr == prev) - break; + { + /* Make sure that got_offset is valid. */ + if (got_offset == (bfd_vma) -1) + got_offset = info [dup].got_offset; + + /* For duplicates, make sure that the kept one has + a valid got_offset. */ + if (got_offset != (bfd_vma) -1) + info [dup - 1].got_offset = got_offset; + break; + } + got_offset = info [dup].got_offset; prev = curr; } @@ -2289,20 +2326,41 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, if (len == 1 && dup < count) { /* If we only move 1 element, we combine it with the next - one. Find the next different one. */ + one. There must be at least a duplicate. 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; + /* Make sure that got_offset is valid. */ + if (got_offset == (bfd_vma) -1) + got_offset = info [diff].got_offset; + } + + /* Makre sure that the last duplicated one has an valid + offset. */ + BFD_ASSERT (curr == prev); + if (got_offset != (bfd_vma) -1) + info [diff - 1].got_offset = got_offset; if (diff < count) { - /* Find the next duplicate. */ + /* Find the next duplicate. Track the current valid + offset. */ prev = info [diff].addend; + got_offset = info [diff].got_offset; for (dup = diff + 1; dup < count; dup++) { curr = info [dup].addend; if (curr == prev) - break; + { + /* For duplicates, make sure that GOT_OFFSET + is valid. */ + if (got_offset == (bfd_vma) -1) + got_offset = info [dup].got_offset; + break; + } + got_offset = info [dup].got_offset; prev = curr; diff++; } @@ -2319,6 +2377,19 @@ sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info, count = dest; } + else + { + /* When we get here, either there is no duplicate at all or + the only duplicate is the last element. */ + if (dest < count) + { + /* If the last element is a duplicate, make sure that the + kept one has a valid got_offset. We also update count. */ + if (got_offset != (bfd_vma) -1) + info [dest - 1].got_offset = got_offset; + count = dest; + } + } return count; } @@ -2441,6 +2512,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 @@ -4651,9 +4723,15 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, - 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); + if (count != loc_h->count) + { + loc_h->count = count; + loc_h->sorted_count = count; + } loc_h->sec_merge_done = 1; } diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 8a29ecec14..9cd711ab46 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,17 @@ +2007-06-19 H.J. Lu + + PR ld/4590 + * ld-ia64/merge1.d: New. + * ld-ia64/merge1.s: Likewise. + * ld-ia64/merge2.d: Likewise. + * ld-ia64/merge2.s: Likewise. + * ld-ia64/merge3.d: Likewise. + * ld-ia64/merge3.s: Likewise. + * ld-ia64/merge4.d: Likewise. + * ld-ia64/merge4.s: Likewise. + * ld-ia64/merge5.d: Likewise. + * ld-ia64/merge5.s: Likewise. + 2007-06-18 Andreas Schwab * ld-scripts/cross3.t: Add .opd section. diff --git a/ld/testsuite/ld-ia64/merge1.d b/ld/testsuite/ld-ia64/merge1.d new file mode 100644 index 0000000000..39882b8674 --- /dev/null +++ b/ld/testsuite/ld-ia64/merge1.d @@ -0,0 +1,10 @@ +#source: merge1.s +#as: -x +#ld: -shared +#objdump: -d + +#... +0+1e0 <.text>: +[ ]*[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 +[ ]*[a-f0-9]+: 00 00 04 00 nop.i 0x0;; diff --git a/ld/testsuite/ld-ia64/merge1.s b/ld/testsuite/ld-ia64/merge1.s new file mode 100644 index 0000000000..8998db43c7 --- /dev/null +++ b/ld/testsuite/ld-ia64/merge1.s @@ -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 ;; diff --git a/ld/testsuite/ld-ia64/merge2.d b/ld/testsuite/ld-ia64/merge2.d new file mode 100644 index 0000000000..dde3d097d1 --- /dev/null +++ b/ld/testsuite/ld-ia64/merge2.d @@ -0,0 +1,10 @@ +#source: merge2.s +#as: -x +#ld: -shared +#objdump: -d + +#... +0+1e0 <.text>: +[ ]*[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 +[ ]*[a-f0-9]+: 00 00 04 00 nop.i 0x0;; diff --git a/ld/testsuite/ld-ia64/merge2.s b/ld/testsuite/ld-ia64/merge2.s new file mode 100644 index 0000000000..6c85ac2ee3 --- /dev/null +++ b/ld/testsuite/ld-ia64/merge2.s @@ -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 ;; diff --git a/ld/testsuite/ld-ia64/merge3.d b/ld/testsuite/ld-ia64/merge3.d new file mode 100644 index 0000000000..d0163f3245 --- /dev/null +++ b/ld/testsuite/ld-ia64/merge3.d @@ -0,0 +1,13 @@ +#source: merge3.s +#as: -x +#ld: -shared +#objdump: -d + +#... +0+210 <.text>: +[ ]*[a-f0-9]+: 0b 60 80 02 00 24 \[MMI\] addl r12=32,r1;; +[ ]*[a-f0-9]+: c0 40 05 00 48 00 addl r12=40,r1 +[ ]*[a-f0-9]+: 00 00 04 00 nop.i 0x0;; +[ ]*[a-f0-9]+: 01 60 60 02 00 24 \[MII\] addl r12=24,r1 +[ ]*[a-f0-9]+: 00 00 00 02 00 00 nop.i 0x0 +[ ]*[a-f0-9]+: 00 00 04 00 nop.i 0x0;; diff --git a/ld/testsuite/ld-ia64/merge3.s b/ld/testsuite/ld-ia64/merge3.s new file mode 100644 index 0000000000..2442701fc8 --- /dev/null +++ b/ld/testsuite/ld-ia64/merge3.s @@ -0,0 +1,16 @@ + .section .rodata.str1.8,"aMS", 1 +.LC1: .string "foo" +.LC2: .string "foo" +.LC3: .string "bar" +.LC4: .string "bar" + .section .data.rel.local,"aw" + .quad .LC2 + .quad .LC3 + .section .rodata,"a" +.LC5: .string "mumble" + .balign 8 + .space 0x400000 + .text + addl r12=@ltoffx(.LC1),r1 ;; + addl r12=@ltoffx(.LC4),r1 ;; + addl r12=@ltoffx(.LC5),r1 ;; diff --git a/ld/testsuite/ld-ia64/merge4.d b/ld/testsuite/ld-ia64/merge4.d new file mode 100644 index 0000000000..0ed5621007 --- /dev/null +++ b/ld/testsuite/ld-ia64/merge4.d @@ -0,0 +1,13 @@ +#source: merge4.s +#as: -x +#ld: -shared +#objdump: -d + +#... +0+240 <.text>: +[ ]*[a-f0-9]+: 0b 60 80 02 00 24 \[MMI\] addl r12=32,r1;; +[ ]*[a-f0-9]+: c0 40 05 00 48 00 addl r12=40,r1 +[ ]*[a-f0-9]+: 00 00 04 00 nop.i 0x0;; +[ ]*[a-f0-9]+: 0b 60 c0 02 00 24 \[MMI\] addl r12=48,r1;; +[ ]*[a-f0-9]+: c0 c0 04 00 48 00 addl r12=24,r1 +[ ]*[a-f0-9]+: 00 00 04 00 nop.i 0x0;; diff --git a/ld/testsuite/ld-ia64/merge4.s b/ld/testsuite/ld-ia64/merge4.s new file mode 100644 index 0000000000..c23b4d0ea1 --- /dev/null +++ b/ld/testsuite/ld-ia64/merge4.s @@ -0,0 +1,21 @@ + .section .rodata.str1.8,"aMS", 1 +.LC1: .string "foo" +.LC2: .string "foo" +.LC3: .string "bar" +.LC4: .string "bar" +.LC5: .string "baz" +.LC6: .string "baz" + .section .data.rel.local,"aw" + .quad .LC2 + .quad .LC4 + .quad .LC5 + .section .rodata,"a" +.LC7: .string "mumble" + .balign 8 + .space 0x400000 + .text + addl r12=@ltoffx(.LC1),r1 ;; + addl r12=@ltoffx(.LC3),r1 ;; + addl r12=@ltoffx(.LC6),r1 ;; + addl r12=@ltoffx(.LC7),r1 ;; + diff --git a/ld/testsuite/ld-ia64/merge5.d b/ld/testsuite/ld-ia64/merge5.d new file mode 100644 index 0000000000..3adfa55ca1 --- /dev/null +++ b/ld/testsuite/ld-ia64/merge5.d @@ -0,0 +1,16 @@ +#source: merge5.s +#as: -x +#ld: -shared +#objdump: -d + +#... +0+270 <.text>: +[ ]*[a-f0-9]+: 0b 60 80 02 00 24 \[MMI\] addl r12=32,r1;; +[ ]*[a-f0-9]+: c0 40 05 00 48 00 addl r12=40,r1 +[ ]*[a-f0-9]+: 00 00 04 00 nop.i 0x0;; +[ ]*[a-f0-9]+: 0b 60 a0 02 00 24 \[MMI\] addl r12=40,r1;; +[ ]*[a-f0-9]+: c0 c0 05 00 48 00 addl r12=56,r1 +[ ]*[a-f0-9]+: 00 00 04 00 nop.i 0x0;; +[ ]*[a-f0-9]+: 01 60 60 02 00 24 \[MII\] addl r12=24,r1 +[ ]*[a-f0-9]+: 00 00 00 02 00 00 nop.i 0x0 +[ ]*[a-f0-9]+: 00 00 04 00 nop.i 0x0;; diff --git a/ld/testsuite/ld-ia64/merge5.s b/ld/testsuite/ld-ia64/merge5.s new file mode 100644 index 0000000000..81428c41cc --- /dev/null +++ b/ld/testsuite/ld-ia64/merge5.s @@ -0,0 +1,24 @@ + .section .rodata.str1.8,"aMS", 1 +.LC1: .string "foo" +.LC2: .string "foo" +.LC3: .string "bar" +.LC4: .string "bar" +.LC5: .string "bar" +.LC6: .string "bar" +.LC7: .string "baz" +.LC8: .string "baz" + .section .data.rel.local,"aw" + .quad .LC2 + .quad .LC4 + .quad .LC6 + .quad .LC7 + .section .rodata,"a" +.LC9: .string "mumble" + .balign 8 + .space 0x400000 + .text + addl r12=@ltoffx(.LC1),r1 ;; + addl r12=@ltoffx(.LC3),r1 ;; + addl r12=@ltoffx(.LC5),r1 ;; + addl r12=@ltoffx(.LC8),r1 ;; + addl r12=@ltoffx(.LC9),r1 ;; -- 2.11.0