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]

Convert absolute personalities into PC-relative ones


As discussed with Mark recently, this patch allows the linker to turn
absolute-but-locally-binding personality pointers into PC-relative ones,
under the usual "info->shared && we support this" condition.  MIPS needs
this to work for indirect pointers too, and that shows up a problem in
the current elf-eh-frame.c code: it treats the top nibble as an enum
of the base address, whereas DW_EH_PE_indirect is really a separate
flag.  So, for example, when adjusting PC-relative offsets to account
for things like removed CIEs and FDEs, we use:

   (encoding & 0xf0) == DW_EH_PE_pcrel

even though (AIUI) the adjustment ought to be applied to
DW_EH_PE_pcrel | DW_EH_PE_indirect as well.

The patch goes through elf-eh-frame.c and replaces 0xf0 with 0x70.
This wasn't just mechanical though!  I did try to justify that each
one was correct.  And I think each one is.  However:

	      switch (ent->fde_encoding & 0xf0)
		{
		case DW_EH_PE_indirect:
		case DW_EH_PE_textrel:
		  BFD_ASSERT (hdr_info == NULL);
		  break;
		case DW_EH_PE_datarel:
		  {
		    asection *got = bfd_get_section_by_name (abfd, ".got");

		    BFD_ASSERT (got != NULL);
		    address += got->vma;
		  }
		  break;
		case DW_EH_PE_pcrel:
		  value += (bfd_vma) ent->offset - ent->new_offset;
		  address += (sec->output_section->vma
			      + sec->output_offset
			      + ent->offset + 8);
		  break;
		}

is an interesting case.  It seems to be asserting that we only have
an .eh_frame_hdr (and thus only use "address") in cases where we can
correctly calculate the address of the target code.  That sounds like
a good idea in principle, but as mentioned above, we ought to exclude
all DW_EH_PE_indirect encodings, not just:

  DW_EH_PE_indirect | DW_EH_PE_absptr

Admittedly that's probably only of academic interest, since no-one is
likely to use indirect pointers for the FDE ranges (are they? ;-)).

More importantly, we don't seem to actually enforce the asserted
condition anywhere, so I'm wondering whether we ought to have
something like the second (completely untested) patch as well.

I tested the first patch in combination with the third (gcc) patch
on mips64octeon-linux-gnu.  There were no regressions from unpatched
GCC and binutils.  After the patches, libstdc++.so still has a read-only
.eh_frame, but it is free from text relocations.

Any objections to the first patch?  Any thoughts on the second?
If the first patch is OK, is it too invasive for the branch?
I'd ideally like to get this into 2.20, so that the feature is
in a released binutils when GCC 4.5 comes out.

If the first patch goes in, I'll apply the GCC one too, and then
do a follow-up to check for the correct linker version.  I'll make
-fno-dwarf2-cfi-asm the default when this linker version check fails.
I'll also make -fno-dwarf2-cfi-asm the unconditional default for MIPS
GCC 4.4, as long as Mark or another GCC release manager agress.

Richard


bfd/
	* elf-bfd.h (eh_cie_fde): Add personality_offset and
	make_per_encoding_relative to the CIE structure.  Add a padding field.
	* elf-eh-frame.c (_bfd_elf_eh_frame_section_offset): Use 0x70
	rather than 0xf0 when masking out the base address encoding
	Record the offset of personality data from the start of the CIE.
	Remove a repeated elf_backend_can_make_relative_eh_frame check.
	(find_merged_cie): Take an info argument.  If the personality
	binds locally, try converting an absolute personality into
	a local one.
	(_bfd_elf_discard_section_eh_frame): Use 0x70 rather than 0xf0
	when masking out the base address encoding.  Update the call to
	find_merged_cie.
	(_bfd_elf_eh_frame_section_offset): Discard relocations against
	the personality data if we are converting into PC-relative form.
	(_bfd_elf_write_section_eh_frame): Use 0x70 rather than 0xf0
	when masking out the base address encoding.  Handle
	make_per_encoding_relative.

ld/testsuite/
	* ld-mips-elf/eh-frame5.s, ld-mips-elf/eh-frame5.ld,
	ld-mips-elf/eh-frame5.d: New test.
	* ld-mips-elf/mips-elf.exp: Run it.

