Skip to content

Commit

Permalink
[lld] Add support for other demanglers other than Itanium
Browse files Browse the repository at this point in the history
LLVM core library supports demangling other mangled symbols other than itanium,
such as D and Rust. LLD should use those demanglers in order to output pretty
demangled symbols on error messages.

Reviewed By: MaskRay, #lld-macho

Differential Revision: https://reviews.llvm.org/D116279
  • Loading branch information
ljmf00 committed Jan 5, 2022
1 parent 1eb5b6e commit 10e40a4
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 42 deletions.
4 changes: 2 additions & 2 deletions lld/COFF/Symbols.cpp
Expand Up @@ -36,9 +36,9 @@ static std::string maybeDemangleSymbol(StringRef symName) {
StringRef demangleInput = prefixless;
if (config->machine == I386)
demangleInput.consume_front("_");
std::string demangled = demangle(std::string(demangleInput));
std::string demangled = demangle(demangleInput, true);
if (demangled != demangleInput)
return prefix + demangle(std::string(demangleInput));
return prefix + demangle(demangleInput, true);
return (prefix + prefixless).str();
}
return std::string(symName);
Expand Down
13 changes: 0 additions & 13 deletions lld/Common/Strings.cpp
Expand Up @@ -9,7 +9,6 @@
#include "lld/Common/Strings.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/LLVM.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/GlobPattern.h"
#include <algorithm>
Expand All @@ -19,18 +18,6 @@
using namespace llvm;
using namespace lld;

// Returns the demangled C++ symbol name for name.
std::string lld::demangleItanium(StringRef name) {
// demangleItanium() can be called for all symbols. Only demangle C++ symbols,
// to avoid getting unexpected result for a C symbol that happens to match a
// mangled type name such as "Pi" (which would demangle to "int*").
if (!name.startswith("_Z") && !name.startswith("__Z") &&
!name.startswith("___Z") && !name.startswith("____Z"))
return std::string(name);

return demangle(std::string(name));
}

