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);
213 dbgs() <<
"Creating empty pointer signing function for " <<
G.getName()
220 size_t NumPtrAuthFixupLocations = 0;
221 for (
auto *
B :
G.blocks())
222 for (
auto &
E :
B->edges())
223 NumPtrAuthFixupLocations +=
226 constexpr size_t MaxPtrSignSeqLength =
235 size_t NumSigningInstrs = NumPtrAuthFixupLocations * MaxPtrSignSeqLength + 3;
238 auto &SigningSection =
243 size_t SigningFunctionSize = NumSigningInstrs * 4;
244 auto &SigningFunctionBlock =
G.createMutableContentBlock(
245 SigningSection,
G.allocateBuffer(SigningFunctionSize),
247 G.addAnonymousSymbol(SigningFunctionBlock, 0, SigningFunctionBlock.getSize(),
251 dbgs() <<
" " << NumPtrAuthFixupLocations <<
" location(s) to sign, up to "
252 << NumSigningInstrs <<
" instructions required ("
253 <<
formatv(
"{0:x}", SigningFunctionBlock.getSize()) <<
" bytes)\n";
267 dbgs() <<
"Writing pointer signing function for " <<
G.getName() <<
"\n";
270 constexpr unsigned Reg1 = 8;
271 constexpr unsigned Reg2 = 9;
272 constexpr unsigned Reg3 = 10;
275 auto *SigningSection =
277 assert(SigningSection &&
"Siging section missing");
278 assert(SigningSection->blocks_size() == 1 &&
279 "Unexpected number of blocks in signing section");
280 assert(SigningSection->symbols_size() == 1 &&
281 "Unexpected number of symbols in signing section");
283 auto &SigningFunctionSym = **SigningSection->symbols().begin();
284 auto &SigningFunctionBlock = SigningFunctionSym.getBlock();
285 auto SigningFunctionBuf = SigningFunctionBlock.getAlreadyMutableContent();
289 {
reinterpret_cast<uint8_t *
>(SigningFunctionBuf.data()),
290 SigningFunctionBuf.size()},
293 auto AppendInstr = [&](
uint32_t Instr) {
297 for (
auto *
B :
G.blocks()) {
298 for (
auto EI =
B->edges().begin(); EI !=
B->edges().end();) {
302 int32_t RealAddend = (
uint32_t)(EncodedInfo & 0xffffffff);
303 uint32_t InitialDiscriminator = (EncodedInfo >> 32) & 0xffff;
304 bool AddressDiversify = (EncodedInfo >> 48) & 0x1;
305 uint32_t Key = (EncodedInfo >> 49) & 0x3;
306 uint32_t HighBits = EncodedInfo >> 51;
307 auto ValueToSign =
E.getTarget().getAddress() + RealAddend;
309 if (HighBits != 0x1000)
310 return make_error<JITLinkError>(
311 "Pointer64Auth edge at " +
312 formatv(
"{0:x}",
B->getFixupAddress(
E).getValue()) +
313 " has invalid encoded addend " +
formatv(
"{0:x}", EncodedInfo));
316 const char *
const KeyNames[] = {
"IA",
"IB",
"DA",
"DB"};
319 dbgs() <<
" " <<
B->getFixupAddress(
E) <<
" <- " << ValueToSign
320 <<
" : key = " << KeyNames[Key] <<
", discriminator = "
321 <<
formatv(
"{0:x4}", InitialDiscriminator)
322 <<
", address diversified = "
323 << (AddressDiversify ?
"yes" :
"no") <<
"\n";
332 B->getFixupAddress(
E).getValue()));
336 Key, InitialDiscriminator, AddressDiversify));
342 EI =
B->removeEdge(EI);
349 constexpr uint32_t RETInstr = 0xd65f03c0;
355 using namespace orc::shared;
356 G.allocActions().push_back(
357 {
cantFail(WrapperFunctionCall::Create<SPSArgList<>>(
358 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.
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.