LLVM: lib/ExecutionEngine/JITLink/aarch64.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

14

16

17#define DEBUG_TYPE "jitlink"

18

19namespace llvm {

20namespace jitlink {

21namespace aarch64 {

22

24 0x00, 0x00, 0x00, 0x00};

25

27 0x10, 0x00, 0x00, (char)0x90u,

28 0x10, 0x02, 0x40, (char)0xf9u,

29 0x00, 0x02, 0x1f, (char)0xd6u

30};

31

33 (char)0xfd, 0x7b, (char)0xbf, (char)0xa9,

34 0x00, 0x00, 0x00, (char)0x94

35};

36

38 switch (R) {

40 return "Pointer64";

42 return "Pointer64Authenticated";

44 return "Pointer32";

46 return "Delta64";

48 return "Delta32";

50 return "NegDelta64";

52 return "NegDelta32";

54 return "Branch26PCRel";

56 return "MoveWide16";

58 return "LDRLiteral19";

60 return "TestAndBranch14PCRel";

62 return "CondBranch19PCRel";

64 return "ADRLiteral21";

66 return "Page21";

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";

87 default:

89 }

90}

91

92

93template

96 assert(DstReg < 32 && "Dst reg out of range");

97 assert(SrcReg < 32 && "Src reg out of range");

98

99 if (DstReg == SrcReg)

101

102 constexpr uint32_t MOVGPR64Template = 0xaa0003e0;

103 constexpr uint32_t DstRegIndex = 0;

104 constexpr uint32_t SrcRegIndex = 16;

105 uint32_t Instr = MOVGPR64Template;

106 Instr |= DstReg << DstRegIndex;

107 Instr |= SrcReg << SrcRegIndex;

108 return Append(Instr);

109}

110

111

112template

115 assert(Reg < 32 && "Invalid register number");

116

117 constexpr uint32_t MovRegImm64Template = 0xd2800000;

118 constexpr unsigned PreserveBitIndex = 29;

119 constexpr unsigned ShiftBitsIndex = 21;

120 constexpr unsigned ImmBitsIndex = 5;

121

122 bool PreserveRegValue = false;

123 for (unsigned I = 0; I != 4; ++I) {

124 uint32_t ImmBits = Imm & 0xffff;

125 Imm >>= 16;

126

127

128 if (PreserveRegValue && !ImmBits)

129 continue;

130

131 uint32_t Instr = MovRegImm64Template;

132 Instr |= PreserveRegValue << PreserveBitIndex;

133 Instr |= (I << ShiftBitsIndex);

134 Instr |= ImmBits << ImmBitsIndex;

135 Instr |= Reg;

136 if (auto Err = Append(Instr))

137 return Err;

138 PreserveRegValue = true;

139 }

140

142}

143

144template

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");

153

154 if (AddressDiversify) {

155

156 if (auto Err = writeMovRegRegSeq(Append, DiscriminatorReg, RawAddrReg))

157 return Err;

158

159 if (EncodedDiscriminator) {

160 constexpr uint32_t MOVKTemplate = 0xf2e00000;

161 constexpr unsigned ImmIndex = 5;

162 uint32_t BlendInstr = MOVKTemplate;

163 BlendInstr |= EncodedDiscriminator << ImmIndex;

164 BlendInstr |= DiscriminatorReg;

165 if (auto Err = Append(BlendInstr))

166 return Err;

167 }

168 } else if (EncodedDiscriminator) {

169

170 if (auto Err =

172 return Err;

173 } else

174 DiscriminatorReg = 31;

175

176 constexpr uint32_t PACTemplate = 0xdac10000;

177 constexpr unsigned ZBitIndex = 13;

178 constexpr unsigned KeyIndex = 10;

179 constexpr unsigned DiscriminatorRegIndex = 5;

180

181 uint32_t Instr = PACTemplate;

182 Instr |= (DiscriminatorReg == 31) << ZBitIndex;

183 Instr |= Key << KeyIndex;

184 Instr |= DiscriminatorReg << DiscriminatorRegIndex;

185 Instr |= DstReg;

186

187 return Append(Instr);

188}

189

190template

192 unsigned SrcReg) {

193 assert(DstLocReg < 32 && "DstLocReg out of range");

194 assert(SrcReg < 32 && "SrcReg out of range");

195

196 constexpr uint32_t STRTemplate = 0xf9000000;

197 constexpr unsigned DstLocRegIndex = 5;

198 constexpr unsigned SrcRegIndex = 0;

199

200 uint32_t Instr = STRTemplate;

201 Instr |= DstLocReg << DstLocRegIndex;

202 Instr |= SrcReg << SrcRegIndex;

203

204 return Append(Instr);

205}

206

207void GOTTableManager::registerExistingEntries() {

208 for (auto *EntrySym : GOTSection->symbols()) {

209 assert(EntrySym->getBlock().edges_size() == 1 &&

210 "GOT block edge count != 1");

212 *EntrySym);

213 }

214}

215

217 for (auto *EntrySym : StubsSection->symbols()) {

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");

223 *EntrySym);

224 }

225}

226

228

229

230

231

232

235 dbgs() << "Creating empty pointer signing function for " << G.getName()

236 << "\n";

237 });

238

239

240

241

242 size_t NumPtrAuthFixupLocations = 0;

