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

1

2

3

4

5

6

7

8

9

10

11

12

16#include

17

18#define DEBUG_TYPE "jitlink"

19

21

22namespace llvm {

23namespace jitlink {

24

26

28

29

31 return make_error("Object is not a relocatable MachO");

32

33 if (auto Err = createNormalizedSections())

34 return std::move(Err);

35

36 if (auto Err = createNormalizedSymbols())

37 return std::move(Err);

38

39 if (auto Err = graphifyRegularSymbols())

40 return std::move(Err);

41

42 if (auto Err = graphifySectionsWithCustomParsers())

43 return std::move(Err);

44

46 return std::move(Err);

47

48 return std::move(G);

49}

50

53 std::shared_ptrorc::SymbolStringPool SSP, Triple TT,

56 : Obj(Obj),

62}

63

67 "Custom parser for this section already exists");

68 CustomSectionParserFunctions[SectionName] = std::move(Parser);

69}

70

75}

76

81 else

83 }

85}

86

89}

90

93 strcmp(NSec.SegName, "__DWARF") == 0);

94}

95

101 return true;

102 default:

103 return false;

104 }

105}

106

107Section &MachOLinkGraphBuilder::getCommonSection() {

108 if (!CommonSection)

111 return *CommonSection;

112}

113

114Error MachOLinkGraphBuilder::createNormalizedSections() {

115

116

117

118 LLVM_DEBUG(dbgs() << "Creating normalized sections...\n");

119

120 for (auto &SecRef : Obj.sections()) {

121 NormalizedSection NSec;

123

124 auto SecIndex = Obj.getSectionIndex(SecRef.getRawDataRefImpl());

125

128 Obj.getSection64(SecRef.getRawDataRefImpl());

129

130 memcpy(&NSec.SectName, &Sec64.sectname, 16);

131 NSec.SectName[16] = '\0';

132 memcpy(&NSec.SegName, Sec64.segname, 16);

133 NSec.SegName[16] = '\0';

134

136 NSec.Size = Sec64.size;

137 NSec.Alignment = 1ULL << Sec64.align;

138 NSec.Flags = Sec64.flags;

139 DataOffset = Sec64.offset;

140 } else {

141 const MachO::section &Sec32 = Obj.getSection(SecRef.getRawDataRefImpl());

142

143 memcpy(&NSec.SectName, &Sec32.sectname, 16);

144 NSec.SectName[16] = '\0';

145 memcpy(&NSec.SegName, Sec32.segname, 16);

146 NSec.SegName[16] = '\0';

147

148 NSec.Address = orc::ExecutorAddr(Sec32.addr);

149 NSec.Size = Sec32.size;

150 NSec.Alignment = 1ULL << Sec32.align;

151 NSec.Flags = Sec32.flags;

152 DataOffset = Sec32.offset;

153 }

154

156 dbgs() << " " << NSec.SegName << "," << NSec.SectName << ": "

157 << formatv("{0:x16}", NSec.Address) << " -- "

158 << formatv("{0:x16}", NSec.Address + NSec.Size)

159 << ", align: " << NSec.Alignment << ", index: " << SecIndex

160 << "\n";

161 });

162

163

165 if (DataOffset + NSec.Size > Obj.getData().size())

166 return make_error(

167 "Section data extends past end of file");

168

169 NSec.Data = Obj.getData().data() + DataOffset;

170 }

171

172

173

174

178 else

180

181 auto FullyQualifiedName =

182 G->allocateContent(StringRef(NSec.SegName) + "," + NSec.SectName);

183 NSec.GraphSection = &G->createSection(

184 StringRef(FullyQualifiedName.data(), FullyQualifiedName.size()), Prot);

185

186

189

190 IndexToSection.insert(std::make_pair(SecIndex, std::move(NSec)));

191 }

192

193 std::vector<NormalizedSection *> Sections;

194 Sections.reserve(IndexToSection.size());

195 for (auto &KV : IndexToSection)

196 Sections.push_back(&KV.second);

197

198

199

200 if (Sections.empty())

202

204 [](const NormalizedSection *LHS, const NormalizedSection *RHS) {

206 if (LHS->Address != RHS->Address)

207 return LHS->Address < RHS->Address;

208 return LHS->Size < RHS->Size;

209 });

