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

1

2

3

4

5

6

7

8

9

10

11

13

14#include

15

16#define DEBUG_TYPE "jitlink"

17

19

20namespace llvm {

21namespace jitlink {

22

27

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

33 : Obj(Obj),

37 std::move(GetEdgeKindName))) {

39 dbgs() << "Created COFFLinkGraphBuilder for \"" << Obj.getFileName()

40 << "\"\n";

41 });

42}

43

45

48

49

50 if (Obj.getDOSHeader())

53}

54

58 return Section->VirtualAddress + Obj.getImageBase();

59}

60

61bool COFFLinkGraphBuilder::isComdatSection(

62 const object::coff_section *Section) {

64}

65

66Section &COFFLinkGraphBuilder::getCommonSection() {

67 if (!CommonSection)

70 return *CommonSection;

71}

72

74 if (!Obj.isRelocatableObject())

76

78 return std::move(Err);

79

81 return std::move(Err);

82

84 return std::move(Err);

85

86 return std::move(G);

87}

88

90COFFLinkGraphBuilder::getCOFFSectionName(COFFSectionIndex SectionIndex,

93 switch (SectionIndex) {

96 return "(common)";

97 else

98 return "(external)";

99 }

101 return "(absolute)";

103

104 return "(debug)";

105 }

106 default: {

107

108 if (Expected SecNameOrErr = Obj.getSectionName(Sec))

109 return *SecNameOrErr;

110 }

111 }

112 return "";

113}

114

116 LLVM_DEBUG(dbgs() << " Creating graph sections...\n");

117

118 GraphBlocks.resize(Obj.getNumberOfSections() + 1);

119

121 SecIndex <= static_cast(Obj.getNumberOfSections());

122 SecIndex++) {

124 if (!Sec)

126

130

131

134 dbgs() << " "

135 << "Skipping section \"" << SectionName << "\"\n";

136 });

137 continue;

138 }

139

141 dbgs() << " "

142 << "Creating section for \"" << SectionName << "\"\n";

143 });

144

145

153

154

155 auto *GraphSec = G->findSectionByName(SectionName);

156 if (!GraphSec) {

157 GraphSec = &G->createSection(SectionName, Prot);

160 }

161 if (GraphSec->getMemProt() != Prot)

163

166 B = &G->createZeroFillBlock(

167 *GraphSec, getSectionSize(Obj, *Sec),

169 (*Sec)->getAlignment(), 0);

170 else {

172 if (auto Err = Obj.getSectionContents(*Sec, Data))

173 return Err;

174

176 reinterpret_cast<const char *>(Data.data()), Data.size());

177

178 if (SectionName == getDirectiveSectionName())

179 if (auto Err = handleDirectiveSection(

180 StringRef(CharData.data(), CharData.size())))

181 return Err;

182

183 B = &G->createContentBlock(

184 *GraphSec, CharData, orc::ExecutorAddr(getSectionAddress(Obj, *Sec)),

185 (*Sec)->getAlignment(), 0);

186 }

187

189 }

190

192}

193

195 LLVM_DEBUG(dbgs() << " Creating graph symbols...\n");

196

197 SymbolSets.resize(Obj.getNumberOfSections() + 1);

198 PendingComdatExports.resize(Obj.getNumberOfSections() + 1);

199 GraphSymbols.resize(Obj.getNumberOfSymbols());

200

202 SymIndex < static_cast(Obj.getNumberOfSymbols());

203 SymIndex++) {

205 if (!Sym)

207

210 SymbolName = *SymNameOrErr;

211

214

216 auto SecOrErr = Obj.getSection(SectionIndex);

217 if (!SecOrErr)

219 "Invalid COFF section number:" + formatv("{0:d}: ", SectionIndex) +

220 " (" + toString(SecOrErr.takeError()) + ")");

221 Sec = *SecOrErr;

222 }

223 auto InternedSymbolName = G->intern(std::move(SymbolName));

224

225

227 if (Sym->isFileRecord())

229 dbgs() << " " << SymIndex << ": Skipping FileRecord symbol \""

230 << InternedSymbolName << "\" in "

231 << getCOFFSectionName(SectionIndex, Sec, *Sym)

232 << " (index: " << SectionIndex << ") \n";

233 });

