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 *
B :
G.blocks())
244 for (
auto &
E :
B->edges())
245 NumPtrAuthFixupLocations +=
248 constexpr size_t MaxPtrSignSeqLength =
257 size_t NumSigningInstrs = NumPtrAuthFixupLocations * MaxPtrSignSeqLength + 3;
260 auto &SigningSection =
265 size_t SigningFunctionSize = NumSigningInstrs * 4;
266 auto &SigningFunctionBlock =
G.createMutableContentBlock(
267 SigningSection,
G.allocateBuffer(SigningFunctionSize),
269 G.addAnonymousSymbol(SigningFunctionBlock, 0, SigningFunctionBlock.getSize(),
273 dbgs() <<
" " << NumPtrAuthFixupLocations <<
" location(s) to sign, up to "
274 << NumSigningInstrs <<
" instructions required ("
275 <<
formatv(
"{0:x}", SigningFunctionBlock.getSize()) <<
" bytes)\n";
289 dbgs() <<
"Writing pointer signing function for " <<
G.getName() <<
"\n";
292 constexpr unsigned Reg1 = 8;
293 constexpr unsigned Reg2 = 9;
294 constexpr unsigned Reg3 = 10;
297 auto *SigningSection =
299 assert(SigningSection &&
"Siging section missing");
300 assert(SigningSection->blocks_size() == 1 &&
301 "Unexpected number of blocks in signing section");
302 assert(SigningSection->symbols_size() == 1 &&
303 "Unexpected number of symbols in signing section");
305 auto &SigningFunctionSym = **SigningSection->symbols().begin();
306 auto &SigningFunctionBlock = SigningFunctionSym.getBlock();
307 auto SigningFunctionBuf = SigningFunctionBlock.getAlreadyMutableContent();
311 {
reinterpret_cast<uint8_t *
>(SigningFunctionBuf.data()),
312 SigningFunctionBuf.size()},
315 auto AppendInstr = [&](
uint32_t Instr) {
319 for (
auto *
B :
G.blocks()) {
320 for (
auto &
E :
B->edges()) {
326 int32_t RealAddend = (
uint32_t)(EncodedInfo & 0xffffffff);
327 uint32_t InitialDiscriminator = (EncodedInfo >> 32) & 0xffff;
328 bool AddressDiversify = (EncodedInfo >> 48) & 0x1;
329 uint32_t Key = (EncodedInfo >> 49) & 0x3;
330 uint32_t HighBits = EncodedInfo >> 51;
331 auto ValueToSign =
E.getTarget().getAddress() + RealAddend;
333 if (HighBits != 0x1000)
334 return make_error<JITLinkError>(
335 "Pointer64Auth edge at " +
336 formatv(
"{0:x}",
B->getFixupAddress(
E).getValue()) +
337 " has invalid encoded addend " +
formatv(
"{0:x}", EncodedInfo));
340 const char *
const KeyNames[] = {
"IA",
"IB",
"DA",
"DB"};
341 dbgs() <<
" " <<
B->getFixupAddress(
E) <<
" <- " << ValueToSign
342 <<
" : key = " << KeyNames[Key] <<
", discriminator = "
343 <<
formatv(
"{0:x4}", InitialDiscriminator)
344 <<
", address diversified = "
345 << (AddressDiversify ?
"yes" :
"no") <<
"\n";
353 B->getFixupAddress(
E).getValue()));
357 InitialDiscriminator, AddressDiversify));
368 constexpr uint32_t RETInstr = 0xd65f03c0;
374 using namespace orc::shared;
375 G.allocActions().push_back(
376 {
cantFail(WrapperFunctionCall::Create<SPSArgList<>>(
377 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.