-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[LLD][COFF] Make unresolved symbol search behavior compliant with MSVC link.exe #85290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 6 commits
d5c4adf
b1149e1
6c2a777
ad59e48
b115c60
9d910c7
865dc26
114870b
0ece320
4d6fcd8
87a90c3
c2e7c78
0f5d47e
baeca96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -187,7 +187,8 @@ MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> mb) { | |
} | ||
|
||
void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb, | ||
bool wholeArchive, bool lazy) { | ||
bool wholeArchive, bool lazy, | ||
ArchiveFile *parent) { | ||
StringRef filename = mb->getBufferIdentifier(); | ||
|
||
MemoryBufferRef mbref = takeBuffer(std::move(mb)); | ||
|
@@ -213,11 +214,11 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb, | |
ctx.symtab.addFile(make<ArchiveFile>(ctx, mbref)); | ||
break; | ||
case file_magic::bitcode: | ||
ctx.symtab.addFile(make<BitcodeFile>(ctx, mbref, "", 0, lazy)); | ||
ctx.symtab.addFile(make<BitcodeFile>(ctx, mbref, "", 0, lazy, parent)); | ||
break; | ||
case file_magic::coff_object: | ||
case file_magic::coff_import_library: | ||
ctx.symtab.addFile(make<ObjFile>(ctx, mbref, lazy)); | ||
ctx.symtab.addFile(make<ObjFile>(ctx, mbref, lazy, parent)); | ||
break; | ||
case file_magic::pdb: | ||
ctx.symtab.addFile(make<PDBInputFile>(ctx, mbref)); | ||
|
@@ -242,7 +243,9 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb, | |
} | ||
} | ||
|
||
void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) { | ||
void LinkerDriver::enqueuePath( | ||
StringRef path, bool wholeArchive, bool lazy, | ||
std::optional<std::shared_future<ArchiveFile *>> parent) { | ||
auto future = std::make_shared<std::future<MBErrPair>>( | ||
createFutureForFile(std::string(path))); | ||
std::string pathStr = std::string(path); | ||
|
@@ -281,13 +284,15 @@ void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) { | |
else | ||
error(msg + "; did you mean '" + nearest + "'"); | ||
} else | ||
ctx.driver.addBuffer(std::move(mb), wholeArchive, lazy); | ||
ctx.driver.addBuffer(std::move(mb), wholeArchive, lazy, | ||
parent ? parent->get() : nullptr); | ||
}); | ||
} | ||
|
||
void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName, | ||
StringRef parentName, | ||
uint64_t offsetInArchive) { | ||
uint64_t offsetInArchive, | ||
ArchiveFile *parent) { | ||
file_magic magic = identify_magic(mb.getBuffer()); | ||
if (magic == file_magic::coff_import_library) { | ||
InputFile *imp = make<ImportFile>(ctx, mb); | ||
|
@@ -298,10 +303,10 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName, | |
|
||
InputFile *obj; | ||
if (magic == file_magic::coff_object) { | ||
obj = make<ObjFile>(ctx, mb); | ||
obj = make<ObjFile>(ctx, mb, /*lazy=*/false, parent); | ||
} else if (magic == file_magic::bitcode) { | ||
obj = | ||
make<BitcodeFile>(ctx, mb, parentName, offsetInArchive, /*lazy=*/false); | ||
obj = make<BitcodeFile>(ctx, mb, parentName, offsetInArchive, | ||
/*lazy=*/false, parent); | ||
} else if (magic == file_magic::coff_cl_gl_object) { | ||
error(mb.getBufferIdentifier() + | ||
": is not a native COFF file. Recompile without /GL?"); | ||
|
@@ -318,7 +323,8 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName, | |
|
||
void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, | ||
const Archive::Symbol &sym, | ||
StringRef parentName) { | ||
StringRef parentName, | ||
ArchiveFile *parent) { | ||
|
||
auto reportBufferError = [=](Error &&e, StringRef childName) { | ||
fatal("could not get the buffer for the member defining symbol " + | ||
|
@@ -335,7 +341,7 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, | |
enqueueTask([=]() { | ||
llvm::TimeTraceScope timeScope("Archive: ", mb.getBufferIdentifier()); | ||
ctx.driver.addArchiveBuffer(mb, toCOFFString(ctx, sym), parentName, | ||
offsetInArchive); | ||
offsetInArchive, parent); | ||
}); | ||
return; | ||
} | ||
|
@@ -356,7 +362,15 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, | |
// used as the buffer identifier. | ||
ctx.driver.addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), | ||
toCOFFString(ctx, sym), "", | ||
/*OffsetInArchive=*/0); | ||
/*OffsetInArchive=*/0, parent); | ||
}); | ||
} | ||
|
||
void LinkerDriver::enqueueLazyFile(InputFile *file) { | ||
enqueueTask([=]() { | ||
// Once it has been enqued, it cannot be lazy anymore. | ||
file->lazy = false; | ||
ctx.symtab.addFile(file); | ||
}); | ||
} | ||
|
||
|
@@ -2111,25 +2125,38 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { | |
{ | ||
llvm::TimeTraceScope timeScope2("Parse & queue inputs"); | ||
bool inLib = false; | ||
std::optional<std::shared_future<ArchiveFile *>> inLibArchive; | ||
for (auto *arg : args) { | ||
switch (arg->getOption().getID()) { | ||
case OPT_end_lib: | ||
if (!inLib) | ||
error("stray " + arg->getSpelling()); | ||
inLib = false; | ||
inLibArchive = std::nullopt; | ||
break; | ||
case OPT_start_lib: | ||
if (inLib) | ||
error("nested " + arg->getSpelling()); | ||
inLib = true; | ||
// In is important to create a fake archive here so that we remember its | ||
// placement on the command-line. This will be later needed to resolve | ||
// symbols in the archive order required by the MSVC specification. | ||
{ | ||
auto a = std::make_shared<std::promise<ArchiveFile *>>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Review note: this is made a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is nitty code golf, but can this be implemented with an explicit lambda capture and std::move? This SO pattern is what I was thinking of. Maybe the task gets copied around more, so if not, then the shared_ptr is fine. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did try several things, including what you're suggesting, as well as the std::bind trick, but nothing else works, besides the |
||
inLibArchive = a->get_future().share(); | ||
enqueueTask([=] { | ||
a->set_value( | ||
make<ArchiveFile>(ctx, MemoryBufferRef({}, "<cmdline-lib>"))); | ||
}); | ||
} | ||
break; | ||
case OPT_wholearchive_file: | ||
if (std::optional<StringRef> path = findFileIfNew(arg->getValue())) | ||
enqueuePath(*path, true, inLib); | ||
break; | ||
case OPT_INPUT: | ||
if (std::optional<StringRef> path = findFileIfNew(arg->getValue())) | ||
enqueuePath(*path, isWholeArchive(*path), inLib); | ||
enqueuePath(*path, isWholeArchive(*path), inLib, inLibArchive); | ||
break; | ||
default: | ||
// Ignore other options. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,9 +94,12 @@ static bool ignoredSymbolName(StringRef name) { | |
} | ||
|
||
ArchiveFile::ArchiveFile(COFFLinkerContext &ctx, MemoryBufferRef m) | ||
: InputFile(ctx, ArchiveKind, m) {} | ||
: InputFile(ctx, ArchiveKind, m, /*lazy=*/true) { | ||
static unsigned Order = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could be a member of |
||
CmdLineIndex = Order++; | ||
} | ||
|
||
void ArchiveFile::parse() { | ||
void ArchiveFile::parseLazy() { | ||
// Parse a MemoryBufferRef as an archive file. | ||
file = CHECK(Archive::create(mb), this); | ||
|
||
|
@@ -115,7 +118,7 @@ void ArchiveFile::addMember(const Archive::Symbol &sym) { | |
if (!seen.insert(c.getChildOffset()).second) | ||
return; | ||
|
||
ctx.driver.enqueueArchiveMember(c, sym, getName()); | ||
ctx.driver.enqueueArchiveMember(c, sym, getName(), this); | ||
} | ||
|
||
std::vector<MemoryBufferRef> lld::coff::getArchiveMembers(Archive *file) { | ||
|
@@ -1000,8 +1003,8 @@ void ImportFile::parse() { | |
|
||
BitcodeFile::BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb, | ||
StringRef archiveName, uint64_t offsetInArchive, | ||
bool lazy) | ||
: InputFile(ctx, BitcodeKind, mb, lazy) { | ||
bool lazy, ArchiveFile *parent) | ||
: InputFile(ctx, BitcodeKind, mb, lazy), parent(parent) { | ||
std::string path = mb.getBufferIdentifier().str(); | ||
if (ctx.config.thinLTOIndexOnly) | ||
path = replaceThinLTOSuffix(mb.getBufferIdentifier(), | ||
|
Uh oh!
There was an error while loading. Please reload this page.