LLVM 20.0.0git
COFFLinkGraphBuilder.cpp
Go to the documentation of this file.
1//=--------- COFFLinkGraphBuilder.cpp - COFF LinkGraph builder ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Generic COFF LinkGraph building code.
10//
11//===----------------------------------------------------------------------===//
13
14#include <memory>
15
16#define DEBUG_TYPE "jitlink"
17
18static const char *CommonSectionName = "__common";
19
20namespace llvm {
21namespace jitlink {
22
24 T.setObjectFormat(Triple::COFF);
25 return T;
26}
27
29 const object::COFFObjectFile &Obj,
30 std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,
31 SubtargetFeatures Features,
33 : Obj(Obj),
34 G(std::make_unique<LinkGraph>(Obj.getFileName().str(), std::move(SSP),
36 std::move(Features), getPointerSize(Obj),
37 getEndianness(Obj),
38 std::move(GetEdgeKindName))) {
40 dbgs() << "Created COFFLinkGraphBuilder for \"" << Obj.getFileName()
41 << "\"\n";
42 });
43}
44
46
47unsigned
48COFFLinkGraphBuilder::getPointerSize(const object::COFFObjectFile &Obj) {
49 return Obj.getBytesInAddress();
50}
51
53COFFLinkGraphBuilder::getEndianness(const object::COFFObjectFile &Obj) {
56}
57
58uint64_t COFFLinkGraphBuilder::getSectionSize(const object::COFFObjectFile &Obj,
59 const object::coff_section *Sec) {
60 // Consider the difference between executable form and object form.
61 // More information is inside COFFObjectFile::getSectionSize
62 if (Obj.getDOSHeader())
63 return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
64 return Sec->SizeOfRawData;
65}
66
68COFFLinkGraphBuilder::getSectionAddress(const object::COFFObjectFile &Obj,
69 const object::coff_section *Section) {
70 return Section->VirtualAddress + Obj.getImageBase();
71}
72
73bool COFFLinkGraphBuilder::isComdatSection(
74 const object::coff_section *Section) {
75 return Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT;
76}
77
78Section &COFFLinkGraphBuilder::getCommonSection() {
79 if (!CommonSection)
80 CommonSection = &G->createSection(CommonSectionName,
82 return *CommonSection;
83}
84
86 if (!Obj.isRelocatableObject())
87 return make_error<JITLinkError>("Object is not a relocatable COFF file");
88
89 if (auto Err = graphifySections())
90 return std::move(Err);
91
92 if (auto Err = graphifySymbols())
93 return std::move(Err);
94
95 if (auto Err = addRelocations())
96 return std::move(Err);
97
98 return std::move(G);
99}
100
102COFFLinkGraphBuilder::getCOFFSectionName(COFFSectionIndex SectionIndex,
103 const object::coff_section *Sec,
105 switch (SectionIndex) {
107 if (Sym.getValue())
108 return "(common)";
109 else
110 return "(external)";
111 }
113 return "(absolute)";
115 // Used with .file symbol
116 return "(debug)";
117 }
118 default: {
119 // Non reserved regular section numbers
120 if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(Sec))
121 return *SecNameOrErr;
122 }
123 }
124 return "";
125}
126
128 LLVM_DEBUG(dbgs() << " Creating graph sections...\n");
129
130 GraphBlocks.resize(Obj.getNumberOfSections() + 1);
131 // For each section...
132 for (COFFSectionIndex SecIndex = 1;
133 SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
134 SecIndex++) {
135 Expected<const object::coff_section *> Sec = Obj.getSection(SecIndex);
136 if (!Sec)
137 return Sec.takeError();
138
140 if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(*Sec))
141 SectionName = *SecNameOrErr;
142
143 // FIXME: Skip debug info sections
144 if (SectionName == ".voltbl") {
145 LLVM_DEBUG({
146 dbgs() << " "
147 << "Skipping section \"" << SectionName << "\"\n";
148 });
149 continue;
150 }
151
152 LLVM_DEBUG({
153 dbgs() << " "
154 << "Creating section for \"" << SectionName << "\"\n";
155 });
156
157 // Get the section's memory protection flags.
159 if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_EXECUTE)
160 Prot |= orc::MemProt::Exec;
161 if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_READ)
162 Prot |= orc::MemProt::Read;
163 if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_WRITE)
164 Prot |= orc::MemProt::Write;
165
166 // Look for existing sections first.
167 auto *GraphSec = G->findSectionByName(SectionName);
168 if (!GraphSec) {
169 GraphSec = &G->createSection(SectionName, Prot);
170 if ((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_REMOVE)
171 GraphSec->setMemLifetime(orc::MemLifetime::NoAlloc);
172 }
173 if (GraphSec->getMemProt() != Prot)
174 return make_error<JITLinkError>("MemProt should match");
175
176 Block *B = nullptr;
177 if ((*Sec)->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
178 B = &G->createZeroFillBlock(
179 *GraphSec, getSectionSize(Obj, *Sec),
180 orc::ExecutorAddr(getSectionAddress(Obj, *Sec)),
181 (*Sec)->getAlignment(), 0);
182 else {
184 if (auto Err = Obj.getSectionContents(*Sec, Data))
185 return Err;
186
187 auto CharData = ArrayRef<char>(
188 reinterpret_cast<const char *>(Data.data()), Data.size());
189
190 if (SectionName == getDirectiveSectionName())
191 if (auto Err = handleDirectiveSection(
192 StringRef(CharData.data(), CharData.size())))
193 return Err;
194
195 B = &G->createContentBlock(
196 *GraphSec, CharData, orc::ExecutorAddr(getSectionAddress(Obj, *Sec)),
197 (*Sec)->getAlignment(), 0);
198 }
199
200 setGraphBlock(SecIndex, B);
201 }
202
203 return Error::success();
204}
205
207 LLVM_DEBUG(dbgs() << " Creating graph symbols...\n");
208
209 SymbolSets.resize(Obj.getNumberOfSections() + 1);
210 PendingComdatExports.resize(Obj.getNumberOfSections() + 1);
211 GraphSymbols.resize(Obj.getNumberOfSymbols());
212
213 for (COFFSymbolIndex SymIndex = 0;
214 SymIndex < static_cast<COFFSymbolIndex>(Obj.getNumberOfSymbols());
215 SymIndex++) {
216 Expected<object::COFFSymbolRef> Sym = Obj.getSymbol(SymIndex);
217 if (!Sym)
218 return Sym.takeError();
219
220 StringRef SymbolName;
221 if (Expected<StringRef> SymNameOrErr = Obj.getSymbolName(*Sym))
222 SymbolName = *SymNameOrErr;
223
224 COFFSectionIndex SectionIndex = Sym->getSectionNumber();
225 const object::coff_section *Sec = nullptr;
226
227 if (!COFF::isReservedSectionNumber(SectionIndex)) {
228 auto SecOrErr = Obj.getSection(SectionIndex);
229 if (!SecOrErr)
230 return make_error<JITLinkError>(
231 "Invalid COFF section number:" + formatv("{0:d}: ", SectionIndex) +
232 " (" + toString(SecOrErr.takeError()) + ")");
233 Sec = *SecOrErr;
234 }
235 auto InternedSymbolName = G->intern(std::move(SymbolName));
236
237 // Create jitlink symbol
238 jitlink::Symbol *GSym = nullptr;
239 if (Sym->isFileRecord())
240 LLVM_DEBUG({
241 dbgs() << " " << SymIndex << ": Skipping FileRecord symbol \""
242 << InternedSymbolName << "\" in "
243 << getCOFFSectionName(SectionIndex, Sec, *Sym)
244 << " (index: " << SectionIndex << ") \n";
245 });
246 else if (Sym->isUndefined()) {
247 GSym = createExternalSymbol(SymIndex, InternedSymbolName, *Sym, Sec);
248 } else if (Sym->isWeakExternal()) {
249 auto *WeakExternal = Sym->getAux<object::coff_aux_weak_external>();
250 COFFSymbolIndex TagIndex = WeakExternal->TagIndex;
251 uint32_t Characteristics = WeakExternal->Characteristics;
252 WeakExternalRequests.push_back(
253 {SymIndex, TagIndex, Characteristics, SymbolName});
254 } else {
256 createDefinedSymbol(SymIndex, InternedSymbolName, *Sym, Sec);
257 if (!NewGSym)
258 return NewGSym.takeError();
259 GSym = *NewGSym;
260 if (GSym) {
261 LLVM_DEBUG({
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";
268 });
269 }
270 }
271
272 // Register the symbol
273 if (GSym)
274 setGraphSymbol(SectionIndex, SymIndex, *GSym);
275 SymIndex += Sym->getNumberOfAuxSymbols();
276 }
277
278 if (auto Err = flushWeakAliasRequests())
279 return Err;
280
281 if (auto Err = handleAlternateNames())
282 return Err;
283
284 if (auto Err = calculateImplicitSizeOfSymbols())
285 return Err;
286
287 return Error::success();
288}
289
290Error COFFLinkGraphBuilder::handleDirectiveSection(StringRef Str) {
291 auto Parsed = DirectiveParser.parse(Str);
292 if (!Parsed)
293 return Parsed.takeError();
294 for (auto *Arg : *Parsed) {
295 StringRef S = Arg->getValue();
296 switch (Arg->getOption().getID()) {
297 case COFF_OPT_alternatename: {
298 StringRef From, To;
299 std::tie(From, To) = S.split('=');
300 if (From.empty() || To.empty())
301 return make_error<JITLinkError>(
302 "Invalid COFF /alternatename directive");
303 AlternateNames[G->intern(From)] = G->intern(To);
304 break;
305 }
306 case COFF_OPT_incl: {
307 auto Symbol = &G->addExternalSymbol(S, 0, false);
308 Symbol->setLive(true);
309 ExternalSymbols[Symbol->getName()] = Symbol;
310 break;
311 }
312 case COFF_OPT_export:
313 break;
314 default: {
315 LLVM_DEBUG({
316 dbgs() << "Unknown coff directive: " << Arg->getSpelling() << "\n";
317 });
318 break;
319 }
320 }
321 }
322 return Error::success();
323}
324
325Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
326 // Export the weak external symbols and alias it
327 for (auto &WeakExternal : WeakExternalRequests) {
328 if (auto *Target = getGraphSymbol(WeakExternal.Target)) {
329 Expected<object::COFFSymbolRef> AliasSymbol =
330 Obj.getSymbol(WeakExternal.Alias);
331 if (!AliasSymbol)
332 return AliasSymbol.takeError();
333
334 // FIXME: IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY and
335 // IMAGE_WEAK_EXTERN_SEARCH_LIBRARY are handled in the same way.
336 Scope S =
337 WeakExternal.Characteristics == COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS
339 : Scope::Local;
340
341 auto NewSymbol = createAliasSymbol(G->intern(WeakExternal.SymbolName),
342 Linkage::Weak, S, *Target);
343 if (!NewSymbol)
344 return NewSymbol.takeError();
345 setGraphSymbol(AliasSymbol->getSectionNumber(), WeakExternal.Alias,
346 **NewSymbol);
347 LLVM_DEBUG({
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";
353 });
354 } else
355 return make_error<JITLinkError>("Weak symbol alias requested but actual "
356 "symbol not found for symbol " +
357 formatv("{0:d}", WeakExternal.Alias));
358 }
359 return Error::success();
360}
361
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(),
371 Target->getSize(), Linkage::Weak, Scope::Local, false);
372 }
373 }
374 return Error::success();
375}
376
377Symbol *COFFLinkGraphBuilder::createExternalSymbol(
378 COFFSymbolIndex SymIndex, orc::SymbolStringPtr SymbolName,
379 object::COFFSymbolRef Symbol, const object::coff_section *Section) {
380 llvm::jitlink::Symbol *Sym = nullptr;
381 if (!ExternalSymbols.count(SymbolName)) {
382 Sym = &G->addExternalSymbol(*SymbolName, Symbol.getValue(), false);
383 ExternalSymbols[Sym->getName()] = Sym;
384 } else {
385 Sym = ExternalSymbols[SymbolName];
386 }
387
388 LLVM_DEBUG({
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";
394 });
395 return Sym;
396}
397
398Expected<Symbol *>
399COFFLinkGraphBuilder::createAliasSymbol(orc::SymbolStringPtr SymbolName,
400 Linkage L, Scope S, Symbol &Target) {
401 if (!Target.isDefined()) {
402 // FIXME: Support this when there's a way to handle this.
403 return make_error<JITLinkError>("Weak external symbol with external "
404 "symbol as alternative not supported.");
405 }
406 return &G->addDefinedSymbol(Target.getBlock(), Target.getOffset(), SymbolName,
407 Target.getSize(), L, S, Target.isCallable(),
408 false);
409}
410
411// In COFF, most of the defined symbols don't contain the size information.
412// Hence, we calculate the "implicit" size of symbol by taking the delta of
413// offsets of consecutive symbols within a block. We maintain a balanced tree
414// set of symbols sorted by offset per each block in order to achieve
415// logarithmic time complexity of sorted symbol insertion. Symbol is inserted to
416// the set once it's processed in graphifySymbols. In this function, we iterate
417// each collected symbol in sorted order and calculate the implicit size.
418Error COFFLinkGraphBuilder::calculateImplicitSizeOfSymbols() {
419 for (COFFSectionIndex SecIndex = 1;
420 SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
421 SecIndex++) {
422 auto &SymbolSet = SymbolSets[SecIndex];
423 if (SymbolSet.empty())
424 continue;
425 jitlink::Block *B = getGraphBlock(SecIndex);
426 orc::ExecutorAddrDiff LastOffset = B->getSize();
427 orc::ExecutorAddrDiff LastDifferentOffset = B->getSize();
428 orc::ExecutorAddrDiff LastSize = 0;
429 for (auto It = SymbolSet.rbegin(); It != SymbolSet.rend(); It++) {
430 orc::ExecutorAddrDiff Offset = It->first;
431 jitlink::Symbol *Symbol = It->second;
432 orc::ExecutorAddrDiff CandSize;
433 // Last offset can be same when aliasing happened
434 if (Symbol->getOffset() == LastOffset)
435 CandSize = LastSize;
436 else
437 CandSize = LastOffset - Offset;
438
439 LLVM_DEBUG({
440 if (Offset + Symbol->getSize() > LastDifferentOffset)
441 dbgs() << " Overlapping symbol range generated for the following "
442 "symbol:"
443 << "\n"
444 << " " << *Symbol << "\n";
445 });
446 (void)LastDifferentOffset;
447 if (LastOffset != Offset)
448 LastDifferentOffset = Offset;
449 LastSize = CandSize;
450 LastOffset = Offset;
451 if (Symbol->getSize()) {
452 // Non empty symbol can happen in COMDAT symbol.
453 // We don't consider the possibility of overlapping symbol range that
454 // could be introduced by disparity between inferred symbol size and
455 // defined symbol size because symbol size information is currently only
456 // used by jitlink-check where we have control to not make overlapping
457 // ranges.
458 continue;
459 }
460
461 LLVM_DEBUG({
462 if (!CandSize)
463 dbgs() << " Empty implicit symbol size generated for the following "
464 "symbol:"
465 << "\n"
466 << " " << *Symbol << "\n";
467 });
468
469 Symbol->setSize(CandSize);
470 }
471 }
472 return Error::success();
473}
474
475Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
476 COFFSymbolIndex SymIndex, orc::SymbolStringPtr SymbolName,
477 object::COFFSymbolRef Symbol, const object::coff_section *Section) {
478
479 if (Symbol.isCommon()) {
480 // FIXME: correct alignment
481 return &G->addDefinedSymbol(
482 G->createZeroFillBlock(getCommonSection(), Symbol.getValue(),
483 orc::ExecutorAddr(), Symbol.getValue(), 0),
484 0, SymbolName, Symbol.getValue(), Linkage::Weak, Scope::Default,
485 false, false);
486 }
487
488 if (Symbol.isAbsolute())
489 return &G->addAbsoluteSymbol(SymbolName,
490 orc::ExecutorAddr(Symbol.getValue()), 0,
492
493 if (llvm::COFF::isReservedSectionNumber(Symbol.getSectionNumber()))
494 return make_error<JITLinkError>(
495 "Reserved section number used in regular symbol " +
496 formatv("{0:d}", SymIndex));
497
498 Block *B = getGraphBlock(Symbol.getSectionNumber());
499 if (!B) {
500 LLVM_DEBUG({
501 dbgs() << " " << SymIndex
502 << ": Skipping graph symbol since section was not created for "
503 "COFF symbol \""
504 << SymbolName << "\" in section " << Symbol.getSectionNumber()
505 << "\n";
506 });
507 return nullptr;
508 }
509
510 if (Symbol.isExternal()) {
511 // This is not a comdat sequence, export the symbol as it is
512 if (!isComdatSection(Section)) {
513 auto GSym = &G->addDefinedSymbol(
515 Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
516 DefinedSymbols[SymbolName] = GSym;
517 return GSym;
518 } else {
519 if (!PendingComdatExports[Symbol.getSectionNumber()])
520 return make_error<JITLinkError>("No pending COMDAT export for symbol " +
521 formatv("{0:d}", SymIndex));
522
523 return exportCOMDATSymbol(SymIndex, SymbolName, Symbol);
524 }
525 }
526
527 if (Symbol.getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC ||
528 Symbol.getStorageClass() == COFF::IMAGE_SYM_CLASS_LABEL) {
529 const object::coff_aux_section_definition *Definition =
530 Symbol.getSectionDefinition();
531 if (!Definition || !isComdatSection(Section)) {
532 // Handle typical static symbol
533 return &G->addDefinedSymbol(
534 *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Local,
535 Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
536 }
537 if (Definition->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
538 auto Target = Definition->getNumber(Symbol.isBigObj());
539 auto GSym = &G->addDefinedSymbol(
540 *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Local,
541 Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
542 getGraphBlock(Target)->addEdge(Edge::KeepAlive, 0, *GSym, 0);
543 return GSym;
544 }
545 if (PendingComdatExports[Symbol.getSectionNumber()])
546 return make_error<JITLinkError>(
547 "COMDAT export request already exists before symbol " +
548 formatv("{0:d}", SymIndex));
549 return createCOMDATExportRequest(SymIndex, Symbol, Definition);
550 }
551 return make_error<JITLinkError>("Unsupported storage class " +
552 formatv("{0:d}", Symbol.getStorageClass()) +
553 " in symbol " + formatv("{0:d}", SymIndex));
554}
555
556// COMDAT handling:
557// When IMAGE_SCN_LNK_COMDAT flag is set in the flags of a section,
558// the section is called a COMDAT section. It contains two symbols
559// in a sequence that specifes the behavior. First symbol is the section
560// symbol which contains the size and name of the section. It also contains
561// selection type that specifies how duplicate of the symbol is handled.
562// Second symbol is COMDAT symbol which usually defines the external name and
563// data type.
564//
565// Since two symbols always come in a specific order, we initiate pending COMDAT
566// export request when we encounter the first symbol and actually exports it
567// when we process the second symbol.
568//
569// Process the first symbol of COMDAT sequence.
570Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
571 COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
572 const object::coff_aux_section_definition *Definition) {
574 switch (Definition->Selection) {
577 break;
578 }
581 break;
582 }
585 // FIXME: Implement size/content validation when LinkGraph is able to
586 // handle this.
588 break;
589 }
591 // FIXME: Support IMAGE_COMDAT_SELECT_LARGEST properly when LinkGraph is
592 // able to handle this.
593 LLVM_DEBUG({
594 dbgs() << " " << SymIndex
595 << ": Partially supported IMAGE_COMDAT_SELECT_LARGEST was used"
596 " in section "
597 << Symbol.getSectionNumber() << " (size: " << Definition->Length
598 << ")\n";
599 });
601 break;
602 }
604 // Even link.exe doesn't support this selection properly.
605 return make_error<JITLinkError>(
606 "IMAGE_COMDAT_SELECT_NEWEST is not supported.");
607 }
608 default: {
609 return make_error<JITLinkError>("Invalid comdat selection type: " +
610 formatv("{0:d}", Definition->Selection));
611 }
612 }
613 PendingComdatExports[Symbol.getSectionNumber()] = {SymIndex, L,
614 Definition->Length};
615 return nullptr;
616}
617
618// Process the second symbol of COMDAT sequence.
619Expected<Symbol *>
620COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
621 orc::SymbolStringPtr SymbolName,
622 object::COFFSymbolRef Symbol) {
623 Block *B = getGraphBlock(Symbol.getSectionNumber());
624 auto &PendingComdatExport = PendingComdatExports[Symbol.getSectionNumber()];
625 // NOTE: ComdatDef->Length is the size of "section" not size of symbol.
626 // We use zero symbol size to not reach out of bound of block when symbol
627 // offset is non-zero.
628 auto GSym = &G->addDefinedSymbol(
629 *B, Symbol.getValue(), SymbolName, 0, PendingComdatExport->Linkage,
631 false);
632 LLVM_DEBUG({
633 dbgs() << " " << SymIndex
634 << ": Exporting COMDAT graph symbol for COFF symbol \"" << SymbolName
635 << "\" in section " << Symbol.getSectionNumber() << "\n";
636 dbgs() << " " << *GSym << "\n";
637 });
638 setGraphSymbol(Symbol.getSectionNumber(), PendingComdatExport->SymbolIndex,
639 *GSym);
640 DefinedSymbols[SymbolName] = GSym;
641 PendingComdatExport = std::nullopt;
642 return GSym;
643}
644
646 if (ImageBase)
647 return *ImageBase;
648
649 auto IBN = G.intern(ImageBaseName);
650
651 // Check external symbols for image base.
652 for (auto *Sym : G.external_symbols()) {
653 if (Sym->getName() == IBN) {
654 ImageBase = Sym;
655 return Sym;
656 }
657 }
658
659 // Check absolute symbols (unexpected, but legal).
660 for (auto *Sym : G.absolute_symbols()) {
661 if (Sym->getName() == IBN) {
662 ImageBase = Sym;
663 return Sym;
664 }
665 }
666
667 // Finally, check defined symbols.
668 for (auto *Sym : G.defined_symbols()) {
669 if (Sym->hasName() && Sym->getName() == IBN) {
670 ImageBase = Sym;
671 return Sym;
672 }
673 }
674
675 ImageBase = nullptr;
676 return nullptr;
677}
678
679} // namespace jitlink
680} // namespace llvm
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static const char * CommonSectionName
COFFYAML::WeakExternalCharacteristics Characteristics
Definition: COFFYAML.cpp:350
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)
#define LLVM_DEBUG(...)
Definition: Debug.h:106
Symbol * Sym
Definition: ELF_riscv.cpp:479
#define G(x, y, z)
Definition: MD5.cpp:56
#define T
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:700
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:147
Manages the enabling and disabling of subtarget specific features.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
bool isLittleEndian() const
Definition: Binary.h:155
StringRef getFileName() const
Definition: Binary.cpp:41
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_LNK_REMOVE
Definition: COFF.h:307
@ IMAGE_SCN_MEM_READ
Definition: COFF.h:335
@ IMAGE_SCN_MEM_EXECUTE
Definition: COFF.h:334
@ IMAGE_SCN_CNT_UNINITIALIZED_DATA
Definition: COFF.h:304
@ IMAGE_SCN_LNK_COMDAT
Definition: COFF.h:308
@ IMAGE_SCN_MEM_WRITE
Definition: COFF.h:336
@ IMAGE_SYM_CLASS_LABEL
Label.
Definition: COFF.h:227
@ IMAGE_SYM_CLASS_STATIC
Static.
Definition: COFF.h:224
@ IMAGE_COMDAT_SELECT_NODUPLICATES
Definition: COFF.h:454
@ IMAGE_COMDAT_SELECT_LARGEST
Definition: COFF.h:459
@ IMAGE_COMDAT_SELECT_NEWEST
Definition: COFF.h:460
@ IMAGE_COMDAT_SELECT_SAME_SIZE
Definition: COFF.h:456
@ IMAGE_COMDAT_SELECT_ASSOCIATIVE
Definition: COFF.h:458
@ IMAGE_COMDAT_SELECT_EXACT_MATCH
Definition: COFF.h:457
@ IMAGE_COMDAT_SELECT_ANY
Definition: COFF.h:455
@ IMAGE_WEAK_EXTERN_SEARCH_ALIAS
Definition: COFF.h:489
bool isReservedSectionNumber(int32_t SectionNumber)
Definition: COFF.h:848
@ IMAGE_SYM_DEBUG
Definition: COFF.h:211
@ IMAGE_SYM_UNDEFINED
Definition: COFF.h:213
@ IMAGE_SYM_ABSOLUTE
Definition: COFF.h:212
@ IMAGE_SYM_DTYPE_FUNCTION
A function that returns a base type.
Definition: COFF.h:275
MemProt
Describes Read/Write/Exec permissions for memory.
Definition: MemoryFlags.h:27
uint64_t ExecutorAddrDiff
@ NoAlloc
NoAlloc memory should not be allocated by the JITLinkMemoryManager at all.
NodeAddr< BlockNode * > Block
Definition: RDFGraph.h:392
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1873
const char * toString(DWARFSectionKind Kind)
endianness
Definition: bit.h:70
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
support::ulittle32_t TagIndex
Definition: COFF.h:507