Skip to content

Commit

Permalink
Merging r366836:
Browse files Browse the repository at this point in the history
------------------------------------------------------------------------
r366836 | nico | 2019-07-23 21:00:01 +0200 (Tue, 23 Jul 2019) | 24 lines

ld.lld: Demangle symbols from archives in diagnostics

This ports r366573 from COFF to ELF.

There are now to toString(Archive::Symbol), one doing MSVC demangling
in COFF and one doing Itanium demangling in ELF, so rename these two
to toCOFFString() and to toELFString() to not get a duplicate symbol.

Nothing ever passes a raw Archive::Symbol to CHECK(), so these not
being part of the normal toString() machinery seems ok.

There are two code paths in the ELF linker that emits this type of
diagnostic:

1. The "normal" one in InputFiles.cpp. This is covered by the tweaked test.

2. An additional one that's only used for libcalls if there's at least
   one bitcode in the link, and if the libcall symbol is lazy, and
   lazily loaded from an archive (i.e. not from a lazy .o file).
   (This code path was added in r339301.) Since all libcall names so far
   are C symbols and never mangled, the change there is not observable
   and hence not covered by tests.

Differential Revision: https://reviews.llvm.org/D65095
------------------------------------------------------------------------

llvm-svn: 369882
  • Loading branch information
zmodem committed Aug 26, 2019
1 parent 565fc9f commit c343ded
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 29 deletions.
10 changes: 6 additions & 4 deletions lld/COFF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,

auto reportBufferError = [=](Error &&e, StringRef childName) {
fatal("could not get the buffer for the member defining symbol " +
toString(sym) + ": " + parentName + "(" + childName + "): " +
toCOFFString(sym) + ": " + parentName + "(" + childName + "): " +
toString(std::move(e)));
};

Expand All @@ -287,23 +287,25 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,
reportBufferError(mbOrErr.takeError(), check(c.getFullName()));
MemoryBufferRef mb = mbOrErr.get();
enqueueTask([=]() {
driver->addArchiveBuffer(mb, toString(sym), parentName, offsetInArchive);
driver->addArchiveBuffer(mb, toCOFFString(sym), parentName,
offsetInArchive);
});
return;
}

std::string childName = CHECK(
c.getFullName(),
"could not get the filename for the member defining symbol " +
toString(sym));
toCOFFString(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)),
toString(sym), parentName, /*OffsetInArchive=*/0);
toCOFFString(sym), parentName,
/*OffsetInArchive=*/0);
});
}

Expand Down
5 changes: 3 additions & 2 deletions lld/COFF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ 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 " + toString(sym));
const Archive::Child &c =
CHECK(sym.getMember(),
"could not get the member for symbol " + toCOFFString(sym));

// Return an empty buffer if we have already returned the same buffer.
if (!seen.insert(c.getChildOffset()).second)
Expand Down
4 changes: 3 additions & 1 deletion lld/COFF/Symbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ static std::string demangle(StringRef symName) {
return symName;
}
std::string toString(coff::Symbol &b) { return demangle(b.getName()); }
std::string toString(const Archive::Symbol &b) { return demangle(b.getName()); }
std::string toCOFFString(const Archive::Symbol &b) {
return demangle(b.getName());
}