210

211 for (unsigned I = 0, E = Sections.size() - 1; I != E; ++I) {

212 auto &Cur = *Sections[I];

213 auto &Next = *Sections[I + 1];

214 if (Next.Address < Cur.Address + Cur.Size)

215 return make_error(

216 "Address range for section " +

217 formatv("\"{0}/{1}\" [ {2:x16} -- {3:x16} ] ", Cur.SegName,

218 Cur.SectName, Cur.Address, Cur.Address + Cur.Size) +

219 "overlaps section \"" + Next.SegName + "/" + Next.SectName + "\"" +

220 formatv("\"{0}/{1}\" [ {2:x16} -- {3:x16} ] ", Next.SegName,

221 Next.SectName, Next.Address, Next.Address + Next.Size));

222 }

223

225}

226

227Error MachOLinkGraphBuilder::createNormalizedSymbols() {

228 LLVM_DEBUG(dbgs() << "Creating normalized symbols...\n");

229

230 for (auto &SymRef : Obj.symbols()) {

231

232 unsigned SymbolIndex = Obj.getSymbolIndex(SymRef.getRawDataRefImpl());

238

240 const MachO::nlist_64 &NL64 =

242 Value = NL64.n_value;

243 NStrX = NL64.n_strx;

244 Type = NL64.n_type;

245 Sect = NL64.n_sect;

246 Desc = NL64.n_desc;

247 } else {

248 const MachO::nlist &NL32 =

250 Value = NL32.n_value;

251 NStrX = NL32.n_strx;

252 Type = NL32.n_type;

253 Sect = NL32.n_sect;

254 Desc = NL32.n_desc;

255 }

256

257

258

260 continue;

261

262 std::optional Name;

263 if (NStrX) {

264 if (auto NameOrErr = SymRef.getName())

265 Name = *NameOrErr;

266 else

267 return NameOrErr.takeError();

269 return make_error("Symbol at index " +

270 formatv("{0}", SymbolIndex) +

271 " has no name (string table index 0), "

272 "but N_EXT bit is set");

273

275 dbgs() << " ";

277 dbgs() << "";

278 else

280 dbgs() << ": value = " << formatv("{0:x16}", Value)

281 << ", type = " << formatv("{0:x2}", Type)

282 << ", desc = " << formatv("{0:x4}", Desc) << ", sect = ";

283 if (Sect)

284 dbgs() << static_cast<unsigned>(Sect - 1);

285 else

286 dbgs() << "none";

287 dbgs() << "\n";

288 });

289

290

291 if (Sect != 0) {

293 if (!NSec)

294 return NSec.takeError();

295

296 if (orc::ExecutorAddr(Value) < NSec->Address ||

297 orc::ExecutorAddr(Value) > NSec->Address + NSec->Size)

298 return make_error("Address " + formatv("{0:x}", Value) +

299 " for symbol " + *Name +

300 " does not fall within section");

301

302 if (!NSec->GraphSection) {

304 dbgs() << " Skipping: Symbol is in section " << NSec->SegName << "/"

305 << NSec->SectName

306 << " which has no associated graph section.\n";

307 });

308 continue;

309 }

310 }

311

314 }

315

317}

318

