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]

[PATCH] Fix --eh-frame-hdr with DW_EH_PE_pcrel personality encoding


Hi!

I've commited the following patch to fix --eh-frame-hdr handling.
I forgot to adjust personalities when reshuffling FDE/CIEs if personalities
are DW_EH_PE_pcrel encoded. It is quite serious bug, will see if I can
cook up a test for gcc configury for this.
Daniel, ok to commit to 2.12 branch? Is 2.12.1 on the horizon?

2002-04-22  Richard Smith  <richard@ex-parrot.com>
	    Jakub Jelinek  <jakub@redhat.com>

	* elf-eh-frame.c (struct eh_cie_fde): Add per_encoding_relative.
	(_bfd_elf_discard_section_eh_frame): Set it for CIEs with pcrel
	encoded personality.
	(_bfd_elf_write_section_eh_frame): Adjust pcrel encoded personality
	for CIE/FDE removal.

--- bfd/elf-eh-frame.c.jj	Tue Feb 19 13:37:48 2002
+++ bfd/elf-eh-frame.c	Mon Apr 22 13:57:23 2002
@@ -64,6 +64,7 @@ struct eh_cie_fde
   unsigned char removed : 1;
   unsigned char make_relative : 1;
   unsigned char make_lsda_relative : 1;
+  unsigned char per_encoding_relative : 1;
 };
 
 struct eh_frame_sec_info
@@ -469,6 +470,8 @@ _bfd_elf_discard_section_eh_frame (abfd,
 		    = cie.make_relative;
 		  sec_info->entry[last_cie_ndx].make_lsda_relative
 		    = cie.make_lsda_relative;
+		  sec_info->entry[last_cie_ndx].per_encoding_relative
+		    = (cie.per_encoding & 0x70) == DW_EH_PE_pcrel;
 		}
 	    }
 
@@ -689,6 +692,7 @@ _bfd_elf_discard_section_eh_frame (abfd,
 	    {
 	      sec_info->entry[i].make_relative = make_relative;
 	      sec_info->entry[i].make_lsda_relative = make_lsda_relative;
+	      sec_info->entry[i].per_encoding_relative = 0;
 	    }
 	}
       else if (sec_info->entry[i].cie && sec_info->entry[i].sec == sec)
@@ -947,7 +951,8 @@ _bfd_elf_write_section_eh_frame (abfd, s
 	  /* CIE */
 	  cie_offset = sec_info->entry[i].new_offset;
 	  if (sec_info->entry[i].make_relative
-	      || sec_info->entry[i].make_lsda_relative)
+	      || sec_info->entry[i].make_lsda_relative
+	      || sec_info->entry[i].per_encoding_relative)
 	    {
 	      unsigned char *aug;
 	      unsigned int action;
@@ -956,7 +961,8 @@ _bfd_elf_write_section_eh_frame (abfd, s
 	      /* 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);
+		       | (sec_info->entry[i].make_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.  */
 	      buf += 9;
@@ -988,10 +994,22 @@ _bfd_elf_write_section_eh_frame (abfd, s
                     per_width = get_DW_EH_PE_width (per_encoding,
 						    ptr_size);
 		    BFD_ASSERT (per_width != 0);
+		    BFD_ASSERT (((per_encoding & 0x70) == DW_EH_PE_pcrel)
+				== sec_info->entry[i].per_encoding_relative);
 		    if ((per_encoding & 0xf0) == DW_EH_PE_aligned)
 		      buf = (contents
 			     + ((buf - contents + per_width - 1)
 				& ~((bfd_size_type) per_width - 1)));
+		    if (action & 4)
+		      {
+			bfd_vma value;
+
+			value = read_value (abfd, buf, per_width);
+			value += (sec_info->entry[i].offset
+				  - sec_info->entry[i].new_offset);
+			write_value (abfd, buf, value, per_width);
+			action &= ~4;
+		      }
 		    buf += per_width;
 		    break;
 		  case 'R':

	Jakub


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