lld-link: Demangle symbols from archives in diagnostics
Also add test coverage for thin archives (which are the only way I could come up with to test at least some of the diagnostic changes). Differential Revision: https://reviews.llvm.org/D64927 llvm-svn: 366573
This commit is contained in:
parent
b288d90b39
commit
cb2c50028d
|
@ -268,13 +268,12 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName,
|
|||
}
|
||||
|
||||
void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,
|
||||
StringRef symName,
|
||||
const Archive::Symbol &sym,
|
||||
StringRef parentName) {
|
||||
|
||||
auto reportBufferError = [=](Error &&e,
|
||||
StringRef childName) {
|
||||
auto reportBufferError = [=](Error &&e, StringRef childName) {
|
||||
fatal("could not get the buffer for the member defining symbol " +
|
||||
symName + ": " + parentName + "(" + childName + "): " +
|
||||
toString(sym) + ": " + parentName + "(" + childName + "): " +
|
||||
toString(std::move(e)));
|
||||
};
|
||||
|
||||
|
@ -285,7 +284,7 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,
|
|||
reportBufferError(mbOrErr.takeError(), check(c.getFullName()));
|
||||
MemoryBufferRef mb = mbOrErr.get();
|
||||
enqueueTask([=]() {
|
||||
driver->addArchiveBuffer(mb, symName, parentName, offsetInArchive);
|
||||
driver->addArchiveBuffer(mb, toString(sym), parentName, offsetInArchive);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -293,15 +292,15 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,
|
|||
std::string childName = CHECK(
|
||||
c.getFullName(),
|
||||
"could not get the filename for the member defining symbol " +
|
||||
symName);
|
||||
toString(sym));
|
||||
auto future = std::make_shared<std::future<MBErrPair>>(
|
||||
createFutureForFile(childName));
|
||||
enqueueTask([=]() {
|
||||
auto mbOrErr = future->get();
|
||||
if (mbOrErr.second)
|
||||
reportBufferError(errorCodeToError(mbOrErr.second), childName);
|
||||
driver->addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), symName,
|
||||
parentName, /* OffsetInArchive */ 0);
|
||||
driver->addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)),
|
||||
toString(sym), parentName, /*OffsetInArchive=*/0);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ public:
|
|||
void parseDirectives(InputFile *file);
|
||||
|
||||
// Used by ArchiveFile to enqueue members.
|
||||
void enqueueArchiveMember(const Archive::Child &c, StringRef symName,
|
||||
void enqueueArchiveMember(const Archive::Child &c, const Archive::Symbol &sym,
|
||||
StringRef parentName);
|
||||
|
||||
MemoryBufferRef takeBuffer(std::unique_ptr<MemoryBuffer> mb);
|
||||
|
|
|
@ -85,16 +85,15 @@ void ArchiveFile::parse() {
|
|||
}
|
||||
|
||||
// Returns a buffer pointing to a member file containing a given symbol.
|
||||
void ArchiveFile::addMember(const Archive::Symbol *sym) {
|
||||
const Archive::Child &c =
|
||||
CHECK(sym->getMember(),
|
||||
"could not get the member for symbol " + sym->getName());
|
||||
void ArchiveFile::addMember(const Archive::Symbol &sym) {
|
||||
const Archive::Child &c = CHECK(
|
||||
sym.getMember(), "could not get the member for symbol " + toString(sym));
|
||||
|
||||
// Return an empty buffer if we have already returned the same buffer.
|
||||
if (!seen.insert(c.getChildOffset()).second)
|
||||
return;
|
||||
|
||||
driver->enqueueArchiveMember(c, sym->getName(), getName());
|
||||
driver->enqueueArchiveMember(c, sym, getName());
|
||||
}
|
||||
|
||||
std::vector<MemoryBufferRef> getArchiveMembers(Archive *file) {
|
||||
|
|
|
@ -96,7 +96,7 @@ public:
|
|||
// Enqueues an archive member load for the given symbol. If we've already
|
||||
// enqueued a load for the same archive member, this function does nothing,
|
||||
// which ensures that we don't load the same member more than once.
|
||||
void addMember(const Archive::Symbol *sym);
|
||||
void addMember(const Archive::Symbol &sym);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Archive> file;
|
||||
|
|
|
@ -179,7 +179,7 @@ void SymbolTable::loadMinGWAutomaticImports() {
|
|||
log("Loading lazy " + l->getName() + " from " + l->file->getName() +
|
||||
" for automatic import");
|
||||
l->pendingArchiveLoad = true;
|
||||
l->file->addMember(&l->sym);
|
||||
l->file->addMember(l->sym);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,13 +363,13 @@ Symbol *SymbolTable::addUndefined(StringRef name, InputFile *f,
|
|||
if (auto *l = dyn_cast<Lazy>(s)) {
|
||||
if (!s->pendingArchiveLoad) {
|
||||
s->pendingArchiveLoad = true;
|
||||
l->file->addMember(&l->sym);
|
||||
l->file->addMember(l->sym);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void SymbolTable::addLazy(ArchiveFile *f, const Archive::Symbol sym) {
|
||||
void SymbolTable::addLazy(ArchiveFile *f, const Archive::Symbol &sym) {
|
||||
StringRef name = sym.getName();
|
||||
Symbol *s;
|
||||
bool wasInserted;
|
||||
|
@ -382,7 +382,7 @@ void SymbolTable::addLazy(ArchiveFile *f, const Archive::Symbol sym) {
|
|||
if (!u || u->weakAlias || s->pendingArchiveLoad)
|
||||
return;
|
||||
s->pendingArchiveLoad = true;
|
||||
f->addMember(&sym);
|
||||
f->addMember(sym);
|
||||
}
|
||||
|
||||
void SymbolTable::reportDuplicate(Symbol *existing, InputFile *newFile) {
|
||||
|
|
|
@ -83,7 +83,7 @@ public:
|
|||
Symbol *addAbsolute(StringRef n, uint64_t va);
|
||||
|
||||
Symbol *addUndefined(StringRef name, InputFile *f, bool isWeakAlias);
|
||||
void addLazy(ArchiveFile *f, const Archive::Symbol sym);
|
||||
void addLazy(ArchiveFile *f, const Archive::Symbol &sym);
|
||||
Symbol *addAbsolute(StringRef n, COFFSymbolRef s);
|
||||
Symbol *addRegular(InputFile *f, StringRef n,
|
||||
const llvm::object::coff_symbol_generic *s = nullptr,
|
||||
|
|
|
@ -20,18 +20,21 @@ using namespace llvm::object;
|
|||
|
||||
using namespace lld::coff;
|
||||
|
||||
namespace lld {
|
||||
|
||||
static_assert(sizeof(SymbolUnion) <= 48,
|
||||
"symbols should be optimized for memory usage");
|
||||
|
||||
// Returns a symbol name for an error message.
|
||||
std::string lld::toString(coff::Symbol &b) {
|
||||
static std::string demangle(StringRef symName) {
|
||||
if (config->demangle)
|
||||
if (Optional<std::string> s = lld::demangleMSVC(b.getName()))
|
||||
if (Optional<std::string> s = demangleMSVC(symName))
|
||||
return *s;
|
||||
return b.getName();
|
||||
return symName;
|
||||
}
|
||||
std::string toString(coff::Symbol &b) { return demangle(b.getName()); }
|
||||
std::string toString(const Archive::Symbol &b) { return demangle(b.getName()); }
|
||||
|
||||
namespace lld {
|
||||
namespace coff {
|
||||
|
||||
StringRef Symbol::getName() {
|
||||
|
|
|
@ -430,6 +430,7 @@ void replaceSymbol(Symbol *s, ArgT &&... arg) {
|
|||
} // namespace coff
|
||||
|
||||
std::string toString(coff::Symbol &b);
|
||||
std::string toString(const coff::Archive::Symbol &b);
|
||||
} // namespace lld
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
.text
|
||||
|
||||
.def "?f@@YAHXZ"
|
||||
.scl 2
|
||||
.type 32
|
||||
.endef
|
||||
.global "?f@@YAHXZ"
|
||||
"?f@@YAHXZ":
|
||||
retq $0
|
|
@ -0,0 +1,36 @@
|
|||
# REQUIRES: x86
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %t.main.obj %s
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %t.lib.obj \
|
||||
# RUN: %S/Inputs/mangled-symbol.s
|
||||
# RUN: lld-link /lib /out:%t.lib %t.lib.obj
|
||||
# RUN: lld-link /lib /llvmlibthin /out:%t_thin.lib %t.lib.obj
|
||||
|
||||
# RUN: lld-link /entry:main %t.main.obj %t.lib /out:%t.exe 2>&1 | \
|
||||
# RUN: FileCheck --allow-empty %s
|
||||
# RUN: lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe 2>&1 | \
|
||||
# RUN: FileCheck --allow-empty %s
|
||||
|
||||
# RUN: rm %t.lib.obj
|
||||
# RUN: lld-link /entry:main %t.main.obj %t.lib /out:%t.exe 2>&1 | \
|
||||
# RUN: FileCheck --allow-empty %s
|
||||
# RUN: not lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe 2>&1 | \
|
||||
# RUN: FileCheck --check-prefix=NOOBJ %s
|
||||
# RUN: not lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe \
|
||||
# RUN: /demangle:no 2>&1 | FileCheck --check-prefix=NOOBJNODEMANGLE %s
|
||||
|
||||
# CHECK-NOT: error: could not get the buffer for the member defining
|
||||
# NOOBJ: error: could not get the buffer for the member defining symbol int __cdecl f(void): {{.*}}.lib({{.*}}.lib.obj):
|
||||
# NOOBJNODEMANGLE: error: could not get the buffer for the member defining symbol ?f@@YAHXZ: {{.*}}.lib({{.*}}.lib.obj):
|
||||
|
||||
.text
|
||||
|
||||
.def main
|
||||
.scl 2
|
||||
.type 32
|
||||
.endef
|
||||
.global main
|
||||
main:
|
||||
call "?f@@YAHXZ"
|
||||
retq $0
|
Loading…
Reference in New Issue