From 3daccaac8a6b261eaedf76e6eac6011295b08d7e Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Sat, 3 Aug 2019 20:17:10 +0000 Subject: [PATCH] [JITLink] Add support for MachO/x86-64 UNSIGNED relocs with length=2. MachO/x86-64 UNSIGNED relocs are almost always 64-bit (length=3), but UNSIGNED relocs of length=2 are allowed if the target resides in the low 32-bits. This patch adds support for such relocations in JITLink (previously they would have triggered an unsupported relocation error). llvm-svn: 367764 --- .../llvm/ExecutionEngine/JITLink/MachO_x86_64.h | 1 + llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp | 24 ++++++++++++++++-- .../JITLink/X86/MachO_x86-64_relocations.s | 29 ++++++++++++++-------- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h b/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h index 1d5b586..00a7feb 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/MachO_x86_64.h @@ -22,6 +22,7 @@ namespace MachO_x86_64_Edges { enum MachOX86RelocationKind : Edge::Kind { Branch32 = Edge::FirstRelocation, + Pointer32, Pointer64, Pointer64Anon, PCRel32, diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp index 6b2b392..52481f8 100644 --- a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp @@ -40,8 +40,12 @@ private: getRelocationKind(const MachO::relocation_info &RI) { switch (RI.r_type) { case MachO::X86_64_RELOC_UNSIGNED: - if (!RI.r_pcrel && RI.r_length == 3) - return RI.r_extern ? Pointer64 : Pointer64Anon; + if (!RI.r_pcrel) { + if (RI.r_length == 3) + return RI.r_extern ? Pointer64 : Pointer64Anon; + else if (RI.r_extern && RI.r_length == 2) + return Pointer32; + } break; case MachO::X86_64_RELOC_SIGNED: if (RI.r_pcrel && RI.r_length == 2) @@ -260,6 +264,13 @@ private: return TargetAtomOrErr.takeError(); Addend = *(const ulittle32_t *)FixupContent; break; + case Pointer32: + if (auto TargetAtomOrErr = findAtomBySymbolIndex(RI)) + TargetAtom = &*TargetAtomOrErr; + else + return TargetAtomOrErr.takeError(); + Addend = *(const ulittle32_t *)FixupContent; + break; case Pointer64: if (auto TargetAtomOrErr = findAtomBySymbolIndex(RI)) TargetAtom = &*TargetAtomOrErr; @@ -526,6 +537,13 @@ private: *(little64_t *)FixupPtr = Value; break; } + case Pointer32: { + uint64_t Value = E.getTarget().getAddress() + E.getAddend(); + if (Value > std::numeric_limits::max()) + return targetOutOfRangeError(A, E); + *(ulittle32_t *)FixupPtr = Value; + break; + } default: llvm_unreachable("Unrecognized edge kind"); } @@ -565,6 +583,8 @@ StringRef getMachOX86RelocationKindName(Edge::Kind R) { switch (R) { case Branch32: return "Branch32"; + case Pointer32: + return "Pointer32"; case Pointer64: return "Pointer64"; case Pointer64Anon: diff --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s b/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s index 1958ae1..0fb1285 100644 --- a/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s +++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s @@ -154,22 +154,31 @@ named_data: named_data_alt_entry: .quad 0 -# Check X86_64_RELOC_UNSIGNED / extern handling by putting the address of a -# local named function in a pointer variable. +# Check X86_64_RELOC_UNSIGNED / quad / extern handling by putting the address of +# a local named function into a quad symbol. # -# jitlink-check: *{8}named_func_addr = named_func - .globl named_func_addr +# jitlink-check: *{8}named_func_addr_quad = named_func + .globl named_func_addr_quad .p2align 3 -named_func_addr: +named_func_addr_quad: .quad named_func -# Check X86_64_RELOC_UNSIGNED / non-extern handling by putting the address of a -# local anonymous function in a pointer variable. +# Check X86_64_RELOC_UNSIGNED / long / extern handling by putting the address of +# an external function (defined to reside in the low 4Gb) into a long symbol. # -# jitlink-check: *{8}anon_func_addr = section_addr(macho_reloc.o, __text) - .globl anon_func_addr +# jitlink-check: *{8}named_func_addr_long = external_func + .globl named_func_addr_long + .p2align 2 +named_func_addr_long: + .long external_func + +# Check X86_64_RELOC_UNSIGNED / quad / non-extern handling by putting the +# address of a local anonymous function into a quad symbol. +# +# jitlink-check: *{8}anon_func_addr_quad = section_addr(macho_reloc.o, __text) + .globl anon_func_addr_quad .p2align 3 -anon_func_addr: +anon_func_addr_quad: .quad Lanon_func # X86_64_RELOC_SUBTRACTOR Quad/Long in named storage with anonymous minuend -- 2.7.4