234 else if (Sym->isUndefined()) {

235 GSym = createExternalSymbol(SymIndex, InternedSymbolName, *Sym, Sec);

236 } else if (Sym->isWeakExternal()) {

239 uint32_t Characteristics = WeakExternal->Characteristics;

240 WeakExternalRequests.push_back(

241 {SymIndex, TagIndex, Characteristics, SymbolName});

242 } else {

244 createDefinedSymbol(SymIndex, InternedSymbolName, *Sym, Sec);

245 if (!NewGSym)

247 GSym = *NewGSym;

248 if (GSym) {

250 dbgs() << " " << SymIndex

251 << ": Creating defined graph symbol for COFF symbol \""

252 << InternedSymbolName << "\" in "

253 << getCOFFSectionName(SectionIndex, Sec, *Sym)

254 << " (index: " << SectionIndex << ") \n";

255 dbgs() << " " << *GSym << "\n";

256 });

257 }

258 }

259

260

261 if (GSym)

263 SymIndex += Sym->getNumberOfAuxSymbols();

264 }

265

266 if (auto Err = flushWeakAliasRequests())

267 return Err;

268

269 if (auto Err = handleAlternateNames())

270 return Err;

271

272 if (auto Err = calculateImplicitSizeOfSymbols())

273 return Err;

274

276}

277

278Error COFFLinkGraphBuilder::handleDirectiveSection(StringRef Str) {

279 auto Parsed = DirectiveParser.parse(Str);

280 if (!Parsed)

281 return Parsed.takeError();

282 for (auto *Arg : *Parsed) {

284 switch (Arg->getOption().getID()) {

285 case COFF_OPT_alternatename: {

287 std::tie(From, To) = S.split('=');

290 "Invalid COFF /alternatename directive");

291 AlternateNames[G->intern(From)] = G->intern(To);

292 break;

293 }

294 case COFF_OPT_incl: {

295 auto Symbol = &G->addExternalSymbol(S, 0, false);

296 Symbol->setLive(true);

297 ExternalSymbols[Symbol->getName()] = Symbol;

298 break;

299 }

300 case COFF_OPT_export:

301 break;

302 default: {

304 dbgs() << "Unknown coff directive: " << Arg->getSpelling() << "\n";

305 });

306 break;

307 }

308 }

309 }

311}

312

313Error COFFLinkGraphBuilder::flushWeakAliasRequests() {

314

315 for (auto &WeakExternal : WeakExternalRequests) {

316 if (auto *Target = getGraphSymbol(WeakExternal.Target)) {

317 Expectedobject::COFFSymbolRef AliasSymbol =

318 Obj.getSymbol(WeakExternal.Alias);

319 if (!AliasSymbol)

320 return AliasSymbol.takeError();

321

322

323

328

329 auto NewSymbol = createAliasSymbol(G->intern(WeakExternal.SymbolName),

331 if (!NewSymbol)

332 return NewSymbol.takeError();

333 setGraphSymbol(AliasSymbol->getSectionNumber(), WeakExternal.Alias,

334 **NewSymbol);

336 dbgs() << " " << WeakExternal.Alias

337 << ": Creating weak external symbol for COFF symbol \""

338 << WeakExternal.SymbolName << "\" in section "

339 << AliasSymbol->getSectionNumber() << "\n";

340 dbgs() << " " << **NewSymbol << "\n";

341 });

342 } else

344 "symbol not found for symbol " +

345 formatv("{0:d}", WeakExternal.Alias));

346 }

348}

349

350Error COFFLinkGraphBuilder::handleAlternateNames() {

351 for (auto &KeyValue : AlternateNames) {

352 auto DefinedSymbolName = KeyValue.second;

353 auto ExternalSymbolsName = KeyValue.first;

354 if (DefinedSymbols.count(DefinedSymbolName) &&

355 ExternalSymbols.count(ExternalSymbolsName)) {

356 auto *Target = DefinedSymbols[DefinedSymbolName];

357 auto *Alias = ExternalSymbols[ExternalSymbolsName];

358 G->makeDefined(*Alias, Target->getBlock(), Target->getOffset(),

360 }

361 }

363}

364

365Symbol *COFFLinkGraphBuilder::createExternalSymbol(

366 COFFSymbolIndex SymIndex, orc::SymbolStringPtr SymbolName,

367 object::COFFSymbolRef Symbol, const object::coff_section *Section) {

368 llvm::jitlink::Symbol *Sym = nullptr;

369 if (auto It = ExternalSymbols.find(SymbolName); It == ExternalSymbols.end()) {

370 Sym = &G->addExternalSymbol(*SymbolName, Symbol.getValue(), false);

371 ExternalSymbols[Sym->getName()] = Sym;

372 } else {

373 Sym = It->second;

374 }

375

377 dbgs() << " " << SymIndex

378 << ": Creating external graph symbol for COFF symbol \""

379 << Sym->getName() << "\" in "

380 << getCOFFSectionName(Symbol.getSectionNumber(), Section, Symbol)

381 << " (index: " << Symbol.getSectionNumber() << ") \n";

382 });

