Index: lld/COFF/CMakeLists.txt =================================================================== --- lld/COFF/CMakeLists.txt +++ lld/COFF/CMakeLists.txt @@ -30,6 +30,7 @@ DebugInfoCodeView DebugInfoMSF DebugInfoPDB + Demangle LibDriver LTO MC Index: lld/COFF/Symbols.cpp =================================================================== --- lld/COFF/Symbols.cpp +++ lld/COFF/Symbols.cpp @@ -12,6 +12,7 @@ #include "lld/Common/Memory.h" #include "lld/Common/Strings.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -26,26 +27,25 @@ "symbols should be optimized for memory usage"); // Returns a symbol name for an error message. -static std::string demangle(StringRef symName) { +static std::string maybeDemangleSymbol(StringRef symName) { if (config->demangle) { - if (Optional s = demangleMSVC(symName)) - return *s; - if (config->mingw) { - StringRef demangleInput = symName; - std::string prefix; - if (demangleInput.consume_front("__imp_")) - prefix = "__declspec(dllimport) "; - if (config->machine == I386) - demangleInput.consume_front("_"); - if (Optional s = demangleItanium(demangleInput)) - return prefix + *s; - } + std::string prefix; + StringRef demangleInput = symName; + if (demangleInput.consume_front("__imp_")) + prefix = "__declspec(dllimport) "; + if (config->machine == I386) + demangleInput.consume_front("_"); + if (Optional s = + tryDemangle(demangleInput, /* StrictPrefix */ true)) + return prefix + *s; } return symName; } -std::string toString(coff::Symbol &b) { return demangle(b.getName()); } +std::string toString(coff::Symbol &b) { + return maybeDemangleSymbol(b.getName()); +} std::string toCOFFString(const Archive::Symbol &b) { - return demangle(b.getName()); + return maybeDemangleSymbol(b.getName()); } namespace coff { Index: lld/Common/CMakeLists.txt =================================================================== --- lld/Common/CMakeLists.txt +++ lld/Common/CMakeLists.txt @@ -46,7 +46,6 @@ LINK_COMPONENTS Codegen Core - Demangle MC Option Support Index: lld/Common/Strings.cpp =================================================================== --- lld/Common/Strings.cpp +++ lld/Common/Strings.cpp @@ -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/GlobPattern.h" #include #include @@ -18,41 +17,6 @@ using namespace llvm; using namespace lld; -// Returns the demangled C++ symbol name for Name. -Optional lld::demangleItanium(StringRef name) { - // itaniumDemangle can be used to demangle strings other than symbol - // names which do not necessarily start with "_Z". Name can be - // either a C or C++ symbol. Don't call itaniumDemangle if the name - // does not look like a C++ symbol name to avoid getting unexpected - // result for a C symbol that happens to match a mangled type name. - if (!name.startswith("_Z")) - return None; - - char *buf = itaniumDemangle(name.str().c_str(), nullptr, nullptr, nullptr); - if (!buf) - return None; - std::string s(buf); - free(buf); - return s; -} - -Optional lld::demangleMSVC(StringRef name) { - std::string prefix; - if (name.consume_front("__imp_")) - prefix = "__declspec(dllimport) "; - - // Demangle only C++ names. - if (!name.startswith("?")) - return None; - - char *buf = microsoftDemangle(name.str().c_str(), nullptr, nullptr, nullptr); - if (!buf) - return None; - std::string s(buf); - free(buf); - return prefix + s; -} - StringMatcher::StringMatcher(ArrayRef pat) { for (StringRef s : pat) { Expected pat = GlobPattern::create(s); Index: lld/ELF/CMakeLists.txt =================================================================== --- lld/ELF/CMakeLists.txt +++ lld/ELF/CMakeLists.txt @@ -51,6 +51,7 @@ BitWriter Core DebugInfoDWARF + Demangle LTO MC Object Index: lld/ELF/SymbolTable.cpp =================================================================== --- lld/ELF/SymbolTable.cpp +++ lld/ELF/SymbolTable.cpp @@ -22,6 +22,7 @@ #include "lld/Common/Memory.h" #include "lld/Common/Strings.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Demangle/Demangle.h" using namespace llvm; using namespace llvm::object; @@ -123,10 +124,8 @@ for (Symbol *sym : symVector) { if (!sym->isDefined() && !sym->isCommon()) continue; - if (Optional s = demangleItanium(sym->getName())) - (*demangledSyms)[*s].push_back(sym); - else - (*demangledSyms)[sym->getName()].push_back(sym); + (*demangledSyms)[demangle(sym->getName(), /* StrictPrefix */ true)] + .push_back(sym); } } return *demangledSyms; Index: lld/ELF/Symbols.cpp =================================================================== --- lld/ELF/Symbols.cpp +++ lld/ELF/Symbols.cpp @@ -16,6 +16,7 @@ #include "lld/Common/ErrorHandler.h" #include "lld/Common/Strings.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/Support/Path.h" #include @@ -43,16 +44,17 @@ Defined *ElfSym::tlsModuleBase; // Returns a symbol for an error message. -static std::string demangle(StringRef symName) { +static std::string maybeDemangleSymbol(StringRef symName) { if (config->demangle) - if (Optional s = demangleItanium(symName)) - return *s; + return demangle(symName, /* StrictPrefix */ true); return symName; } namespace lld { -std::string toString(const Symbol &b) { return demangle(b.getName()); } +std::string toString(const Symbol &b) { + return maybeDemangleSymbol(b.getName()); +} std::string toELFString(const Archive::Symbol &b) { - return demangle(b.getName()); + return maybeDemangleSymbol(b.getName()); } } // namespace lld Index: lld/include/lld/Common/Strings.h =================================================================== --- lld/include/lld/Common/Strings.h +++ lld/include/lld/Common/Strings.h @@ -10,17 +10,12 @@ #define LLD_STRINGS_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/GlobPattern.h" #include #include namespace lld { -// Returns a demangled C++ symbol name. If Name is not a mangled -// name, it returns Optional::None. -llvm::Optional demangleItanium(llvm::StringRef name); -llvm::Optional demangleMSVC(llvm::StringRef s); std::vector parseHex(llvm::StringRef s); bool isValidCIdentifier(llvm::StringRef s); Index: lld/test/COFF/undefined-symbol-itanium-i386.s =================================================================== --- lld/test/COFF/undefined-symbol-itanium-i386.s +++ lld/test/COFF/undefined-symbol-itanium-i386.s @@ -7,6 +7,7 @@ # NODEMANGLE: error: undefined symbol: __Z3fooi # NODEMANGLE: error: undefined symbol: __Z3barPKc # NODEMANGLE: error: undefined symbol: __imp___Z3bazv +# NODEMANGLE: error: undefined symbol: _Z3fooi # CHECK: error: undefined symbol: foo(int) # CHECK-NEXT: >>> referenced by {{.*}}.o:(_main) @@ -17,6 +18,9 @@ # CHECK-NEXT: >>> referenced by {{.*}}.o:(_f1) # CHECK-EMPTY: # CHECK-NEXT: error: undefined symbol: __declspec(dllimport) baz() +# CHECK-NEXT: >>> referenced by {{.*}}.o:(_f2) +# CHECK-EMPTY: +# CHECK-NEXT: error: undefined symbol: _Z3fooi # CHECK-NEXT: >>> referenced by {{.*}}.o:(_f2) .section .text,"xr",one_only,_main @@ -34,3 +38,4 @@ .globl _f2 _f2: call *__imp___Z3bazv + call _Z3fooi Index: lld/test/COFF/undefined-symbol-itanium.s =================================================================== --- lld/test/COFF/undefined-symbol-itanium.s +++ lld/test/COFF/undefined-symbol-itanium.s @@ -7,6 +7,7 @@ # NODEMANGLE: error: undefined symbol: _Z3fooi # NODEMANGLE: error: undefined symbol: _Z3barPKc # NODEMANGLE: error: undefined symbol: __imp__Z3bazv +# NODEMANGLE: error: undefined symbol: __Z3fooi # CHECK: error: undefined symbol: foo(int) # CHECK-NEXT: >>> referenced by {{.*}}.o:(main) @@ -17,6 +18,9 @@ # CHECK-NEXT: >>> referenced by {{.*}}.o:(f1) # CHECK-EMPTY: # CHECK-NEXT: error: undefined symbol: __declspec(dllimport) baz() +# CHECK-NEXT: >>> referenced by {{.*}}.o:(f2) +# CHECK-EMPTY: +# CHECK-NEXT: error: undefined symbol: __Z3fooi # CHECK-NEXT: >>> referenced by {{.*}}.o:(f2) .section .text,"xr",one_only,main @@ -34,3 +38,4 @@ .globl f2 f2: callq *__imp__Z3bazv(%rip) + callq __Z3fooi Index: lld/test/COFF/undefined-symbol.s =================================================================== --- lld/test/COFF/undefined-symbol.s +++ lld/test/COFF/undefined-symbol.s @@ -7,6 +7,7 @@ # NODEMANGLE: error: undefined symbol: ?foo@@YAHXZ # NODEMANGLE: error: undefined symbol: ?bar@@YAHXZ # NODEMANGLE: error: undefined symbol: __imp_?baz@@YAHXZ +# NODEMANGLE: error: undefined symbol: __imp_undecorated # CHECK: error: undefined symbol: int __cdecl foo(void) # CHECK-NEXT: >>> referenced by {{.*}}.obj:(main) @@ -17,6 +18,9 @@ # CHECK-NEXT: >>> referenced by {{.*}}.obj:(f1) # CHECK-EMPTY: # CHECK-NEXT: error: undefined symbol: __declspec(dllimport) int __cdecl baz(void) +# CHECK-NEXT: >>> referenced by {{.*}}.obj:(f2) +# CHECK-EMPTY: +# CHECK-NEXT: error: undefined symbol: __imp_undecorated # CHECK-NEXT: >>> referenced by {{.*}}.obj:(f2) .section .text,"xr",one_only,main @@ -34,3 +38,4 @@ .globl f2 f2: callq *"__imp_?baz@@YAHXZ"(%rip) + callq *__imp_undecorated(%rip) Index: lld/test/ELF/undef.s =================================================================== --- lld/test/ELF/undef.s +++ lld/test/ELF/undef.s @@ -23,6 +23,10 @@ # CHECK: error: undefined symbol: vtable for Foo # CHECK: the vtable symbol may be undefined because the class is missing its key function (see https://lld.llvm.org/missingkeyfunction) +# CHECK: error: undefined symbol: __Z3fooi +# CHECK: >>> referenced by undef.s +# CHECK: >>> {{.*}}:(.text+0x1A) + # CHECK: error: undefined symbol: zed2 # CHECK: >>> referenced by {{.*}}.o:(.text+0x0) in archive {{.*}}2.a @@ -64,3 +68,4 @@ call zed1 call _Z3fooi call _ZTV3Foo + call __Z3fooi Index: lld/wasm/Symbols.h =================================================================== --- lld/wasm/Symbols.h +++ lld/wasm/Symbols.h @@ -542,7 +542,6 @@ // Returns a symbol name for an error message. std::string toString(const wasm::Symbol &sym); std::string toString(wasm::Symbol::Kind kind); -std::string maybeDemangleSymbol(StringRef name); } // namespace lld Index: lld/wasm/Symbols.cpp =================================================================== --- lld/wasm/Symbols.cpp +++ lld/wasm/Symbols.cpp @@ -16,6 +16,7 @@ #include "OutputSegment.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Strings.h" +#include "llvm/Demangle/Demangle.h" #define DEBUG_TYPE "lld" @@ -299,14 +300,7 @@ void LazySymbol::fetch() { cast(file)->addMember(&archiveSymbol); } std::string lld::toString(const wasm::Symbol &sym) { - return lld::maybeDemangleSymbol(sym.getName()); -} - -std::string lld::maybeDemangleSymbol(StringRef name) { - if (config->demangle) - if (Optional s = demangleItanium(name)) - return *s; - return name; + return demangle(sym.getName(), /* StrictPrefix */ true); } std::string lld::toString(wasm::Symbol::Kind kind) { @@ -335,7 +329,6 @@ llvm_unreachable("invalid symbol kind"); } - void lld::wasm::printTraceSymbolUndefined(StringRef name, const InputFile* file) { message(toString(file) + ": reference to " + name); } Index: lld/wasm/SyntheticSections.cpp =================================================================== --- lld/wasm/SyntheticSections.cpp +++ lld/wasm/SyntheticSections.cpp @@ -17,6 +17,7 @@ #include "InputGlobal.h" #include "OutputSegment.h" #include "SymbolTable.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/Support/Path.h" using namespace llvm; @@ -524,7 +525,8 @@ if (!f->getDebugName().empty()) { writeStr(sub.os, f->getDebugName(), "symbol name"); } else { - writeStr(sub.os, maybeDemangleSymbol(f->getName()), "symbol name"); + writeStr(sub.os, demangle(f->getName(), /* StrictPrefix */ true), + "symbol name"); } } } Index: llvm/include/llvm/Demangle/Demangle.h =================================================================== --- llvm/include/llvm/Demangle/Demangle.h +++ llvm/include/llvm/Demangle/Demangle.h @@ -9,6 +9,7 @@ #ifndef LLVM_DEMANGLE_DEMANGLE_H #define LLVM_DEMANGLE_DEMANGLE_H +#include "llvm/ADT/Optional.h" #include #include @@ -39,9 +40,20 @@ /// Attempt to demangle a string using different demangling schemes. /// The function uses heuristics to determine which demangling scheme to use. /// \param MangledName - reference to string to demangle. +/// \param StrictPrefix - whether itanium demangling requires exactly one +/// leading underscore. /// \returns - the demangled string, or a copy of the input string if no /// demangling occurred. -std::string demangle(const std::string &MangledName); +std::string demangle(const std::string &MangledName, bool StrictPrefix = false); + +/// Attempt to demangle a string using different demangling schemes. +/// The function uses heuristics to determine which demangling scheme to use. +/// \param MangledName - reference to string to demangle. +/// \param StrictPrefix - whether itanium demangling requires exactly one +/// leading underscore. +/// \returns - an optional demangled string. +Optional tryDemangle(const std::string &MangledName, + bool StrictPrefix = false); /// "Partial" demangler. This supports demangling a string into an AST /// (typically an intermediate stage in itaniumDemangle) and querying certain Index: llvm/lib/Demangle/Demangle.cpp =================================================================== --- llvm/lib/Demangle/Demangle.cpp +++ llvm/lib/Demangle/Demangle.cpp @@ -13,24 +13,33 @@ #include "llvm/Demangle/Demangle.h" #include -static bool isItaniumEncoding(const std::string &MangledName) { +static bool isItaniumEncoding(const std::string &MangledName, + bool StrictPrefix) { size_t Pos = MangledName.find_first_not_of('_'); // A valid Itanium encoding requires 1-4 leading underscores, followed by 'Z'. - return Pos > 0 && Pos <= 4 && MangledName[Pos] == 'Z'; + return Pos > 0 && Pos <= (StrictPrefix ? 1 : 4) && MangledName[Pos] == 'Z'; } -std::string llvm::demangle(const std::string &MangledName) { +llvm::Optional llvm::tryDemangle(const std::string &MangledName, + bool StrictPrefix) { char *Demangled; - if (isItaniumEncoding(MangledName)) + if (isItaniumEncoding(MangledName, StrictPrefix)) Demangled = itaniumDemangle(MangledName.c_str(), nullptr, nullptr, nullptr); else Demangled = microsoftDemangle(MangledName.c_str(), nullptr, nullptr, nullptr); if (!Demangled) - return MangledName; + return None; std::string Ret = Demangled; free(Demangled); return Ret; } + +std::string llvm::demangle(const std::string &MangledName, bool StrictPrefix) { + llvm::Optional Ret = tryDemangle(MangledName, StrictPrefix); + if (!Ret) + return MangledName; + return *Ret; +}