diff options
-rw-r--r-- | bfd/ChangeLog | 25 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 24 | ||||
-rw-r--r-- | bfd/elf-eh-frame.c | 42 | ||||
-rw-r--r-- | bfd/elf32-frv.c | 58 | ||||
-rw-r--r-- | bfd/elfxx-target.h | 12 |
5 files changed, 158 insertions, 3 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 113dc22..249f266 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,30 @@ 2004-02-27 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. + +2004-02-27 Alexandre Oliva <aoliva@redhat.com> + * elf32-frv.c (elf32_frv_howto_table) <R_FRV_LABEL16>: Set complain_on_overflow to signed. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 6bbacad..3e861ea 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -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) @@ -1301,6 +1319,12 @@ extern void _bfd_elf_sprintf_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 *); extern bfd_vma _bfd_elf_rela_local_sym diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c index 28e0b55..d3777b4 100644 --- a/bfd/elf-eh-frame.c +++ b/bfd/elf-eh-frame.c @@ -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 *abfd, struct bfd_link_info *info) 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 *abfd, struct bfd_link_info *info) 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 *abfd, struct bfd_link_info *info) 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; @@ -1181,3 +1191,29 @@ _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info) 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; +} diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c index 78a4a4c..a813ddc 100644 --- a/bfd/elf32-frv.c +++ b/bfd/elf32-frv.c @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "libbfd.h" #include "elf-bfd.h" #include "elf/frv.h" +#include "elf/dwarf2.h" #include "hashtab.h" /* Forward declarations. */ @@ -3700,6 +3701,57 @@ elf32_frv_finish_dynamic_symbol (bfd *output_bfd ATTRIBUTE_UNUSED, 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 @@ -4419,6 +4471,12 @@ frv_elf_print_private_bfd_data (abfd, ptr) #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 /* We use REL for dynamic relocations only. */ diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h index ca0e47b..5bf8f4d 100644 --- a/bfd/elfxx-target.h +++ b/bfd/elfxx-target.h @@ -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 elfNN_bed = 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, |