diff options
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r-- | bfd/elf64-x86-64.c | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 975b558473..7b92097120 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -30,6 +30,7 @@ #include "objalloc.h" #include "hashtab.h" #include "dwarf2.h" +#include "libiberty.h" #include "elf/x86-64.h" @@ -178,7 +179,12 @@ static reloc_howto_type x86_64_elf_howto_table[] = /* GNU extension to record C++ vtable member usage. */ HOWTO (R_X86_64_GNU_VTENTRY, 0, 4, 0, FALSE, 0, complain_overflow_dont, _bfd_elf_rel_vtable_reloc_fn, "R_X86_64_GNU_VTENTRY", FALSE, 0, 0, - FALSE) + FALSE), + +/* Use complain_overflow_bitfield on R_X86_64_32 for x32. */ + HOWTO(R_X86_64_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_X86_64_32", FALSE, 0xffffffff, 0xffffffff, + FALSE) }; #define IS_X86_64_PCREL_TYPE(TYPE) \ @@ -241,8 +247,15 @@ elf_x86_64_rtype_to_howto (bfd *abfd, unsigned r_type) { unsigned i; - if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT - || r_type >= (unsigned int) R_X86_64_max) + if (r_type == (unsigned int) R_X86_64_32) + { + if (ABI_64_P (abfd)) + i = r_type; + else + i = ARRAY_SIZE (x86_64_elf_howto_table) - 1; + } + else if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT + || r_type >= (unsigned int) R_X86_64_max) { if (r_type >= (unsigned int) R_X86_64_standard) { @@ -276,15 +289,21 @@ elf_x86_64_reloc_type_lookup (bfd *abfd, } static reloc_howto_type * -elf_x86_64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, +elf_x86_64_reloc_name_lookup (bfd *abfd, const char *r_name) { unsigned int i; - for (i = 0; - i < (sizeof (x86_64_elf_howto_table) - / sizeof (x86_64_elf_howto_table[0])); - i++) + if (!ABI_64_P (abfd) && strcasecmp (r_name, "R_X86_64_32") == 0) + { + /* Get x32 R_X86_64_32. */ + reloc_howto_type *reloc + = &x86_64_elf_howto_table[ARRAY_SIZE (x86_64_elf_howto_table) - 1]; + BFD_ASSERT (reloc->type == (unsigned int) R_X86_64_32); + return reloc; + } + + for (i = 0; i < ARRAY_SIZE (x86_64_elf_howto_table); i++) if (x86_64_elf_howto_table[i].name != NULL && strcasecmp (x86_64_elf_howto_table[i].name, r_name) == 0) return &x86_64_elf_howto_table[i]; @@ -1396,14 +1415,6 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, default: break; - case R_X86_64_64: - /* Allow R_X86_64_64 relocations in SEC_DEBUGGING sections - when building shared libraries. */ - if (info->shared - && !info->executable - && (sec->flags & SEC_DEBUGGING) != 0) - break; - case R_X86_64_DTPOFF64: case R_X86_64_TPOFF64: case R_X86_64_PC64: @@ -3022,7 +3033,12 @@ elf_x86_64_relocate_section (bfd *output_bfd, return FALSE; } - howto = x86_64_elf_howto_table + r_type; + if (r_type != (int) R_X86_64_32 + || ABI_64_P (output_bfd)) + howto = x86_64_elf_howto_table + r_type; + else + howto = (x86_64_elf_howto_table + + ARRAY_SIZE (x86_64_elf_howto_table) - 1); r_symndx = htab->r_sym (rel->r_info); h = NULL; sym = NULL; |