14#define DEBUG_TYPE "jitlink"
32 getEndianness(Obj),
std::
move(GetEdgeKindName))) {
51uint64_t COFFLinkGraphBuilder::getSectionSize(
const object::COFFObjectFile &Obj,
52 const object::coff_section *Sec) {
55 if (Obj.getDOSHeader())
56 return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
57 return Sec->SizeOfRawData;
61COFFLinkGraphBuilder::getSectionAddress(
const object::COFFObjectFile &Obj,
62 const object::coff_section *Section) {
63 return Section->VirtualAddress + Obj.getImageBase();
66bool COFFLinkGraphBuilder::isComdatSection(
67 const object::coff_section *Section) {
71Section &COFFLinkGraphBuilder::getCommonSection() {
75 return *CommonSection;
79 if (!Obj.isRelocatableObject())
80 return make_error<JITLinkError>(
"Object is not a relocatable COFF file");
83 return std::move(Err);
86 return std::move(Err);
89 return std::move(Err);
95COFFLinkGraphBuilder::getCOFFSectionName(COFFSectionIndex SectionIndex,
98 switch (SectionIndex) {
113 if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(Sec))
114 return *SecNameOrErr;
123 GraphBlocks.resize(Obj.getNumberOfSections() + 1);
126 SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
147 <<
"Creating section for \"" <<
SectionName <<
"\"\n";
160 auto *GraphSec = G->findSectionByName(
SectionName);
166 if (GraphSec->getMemProt() != Prot)
167 return make_error<JITLinkError>(
"MemProt should match");
171 B = &G->createZeroFillBlock(
172 *GraphSec, getSectionSize(Obj, *Sec),
174 (*Sec)->getAlignment(), 0);
177 if (
auto Err = Obj.getSectionContents(*Sec,
Data))
181 reinterpret_cast<const char *
>(
Data.data()),
Data.size());
184 if (
auto Err = handleDirectiveSection(
185 StringRef(CharData.data(), CharData.size())))
188 B = &G->createContentBlock(
190 (*Sec)->getAlignment(), 0);
202 SymbolSets.resize(Obj.getNumberOfSections() + 1);
203 PendingComdatExports.resize(Obj.getNumberOfSections() + 1);
204 GraphSymbols.resize(Obj.getNumberOfSymbols());
207 SymIndex < static_cast<COFFSymbolIndex>(Obj.getNumberOfSymbols());
211 return Sym.takeError();
215 SymbolName = *SymNameOrErr;
221 auto SecOrErr = Obj.getSection(SectionIndex);
223 return make_error<JITLinkError>(
224 "Invalid COFF section number:" +
formatv(
"{0:d}: ", SectionIndex) +
225 " (" +
toString(SecOrErr.takeError()) +
")");
231 if (
Sym->isFileRecord())
233 dbgs() <<
" " << SymIndex <<
": Skipping FileRecord symbol \""
234 << SymbolName <<
"\" in "
235 << getCOFFSectionName(SectionIndex, Sec, *
Sym)
236 <<
" (index: " << SectionIndex <<
") \n";
238 else if (
Sym->isUndefined()) {
239 GSym = createExternalSymbol(SymIndex, SymbolName, *
Sym, Sec);
240 }
else if (
Sym->isWeakExternal()) {
244 WeakExternalRequests.push_back(
248 createDefinedSymbol(SymIndex, SymbolName, *
Sym, Sec);
254 dbgs() <<
" " << SymIndex
255 <<
": Creating defined graph symbol for COFF symbol \""
256 << SymbolName <<
"\" in "
257 << getCOFFSectionName(SectionIndex, Sec, *
Sym)
258 <<
" (index: " << SectionIndex <<
") \n";
259 dbgs() <<
" " << *GSym <<
"\n";
267 SymIndex +=
Sym->getNumberOfAuxSymbols();
270 if (
auto Err = flushWeakAliasRequests())
273 if (
auto Err = handleAlternateNames())
276 if (
auto Err = calculateImplicitSizeOfSymbols())
282Error COFFLinkGraphBuilder::handleDirectiveSection(
StringRef Str) {
283 auto Parsed = DirectiveParser.
parse(Str);
285 return Parsed.takeError();
286 for (
auto *Arg : *Parsed) {
288 switch (Arg->getOption().getID()) {
289 case COFF_OPT_alternatename: {
293 return make_error<JITLinkError>(
294 "Invalid COFF /alternatename directive");
295 AlternateNames[
From] = To;
298 case COFF_OPT_incl: {
299 auto DataCopy = G->allocateContent(S);
300 StringRef StrCopy(DataCopy.data(), DataCopy.size());
301 ExternalSymbols[StrCopy] = &G->addExternalSymbol(StrCopy, 0,
false);
302 ExternalSymbols[StrCopy]->setLive(
true);
305 case COFF_OPT_export:
309 dbgs() <<
"Unknown coff directive: " << Arg->getSpelling() <<
"\n";
318Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
320 for (
auto &WeakExternal : WeakExternalRequests) {
322 Expected<object::COFFSymbolRef> AliasSymbol =
323 Obj.getSymbol(WeakExternal.Alias);
325 return AliasSymbol.takeError();
335 createAliasSymbol(WeakExternal.SymbolName,
Linkage::Weak, S, *Target);
337 return NewSymbol.takeError();
338 setGraphSymbol(AliasSymbol->getSectionNumber(), WeakExternal.Alias,
341 dbgs() <<
" " << WeakExternal.Alias
342 <<
": Creating weak external symbol for COFF symbol \""
343 << WeakExternal.SymbolName <<
"\" in section "
344 << AliasSymbol->getSectionNumber() <<
"\n";
345 dbgs() <<
" " << **NewSymbol <<
"\n";
348 return make_error<JITLinkError>(
"Weak symbol alias requested but actual "
349 "symbol not found for symbol " +
350 formatv(
"{0:d}", WeakExternal.Alias));
355Error COFFLinkGraphBuilder::handleAlternateNames() {
356 for (
auto &KeyValue : AlternateNames)
357 if (DefinedSymbols.count(KeyValue.second) &&
358 ExternalSymbols.count(KeyValue.first)) {
359 auto *
Target = DefinedSymbols[KeyValue.second];
360 auto *Alias = ExternalSymbols[KeyValue.first];
361 G->makeDefined(*Alias,
Target->getBlock(),
Target->getOffset(),
367Symbol *COFFLinkGraphBuilder::createExternalSymbol(
368 COFFSymbolIndex SymIndex, StringRef SymbolName,
369 object::COFFSymbolRef Symbol,
const object::coff_section *Section) {
370 if (!ExternalSymbols.count(SymbolName))
372 &G->addExternalSymbol(SymbolName,
Symbol.getValue(),
false);
375 dbgs() <<
" " << SymIndex
376 <<
": Creating external graph symbol for COFF symbol \""
378 << getCOFFSectionName(
Symbol.getSectionNumber(), Section, Symbol)
379 <<
" (index: " <<
Symbol.getSectionNumber() <<
") \n";
384Expected<Symbol *> COFFLinkGraphBuilder::createAliasSymbol(StringRef SymbolName,
387 if (!
Target.isDefined()) {
389 return make_error<JITLinkError>(
"Weak external symbol with external "
390 "symbol as alternative not supported.");
392 return &G->addDefinedSymbol(
Target.getBlock(),
Target.getOffset(), SymbolName,
404Error COFFLinkGraphBuilder::calculateImplicitSizeOfSymbols() {
406 SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
408 auto &SymbolSet = SymbolSets[SecIndex];
409 if (SymbolSet.empty())
415 for (
auto It = SymbolSet.rbegin(); It != SymbolSet.rend(); It++) {
417 jitlink::Symbol *
Symbol = It->second;
420 if (
Symbol->getOffset() == LastOffset)
423 CandSize = LastOffset -
Offset;
427 dbgs() <<
" Overlapping symbol range generated for the following "
430 <<
" " << *Symbol <<
"\n";
432 (void)LastDifferentOffset;
434 LastDifferentOffset =
Offset;
449 dbgs() <<
" Empty implicit symbol size generated for the following "
452 <<
" " << *Symbol <<
"\n";
455 Symbol->setSize(CandSize);
461Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
462 COFFSymbolIndex SymIndex, StringRef SymbolName,
463 object::COFFSymbolRef Symbol,
const object::coff_section *Section) {
466 return &G->addDefinedSymbol(
467 G->createZeroFillBlock(getCommonSection(),
Symbol.getValue(),
468 orc::ExecutorAddr(),
Symbol.getValue(), 0),
473 return &G->addAbsoluteSymbol(SymbolName,
474 orc::ExecutorAddr(
Symbol.getValue()), 0,
478 return make_error<JITLinkError>(
479 "Reserved section number used in regular symbol " +
485 dbgs() <<
" " << SymIndex
486 <<
": Skipping graph symbol since section was not created for "
494 if (
Symbol.isExternal()) {
496 if (!isComdatSection(Section)) {
497 auto GSym = &G->addDefinedSymbol(
503 if (!PendingComdatExports[
Symbol.getSectionNumber()])
504 return make_error<JITLinkError>(
"No pending COMDAT export for symbol " +
507 return exportCOMDATSymbol(SymIndex, SymbolName, Symbol);
513 const object::coff_aux_section_definition *Definition =
514 Symbol.getSectionDefinition();
515 if (!Definition || !isComdatSection(Section)) {
517 return &G->addDefinedSymbol(
523 auto GSym = &G->addDefinedSymbol(
529 if (PendingComdatExports[
Symbol.getSectionNumber()])
530 return make_error<JITLinkError>(
531 "COMDAT export request already exists before symbol " +
533 return createCOMDATExportRequest(SymIndex, Symbol, Definition);
535 return make_error<JITLinkError>(
"Unsupported storage class " +
537 " in symbol " +
formatv(
"{0:d}", SymIndex));
554Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
555 COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
556 const object::coff_aux_section_definition *Definition) {
558 switch (Definition->Selection) {
578 dbgs() <<
" " << SymIndex
579 <<
": Partially supported IMAGE_COMDAT_SELECT_LARGEST was used"
581 <<
Symbol.getSectionNumber() <<
" (size: " << Definition->Length
589 return make_error<JITLinkError>(
590 "IMAGE_COMDAT_SELECT_NEWEST is not supported.");
593 return make_error<JITLinkError>(
"Invalid comdat selection type: " +
594 formatv(
"{0:d}", Definition->Selection));
597 PendingComdatExports[
Symbol.getSectionNumber()] = {SymIndex,
L,
604COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
605 StringRef SymbolName,
606 object::COFFSymbolRef Symbol) {
608 auto &PendingComdatExport = PendingComdatExports[
Symbol.getSectionNumber()];
612 auto GSym = &G->addDefinedSymbol(
613 *
B,
Symbol.getValue(), SymbolName, 0, PendingComdatExport->Linkage,
617 dbgs() <<
" " << SymIndex
618 <<
": Exporting COMDAT graph symbol for COFF symbol \"" <<
SymbolName
619 <<
"\" in section " <<
Symbol.getSectionNumber() <<
"\n";
620 dbgs() <<
" " << *GSym <<
"\n";
625 PendingComdatExport = std::nullopt;
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 uint64_t 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
COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT, SubtargetFeatures Features, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
Symbol * getGraphSymbol(COFFSymbolIndex SymIndex) const
virtual ~COFFLinkGraphBuilder()
Block * getGraphBlock(COFFSectionIndex SecIndex) const
void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex, Symbol &Sym)
void setGraphBlock(COFFSectionIndex SecIndex, Block *B)
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.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
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(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< 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.
Implement std::hash so that hash_code can be used in STL containers.
support::ulittle32_t TagIndex