383 return Sym;

384}

385

386Expected<Symbol *>

387COFFLinkGraphBuilder::createAliasSymbol(orc::SymbolStringPtr SymbolName,

389 if (Target.isDefined()) {

390

392 "symbol as alternative not supported.");

393 }

394 return &G->addDefinedSymbol(Target.getBlock(), Target.getOffset(), SymbolName,

396 false);

397}

398

399

400

401

402

403

404

405

406Error COFFLinkGraphBuilder::calculateImplicitSizeOfSymbols() {

408 SecIndex <= static_cast(Obj.getNumberOfSections());

409 SecIndex++) {

410 auto &SymbolSet = SymbolSets[SecIndex];

411 if (SymbolSet.empty())

412 continue;

417 for (auto It = SymbolSet.rbegin(); It != SymbolSet.rend(); It++) {

419 jitlink::Symbol *Symbol = It->second;

421

422 if (Symbol->getOffset() == LastOffset)

423 CandSize = LastSize;

424 else

425 CandSize = LastOffset - Offset;

426

428 if (Offset + Symbol->getSize() > LastDifferentOffset)

429 dbgs() << " Overlapping symbol range generated for the following "

430 "symbol:"

431 << "\n"

432 << " " << *Symbol << "\n";

433 });

434 (void)LastDifferentOffset;

435 if (LastOffset != Offset)

436 LastDifferentOffset = Offset;

437 LastSize = CandSize;

439 if (Symbol->getSize()) {

440

441

442

443

444

445

446 continue;

447 }

448

450 if (!CandSize)

451 dbgs() << " Empty implicit symbol size generated for the following "

452 "symbol:"

453 << "\n"

454 << " " << *Symbol << "\n";

455 });

456

457 Symbol->setSize(CandSize);

458 }

459 }

461}

462

463Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(

464 COFFSymbolIndex SymIndex, orc::SymbolStringPtr SymbolName,

465 object::COFFSymbolRef Symbol, const object::coff_section *Section) {

466

467 if (Symbol.isCommon()) {

468

469 return &G->addDefinedSymbol(

470 G->createZeroFillBlock(getCommonSection(), Symbol.getValue(),

471 orc::ExecutorAddr(), Symbol.getValue(), 0),

473 false, false);

474 }

475

476 if (Symbol.isAbsolute())

477 return &G->addAbsoluteSymbol(SymbolName,

478 orc::ExecutorAddr(Symbol.getValue()), 0,

480

483 "Reserved section number used in regular symbol " +

484 formatv("{0:d}", SymIndex));

485

487 if (B) {

489 dbgs() << " " << SymIndex

490 << ": Skipping graph symbol since section was not created for "

491 "COFF symbol \""

492 << SymbolName << "\" in section " << Symbol.getSectionNumber()

493 << "\n";

494 });

495 return nullptr;

496 }

497

498 if (Symbol.isExternal()) {

499

500 if (!isComdatSection(Section)) {

501 auto GSym = &G->addDefinedSymbol(

505 return GSym;

506 } else {

507 if (!PendingComdatExports[Symbol.getSectionNumber()])

509 formatv("{0:d}", SymIndex));

510

511 return exportCOMDATSymbol(SymIndex, SymbolName, Symbol);

512 }

513 }

514

517 const object::coff_aux_section_definition *Definition =

518 Symbol.getSectionDefinition();

519 if (!Definition || !isComdatSection(Section)) {

520

521 return &G->addDefinedSymbol(

524 }

526 auto Target = Definition->getNumber(Symbol.isBigObj());

527 auto GSym = &G->addDefinedSymbol(

531 return GSym;

532 }

533 if (PendingComdatExports[Symbol.getSectionNumber()])

535 "COMDAT export request already exists before symbol " +

536 formatv("{0:d}", SymIndex));

537 return createCOMDATExportRequest(SymIndex, Symbol, Definition);

538 }

541 " in symbol " + formatv("{0:d}", SymIndex));

542}

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(

559 COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,

560 const object::coff_aux_section_definition *Definition) {

562 switch (Definition->Selection) {

565 break;

566 }

569 break;

570 }

573

574

576 break;

577 }

579

580

582 dbgs() << " " << SymIndex

583 << ": Partially supported IMAGE_COMDAT_SELECT_LARGEST was used"

584 " in section "

585 << Symbol.getSectionNumber() << " (size: " << Definition->Length

586 << ")\n";

587 });

589 break;

590 }

592

594 "IMAGE_COMDAT_SELECT_NEWEST is not supported.");

