summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2016-09-20 10:06:39 +0000
committerkettenis <kettenis@openbsd.org>2016-09-20 10:06:39 +0000
commit5bd6f1f18a1f1e3d431c7b6c3192dd519ee52f52 (patch)
tree1d8a1475c227f659773c4234bd2bb7e5dcc974b9
parentRewrite awkward phrase, pointed out by Bryan Vyhmeister, wording tweak (diff)
downloadwireguard-openbsd-5bd6f1f18a1f1e3d431c7b6c3192dd519ee52f52.tar.xz
wireguard-openbsd-5bd6f1f18a1f1e3d431c7b6c3192dd519ee52f52.zip
Support a few more relocations, most notably R_ARM_MOVW_ABS_NC and
R_ARM_MOVT_ABS that clang creates in its default configuration. From FreeBSD. ok jsg@
-rw-r--r--gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h6
-rw-r--r--gnu/usr.bin/binutils-2.17/bfd/elf32-arm.c55
-rw-r--r--gnu/usr.bin/binutils-2.17/bfd/libbfd.h4
-rw-r--r--gnu/usr.bin/binutils-2.17/bfd/reloc.c8
4 files changed, 73 insertions, 0 deletions
diff --git a/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h b/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h
index 1b4cef83dc1..f8738070a4b 100644
--- a/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h
+++ b/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h
@@ -2907,6 +2907,12 @@ pc-relative or some form of GOT-indirect relocation. */
/* 31-bit PC relative address. */
BFD_RELOC_ARM_PREL31,
+/* Low and High halfword relocations for MOVW and MOVT instructions. */
+ BFD_RELOC_ARM_MOVW,
+ BFD_RELOC_ARM_MOVT,
+ BFD_RELOC_ARM_MOVW_PCREL,
+ BFD_RELOC_ARM_MOVT_PCREL,
+
/* Relocations for setting up GOTs and PLTs for shared libraries. */
BFD_RELOC_ARM_JUMP_SLOT,
BFD_RELOC_ARM_GLOB_DAT,
diff --git a/gnu/usr.bin/binutils-2.17/bfd/elf32-arm.c b/gnu/usr.bin/binutils-2.17/bfd/elf32-arm.c
index f16ec58c529..7556c6b1f1b 100644
--- a/gnu/usr.bin/binutils-2.17/bfd/elf32-arm.c
+++ b/gnu/usr.bin/binutils-2.17/bfd/elf32-arm.c
@@ -1366,6 +1366,10 @@ static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] =
{BFD_RELOC_ARM_TLS_LE32, R_ARM_TLS_LE32},
{BFD_RELOC_VTABLE_INHERIT, R_ARM_GNU_VTINHERIT},
{BFD_RELOC_VTABLE_ENTRY, R_ARM_GNU_VTENTRY},
+ {BFD_RELOC_ARM_MOVW, R_ARM_MOVW_ABS_NC},
+ {BFD_RELOC_ARM_MOVT, R_ARM_MOVT_ABS},
+ {BFD_RELOC_ARM_MOVW_PCREL, R_ARM_MOVW_PREL_NC},
+ {BFD_RELOC_ARM_MOVT_PCREL, R_ARM_MOVT_PREL},
};
static reloc_howto_type *
@@ -4080,6 +4084,49 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
}
return bfd_reloc_ok;
+ case R_ARM_MOVW_ABS_NC:
+ case R_ARM_MOVT_ABS:
+ case R_ARM_MOVW_PREL_NC:
+ case R_ARM_MOVT_PREL:
+ /* Until we properly support segment-base-relative addressing then
+ we assume the segment base to be zero, as for the group relocations.
+ Thus R_ARM_MOVW_BREL_NC has the same semantics as R_ARM_MOVW_ABS_NC
+ and R_ARM_MOVT_BREL has the same semantics as R_ARM_MOVT_ABS. */
+ case R_ARM_MOVW_BREL_NC:
+ case R_ARM_MOVW_BREL:
+ case R_ARM_MOVT_BREL:
+ {
+ bfd_vma insn = bfd_get_32 (input_bfd, hit_data);
+
+ if (globals->use_rel)
+ {
+ addend = ((insn >> 4) & 0xf000) | (insn & 0xfff);
+ signed_addend = (addend ^ 0x8000) - 0x8000;
+ }
+
+ value += signed_addend;
+
+ if (r_type == R_ARM_MOVW_PREL_NC || r_type == R_ARM_MOVT_PREL)
+ value -= (input_section->output_section->vma
+ + input_section->output_offset + rel->r_offset);
+
+ if (r_type == R_ARM_MOVW_BREL && value >= 0x10000)
+ return bfd_reloc_overflow;
+
+ if (sym_flags == STT_ARM_TFUNC)
+ value |= 1;
+
+ if (r_type == R_ARM_MOVT_ABS || r_type == R_ARM_MOVT_PREL
+ || r_type == R_ARM_MOVT_BREL)
+ value >>= 16;
+
+ insn &= 0xfff0f000;
+ insn |= value & 0xfff;
+ insn |= (value & 0xf000) << 4;
+ bfd_put_32 (input_bfd, insn, hit_data);
+ }
+ return bfd_reloc_ok;
+
default:
return bfd_reloc_notsupported;
}
@@ -5651,6 +5698,10 @@ elf32_arm_gc_sweep_hook (bfd * abfd,
case R_ARM_JUMP24:
case R_ARM_PREL31:
case R_ARM_THM_CALL:
+ case R_ARM_MOVW_ABS_NC:
+ case R_ARM_MOVT_ABS:
+ case R_ARM_MOVW_PREL_NC:
+ case R_ARM_MOVT_PREL:
/* Should the interworking branches be here also? */
if (h != NULL)
@@ -5861,6 +5912,10 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_ARM_JUMP24:
case R_ARM_PREL31:
case R_ARM_THM_CALL:
+ case R_ARM_MOVW_ABS_NC:
+ case R_ARM_MOVT_ABS:
+ case R_ARM_MOVW_PREL_NC:
+ case R_ARM_MOVT_PREL:
/* Should the interworking branches be listed here? */
if (h != NULL)
{
diff --git a/gnu/usr.bin/binutils-2.17/bfd/libbfd.h b/gnu/usr.bin/binutils-2.17/bfd/libbfd.h
index 24964899c91..d54a6decac9 100644
--- a/gnu/usr.bin/binutils-2.17/bfd/libbfd.h
+++ b/gnu/usr.bin/binutils-2.17/bfd/libbfd.h
@@ -1209,6 +1209,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_ARM_SBREL32",
"BFD_RELOC_ARM_TARGET2",
"BFD_RELOC_ARM_PREL31",
+ "BFD_RELOC_ARM_MOVW",
+ "BFD_RELOC_ARM_MOVT",
+ "BFD_RELOC_ARM_MOVW_PCREL",
+ "BFD_RELOC_ARM_MOVT_PCREL",
"BFD_RELOC_ARM_JUMP_SLOT",
"BFD_RELOC_ARM_GLOB_DAT",
"BFD_RELOC_ARM_GOT32",
diff --git a/gnu/usr.bin/binutils-2.17/bfd/reloc.c b/gnu/usr.bin/binutils-2.17/bfd/reloc.c
index c80a0f9daea..b809a6108d4 100644
--- a/gnu/usr.bin/binutils-2.17/bfd/reloc.c
+++ b/gnu/usr.bin/binutils-2.17/bfd/reloc.c
@@ -2705,6 +2705,14 @@ ENUM
BFD_RELOC_ARM_PREL31
ENUMDOC
31-bit PC relative address.
+ENUM
+ BFD_RELOC_ARM_MOVW
+ENUMX
+ BFD_RELOC_ARM_MOVT
+ENUMX
+ BFD_RELOC_ARM_MOVW_PCREL
+ENUMX
+ BFD_RELOC_ARM_MOVT_PCREL
ENUM
BFD_RELOC_ARM_JUMP_SLOT