bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 19 Jun 2007 13:05:55 +0000 (13:05 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 19 Jun 2007 13:05:55 +0000 (13:05 +0000)
2007-06-19  H.J. Lu  <hongjiu.lu@intel.com>

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  <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.
* 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.

13 files changed:
bfd/ChangeLog
bfd/elfxx-ia64.c
ld/testsuite/ChangeLog
ld/testsuite/ld-ia64/merge1.d [new file with mode: 0644]
ld/testsuite/ld-ia64/merge1.s [new file with mode: 0644]
ld/testsuite/ld-ia64/merge2.d [new file with mode: 0644]
ld/testsuite/ld-ia64/merge2.s [new file with mode: 0644]
ld/testsuite/ld-ia64/merge3.d [new file with mode: 0644]
ld/testsuite/ld-ia64/merge3.s [new file with mode: 0644]
ld/testsuite/ld-ia64/merge4.d [new file with mode: 0644]
ld/testsuite/ld-ia64/merge4.s [new file with mode: 0644]
ld/testsuite/ld-ia64/merge5.d [new file with mode: 0644]
ld/testsuite/ld-ia64/merge5.s [new file with mode: 0644]

index cf6669947b8787863801fb2a648df59e43000b30..e956197fdf19587db30f71107161b8ec3f9cf777 100644 (file)
@@ -1,3 +1,13 @@
+2007-06-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+       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  <hongjiu.lu@intel.com>
 
        * libpei.h (_bfd_XXi_final_link_postscript): Remove
index f3674b4514691f65aa090f3ecd9f7fc40c3e8262..68f2010c61922f39a056d122c546340a7dd3c4b3 100644 (file)
@@ -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;
                }
index 8a29ecec145b0fa613c2e17d96fcd81143044fb3..9cd711ab46b8e560d3044a8fb62a44415190502b 100644 (file)
@@ -1,3 +1,17 @@
+2007-06-19  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.
+       * 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  <schwab@suse.de>
 
        * 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 (file)
index 0000000..39882b8
--- /dev/null
@@ -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 (file)
index 0000000..8998db4
--- /dev/null
@@ -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 (file)
index 0000000..dde3d09
--- /dev/null
@@ -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 (file)
index 0000000..6c85ac2
--- /dev/null
@@ -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 (file)
index 0000000..d0163f3
--- /dev/null
@@ -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 (file)
index 0000000..2442701
--- /dev/null
@@ -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 (file)
index 0000000..0ed5621
--- /dev/null
@@ -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 (file)
index 0000000..c23b4d0
--- /dev/null
@@ -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 (file)
index 0000000..3adfa55
--- /dev/null
@@ -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 (file)
index 0000000..81428c4
--- /dev/null
@@ -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 ;;