243 for (auto &Sec : G.sections()) {

244

245

246

247

249 continue;

250

251 for (auto *B : Sec.blocks()) {

252 for (auto &E : B->edges())

253 NumPtrAuthFixupLocations +=

255 }

256 }

257

258 constexpr size_t MaxPtrSignSeqLength =

259 4 +

260 4 +

261 3 +

262 1;

263

264

265

266

267 size_t NumSigningInstrs = NumPtrAuthFixupLocations * MaxPtrSignSeqLength + 3;

268

269

270 auto &SigningSection =

274

275 size_t SigningFunctionSize = NumSigningInstrs * 4;

276 auto &SigningFunctionBlock = G.createMutableContentBlock(

277 SigningSection, G.allocateBuffer(SigningFunctionSize),

279 G.addAnonymousSymbol(SigningFunctionBlock, 0, SigningFunctionBlock.getSize(),

280 true, true);

281

283 dbgs() << " " << NumPtrAuthFixupLocations << " location(s) to sign, up to "

284 << NumSigningInstrs << " instructions required ("

285 << formatv("{0:x}", SigningFunctionBlock.getSize()) << " bytes)\n";

286 });

287

289}

290

291

292

293

294

295

296

299 dbgs() << "Writing pointer signing function for " << G.getName() << "\n";

300 });

301

302 constexpr unsigned Reg1 = 8;

303 constexpr unsigned Reg2 = 9;

304 constexpr unsigned Reg3 = 10;

305

306

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");

314

315 auto &SigningFunctionSym = **SigningSection->symbols().begin();

316 auto &SigningFunctionBlock = SigningFunctionSym.getBlock();

317 auto SigningFunctionBuf = SigningFunctionBlock.getAlreadyMutableContent();

318

319

321 {reinterpret_cast<uint8_t *>(SigningFunctionBuf.data()),

322 SigningFunctionBuf.size()},

323 G.getEndianness());

324

325 auto AppendInstr = [&](uint32_t Instr) {

327 };

328

329 for (auto &Sec : G.sections()) {

330

332 continue;

333

334 for (auto *B : Sec.blocks()) {

335 for (auto &E : B->edges()) {

336

338 continue;

339

340 uint64_t EncodedInfo = E.getAddend();

341 int32_t RealAddend = (uint32_t)(EncodedInfo & 0xffffffff);

342 auto ValueToSign = E.getTarget().getAddress() + RealAddend;

343 if (!ValueToSign) {

344 LLVM_DEBUG(dbgs() << " " << B->getFixupAddress(E) << " <- null\n");

345 E.setAddend(RealAddend);

347 continue;

348 }

349

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;

354

355 if (HighBits != 0x1000)

357 "Pointer64Auth edge at " +

358 formatv("{0:x}", B->getFixupAddress(E).getValue()) +

359 " has invalid encoded addend " + formatv("{0:x}", EncodedInfo));

360

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";

368 });

369

370

373

374

376 B->getFixupAddress(E).getValue()));

377

378

380 Key, InitialDiscriminator, AddressDiversify));

381

382

384

385

386 E.setKind(Edge::KeepAlive);

387 }

388 }

389 }

390

391

392 constexpr uint32_t RETInstr = 0xd65f03c0;

395 cantFail(AppendInstr(RETInstr));

396

397

399 G.allocActions().push_back(

400 {cantFail(WrapperFunctionCall::Create<SPSArgList<>>(

401 SigningFunctionSym.getAddress())),

402 {}});

403

405}

406

407}

408}

409}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-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)

LLVM_ABI void registerExistingEntries()

Definition aarch64.cpp:216

Represents an address in the executor process.

LLVM_ABI const char NullPointerContent[PointerSize]

AArch64 null pointer content.

Definition aarch64.cpp:23

static Error writeMovRegImm64Seq(AppendFtor &Append, uint64_t Reg, uint64_t Imm)

Definition aarch64.cpp:113

LLVM_ABI const char ReentryTrampolineContent[8]

AArch64 reentry trampoline.

Definition aarch64.cpp:32

static Error writeMovRegRegSeq(AppendFtor &Append, uint64_t DstReg, uint64_t SrcReg)

Definition aarch64.cpp:94

LLVM_ABI const char PointerJumpStubContent[12]

Definition aarch64.cpp:26

LLVM_ABI Error createEmptyPointerSigningFunction(LinkGraph &G)

Creates a pointer signing function section, block, and symbol to reserve space for a signing function...

Definition aarch64.cpp:233

LLVM_ABI Error lowerPointer64AuthEdgesToSigningFunction(LinkGraph &G)

Given a LinkGraph containing Pointer64Authenticated edges, transform those edges to Pointer64 and add...

Definition aarch64.cpp:297

LLVM_ABI const char * getEdgeKindName(Edge::Kind K)

Returns a string name for the given aarch64 edge.

Definition aarch64.cpp:37

LLVM_ABI const char * getPointerSigningFunctionSectionName()

Returns the name of the pointer signing function section.

Definition aarch64.cpp:227

static Error writeStoreRegSeq(AppendFtor &Append, unsigned DstLocReg, unsigned SrcReg)

Definition aarch64.cpp:191

@ 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)

Definition aarch64.cpp:146

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.

LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

void cantFail(Error Err, const char *Msg=nullptr)

Report a fatal error if Err is a failure value.