Index: bfd/elf-bfd.h
===================================================================
--- bfd/elf-bfd.h	2009-09-13 18:18:04.000000000 +0100
+++ bfd/elf-bfd.h	2009-09-13 18:36:01.000000000 +0100
@@ -305,6 +305,10 @@ struct eh_cie_fde
  	asection *sec;
       } u;
 
+      /* The offset of the personality data from the start of the CIE,
+	 or 0 if the CIE doesn't have any.  */
+      unsigned int personality_offset : 8;
+
       /* True if we have marked relocations associated with this CIE.  */
       unsigned int gc_mark : 1;
 
@@ -312,8 +316,13 @@ struct eh_cie_fde
 	 a PC-relative one.  */
       unsigned int make_lsda_relative : 1;
 
-      /* True if the CIE contains personality data and if that data
-	 uses a PC-relative encoding.  */
+      /* True if we have decided to turn an absolute personality
+	 encoding into a PC-relative one.  */
+      unsigned int make_per_encoding_relative : 1;
+
+      /* True if the CIE contains personality data and if that
+	 data uses a PC-relative encoding.  Always true when
+	 make_per_encoding_relative is.  */
       unsigned int per_encoding_relative : 1;
 
       /* True if we need to add an 'R' (FDE encoding) entry to the
@@ -322,6 +331,9 @@ struct eh_cie_fde
 
       /* True if we have merged this CIE with another.  */
       unsigned int merged : 1;
+
+      /* Unused bits.  */
+      unsigned int pad1 : 18;
     } cie;
   } u;
   unsigned int reloc_index;
Index: bfd/elf-eh-frame.c
===================================================================
--- bfd/elf-eh-frame.c	2009-09-13 18:18:04.000000000 +0100
+++ bfd/elf-eh-frame.c	2009-09-13 18:36:01.000000000 +0100
@@ -675,11 +675,12 @@ #define GET_RELOC(buf)					\
 		      per_width = get_DW_EH_PE_width (cie->per_encoding,
 						      ptr_size);
 		      REQUIRE (per_width);
-		      if ((cie->per_encoding & 0xf0) == DW_EH_PE_aligned)
+		      if ((cie->per_encoding & 0x70) == DW_EH_PE_aligned)
 			{
 			  length = -(buf - ehbuf) & (per_width - 1);
 			  REQUIRE (skip_bytes (&buf, end, length));
 			}
+		      this_inf->u.cie.personality_offset = buf - start;
 		      ENSURE_NO_RELOCS (buf);
 		      /* Ensure we have a reloc here.  */
 		      REQUIRE (GET_RELOC (buf));
@@ -705,27 +706,23 @@ #define GET_RELOC(buf)					\
 		  ->elf_backend_can_make_relative_eh_frame
 		  (abfd, info, sec)))
 	    {
-	      if ((cie->fde_encoding & 0xf0) == DW_EH_PE_absptr)
+	      if ((cie->fde_encoding & 0x70) == DW_EH_PE_absptr)
 		this_inf->make_relative = 1;
 	      /* If the CIE doesn't already have an 'R' entry, it's fairly
 		 easy to add one, provided that there's no aligned data
 		 after the augmentation string.  */
 	      else if (cie->fde_encoding == DW_EH_PE_omit
-		       && (cie->per_encoding & 0xf0) != DW_EH_PE_aligned)
+		       && (cie->per_encoding & 0x70) != DW_EH_PE_aligned)
 		{
 		  if (*cie->augmentation == 0)
 		    this_inf->add_augmentation_size = 1;
 		  this_inf->u.cie.add_fde_encoding = 1;
 		  this_inf->make_relative = 1;
 		}
-	    }
 
-	  if (info->shared
-	      && (get_elf_backend_data (abfd)
-		  ->elf_backend_can_make_lsda_relative_eh_frame
-		  (abfd, info, sec))
-	      && (cie->lsda_encoding & 0xf0) == DW_EH_PE_absptr)
-	    cie->can_make_lsda_relative = 1;
+	      if ((cie->lsda_encoding & 0x70) == DW_EH_PE_absptr)
+		cie->can_make_lsda_relative = 1;
+	    }
 
 	  /* If FDE encoding was not specified, it defaults to
 	     DW_EH_absptr.  */
