14#define DEBUG_TYPE "jitlink"
52uint64_t COFFLinkGraphBuilder::getSectionSize(
const object::COFFObjectFile &Obj,
53 const object::coff_section *Sec) {
56 if (Obj.getDOSHeader())
57 return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
58 return Sec->SizeOfRawData;
62COFFLinkGraphBuilder::getSectionAddress(
const object::COFFObjectFile &Obj,
63 const object::coff_section *Section) {
64 return Section->VirtualAddress + Obj.getImageBase();
67bool COFFLinkGraphBuilder::isComdatSection(
68 const object::coff_section *Section) {
72Section &COFFLinkGraphBuilder::getCommonSection() {
76 return *CommonSection;
80 if (!Obj.isRelocatableObject())
81 return make_error<JITLinkError>(
"Object is not a relocatable COFF file");
84 return std::move(Err);
87 return std::move(Err);
90 return std::move(Err);
96COFFLinkGraphBuilder::getCOFFSectionName(COFFSectionIndex SectionIndex,
99 switch (SectionIndex) {
114 if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(Sec))
115 return *SecNameOrErr;
124 GraphBlocks.resize(Obj.getNumberOfSections() + 1);
127 SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
141 <<
"Creating section for \"" <<
SectionName <<
"\"\n";
154 auto *GraphSec = G->findSectionByName(
SectionName);
160 if (GraphSec->getMemProt() != Prot)
161 return make_error<JITLinkError>(
"MemProt should match");
165 B = &G->createZeroFillBlock(
166 *GraphSec, getSectionSize(Obj, *Sec),
168 (*Sec)->getAlignment(), 0);
171 if (
auto Err = Obj.getSectionContents(*Sec,
Data))
175 reinterpret_cast<const char *
>(
Data.data()),
Data.size());
178 if (
auto Err = handleDirectiveSection(
179 StringRef(CharData.data(), CharData.size())))
182 B = &G->createContentBlock(
184 (*Sec)->getAlignment(), 0);
196 SymbolSets.resize(Obj.getNumberOfSections() + 1);
197 PendingComdatExports.resize(Obj.getNumberOfSections() + 1);
198 GraphSymbols.resize(Obj.getNumberOfSymbols());
201 SymIndex < static_cast<COFFSymbolIndex>(Obj.getNumberOfSymbols());
209 SymbolName = *SymNameOrErr;
215 auto SecOrErr = Obj.getSection(SectionIndex);
217 return make_error<JITLinkError>(
218 "Invalid COFF section number:" +
formatv(
"{0:d}: ", SectionIndex) +
219 " (" +
toString(SecOrErr.takeError()) +
")");
225 if (Sym->isFileRecord())
227 dbgs() <<
" " << SymIndex <<
": Skipping FileRecord symbol \""
228 << SymbolName <<
"\" in "
229 << getCOFFSectionName(SectionIndex, Sec, *Sym)
230 <<
" (index: " << SectionIndex <<
") \n";
232 else if (Sym->isUndefined()) {
233 GSym = createExternalSymbol(SymIndex, SymbolName, *Sym, Sec);
234 }
else if (Sym->isWeakExternal()) {
238 WeakExternalRequests.push_back(
242 createDefinedSymbol(SymIndex, SymbolName, *Sym, Sec);
248 dbgs() <<
" " << SymIndex
249 <<
": Creating defined graph symbol for COFF symbol \""
250 << SymbolName <<
"\" in "
251 << getCOFFSectionName(SectionIndex, Sec, *Sym)
252 <<
" (index: " << SectionIndex <<
") \n";
253 dbgs() <<
" " << *GSym <<
"\n";
261 SymIndex += Sym->getNumberOfAuxSymbols();
264 if (
auto Err = flushWeakAliasRequests())
267 if (
auto Err = handleAlternateNames())
270 if (
auto Err = calculateImplicitSizeOfSymbols())
276Error COFFLinkGraphBuilder::handleDirectiveSection(
StringRef Str) {
277 auto Parsed = DirectiveParser.
parse(Str);
279 return Parsed.takeError();
280 for (
auto *
Arg : *Parsed) {
282 switch (
Arg->getOption().getID()) {
283 case COFF_OPT_alternatename: {
287 return make_error<JITLinkError>(
288 "Invalid COFF /alternatename directive");
289 AlternateNames[
From] = To;
292 case COFF_OPT_incl: {
293 auto DataCopy = G->allocateContent(S);
294 StringRef StrCopy(DataCopy.data(), DataCopy.size());
295 ExternalSymbols[StrCopy] = &G->addExternalSymbol(StrCopy, 0,
false);
296 ExternalSymbols[StrCopy]->setLive(
true);
299 case COFF_OPT_export:
303 dbgs() <<
"Unknown coff directive: " <<
Arg->getSpelling() <<
"\n";
312Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
314 for (
auto &WeakExternal : WeakExternalRequests) {
316 Expected<object::COFFSymbolRef> AliasSymbol =
317 Obj.getSymbol(WeakExternal.Alias);
319 return AliasSymbol.takeError();
329 createAliasSymbol(WeakExternal.SymbolName,
Linkage::Weak, S, *Target);
331 return NewSymbol.takeError();
332 setGraphSymbol(AliasSymbol->getSectionNumber(), WeakExternal.Alias,
335 dbgs() <<
" " << WeakExternal.Alias
336 <<
": Creating weak external symbol for COFF symbol \""
337 << WeakExternal.SymbolName <<
"\" in section "
338 << AliasSymbol->getSectionNumber() <<
"\n";
339 dbgs() <<
" " << **NewSymbol <<
"\n";
342 return make_error<JITLinkError>(
"Weak symbol alias requested but actual "
343 "symbol not found for symbol " +
344 formatv(
"{0:d}", WeakExternal.Alias));
349Error COFFLinkGraphBuilder::handleAlternateNames() {
350 for (
auto &KeyValue : AlternateNames)
351 if (DefinedSymbols.count(KeyValue.second) &&
352 ExternalSymbols.count(KeyValue.first)) {
353 auto *
Target = DefinedSymbols[KeyValue.second];
354 auto *Alias = ExternalSymbols[KeyValue.first];
355 G->makeDefined(*Alias,
Target->getBlock(),
Target->getOffset(),
361Symbol *COFFLinkGraphBuilder::createExternalSymbol(
362 COFFSymbolIndex SymIndex, StringRef SymbolName,
363 object::COFFSymbolRef Symbol,
const object::coff_section *Section) {
364 if (!ExternalSymbols.count(SymbolName))
366 &G->addExternalSymbol(SymbolName,
Symbol.getValue(),
false);
369 dbgs() <<
" " << SymIndex
370 <<
": Creating external graph symbol for COFF symbol \""
372 << getCOFFSectionName(
Symbol.getSectionNumber(), Section, Symbol)
373 <<
" (index: " <<
Symbol.getSectionNumber() <<
") \n";
378Expected<Symbol *> COFFLinkGraphBuilder::createAliasSymbol(StringRef SymbolName,
381 if (!
Target.isDefined()) {
383 return make_error<JITLinkError>(
"Weak external symbol with external "
384 "symbol as alternative not supported.");
386 return &G->addDefinedSymbol(
Target.getBlock(),
Target.getOffset(), SymbolName,
398Error COFFLinkGraphBuilder::calculateImplicitSizeOfSymbols() {
400 SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
402 auto &SymbolSet = SymbolSets[SecIndex];
403 if (SymbolSet.empty())
409 for (
auto It = SymbolSet.rbegin(); It != SymbolSet.rend(); It++) {
411 jitlink::Symbol *
Symbol = It->second;
414 if (
Symbol->getOffset() == LastOffset)
417 CandSize = LastOffset -
Offset;
421 dbgs() <<
" Overlapping symbol range generated for the following "
424 <<
" " << *Symbol <<
"\n";
426 (void)LastDifferentOffset;
428 LastDifferentOffset =
Offset;
443 dbgs() <<
" Empty implicit symbol size generated for the following "
446 <<
" " << *Symbol <<
"\n";
449 Symbol->setSize(CandSize);
455Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
456 COFFSymbolIndex SymIndex, StringRef SymbolName,
457 object::COFFSymbolRef Symbol,
const object::coff_section *Section) {
460 return &G->addDefinedSymbol(
461 G->createZeroFillBlock(getCommonSection(),
Symbol.getValue(),
462 orc::ExecutorAddr(),
Symbol.getValue(), 0),
467 return &G->addAbsoluteSymbol(SymbolName,
468 orc::ExecutorAddr(
Symbol.getValue()), 0,
472 return make_error<JITLinkError>(
473 "Reserved section number used in regular symbol " +
479 dbgs() <<
" " << SymIndex
480 <<
": Skipping graph symbol since section was not created for "
488 if (
Symbol.isExternal()) {
490 if (!isComdatSection(Section)) {
491 auto GSym = &G->addDefinedSymbol(
497 if (!PendingComdatExports[
Symbol.getSectionNumber()])
498 return make_error<JITLinkError>(
"No pending COMDAT export for symbol " +
501 return exportCOMDATSymbol(SymIndex, SymbolName, Symbol);
507 const object::coff_aux_section_definition *Definition =
508 Symbol.getSectionDefinition();
509 if (!Definition || !isComdatSection(Section)) {
511 return &G->addDefinedSymbol(
517 auto GSym = &G->addDefinedSymbol(
523 if (PendingComdatExports[
Symbol.getSectionNumber()])
524 return make_error<JITLinkError>(
525 "COMDAT export request already exists before symbol " +
527 return createCOMDATExportRequest(SymIndex, Symbol, Definition);
529 return make_error<JITLinkError>(
"Unsupported storage class " +
531 " in symbol " +
formatv(
"{0:d}", SymIndex));
548Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
549 COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
550 const object::coff_aux_section_definition *Definition) {
552 switch (Definition->Selection) {
572 dbgs() <<
" " << SymIndex
573 <<
": Partially supported IMAGE_COMDAT_SELECT_LARGEST was used"
575 <<
Symbol.getSectionNumber() <<
" (size: " << Definition->Length
583 return make_error<JITLinkError>(
584 "IMAGE_COMDAT_SELECT_NEWEST is not supported.");
587 return make_error<JITLinkError>(
"Invalid comdat selection type: " +
588 formatv(
"{0:d}", Definition->Selection));
591 PendingComdatExports[
Symbol.getSectionNumber()] = {SymIndex,
L,
598COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
599 StringRef SymbolName,
600 object::COFFSymbolRef Symbol) {
602 auto &PendingComdatExport = PendingComdatExports[
Symbol.getSectionNumber()];
606 auto GSym = &G->addDefinedSymbol(
607 *
B,
Symbol.getValue(), SymbolName, 0, PendingComdatExport->Linkage,
611 dbgs() <<
" " << SymIndex
612 <<
": Exporting COMDAT graph symbol for COFF symbol \"" <<
SymbolName
613 <<
"\" in section " <<
Symbol.getSectionNumber() <<
"\n";
614 dbgs() <<
" " << *GSym <<
"\n";
619 PendingComdatExport = std::nullopt;
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
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.
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
virtual ~COFFLinkGraphBuilder()
Block * getGraphBlock(COFFSectionIndex SecIndex) const
void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex, Symbol &Sym)
void setGraphBlock(COFFSectionIndex SecIndex, Block *B)
COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
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.
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.
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.
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.
support::ulittle32_t TagIndex