14#define DEBUG_TYPE "jitlink"
32 getEndianness(Obj),
std::
move(GetEdgeKindName))) {
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());
148 <<
"Creating section for \"" <<
SectionName <<
"\"\n";
161 auto *GraphSec = G->findSectionByName(
SectionName);
167 if (GraphSec->getMemProt() != Prot)
168 return make_error<JITLinkError>(
"MemProt should match");
172 B = &G->createZeroFillBlock(
173 *GraphSec, getSectionSize(Obj, *Sec),
175 (*Sec)->getAlignment(), 0);
178 if (
auto Err = Obj.getSectionContents(*Sec,
Data))
182 reinterpret_cast<const char *
>(
Data.data()),
Data.size());
185 if (
auto Err = handleDirectiveSection(
186 StringRef(CharData.data(), CharData.size())))
189 B = &G->createContentBlock(
191 (*Sec)->getAlignment(), 0);
203 SymbolSets.resize(Obj.getNumberOfSections() + 1);
204 PendingComdatExports.resize(Obj.getNumberOfSections() + 1);
205 GraphSymbols.resize(Obj.getNumberOfSymbols());
208 SymIndex < static_cast<COFFSymbolIndex>(Obj.getNumberOfSymbols());
212 return Sym.takeError();
216 SymbolName = *SymNameOrErr;
222 auto SecOrErr = Obj.getSection(SectionIndex);
224 return make_error<JITLinkError>(
225 "Invalid COFF section number:" +
formatv(
"{0:d}: ", SectionIndex) +
226 " (" +
toString(SecOrErr.takeError()) +
")");
232 if (
Sym->isFileRecord())
234 dbgs() <<
" " << SymIndex <<
": Skipping FileRecord symbol \""
235 << SymbolName <<
"\" in "
236 << getCOFFSectionName(SectionIndex, Sec, *
Sym)
237 <<
" (index: " << SectionIndex <<
") \n";
239 else if (
Sym->isUndefined()) {
240 GSym = createExternalSymbol(SymIndex, SymbolName, *
Sym, Sec);
241 }
else if (
Sym->isWeakExternal()) {
245 WeakExternalRequests.push_back(
249 createDefinedSymbol(SymIndex, SymbolName, *
Sym, Sec);
255 dbgs() <<
" " << SymIndex
256 <<
": Creating defined graph symbol for COFF symbol \""
257 << SymbolName <<
"\" in "
258 << getCOFFSectionName(SectionIndex, Sec, *
Sym)
259 <<
" (index: " << SectionIndex <<
") \n";
260 dbgs() <<
" " << *GSym <<
"\n";
268 SymIndex +=
Sym->getNumberOfAuxSymbols();
271 if (
auto Err = flushWeakAliasRequests())
274 if (
auto Err = handleAlternateNames())
277 if (
auto Err = calculateImplicitSizeOfSymbols())
283Error COFFLinkGraphBuilder::handleDirectiveSection(
StringRef Str) {
284 auto Parsed = DirectiveParser.
parse(Str);
286 return Parsed.takeError();
287 for (
auto *Arg : *Parsed) {
289 switch (Arg->getOption().getID()) {
290 case COFF_OPT_alternatename: {
294 return make_error<JITLinkError>(
295 "Invalid COFF /alternatename directive");
296 AlternateNames[
From] = To;
299 case COFF_OPT_incl: {
300 auto DataCopy = G->allocateContent(S);
301 StringRef StrCopy(DataCopy.data(), DataCopy.size());
302 ExternalSymbols[StrCopy] = &G->addExternalSymbol(StrCopy, 0,
false);
303 ExternalSymbols[StrCopy]->setLive(
true);
306 case COFF_OPT_export:
310 dbgs() <<
"Unknown coff directive: " << Arg->getSpelling() <<
"\n";
319Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
321 for (
auto &WeakExternal : WeakExternalRequests) {
323 Expected<object::COFFSymbolRef> AliasSymbol =
324 Obj.getSymbol(WeakExternal.Alias);
326 return AliasSymbol.takeError();
336 createAliasSymbol(WeakExternal.SymbolName,
Linkage::Weak, S, *Target);
338 return NewSymbol.takeError();
339 setGraphSymbol(AliasSymbol->getSectionNumber(), WeakExternal.Alias,
342 dbgs() <<
" " << WeakExternal.Alias
343 <<
": Creating weak external symbol for COFF symbol \""
344 << WeakExternal.SymbolName <<
"\" in section "
345 << AliasSymbol->getSectionNumber() <<
"\n";
346 dbgs() <<
" " << **NewSymbol <<
"\n";
349 return make_error<JITLinkError>(
"Weak symbol alias requested but actual "
350 "symbol not found for symbol " +
351 formatv(
"{0:d}", WeakExternal.Alias));
356Error COFFLinkGraphBuilder::handleAlternateNames() {
357 for (
auto &KeyValue : AlternateNames)
358 if (DefinedSymbols.count(KeyValue.second) &&
359 ExternalSymbols.count(KeyValue.first)) {
360 auto *
Target = DefinedSymbols[KeyValue.second];
361 auto *Alias = ExternalSymbols[KeyValue.first];
362 G->makeDefined(*Alias,
Target->getBlock(),
Target->getOffset(),
368Symbol *COFFLinkGraphBuilder::createExternalSymbol(
369 COFFSymbolIndex SymIndex, StringRef SymbolName,
370 object::COFFSymbolRef Symbol,
const object::coff_section *Section) {
371 if (!ExternalSymbols.count(SymbolName))
373 &G->addExternalSymbol(SymbolName,
Symbol.getValue(),
false);
376 dbgs() <<
" " << SymIndex
377 <<
": Creating external graph symbol for COFF symbol \""
379 << getCOFFSectionName(
Symbol.getSectionNumber(), Section, Symbol)
380 <<
" (index: " <<
Symbol.getSectionNumber() <<
") \n";
385Expected<Symbol *> COFFLinkGraphBuilder::createAliasSymbol(StringRef SymbolName,
388 if (!
Target.isDefined()) {
390 return make_error<JITLinkError>(
"Weak external symbol with external "
391 "symbol as alternative not supported.");
393 return &G->addDefinedSymbol(
Target.getBlock(),
Target.getOffset(), SymbolName,
405Error COFFLinkGraphBuilder::calculateImplicitSizeOfSymbols() {
407 SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
409 auto &SymbolSet = SymbolSets[SecIndex];
410 if (SymbolSet.empty())
416 for (
auto It = SymbolSet.rbegin(); It != SymbolSet.rend(); It++) {
418 jitlink::Symbol *
Symbol = It->second;
421 if (
Symbol->getOffset() == LastOffset)
424 CandSize = LastOffset -
Offset;
428 dbgs() <<
" Overlapping symbol range generated for the following "
431 <<
" " << *Symbol <<
"\n";
433 (void)LastDifferentOffset;
435 LastDifferentOffset =
Offset;
450 dbgs() <<
" Empty implicit symbol size generated for the following "
453 <<
" " << *Symbol <<
"\n";
456 Symbol->setSize(CandSize);
462Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
463 COFFSymbolIndex SymIndex, StringRef SymbolName,
464 object::COFFSymbolRef Symbol,
const object::coff_section *Section) {
467 return &G->addDefinedSymbol(
468 G->createZeroFillBlock(getCommonSection(),
Symbol.getValue(),
469 orc::ExecutorAddr(),
Symbol.getValue(), 0),
474 return &G->addAbsoluteSymbol(SymbolName,
475 orc::ExecutorAddr(
Symbol.getValue()), 0,
479 return make_error<JITLinkError>(
480 "Reserved section number used in regular symbol " +
486 dbgs() <<
" " << SymIndex
487 <<
": Skipping graph symbol since section was not created for "
495 if (
Symbol.isExternal()) {
497 if (!isComdatSection(Section)) {
498 auto GSym = &G->addDefinedSymbol(
504 if (!PendingComdatExports[
Symbol.getSectionNumber()])
505 return make_error<JITLinkError>(
"No pending COMDAT export for symbol " +
508 return exportCOMDATSymbol(SymIndex, SymbolName, Symbol);
514 const object::coff_aux_section_definition *Definition =
515 Symbol.getSectionDefinition();
516 if (!Definition || !isComdatSection(Section)) {
518 return &G->addDefinedSymbol(
524 auto GSym = &G->addDefinedSymbol(
530 if (PendingComdatExports[
Symbol.getSectionNumber()])
531 return make_error<JITLinkError>(
532 "COMDAT export request already exists before symbol " +
534 return createCOMDATExportRequest(SymIndex, Symbol, Definition);
536 return make_error<JITLinkError>(
"Unsupported storage class " +
538 " in symbol " +
formatv(
"{0:d}", SymIndex));
555Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
556 COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
557 const object::coff_aux_section_definition *Definition) {
559 switch (Definition->Selection) {
579 dbgs() <<
" " << SymIndex
580 <<
": Partially supported IMAGE_COMDAT_SELECT_LARGEST was used"
582 <<
Symbol.getSectionNumber() <<
" (size: " << Definition->Length
590 return make_error<JITLinkError>(
591 "IMAGE_COMDAT_SELECT_NEWEST is not supported.");
594 return make_error<JITLinkError>(
"Invalid comdat selection type: " +
595 formatv(
"{0:d}", Definition->Selection));
598 PendingComdatExports[
Symbol.getSectionNumber()] = {SymIndex,
L,
605COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
606 StringRef SymbolName,
607 object::COFFSymbolRef Symbol) {
609 auto &PendingComdatExport = PendingComdatExports[
Symbol.getSectionNumber()];
613 auto GSym = &G->addDefinedSymbol(
614 *
B,
Symbol.getValue(), SymbolName, 0, PendingComdatExport->Linkage,
618 dbgs() <<
" " << SymIndex
619 <<
": Exporting COMDAT graph symbol for COFF symbol \"" <<
SymbolName
620 <<
"\" in section " <<
Symbol.getSectionNumber() <<
"\n";
621 dbgs() <<
" " << *GSym <<
"\n";
626 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 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
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(support::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