319void MachOLinkGraphBuilder::addSectionStartSymAndBlock(

320 unsigned SecIndex, Section &GraphSec, orc::ExecutorAddr Address,

322 bool IsLive) {

324 Data ? G->createContentBlock(GraphSec, ArrayRef(Data, Size),

326 : G->createZeroFillBlock(GraphSec, Size, Address, Alignment, 0);

327 auto &Sym = G->addAnonymousSymbol(B, 0, Size, false, IsLive);

328 auto SecI = IndexToSection.find(SecIndex);

329 assert(SecI != IndexToSection.end() && "SecIndex invalid");

330 auto &NSec = SecI->second;

331 assert(!NSec.CanonicalSymbols.count(Sym.getAddress()) &&

332 "Anonymous block start symbol clashes with existing symbol address");

333 NSec.CanonicalSymbols[Sym.getAddress()] = &Sym;

334}

335

336Error MachOLinkGraphBuilder::graphifyRegularSymbols() {

337

339

340

341 std::vector<std::vector<NormalizedSymbol *>> SecIndexToSymbols;

342 SecIndexToSymbols.resize(256);

343

344

345

346 for (auto &KV : IndexToSymbol) {

347 auto &NSym = *KV.second;

348

351 if (NSym.Value) {

352 if (!NSym.Name)

353 return make_error("Anonymous common symbol at index " +

354 Twine(KV.first));

355 NSym.GraphSymbol = &G->addDefinedSymbol(

356 G->createZeroFillBlock(getCommonSection(),

358 orc::ExecutorAddr(),

362 } else {

363 if (!NSym.Name)

364 return make_error("Anonymous external symbol at "

365 "index " +

366 Twine(KV.first));

367 NSym.GraphSymbol = &G->addExternalSymbol(

369 }

370 break;

372 if (!NSym.Name)

373 return make_error("Anonymous absolute symbol at index " +

374 Twine(KV.first));

375 NSym.GraphSymbol = &G->addAbsoluteSymbol(

376 *NSym.Name, orc::ExecutorAddr(NSym.Value), 0, Linkage::Strong,

378 break;

380 SecIndexToSymbols[NSym.Sect - 1].push_back(&NSym);

381 break;

383 return make_error(

384 "Unupported N_PBUD symbol " +

385 (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("")) +

386 " at index " + Twine(KV.first));

388 return make_error(

389 "Unupported N_INDR symbol " +

390 (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("")) +

391 " at index " + Twine(KV.first));

392 default:

393 return make_error(

394 "Unrecognized symbol type " + Twine(NSym.Type & MachO::N_TYPE) +

395 " for symbol " +

396 (NSym.Name ? ("\"" + *NSym.Name + "\"") : Twine("")) +

397 " at index " + Twine(KV.first));

398 }

399 }

400

401

402

403 for (auto &KV : IndexToSection) {

404 auto SecIndex = KV.first;

405 auto &NSec = KV.second;

406

407 if (!NSec.GraphSection) {

409 dbgs() << " " << NSec.SegName << "/" << NSec.SectName

410 << " has no graph section. Skipping.\n";

411 });

412 continue;

413 }

414

415

416 if (CustomSectionParserFunctions.count(NSec.GraphSection->getName())) {

418 dbgs() << " Skipping section " << NSec.GraphSection->getName()

419 << " as it has a custom parser.\n";

420 });

421 continue;

424 if (auto Err = graphifyCStringSection(

425 NSec, std::move(SecIndexToSymbols[SecIndex])))

426 return Err;

427 continue;

428 } else

430 dbgs() << " Graphifying regular section "

431 << NSec.GraphSection->getName() << "...\n";

432 });

433

436

437 auto &SecNSymStack = SecIndexToSymbols[SecIndex];

438

439

440

441 if (SecNSymStack.empty()) {

442 if (NSec.Size > 0) {

444 dbgs() << " Section non-empty, but contains no symbols. "

445 "Creating anonymous block to cover "

446 << formatv("{0:x16}", NSec.Address) << " -- "

447 << formatv("{0:x16}", NSec.Address + NSec.Size) << "\n";

448 });

449 addSectionStartSymAndBlock(SecIndex, *NSec.GraphSection, NSec.Address,

450 NSec.Data, NSec.Size, NSec.Alignment,

451 SectionIsNoDeadStrip);

452 } else

454 dbgs() << " Section empty and contains no symbols. Skipping.\n";

455 });

456 continue;

457 }

458

459

460

461

462 llvm::sort(SecNSymStack, [](const NormalizedSymbol *LHS,

463 const NormalizedSymbol *RHS) {

464 if (LHS->Value != RHS->Value)

465 return LHS->Value > RHS->Value;

468 if (LHS->S != RHS->S)

470 return LHS->Name < RHS->Name;

471 });

472

473

474 if (!SecNSymStack.empty() && isAltEntry(*SecNSymStack.back()))

475 return make_error(

476 "First symbol in " + NSec.GraphSection->getName() + " is alt-entry");

477

478

479

480 if (orc::ExecutorAddr(SecNSymStack.back()->Value) != NSec.Address) {

481 auto AnonBlockSize =

482 orc::ExecutorAddr(SecNSymStack.back()->Value) - NSec.Address;

484 dbgs() << " Section start not covered by symbol. "

485 << "Creating anonymous block to cover [ " << NSec.Address

486 << " -- " << (NSec.Address + AnonBlockSize) << " ]\n";

487 });

