This is the mail archive of the binutils@sources.redhat.com 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]

Fix ld/418


Hi Jakub,
  I'd like your opinion on the following patch to fix
http://sources.redhat.com/bugzilla/show_bug.cgi?id=418.  xlc apparently
uses a LSDA that isn't a pointer, thus making it pc-relative doesn't
really make much sense.  The changelog below should make it clear
what I'm doing.

	* elf-bfd.h (struct eh_cie_fde): Add need_relative and
	need_lsda_relative.
	* elf-eh-frame.c (_bfd_elf_eh_frame_section_offset): Set
	need_relative or need_lsda_relative if we are processing an
	offset for a reloc on a FDE initial loc or LSDA field
	respectively.
	(_bfd_elf_write_section_eh_frame): Test need_relative and
	need_lsda_relative in place of corresponding make_* field
	when deciding to use pc-relative encodings.

BTW, I haven't tested this very well yet, just binutils testsuite runs
and checking that this cures the testcase.  I intend to build gcc and
glibc overnight, and verify that it doesn't cause regressions before
committing.

An alternative hack that works in this particular case is to not
translate lsda to pcrel if lsda is too small to be a pointer.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.158
diff -u -p -r1.158 elf-bfd.h
--- bfd/elf-bfd.h	17 Sep 2004 07:14:25 -0000	1.158
+++ bfd/elf-bfd.h	30 Sep 2004 14:00:31 -0000
@@ -296,7 +296,9 @@ struct eh_cie_fde
   unsigned int cie : 1;
   unsigned int removed : 1;
   unsigned int make_relative : 1;
+  unsigned int need_relative : 1;
   unsigned int make_lsda_relative : 1;
+  unsigned int need_lsda_relative : 1;
   unsigned int per_encoding_relative : 1;
 };
 
Index: bfd/elf-eh-frame.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-eh-frame.c,v
retrieving revision 1.31
diff -u -p -r1.31 elf-eh-frame.c
--- bfd/elf-eh-frame.c	24 Jun 2004 04:46:17 -0000	1.31
+++ bfd/elf-eh-frame.c	30 Sep 2004 13:59:52 -0000
@@ -775,7 +775,10 @@ _bfd_elf_eh_frame_section_offset (bfd *o
   if (sec_info->entry[mid].make_relative
       && ! sec_info->entry[mid].cie
       && offset == sec_info->entry[mid].offset + 8)
-    return (bfd_vma) -2;
+    {
+      sec_info->entry[mid].need_relative = 1;
+      return (bfd_vma) -2;
+    }
 
   /* If converting LSDA pointers to DW_EH_PE_pcrel, there will be no need
      for run-time relocation against LSDA field.  */
@@ -783,7 +786,10 @@ _bfd_elf_eh_frame_section_offset (bfd *o
       && ! sec_info->entry[mid].cie
       && (offset == (sec_info->entry[mid].offset + 8
 		     + sec_info->entry[mid].lsda_offset)))
-    return (bfd_vma) -2;
+    {
+      sec_info->entry[mid].need_lsda_relative = 1;
+      return (bfd_vma) -2;
+    }
 
   return (offset + sec_info->entry[mid].new_offset
 	  - sec_info->entry[mid].offset);
@@ -850,8 +856,8 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 	{
 	  /* CIE */
 	  cie_offset = sec_info->entry[i].new_offset;
-	  if (sec_info->entry[i].make_relative
-	      || sec_info->entry[i].make_lsda_relative
+	  if (sec_info->entry[i].need_relative
+	      || sec_info->entry[i].need_lsda_relative
 	      || sec_info->entry[i].per_encoding_relative)
 	    {
 	      unsigned char *aug;
@@ -860,8 +866,8 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 
 	      /* Need to find 'R' or 'L' augmentation's argument and modify
 		 DW_EH_PE_* value.  */
-	      action = (sec_info->entry[i].make_relative ? 1 : 0)
-		       | (sec_info->entry[i].make_lsda_relative ? 2 : 0)
+	      action = (sec_info->entry[i].need_relative ? 1 : 0)
+		       | (sec_info->entry[i].need_lsda_relative ? 2 : 0)
 		       | (sec_info->entry[i].per_encoding_relative ? 4 : 0);
 	      buf = contents + sec_info->entry[i].offset;
 	      /* Skip length, id and version.  */
@@ -968,7 +974,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 			      + sec_info->entry[i].offset + 8);
 		  break;
 		}
-	      if (sec_info->entry[i].make_relative)
+	      if (sec_info->entry[i].need_relative)
 		value -= (sec->output_section->vma + sec->output_offset
 			  + sec_info->entry[i].new_offset + 8);
 	      write_value (abfd, buf, value, width);
@@ -983,7 +989,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 	    }
 
 	  if ((sec_info->entry[i].lsda_encoding & 0xf0) == DW_EH_PE_pcrel
-	      || sec_info->entry[i].make_lsda_relative)
+	      || sec_info->entry[i].need_lsda_relative)
 	    {
 	      buf += sec_info->entry[i].lsda_offset;
 	      width = get_DW_EH_PE_width (sec_info->entry[i].lsda_encoding,
@@ -997,7 +1003,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 		      == DW_EH_PE_pcrel)
 		    value += (sec_info->entry[i].offset
 			      - sec_info->entry[i].new_offset);
-		  else if (sec_info->entry[i].make_lsda_relative)
+		  else if (sec_info->entry[i].need_lsda_relative)
 		    value -= (sec->output_section->vma + sec->output_offset
 			      + sec_info->entry[i].new_offset + 8
 			      + sec_info->entry[i].lsda_offset);

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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