1 //===- SymbolTable.cpp ----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "SymbolTable.h"
10 #include "COFFLinkerContext.h"
16 #include "lld/Common/ErrorHandler.h"
17 #include "lld/Common/Memory.h"
18 #include "lld/Common/Timer.h"
19 #include "llvm/DebugInfo/DIContext.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/IR/Mangler.h"
22 #include "llvm/LTO/LTO.h"
23 #include "llvm/Object/COFFModuleDefinition.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/GlobPattern.h"
26 #include "llvm/Support/Parallel.h"
27 #include "llvm/Support/TimeProfiler.h"
28 #include "llvm/Support/raw_ostream.h"
32 using namespace llvm::COFF
;
33 using namespace llvm::object
;
34 using namespace llvm::support
;
38 StringRef
ltrim1(StringRef s
, const char *chars
) {
39 if (!s
.empty() && strchr(chars
, s
[0]))
44 static COFFSyncStream
errorOrWarn(COFFLinkerContext
&ctx
) {
45 return {ctx
, ctx
.config
.forceUnresolved
? DiagLevel::Warn
: DiagLevel::Err
};
48 // Causes the file associated with a lazy symbol to be linked in.
49 static void forceLazy(Symbol
*s
) {
50 s
->pendingArchiveLoad
= true;
52 case Symbol::Kind::LazyArchiveKind
: {
53 auto *l
= cast
<LazyArchive
>(s
);
54 l
->file
->addMember(l
->sym
);
57 case Symbol::Kind::LazyObjectKind
: {
58 InputFile
*file
= cast
<LazyObject
>(s
)->file
;
59 // FIXME: Remove this once we resolve all defineds before all undefineds in
60 // ObjFile::initializeSymbols().
64 file
->symtab
.ctx
.driver
.addFile(file
);
67 case Symbol::Kind::LazyDLLSymbolKind
: {
68 auto *l
= cast
<LazyDLLSymbol
>(s
);
69 l
->file
->makeImport(l
->sym
);
74 "symbol passed to forceLazy is not a LazyArchive or LazyObject");
78 // Returns the symbol in SC whose value is <= Addr that is closest to Addr.
79 // This is generally the global variable or function whose definition contains
81 static Symbol
*getSymbol(SectionChunk
*sc
, uint32_t addr
) {
82 DefinedRegular
*candidate
= nullptr;
84 for (Symbol
*s
: sc
->file
->getSymbols()) {
85 auto *d
= dyn_cast_or_null
<DefinedRegular
>(s
);
86 if (!d
|| !d
->data
|| d
->file
!= sc
->file
|| d
->getChunk() != sc
||
87 d
->getValue() > addr
||
88 (candidate
&& d
->getValue() < candidate
->getValue()))
97 static std::vector
<std::string
> getSymbolLocations(BitcodeFile
*file
) {
98 std::string
res("\n>>> referenced by ");
99 StringRef source
= file
->obj
->getSourceFileName();
101 res
+= source
.str() + "\n>>> ";
102 res
+= toString(file
);
106 static std::optional
<std::pair
<StringRef
, uint32_t>>
107 getFileLineDwarf(const SectionChunk
*c
, uint32_t addr
) {
108 std::optional
<DILineInfo
> optionalLineInfo
=
109 c
->file
->getDILineInfo(addr
, c
->getSectionNumber() - 1);
110 if (!optionalLineInfo
)
112 const DILineInfo
&lineInfo
= *optionalLineInfo
;
113 if (lineInfo
.FileName
== DILineInfo::BadString
)
115 return std::make_pair(saver().save(lineInfo
.FileName
), lineInfo
.Line
);
118 static std::optional
<std::pair
<StringRef
, uint32_t>>
119 getFileLine(const SectionChunk
*c
, uint32_t addr
) {
120 // MinGW can optionally use codeview, even if the default is dwarf.
121 std::optional
<std::pair
<StringRef
, uint32_t>> fileLine
=
122 getFileLineCodeView(c
, addr
);
123 // If codeview didn't yield any result, check dwarf in MinGW mode.
124 if (!fileLine
&& c
->file
->symtab
.ctx
.config
.mingw
)
125 fileLine
= getFileLineDwarf(c
, addr
);
129 // Given a file and the index of a symbol in that file, returns a description
130 // of all references to that symbol from that file. If no debug information is
131 // available, returns just the name of the file, else one string per actual
132 // reference as described in the debug info.
133 // Returns up to maxStrings string descriptions, along with the total number of
135 static std::pair
<std::vector
<std::string
>, size_t>
136 getSymbolLocations(ObjFile
*file
, uint32_t symIndex
, size_t maxStrings
) {
139 std::pair
<StringRef
, uint32_t> fileLine
;
141 std::vector
<Location
> locations
;
142 size_t numLocations
= 0;
144 for (Chunk
*c
: file
->getChunks()) {
145 auto *sc
= dyn_cast
<SectionChunk
>(c
);
148 for (const coff_relocation
&r
: sc
->getRelocs()) {
149 if (r
.SymbolTableIndex
!= symIndex
)
152 if (locations
.size() >= maxStrings
)
155 std::optional
<std::pair
<StringRef
, uint32_t>> fileLine
=
156 getFileLine(sc
, r
.VirtualAddress
);
157 Symbol
*sym
= getSymbol(sc
, r
.VirtualAddress
);
159 locations
.push_back({sym
, *fileLine
});
161 locations
.push_back({sym
, {"", 0}});
166 return std::make_pair(std::vector
<std::string
>(), numLocations
);
168 if (numLocations
== 0)
169 return std::make_pair(
170 std::vector
<std::string
>{"\n>>> referenced by " + toString(file
)}, 1);
172 std::vector
<std::string
> symbolLocations(locations
.size());
174 for (Location loc
: locations
) {
175 llvm::raw_string_ostream
os(symbolLocations
[i
++]);
176 os
<< "\n>>> referenced by ";
177 if (!loc
.fileLine
.first
.empty())
178 os
<< loc
.fileLine
.first
<< ":" << loc
.fileLine
.second
180 os
<< toString(file
);
182 os
<< ":(" << toString(file
->symtab
.ctx
, *loc
.sym
) << ')';
184 return std::make_pair(symbolLocations
, numLocations
);
187 std::vector
<std::string
> getSymbolLocations(ObjFile
*file
, uint32_t symIndex
) {
188 return getSymbolLocations(file
, symIndex
, SIZE_MAX
).first
;
191 static std::pair
<std::vector
<std::string
>, size_t>
192 getSymbolLocations(InputFile
*file
, uint32_t symIndex
, size_t maxStrings
) {
193 if (auto *o
= dyn_cast
<ObjFile
>(file
))
194 return getSymbolLocations(o
, symIndex
, maxStrings
);
195 if (auto *b
= dyn_cast
<BitcodeFile
>(file
)) {
196 std::vector
<std::string
> symbolLocations
= getSymbolLocations(b
);
197 size_t numLocations
= symbolLocations
.size();
198 if (symbolLocations
.size() > maxStrings
)
199 symbolLocations
.resize(maxStrings
);
200 return std::make_pair(symbolLocations
, numLocations
);
202 llvm_unreachable("unsupported file type passed to getSymbolLocations");
203 return std::make_pair(std::vector
<std::string
>(), (size_t)0);
206 // For an undefined symbol, stores all files referencing it and the index of
207 // the undefined symbol in each file.
208 struct UndefinedDiag
{
214 std::vector
<File
> files
;
217 static void reportUndefinedSymbol(COFFLinkerContext
&ctx
,
218 const UndefinedDiag
&undefDiag
) {
219 auto diag
= errorOrWarn(ctx
);
220 diag
<< "undefined symbol: " << undefDiag
.sym
;
222 const size_t maxUndefReferences
= 3;
223 size_t numDisplayedRefs
= 0, numRefs
= 0;
224 for (const UndefinedDiag::File
&ref
: undefDiag
.files
) {
225 auto [symbolLocations
, totalLocations
] = getSymbolLocations(
226 ref
.file
, ref
.symIndex
, maxUndefReferences
- numDisplayedRefs
);
228 numRefs
+= totalLocations
;
229 numDisplayedRefs
+= symbolLocations
.size();
230 for (const std::string
&s
: symbolLocations
)
233 if (numDisplayedRefs
< numRefs
)
234 diag
<< "\n>>> referenced " << numRefs
- numDisplayedRefs
<< " more times";
237 void SymbolTable::loadMinGWSymbols() {
238 for (auto &i
: symMap
) {
239 Symbol
*sym
= i
.second
;
240 auto *undef
= dyn_cast
<Undefined
>(sym
);
243 if (undef
->getWeakAlias())
246 StringRef name
= undef
->getName();
248 if (machine
== I386
&& ctx
.config
.stdcallFixup
) {
249 // Check if we can resolve an undefined decorated symbol by finding
250 // the intended target as an undecorated symbol (only with a leading
252 StringRef origName
= name
;
253 StringRef baseName
= name
;
254 // Trim down stdcall/fastcall/vectorcall symbols to the base name.
255 baseName
= ltrim1(baseName
, "_@");
256 baseName
= baseName
.substr(0, baseName
.find('@'));
257 // Add a leading underscore, as it would be in cdecl form.
258 std::string newName
= ("_" + baseName
).str();
260 if (newName
!= origName
&& (l
= find(newName
)) != nullptr) {
261 // If we found a symbol and it is lazy; load it.
262 if (l
->isLazy() && !l
->pendingArchiveLoad
) {
263 Log(ctx
) << "Loading lazy " << l
->getName() << " from "
264 << l
->getFile()->getName() << " for stdcall fixup";
267 // If it's lazy or already defined, hook it up as weak alias.
268 if (l
->isLazy() || isa
<Defined
>(l
)) {
269 if (ctx
.config
.warnStdcallFixup
)
270 Warn(ctx
) << "Resolving " << origName
<< " by linking to "
273 Log(ctx
) << "Resolving " << origName
<< " by linking to "
275 undef
->setWeakAlias(l
);
281 if (ctx
.config
.autoImport
) {
282 if (name
.starts_with("__imp_"))
284 // If we have an undefined symbol, but we have a lazy symbol we could
286 Symbol
*l
= find(("__imp_" + name
).str());
287 if (!l
|| l
->pendingArchiveLoad
|| !l
->isLazy())
290 Log(ctx
) << "Loading lazy " << l
->getName() << " from "
291 << l
->getFile()->getName() << " for automatic import";
297 Defined
*SymbolTable::impSymbol(StringRef name
) {
298 if (name
.starts_with("__imp_"))
300 return dyn_cast_or_null
<Defined
>(find(("__imp_" + name
).str()));
303 bool SymbolTable::handleMinGWAutomaticImport(Symbol
*sym
, StringRef name
) {
304 Defined
*imp
= impSymbol(name
);
308 // Replace the reference directly to a variable with a reference
309 // to the import address table instead. This obviously isn't right,
310 // but we mark the symbol as isRuntimePseudoReloc, and a later pass
311 // will add runtime pseudo relocations for every relocation against
312 // this Symbol. The runtime pseudo relocation framework expects the
313 // reference itself to point at the IAT entry.
315 if (isa
<DefinedImportData
>(imp
)) {
316 Log(ctx
) << "Automatically importing " << name
<< " from "
317 << cast
<DefinedImportData
>(imp
)->getDLLName();
318 impSize
= sizeof(DefinedImportData
);
319 } else if (isa
<DefinedRegular
>(imp
)) {
320 Log(ctx
) << "Automatically importing " << name
<< " from "
321 << toString(cast
<DefinedRegular
>(imp
)->file
);
322 impSize
= sizeof(DefinedRegular
);
324 Warn(ctx
) << "unable to automatically import " << name
<< " from "
325 << imp
->getName() << " from " << cast
<DefinedRegular
>(imp
)->file
326 << "; unexpected symbol type";
329 sym
->replaceKeepingName(imp
, impSize
);
330 sym
->isRuntimePseudoReloc
= true;
332 // There may exist symbols named .refptr.<name> which only consist
333 // of a single pointer to <name>. If it turns out <name> is
334 // automatically imported, we don't need to keep the .refptr.<name>
335 // pointer at all, but redirect all accesses to it to the IAT entry
336 // for __imp_<name> instead, and drop the whole .refptr.<name> chunk.
337 DefinedRegular
*refptr
=
338 dyn_cast_or_null
<DefinedRegular
>(find((".refptr." + name
).str()));
339 if (refptr
&& refptr
->getChunk()->getSize() == ctx
.config
.wordsize
) {
340 SectionChunk
*sc
= dyn_cast_or_null
<SectionChunk
>(refptr
->getChunk());
341 if (sc
&& sc
->getRelocs().size() == 1 && *sc
->symbols().begin() == sym
) {
342 Log(ctx
) << "Replacing .refptr." << name
<< " with " << imp
->getName();
343 refptr
->getChunk()->live
= false;
344 refptr
->replaceKeepingName(imp
, impSize
);
350 /// Helper function for reportUnresolvable and resolveRemainingUndefines.
351 /// This function emits an "undefined symbol" diagnostic for each symbol in
352 /// undefs. If localImports is not nullptr, it also emits a "locally
353 /// defined symbol imported" diagnostic for symbols in localImports.
354 /// objFiles and bitcodeFiles (if not nullptr) are used to report where
355 /// undefined symbols are referenced.
356 void SymbolTable::reportProblemSymbols(
357 const SmallPtrSetImpl
<Symbol
*> &undefs
,
358 const DenseMap
<Symbol
*, Symbol
*> *localImports
, bool needBitcodeFiles
) {
359 // Return early if there is nothing to report (which should be
361 if (undefs
.empty() && (!localImports
|| localImports
->empty()))
364 for (Symbol
*b
: ctx
.config
.gcroot
) {
366 errorOrWarn(ctx
) << "<root>: undefined symbol: " << b
;
368 if (Symbol
*imp
= localImports
->lookup(b
))
369 Warn(ctx
) << "<root>: locally defined symbol imported: " << imp
370 << " (defined in " << toString(imp
->getFile())
374 std::vector
<UndefinedDiag
> undefDiags
;
375 DenseMap
<Symbol
*, int> firstDiag
;
377 auto processFile
= [&](InputFile
*file
, ArrayRef
<Symbol
*> symbols
) {
378 uint32_t symIndex
= (uint32_t)-1;
379 for (Symbol
*sym
: symbols
) {
383 if (undefs
.count(sym
)) {
384 auto [it
, inserted
] = firstDiag
.try_emplace(sym
, undefDiags
.size());
386 undefDiags
.push_back({sym
, {{file
, symIndex
}}});
388 undefDiags
[it
->second
].files
.push_back({file
, symIndex
});
391 if (Symbol
*imp
= localImports
->lookup(sym
))
392 Warn(ctx
) << file
<< ": locally defined symbol imported: " << imp
393 << " (defined in " << imp
->getFile() << ") [LNK4217]";
397 for (ObjFile
*file
: ctx
.objFileInstances
)
398 processFile(file
, file
->getSymbols());
400 if (needBitcodeFiles
)
401 for (BitcodeFile
*file
: bitcodeFileInstances
)
402 processFile(file
, file
->getSymbols());
404 for (const UndefinedDiag
&undefDiag
: undefDiags
)
405 reportUndefinedSymbol(ctx
, undefDiag
);
408 void SymbolTable::reportUnresolvable() {
409 SmallPtrSet
<Symbol
*, 8> undefs
;
410 for (auto &i
: symMap
) {
411 Symbol
*sym
= i
.second
;
412 auto *undef
= dyn_cast
<Undefined
>(sym
);
413 if (!undef
|| sym
->deferUndefined
)
415 if (undef
->getWeakAlias())
417 StringRef name
= undef
->getName();
418 if (name
.starts_with("__imp_")) {
419 Symbol
*imp
= find(name
.substr(strlen("__imp_")));
420 if (Defined
*def
= dyn_cast_or_null
<Defined
>(imp
)) {
421 def
->isUsedInRegularObj
= true;
425 if (name
.contains("_PchSym_"))
427 if (ctx
.config
.autoImport
&& impSymbol(name
))
432 reportProblemSymbols(undefs
, /*localImports=*/nullptr, true);
435 bool SymbolTable::resolveRemainingUndefines() {
436 llvm::TimeTraceScope
timeScope("Resolve remaining undefined symbols");
437 SmallPtrSet
<Symbol
*, 8> undefs
;
438 DenseMap
<Symbol
*, Symbol
*> localImports
;
439 bool foundLazy
= false;
441 for (auto &i
: symMap
) {
442 Symbol
*sym
= i
.second
;
443 auto *undef
= dyn_cast
<Undefined
>(sym
);
446 if (!sym
->isUsedInRegularObj
)
449 StringRef name
= undef
->getName();
451 // A weak alias may have been resolved, so check for that.
452 if (undef
->resolveWeakAlias())
455 // If we can resolve a symbol by removing __imp_ prefix, do that.
456 // This odd rule is for compatibility with MSVC linker.
457 if (name
.starts_with("__imp_")) {
458 auto findLocalSym
= [&](StringRef n
) {
459 Symbol
*sym
= find(n
);
460 if (auto undef
= dyn_cast_or_null
<Undefined
>(sym
)) {
461 // The unprefixed symbol might come later in symMap, so handle it now
463 if (!undef
->resolveWeakAlias())
469 StringRef impName
= name
.substr(strlen("__imp_"));
470 Symbol
*imp
= findLocalSym(impName
);
471 if (!imp
&& isEC()) {
472 // Try to use the mangled symbol on ARM64EC.
473 std::optional
<std::string
> mangledName
=
474 getArm64ECMangledFunctionName(impName
);
476 imp
= findLocalSym(*mangledName
);
477 if (!imp
&& impName
.consume_front("aux_")) {
478 // If it's a __imp_aux_ symbol, try skipping the aux_ prefix.
479 imp
= findLocalSym(impName
);
480 if (!imp
&& (mangledName
= getArm64ECMangledFunctionName(impName
)))
481 imp
= findLocalSym(*mangledName
);
484 if (imp
&& imp
->isLazy()) {
489 if (imp
&& isa
<Defined
>(imp
)) {
490 auto *d
= cast
<Defined
>(imp
);
491 replaceSymbol
<DefinedLocalImport
>(sym
, ctx
, name
, d
);
492 localImportChunks
.push_back(cast
<DefinedLocalImport
>(sym
)->getChunk());
493 localImports
[sym
] = d
;
498 // We don't want to report missing Microsoft precompiled headers symbols.
499 // A proper message will be emitted instead in PDBLinker::aquirePrecompObj
500 if (name
.contains("_PchSym_"))
503 if (ctx
.config
.autoImport
&& handleMinGWAutomaticImport(sym
, name
))
506 // Remaining undefined symbols are not fatal if /force is specified.
507 // They are replaced with dummy defined symbols.
508 if (ctx
.config
.forceUnresolved
)
509 replaceSymbol
<DefinedAbsolute
>(sym
, ctx
, name
, 0);
513 reportProblemSymbols(
514 undefs
, ctx
.config
.warnLocallyDefinedImported
? &localImports
: nullptr,
519 std::pair
<Symbol
*, bool> SymbolTable::insert(StringRef name
) {
520 bool inserted
= false;
521 Symbol
*&sym
= symMap
[CachedHashStringRef(name
)];
523 sym
= reinterpret_cast<Symbol
*>(make
<SymbolUnion
>());
524 sym
->isUsedInRegularObj
= false;
525 sym
->pendingArchiveLoad
= false;
526 sym
->canInline
= true;
529 if (isEC() && name
.starts_with("EXP+"))
530 expSymbols
.push_back(sym
);
532 return {sym
, inserted
};
535 std::pair
<Symbol
*, bool> SymbolTable::insert(StringRef name
, InputFile
*file
) {
536 std::pair
<Symbol
*, bool> result
= insert(name
);
537 if (!file
|| !isa
<BitcodeFile
>(file
))
538 result
.first
->isUsedInRegularObj
= true;
542 void SymbolTable::initializeLoadConfig() {
544 dyn_cast_or_null
<DefinedRegular
>(findUnderscore("_load_config_used"));
547 Warn(ctx
) << "EC version of '_load_config_used' is missing";
550 if (ctx
.hybridSymtab
) {
551 Warn(ctx
) << "native version of '_load_config_used' is missing for "
555 if (ctx
.config
.guardCF
!= GuardCFLevel::Off
)
557 << "Control Flow Guard is enabled but '_load_config_used' is missing";
558 if (ctx
.config
.dependentLoadFlags
)
559 Warn(ctx
) << "_load_config_used not found, /dependentloadflag will have "
564 SectionChunk
*sc
= sym
->getChunk();
566 Err(ctx
) << "_load_config_used points to uninitialized data";
569 uint64_t offsetInChunk
= sym
->getValue();
570 if (offsetInChunk
+ 4 > sc
->getSize()) {
571 Err(ctx
) << "_load_config_used section chunk is too small";
575 ArrayRef
<uint8_t> secContents
= sc
->getContents();
577 *reinterpret_cast<const ulittle32_t
*>(&secContents
[offsetInChunk
]);
578 if (offsetInChunk
+ loadConfigSize
> sc
->getSize()) {
579 Err(ctx
) << "_load_config_used specifies a size larger than its containing "
584 uint32_t expectedAlign
= ctx
.config
.is64() ? 8 : 4;
585 if (sc
->getAlignment() < expectedAlign
)
586 Warn(ctx
) << "'_load_config_used' is misaligned (expected alignment to be "
587 << expectedAlign
<< " bytes, got " << sc
->getAlignment()
589 else if (!isAligned(Align(expectedAlign
), offsetInChunk
))
590 Warn(ctx
) << "'_load_config_used' is misaligned (section offset is 0x"
591 << Twine::utohexstr(sym
->getValue()) << " not aligned to "
592 << expectedAlign
<< " bytes)";
597 void SymbolTable::addEntryThunk(Symbol
*from
, Symbol
*to
) {
598 entryThunks
.push_back({from
, to
});
601 void SymbolTable::addExitThunk(Symbol
*from
, Symbol
*to
) {
602 exitThunks
[from
] = to
;
605 void SymbolTable::initializeECThunks() {
606 if (!isArm64EC(ctx
.config
.machine
))
609 for (auto it
: entryThunks
) {
610 auto *to
= dyn_cast
<Defined
>(it
.second
);
613 auto *from
= dyn_cast
<DefinedRegular
>(it
.first
);
614 // We need to be able to add padding to the function and fill it with an
615 // offset to its entry thunks. To ensure that padding the function is
616 // feasible, functions are required to be COMDAT symbols with no offset.
617 if (!from
|| !from
->getChunk()->isCOMDAT() ||
618 cast
<DefinedRegular
>(from
)->getValue()) {
619 Err(ctx
) << "non COMDAT symbol '" << from
->getName() << "' in hybrid map";
622 from
->getChunk()->setEntryThunk(to
);
625 for (ImportFile
*file
: ctx
.importFileInstances
) {
626 if (!file
->impchkThunk
)
629 Symbol
*sym
= exitThunks
.lookup(file
->thunkSym
);
631 sym
= exitThunks
.lookup(file
->impECSym
);
632 file
->impchkThunk
->exitThunk
= dyn_cast_or_null
<Defined
>(sym
);
635 // On ARM64EC, the __imp_ symbol references the auxiliary IAT, while the
636 // __imp_aux_ symbol references the regular IAT. However, x86_64 code expects
637 // both to reference the regular IAT, so adjust the symbol if necessary.
638 parallelForEach(ctx
.objFileInstances
, [&](ObjFile
*file
) {
639 if (file
->getMachineType() != AMD64
)
641 for (auto &sym
: file
->getMutableSymbols()) {
642 auto impSym
= dyn_cast_or_null
<DefinedImportData
>(sym
);
643 if (impSym
&& impSym
->file
->impchkThunk
&& sym
== impSym
->file
->impECSym
)
644 sym
= impSym
->file
->impSym
;
649 Symbol
*SymbolTable::addUndefined(StringRef name
, InputFile
*f
,
651 auto [s
, wasInserted
] = insert(name
, f
);
652 if (wasInserted
|| (s
->isLazy() && overrideLazy
)) {
653 replaceSymbol
<Undefined
>(s
, name
);
661 Symbol
*SymbolTable::addGCRoot(StringRef name
, bool aliasEC
) {
662 Symbol
*b
= addUndefined(name
);
665 ctx
.config
.gcroot
.push_back(b
);
668 // On ARM64EC, a symbol may be defined in either its mangled or demangled form
669 // (or both). Define an anti-dependency symbol that binds both forms, similar
670 // to how compiler-generated code references external functions.
671 if (aliasEC
&& isEC()) {
672 if (std::optional
<std::string
> mangledName
=
673 getArm64ECMangledFunctionName(name
)) {
674 auto u
= dyn_cast
<Undefined
>(b
);
675 if (u
&& !u
->weakAlias
) {
676 Symbol
*t
= addUndefined(saver().save(*mangledName
));
677 u
->setWeakAlias(t
, true);
679 } else if (std::optional
<std::string
> demangledName
=
680 getArm64ECDemangledFunctionName(name
)) {
681 Symbol
*us
= addUndefined(saver().save(*demangledName
));
682 auto u
= dyn_cast
<Undefined
>(us
);
683 if (u
&& !u
->weakAlias
)
684 u
->setWeakAlias(b
, true);
690 // On ARM64EC, a function symbol may appear in both mangled and demangled forms:
691 // - ARM64EC archives contain only the mangled name, while the demangled symbol
692 // is defined by the object file as an alias.
693 // - x86_64 archives contain only the demangled name (the mangled name is
694 // usually defined by an object referencing the symbol as an alias to a guess
696 // - ARM64EC import files contain both the mangled and demangled names for
698 // If more than one archive defines the same function, this could lead
699 // to different libraries being used for the same function depending on how they
700 // are referenced. Avoid this by checking if the paired symbol is already
701 // defined before adding a symbol to the table.
702 template <typename T
>
703 bool checkLazyECPair(SymbolTable
*symtab
, StringRef name
, InputFile
*f
) {
704 if (name
.starts_with("__imp_"))
706 std::string pairName
;
707 if (std::optional
<std::string
> mangledName
=
708 getArm64ECMangledFunctionName(name
))
709 pairName
= std::move(*mangledName
);
710 else if (std::optional
<std::string
> demangledName
=
711 getArm64ECDemangledFunctionName(name
))
712 pairName
= std::move(*demangledName
);
716 Symbol
*sym
= symtab
->find(pairName
);
719 if (sym
->pendingArchiveLoad
)
721 if (auto u
= dyn_cast
<Undefined
>(sym
))
722 return !u
->weakAlias
|| u
->isAntiDep
;
723 // If the symbol is lazy, allow it only if it originates from the same
725 auto lazy
= dyn_cast
<T
>(sym
);
726 return lazy
&& lazy
->file
== f
;
729 void SymbolTable::addLazyArchive(ArchiveFile
*f
, const Archive::Symbol
&sym
) {
730 StringRef name
= sym
.getName();
731 if (isEC() && !checkLazyECPair
<LazyArchive
>(this, name
, f
))
733 auto [s
, wasInserted
] = insert(name
);
735 replaceSymbol
<LazyArchive
>(s
, f
, sym
);
738 auto *u
= dyn_cast
<Undefined
>(s
);
739 if (!u
|| (u
->weakAlias
&& !u
->isECAlias(machine
)) || s
->pendingArchiveLoad
)
741 s
->pendingArchiveLoad
= true;
745 void SymbolTable::addLazyObject(InputFile
*f
, StringRef n
) {
747 if (isEC() && !checkLazyECPair
<LazyObject
>(this, n
, f
))
749 auto [s
, wasInserted
] = insert(n
, f
);
751 replaceSymbol
<LazyObject
>(s
, f
, n
);
754 auto *u
= dyn_cast
<Undefined
>(s
);
755 if (!u
|| (u
->weakAlias
&& !u
->isECAlias(machine
)) || s
->pendingArchiveLoad
)
757 s
->pendingArchiveLoad
= true;
759 ctx
.driver
.addFile(f
);
762 void SymbolTable::addLazyDLLSymbol(DLLFile
*f
, DLLFile::Symbol
*sym
,
764 auto [s
, wasInserted
] = insert(n
);
766 replaceSymbol
<LazyDLLSymbol
>(s
, f
, sym
, n
);
769 auto *u
= dyn_cast
<Undefined
>(s
);
770 if (!u
|| u
->weakAlias
|| s
->pendingArchiveLoad
)
772 s
->pendingArchiveLoad
= true;
776 static std::string
getSourceLocationBitcode(BitcodeFile
*file
) {
777 std::string
res("\n>>> defined at ");
778 StringRef source
= file
->obj
->getSourceFileName();
780 res
+= source
.str() + "\n>>> ";
781 res
+= toString(file
);
785 static std::string
getSourceLocationObj(ObjFile
*file
, SectionChunk
*sc
,
786 uint32_t offset
, StringRef name
) {
787 std::optional
<std::pair
<StringRef
, uint32_t>> fileLine
;
789 fileLine
= getFileLine(sc
, offset
);
791 fileLine
= file
->getVariableLocation(name
);
794 llvm::raw_string_ostream
os(res
);
795 os
<< "\n>>> defined at ";
797 os
<< fileLine
->first
<< ":" << fileLine
->second
<< "\n>>> ";
798 os
<< toString(file
);
802 static std::string
getSourceLocation(InputFile
*file
, SectionChunk
*sc
,
803 uint32_t offset
, StringRef name
) {
806 if (auto *o
= dyn_cast
<ObjFile
>(file
))
807 return getSourceLocationObj(o
, sc
, offset
, name
);
808 if (auto *b
= dyn_cast
<BitcodeFile
>(file
))
809 return getSourceLocationBitcode(b
);
810 return "\n>>> defined at " + toString(file
);
813 // Construct and print an error message in the form of:
815 // lld-link: error: duplicate symbol: foo
816 // >>> defined at bar.c:30
818 // >>> defined at baz.c:563
820 void SymbolTable::reportDuplicate(Symbol
*existing
, InputFile
*newFile
,
822 uint32_t newSectionOffset
) {
823 COFFSyncStream
diag(ctx
, ctx
.config
.forceMultiple
? DiagLevel::Warn
825 diag
<< "duplicate symbol: " << existing
;
827 DefinedRegular
*d
= dyn_cast
<DefinedRegular
>(existing
);
828 if (d
&& isa
<ObjFile
>(d
->getFile())) {
829 diag
<< getSourceLocation(d
->getFile(), d
->getChunk(), d
->getValue(),
830 existing
->getName());
832 diag
<< getSourceLocation(existing
->getFile(), nullptr, 0, "");
834 diag
<< getSourceLocation(newFile
, newSc
, newSectionOffset
,
835 existing
->getName());
838 Symbol
*SymbolTable::addAbsolute(StringRef n
, COFFSymbolRef sym
) {
839 auto [s
, wasInserted
] = insert(n
, nullptr);
840 s
->isUsedInRegularObj
= true;
841 if (wasInserted
|| isa
<Undefined
>(s
) || s
->isLazy())
842 replaceSymbol
<DefinedAbsolute
>(s
, ctx
, n
, sym
);
843 else if (auto *da
= dyn_cast
<DefinedAbsolute
>(s
)) {
844 if (da
->getVA() != sym
.getValue())
845 reportDuplicate(s
, nullptr);
846 } else if (!isa
<DefinedCOFF
>(s
))
847 reportDuplicate(s
, nullptr);
851 Symbol
*SymbolTable::addAbsolute(StringRef n
, uint64_t va
) {
852 auto [s
, wasInserted
] = insert(n
, nullptr);
853 s
->isUsedInRegularObj
= true;
854 if (wasInserted
|| isa
<Undefined
>(s
) || s
->isLazy())
855 replaceSymbol
<DefinedAbsolute
>(s
, ctx
, n
, va
);
856 else if (auto *da
= dyn_cast
<DefinedAbsolute
>(s
)) {
857 if (da
->getVA() != va
)
858 reportDuplicate(s
, nullptr);
859 } else if (!isa
<DefinedCOFF
>(s
))
860 reportDuplicate(s
, nullptr);
864 Symbol
*SymbolTable::addSynthetic(StringRef n
, Chunk
*c
) {
865 auto [s
, wasInserted
] = insert(n
, nullptr);
866 s
->isUsedInRegularObj
= true;
867 if (wasInserted
|| isa
<Undefined
>(s
) || s
->isLazy())
868 replaceSymbol
<DefinedSynthetic
>(s
, n
, c
);
869 else if (!isa
<DefinedCOFF
>(s
))
870 reportDuplicate(s
, nullptr);
874 Symbol
*SymbolTable::addRegular(InputFile
*f
, StringRef n
,
875 const coff_symbol_generic
*sym
, SectionChunk
*c
,
876 uint32_t sectionOffset
, bool isWeak
) {
877 auto [s
, wasInserted
] = insert(n
, f
);
878 if (wasInserted
|| !isa
<DefinedRegular
>(s
) || s
->isWeak
)
879 replaceSymbol
<DefinedRegular
>(s
, f
, n
, /*IsCOMDAT*/ false,
880 /*IsExternal*/ true, sym
, c
, isWeak
);
882 reportDuplicate(s
, f
, c
, sectionOffset
);
886 std::pair
<DefinedRegular
*, bool>
887 SymbolTable::addComdat(InputFile
*f
, StringRef n
,
888 const coff_symbol_generic
*sym
) {
889 auto [s
, wasInserted
] = insert(n
, f
);
890 if (wasInserted
|| !isa
<DefinedRegular
>(s
)) {
891 replaceSymbol
<DefinedRegular
>(s
, f
, n
, /*IsCOMDAT*/ true,
892 /*IsExternal*/ true, sym
, nullptr);
893 return {cast
<DefinedRegular
>(s
), true};
895 auto *existingSymbol
= cast
<DefinedRegular
>(s
);
896 if (!existingSymbol
->isCOMDAT
)
897 reportDuplicate(s
, f
);
898 return {existingSymbol
, false};
901 Symbol
*SymbolTable::addCommon(InputFile
*f
, StringRef n
, uint64_t size
,
902 const coff_symbol_generic
*sym
, CommonChunk
*c
) {
903 auto [s
, wasInserted
] = insert(n
, f
);
904 if (wasInserted
|| !isa
<DefinedCOFF
>(s
))
905 replaceSymbol
<DefinedCommon
>(s
, f
, n
, size
, sym
, c
);
906 else if (auto *dc
= dyn_cast
<DefinedCommon
>(s
))
907 if (size
> dc
->getSize())
908 replaceSymbol
<DefinedCommon
>(s
, f
, n
, size
, sym
, c
);
912 DefinedImportData
*SymbolTable::addImportData(StringRef n
, ImportFile
*f
,
914 auto [s
, wasInserted
] = insert(n
, nullptr);
915 s
->isUsedInRegularObj
= true;
916 if (wasInserted
|| isa
<Undefined
>(s
) || s
->isLazy()) {
917 replaceSymbol
<DefinedImportData
>(s
, n
, f
, location
);
918 return cast
<DefinedImportData
>(s
);
921 reportDuplicate(s
, f
);
925 Defined
*SymbolTable::addImportThunk(StringRef name
, DefinedImportData
*id
,
926 ImportThunkChunk
*chunk
) {
927 auto [s
, wasInserted
] = insert(name
, nullptr);
928 s
->isUsedInRegularObj
= true;
929 if (wasInserted
|| isa
<Undefined
>(s
) || s
->isLazy()) {
930 replaceSymbol
<DefinedImportThunk
>(s
, ctx
, name
, id
, chunk
);
931 return cast
<Defined
>(s
);
934 reportDuplicate(s
, id
->file
);
938 void SymbolTable::addLibcall(StringRef name
) {
939 Symbol
*sym
= findUnderscore(name
);
943 if (auto *l
= dyn_cast
<LazyArchive
>(sym
)) {
944 MemoryBufferRef mb
= l
->getMemberBuffer();
946 addUndefined(sym
->getName());
947 } else if (LazyObject
*o
= dyn_cast
<LazyObject
>(sym
)) {
948 if (isBitcode(o
->file
->mb
))
949 addUndefined(sym
->getName());
953 Symbol
*SymbolTable::find(StringRef name
) const {
954 return symMap
.lookup(CachedHashStringRef(name
));
957 Symbol
*SymbolTable::findUnderscore(StringRef name
) const {
959 return find(("_" + name
).str());
963 // Return all symbols that start with Prefix, possibly ignoring the first
964 // character of Prefix or the first character symbol.
965 std::vector
<Symbol
*> SymbolTable::getSymsWithPrefix(StringRef prefix
) {
966 std::vector
<Symbol
*> syms
;
967 for (auto pair
: symMap
) {
968 StringRef name
= pair
.first
.val();
969 if (name
.starts_with(prefix
) || name
.starts_with(prefix
.drop_front()) ||
970 name
.drop_front().starts_with(prefix
) ||
971 name
.drop_front().starts_with(prefix
.drop_front())) {
972 syms
.push_back(pair
.second
);
978 Symbol
*SymbolTable::findMangle(StringRef name
) {
979 if (Symbol
*sym
= find(name
)) {
980 if (auto *u
= dyn_cast
<Undefined
>(sym
)) {
981 // We're specifically looking for weak aliases that ultimately resolve to
982 // defined symbols, hence the call to getWeakAlias() instead of just using
983 // the weakAlias member variable. This matches link.exe's behavior.
984 if (Symbol
*weakAlias
= u
->getWeakAlias())
991 // Efficient fuzzy string lookup is impossible with a hash table, so iterate
992 // the symbol table once and collect all possibly matching symbols into this
993 // vector. Then compare each possibly matching symbol with each possible
995 std::vector
<Symbol
*> syms
= getSymsWithPrefix(name
);
996 auto findByPrefix
= [&syms
](const Twine
&t
) -> Symbol
* {
997 std::string prefix
= t
.str();
999 if (s
->getName().starts_with(prefix
))
1004 // For non-x86, just look for C++ functions.
1005 if (machine
!= I386
)
1006 return findByPrefix("?" + name
+ "@@Y");
1008 if (!name
.starts_with("_"))
1010 // Search for x86 stdcall function.
1011 if (Symbol
*s
= findByPrefix(name
+ "@"))
1013 // Search for x86 fastcall function.
1014 if (Symbol
*s
= findByPrefix("@" + name
.substr(1) + "@"))
1016 // Search for x86 vectorcall function.
1017 if (Symbol
*s
= findByPrefix(name
.substr(1) + "@@"))
1019 // Search for x86 C++ non-member function.
1020 return findByPrefix("?" + name
.substr(1) + "@@Y");
1023 bool SymbolTable::findUnderscoreMangle(StringRef sym
) {
1024 Symbol
*s
= findMangle(mangle(sym
));
1025 return s
&& !isa
<Undefined
>(s
);
1028 // Symbol names are mangled by prepending "_" on x86.
1029 StringRef
SymbolTable::mangle(StringRef sym
) {
1030 assert(machine
!= IMAGE_FILE_MACHINE_UNKNOWN
);
1031 if (machine
== I386
)
1032 return saver().save("_" + sym
);
1036 StringRef
SymbolTable::mangleMaybe(Symbol
*s
) {
1037 // If the plain symbol name has already been resolved, do nothing.
1038 Undefined
*unmangled
= dyn_cast
<Undefined
>(s
);
1042 // Otherwise, see if a similar, mangled symbol exists in the symbol table.
1043 Symbol
*mangled
= findMangle(unmangled
->getName());
1047 // If we find a similar mangled symbol, make this an alias to it and return
1049 Log(ctx
) << unmangled
->getName() << " aliased to " << mangled
->getName();
1050 unmangled
->setWeakAlias(addUndefined(mangled
->getName()));
1051 return mangled
->getName();
1054 // Windows specific -- find default entry point name.
1056 // There are four different entry point functions for Windows executables,
1057 // each of which corresponds to a user-defined "main" function. This function
1058 // infers an entry point from a user-defined "main" function.
1059 StringRef
SymbolTable::findDefaultEntry() {
1060 assert(ctx
.config
.subsystem
!= IMAGE_SUBSYSTEM_UNKNOWN
&&
1061 "must handle /subsystem before calling this");
1063 if (ctx
.config
.mingw
)
1064 return mangle(ctx
.config
.subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
1065 ? "WinMainCRTStartup"
1066 : "mainCRTStartup");
1068 if (ctx
.config
.subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
) {
1069 if (findUnderscoreMangle("wWinMain")) {
1070 if (!findUnderscoreMangle("WinMain"))
1071 return mangle("wWinMainCRTStartup");
1072 Warn(ctx
) << "found both wWinMain and WinMain; using latter";
1074 return mangle("WinMainCRTStartup");
1076 if (findUnderscoreMangle("wmain")) {
1077 if (!findUnderscoreMangle("main"))
1078 return mangle("wmainCRTStartup");
1079 Warn(ctx
) << "found both wmain and main; using latter";
1081 return mangle("mainCRTStartup");
1084 WindowsSubsystem
SymbolTable::inferSubsystem() {
1086 return IMAGE_SUBSYSTEM_WINDOWS_GUI
;
1087 if (ctx
.config
.mingw
)
1088 return IMAGE_SUBSYSTEM_WINDOWS_CUI
;
1089 // Note that link.exe infers the subsystem from the presence of these
1090 // functions even if /entry: or /nodefaultlib are passed which causes them
1091 // to not be called.
1092 bool haveMain
= findUnderscoreMangle("main");
1093 bool haveWMain
= findUnderscoreMangle("wmain");
1094 bool haveWinMain
= findUnderscoreMangle("WinMain");
1095 bool haveWWinMain
= findUnderscoreMangle("wWinMain");
1096 if (haveMain
|| haveWMain
) {
1097 if (haveWinMain
|| haveWWinMain
) {
1098 Warn(ctx
) << "found " << (haveMain
? "main" : "wmain") << " and "
1099 << (haveWinMain
? "WinMain" : "wWinMain")
1100 << "; defaulting to /subsystem:console";
1102 return IMAGE_SUBSYSTEM_WINDOWS_CUI
;
1104 if (haveWinMain
|| haveWWinMain
)
1105 return IMAGE_SUBSYSTEM_WINDOWS_GUI
;
1106 return IMAGE_SUBSYSTEM_UNKNOWN
;
1109 void SymbolTable::addUndefinedGlob(StringRef arg
) {
1110 Expected
<GlobPattern
> pat
= GlobPattern::create(arg
);
1112 Err(ctx
) << "/includeglob: " << toString(pat
.takeError());
1116 SmallVector
<Symbol
*, 0> syms
;
1117 forEachSymbol([&syms
, &pat
](Symbol
*sym
) {
1118 if (pat
->match(sym
->getName())) {
1119 syms
.push_back(sym
);
1123 for (Symbol
*sym
: syms
)
1124 addGCRoot(sym
->getName());
1127 // Convert stdcall/fastcall style symbols into unsuffixed symbols,
1128 // with or without a leading underscore. (MinGW specific.)
1129 static StringRef
killAt(StringRef sym
, bool prefix
) {
1132 // Strip any trailing stdcall suffix
1133 sym
= sym
.substr(0, sym
.find('@', 1));
1134 if (!sym
.starts_with("@")) {
1135 if (prefix
&& !sym
.starts_with("_"))
1136 return saver().save("_" + sym
);
1139 // For fastcall, remove the leading @ and replace it with an
1140 // underscore, if prefixes are used.
1141 sym
= sym
.substr(1);
1143 sym
= saver().save("_" + sym
);
1147 static StringRef
exportSourceName(ExportSource s
) {
1149 case ExportSource::Directives
:
1150 return "source file (directives)";
1151 case ExportSource::Export
:
1153 case ExportSource::ModuleDefinition
:
1156 llvm_unreachable("unknown ExportSource");
1160 // Performs error checking on all /export arguments.
1161 // It also sets ordinals.
1162 void SymbolTable::fixupExports() {
1163 llvm::TimeTraceScope
timeScope("Fixup exports");
1164 // Symbol ordinals must be unique.
1165 std::set
<uint16_t> ords
;
1166 for (Export
&e
: exports
) {
1169 if (!ords
.insert(e
.ordinal
).second
)
1170 Fatal(ctx
) << "duplicate export ordinal: " << e
.name
;
1173 for (Export
&e
: exports
) {
1174 if (!e
.exportAs
.empty()) {
1175 e
.exportName
= e
.exportAs
;
1180 !e
.forwardTo
.empty() || e
.extName
.empty() ? e
.name
: e
.extName
;
1181 if (machine
== I386
&& sym
.starts_with("_")) {
1182 // In MSVC mode, a fully decorated stdcall function is exported
1183 // as-is with the leading underscore (with type IMPORT_NAME).
1184 // In MinGW mode, a decorated stdcall function gets the underscore
1185 // removed, just like normal cdecl functions.
1186 if (ctx
.config
.mingw
|| !sym
.contains('@')) {
1187 e
.exportName
= sym
.substr(1);
1191 if (isEC() && !e
.data
&& !e
.constant
) {
1192 if (std::optional
<std::string
> demangledName
=
1193 getArm64ECDemangledFunctionName(sym
)) {
1194 e
.exportName
= saver().save(*demangledName
);
1201 if (ctx
.config
.killAt
&& machine
== I386
) {
1202 for (Export
&e
: exports
) {
1203 e
.name
= killAt(e
.name
, true);
1204 e
.exportName
= killAt(e
.exportName
, false);
1205 e
.extName
= killAt(e
.extName
, true);
1206 e
.symbolName
= killAt(e
.symbolName
, true);
1210 // Uniquefy by name.
1211 DenseMap
<StringRef
, std::pair
<Export
*, unsigned>> map(exports
.size());
1212 std::vector
<Export
> v
;
1213 for (Export
&e
: exports
) {
1214 auto pair
= map
.insert(std::make_pair(e
.exportName
, std::make_pair(&e
, 0)));
1215 bool inserted
= pair
.second
;
1217 pair
.first
->second
.second
= v
.size();
1221 Export
*existing
= pair
.first
->second
.first
;
1222 if (e
== *existing
|| e
.name
!= existing
->name
)
1224 // If the existing export comes from .OBJ directives, we are allowed to
1225 // overwrite it with /DEF: or /EXPORT without any warning, as MSVC link.exe
1227 if (existing
->source
== ExportSource::Directives
) {
1229 v
[pair
.first
->second
.second
] = e
;
1232 if (existing
->source
== e
.source
) {
1233 Warn(ctx
) << "duplicate " << exportSourceName(existing
->source
)
1234 << " option: " << e
.name
;
1236 Warn(ctx
) << "duplicate export: " << e
.name
<< " first seen in "
1237 << exportSourceName(existing
->source
) << ", now in "
1238 << exportSourceName(e
.source
);
1241 exports
= std::move(v
);
1244 llvm::sort(exports
, [](const Export
&a
, const Export
&b
) {
1245 return a
.exportName
< b
.exportName
;
1249 void SymbolTable::assignExportOrdinals() {
1250 // Assign unique ordinals if default (= 0).
1252 for (Export
&e
: exports
)
1253 max
= std::max(max
, (uint32_t)e
.ordinal
);
1254 for (Export
&e
: exports
)
1257 if (max
> std::numeric_limits
<uint16_t>::max())
1258 Fatal(ctx
) << "too many exported symbols (got " << max
<< ", max "
1259 << Twine(std::numeric_limits
<uint16_t>::max()) << ")";
1262 void SymbolTable::parseModuleDefs(StringRef path
) {
1263 llvm::TimeTraceScope
timeScope("Parse def file");
1264 std::unique_ptr
<MemoryBuffer
> mb
=
1265 CHECK(MemoryBuffer::getFile(path
, /*IsText=*/false,
1266 /*RequiresNullTerminator=*/false,
1267 /*IsVolatile=*/true),
1268 "could not open " + path
);
1269 COFFModuleDefinition m
= check(parseCOFFModuleDefinition(
1270 mb
->getMemBufferRef(), machine
, ctx
.config
.mingw
));
1272 // Include in /reproduce: output if applicable.
1273 ctx
.driver
.takeBuffer(std::move(mb
));
1275 if (ctx
.config
.outputFile
.empty())
1276 ctx
.config
.outputFile
= std::string(saver().save(m
.OutputFile
));
1277 ctx
.config
.importName
= std::string(saver().save(m
.ImportName
));
1279 ctx
.config
.imageBase
= m
.ImageBase
;
1281 ctx
.config
.stackReserve
= m
.StackReserve
;
1283 ctx
.config
.stackCommit
= m
.StackCommit
;
1285 ctx
.config
.heapReserve
= m
.HeapReserve
;
1287 ctx
.config
.heapCommit
= m
.HeapCommit
;
1288 if (m
.MajorImageVersion
)
1289 ctx
.config
.majorImageVersion
= m
.MajorImageVersion
;
1290 if (m
.MinorImageVersion
)
1291 ctx
.config
.minorImageVersion
= m
.MinorImageVersion
;
1292 if (m
.MajorOSVersion
)
1293 ctx
.config
.majorOSVersion
= m
.MajorOSVersion
;
1294 if (m
.MinorOSVersion
)
1295 ctx
.config
.minorOSVersion
= m
.MinorOSVersion
;
1297 for (COFFShortExport e1
: m
.Exports
) {
1299 // Renamed exports are parsed and set as "ExtName = Name". If Name has
1300 // the form "OtherDll.Func", it shouldn't be a normal exported
1301 // function but a forward to another DLL instead. This is supported
1302 // by both MS and GNU linkers.
1303 if (!e1
.ExtName
.empty() && e1
.ExtName
!= e1
.Name
&&
1304 StringRef(e1
.Name
).contains('.')) {
1305 e2
.name
= saver().save(e1
.ExtName
);
1306 e2
.forwardTo
= saver().save(e1
.Name
);
1308 e2
.name
= saver().save(e1
.Name
);
1309 e2
.extName
= saver().save(e1
.ExtName
);
1311 e2
.exportAs
= saver().save(e1
.ExportAs
);
1312 e2
.importName
= saver().save(e1
.ImportName
);
1313 e2
.ordinal
= e1
.Ordinal
;
1314 e2
.noname
= e1
.Noname
;
1316 e2
.isPrivate
= e1
.Private
;
1317 e2
.constant
= e1
.Constant
;
1318 e2
.source
= ExportSource::ModuleDefinition
;
1319 exports
.push_back(e2
);
1323 Symbol
*SymbolTable::addUndefined(StringRef name
) {
1324 return addUndefined(name
, nullptr, false);
1327 void SymbolTable::compileBitcodeFiles() {
1328 if (bitcodeFileInstances
.empty())
1331 llvm::TimeTraceScope
timeScope("Compile bitcode");
1332 ScopedTimer
t(ctx
.ltoTimer
);
1333 lto
.reset(new BitcodeCompiler(ctx
));
1334 for (BitcodeFile
*f
: bitcodeFileInstances
)
1336 for (InputFile
*newObj
: lto
->compile()) {
1337 ObjFile
*obj
= cast
<ObjFile
>(newObj
);
1339 ctx
.objFileInstances
.push_back(obj
);
1343 } // namespace lld::coff