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]

FR-V FDPIC ABI: new EH frame BFD hooks


Some time ago, when I posted the bulk of the FR-V FDPIC ABI supporting
code, I alluded to the need for additional work to get EH to work
properly, because of the impossibility to use PC-relative relocations
to reference symbols in other segments (remember they may be relocated
by different amounts).

Back then, I'd written an uglier version of this patch that I intended
to rewrite into something nicer, that would let the back-end decide
whether/how to re-encode addresses that might be suitable for
re-encoding.  Unfortunately, since the encoding has to be the same for
all FDEs in a CIE and I couldn't think of any nice way to enable the
back-end to be communicated of such semi-global needs, I gave up and
retained the new hooks that decide whether we can decay encodings
within FDEs to PC-relative, instead of using the other hook added to
enable the back-end to decide the encoding to be given to reference
.eh_frame from .eh_frame_hdr.

Ideally, we'd like to use GOTOFF32 or PC32 relocs for symbols in the
data segment, GPREL32 for those in the text segment (although it would
be quite tricky to find _gp for a given module within
dl_iterate_phdr), and absolute encodings for symbols whose locations
are not known, that ideally decay to either of them in the linker.
Unfortunately, we don't have GOTOFF32 or PC32 relocs available in
FR-V, so the compiler has to use absolute encodings all over, and the
linker can't decay them to PC-relative.  ==> Lots of dynamic
relocations ;-(

Suggestions on how to improve the code to make encodings relative to
_G_O_T_ or PC would be definitely welcome.

Anyway, this patch at least gets things to work.  Tested on
i686-pc-linux-gnu x frv-uclinux.  Ok to install?

Index: bfd/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* elf-bfd.h (struct elf_backend_data): Added
	elf_backend_can_make_relative_eh_frame,
	elf_backend_can_make_lsda_relative_eh_frame and
	elf_backend_encode_eh_address.
	(_bfd_elf_encode_eh_address): Declare.
	(_bfd_elf_can_make_relative): Declare.
	* elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Use new
	hooks to decide whether to attempt to make_relative and
	make_lsda_relative.
	(_bfd_elf_write_section_eh_frame_hdr): Call encode_eh_address.
	(_bfd_elf_can_make_relative): New.
	(_bfd_elf_encode_eh_address): New.
	* elf32-frv.c (frv_elf_use_relative_eh_frame): New.
	(frv_elf_encode_eh_address): New.
	(elf_backend_can_make_relative_eh_frame): Define.
	(elf_backend_can_make_lsda_relative_eh_frame): Define.
	(elf_backend_encode_eh_address): Define.
	* elfxx-target.h
	(elf_backend_can_make_relative_eh_frame): Define.
	(elf_backend_can_make_lsda_relative_eh_frame): Define.
	(elf_backend_encode_eh_address): Define.
	(elfNN_bed): Add them.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.125
diff -u -p -r1.125 elf-bfd.h
--- bfd/elf-bfd.h 9 Feb 2004 08:04:00 -0000 1.125
+++ bfd/elf-bfd.h 10 Feb 2004 06:05:15 -0000
@@ -860,6 +860,24 @@ struct elf_backend_data
   bfd_boolean (*elf_backend_ignore_discarded_relocs)
     (asection *);
 
+  /* These functions tell elf-eh-frame whether to attempt to turn
+     absolute or lsda encodings into pc-relative ones.  The default
+     definition enables these transformations.  */
+  bfd_boolean (*elf_backend_can_make_relative_eh_frame)
+     (bfd *, struct bfd_link_info *, asection *);
+  bfd_boolean (*elf_backend_can_make_lsda_relative_eh_frame)
+     (bfd *, struct bfd_link_info *, asection *);
+
+  /* This function returns an encoding after computing the encoded
+     value (and storing it in ENCODED) for the given OFFSET into OSEC,
+     to be stored in at LOC_OFFSET into the LOC_SEC input section.
+     The default definition chooses a 32-bit PC-relative encoding.  */
+  bfd_byte (*elf_backend_encode_eh_address)
+     (bfd *abfd, struct bfd_link_info *info,
+      asection *osec, bfd_vma offset,
+      asection *loc_sec, bfd_vma loc_offset,
+      bfd_vma *encoded);
+
   /* This function, if defined, may write out the given section.
      Returns TRUE if it did so and FALSE if the caller should.  */
   bfd_boolean (*elf_backend_write_section)
@@ -1300,6 +1318,12 @@ extern void _bfd_elf_sprintf_vma
   (bfd *, char *, bfd_vma);
 extern void _bfd_elf_fprintf_vma
   (bfd *, void *, bfd_vma);
+
+extern bfd_byte _bfd_elf_encode_eh_address
+  (bfd *abfd, struct bfd_link_info *info, asection *osec, bfd_vma offset,
+   asection *loc_sec, bfd_vma loc_offset, bfd_vma *encoded);
+extern bfd_boolean _bfd_elf_can_make_relative
+  (bfd *input_bfd, struct bfd_link_info *info, asection *eh_frame_section);
 
 extern enum elf_reloc_type_class _bfd_elf_reloc_type_class
   (const Elf_Internal_Rela *);
Index: bfd/elf-eh-frame.c
===================================================================
RCS file: /cvs/src/src/bfd/elf-eh-frame.c,v
retrieving revision 1.27
diff -u -p -r1.27 elf-eh-frame.c
--- bfd/elf-eh-frame.c 16 Oct 2003 21:04:04 -0000 1.27
+++ bfd/elf-eh-frame.c 10 Feb 2004 06:05:16 -0000
@@ -518,10 +518,16 @@ _bfd_elf_discard_section_eh_frame
 	  /* For shared libraries, try to get rid of as many RELATIVE relocs
 	     as possible.  */
           if (info->shared
+	      && (get_elf_backend_data (abfd)
+		  ->elf_backend_can_make_relative_eh_frame
+		  (abfd, info, sec))
 	      && (cie.fde_encoding & 0xf0) == DW_EH_PE_absptr)
 	    cie.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.make_lsda_relative = 1;
 
@@ -1120,6 +1126,7 @@ _bfd_elf_write_section_eh_frame_hdr (bfd
   asection *eh_frame_sec;
   bfd_size_type size;
   bfd_boolean retval;
+  bfd_vma encoded_eh_frame;
 
   htab = elf_hash_table (info);
   hdr_info = &htab->eh_info;
@@ -1143,7 +1150,10 @@ _bfd_elf_write_section_eh_frame_hdr (bfd
 
   memset (contents, 0, EH_FRAME_HDR_SIZE);
   contents[0] = 1;				/* Version.  */
-  contents[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; /* .eh_frame offset.  */
+  contents[1] = get_elf_backend_data (abfd)->elf_backend_encode_eh_address
+    (abfd, info, eh_frame_sec, 0, sec, 4,
+     &encoded_eh_frame);			/* .eh_frame offset.  */
+
   if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
     {
       contents[2] = DW_EH_PE_udata4;		/* FDE count encoding.  */
@@ -1154,8 +1164,8 @@ _bfd_elf_write_section_eh_frame_hdr (bfd
       contents[2] = DW_EH_PE_omit;
       contents[3] = DW_EH_PE_omit;
     }
-  bfd_put_32 (abfd, eh_frame_sec->vma - sec->output_section->vma - 4,
-	      contents + 4);
+  bfd_put_32 (abfd, encoded_eh_frame, contents + 4);
+
   if (contents[2] != DW_EH_PE_omit)
     {
       unsigned int i;
@@ -1180,4 +1190,30 @@ _bfd_elf_write_section_eh_frame_hdr (bfd
 				     sec->_cooked_size);
   free (contents);
   return retval;
+}
+
+/* Decide whether we can use a PC-relative encoding within the given
+   EH frame section.  This is the default implementation.  */
+
+bfd_boolean
+_bfd_elf_can_make_relative (bfd *input_bfd ATTRIBUTE_UNUSED,
+			    struct bfd_link_info *info ATTRIBUTE_UNUSED,
+			    asection *eh_frame_section ATTRIBUTE_UNUSED)
+{
+  return TRUE;
+}
+
+/* Select an encoding for the given address.  Preference is given to
+   PC-relative addressing modes.  */
+
+bfd_byte
+_bfd_elf_encode_eh_address (bfd *abfd ATTRIBUTE_UNUSED,
+			    struct bfd_link_info *info ATTRIBUTE_UNUSED,
+			    asection *osec, bfd_vma offset,
+			    asection *loc_sec, bfd_vma loc_offset,
+			    bfd_vma *encoded)
+{
+  *encoded = osec->vma + offset -
+    (loc_sec->output_section->vma + loc_sec->output_offset + loc_offset);
+  return DW_EH_PE_pcrel | DW_EH_PE_sdata4;
 }
Index: bfd/elf32-frv.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-frv.c,v
retrieving revision 1.12
diff -u -p -r1.12 elf32-frv.c
--- bfd/elf32-frv.c 30 Jan 2004 21:11:37 -0000 1.12
+++ bfd/elf32-frv.c 10 Feb 2004 06:05:18 -0000
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suit
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/frv.h"
+#include "elf/dwarf2.h"
 #include "hashtab.h"
 
 /* Forward declarations.  */
@@ -3672,6 +3673,57 @@ elf32_frv_finish_dynamic_symbol (bfd *ou
   return TRUE;
 }
 
+/* Decide whether to attempt to turn absptr or lsda encodings in
+   shared libraries into pcrel within the given input section.  */
+
+static bfd_boolean
+frv_elf_use_relative_eh_frame (bfd *input_bfd,
+			       struct bfd_link_info *info ATTRIBUTE_UNUSED,
+			       asection *eh_frame_section ATTRIBUTE_UNUSED)
+{
+  /* We can't use PC-relative encodings in FDPIC binaries, in general.  */
+  if (elf_elfheader (input_bfd)->e_flags & EF_FRV_FDPIC)
+    return FALSE;
+
+  return TRUE;
+}
+
+/* Adjust the contents of an eh_frame_hdr section before they're output.  */
+
+static bfd_byte
+frv_elf_encode_eh_address (bfd *abfd,
+			   struct bfd_link_info *info,
+			   asection *osec, bfd_vma offset,
+			   asection *loc_sec, bfd_vma loc_offset,
+			   bfd_vma *encoded)
+{
+  struct elf_link_hash_entry *h;
+
+  /* Non-FDPIC binaries can use PC-relative encodings.  */
+  if (! (elf_elfheader (abfd)->e_flags & EF_FRV_FDPIC))
+    return _bfd_elf_encode_eh_address (abfd, info, osec, offset,
+				       loc_sec, loc_offset, encoded);
+
+  h = elf_hash_table (info)->hgot;
+  BFD_ASSERT (h && h->root.type == bfd_link_hash_defined);
+
+  if (! h || (_frv_osec_to_segment (abfd, osec)
+	      == _frv_osec_to_segment (abfd, loc_sec->output_section)))
+    return _bfd_elf_encode_eh_address (abfd, info, osec, offset,
+				       loc_sec, loc_offset, encoded);
+
+  BFD_ASSERT (_frv_osec_to_segment (abfd, osec)
+	      == _frv_osec_to_segment (abfd,
+				       h->root.u.def.section->output_section));
+
+  *encoded = osec->vma + offset
+    - (h->root.u.def.value
+       + h->root.u.def.section->output_section->vma
+       + h->root.u.def.section->output_offset);
+
+  return DW_EH_PE_datarel | DW_EH_PE_sdata4;
+}
+
 /* Look through the relocs for a section during the first phase.
 
    Besides handling virtual table relocs for gc, we have to deal with
@@ -4390,6 +4442,12 @@ frv_elf_print_private_bfd_data (abfd, pt
 #define elf_backend_plt_readonly	1
 #define elf_backend_want_plt_sym	0
 #define elf_backend_plt_header_size	0
+
+#define elf_backend_can_make_relative_eh_frame \
+		frv_elf_use_relative_eh_frame
+#define elf_backend_can_make_lsda_relative_eh_frame \
+		frv_elf_use_relative_eh_frame
+#define elf_backend_encode_eh_address	frv_elf_encode_eh_address
 
 #define elf_backend_may_use_rel_p       1
 #define elf_backend_may_use_rela_p      1
Index: bfd/elfxx-target.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-target.h,v
retrieving revision 1.59
diff -u -p -r1.59 elfxx-target.h
--- bfd/elfxx-target.h 9 Feb 2004 08:04:00 -0000 1.59
+++ bfd/elfxx-target.h 10 Feb 2004 06:05:19 -0000
@@ -391,6 +391,15 @@
 #ifndef elf_backend_ignore_discarded_relocs
 #define elf_backend_ignore_discarded_relocs	NULL
 #endif
+#ifndef elf_backend_can_make_relative_eh_frame
+#define elf_backend_can_make_relative_eh_frame	_bfd_elf_can_make_relative
+#endif
+#ifndef elf_backend_can_make_lsda_relative_eh_frame
+#define elf_backend_can_make_lsda_relative_eh_frame	_bfd_elf_can_make_relative
+#endif
+#ifndef elf_backend_encode_eh_address
+#define elf_backend_encode_eh_address		_bfd_elf_encode_eh_address
+#endif
 #ifndef elf_backend_write_section
 #define elf_backend_write_section		NULL
 #endif
@@ -497,6 +506,9 @@ static const struct elf_backend_data elf
   elf_backend_reloc_type_class,
   elf_backend_discard_info,
   elf_backend_ignore_discarded_relocs,
+  elf_backend_can_make_relative_eh_frame,
+  elf_backend_can_make_lsda_relative_eh_frame,
+  elf_backend_encode_eh_address,
   elf_backend_write_section,
   elf_backend_mips_irix_compat,
   elf_backend_mips_rtype_to_howto,
-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Happy GNU Year!                     oliva@{lsd.ic.unicamp.br, gnu.org}
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist                Professional serial bug killer

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