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

1

2

3

4

5

6

7

8

9

10

11

12

17

21

22#define DEBUG_TYPE "jitlink"

23

24using namespace llvm;

26

27namespace {

28

30public:

32 std::shared_ptrorc::SymbolStringPool SSP,

35 Triple("x86_64-apple-darwin"),

37

38private:

39 enum MachONormalizedRelocationType : unsigned {

40 MachOBranch32,

41 MachOPointer32,

42 MachOPointer64,

43 MachOPointer64Anon,

44 MachOPCRel32,

45 MachOPCRel32Minus1,

46 MachOPCRel32Minus2,

47 MachOPCRel32Minus4,

48 MachOPCRel32Anon,

49 MachOPCRel32Minus1Anon,

50 MachOPCRel32Minus2Anon,

51 MachOPCRel32Minus4Anon,

52 MachOPCRel32GOTLoad,

53 MachOPCRel32GOT,

54 MachOPCRel32TLV,

55 MachOSubtractor32,

56 MachOSubtractor64,

57 };

58

65 return RI.r_extern ? MachOPointer64 : MachOPointer64Anon;

67 return MachOPointer32;

68 }

69 break;

72 return RI.r_extern ? MachOPCRel32 : MachOPCRel32Anon;

73 break;

76 return MachOBranch32;

77 break;

80 return MachOPCRel32GOTLoad;

81 break;

84 return MachOPCRel32GOT;

85 break;

89 return MachOSubtractor32;

91 return MachOSubtractor64;

92 }

93 break;

96 return RI.r_extern ? MachOPCRel32Minus1 : MachOPCRel32Minus1Anon;

97 break;

100 return RI.r_extern ? MachOPCRel32Minus2 : MachOPCRel32Minus2Anon;

101 break;

104 return RI.r_extern ? MachOPCRel32Minus4 : MachOPCRel32Minus4Anon;

105 break;

108 return MachOPCRel32TLV;

109 break;

110 }

111

113 "Unsupported x86-64 relocation: address=" +

117 ", pc_rel=" + (RI.r_pcrel ? "true" : "false") +

118 ", extern=" + (RI.r_extern ? "true" : "false") +

120 }

121

122 using PairRelocInfo = std::tuple<Edge::Kind, Symbol *, uint64_t>;

123

124

125

127 Block &BlockToFix, MachONormalizedRelocationType SubtractorKind,

132

133 assert(((SubtractorKind == MachOSubtractor32 && SubRI.r_length == 2) ||

134 (SubtractorKind == MachOSubtractor64 && SubRI.r_length == 3)) &&

135 "Subtractor kind should match length");

136 assert(SubRI.r_extern && "SUBTRACTOR reloc symbol should be extern");

137 assert(!SubRI.r_pcrel && "SUBTRACTOR reloc should not be PCRel");

138

139 if (UnsignedRelItr == RelEnd)

141 "UNSIGNED relocation");

142

143 auto UnsignedRI = getRelocationInfo(UnsignedRelItr);

144

145 if (SubRI.r_address != UnsignedRI.r_address)

147 "point to different addresses");

148

149 if (SubRI.r_length != UnsignedRI.r_length)

151 "UNSIGNED reloc must match");

152

154 if (auto FromSymbolOrErr = findSymbolByIndex(SubRI.r_symbolnum))

155 FromSymbol = FromSymbolOrErr->GraphSymbol;

156 else

157 return FromSymbolOrErr.takeError();

158

159

162 FixupValue = *(const little64_t *)FixupContent;

163 else

164 FixupValue = *(const little32_t *)FixupContent;

165

166

167

168 Symbol *ToSymbol = nullptr;

169 if (UnsignedRI.r_extern) {

170

171 if (auto ToSymbolOrErr = findSymbolByIndex(UnsignedRI.r_symbolnum))

172 ToSymbol = ToSymbolOrErr->GraphSymbol;

173 else

174 return ToSymbolOrErr.takeError();

175 } else {

176 auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1);

177 if (!ToSymbolSec)