488 addSectionStartSymAndBlock(SecIndex, *NSec.GraphSection, NSec.Address,

489 NSec.Data, AnonBlockSize, NSec.Alignment,

490 SectionIsNoDeadStrip);

491 }

492

493

494

495

496

497

498

499

500

501 while (!SecNSymStack.empty()) {

502 SmallVector<NormalizedSymbol *, 8> BlockSyms;

503

504

505

506 BlockSyms.push_back(SecNSymStack.back());

507 SecNSymStack.pop_back();

508 while (!SecNSymStack.empty() &&

510 SecNSymStack.back()->Value == BlockSyms.back()->Value ||

511 !SubsectionsViaSymbols)) {

512 BlockSyms.push_back(SecNSymStack.back());

513 SecNSymStack.pop_back();

514 }

515

516

517 auto BlockStart = orc::ExecutorAddr(BlockSyms.front()->Value);

518 orc::ExecutorAddr BlockEnd =

519 SecNSymStack.empty() ? NSec.Address + NSec.Size

520 : orc::ExecutorAddr(SecNSymStack.back()->Value);

523

525 dbgs() << " Creating block for " << formatv("{0:x16}", BlockStart)

526 << " -- " << formatv("{0:x16}", BlockEnd) << ": "

527 << NSec.GraphSection->getName() << " + "

528 << formatv("{0:x16}", BlockOffset) << " with "

529 << BlockSyms.size() << " symbol(s)...\n";

530 });

531

533 NSec.Data

534 ? G->createContentBlock(

535 *NSec.GraphSection,

536 ArrayRef(NSec.Data + BlockOffset, BlockSize),

537 BlockStart, NSec.Alignment, BlockStart % NSec.Alignment)

538 : G->createZeroFillBlock(*NSec.GraphSection, BlockSize,

539 BlockStart, NSec.Alignment,

540 BlockStart % NSec.Alignment);

541

542 std::optionalorc::ExecutorAddr LastCanonicalAddr;

543 auto SymEnd = BlockEnd;

544 while (!BlockSyms.empty()) {

545 auto &NSym = *BlockSyms.back();

546 BlockSyms.pop_back();

547

548 bool SymLive =

550

551 auto &Sym = createStandardGraphSymbol(

552 NSym, B, SymEnd - orc::ExecutorAddr(NSym.Value), SectionIsText,

553 SymLive, LastCanonicalAddr != orc::ExecutorAddr(NSym.Value));

554

555 if (LastCanonicalAddr != Sym.getAddress()) {

556 if (LastCanonicalAddr)

557 SymEnd = *LastCanonicalAddr;

558 LastCanonicalAddr = Sym.getAddress();

559 }

560 }

561 }

562 }

563

565}

566

567Symbol &MachOLinkGraphBuilder::createStandardGraphSymbol(NormalizedSymbol &NSym,

568 Block &B, size_t Size,

569 bool IsText,

570 bool IsNoDeadStrip,

571 bool IsCanonical) {

572

574 dbgs() << " " << formatv("{0:x16}", NSym.Value) << " -- "

575 << formatv("{0:x16}", NSym.Value + Size) << ": ";

576 if (!NSym.Name)

577 dbgs() << "";

578 else

579 dbgs() << *NSym.Name;

580 if (IsText)

581 dbgs() << " [text]";

582 if (IsNoDeadStrip)

583 dbgs() << " [no-dead-strip]";

584 if (!IsCanonical)

585 dbgs() << " [non-canonical]";

586 dbgs() << "\n";

587 });

588

589 auto SymOffset = orc::ExecutorAddr(NSym.Value) - B.getAddress();

590 auto &Sym =

591 NSym.Name

592 ? G->addDefinedSymbol(B, SymOffset, *NSym.Name, Size, NSym.L, NSym.S,

593 IsText, IsNoDeadStrip)

594 : G->addAnonymousSymbol(B, SymOffset, Size, IsText, IsNoDeadStrip);

595 NSym.GraphSymbol = &Sym;

596

597 if (IsCanonical)

599

600 return Sym;

601}

602