SingleStringMatcher::SingleStringMatcher(StringRef Pattern) {
if (Pattern.size() > 2 && Pattern.startswith("\"") &&
Pattern.endswith("\"")) {
Expand Down
9 changes: 5 additions & 4 deletions lld/ELF/SymbolTable.cpp
Expand Up @@ -143,12 +143,13 @@ StringMap<SmallVector<Symbol *, 0>> &SymbolTable::getDemangledSyms() {
StringRef name = sym->getName();
size_t pos = name.find('@');
if (pos == std::string::npos)
demangled = demangleItanium(name);
demangled = demangle(name, config->demangle);
else if (pos + 1 == name.size() || name[pos + 1] == '@')
demangled = demangleItanium(name.substr(0, pos));
demangled = demangle(name.substr(0, pos), config->demangle);
else
demangled =
(demangleItanium(name.substr(0, pos)) + name.substr(pos)).str();
demangled = (demangle(name.substr(0, pos), config->demangle) +
name.substr(pos))
.str();
(*demangledSyms)[demangled].push_back(sym);
}
}
Expand Down
11 changes: 2 additions & 9 deletions lld/ELF/Symbols.cpp
Expand Up @@ -26,16 +26,9 @@ using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;

// Returns a symbol for an error message.
static std::string demangle(StringRef symName) {
if (elf::config->demangle)
return demangleItanium(symName);
return std::string(symName);
}

std::string lld::toString(const elf::Symbol &sym) {
StringRef name = sym.getName();
std::string ret = demangle(name);
std::string ret = demangle(name, config->demangle);

const char *suffix = sym.getVersionSuffix();
if (*suffix == '@')
Expand All @@ -44,7 +37,7 @@ std::string lld::toString(const elf::Symbol &sym) {
}

std::string lld::toELFString(const Archive::Symbol &b) {
return demangle(b.getName());
return demangle(b.getName(), config->demangle);
}

Defined *ElfSym::bss;
Expand Down
1 change: 1 addition & 0 deletions lld/MachO/CMakeLists.txt
Expand Up @@ -38,6 +38,7 @@ add_lld_library(lldMachO
BitReader
Core
DebugInfoDWARF
Demangle
LTO
MC
ObjCARCOpts
Expand Down
12 changes: 4 additions & 8 deletions lld/MachO/Symbols.cpp
Expand Up @@ -9,6 +9,7 @@
#include "Symbols.h"
#include "InputFiles.h"
#include "SyntheticSections.h"
#include "lld/Common/Strings.h"

using namespace llvm;
using namespace lld;
Expand All @@ -27,17 +28,12 @@ static_assert(sizeof(void *) != 8 || sizeof(Defined) == 80,
static_assert(sizeof(SymbolUnion) == sizeof(Defined),
"Defined should be the largest Symbol kind");
// Returns a symbol for an error message.
static std::string demangle(StringRef symName) {
if (config->demangle)
return demangleItanium(symName);
return std::string(symName);
std::string lld::toString(const Symbol &sym) {
return demangle(sym.getName(), config->demangle);
}
std::string lld::toString(const Symbol &sym) { return demangle(sym.getName()); }
std::string lld::toMachOString(const object::Archive::Symbol &b) {
return demangle(b.getName());
return demangle(b.getName(), config->demangle);
}
uint64_t Symbol::getStubVA() const { return in.stubs->getVA(stubsIndex); }
Expand Down
11 changes: 8 additions & 3 deletions lld/include/lld/Common/Strings.h
Expand Up @@ -12,14 +12,19 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/GlobPattern.h"
#include <string>
#include <vector>

namespace lld {
// Returns a demangled C++ symbol name. If Name is not a mangled
// name, it returns name.
std::string demangleItanium(llvm::StringRef name);
// Returns a demangled symbol name. If Name is not a mangled name, it returns
// name.
inline std::string demangle(llvm::StringRef symName, bool shouldDemangle) {
if (shouldDemangle)
return llvm::demangle(symName.str().c_str());
return std::string(symName);
}

std::vector<uint8_t> parseHex(llvm::StringRef s);
bool isValidCIdentifier(llvm::StringRef s);
Expand Down
15 changes: 15 additions & 0 deletions lld/test/ELF/undef.s
Expand Up @@ -31,6 +31,18 @@
# CHECK-NEXT: >>> referenced by undef.s
# CHECK-NEXT: >>> {{.*}}:(.text+0x1A)

# CHECK: error: undefined symbol: Pi
# CHECK-NEXT: >>> referenced by undef.s
# CHECK-NEXT: >>> {{.*}}:(.text+0x1F)

# CHECK: error: undefined symbol: D main
# CHECK-NEXT: >>> referenced by undef.s
# CHECK-NEXT: >>> {{.*}}:(.text+0x24)

# CHECK: error: undefined symbol: a::main
# CHECK-NEXT: >>> referenced by undef.s
# CHECK-NEXT: >>> {{.*}}:(.text+0x29)

# CHECK: error: undefined symbol: zed2
# CHECK-NEXT: >>> referenced by {{.*}}.o:(.text+0x0) in archive {{.*}}2.a

Expand Down Expand Up @@ -84,3 +96,6 @@ _start:
call _Z3fooi
call _ZTV3Foo
call __Z3fooi
call Pi
call _Dmain
call _RNvC1a4main
6 changes: 3 additions & 3 deletions lld/wasm/Symbols.cpp
Expand Up @@ -22,6 +22,7 @@
using namespace llvm;
using namespace llvm::object;
using namespace llvm::wasm;
using namespace lld::wasm;

namespace lld {
std::string toString(const wasm::Symbol &sym) {
Expand All @@ -33,9 +34,8 @@ std::string maybeDemangleSymbol(StringRef name) {
// `main` in the case where we need to pass it arguments.
if (name == "__main_argc_argv")
return "main";
if (wasm::config->demangle)
return demangleItanium(name);
return std::string(name);

return demangle(name, config->demangle);
}

std::string toString(wasm::Symbol::Kind kind) {
Expand Down

0 comments on commit 10e40a4

Please sign in to comment.