178 return ToSymbolSec.takeError();

179 ToSymbol = getSymbolByAddress(*ToSymbolSec, ToSymbolSec->Address);

180 assert(ToSymbol && "No symbol for section");

182 }

183

184 Edge::Kind DeltaKind;

185 Symbol *TargetSymbol;

187

188 bool FixingFromSymbol = true;

191

192

193 if (ToSymbol->getAddress() > FixupAddress)

194 FixingFromSymbol = true;

195 else if (FromSymbol->getAddress() > FixupAddress)

196 FixingFromSymbol = false;

197 else

199 } else

200 FixingFromSymbol = true;

201 } else {

203 FixingFromSymbol = false;

204 else {

205

207 "either 'A' or 'B' (or a symbol in one "

208 "of their alt-entry groups)");

209 }

210 }

211

212 if (FixingFromSymbol) {

213 TargetSymbol = ToSymbol;

215 Addend = FixupValue + (FixupAddress - FromSymbol->getAddress());

216

217 } else {

218 TargetSymbol = FromSymbol;

219 DeltaKind =

221 Addend = FixupValue - (FixupAddress - ToSymbol->getAddress());

222 }

223

224 return PairRelocInfo(DeltaKind, TargetSymbol, Addend);

225 }

226

227 Error addRelocations() override {

230

232

233 for (const auto &S : Obj.sections()) {

234

236

237

238 if (S.isVirtual()) {

239 if (!S.relocations().empty())

241 "relocations");

242 continue;

243 }

244

245 auto NSec =

246 findSectionByIndex(Obj.getSectionIndex(S.getRawDataRefImpl()));

247 if (!NSec)

248 return NSec.takeError();

249

250

251

252 {

253 if (!NSec->GraphSection) {

255 dbgs() << " Skipping relocations for MachO section "

256 << NSec->SegName << "/" << NSec->SectName

257 << " which has no associated graph section\n";

258 });

259 continue;

260 }

261 }

262

263

264 for (auto RelItr = S.relocation_begin(), RelEnd = S.relocation_end();

265 RelItr != RelEnd; ++RelItr) {

266

268

269

271

273 dbgs() << " " << NSec->SectName << " + "

275 });

276

277

278 Block *BlockToFix = nullptr;

279 {

280 auto SymbolToFixOrErr = findSymbolByAddress(*NSec, FixupAddress);

281 if (!SymbolToFixOrErr)

282 return SymbolToFixOrErr.takeError();

283 BlockToFix = &SymbolToFixOrErr->getBlock();

284 }

285

287 BlockToFix->getAddress() + BlockToFix->getContent().size())

289 "Relocation extends past end of fixup block");

290

291

292 const char *FixupContent = BlockToFix->getContent().data() +

293 (FixupAddress - BlockToFix->getAddress());

294

295 size_t FixupOffset = FixupAddress - BlockToFix->getAddress();

296

297

298 Symbol *TargetSymbol = nullptr;

300

301

302 auto MachORelocKind = getRelocKind(RI);

303 if (!MachORelocKind)

304 return MachORelocKind.takeError();

305

306 Edge::Kind Kind = Edge::Invalid;

307

308 switch (*MachORelocKind) {

309 case MachOBranch32:

310 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))

311 TargetSymbol = TargetSymbolOrErr->GraphSymbol;

312 else

313 return TargetSymbolOrErr.takeError();

314 Addend = *(const little32_t *)FixupContent;

316 break;

317 case MachOPCRel32:

318 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))

319 TargetSymbol = TargetSymbolOrErr->GraphSymbol;

320 else

321 return TargetSymbolOrErr.takeError();

322 Addend = *(const little32_t *)FixupContent - 4;

324 break;

325 case MachOPCRel32GOTLoad:

326 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))

327 TargetSymbol = TargetSymbolOrErr->GraphSymbol;

328 else

329 return TargetSymbolOrErr.takeError();

330 Addend = *(const little32_t *)FixupContent;

332 if (FixupOffset < 3)

