aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2005-01-31 20:39:11 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2005-01-31 20:39:11 +0000
commit8c946ed5d5af555d95f39630fcb56bfc6b0ce93b (patch)
tree65cab0a41c020d51a982aef8b506199ec171ea51 /bfd
parent89fac5e3c33745a93c9b90538048505d46ca365c (diff)
downloadgdb-8c946ed5d5af555d95f39630fcb56bfc6b0ce93b.zip
gdb-8c946ed5d5af555d95f39630fcb56bfc6b0ce93b.tar.gz
gdb-8c946ed5d5af555d95f39630fcb56bfc6b0ce93b.tar.bz2
* elf-bfd.h (elf_backend_data): Add elf_backend_eh_frame_address_size.
(_bfd_elf_eh_frame_address_size): Declare. * elfxx-target.h (elf_backend_eh_frame_address_size): Define a default. (elfNN_bed): Initialize elf_backend_eh_frame_address_size. * elfxx-mips.h (_bfd_mips_elf_eh_frame_address_size): Declare. (elf_backend_eh_frame_address_size): Define. * elfxx-mips.c (_bfd_mips_elf_eh_frame_address_size): New function. * elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Get the address size from the new backend hook. (_bfd_elf_write_section_eh_frame): Likewise. (_bfd_elf_eh_frame_address_size): New function.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog14
-rw-r--r--bfd/elf-bfd.h8
-rw-r--r--bfd/elf-eh-frame.c22
-rw-r--r--bfd/elfxx-mips.c66
-rw-r--r--bfd/elfxx-mips.h3
-rw-r--r--bfd/elfxx-target.h4
6 files changed, 112 insertions, 5 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index b0f0666..c76d939 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,17 @@
+2005-01-31 Richard Sandiford <rsandifo@redhat.com>
+
+ * elf-bfd.h (elf_backend_data): Add elf_backend_eh_frame_address_size.
+ (_bfd_elf_eh_frame_address_size): Declare.
+ * elfxx-target.h (elf_backend_eh_frame_address_size): Define a default.
+ (elfNN_bed): Initialize elf_backend_eh_frame_address_size.
+ * elfxx-mips.h (_bfd_mips_elf_eh_frame_address_size): Declare.
+ (elf_backend_eh_frame_address_size): Define.
+ * elfxx-mips.c (_bfd_mips_elf_eh_frame_address_size): New function.
+ * elf-eh-frame.c (_bfd_elf_discard_section_eh_frame): Get the address
+ size from the new backend hook.
+ (_bfd_elf_write_section_eh_frame): Likewise.
+ (_bfd_elf_eh_frame_address_size): New function.
+
2005-01-31 Andrew Cagney <cagney@gnu.org>
* configure: Regenerate to track ../gettext.m4.
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 6645c9a..f2a063b 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -906,6 +906,12 @@ struct elf_backend_data
bfd_boolean (*elf_backend_ignore_discarded_relocs)
(asection *);
+ /* This function returns the width of FDE pointers in bytes, or 0 if
+ that can't be determined for some reason. The default definition
+ goes by the bfd's EI_CLASS. */
+ unsigned int (*elf_backend_eh_frame_address_size)
+ (bfd *, 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. */
@@ -1381,6 +1387,8 @@ extern void _bfd_elf_sprintf_vma
extern void _bfd_elf_fprintf_vma
(bfd *, void *, bfd_vma);
+extern unsigned int _bfd_elf_eh_frame_address_size
+ (bfd *, asection *);
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);
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index ab316ad..389f6f3 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -418,8 +418,10 @@ _bfd_elf_discard_section_eh_frame
it (it would need to use 64-bit .eh_frame format anyway). */
REQUIRE (sec->size == (unsigned int) sec->size);
- ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]
- == ELFCLASS64) ? 8 : 4;
+ ptr_size = (get_elf_backend_data (abfd)
+ ->elf_backend_eh_frame_address_size (abfd, sec));
+ REQUIRE (ptr_size != 0);
+
buf = ehbuf;
last_cie = NULL;
last_cie_inf = NULL;
@@ -987,12 +989,14 @@ _bfd_elf_write_section_eh_frame (bfd *abfd,
unsigned int ptr_size;
struct eh_cie_fde *ent;
- ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS]
- == ELFCLASS64) ? 8 : 4;
-
if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME)
return bfd_set_section_contents (abfd, sec->output_section, contents,
sec->output_offset, sec->size);
+
+ ptr_size = (get_elf_backend_data (abfd)
+ ->elf_backend_eh_frame_address_size (abfd, sec));
+ BFD_ASSERT (ptr_size != 0);
+
sec_info = elf_section_data (sec)->sec_info;
htab = elf_hash_table (info);
hdr_info = &htab->eh_info;
@@ -1407,6 +1411,14 @@ _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
return retval;
}
+/* Return the width of FDE addresses. This is the default implementation. */
+
+unsigned int
+_bfd_elf_eh_frame_address_size (bfd *abfd, asection *sec ATTRIBUTE_UNUSED)
+{
+ return elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64 ? 8 : 4;
+}
+
/* Decide whether we can use a PC-relative encoding within the given
EH frame section. This is the default implementation. */
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 9ec9c86..595c9df 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -4248,6 +4248,72 @@ _bfd_mips_elf_symbol_processing (bfd *abfd, asymbol *asym)
}
}
+/* Implement elf_backend_eh_frame_address_size. This differs from
+ the default in the way it handles EABI64.
+
+ EABI64 was originally specified as an LP64 ABI, and that is what
+ -mabi=eabi normally gives on a 64-bit target. However, gcc has
+ historically accepted the combination of -mabi=eabi and -mlong32,
+ and this ILP32 variation has become semi-official over time.
+ Both forms use elf32 and have pointer-sized FDE addresses.
+
+ If an EABI object was generated by GCC 4.0 or above, it will have
+ an empty .gcc_compiled_longXX section, where XX is the size of longs
+ in bits. Unfortunately, ILP32 objects generated by earlier compilers
+ have no special marking to distinguish them from LP64 objects.
+
+ We don't want users of the official LP64 ABI to be punished for the
+ existence of the ILP32 variant, but at the same time, we don't want
+ to mistakenly interpret pre-4.0 ILP32 objects as being LP64 objects.
+ We therefore take the following approach:
+
+ - If ABFD contains a .gcc_compiled_longXX section, use it to
+ determine the pointer size.
+
+ - Otherwise check the type of the first relocation. Assume that
+ the LP64 ABI is being used if the relocation is of type R_MIPS_64.
+
+ - Otherwise punt.
+
+ The second check is enough to detect LP64 objects generated by pre-4.0
+ compilers because, in the kind of output generated by those compilers,
+ the first relocation will be associated with either a CIE personality
+ routine or an FDE start address. Furthermore, the compilers never
+ used a special (non-pointer) encoding for this ABI.
+
+ Checking the relocation type should also be safe because there is no
+ reason to use R_MIPS_64 in an ILP32 object. Pre-4.0 compilers never
+ did so. */
+
+unsigned int
+_bfd_mips_elf_eh_frame_address_size (bfd *abfd, asection *sec)
+{
+ if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64)
+ return 8;
+ if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI64)
+ {
+ bfd_boolean long32_p, long64_p;
+
+ long32_p = bfd_get_section_by_name (abfd, ".gcc_compiled_long32") != 0;
+ long64_p = bfd_get_section_by_name (abfd, ".gcc_compiled_long64") != 0;
+ if (long32_p && long64_p)
+ return 0;
+ if (long32_p)
+ return 4;
+ if (long64_p)
+ return 8;
+
+ if (sec->reloc_count > 0
+ && elf_section_data (sec)->relocs != NULL
+ && (ELF32_R_TYPE (elf_section_data (sec)->relocs[0].r_info)
+ == R_MIPS_64))
+ return 8;
+
+ return 0;
+ }
+ return 4;
+}
+
/* There appears to be a bug in the MIPSpro linker that causes GOT_DISP
relocations against two unnamed section symbols to resolve to the
same address. For example, if we have code like:
diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h
index 0a684d9..de48c63 100644
--- a/bfd/elfxx-mips.h
+++ b/bfd/elfxx-mips.h
@@ -24,6 +24,8 @@ extern bfd_boolean _bfd_mips_elf_new_section_hook
(bfd *, asection *);
extern void _bfd_mips_elf_symbol_processing
(bfd *, asymbol *);
+extern unsigned int _bfd_mips_elf_eh_frame_address_size
+ (bfd *, asection *);
extern bfd_boolean _bfd_mips_elf_name_local_section_symbols
(bfd *);
extern bfd_boolean _bfd_mips_elf_section_processing
@@ -124,3 +126,4 @@ extern struct bfd_elf_special_section const _bfd_mips_elf_special_sections[];
#define elf_backend_name_local_section_symbols \
_bfd_mips_elf_name_local_section_symbols
#define elf_backend_special_sections _bfd_mips_elf_special_sections
+#define elf_backend_eh_frame_address_size _bfd_mips_elf_eh_frame_address_size
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index a9d49c3..baad96d 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -442,6 +442,9 @@
#ifndef elf_backend_ignore_discarded_relocs
#define elf_backend_ignore_discarded_relocs NULL
#endif
+#ifndef elf_backend_eh_frame_address_size
+#define elf_backend_eh_frame_address_size _bfd_elf_eh_frame_address_size
+#endif
#ifndef elf_backend_can_make_relative_eh_frame
#define elf_backend_can_make_relative_eh_frame _bfd_elf_can_make_relative
#endif
@@ -573,6 +576,7 @@ static const struct elf_backend_data elfNN_bed =
elf_backend_reloc_type_class,
elf_backend_discard_info,
elf_backend_ignore_discarded_relocs,
+ elf_backend_eh_frame_address_size,
elf_backend_can_make_relative_eh_frame,
elf_backend_can_make_lsda_relative_eh_frame,
elf_backend_encode_eh_address,