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
52 return "Branch26PCRel";
56 return "LDRLiteral19";
58 return "TestAndBranch14PCRel";
60 return "CondBranch19PCRel";
62 return "ADRLiteral21";
66 return "PageOffset12";
68 return "GotPageOffset15";
70 return "RequestGOTAndTransformToPage21";
72 return "RequestGOTAndTransformToPageOffset12";
74 return "RequestGOTAndTransformToPageOffset15";
76 return "RequestGOTAndTransformToDelta32";
78 return "RequestTLVPAndTransformToPage21";
80 return "RequestTLVPAndTransformToPageOffset12";
82 return "RequestTLSDescEntryAndTransformToPage21";
84 return "RequestTLSDescEntryAndTransformToPageOffset12";
91template <
typename AppendFtor>
94 assert(DstReg < 32 &&
"Dst reg out of range");
95 assert(SrcReg < 32 &&
"Src reg out of range");
100 constexpr uint32_t MOVGPR64Template = 0xaa0003e0;
102 constexpr uint32_t SrcRegIndex = 16;
104 Instr |= DstReg << DstRegIndex;
105 Instr |= SrcReg << SrcRegIndex;
106 return Append(Instr);
110template <
typename AppendFtor>
113 assert(
Reg < 32 &&
"Invalid register number");
115 constexpr uint32_t MovRegImm64Template = 0xd2800000;
116 constexpr unsigned PreserveBitIndex = 29;
117 constexpr unsigned ShiftBitsIndex = 21;
118 constexpr unsigned ImmBitsIndex = 5;
120 bool PreserveRegValue =
false;
121 for (
unsigned I = 0;
I != 4; ++
I) {
126 if (PreserveRegValue && !ImmBits)
129 uint32_t Instr = MovRegImm64Template;
130 Instr |= PreserveRegValue << PreserveBitIndex;
131 Instr |= (
I << ShiftBitsIndex);
132 Instr |= ImmBits << ImmBitsIndex;
134 if (
auto Err = Append(Instr))
136 PreserveRegValue =
true;
142template <
typename AppendFtor>
145 unsigned RawAddrReg,
unsigned DiscriminatorReg,
unsigned Key,
146 uint64_t EncodedDiscriminator,
bool AddressDiversify) {
147 assert(DstReg < 32 &&
"DstReg out of range");
148 assert(RawAddrReg < 32 &&
"AddrReg out of range");
149 assert(DiscriminatorReg < 32 &&
"DiscriminatorReg out of range");
150 assert(EncodedDiscriminator < 0x10000 &&
"EncodedDiscriminator out of range");
152 if (AddressDiversify) {
157 if (EncodedDiscriminator) {
158 constexpr uint32_t MOVKTemplate = 0xf2e00000;
159 constexpr unsigned ImmIndex = 5;
161 BlendInstr |= EncodedDiscriminator << ImmIndex;
162 BlendInstr |= DiscriminatorReg;
163 if (
auto Err = Append(BlendInstr))
166 }
else if (EncodedDiscriminator) {
172 DiscriminatorReg = 31;
174 constexpr uint32_t PACTemplate = 0xdac10000;
175 constexpr unsigned ZBitIndex = 13;
176 constexpr unsigned KeyIndex = 10;
177 constexpr unsigned DiscriminatorRegIndex = 5;
180 Instr |= (DiscriminatorReg == 31) << ZBitIndex;
181 Instr |= Key << KeyIndex;
182 Instr |= DiscriminatorReg << DiscriminatorRegIndex;
185 return Append(Instr);
188template <
typename AppendFtor>
191 assert(DstLocReg < 32 &&
"DstLocReg out of range");
192 assert(SrcReg < 32 &&
"SrcReg out of range");
194 constexpr uint32_t STRTemplate = 0xf9000000;
195 constexpr unsigned DstLocRegIndex = 5;
196 constexpr unsigned SrcRegIndex = 0;
199 Instr |= DstLocReg << DstLocRegIndex;
200 Instr |= SrcReg << SrcRegIndex;
202 return Append(Instr);
205void GOTTableManager::registerExistingEntries() {
206 for (
auto *EntrySym : GOTSection->
symbols()) {
207 assert(EntrySym->getBlock().edges_size() == 1 &&
208 "GOT block edge count != 1");
216 assert(EntrySym->getBlock().edges_size() == 2 &&
217 "PLT block edge count != 2");
218 auto &GOTSym = EntrySym->getBlock().edges().begin()->getTarget();
219 assert(GOTSym.getBlock().edges_size() == 1 &&
"GOT block edge count != 1");
233 dbgs() <<
"Creating empty pointer signing function for " <<
G.getName()
240 size_t NumPtrAuthFixupLocations = 0;
241 for (
auto *
B :
G.blocks())
242 for (
auto &
E :
B->edges())
243 NumPtrAuthFixupLocations +=
246 constexpr size_t MaxPtrSignSeqLength =
255 size_t NumSigningInstrs = NumPtrAuthFixupLocations * MaxPtrSignSeqLength + 3;
258 auto &SigningSection =
263 size_t SigningFunctionSize = NumSigningInstrs * 4;
264 auto &SigningFunctionBlock =
G.createMutableContentBlock(
265 SigningSection,
G.allocateBuffer(SigningFunctionSize),
267 G.addAnonymousSymbol(SigningFunctionBlock, 0, SigningFunctionBlock.getSize(),
271 dbgs() <<
" " << NumPtrAuthFixupLocations <<
" location(s) to sign, up to "
272 << NumSigningInstrs <<
" instructions required ("
273 <<
formatv(
"{0:x}", SigningFunctionBlock.getSize()) <<
" bytes)\n";
287 dbgs() <<
"Writing pointer signing function for " <<
G.getName() <<
"\n";
290 constexpr unsigned Reg1 = 8;
291 constexpr unsigned Reg2 = 9;
292 constexpr unsigned Reg3 = 10;
295 auto *SigningSection =
297 assert(SigningSection &&
"Siging section missing");
298 assert(SigningSection->blocks_size() == 1 &&
299 "Unexpected number of blocks in signing section");
300 assert(SigningSection->symbols_size() == 1 &&
301 "Unexpected number of symbols in signing section");
303 auto &SigningFunctionSym = **SigningSection->symbols().begin();
304 auto &SigningFunctionBlock = SigningFunctionSym.getBlock();
305 auto SigningFunctionBuf = SigningFunctionBlock.getAlreadyMutableContent();
309 {
reinterpret_cast<uint8_t *
>(SigningFunctionBuf.data()),
310 SigningFunctionBuf.size()},
313 auto AppendInstr = [&](
uint32_t Instr) {
317 for (
auto *
B :
G.blocks()) {
318 for (
auto EI =
B->edges().begin(); EI !=
B->edges().end();) {
322 int32_t RealAddend = (
uint32_t)(EncodedInfo & 0xffffffff);
323 uint32_t InitialDiscriminator = (EncodedInfo >> 32) & 0xffff;
324 bool AddressDiversify = (EncodedInfo >> 48) & 0x1;
325 uint32_t Key = (EncodedInfo >> 49) & 0x3;
326 uint32_t HighBits = EncodedInfo >> 51;
327 auto ValueToSign =
E.getTarget().getAddress() + RealAddend;
329 if (HighBits != 0x1000)
330 return make_error<JITLinkError>(
331 "Pointer64Auth edge at " +
332 formatv(
"{0:x}",
B->getFixupAddress(
E).getValue()) +
333 " has invalid encoded addend " +
formatv(
"{0:x}", EncodedInfo));
336 const char *
const KeyNames[] = {
"IA",
"IB",
"DA",
"DB"};
339 dbgs() <<
" " <<
B->getFixupAddress(
E) <<
" <- " << ValueToSign
340 <<
" : key = " << KeyNames[Key] <<
", discriminator = "
341 <<
formatv(
"{0:x4}", InitialDiscriminator)
342 <<
", address diversified = "
343 << (AddressDiversify ?
"yes" :
"no") <<
"\n";
352 B->getFixupAddress(
E).getValue()));
356 Key, InitialDiscriminator, AddressDiversify));
362 EI =
B->removeEdge(EI);
369 constexpr uint32_t RETInstr = 0xd65f03c0;
375 using namespace orc::shared;
376 G.allocActions().push_back(
377 {
cantFail(WrapperFunctionCall::Create<SPSArgList<>>(
378 SigningFunctionSym.getAddress())),
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
void registerExistingEntries()
Represents an address in the executor process.
const char NullPointerContent[PointerSize]
AArch64 null pointer content.
static Error writeMovRegImm64Seq(AppendFtor &Append, uint64_t Reg, uint64_t Imm)
const char ReentryTrampolineContent[8]
AArch64 reentry trampoline.
static Error writeMovRegRegSeq(AppendFtor &Append, uint64_t DstReg, uint64_t SrcReg)
const char PointerJumpStubContent[12]
Error createEmptyPointerSigningFunction(LinkGraph &G)
Creates a pointer signing function section, block, and symbol to reserve space for a signing function...
Error lowerPointer64AuthEdgesToSigningFunction(LinkGraph &G)
Given a LinkGraph containing Pointer64Authenticated edges, transform those edges to Pointer64 and add...
const char * getEdgeKindName(Edge::Kind K)
Returns a string name for the given aarch64 edge.
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)
const char * getGenericEdgeKindName(Edge::Kind K)
Returns the string name of the given generic edge kind, or "unknown" otherwise.
@ 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)
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.