334 formatv("{0}", FixupOffset));

335 break;

336 case MachOPCRel32GOT:

337 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))

338 TargetSymbol = TargetSymbolOrErr->GraphSymbol;

339 else

340 return TargetSymbolOrErr.takeError();

341 Addend = *(const little32_t *)FixupContent - 4;

343 break;

344 case MachOPCRel32TLV:

345 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))

346 TargetSymbol = TargetSymbolOrErr->GraphSymbol;

347 else

348 return TargetSymbolOrErr.takeError();

349 Addend = *(const little32_t *)FixupContent;

351 if (FixupOffset < 3)

353 formatv("{0}", FixupOffset));

354 break;

355 case MachOPointer32:

356 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))

357 TargetSymbol = TargetSymbolOrErr->GraphSymbol;

358 else

359 return TargetSymbolOrErr.takeError();

360 Addend = *(const ulittle32_t *)FixupContent;

362 break;

363 case MachOPointer64:

364 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))

365 TargetSymbol = TargetSymbolOrErr->GraphSymbol;

366 else

367 return TargetSymbolOrErr.takeError();

368 Addend = *(const ulittle64_t *)FixupContent;

370 break;

371 case MachOPointer64Anon: {

372 orc::ExecutorAddr TargetAddress(*(const ulittle64_t *)FixupContent);

373 auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);

374 if (!TargetNSec)

375 return TargetNSec.takeError();

376 if (auto TargetSymbolOrErr =

377 findSymbolByAddress(*TargetNSec, TargetAddress))

378 TargetSymbol = &*TargetSymbolOrErr;

379 else

380 return TargetSymbolOrErr.takeError();

381 Addend = TargetAddress - TargetSymbol->getAddress();

383 break;

384 }

385 case MachOPCRel32Minus1:

386 case MachOPCRel32Minus2:

387 case MachOPCRel32Minus4:

388 if (auto TargetSymbolOrErr = findSymbolByIndex(RI.r_symbolnum))

389 TargetSymbol = TargetSymbolOrErr->GraphSymbol;

390 else

391 return TargetSymbolOrErr.takeError();

392 Addend = *(const little32_t *)FixupContent - 4;

394 break;

395 case MachOPCRel32Anon: {

397 *(const little32_t *)FixupContent);

398 auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);

399 if (!TargetNSec)

400 return TargetNSec.takeError();

401 if (auto TargetSymbolOrErr =

402 findSymbolByAddress(*TargetNSec, TargetAddress))

403 TargetSymbol = &*TargetSymbolOrErr;

404 else

405 return TargetSymbolOrErr.takeError();

406 Addend = TargetAddress - TargetSymbol->getAddress() - 4;

408 break;

409 }

410 case MachOPCRel32Minus1Anon:

411 case MachOPCRel32Minus2Anon:

412 case MachOPCRel32Minus4Anon: {

415 1ULL << (*MachORelocKind - MachOPCRel32Minus1Anon));

417 FixupAddress + Delta + *(const little32_t *)FixupContent;

418 auto TargetNSec = findSectionByIndex(RI.r_symbolnum - 1);

419 if (!TargetNSec)

420 return TargetNSec.takeError();

421 if (auto TargetSymbolOrErr =

422 findSymbolByAddress(*TargetNSec, TargetAddress))

423 TargetSymbol = &*TargetSymbolOrErr;

424 else

425 return TargetSymbolOrErr.takeError();

426 Addend = TargetAddress - TargetSymbol->getAddress() - Delta;

428 break;

429 }

430 case MachOSubtractor32:

431 case MachOSubtractor64: {

432

433

434

435

436

437 auto PairInfo =

438 parsePairRelocation(*BlockToFix, *MachORelocKind, RI,

439 FixupAddress, FixupContent, ++RelItr, RelEnd);

440 if (!PairInfo)

441 return PairInfo.takeError();

442 std::tie(Kind, TargetSymbol, Addend) = *PairInfo;

443 assert(TargetSymbol && "No target symbol from parsePairRelocation?");

444 break;

445 }