603Error MachOLinkGraphBuilder::graphifySectionsWithCustomParsers() {

604

605 for (auto &KV : IndexToSection) {

606 auto &NSec = KV.second;

607

608

609 if (!NSec.GraphSection)

610 continue;

611

612 auto HI = CustomSectionParserFunctions.find(NSec.GraphSection->getName());

613 if (HI != CustomSectionParserFunctions.end()) {

614 auto &Parse = HI->second;

615 if (auto Err = Parse(NSec))

616 return Err;

617 }

618 }

619

621}

622

623Error MachOLinkGraphBuilder::graphifyCStringSection(

624 NormalizedSection &NSec, std::vector<NormalizedSymbol *> NSyms) {

625 assert(NSec.GraphSection && "C string literal section missing graph section");

626 assert(NSec.Data && "C string literal section has no data");

627

629 dbgs() << " Graphifying C-string literal section "

630 << NSec.GraphSection->getName() << "\n";

631 });

632

633 if (NSec.Data[NSec.Size - 1] != '\0')

634 return make_error("C string literal section " +

635 NSec.GraphSection->getName() +

636 " does not end with null terminator");

637

638

640 [](const NormalizedSymbol *LHS, const NormalizedSymbol *RHS) {

641 if (LHS->Value != RHS->Value)

642 return LHS->Value > RHS->Value;

644 return LHS->L > RHS->L;

646 return LHS->S > RHS->S;

648 if (!LHS->Name)

649 return true;

650 return *LHS->Name > *RHS->Name;

651 }

652 return false;

653 });

654

658

659

660 for (size_t I = 0; I != NSec.Size; ++I) {

661 if (NSec.Data[I] == '\0') {

662 size_t BlockSize = I + 1 - BlockStart;

663

664 auto &B = G->createContentBlock(*NSec.GraphSection,

665 {NSec.Data + BlockStart, BlockSize},

666 NSec.Address + BlockStart, NSec.Alignment,

667 BlockStart % NSec.Alignment);

668

670 dbgs() << " Created block " << B.getRange()

671 << ", align = " << B.getAlignment()

672 << ", align-ofs = " << B.getAlignmentOffset() << " for \"";

673 for (size_t J = 0; J != std::min(B.getSize(), size_t(16)); ++J)

674 switch (B.getContent()[J]) {

675 case '\0': break;

676 case '\n': dbgs() << "\\n"; break;

677 case '\t': dbgs() << "\\t"; break;

678 default: dbgs() << B.getContent()[J]; break;

679 }

680 if (B.getSize() > 16)

681 dbgs() << "...";

682 dbgs() << "\"\n";

683 });

684

685

686 if (NSyms.empty() ||

687 orc::ExecutorAddr(NSyms.back()->Value) != B.getAddress()) {

688 auto &S = G->addAnonymousSymbol(B, 0, BlockSize, false, false);

689 setCanonicalSymbol(NSec, S);

691 dbgs() << " Adding symbol for c-string block " << B.getRange()

692 << ": at offset 0\n";

693 });

694 }

695

696

697 auto LastCanonicalAddr = B.getAddress() + BlockSize;

698 while (!NSyms.empty() && orc::ExecutorAddr(NSyms.back()->Value) <

700 auto &NSym = *NSyms.back();

701 size_t SymSize = (B.getAddress() + BlockSize) -

702 orc::ExecutorAddr(NSyms.back()->Value);

703 bool SymLive =

705

706 bool IsCanonical = false;

707 if (LastCanonicalAddr != orc::ExecutorAddr(NSym.Value)) {

708 IsCanonical = true;

709 LastCanonicalAddr = orc::ExecutorAddr(NSym.Value);

710 }

711

712 auto &Sym = createStandardGraphSymbol(NSym, B, SymSize, SectionIsText,

713 SymLive, IsCanonical);

714 (void)Sym;

716 dbgs() << " Adding symbol for c-string block " << B.getRange()

717 << ": "

718 << (Sym.hasName() ? *Sym.getName() : "")

719 << " at offset " << formatv("{0:x}", Sym.getOffset()) << "\n";

720 });

721

722 NSyms.pop_back();

723 }

724

726 }

727 }

728

730 [](Block *B) { return isCStringBlock(*B); }) &&

