16#define DEBUG_TYPE "jitlink"
30 std::shared_ptr<orc::SymbolStringPool> SSP,
Triple TT,
58uint64_t COFFLinkGraphBuilder::getSectionSize(
const object::COFFObjectFile &Obj,
59 const object::coff_section *Sec) {
62 if (Obj.getDOSHeader())
63 return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
64 return Sec->SizeOfRawData;
68COFFLinkGraphBuilder::getSectionAddress(
const object::COFFObjectFile &Obj,
69 const object::coff_section *Section) {
70 return Section->VirtualAddress + Obj.getImageBase();
73bool COFFLinkGraphBuilder::isComdatSection(
74 const object::coff_section *Section) {
78Section &COFFLinkGraphBuilder::getCommonSection() {
82 return *CommonSection;
86 if (!Obj.isRelocatableObject())
87 return make_error<JITLinkError>(
"Object is not a relocatable COFF file");
90 return std::move(Err);
93 return std::move(Err);
96 return std::move(Err);
102COFFLinkGraphBuilder::getCOFFSectionName(COFFSectionIndex SectionIndex,
105 switch (SectionIndex) {
120 if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(Sec))
121 return *SecNameOrErr;
130 GraphBlocks.resize(Obj.getNumberOfSections() + 1);
133 SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
154 <<
"Creating section for \"" <<
SectionName <<
"\"\n";
167 auto *GraphSec = G->findSectionByName(
SectionName);
173 if (GraphSec->getMemProt() != Prot)
174 return make_error<JITLinkError>(
"MemProt should match");
178 B = &G->createZeroFillBlock(
179 *GraphSec, getSectionSize(Obj, *Sec),
181 (*Sec)->getAlignment(), 0);
184 if (
auto Err = Obj.getSectionContents(*Sec,
Data))
188 reinterpret_cast<const char *
>(
Data.data()),
Data.size());
191 if (
auto Err = handleDirectiveSection(
192 StringRef(CharData.data(), CharData.size())))
195 B = &G->createContentBlock(
197 (*Sec)->getAlignment(), 0);
209 SymbolSets.resize(Obj.getNumberOfSections() + 1);
210 PendingComdatExports.resize(Obj.getNumberOfSections() + 1);
211 GraphSymbols.resize(Obj.getNumberOfSymbols());
214 SymIndex < static_cast<COFFSymbolIndex>(Obj.getNumberOfSymbols());
218 return Sym.takeError();
222 SymbolName = *SymNameOrErr;
228 auto SecOrErr = Obj.getSection(SectionIndex);
230 return make_error<JITLinkError>(
231 "Invalid COFF section number:" +
formatv(
"{0:d}: ", SectionIndex) +
232 " (" +
toString(SecOrErr.takeError()) +
")");
235 auto InternedSymbolName = G->intern(std::move(SymbolName));
239 if (
Sym->isFileRecord())
241 dbgs() <<
" " << SymIndex <<
": Skipping FileRecord symbol \""
242 << InternedSymbolName <<
"\" in "
243 << getCOFFSectionName(SectionIndex, Sec, *
Sym)
244 <<
" (index: " << SectionIndex <<
") \n";
246 else if (
Sym->isUndefined()) {
247 GSym = createExternalSymbol(SymIndex, InternedSymbolName, *
Sym, Sec);
248 }
else if (
Sym->isWeakExternal()) {
252 WeakExternalRequests.push_back(
256 createDefinedSymbol(SymIndex, InternedSymbolName, *
Sym, Sec);
262 dbgs() <<
" " << SymIndex
263 <<
": Creating defined graph symbol for COFF symbol \""
264 << InternedSymbolName <<
"\" in "
265 << getCOFFSectionName(SectionIndex, Sec, *
Sym)
266 <<
" (index: " << SectionIndex <<
") \n";
267 dbgs() <<
" " << *GSym <<
"\n";
275 SymIndex +=
Sym->getNumberOfAuxSymbols();
278 if (
auto Err = flushWeakAliasRequests())
281 if (
auto Err = handleAlternateNames())
284 if (
auto Err = calculateImplicitSizeOfSymbols())
290Error COFFLinkGraphBuilder::handleDirectiveSection(
StringRef Str) {
291 auto Parsed = DirectiveParser.
parse(Str);
293 return Parsed.takeError();
294 for (
auto *Arg : *Parsed) {
296 switch (Arg->getOption().getID()) {
297 case COFF_OPT_alternatename: {
301 return make_error<JITLinkError>(
302 "Invalid COFF /alternatename directive");
303 AlternateNames[G->intern(
From)] = G->intern(To);
306 case COFF_OPT_incl: {
307 auto Symbol = &G->addExternalSymbol(S, 0,
false);
308 Symbol->setLive(
true);
309 ExternalSymbols[Symbol->getName()] = Symbol;
312 case COFF_OPT_export:
316 dbgs() <<
"Unknown coff directive: " << Arg->getSpelling() <<
"\n";
325Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
327 for (
auto &WeakExternal : WeakExternalRequests) {
329 Expected<object::COFFSymbolRef> AliasSymbol =
330 Obj.getSymbol(WeakExternal.Alias);
332 return AliasSymbol.takeError();
341 auto NewSymbol = createAliasSymbol(G->intern(WeakExternal.SymbolName),
344 return NewSymbol.takeError();
345 setGraphSymbol(AliasSymbol->getSectionNumber(), WeakExternal.Alias,
348 dbgs() <<
" " << WeakExternal.Alias
349 <<
": Creating weak external symbol for COFF symbol \""
350 << WeakExternal.SymbolName <<
"\" in section "
351 << AliasSymbol->getSectionNumber() <<
"\n";
352 dbgs() <<
" " << **NewSymbol <<
"\n";
355 return make_error<JITLinkError>(
"Weak symbol alias requested but actual "
356 "symbol not found for symbol " +
357 formatv(
"{0:d}", WeakExternal.Alias));
362Error COFFLinkGraphBuilder::handleAlternateNames() {
363 for (
auto &KeyValue : AlternateNames) {
364 auto DefinedSymbolName = KeyValue.second;
365 auto ExternalSymbolsName = KeyValue.first;
366 if (DefinedSymbols.count(DefinedSymbolName) &&
367 ExternalSymbols.count(ExternalSymbolsName)) {
368 auto *
Target = DefinedSymbols[DefinedSymbolName];
369 auto *Alias = ExternalSymbols[ExternalSymbolsName];
370 G->makeDefined(*Alias,
Target->getBlock(),
Target->getOffset(),
377Symbol *COFFLinkGraphBuilder::createExternalSymbol(
378 COFFSymbolIndex SymIndex, orc::SymbolStringPtr SymbolName,
379 object::COFFSymbolRef Symbol,
const object::coff_section *Section) {
381 if (!ExternalSymbols.count(SymbolName)) {
382 Sym = &G->addExternalSymbol(*SymbolName,
Symbol.getValue(),
false);
383 ExternalSymbols[
Sym->getName()] =
Sym;
389 dbgs() <<
" " << SymIndex
390 <<
": Creating external graph symbol for COFF symbol \""
391 <<
Sym->getName() <<
"\" in "
392 << getCOFFSectionName(
Symbol.getSectionNumber(), Section, Symbol)
393 <<
" (index: " <<
Symbol.getSectionNumber() <<
") \n";
399COFFLinkGraphBuilder::createAliasSymbol(orc::SymbolStringPtr SymbolName,
401 if (!
Target.isDefined()) {
403 return make_error<JITLinkError>(
"Weak external symbol with external "
404 "symbol as alternative not supported.");
406 return &G->addDefinedSymbol(
Target.getBlock(),
Target.getOffset(), SymbolName,
418Error COFFLinkGraphBuilder::calculateImplicitSizeOfSymbols() {
420 SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
422 auto &SymbolSet = SymbolSets[SecIndex];
423 if (SymbolSet.empty())
429 for (
auto It = SymbolSet.rbegin(); It != SymbolSet.rend(); It++) {
431 jitlink::Symbol *
Symbol = It->second;
434 if (
Symbol->getOffset() == LastOffset)
437 CandSize = LastOffset -
Offset;
441 dbgs() <<
" Overlapping symbol range generated for the following "
444 <<
" " << *Symbol <<
"\n";
446 (void)LastDifferentOffset;
448 LastDifferentOffset =
Offset;
463 dbgs() <<
" Empty implicit symbol size generated for the following "
466 <<
" " << *Symbol <<
"\n";
469 Symbol->setSize(CandSize);
475Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
476 COFFSymbolIndex SymIndex, orc::SymbolStringPtr SymbolName,
477 object::COFFSymbolRef Symbol,
const object::coff_section *Section) {
481 return &G->addDefinedSymbol(
482 G->createZeroFillBlock(getCommonSection(),
Symbol.getValue(),
483 orc::ExecutorAddr(),
Symbol.getValue(), 0),
489 return &G->addAbsoluteSymbol(SymbolName,
490 orc::ExecutorAddr(
Symbol.getValue()), 0,
494 return make_error<JITLinkError>(
495 "Reserved section number used in regular symbol " +
501 dbgs() <<
" " << SymIndex
502 <<
": Skipping graph symbol since section was not created for "
510 if (
Symbol.isExternal()) {
512 if (!isComdatSection(Section)) {
513 auto GSym = &G->addDefinedSymbol(
519 if (!PendingComdatExports[
Symbol.getSectionNumber()])
520 return make_error<JITLinkError>(
"No pending COMDAT export for symbol " +
523 return exportCOMDATSymbol(SymIndex, SymbolName, Symbol);
529 const object::coff_aux_section_definition *Definition =
530 Symbol.getSectionDefinition();
531 if (!Definition || !isComdatSection(Section)) {
533 return &G->addDefinedSymbol(
539 auto GSym = &G->addDefinedSymbol(
545 if (PendingComdatExports[
Symbol.getSectionNumber()])
546 return make_error<JITLinkError>(
547 "COMDAT export request already exists before symbol " +
549 return createCOMDATExportRequest(SymIndex, Symbol, Definition);
551 return make_error<JITLinkError>(
"Unsupported storage class " +
553 " in symbol " +
formatv(
"{0:d}", SymIndex));
570Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
571 COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
572 const object::coff_aux_section_definition *Definition) {
574 switch (Definition->Selection) {
594 dbgs() <<
" " << SymIndex
595 <<
": Partially supported IMAGE_COMDAT_SELECT_LARGEST was used"
597 <<
Symbol.getSectionNumber() <<
" (size: " << Definition->Length
605 return make_error<JITLinkError>(
606 "IMAGE_COMDAT_SELECT_NEWEST is not supported.");
609 return make_error<JITLinkError>(
"Invalid comdat selection type: " +
610 formatv(
"{0:d}", Definition->Selection));
613 PendingComdatExports[
Symbol.getSectionNumber()] = {SymIndex,
L,
620COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
621 orc::SymbolStringPtr SymbolName,
622 object::COFFSymbolRef Symbol) {
624 auto &PendingComdatExport = PendingComdatExports[
Symbol.getSectionNumber()];
628 auto GSym = &G->addDefinedSymbol(
629 *
B,
Symbol.getValue(), SymbolName, 0, PendingComdatExport->Linkage,
633 dbgs() <<
" " << SymIndex
634 <<
": Exporting COMDAT graph symbol for COFF symbol \"" <<
SymbolName
635 <<
"\" in section " <<
Symbol.getSectionNumber() <<
"\n";
636 dbgs() <<
" " << *GSym <<
"\n";
641 PendingComdatExport = std::nullopt;
649 auto IBN =
G.intern(ImageBaseName);
652 for (
auto *
Sym :
G.external_symbols()) {
653 if (
Sym->getName() == IBN) {
660 for (
auto *
Sym :
G.absolute_symbols()) {
661 if (
Sym->getName() == IBN) {
668 for (
auto *
Sym :
G.defined_symbols()) {
669 if (
Sym->hasName() &&
Sym->getName() == IBN) {
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static const char * CommonSectionName
COFFYAML::WeakExternalCharacteristics Characteristics
static Expected< StringRef > getFileName(const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID)
static std::optional< TypeSize > getPointerSize(const Value *V, const DataLayout &DL, const TargetLibraryInfo &TLI, const Function *F)
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()
virtual Error addRelocations()=0
Symbol * getGraphSymbol(COFFSymbolIndex SymIndex) const
COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, std::shared_ptr< orc::SymbolStringPool > SSP, Triple TT, SubtargetFeatures Features, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
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)
const char *(*)(Edge::Kind) GetEdgeKindNameFunction
bool isLittleEndian() const
StringRef getFileName() const
uint8_t getBytesInAddress() const override
The number of bytes used to represent an address in this object file format.
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)
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.
NodeAddr< BlockNode * > Block
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.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
const char * toString(DWARFSectionKind Kind)
Implement std::hash so that hash_code can be used in STL containers.
support::ulittle32_t TagIndex