summaryrefslogtreecommitdiff
path: root/bfd/elf64-x86-64.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r--bfd/elf64-x86-64.c50
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;