731 "All blocks in section should hold single c-strings");

732

734}

735

737 auto *CUSec = G.findSectionByName(CompactUnwindSectionName);

738 if (!CUSec)

740

741 if (G.getTargetTriple().isOSBinFormatMachO())

742 return make_error(

743 "Error linking " + G.getName() +

744 ": compact unwind splitting not supported on non-macho target " +

745 G.getTargetTriple().str());

746

747 unsigned CURecordSize = 0;

748 unsigned PersonalityEdgeOffset = 0;

749 unsigned LSDAEdgeOffset = 0;

750 switch (G.getTargetTriple().getArch()) {

753

754

755

756

757

758

759 CURecordSize = 32;

760 PersonalityEdgeOffset = 16;

761 LSDAEdgeOffset = 24;

762 break;

763 default:

764 return make_error(

765 "Error linking " + G.getName() +

766 ": compact unwind splitting not supported on " +

767 G.getTargetTriple().getArchName());

768 }

769

770 std::vector<Block *> OriginalBlocks(CUSec->blocks().begin(),

771 CUSec->blocks().end());

773 dbgs() << "In " << G.getName() << " splitting compact unwind section "

774 << CompactUnwindSectionName << " containing "

775 << OriginalBlocks.size() << " initial blocks...\n";

776 });

777

778 while (!OriginalBlocks.empty()) {

779 auto *B = OriginalBlocks.back();

780 OriginalBlocks.pop_back();

781

782 if (B->getSize() == 0) {

784 dbgs() << " Skipping empty block at "

785 << formatv("{0:x16}", B->getAddress()) << "\n";

786 });

787 continue;

788 }

789

790 unsigned NumBlocks = B->getSize() / CURecordSize;

791

793 dbgs() << " Splitting block at " << formatv("{0:x16}", B->getAddress())

794 << " into " << NumBlocks << " compact unwind record(s)\n";

795 });

796

797 if (B->getSize() % CURecordSize)

798 return make_error(

799 "Error splitting compact unwind record in " + G.getName() +

800 ": block at " + formatv("{0:x}", B->getAddress()) + " has size " +

801 formatv("{0:x}", B->getSize()) +

802 " (not a multiple of CU record size of " +

803 formatv("{0:x}", CURecordSize) + ")");

804

807 return Idx * CURecordSize;

808 }));

809

810 for (auto *CURec : Blocks) {

811 bool AddedKeepAlive = false;

812

813 for (auto &E : CURec->edges()) {

814 if (E.getOffset() == 0) {

816 dbgs() << " Updating compact unwind record at "

817 << CURec->getAddress() << " to point to "

818 << (E.getTarget().hasName() ? *E.getTarget().getName()

820 << " (at " << E.getTarget().getAddress() << ")\n";

821 });

822

823 if (E.getTarget().isExternal())

824 return make_error(

825 "Error adding keep-alive edge for compact unwind record at " +

826 formatv("{0:x}", CURec->getAddress()) + ": target " +

827 *E.getTarget().getName() + " is an external symbol");

828 auto &TgtBlock = E.getTarget().getBlock();

829 auto &CURecSym =

830 G.addAnonymousSymbol(*CURec, 0, CURecordSize, false, false);

832 AddedKeepAlive = true;

833 } else if (E.getOffset() != PersonalityEdgeOffset &&

834 E.getOffset() != LSDAEdgeOffset)

835 return make_error(

836 "Unexpected edge at offset " + formatv("{0:x}", E.getOffset()) +

837 " in compact unwind record at " +

838 formatv("{0:x}", CURec->getAddress()));

839 }

840

841 if (!AddedKeepAlive)

842 return make_error(

843 "Error adding keep-alive edge for compact unwind record at " +

844 formatv("{0:x}", CURec->getAddress()) +

845 ": no outgoing target edge at offset 0");

846 }

847 }

848

850}

851

852}

853}

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

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

static const char * CommonSectionName

static Expected< StringRef > getFileName(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID)

Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx

DenseMap< Block *, BlockRelaxAux > Blocks

static const char * CommonSectionName

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

Provides some synthesis utilities to produce sequences of values.

static const int BlockSize

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.

iterator find(StringRef Key)

size_type count(StringRef Key) const