595 }

596 default: {

598 formatv("{0:d}", Definition->Selection));

599 }

600 }

601 PendingComdatExports[Symbol.getSectionNumber()] = {SymIndex, L,

602 Definition->Length};

603 return nullptr;

604}

605

606

607Expected<Symbol *>

608COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,

609 orc::SymbolStringPtr SymbolName,

610 object::COFFSymbolRef Symbol) {

612 auto &PendingComdatExport = PendingComdatExports[Symbol.getSectionNumber()];

613

614

615

616 auto GSym = &G->addDefinedSymbol(

617 *B, Symbol.getValue(), SymbolName, 0, PendingComdatExport->Linkage,

619 false);

621 dbgs() << " " << SymIndex

622 << ": Exporting COMDAT graph symbol for COFF symbol \"" << SymbolName

623 << "\" in section " << Symbol.getSectionNumber() << "\n";

624 dbgs() << " " << *GSym << "\n";

625 });

627 *GSym);

629 PendingComdatExport = std::nullopt;

630 return GSym;

631}

632

634 if (ImageBase)

635 return *ImageBase;

636

637 auto IBN = G.intern(ImageBaseName);

638 ImageBase = G.findExternalSymbolByName(IBN);

639 if (*ImageBase)

640 return *ImageBase;

641 ImageBase = G.findAbsoluteSymbolByName(IBN);

642 if (*ImageBase)

643 return *ImageBase;

644 ImageBase = G.findDefinedSymbolByName(IBN);

645 if (*ImageBase)

646 return *ImageBase;

647

648 return nullptr;

649}

650

651}

652}

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

static const char * CommonSectionName

Definition COFFLinkGraphBuilder.cpp:18

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

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

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.

Error takeError()

Take ownership of the stored error.

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

std::pair< StringRef, StringRef > split(char Separator) const

Split into two substrings around the first occurrence of a separator character.

constexpr bool empty() const

empty - Check if the string is empty.

Manages the enabling and disabling of subtarget specific features.

Triple - Helper class for working with autoconf configuration names.

An Addressable with content and edges.

void addEdge(Edge::Kind K, Edge::OffsetT Offset, Symbol &Target, Edge::AddendT Addend)

Add an edge to this block.

Expected< opt::InputArgList > parse(StringRef Str)

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

Definition COFFLinkGraphBuilder.cpp:73

virtual Error addRelocations()=0

Symbol * getGraphSymbol(COFFSymbolIndex SymIndex) const

Error graphifySections()

Definition COFFLinkGraphBuilder.cpp:115

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

Definition COFFLinkGraphBuilder.cpp:28

Error graphifySymbols()

Definition COFFLinkGraphBuilder.cpp:194

virtual ~COFFLinkGraphBuilder()

Block * getGraphBlock(COFFSectionIndex SecIndex) const

void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex, Symbol &Sym)

void setGraphBlock(COFFSectionIndex SecIndex, Block *B)

Symbol * operator()(LinkGraph &G)

Definition COFFLinkGraphBuilder.cpp:633

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

Represents an object file section.

const orc::SymbolStringPtr & getName() const

Returns the name of this symbol (empty if the symbol is anonymous).

uint32_t getValue() const

Represents an address in the executor process.

constexpr char SymbolName[]

Key for Kernel::Metadata::mSymbolName.

@ IMAGE_SCN_CNT_UNINITIALIZED_DATA

@ IMAGE_SYM_CLASS_LABEL

Label.

@ IMAGE_SYM_CLASS_STATIC

Static.

@ IMAGE_COMDAT_SELECT_NODUPLICATES

@ IMAGE_COMDAT_SELECT_LARGEST

@ IMAGE_COMDAT_SELECT_NEWEST

@ IMAGE_COMDAT_SELECT_SAME_SIZE

@ IMAGE_COMDAT_SELECT_ASSOCIATIVE

@ IMAGE_COMDAT_SELECT_EXACT_MATCH

@ IMAGE_COMDAT_SELECT_ANY

@ IMAGE_WEAK_EXTERN_SEARCH_ALIAS

bool isReservedSectionNumber(int32_t SectionNumber)

@ IMAGE_SYM_DTYPE_FUNCTION

A function that returns a base type.

static Triple createTripleWithCOFFFormat(Triple T)

Definition COFFLinkGraphBuilder.cpp:23

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...

MemProt

Describes Read/Write/Exec permissions for memory.

uint64_t ExecutorAddrDiff

@ NoAlloc

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

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.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)

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.

support::ulittle32_t VirtualSize

support::ulittle32_t SizeOfRawData