
PointerToGOT lowering was accidentally changed from Delta32 to Delta64 in db3722580335c. This patch moves it back to Delta32 and renames the generic aarch64 edge to Delta32ToGOT to avoid the ambiguity. No test case yet -- I haven't figured out how to write a succinct test case (this typically appears in CIEs in eh-frames).
585 lines
21 KiB
C++
585 lines
21 KiB
C++
//===---- MachO_arm64.cpp - JIT linker implementation for MachO/arm64 -----===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// MachO/arm64 jit-link implementation.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ExecutionEngine/JITLink/MachO_arm64.h"
|
|
#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
|
|
#include "llvm/ExecutionEngine/JITLink/aarch64.h"
|
|
|
|
#include "MachOLinkGraphBuilder.h"
|
|
|
|
#define DEBUG_TYPE "jitlink"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::jitlink;
|
|
|
|
namespace {
|
|
|
|
class MachOLinkGraphBuilder_arm64 : public MachOLinkGraphBuilder {
|
|
public:
|
|
MachOLinkGraphBuilder_arm64(const object::MachOObjectFile &Obj)
|
|
: MachOLinkGraphBuilder(Obj, Triple("arm64-apple-darwin"),
|
|
aarch64::getEdgeKindName),
|
|
NumSymbols(Obj.getSymtabLoadCommand().nsyms) {}
|
|
|
|
private:
|
|
enum MachOARM64RelocationKind : Edge::Kind {
|
|
MachOBranch26 = Edge::FirstRelocation,
|
|
MachOPointer32,
|
|
MachOPointer64,
|
|
MachOPointer64Anon,
|
|
MachOPage21,
|
|
MachOPageOffset12,
|
|
MachOGOTPage21,
|
|
MachOGOTPageOffset12,
|
|
MachOTLVPage21,
|
|
MachOTLVPageOffset12,
|
|
MachOPointerToGOT,
|
|
MachOPairedAddend,
|
|
MachOLDRLiteral19,
|
|
MachODelta32,
|
|
MachODelta64,
|
|
MachONegDelta32,
|
|
MachONegDelta64,
|
|
};
|
|
|
|
static Expected<MachOARM64RelocationKind>
|
|
getRelocationKind(const MachO::relocation_info &RI) {
|
|
switch (RI.r_type) {
|
|
case MachO::ARM64_RELOC_UNSIGNED:
|
|
if (!RI.r_pcrel) {
|
|
if (RI.r_length == 3)
|
|
return RI.r_extern ? MachOPointer64 : MachOPointer64Anon;
|
|
else if (RI.r_length == 2)
|
|
return MachOPointer32;
|
|
}
|
|
break;
|
|
case MachO::ARM64_RELOC_SUBTRACTOR:
|
|
// SUBTRACTOR must be non-pc-rel, extern, with length 2 or 3.
|
|
// Initially represent SUBTRACTOR relocations with 'Delta<W>'.
|
|
// They may be turned into NegDelta<W> by parsePairRelocation.
|
|
if (!RI.r_pcrel && RI.r_extern) {
|
|
if (RI.r_length == 2)
|
|
return MachODelta32;
|
|
else if (RI.r_length == 3)
|
|
return MachODelta64;
|
|
}
|
|
break;
|
|
case MachO::ARM64_RELOC_BRANCH26:
|
|
if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
|
|
return MachOBranch26;
|
|
break;
|
|
case MachO::ARM64_RELOC_PAGE21:
|
|
if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
|
|
return MachOPage21;
|
|
break;
|
|
case MachO::ARM64_RELOC_PAGEOFF12:
|
|
if (!RI.r_pcrel && RI.r_extern && RI.r_length == 2)
|
|
return MachOPageOffset12;
|
|
break;
|
|
case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
|
|
if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
|
|
return MachOGOTPage21;
|
|
break;
|
|
case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
|
|
if (!RI.r_pcrel && RI.r_extern && RI.r_length == 2)
|
|
return MachOGOTPageOffset12;
|
|
break;
|
|
case MachO::ARM64_RELOC_POINTER_TO_GOT:
|
|
if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
|
|
return MachOPointerToGOT;
|
|
break;
|
|
case MachO::ARM64_RELOC_ADDEND:
|
|
if (!RI.r_pcrel && !RI.r_extern && RI.r_length == 2)
|
|
return MachOPairedAddend;
|
|
break;
|
|
case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
|
|
if (RI.r_pcrel && RI.r_extern && RI.r_length == 2)
|
|
return MachOTLVPage21;
|
|
break;
|
|
case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
|
|
if (!RI.r_pcrel && RI.r_extern && RI.r_length == 2)
|
|
return MachOTLVPageOffset12;
|
|
break;
|
|
}
|
|
|
|
return make_error<JITLinkError>(
|
|
"Unsupported arm64 relocation: address=" +
|
|
formatv("{0:x8}", RI.r_address) +
|
|
", symbolnum=" + formatv("{0:x6}", RI.r_symbolnum) +
|
|
", kind=" + formatv("{0:x1}", RI.r_type) +
|
|
", pc_rel=" + (RI.r_pcrel ? "true" : "false") +
|
|
", extern=" + (RI.r_extern ? "true" : "false") +
|
|
", length=" + formatv("{0:d}", RI.r_length));
|
|
}
|
|
|
|
using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;
|
|
|
|
// Parses paired SUBTRACTOR/UNSIGNED relocations and, on success,
|
|
// returns the edge kind and addend to be used.
|
|
Expected<PairRelocInfo>
|
|
parsePairRelocation(Block &BlockToFix, Edge::Kind SubtractorKind,
|
|
const MachO::relocation_info &SubRI,
|
|
orc::ExecutorAddr FixupAddress, const char *FixupContent,
|
|
object::relocation_iterator &UnsignedRelItr,
|
|
object::relocation_iterator &RelEnd) {
|
|
using namespace support;
|
|
|
|
assert(((SubtractorKind == MachODelta32 && SubRI.r_length == 2) ||
|
|
(SubtractorKind == MachODelta64 && SubRI.r_length == 3)) &&
|
|
"Subtractor kind should match length");
|
|
assert(SubRI.r_extern && "SUBTRACTOR reloc symbol should be extern");
|
|
assert(!SubRI.r_pcrel && "SUBTRACTOR reloc should not be PCRel");
|
|
|
|
if (UnsignedRelItr == RelEnd)
|
|
return make_error<JITLinkError>("arm64 SUBTRACTOR without paired "
|
|
"UNSIGNED relocation");
|
|
|
|
auto UnsignedRI = getRelocationInfo(UnsignedRelItr);
|
|
|
|
if (SubRI.r_address != UnsignedRI.r_address)
|
|
return make_error<JITLinkError>("arm64 SUBTRACTOR and paired UNSIGNED "
|
|
"point to different addresses");
|
|
|
|
if (SubRI.r_length != UnsignedRI.r_length)
|
|
return make_error<JITLinkError>("length of arm64 SUBTRACTOR and paired "
|
|
"UNSIGNED reloc must match");
|
|
|
|
Symbol *FromSymbol;
|
|
if (auto FromSymbolOrErr = findSymbolByIndex(SubRI.r_symbolnum))
|
|
FromSymbol = FromSymbolOrErr->GraphSymbol;
|
|
else
|
|
return FromSymbolOrErr.takeError();
|
|
|
|
// Read the current fixup value.
|
|
uint64_t FixupValue = 0;
|
|
if (SubRI.r_length == 3)
|
|
FixupValue = *(const little64_t *)FixupContent;
|
|
else
|
|
FixupValue = *(const little32_t *)FixupContent;
|
|
|
|
// Find 'ToSymbol' using symbol number or address, depending on whether the
|
|
// paired UNSIGNED relocation is extern.
|
|
Symbol *ToSymbol = nullptr;
|
|
if (UnsignedRI.r_extern) {
|
|
// Find target symbol by symbol index.
|
|
if (auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum))
|
|
ToSymbol = ToSymbolOrErr->GraphSymbol;
|
|
else
|
|
return ToSymbolOrErr.takeError();
|
|
} else {
|
|
auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);
|
|
if (!ToSymbolSec)
|
|
return ToSymbolSec.takeError();
|
|
ToSymbol = getSymbolByAddress(*ToSymbolSec, ToSymbolSec->Address);
|
|
assert(ToSymbol && "No symbol for section");
|
|
FixupValue -= ToSymbol->getAddress().getValue();
|
|
}
|
|
|
|
Edge::Kind DeltaKind;
|
|
Symbol *TargetSymbol;
|
|
uint64_t Addend;
|
|
if (&BlockToFix == &FromSymbol->getAddressable()) {
|
|
TargetSymbol = ToSymbol;
|
|
DeltaKind = (SubRI.r_length == 3) ? aarch64::Delta64 : aarch64::Delta32;
|
|
Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());
|
|
// FIXME: handle extern 'from'.
|
|
} else if (&BlockToFix == &ToSymbol->getAddressable()) {
|
|
TargetSymbol = &*FromSymbol;
|
|
DeltaKind =
|
|
(SubRI.r_length == 3) ? aarch64::NegDelta64 : aarch64::NegDelta32;
|
|
Addend = FixupValue - (FixupAddress - ToSymbol->getAddress());
|
|
} else {
|
|
// BlockToFix was neither FromSymbol nor ToSymbol.
|
|
return make_error<JITLinkError>("SUBTRACTOR relocation must fix up "
|
|
"either 'A' or 'B' (or a symbol in one "
|
|
"of their alt-entry groups)");
|
|
}
|
|
|
|
return PairRelocInfo(DeltaKind, TargetSymbol, Addend);
|
|
}
|
|
|
|
Error addRelocations() override {
|
|
using namespace support;
|
|
auto &Obj = getObject();
|
|
|
|
LLVM_DEBUG(dbgs() << "Processing relocations:\n");
|
|
|
|
for (auto &S : Obj.sections()) {
|
|
|
|
orc::ExecutorAddr SectionAddress(S.getAddress());
|
|
|
|
// Skip relocations virtual sections.
|
|
if (S.isVirtual()) {
|
|
if (S.relocation_begin() != S.relocation_end())
|
|
return make_error<JITLinkError>("Virtual section contains "
|
|
"relocations");
|
|
continue;
|
|
}
|
|
|
|
auto NSec =
|
|
findSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));
|
|
if (!NSec)
|
|
return NSec.takeError();
|
|
|
|
// Skip relocations for MachO sections without corresponding graph
|
|
// sections.
|
|
{
|
|
if (!NSec->GraphSection) {
|
|
LLVM_DEBUG({
|
|
dbgs() << " Skipping relocations for MachO section "
|
|
<< NSec->SegName << "/" << NSec->SectName
|
|
<< " which has no associated graph section\n";
|
|
});
|
|
continue;
|
|
}
|
|
}
|
|
|
|
for (auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();
|
|
RelItr != RelEnd; ++RelItr) {
|
|
|
|
MachO::relocation_info RI = getRelocationInfo(RelItr);
|
|
|
|
// Validate the relocation kind.
|
|
auto MachORelocKind = getRelocationKind(RI);
|
|
if (!MachORelocKind)
|
|
return MachORelocKind.takeError();
|
|
|
|
// Find the address of the value to fix up.
|
|
orc::ExecutorAddr FixupAddress =
|
|
SectionAddress + (uint32_t)RI.r_address;
|
|
LLVM_DEBUG({
|
|
dbgs() << " " << NSec->SectName << " + "
|
|
<< formatv("{0:x8}", RI.r_address) << ":\n";
|
|
});
|
|
|
|
// Find the block that the fixup points to.
|
|
Block *BlockToFix = nullptr;
|
|
{
|
|
auto SymbolToFixOrErr = findSymbolByAddress(*NSec, FixupAddress);
|
|
if (!SymbolToFixOrErr)
|
|
return SymbolToFixOrErr.takeError();
|
|
BlockToFix = &SymbolToFixOrErr->getBlock();
|
|
}
|
|
|
|
if (FixupAddress + orc::ExecutorAddrDiff(1ULL << RI.r_length) >
|
|
BlockToFix->getAddress() + BlockToFix->getContent().size())
|
|
return make_error<JITLinkError>(
|
|
"Relocation content extends past end of fixup block");
|
|
|
|
Edge::Kind Kind = Edge::Invalid;
|
|
|
|
// Get a pointer to the fixup content.
|
|
const char *FixupContent = BlockToFix->getContent().data() +
|
|
(FixupAddress - BlockToFix->getAddress());
|
|
|
|
// The target symbol and addend will be populated by the switch below.
|
|
Symbol *TargetSymbol = nullptr;
|
|
uint64_t Addend = 0;
|
|
|
|
if (*MachORelocKind == MachOPairedAddend) {
|
|
// If this is an Addend relocation then process it and move to the
|
|
// paired reloc.
|
|
|
|
Addend = SignExtend64(RI.r_symbolnum, 24);
|
|
|
|
if (RelItr == RelEnd)
|
|
return make_error<JITLinkError>("Unpaired Addend reloc at " +
|
|
formatv("{0:x16}", FixupAddress));
|
|
++RelItr;
|
|
RI = getRelocationInfo(RelItr);
|
|
|
|
MachORelocKind = getRelocationKind(RI);
|
|
if (!MachORelocKind)
|
|
return MachORelocKind.takeError();
|
|
|
|
if (*MachORelocKind != MachOBranch26 &&
|
|
*MachORelocKind != MachOPage21 &&
|
|
*MachORelocKind != MachOPageOffset12)
|
|
return make_error<JITLinkError>(
|
|
"Invalid relocation pair: Addend + " +
|
|
StringRef(getMachOARM64RelocationKindName(*MachORelocKind)));
|
|
|
|
LLVM_DEBUG({
|
|
dbgs() << " Addend: value = " << formatv("{0:x6}", Addend)
|
|
<< ", pair is "
|
|
<< getMachOARM64RelocationKindName(*MachORelocKind) << "\n";
|
|
});
|
|
|
|
// Find the address of the value to fix up.
|
|
orc::ExecutorAddr PairedFixupAddress =
|
|
SectionAddress + (uint32_t)RI.r_address;
|
|
if (PairedFixupAddress != FixupAddress)
|
|
return make_error<JITLinkError>("Paired relocation points at "
|
|
"different target");
|
|
}
|
|
|
|
switch (*MachORelocKind) {
|
|
case MachOBranch26: {
|
|
if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
|
|
TargetSymbol = TargetSymbolOrErr->GraphSymbol;
|
|
else
|
|
return TargetSymbolOrErr.takeError();
|
|
uint32_t Instr = *(const ulittle32_t *)FixupContent;
|
|
if ((Instr & 0x7fffffff) != 0x14000000)
|
|
return make_error<JITLinkError>("BRANCH26 target is not a B or BL "
|
|
"instruction with a zero addend");
|
|
Kind = aarch64::Branch26;
|
|
break;
|
|
}
|
|
case MachOPointer32:
|
|
if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
|
|
TargetSymbol = TargetSymbolOrErr->GraphSymbol;
|
|
else
|
|
return TargetSymbolOrErr.takeError();
|
|
Addend = *(const ulittle32_t *)FixupContent;
|
|
Kind = aarch64::Pointer32;
|
|
break;
|
|
case MachOPointer64:
|
|
if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
|
|
TargetSymbol = TargetSymbolOrErr->GraphSymbol;
|
|
else
|
|
return TargetSymbolOrErr.takeError();
|
|
Addend = *(const ulittle64_t *)FixupContent;
|
|
Kind = aarch64::Pointer64;
|
|
break;
|
|
case MachOPointer64Anon: {
|
|
orc::ExecutorAddr TargetAddress(*(const ulittle64_t *)FixupContent);
|
|
auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);
|
|
if (!TargetNSec)
|
|
return TargetNSec.takeError();
|
|
if (auto TargetSymbolOrErr =
|
|
findSymbolByAddress(*TargetNSec, TargetAddress))
|
|
TargetSymbol = &*TargetSymbolOrErr;
|
|
else
|
|
return TargetSymbolOrErr.takeError();
|
|
Addend = TargetAddress - TargetSymbol->getAddress();
|
|
Kind = aarch64::Pointer64Anon;
|
|
break;
|
|
}
|
|
case MachOPage21:
|
|
case MachOTLVPage21:
|
|
case MachOGOTPage21: {
|
|
if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
|
|
TargetSymbol = TargetSymbolOrErr->GraphSymbol;
|
|
else
|
|
return TargetSymbolOrErr.takeError();
|
|
uint32_t Instr = *(const ulittle32_t *)FixupContent;
|
|
if ((Instr & 0xffffffe0) != 0x90000000)
|
|
return make_error<JITLinkError>("PAGE21/GOTPAGE21 target is not an "
|
|
"ADRP instruction with a zero "
|
|
"addend");
|
|
|
|
if (*MachORelocKind == MachOPage21) {
|
|
Kind = aarch64::Page21;
|
|
} else if (*MachORelocKind == MachOTLVPage21) {
|
|
Kind = aarch64::TLVPage21;
|
|
} else if (*MachORelocKind == MachOGOTPage21) {
|
|
Kind = aarch64::GOTPage21;
|
|
}
|
|
break;
|
|
}
|
|
case MachOPageOffset12: {
|
|
if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
|
|
TargetSymbol = TargetSymbolOrErr->GraphSymbol;
|
|
else
|
|
return TargetSymbolOrErr.takeError();
|
|
uint32_t Instr = *(const ulittle32_t *)FixupContent;
|
|
uint32_t EncodedAddend = (Instr & 0x003FFC00) >> 10;
|
|
if (EncodedAddend != 0)
|
|
return make_error<JITLinkError>("GOTPAGEOFF12 target has non-zero "
|
|
"encoded addend");
|
|
Kind = aarch64::PageOffset12;
|
|
break;
|
|
}
|
|
case MachOTLVPageOffset12:
|
|
case MachOGOTPageOffset12: {
|
|
if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
|
|
TargetSymbol = TargetSymbolOrErr->GraphSymbol;
|
|
else
|
|
return TargetSymbolOrErr.takeError();
|
|
uint32_t Instr = *(const ulittle32_t *)FixupContent;
|
|
if ((Instr & 0xfffffc00) != 0xf9400000)
|
|
return make_error<JITLinkError>("GOTPAGEOFF12 target is not an LDR "
|
|
"immediate instruction with a zero "
|
|
"addend");
|
|
|
|
if (*MachORelocKind == MachOTLVPageOffset12) {
|
|
Kind = aarch64::TLVPageOffset12;
|
|
} else if (*MachORelocKind == MachOGOTPageOffset12) {
|
|
Kind = aarch64::GOTPageOffset12;
|
|
}
|
|
break;
|
|
}
|
|
case MachOPointerToGOT:
|
|
if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))
|
|
TargetSymbol = TargetSymbolOrErr->GraphSymbol;
|
|
else
|
|
return TargetSymbolOrErr.takeError();
|
|
|
|
Kind = aarch64::Delta32ToGOT;
|
|
break;
|
|
case MachODelta32:
|
|
case MachODelta64: {
|
|
// We use Delta32/Delta64 to represent SUBTRACTOR relocations.
|
|
// parsePairRelocation handles the paired reloc, and returns the
|
|
// edge kind to be used (either Delta32/Delta64, or
|
|
// NegDelta32/NegDelta64, depending on the direction of the
|
|
// subtraction) along with the addend.
|
|
auto PairInfo =
|
|
parsePairRelocation(*BlockToFix, *MachORelocKind, RI,
|
|
FixupAddress, FixupContent, ++RelItr, RelEnd);
|
|
if (!PairInfo)
|
|
return PairInfo.takeError();
|
|
std::tie(Kind, TargetSymbol, Addend) = *PairInfo;
|
|
assert(TargetSymbol && "No target symbol from parsePairRelocation?");
|
|
break;
|
|
}
|
|
default:
|
|
llvm_unreachable("Special relocation kind should not appear in "
|
|
"mach-o file");
|
|
}
|
|
|
|
LLVM_DEBUG({
|
|
dbgs() << " ";
|
|
Edge GE(Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,
|
|
Addend);
|
|
printEdge(dbgs(), *BlockToFix, GE, aarch64::getEdgeKindName(Kind));
|
|
dbgs() << "\n";
|
|
});
|
|
BlockToFix->addEdge(Kind, FixupAddress - BlockToFix->getAddress(),
|
|
*TargetSymbol, Addend);
|
|
}
|
|
}
|
|
return Error::success();
|
|
}
|
|
|
|
/// Return the string name of the given MachO arm64 edge kind.
|
|
const char *getMachOARM64RelocationKindName(Edge::Kind R) {
|
|
switch (R) {
|
|
case MachOBranch26:
|
|
return "MachOBranch26";
|
|
case MachOPointer64:
|
|
return "MachOPointer64";
|
|
case MachOPointer64Anon:
|
|
return "MachOPointer64Anon";
|
|
case MachOPage21:
|
|
return "MachOPage21";
|
|
case MachOPageOffset12:
|
|
return "MachOPageOffset12";
|
|
case MachOGOTPage21:
|
|
return "MachOGOTPage21";
|
|
case MachOGOTPageOffset12:
|
|
return "MachOGOTPageOffset12";
|
|
case MachOTLVPage21:
|
|
return "MachOTLVPage21";
|
|
case MachOTLVPageOffset12:
|
|
return "MachOTLVPageOffset12";
|
|
case MachOPointerToGOT:
|
|
return "MachOPointerToGOT";
|
|
case MachOPairedAddend:
|
|
return "MachOPairedAddend";
|
|
case MachOLDRLiteral19:
|
|
return "MachOLDRLiteral19";
|
|
case MachODelta32:
|
|
return "MachODelta32";
|
|
case MachODelta64:
|
|
return "MachODelta64";
|
|
case MachONegDelta32:
|
|
return "MachONegDelta32";
|
|
case MachONegDelta64:
|
|
return "MachONegDelta64";
|
|
default:
|
|
return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
|
|
}
|
|
}
|
|
|
|
unsigned NumSymbols = 0;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
namespace llvm {
|
|
namespace jitlink {
|
|
|
|
Error buildTables_MachO_arm64(LinkGraph &G) {
|
|
LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
|
|
|
|
aarch64::GOTTableManager GOT;
|
|
aarch64::PLTTableManager PLT(GOT);
|
|
visitExistingEdges(G, GOT, PLT);
|
|
return Error::success();
|
|
}
|
|
|
|
class MachOJITLinker_arm64 : public JITLinker<MachOJITLinker_arm64> {
|
|
friend class JITLinker<MachOJITLinker_arm64>;
|
|
|
|
public:
|
|
MachOJITLinker_arm64(std::unique_ptr<JITLinkContext> Ctx,
|
|
std::unique_ptr<LinkGraph> G,
|
|
PassConfiguration PassConfig)
|
|
: JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
|
|
|
|
private:
|
|
Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
|
|
return aarch64::applyFixup(G, B, E);
|
|
}
|
|
|
|
uint64_t NullValue = 0;
|
|
};
|
|
|
|
Expected<std::unique_ptr<LinkGraph>>
|
|
createLinkGraphFromMachOObject_arm64(MemoryBufferRef ObjectBuffer) {
|
|
auto MachOObj = object::ObjectFile::createMachOObjectFile(ObjectBuffer);
|
|
if (!MachOObj)
|
|
return MachOObj.takeError();
|
|
return MachOLinkGraphBuilder_arm64(**MachOObj).buildGraph();
|
|
}
|
|
|
|
void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
|
|
std::unique_ptr<JITLinkContext> Ctx) {
|
|
|
|
PassConfiguration Config;
|
|
|
|
if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
|
|
// Add a mark-live pass.
|
|
if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
|
|
Config.PrePrunePasses.push_back(std::move(MarkLive));
|
|
else
|
|
Config.PrePrunePasses.push_back(markAllSymbolsLive);
|
|
|
|
// Add compact unwind splitter pass.
|
|
Config.PrePrunePasses.push_back(
|
|
CompactUnwindSplitter("__LD,__compact_unwind"));
|
|
|
|
// Add eh-frame passses.
|
|
// FIXME: Prune eh-frames for which compact-unwind is available once
|
|
// we support compact-unwind registration with libunwind.
|
|
Config.PrePrunePasses.push_back(
|
|
DWARFRecordSectionSplitter("__TEXT,__eh_frame"));
|
|
Config.PrePrunePasses.push_back(EHFrameEdgeFixer(
|
|
"__TEXT,__eh_frame", 8, aarch64::Pointer32, aarch64::Pointer64,
|
|
aarch64::Delta32, aarch64::Delta64, aarch64::NegDelta32));
|
|
|
|
// Add an in-place GOT/Stubs pass.
|
|
Config.PostPrunePasses.push_back(buildTables_MachO_arm64);
|
|
}
|
|
|
|
if (auto Err = Ctx->modifyPassConfig(*G, Config))
|
|
return Ctx->notifyFailed(std::move(Err));
|
|
|
|
// Construct a JITLinker and run the link function.
|
|
MachOJITLinker_arm64::link(std::move(Ctx), std::move(G), std::move(Config));
|
|
}
|
|
|
|
} // end namespace jitlink
|
|
} // end namespace llvm
|