count - Return 1 if the element is in the map, 0 otherwise.

StringRef - Represent a constant reference to a string, i.e.

constexpr size_t size() const

size - Get the string size.

constexpr const char * data() const

data - Get a pointer to the start of the string (which may not be null terminated).

Manages the enabling and disabling of subtarget specific features.

Triple - Helper class for working with autoconf configuration names.

The instances of the Type class are immutable: once they are created, they are never changed.

Error operator()(LinkGraph &G)

const char *(*)(Edge::Kind) GetEdgeKindNameFunction

static bool isDebugSection(const NormalizedSection &NSec)

void addCustomSectionParser(StringRef SectionName, SectionParserFunction Parse)

virtual ~MachOLinkGraphBuilder()

virtual Error addRelocations()=0

std::function< Error(NormalizedSection &S)> SectionParserFunction

static Scope getScope(StringRef Name, uint8_t Type)

static bool isZeroFillSection(const NormalizedSection &NSec)

Expected< std::unique_ptr< LinkGraph > > buildGraph()

NormalizedSection & getSectionByIndex(unsigned Index)

Index is zero-based (MachO section indexes are usually one-based) and assumed to be in-range.

MachOLinkGraphBuilder(const object::MachOObjectFile &Obj, std::shared_ptr< orc::SymbolStringPool > SSP, Triple TT, SubtargetFeatures Features, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)

NormalizedSymbol & createNormalizedSymbol(ArgTs &&... Args)

Create a symbol.

static Linkage getLinkage(uint16_t Desc)

static bool isAltEntry(const NormalizedSymbol &NSym)

Expected< NormalizedSection & > findSectionByIndex(unsigned Index)

Try to get the section at the given index.

Represents an object file section.

StringRef getData() const

const MachO::mach_header_64 & getHeader64() const

Expected< SectionRef > getSection(unsigned SectionIndex) const

uint64_t getSymbolIndex(DataRefImpl Symb) const

MachO::nlist getSymbolTableEntry(DataRefImpl DRI) const

MachO::section_64 getSection64(DataRefImpl DRI) const

bool isRelocatableObject() const override

True if this is a relocatable object (.o/.obj).

MachO::nlist_64 getSymbol64TableEntry(DataRefImpl DRI) const

bool is64Bit() const override

uint64_t getSectionIndex(DataRefImpl Sec) const override

section_iterator_range sections() const

symbol_iterator_range symbols() const

Represents an address in the executor process.

@ S_ATTR_DEBUG

S_ATTR_DEBUG - A debug section.

@ S_ATTR_NO_DEAD_STRIP

S_ATTR_NO_DEAD_STRIP - No dead stripping.

@ S_ATTR_PURE_INSTRUCTIONS

S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine instructions.

@ S_GB_ZEROFILL

S_GB_ZEROFILL - Zero fill on demand section (that can be larger than 4 gigabytes).

@ S_THREAD_LOCAL_ZEROFILL

S_THREAD_LOCAL_ZEROFILL - Thread local zerofill section.

@ S_CSTRING_LITERALS

S_CSTRING_LITERALS - Section with literal C strings.

@ S_ZEROFILL

S_ZEROFILL - Zero fill on demand section.

uint8_t GET_COMM_ALIGN(uint16_t n_desc)

@ MH_SUBSECTIONS_VIA_SYMBOLS

Linkage

Describes symbol linkage. This can be used to resolve definition clashes.

Scope

Defines the scope in which this symbol should be visible: Default – Visible in the public interface o...

Type

MessagePack types as defined in the standard, with the exception of Integer being divided into a sign...

MemProt

Describes Read/Write/Exec permissions for memory.

uint64_t ExecutorAddrDiff

@ NoAlloc

NoAlloc memory should not be allocated by the JITLinkMemoryManager at all.

NodeAddr< BlockNode * > Block

This is an optimization pass for GlobalISel generic memory operations.

bool all_of(R &&range, UnaryPredicate P)

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

auto map_range(ContainerTy &&C, FuncTy F)

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

void sort(IteratorTy Start, IteratorTy End)

raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

OutputIt move(R &&Range, OutputIt Out)

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

auto seq(T Begin, T End)

Iterate over an integral type from Begin up to - but not including - End.

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

Description of the encoding of one expression Op.