446 }

447

449 dbgs() << " ";

450 Edge GE(Kind, FixupAddress - BlockToFix->getAddress(), *TargetSymbol,

451 Addend);

453 dbgs() << "\n";

454 });

455 BlockToFix->addEdge(Kind, FixupAddress - BlockToFix->getAddress(),

456 *TargetSymbol, Addend);

457 }

458 }

460 }

461};

462

468}

469

470}

471

472namespace llvm {

474

477

478public:

480 std::unique_ptr G,

483

484private:

487 }

488};

489

491 MemoryBufferRef ObjectBuffer, std::shared_ptrorc::SymbolStringPool SSP) {

493 if (!MachOObj)

494 return MachOObj.takeError();

495

496 auto Features = (*MachOObj)->getFeatures();

497 if (!Features)

498 return Features.takeError();

499

500 return MachOLinkGraphBuilder_x86_64(**MachOObj, std::move(SSP),

501 std::move(*Features))

502 .buildGraph();

503}

504

507 8> {

508

509

510

511

513

516

518

520 constexpr uint32_t DWARFMode = 0x04000000;

522 }

523

525 constexpr uint32_t StackIndirectMode = 0x03000000;

527 }

528};

529

531 std::unique_ptr Ctx) {

532

534

535 if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {

536

537 if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))

538 Config.PrePrunePasses.push_back(std::move(MarkLive));

539 else

541

542

545

546

547 auto CompactUnwindMgr = std::make_shared<

551

552

554 return CompactUnwindMgr->prepareForPrune(G);

555 });

556

557

561

562

563 Config.PostPrunePasses.push_back(buildGOTAndStubs_MachO_x86_64);

564

565

567 return CompactUnwindMgr->processAndReserveUnwindInfo(G);

568 });

569

570

572 return CompactUnwindMgr->writeUnwindInfo(G);

573 });

574

575

577 }

578

579 if (auto Err = Ctx->modifyPassConfig(*G, Config))

580 return Ctx->notifyFailed(std::move(Err));

581

582

584}

585

589

594}

595

596}

597}

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

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static Error getObject(const T *&Obj, MemoryBufferRef M, const void *Ptr, const uint64_t Size=sizeof(T))

#define LLVM_UNLIKELY(EXPR)

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Manages the enabling and disabling of subtarget specific features.

Triple - Helper class for working with autoconf configuration names.

An Addressable with content and edges.

Architecture specific implementation of CompactUnwindManager.

A LinkGraph pass that splits blocks in a section that follows the DWARF Record format into sub-blocks...

A LinkGraph pass that adds missing FDE-to-CIE, FDE-to-PC and FDE-to-LSDA edges.

Represents fixups and constraints in the LinkGraph.

static void link(ArgTs &&... Args)

MachOJITLinker_x86_64(std::unique_ptr< JITLinkContext > Ctx, std::unique_ptr< LinkGraph > G, PassConfiguration PassConfig)

Definition MachO_x86_64.cpp:479

Addressable & getAddressable()

Return the addressable that this symbol points to.

orc::ExecutorAddr getAddress() const

Returns the address of this symbol.

Global Offset Table Builder.

Procedure Linkage Table Builder.

static Expected< std::unique_ptr< MachOObjectFile > > createMachOObjectFile(MemoryBufferRef Object, uint32_t UniversalCputype=0, uint32_t UniversalIndex=0, size_t MachOFilesetEntryOffset=0)

Create a MachOObjectFile instance from a given buffer.

Represents an address in the executor process.

uint64_t getValue() const

@ X86_64_RELOC_SUBTRACTOR

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

Returns a string name for the given x86-64 edge.

Error applyFixup(LinkGraph &G, Block &B, const Edge &E, const Symbol *GOTSymbol)

Apply fixup expression for edge to block content.

constexpr uint64_t PointerSize

x86_64 pointer size.

LLVM_ABI Error optimizeGOTAndStubAccesses(LinkGraph &G)

