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 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 ;;


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