@@ -843,7 +840,7 @@ #define GET_RELOC(buf)					\
 	  cie->length -= end - insns_end;
 	}
       if (set_loc_count
-	  && ((cie->fde_encoding & 0xf0) == DW_EH_PE_pcrel
+	  && ((cie->fde_encoding & 0x70) == DW_EH_PE_pcrel
 	      || this_inf->make_relative))
 	{
 	  unsigned int cnt;
@@ -963,7 +960,7 @@ _bfd_elf_gc_mark_fdes (struct bfd_link_i
    relocations in REL.  */
 
 static struct eh_cie_fde *
-find_merged_cie (bfd *abfd, asection *sec,
+find_merged_cie (bfd *abfd, struct bfd_link_info *info, asection *sec,
 		 struct eh_frame_hdr_info *hdr_info,
 		 struct elf_reloc_cookie *cookie,
 		 struct eh_cie_fde *cie_inf)
@@ -993,6 +990,8 @@ find_merged_cie (bfd *abfd, asection *se
 
   if (cie->per_encoding != DW_EH_PE_omit)
     {
+      bfd_boolean per_binds_local;
+
       /* Work out the address of personality routine, either as an absolute
 	 value or as a symbol.  */
       rel = cookie->rels + cie->personality.reloc_index;
@@ -1016,6 +1015,7 @@ find_merged_cie (bfd *abfd, asection *se
 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
 	  cie->personality.h = h;
+	  per_binds_local = SYMBOL_REFERENCES_LOCAL (info, h);
 	}
       else
 	{
@@ -1036,6 +1036,17 @@ find_merged_cie (bfd *abfd, asection *se
 	  cie->personality.val = (sym->st_value
 				  + sym_sec->output_offset
 				  + sym_sec->output_section->vma);
+	  per_binds_local = TRUE;
+	}
+
+      if (per_binds_local
+	  && info->shared
+	  && (cie->per_encoding & 0x70) == DW_EH_PE_absptr
+	  && (get_elf_backend_data (abfd)
+	      ->elf_backend_can_make_relative_eh_frame (abfd, info, sec)))
+	{
+	  cie_inf->u.cie.make_per_encoding_relative = 1;
+	  cie_inf->u.cie.per_encoding_relative = 1;
 	}
     }
 
@@ -1110,9 +1121,9 @@ find_merged_cie (bfd *abfd, asection *se
 	if (!(*reloc_symbol_deleted_p) (ent->offset + 8, cookie))
 	  {
 	    if (info->shared
-		&& (((ent->fde_encoding & 0xf0) == DW_EH_PE_absptr
+		&& (((ent->fde_encoding & 0x70) == DW_EH_PE_absptr
 		     && ent->make_relative == 0)
-		    || (ent->fde_encoding & 0xf0) == DW_EH_PE_aligned))
+		    || (ent->fde_encoding & 0x70) == DW_EH_PE_aligned))
 	      {
 		/* If a shared library uses absolute pointers
 		   which we cannot turn into PC relative,
@@ -1125,8 +1136,8 @@ find_merged_cie (bfd *abfd, asection *se
 	      }
 	    ent->removed = 0;
 	    hdr_info->fde_count++;
-	    ent->u.fde.cie_inf = find_merged_cie (abfd, sec, hdr_info, cookie,
-						  ent->u.fde.cie_inf);
+	    ent->u.fde.cie_inf = find_merged_cie (abfd, info, sec, hdr_info,
+						  cookie, ent->u.fde.cie_inf);
 	  }
       }
 
@@ -1276,6 +1287,14 @@ _bfd_elf_eh_frame_section_offset (bfd *o
   if (sec_info->entry[mid].removed)
     return (bfd_vma) -1;
 
+  /* If converting personality pointers to DW_EH_PE_pcrel, there will be
+     no need for run-time relocation against the personality field.  */
+  if (sec_info->entry[mid].cie
+      && sec_info->entry[mid].u.cie.make_per_encoding_relative
+      && offset == (sec_info->entry[mid].offset + 8
+		    + sec_info->entry[mid].u.cie.personality_offset))
+    return (bfd_vma) -2;
+
   /* If converting to DW_EH_PE_pcrel, there will be no need for run-time
      relocation against FDE's initial_location field.  */
   if (!sec_info->entry[mid].cie
@@ -1452,12 +1471,14 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 		    buf++;
 		    break;
 		  case 'P':
+		    if (ent->u.cie.make_per_encoding_relative)
+		      *buf |= DW_EH_PE_pcrel;
 		    per_encoding = *buf++;
 		    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)
 				== ent->u.cie.per_encoding_relative);
-		    if ((per_encoding & 0xf0) == DW_EH_PE_aligned)
+		    if ((per_encoding & 0x70) == DW_EH_PE_aligned)
 		      buf = (contents
 			     + ((buf - contents + per_width - 1)
 				& ~((bfd_size_type) per_width - 1)));
@@ -1467,8 +1488,15 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 
 			val = read_value (abfd, buf, per_width,
 					  get_DW_EH_PE_signed (per_encoding));
-			val += (bfd_vma) ent->offset - ent->new_offset;
-			val -= extra_string + extra_data;
+			if (ent->u.cie.make_per_encoding_relative)
+			  val -= (sec->output_section->vma
+				  + sec->output_offset
+				  + (buf - contents));
+			else
+			  {
+			    val += (bfd_vma) ent->offset - ent->new_offset;
+			    val -= extra_string + extra_data;
+			  }
 			write_value (abfd, buf, val, per_width);
 			action &= ~4;
 		      }
@@ -1511,9 +1539,8 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 	  address = value;
 	  if (value)
 	    {
-	      switch (ent->fde_encoding & 0xf0)
+	      switch (ent->fde_encoding & 0x70)
 		{
-		case DW_EH_PE_indirect:
 		case DW_EH_PE_textrel:
 		  BFD_ASSERT (hdr_info == NULL);
 		  break;
@@ -1550,7 +1577,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 		   + ent->new_offset);
 	    }
 
-	  if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel
+	  if ((ent->lsda_encoding & 0x70) == DW_EH_PE_pcrel
 	      || cie->u.cie.make_lsda_relative)
 	    {
 	      buf += ent->lsda_offset;
@@ -1559,7 +1586,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 				  get_DW_EH_PE_signed (ent->lsda_encoding));
 	      if (value)
 		{
-		  if ((ent->lsda_encoding & 0xf0) == DW_EH_PE_pcrel)
+		  if ((ent->lsda_encoding & 0x70) == DW_EH_PE_pcrel)
 		    value += (bfd_vma) ent->offset - ent->new_offset;
 		  else if (cie->u.cie.make_lsda_relative)
 		    value -= (sec->output_section->vma
@@ -1598,7 +1625,7 @@ _bfd_elf_write_section_eh_frame (bfd *ab
 		  if (!value)
 		    continue;
 
-		  if ((ent->fde_encoding & 0xf0) == DW_EH_PE_pcrel)
+		  if ((ent->fde_encoding & 0x70) == DW_EH_PE_pcrel)
 		    value += (bfd_vma) ent->offset + 8 - new_offset;
 		  if (ent->make_relative)
 		    value -= (sec->output_section->vma
Index: ld/testsuite/ld-mips-elf/eh-frame5.s
===================================================================
--- /dev/null	2009-09-12 23:43:45.501816639 +0100
+++ ld/testsuite/ld-mips-elf/eh-frame5.s	2009-09-13 18:57:26.000000000 +0100
@@ -0,0 +1,107 @@
+	.cfi_startproc
+	.cfi_personality 0x0,local_pers
+	.cfi_lsda 0x0,LSDA
+	.ent	f1
+f1:
+	nop
+	.end	f1
+	.cfi_endproc
+
+	.cfi_startproc
+	.cfi_personality 0x0,hidden_pers
+	.cfi_lsda 0x0,LSDA
+	.ent	f2
+f2:
+	nop
+	.end	f2
+	.cfi_endproc
+
+	.cfi_startproc
+	.cfi_personality 0x0,global_pers
+	.cfi_lsda 0x0,LSDA
+	.ent	f3
+f3:
+	nop
+	.end	f3
+	.cfi_endproc
+
+	.cfi_startproc
+	.cfi_personality 0x0,extern_pers
+	.cfi_lsda 0x0,LSDA
+	.ent	f4
+f4:
+	nop
+	.end	f4
+	.cfi_endproc
+
+	.cfi_startproc
+	.cfi_personality 0x80,local_indirect_ptr
+	.cfi_lsda 0x0,LSDA
+	.ent	f5
+f5:
+	nop
+	.end	f5
+	.cfi_endproc
+
+	.cfi_startproc
+	.cfi_personality 0x80,hidden_indirect_ptr
+	.cfi_lsda 0x0,LSDA
+	.ent	f6
+f6:
+	nop
+	.end	f6
+	.cfi_endproc
+
+	.cfi_startproc
+	.cfi_personality 0x80,global_indirect_ptr
+	.cfi_lsda 0x0,LSDA
+	.ent	f7
+f7:
+	nop
+	.end	f7
+	.cfi_endproc
+
+	.cfi_startproc
+	.cfi_personality 0x80,extern_indirect_ptr
+	.cfi_lsda 0x0,LSDA
+	.ent	f8
+f8:
+	nop
+	.end	f8
+	.cfi_endproc
+
+
+	.ent	local_pers
+local_pers:
+	nop
+	.end	local_pers
+
+	.globl	hidden_pers
+	.hidden	hidden_pers
+	.ent	hidden_pers
+hidden_pers:
+	nop
+	.end	hidden_pers
+
+	.globl	global_pers
+	.ent	global_pers
+global_pers:
+	nop
+	.end	global_pers
+
+	.section .data,"aw",@progbits
+
+local_indirect_ptr:
+	.4byte	pers1
+
+	.globl hidden_indirect_ptr
+	.hidden hidden_indirect_ptr
+hidden_indirect_ptr:
+	.4byte	pers2
+
+	.globl global_indirect_ptr
+global_indirect_ptr:
+	.4byte	pers3
+
+LSDA:
+	.4byte	0
Index: ld/testsuite/ld-mips-elf/eh-frame5.ld
===================================================================
--- /dev/null	2009-09-12 23:43:45.501816639 +0100
+++ ld/testsuite/ld-mips-elf/eh-frame5.ld	2009-09-13 18:56:54.000000000 +0100
@@ -0,0 +1,18 @@
+SECTIONS
+{
+  . = 0;
+  .reginfo : { *(.reginfo) }
+  .dynamic : { *(.dynamic) }
+  .dynsym : { *(.dynsym) }
+  .dynstr : { *(.dynstr) }
+  .rel.dyn : { *(.rel.dyn) }
+  . = 0x800;
+  .text : { *(.text) }
+  . = 0xc00;
+  .eh_frame : { *(.eh_frame) }
+  . = 0x10000;
+  .data : { *(.data) }
+  . = 0x10400;
+  _gp = . + 0x7ff0;
+  .got : { *(.got) }
+}
Index: ld/testsuite/ld-mips-elf/eh-frame5.d
===================================================================
--- /dev/null	2009-09-12 23:43:45.501816639 +0100
+++ ld/testsuite/ld-mips-elf/eh-frame5.d	2009-09-13 19:25:38.000000000 +0100
@@ -0,0 +1,278 @@
+
+Relocation section '.rel.dyn' at offset 0x101f0 contains 8 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+00000000  .* R_MIPS_NONE *
+#
+# The order of the relocations doesn't really matter, but they must
+# be some permutation of the list below.
+#
+00010008  .* R_MIPS_REL32      00000000   pers3
+00000c7b  .* R_MIPS_REL32      00000828   global_pers
+00000d7f  .* R_MIPS_REL32      00000000   extern_indirect_ptr
+00010000  .* R_MIPS_REL32      00000000   pers1
+00010004  .* R_MIPS_REL32      00000000   pers2
+00000caf  .* R_MIPS_REL32      00000000   extern_pers
+00000d4b  .* R_MIPS_REL32      00010008   global_indirect_ptr
+Contents of the \.eh_frame section:
+
+# Text addresses
+# --------------
+# f1 = 0x800
+# f2 = 0x804
+# f3 = 0x808
+# f4 = 0x80c
+# f5 = 0x810
+# f6 = 0x814
+# f7 = 0x818
+# f8 = 0x81c
+# local_pers = 0x820
+# hidden_pers = 0x824
+# global_pers = 0x828
+
+# Data addresses
+# --------------
+# local_indirect_ptr = 0x10000
+# hidden_indirect_ptr = 0x10004
+# global_indirect_ptr = 0x10008
+# LSDA = 0x1000c
+
+#-------------------------------------------------------------------------
+# f1
+#-------------------------------------------------------------------------
+00000000 00000018 00000000 CIE
+  Version:               1
+  Augmentation:          "zPLR"
+  Code alignment factor: 1
+  Data alignment factor: -4
+  Return address column: 31
+#
+# 0xc12: DW_EH_PE_pcrel for personality encoding
+# 0xc13: 0x820 - 0xc13 (local_pers - .)
+# 0xc17: DW_EH_PE_pcrel for LDSA encoding
+# 0xc18: DW_EH_PE_pcrel | DW_EH_PE_sdata4 for FDE encoding
+#
+  Augmentation data:     10 ff ff fc 0d 10 1b
+
+  DW_CFA_def_cfa_register: r29
+  DW_CFA_nop
+
+0000001c 00000014 00000020 FDE cie=00000000 pc=00000800..00000804
+#
+# 0xc2d: 0x1000c - 0xc2d (LDSA - .)
+#
+  Augmentation data:     00 00 f3 df
+
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+#-------------------------------------------------------------------------
+# f2
+#-------------------------------------------------------------------------
+00000034 00000018 00000000 CIE
+  Version:               1
+  Augmentation:          "zPLR"
+  Code alignment factor: 1
+  Data alignment factor: -4
+  Return address column: 31
+#
+# 0xc46: DW_EH_PE_pcrel for personality encoding
+# 0xc47: 0x824 - 0xc47 (hidden_pers - .)
+# 0xc4d: DW_EH_PE_pcrel for LDSA encoding
+# 0xc4e: DW_EH_PE_pcrel | DW_EH_PE_sdata4 for FDE encoding
+#
+  Augmentation data:     10 ff ff fb dd 10 1b
+
+  DW_CFA_def_cfa_register: r29
+  DW_CFA_nop
+
+00000050 00000014 00000020 FDE cie=00000034 pc=00000804..00000808
+#
+# 0xc61: 0x1000c - 0xc61 (LDSA - .)
+#
+  Augmentation data:     00 00 f3 ab
+
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+#-------------------------------------------------------------------------
+# f3
+#-------------------------------------------------------------------------
+00000068 00000018 00000000 CIE
+  Version:               1
+  Augmentation:          "zPLR"
+  Code alignment factor: 1
+  Data alignment factor: -4
+  Return address column: 31
+#
+# 0xc7a: DW_EH_PE_absptr for personality encoding
+# 0xc7b: global_pers (reloc above)
+# 0xc7f: DW_EH_PE_pcrel for LDSA encoding
+# 0xc80: DW_EH_PE_pcrel | DW_EH_PE_sdata4 for FDE encoding
+#
+  Augmentation data:     00 00 00 00 00 10 1b
+
+  DW_CFA_def_cfa_register: r29
+  DW_CFA_nop
+
+00000084 00000014 00000020 FDE cie=00000068 pc=00000808..0000080c
+#
+# 0xc95: 0x1000c - 0xc95 (LDSA - .)
+#
+  Augmentation data:     00 00 f3 77
+
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+#-------------------------------------------------------------------------
+# f4
+#-------------------------------------------------------------------------
+0000009c 00000018 00000000 CIE
+  Version:               1
+  Augmentation:          "zPLR"
+  Code alignment factor: 1
+  Data alignment factor: -4
+  Return address column: 31
+#
+# 0xcae: DW_EH_PE_absptr for personality encoding
+# 0xcaf: extern_pers (reloc above)
+# 0xcb3: DW_EH_PE_pcrel for LDSA encoding
+# 0xcb4: DW_EH_PE_pcrel | DW_EH_PE_sdata4 for FDE encoding
+#
+  Augmentation data:     00 00 00 00 00 10 1b
+
+  DW_CFA_def_cfa_register: r29
+  DW_CFA_nop
+
+000000b8 00000014 00000020 FDE cie=0000009c pc=0000080c..00000810
+#
+# 0xcc9: 0x1000c - 0xcc9 (LDSA - .)
+#
+  Augmentation data:     00 00 f3 43
+
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+#-------------------------------------------------------------------------
+# f5
+#-------------------------------------------------------------------------
+000000d0 00000018 00000000 CIE
+  Version:               1
+  Augmentation:          "zPLR"
+  Code alignment factor: 1
+  Data alignment factor: -4
+  Return address column: 31
+#
+# 0xce2: DW_EH_PE_indirect | DW_EH_PE_pcrel for personality encoding
+# 0xce3: 0x10000 - 0xce3 (local_indirect_ptr - .)
+# 0xce7: DW_EH_PE_pcrel for LDSA encoding
+# 0xce8: DW_EH_PE_pcrel | DW_EH_PE_sdata4 for FDE encoding
+#
+  Augmentation data:     90 00 00 f3 1d 10 1b
+
+  DW_CFA_def_cfa_register: r29
+  DW_CFA_nop
+
+000000ec 00000014 00000020 FDE cie=000000d0 pc=00000810..00000814
+#
+# 0xcfd: 0x1000c - 0xcfd (LDSA - .)
+#
+  Augmentation data:     00 00 f3 0f
+
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+#-------------------------------------------------------------------------
+# f6
+#-------------------------------------------------------------------------
+00000104 00000018 00000000 CIE
+  Version:               1
+  Augmentation:          "zPLR"
+  Code alignment factor: 1
+  Data alignment factor: -4
+  Return address column: 31
+#
+# 0xd16: DW_EH_PE_pcrel for personality encoding
+# 0xd17: 0x10004 - 0xd17 (hidden_indirect_ptr - .)
+# 0xd1d: DW_EH_PE_pcrel for LDSA encoding
+# 0xd1e: DW_EH_PE_pcrel | DW_EH_PE_sdata4 for FDE encoding
+#
+  Augmentation data:     90 00 00 f2 ed 10 1b
+
+  DW_CFA_def_cfa_register: r29
+  DW_CFA_nop
+
+00000120 00000014 00000020 FDE cie=00000104 pc=00000814..00000818
+#
+# 0xd31: 0x1000c - 0xd31 (LDSA - .)
+#
+  Augmentation data:     00 00 f2 db
+
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+#-------------------------------------------------------------------------
+# f7
+#-------------------------------------------------------------------------
+00000138 00000018 00000000 CIE
+  Version:               1
+  Augmentation:          "zPLR"
+  Code alignment factor: 1
+  Data alignment factor: -4
+  Return address column: 31
+#
+# 0xd4a: DW_EH_PE_indirect | DW_EH_PE_absptr for personality encoding
+# 0xd4b: global_indirect_ptr (reloc above)
+# 0xd4f: DW_EH_PE_pcrel for LDSA encoding
+# 0xd50: DW_EH_PE_pcrel | DW_EH_PE_sdata4 for FDE encoding
+#
+  Augmentation data:     80 00 00 00 00 10 1b
+
+  DW_CFA_def_cfa_register: r29
+  DW_CFA_nop
+
+00000154 00000014 00000020 FDE cie=00000138 pc=00000818..0000081c
+#
+# 0xd65: 0x1000c - 0xd65 (LDSA - .)
+#
+  Augmentation data:     00 00 f2 a7
+
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+#-------------------------------------------------------------------------
+# f8
+#-------------------------------------------------------------------------
+0000016c 00000018 00000000 CIE
+  Version:               1
+  Augmentation:          "zPLR"
+  Code alignment factor: 1
+  Data alignment factor: -4
+  Return address column: 31
+#
+# 0xd7e: DW_EH_PE_indirect | DW_EH_PE_absptr for personality encoding
+# 0xd7f: extern_indirect_ptr (reloc above)
+# 0xd83: DW_EH_PE_pcrel for LDSA encoding
+# 0xd84: DW_EH_PE_pcrel | DW_EH_PE_sdata4 for FDE encoding
+#
+  Augmentation data:     80 00 00 00 00 10 1b
+
+  DW_CFA_def_cfa_register: r29
+  DW_CFA_nop
+
+00000188 00000014 00000020 FDE cie=0000016c pc=0000081c..00000820
+#
+# 0xd99: 0x1000c - 0xd99 (LDSA - .)
+#
+  Augmentation data:     00 00 f2 73
+
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
Index: ld/testsuite/ld-mips-elf/mips-elf.exp
===================================================================
--- ld/testsuite/ld-mips-elf/mips-elf.exp	2009-09-13 19:21:55.000000000 +0100
+++ ld/testsuite/ld-mips-elf/mips-elf.exp	2009-09-13 19:34:36.000000000 +0100
@@ -304,6 +304,17 @@ if {$embedded_elf} {
     run_dump_test "eh-frame3"
     run_dump_test "eh-frame4"
 }
+if {$linux_gnu} {
+    set eh_frame5_test {
+	{"MIPS eh-frame 5"
+	 "-melf32btsmip -shared -Teh-frame5.ld"
+	 "-32 -EB"
+	 {eh-frame5.s}
+	 {{readelf {--relocs -wf} eh-frame5.d}}
+	 "eh-frame5.so"}
+    }
+    run_ld_link_tests $eh_frame5_test
+}
 
 run_dump_test "jaloverflow"
 run_dump_test "jaloverflow-2"
bfd/
	* elf-eh-frame.c (can_identify_fde_code_p): New function.
	(_bfd_elf_discard_section_eh_frame): Use it.

Index: bfd/elf-eh-frame.c
===================================================================
--- bfd/elf-eh-frame.c	2009-09-13 20:19:46.000000000 +0100
+++ bfd/elf-eh-frame.c	2009-09-13 20:28:12.000000000 +0100
@@ -1086,6 +1086,30 @@ find_merged_cie (bfd *abfd, struct bfd_l
   return new_cie->cie_inf;
 }
 
+/* Return true if ENT's FDE encoding allows us to identify the target
+   code at link time.  */
+
+static bfd_boolean
+can_identify_fde_code_p (struct bfd_link_info *info, struct eh_cie_fde *ent)
+{
+  if ((ent->fde_encoding & DW_EH_PE_indirect) != 0)
+    return FALSE;
+
+  switch (ent->fde_encoding & 0x70)
+    {
+    case DW_EH_PE_aligned:
+    case DW_EH_PE_absptr:
+      return !info->shared || ent->make_relative;
+
+    case DW_EH_PE_pcrel:
+    case DW_EH_PE_datarel:
+      return TRUE;
+
+    default:
+      return FALSE;
+    }
+}
+
 /* This function is called for each input file before the .eh_frame
    section is relocated.  It discards duplicate CIEs and FDEs for discarded
    functions.  The function returns TRUE iff any entries have been
@@ -1120,10 +1144,7 @@ find_merged_cie (bfd *abfd, struct bfd_l
 		    && cookie->rel->r_offset == ent->offset + 8);
 	if (!(*reloc_symbol_deleted_p) (ent->offset + 8, cookie))
 	  {
-	    if (info->shared
-		&& (((ent->fde_encoding & 0x70) == DW_EH_PE_absptr
-		     && ent->make_relative == 0)
-		    || (ent->fde_encoding & 0x70) == DW_EH_PE_aligned))
+	    if (!can_identify_fde_code_p (info, ent))
 	      {
 		/* If a shared library uses absolute pointers
 		   which we cannot turn into PC relative,
gcc/
	* config/mips/mips.h (ASM_PREFERRED_EH_DATA_FORMAT): Use indirect
	pointers for global data on true PIC targets.

Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	2009-09-13 02:51:11.000000000 +0100
+++ gcc/config/mips/mips.h	2009-09-13 02:51:11.000000000 +0100
@@ -3174,3 +3174,10 @@ #define FINAL_PRESCAN_INSN(INSN, OPVEC, 
 /* This is necessary to avoid a warning about comparing different enum
    types.  */
 #define mips_tune_attr ((enum attr_cpu) mips_tune)
+
+/* Use indirect pointers for global data so that the .eh_frame section
+   can be read-only.  The linker will turn absolute relocations into
+   relative ones.  */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+  (((GLOBAL) && flag_pic && !TARGET_ABSOLUTE_ABICALLS ? DW_EH_PE_indirect : 0) \
+   | DW_EH_PE_absptr)
Index: gcc/dwarf2asm.c
===================================================================
--- gcc/dwarf2asm.c	2009-09-13 08:13:55.000000000 +0100
+++ gcc/dwarf2asm.c	2009-09-13 08:13:58.000000000 +0100
@@ -446,6 +446,8 @@ #define S(p, v)		case p: return v;
   S(DW_EH_PE_sdata4 | DW_EH_PE_funcrel, "funcrel sdata4")
   S(DW_EH_PE_sdata8 | DW_EH_PE_funcrel, "funcrel sdata8")
 
+  S(DW_EH_PE_indirect | DW_EH_PE_absptr, "indirect absolute")
+
   S(DW_EH_PE_indirect | DW_EH_PE_absptr | DW_EH_PE_pcrel,
     "indirect pcrel")
   S(DW_EH_PE_indirect | DW_EH_PE_uleb128 | DW_EH_PE_pcrel,

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