17#define DEBUG_TYPE "jitlink"
24 0x00, 0x00, 0x00, 0x00};
27 0x10, 0x00, 0x00, (
char)0x90u,
28 0x10, 0x02, 0x40, (
char)0xf9u,
29 0x00, 0x02, 0x1f, (
char)0xd6u
33 (
char)0xfd, 0x7b, (
char)0xbf, (
char)0xa9,
34 0x00, 0x00, 0x00, (
char)0x94
42 return "Pointer64Authenticated";
54 return "Branch26PCRel";
58 return "LDRLiteral19";
60 return "TestAndBranch14PCRel";
62 return "CondBranch19PCRel";
64 return "ADRLiteral21";
68 return "PageOffset12";
70 return "GotPageOffset15";
72 return "RequestGOTAndTransformToPage21";
74 return "RequestGOTAndTransformToPageOffset12";
76 return "RequestGOTAndTransformToPageOffset15";
78 return "RequestGOTAndTransformToDelta32";
80 return "RequestTLVPAndTransformToPage21";
82 return "RequestTLVPAndTransformToPageOffset12";
84 return "RequestTLSDescEntryAndTransformToPage21";
86 return "RequestTLSDescEntryAndTransformToPageOffset12";
93template <
typename AppendFtor>
96 assert(DstReg < 32 &&
"Dst reg out of range");
97 assert(SrcReg < 32 &&
"Src reg out of range");
102 constexpr uint32_t MOVGPR64Template = 0xaa0003e0;
104 constexpr uint32_t SrcRegIndex = 16;
106 Instr |= DstReg << DstRegIndex;
107 Instr |= SrcReg << SrcRegIndex;
108 return Append(Instr);
112template <
typename AppendFtor>
115 assert(
Reg < 32 &&
"Invalid register number");
117 constexpr uint32_t MovRegImm64Template = 0xd2800000;
118 constexpr unsigned PreserveBitIndex = 29;
119 constexpr unsigned ShiftBitsIndex = 21;
120 constexpr unsigned ImmBitsIndex = 5;
122 bool PreserveRegValue =
false;
123 for (
unsigned I = 0;
I != 4; ++
I) {
128 if (PreserveRegValue && !ImmBits)
131 uint32_t Instr = MovRegImm64Template;
132 Instr |= PreserveRegValue << PreserveBitIndex;
133 Instr |= (
I << ShiftBitsIndex);
134 Instr |= ImmBits << ImmBitsIndex;
136 if (
auto Err = Append(Instr))
138 PreserveRegValue =
true;
144template <
typename AppendFtor>
147 unsigned RawAddrReg,
unsigned DiscriminatorReg,
unsigned Key,
148 uint64_t EncodedDiscriminator,
bool AddressDiversify) {
149 assert(DstReg < 32 &&
"DstReg out of range");
150 assert(RawAddrReg < 32 &&
"AddrReg out of range");
151 assert(DiscriminatorReg < 32 &&
"DiscriminatorReg out of range");
152 assert(EncodedDiscriminator < 0x10000 &&
"EncodedDiscriminator out of range");
154 if (AddressDiversify) {
159 if (EncodedDiscriminator) {
160 constexpr uint32_t MOVKTemplate = 0xf2e00000;
161 constexpr unsigned ImmIndex = 5;
163 BlendInstr |= EncodedDiscriminator << ImmIndex;
164 BlendInstr |= DiscriminatorReg;
165 if (
auto Err = Append(BlendInstr))
168 }
else if (EncodedDiscriminator) {
174 DiscriminatorReg = 31;
176 constexpr uint32_t PACTemplate = 0xdac10000;
177 constexpr unsigned ZBitIndex = 13;
178 constexpr unsigned KeyIndex = 10;
179 constexpr unsigned DiscriminatorRegIndex = 5;
182 Instr |= (DiscriminatorReg == 31) << ZBitIndex;
183 Instr |= Key << KeyIndex;
184 Instr |= DiscriminatorReg << DiscriminatorRegIndex;
187 return Append(Instr);
190template <
typename AppendFtor>
193 assert(DstLocReg < 32 &&
"DstLocReg out of range");
194 assert(SrcReg < 32 &&
"SrcReg out of range");
196 constexpr uint32_t STRTemplate = 0xf9000000;
197 constexpr unsigned DstLocRegIndex = 5;
198 constexpr unsigned SrcRegIndex = 0;
201 Instr |= DstLocReg << DstLocRegIndex;
202 Instr |= SrcReg << SrcRegIndex;
204 return Append(Instr);
207void GOTTableManager::registerExistingEntries() {
208 for (
auto *EntrySym : GOTSection->
symbols()) {
209 assert(EntrySym->getBlock().edges_size() == 1 &&
210 "GOT block edge count != 1");
218 assert(EntrySym->getBlock().edges_size() == 2 &&
219 "PLT block edge count != 2");
220 auto &GOTSym = EntrySym->getBlock().edges().begin()->getTarget();
221 assert(GOTSym.getBlock().edges_size() == 1 &&
"GOT block edge count != 1");
235 dbgs() <<
"Creating empty pointer signing function for " <<
G.getName()
242 size_t NumPtrAuthFixupLocations = 0;
243 for (
auto &Sec :
G.sections()) {
251 for (
auto *
B : Sec.blocks()) {
252 for (
auto &
E :
B->edges())
253 NumPtrAuthFixupLocations +=
258 constexpr size_t MaxPtrSignSeqLength =
267 size_t NumSigningInstrs = NumPtrAuthFixupLocations * MaxPtrSignSeqLength + 3;
270 auto &SigningSection =
275 size_t SigningFunctionSize = NumSigningInstrs * 4;
276 auto &SigningFunctionBlock =
G.createMutableContentBlock(
277 SigningSection,
G.allocateBuffer(SigningFunctionSize),
279 G.addAnonymousSymbol(SigningFunctionBlock, 0, SigningFunctionBlock.getSize(),
283 dbgs() <<
" " << NumPtrAuthFixupLocations <<
" location(s) to sign, up to "
284 << NumSigningInstrs <<
" instructions required ("
285 <<
formatv(
"{0:x}", SigningFunctionBlock.getSize()) <<
" bytes)\n";
299 dbgs() <<
"Writing pointer signing function for " <<
G.getName() <<
"\n";
302 constexpr unsigned Reg1 = 8;
303 constexpr unsigned Reg2 = 9;
304 constexpr unsigned Reg3 = 10;
307 auto *SigningSection =
309 assert(SigningSection &&
"Siging section missing");
310 assert(SigningSection->blocks_size() == 1 &&
311 "Unexpected number of blocks in signing section");
312 assert(SigningSection->symbols_size() == 1 &&
313 "Unexpected number of symbols in signing section");
315 auto &SigningFunctionSym = **SigningSection->symbols().begin();
316 auto &SigningFunctionBlock = SigningFunctionSym.getBlock();
317 auto SigningFunctionBuf = SigningFunctionBlock.getAlreadyMutableContent();
321 {
reinterpret_cast<uint8_t *
>(SigningFunctionBuf.data()),
322 SigningFunctionBuf.size()},
325 auto AppendInstr = [&](
uint32_t Instr) {
329 for (
auto &Sec :
G.sections()) {
334 for (
auto *
B : Sec.blocks()) {
335 for (
auto &
E :
B->edges()) {
341 int32_t RealAddend = (
uint32_t)(EncodedInfo & 0xffffffff);
342 auto ValueToSign =
E.getTarget().getAddress() + RealAddend;
345 E.setAddend(RealAddend);
350 uint32_t InitialDiscriminator = (EncodedInfo >> 32) & 0xffff;
351 bool AddressDiversify = (EncodedInfo >> 48) & 0x1;
352 uint32_t Key = (EncodedInfo >> 49) & 0x3;
353 uint32_t HighBits = EncodedInfo >> 51;
355 if (HighBits != 0x1000)
356 return make_error<JITLinkError>(
357 "Pointer64Auth edge at " +
358 formatv(
"{0:x}",
B->getFixupAddress(
E).getValue()) +
359 " has invalid encoded addend " +
formatv(
"{0:x}", EncodedInfo));
362 const char *
const KeyNames[] = {
"IA",
"IB",
"DA",
"DB"};
363 dbgs() <<
" " <<
B->getFixupAddress(
E) <<
" <- " << ValueToSign
364 <<
" : key = " << KeyNames[Key] <<
", discriminator = "
365 <<
formatv(
"{0:x4}", InitialDiscriminator)
366 <<
", address diversified = "
367 << (AddressDiversify ?
"yes" :
"no") <<
"\n";
376 B->getFixupAddress(
E).getValue()));
380 Key, InitialDiscriminator, AddressDiversify));
386 E.setKind(Edge::KeepAlive);
392 constexpr uint32_t RETInstr = 0xd65f03c0;
398 using namespace orc::shared;
399 G.allocActions().push_back(
400 {
cantFail(WrapperFunctionCall::Create<SPSArgList<>>(
401 SigningFunctionSym.getAddress())),
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Provides write only access to a subclass of WritableBinaryStream.
Error writeInteger(T Value)
Write the integer Value to the underlying stream in the specified endianness.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
iterator_range< symbol_iterator > symbols()
Returns an iterator over the symbols defined in this section.
bool registerPreExistingEntry(Symbol &Target, Symbol &Entry)
Register a pre-existing entry.
LLVM_ABI void registerExistingEntries()
Represents an address in the executor process.
LLVM_ABI const char NullPointerContent[PointerSize]
AArch64 null pointer content.
static Error writeMovRegImm64Seq(AppendFtor &Append, uint64_t Reg, uint64_t Imm)
LLVM_ABI const char ReentryTrampolineContent[8]
AArch64 reentry trampoline.
static Error writeMovRegRegSeq(AppendFtor &Append, uint64_t DstReg, uint64_t SrcReg)
LLVM_ABI const char PointerJumpStubContent[12]
LLVM_ABI Error createEmptyPointerSigningFunction(LinkGraph &G)
Creates a pointer signing function section, block, and symbol to reserve space for a signing function...
LLVM_ABI Error lowerPointer64AuthEdgesToSigningFunction(LinkGraph &G)
Given a LinkGraph containing Pointer64Authenticated edges, transform those edges to Pointer64 and add...
LLVM_ABI const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given aarch64 edge.
LLVM_ABI const char * getPointerSigningFunctionSectionName()
Returns the name of the pointer signing function section.
static Error writeStoreRegSeq(AppendFtor &Append, unsigned DstLocReg, unsigned SrcReg)
@ LDRLiteral19
The signed 21-bit delta from the fixup to the target.
@ Pointer64Authenticated
An arm64e authenticated pointer relocation.
@ RequestGOTAndTransformToPageOffset15
A GOT entry getter/constructor, transformed to Pageoffset15 pointing at the GOT entry for the origina...
@ CondBranch19PCRel
A 19-bit PC-relative conditional branch.
@ RequestTLVPAndTransformToPageOffset12
A TLVP entry getter/constructor, transformed to PageOffset12.
@ RequestTLSDescEntryAndTransformToPageOffset12
A TLSDesc entry getter/constructor, transformed to PageOffset12.
@ Page21
The signed 21-bit delta from the fixup page to the page containing the target.
@ Branch26PCRel
A 26-bit PC-relative branch.
@ Pointer64
A plain 64-bit pointer value relocation.
@ Pointer32
A plain 32-bit pointer value relocation.
@ RequestTLVPAndTransformToPage21
A TLVP entry getter/constructor, transformed to Page21.
@ GotPageOffset15
The 15-bit offset of the GOT entry from the GOT table.
@ MoveWide16
A 16-bit slice of the target address (which slice depends on the instruction at the fixup location).
@ TestAndBranch14PCRel
A 14-bit PC-relative test and branch.
@ RequestGOTAndTransformToPage21
A GOT entry getter/constructor, transformed to Page21 pointing at the GOT entry for the original targ...
@ ADRLiteral21
The signed 21-bit delta from the fixup to the target.
@ RequestGOTAndTransformToPageOffset12
A GOT entry getter/constructor, transformed to Pageoffset12 pointing at the GOT entry for the origina...
@ NegDelta32
A 32-bit negative delta.
@ NegDelta64
A 64-bit negative delta.
@ RequestGOTAndTransformToDelta32
A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT entry for the original tar...
@ PageOffset12
The 12-bit (potentially shifted) offset of the target within its page.
@ RequestTLSDescEntryAndTransformToPage21
A TLSDesc entry getter/constructor, transformed to Page21.
static Error writePACSignSeq(AppendFtor &Append, unsigned DstReg, orc::ExecutorAddr RawAddr, unsigned RawAddrReg, unsigned DiscriminatorReg, unsigned Key, uint64_t EncodedDiscriminator, bool AddressDiversify)
LLVM_ABI const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
@ NoAlloc
NoAlloc memory should not be allocated by the JITLinkMemoryManager at all.
@ Finalize
Finalize memory should be allocated by the allocator, and then be overwritten and deallocated after a...
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.