Optimize the GOT and Stub relocations if the edge target address is in range.

@ Pointer32

A plain 32-bit pointer value relocation.

@ RequestGOTAndTransformToDelta32

A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT entry for the original tar...

@ BranchPCRel32

A 32-bit PC-relative branch.

@ RequestTLVPAndTransformToPCRel32TLVPLoadREXRelaxable

A TLVP entry getter/constructor, transformed to Delta32ToTLVPLoadREXRelaxable.

@ NegDelta64

A 64-bit negative delta.

@ Pointer64

A plain 64-bit pointer value relocation.

@ RequestGOTAndTransformToPCRel32GOTLoadREXRelaxable

A GOT entry getter/constructor, transformed to PCRel32ToGOTLoadREXRelaxable pointing at the GOT entry...

@ NegDelta32

A 32-bit negative delta.

unique_function< Error(LinkGraph &)> LinkGraphPassFunction

A function for mutating LinkGraphs.

LLVM_ABI LinkGraphPassFunction createEHFrameEdgeFixerPass_MachO_x86_64()

Returns a pass suitable for fixing missing edges in an __eh_frame section in a MachO/x86-64 object.

Definition MachO_x86_64.cpp:590

LLVM_ABI Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromMachOObject_x86_64(MemoryBufferRef ObjectBuffer, std::shared_ptr< orc::SymbolStringPool > SSP)

Create a LinkGraph from a MachO/x86-64 relocatable object.

Definition MachO_x86_64.cpp:490

void visitExistingEdges(LinkGraph &G, VisitorTs &&...Vs)

For each edge in the given graph, apply a list of visitors to the edge, stopping when the first visit...

LLVM_ABI Error markAllSymbolsLive(LinkGraph &G)

Marks all symbols in a graph live.

LLVM_ABI void link_MachO_x86_64(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)

jit-link the given LinkGraph.

Definition MachO_x86_64.cpp:530

LLVM_ABI LinkGraphPassFunction createEHFrameSplitterPass_MachO_x86_64()

Returns a pass suitable for splitting __eh_frame sections in MachO/x86-64 objects.

Definition MachO_x86_64.cpp:586

LLVM_ABI void printEdge(raw_ostream &OS, const Block &B, const Edge &E, StringRef EdgeKindName)

DefineExternalSectionStartAndEndSymbols< SymbolIdentifierFunction > createDefineExternalSectionStartAndEndSymbolsPass(SymbolIdentifierFunction &&F)

Returns a JITLink pass (as a function class) that uses the given symbol identification function to id...

SectionRangeSymbolDesc identifyMachOSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym)

MachO section start/end symbol detection.

content_iterator< RelocationRef > relocation_iterator

LLVM_ABI StringRef MachOEHFrameSectionName

uint64_t ExecutorAddrDiff

LLVM_ABI StringRef MachOCompactUnwindSectionName

LLVM_ABI StringRef MachOUnwindInfoSectionName

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.

Error make_error(ArgTs &&... Args)

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

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

Implement std::hash so that hash_code can be used in STL containers.

Definition MachO_x86_64.cpp:507

static bool encodingCannotBeMerged(uint32_t Encoding)

Definition MachO_x86_64.cpp:524

static constexpr endianness Endianness

Definition MachO_x86_64.cpp:512

x86_64::GOTTableManager GOTManager

Definition MachO_x86_64.cpp:517

static constexpr uint32_t EncodingModeMask

Definition MachO_x86_64.cpp:514

static bool encodingSpecifiesDWARF(uint32_t Encoding)

Definition MachO_x86_64.cpp:519

static constexpr uint32_t DWARFSectionOffsetMask

Definition MachO_x86_64.cpp:515

CRTP base for compact unwind traits classes.

An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...

LinkGraphPassList PostAllocationPasses

Post-allocation passes.

LinkGraphPassList PreFixupPasses

Pre-fixup passes.

LinkGraphPassList PostPrunePasses

Post-prune passes.

LinkGraphPassList PrePrunePasses

Pre-prune passes.