namespace coff {

Expand Down
10 changes: 8 additions & 2 deletions lld/COFF/Symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@
#include <vector>

namespace lld {

std::string toString(coff::Symbol &b);

// There are two different ways to convert an Archive::Symbol to a string:
// One for Microsoft name mangling and one for Itanium name mangling.
// Call the functions toCOFFString and toELFString, not just toString.
std::string toCOFFString(const coff::Archive::Symbol &b);

namespace coff {

using llvm::object::Archive;
Expand Down Expand Up @@ -429,8 +437,6 @@ 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
4 changes: 2 additions & 2 deletions lld/ELF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,7 @@ void ArchiveFile::fetch(const Archive::Symbol &sym) {
Archive::Child c =
CHECK(sym.getMember(), toString(this) +
": could not get the member for symbol " +
sym.getName());
toELFString(sym));

if (!seen.insert(c.getChildOffset()).second)
return;
Expand All @@ -1153,7 +1153,7 @@ void ArchiveFile::fetch(const Archive::Symbol &sym) {
CHECK(c.getMemoryBufferRef(),
toString(this) +
": could not get the buffer for the member defining symbol " +
sym.getName());
toELFString(sym));

if (tar && c.getParent()->isThin())
tar->append(relativeToRoot(CHECK(c.getFullName(), this)), mb.getBuffer());
Expand Down
29 changes: 18 additions & 11 deletions lld/ELF/Symbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ Defined *ElfSym::relaIpltEnd;
Defined *ElfSym::riscvGlobalPointer;
Defined *ElfSym::tlsModuleBase;

// Returns a symbol for an error message.
static std::string demangle(StringRef symName) {
if (config->demangle)
if (Optional<std::string> s = demangleItanium(symName))
return *s;
return symName;
}
namespace lld {
std::string toString(const Symbol &b) { return demangle(b.getName()); }
std::string toELFString(const Archive::Symbol &b) {
return demangle(b.getName());
}
} // namespace lld

static uint64_t getSymVA(const Symbol &sym, int64_t &addend) {
switch (sym.kind()) {
case Symbol::DefinedKind: {
Expand Down Expand Up @@ -250,12 +264,13 @@ void Symbol::fetch() const {
}

MemoryBufferRef LazyArchive::getMemberBuffer() {
Archive::Child c = CHECK(
sym.getMember(), "could not get the member for symbol " + sym.getName());
Archive::Child c =
CHECK(sym.getMember(),
"could not get the member for symbol " + toELFString(sym));

return CHECK(c.getMemoryBufferRef(),
"could not get the buffer for the member defining symbol " +
sym.getName());
toELFString(sym));
}

uint8_t Symbol::computeBinding() const {
Expand Down Expand Up @@ -331,14 +346,6 @@ void elf::maybeWarnUnorderableSymbol(const Symbol *sym) {
report(": unable to order discarded symbol: ");
}

// Returns a symbol for an error message.
std::string lld::toString(const Symbol &b) {
if (config->demangle)
if (Optional<std::string> s = demangleItanium(b.getName()))
return *s;
return b.getName();
}

static uint8_t getMinVisibility(uint8_t va, uint8_t vb) {
if (va == STV_DEFAULT)
return vb;
Expand Down
6 changes: 5 additions & 1 deletion lld/ELF/Symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ class Undefined;
} // namespace elf

std::string toString(const elf::Symbol &);
std::string toString(const elf::InputFile *);

// There are two different ways to convert an Archive::Symbol to a string:
// One for Microsoft name mangling and one for Itanium name mangling.
// Call the functions toCOFFString and toELFString, not just toString.
std::string toELFString(const elf::Archive::Symbol &);

namespace elf {

Expand Down
14 changes: 8 additions & 6 deletions lld/test/ELF/archive-thin-missing-member.s
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@
# RUN: rm %t.o

# Test error when loading symbols from missing thin archive member.
# RUN: not ld.lld %t-no-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR1
# RUN: not ld.lld --entry=_Z1fi %t-no-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR1
# ERR1: {{.*}}-no-syms.a: could not get the buffer for a child of the archive: '{{.*}}.o': {{[Nn]}}o such file or directory

# Test error when thin archive has symbol table but member is missing.
# RUN: not ld.lld -m elf_amd64_fbsd %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2
# ERR2: {{.*}}-syms.a: could not get the buffer for the member defining symbol _start: '{{.*}}.o': {{[Nn]}}o such file or directory
# RUN: not ld.lld --entry=_Z1fi -m elf_amd64_fbsd %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2
# ERR2: {{.*}}-syms.a: could not get the buffer for the member defining symbol f(int): '{{.*}}.o': {{[Nn]}}o such file or directory
# RUN: not ld.lld --entry=_Z1fi --no-demangle -m elf_amd64_fbsd %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2MANGLE
# ERR2MANGLE: {{.*}}-syms.a: could not get the buffer for the member defining symbol _Z1fi: '{{.*}}.o': {{[Nn]}}o such file or directory

# Test error when thin archive is linked using --whole-archive but member is missing.
# RUN: not ld.lld --whole-archive %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR3
# RUN: not ld.lld --entry=_Z1fi --whole-archive %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR3
# ERR3: {{.*}}-syms.a: could not get the buffer for a child of the archive: '{{.*}}.o': {{[Nn]}}o such file or directory

.global _start
_start:
.global _Z1fi
_Z1fi:
nop

0 comments on commit c343ded

Please sign in to comment.