This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH: PR ld/4590: String merging breaks ia64 linker


On Thu, Jun 14, 2007 at 04:18:25PM +0200, Andreas Schwab wrote:
> "H. J. Lu" <hjl@lucon.org> writes:
> 
> > @@ -2290,20 +2326,41 @@ 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.  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)
>                              !=
> 
> With this typo fix it works.
> 

Can you try this one? I fixed another problem.

Thanks.


H.J.
---
bfd/

2007-06-12  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-12  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.

--- binutils/bfd/elfxx-ia64.c.merge	2007-06-12 18:37:38.000000000 -0700
+++ binutils/bfd/elfxx-ia64.c	2007-06-14 08:13:50.000000000 -0700
@@ -2235,37 +2235,66 @@ 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;
     }
 
   /* Remove duplicates.  */
   if (i < count)
     {
+      /* For duplicates, make sure that the kept one has a valid
+	 got_offset before we enter the loop since we may skip it.  */
+      if (got_offset != (bfd_vma) -1)
+	info [i - 1].got_offset = got_offset;
+
       /* 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;
@@ -2273,13 +2302,25 @@ 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;
+	  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;
 	    }
 
@@ -2290,20 +2331,41 @@ 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.  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++;
 		    }
@@ -2442,6 +2504,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
@@ -4652,9 +4715,15 @@ 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);
+		  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.merge	2007-06-14 07:35:10.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge1.d	2007-06-14 07:35:10.000000000 -0700
@@ -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;;
--- binutils/ld/testsuite/ld-ia64/merge1.s.merge	2007-06-14 07:35:10.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge1.s	2007-06-14 07:35:10.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.merge	2007-06-14 07:35:10.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge2.d	2007-06-14 07:35:10.000000000 -0700
@@ -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;;
--- binutils/ld/testsuite/ld-ia64/merge2.s.merge	2007-06-14 07:35:10.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge2.s	2007-06-14 07:35:10.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 ;;
--- binutils/ld/testsuite/ld-ia64/merge3.d.merge	2007-06-14 07:35:10.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge3.d	2007-06-14 07:35:10.000000000 -0700
@@ -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;;
--- binutils/ld/testsuite/ld-ia64/merge3.s.merge	2007-06-14 07:35:10.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge3.s	2007-06-14 07:35:10.000000000 -0700
@@ -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 ;;
--- binutils/ld/testsuite/ld-ia64/merge4.d.merge	2007-06-14 07:35:10.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge4.d	2007-06-14 07:35:10.000000000 -0700
@@ -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;;
--- binutils/ld/testsuite/ld-ia64/merge4.s.merge	2007-06-14 07:35:10.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge4.s	2007-06-14 07:35:10.000000000 -0700
@@ -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 ;;
+
--- binutils/ld/testsuite/ld-ia64/merge5.d.merge	2007-06-14 07:35:10.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge5.d	2007-06-14 07:35:10.000000000 -0700
@@ -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;;
--- binutils/ld/testsuite/ld-ia64/merge5.s.merge	2007-06-14 07:35:10.000000000 -0700
+++ binutils/ld/testsuite/ld-ia64/merge5.s	2007-06-14 07:35:10.000000000 -0700
@@ -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 ;;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]