Index: libcxxabi/src/cxa_demangle.cpp =================================================================== --- libcxxabi/src/cxa_demangle.cpp +++ libcxxabi/src/cxa_demangle.cpp @@ -312,21 +312,6 @@ return Alloc.allocate(sizeof(Node *) * sz); } }; - -bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S, - size_t InitSize) { - size_t BufferSize; - if (Buf == nullptr) { - Buf = static_cast(std::malloc(InitSize)); - if (Buf == nullptr) - return true; - BufferSize = InitSize; - } else - BufferSize = *N; - - S.reset(Buf, BufferSize); - return false; -} } // unnamed namespace //===----------------------------------------------------------------------===// Index: libcxxabi/src/demangle/Utility.h =================================================================== --- libcxxabi/src/demangle/Utility.h +++ libcxxabi/src/demangle/Utility.h @@ -71,22 +71,6 @@ BufferCapacity = BufferCapacity_; } - /// Create an OutputStream from a buffer and a size. If either of these are - /// null a buffer is allocated. - static OutputStream create(char *StartBuf, size_t *Size, size_t AllocSize) { - OutputStream Result; - - if (!StartBuf || !Size) { - StartBuf = static_cast(std::malloc(AllocSize)); - if (StartBuf == nullptr) - std::terminate(); - Size = &AllocSize; - } - - Result.reset(StartBuf, *Size); - return Result; - } - /// If a ParameterPackExpansion (or similar type) is encountered, the offset /// into the pack that we're currently printing. unsigned CurrentPackIndex = std::numeric_limits::max(); @@ -186,6 +170,21 @@ SwapAndRestore &operator=(const SwapAndRestore &) = delete; }; +inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S, + size_t InitSize) { + size_t BufferSize; + if (Buf == nullptr) { + Buf = static_cast(std::malloc(InitSize)); + if (Buf == nullptr) + return true; + BufferSize = InitSize; + } else + BufferSize = *N; + + S.reset(Buf, BufferSize); + return false; +} + } // namespace #endif Index: lld/COFF/SymbolTable.cpp =================================================================== --- lld/COFF/SymbolTable.cpp +++ lld/COFF/SymbolTable.cpp @@ -66,10 +66,10 @@ error(S); } -// Returns the name of the symbol in SC whose value is <= Addr that is closest -// to Addr. This is generally the name of the global variable or function whose -// definition contains Addr. -static StringRef getSymbolName(SectionChunk *SC, uint32_t Addr) { +// Returns the symbol in SC whose value is <= Addr that is closest to Addr. +// This is generally the global variable or function whose definition contains +// Addr. +static Symbol *getSymbol(SectionChunk *SC, uint32_t Addr) { DefinedRegular *Candidate = nullptr; for (Symbol *S : SC->File->getSymbols()) { @@ -81,14 +81,12 @@ Candidate = D; } - if (!Candidate) - return ""; - return Candidate->getName(); + return Candidate; } static std::string getSymbolLocations(ObjFile *File, uint32_t SymIndex) { struct Location { - StringRef SymName; + Symbol *Sym; std::pair FileLine; }; std::vector Locations; @@ -102,9 +100,9 @@ continue; std::pair FileLine = getFileLine(SC, R.VirtualAddress); - StringRef SymName = getSymbolName(SC, R.VirtualAddress); - if (!FileLine.first.empty() || !SymName.empty()) - Locations.push_back({SymName, FileLine}); + Symbol *Sym = getSymbol(SC, R.VirtualAddress); + if (!FileLine.first.empty() || Sym) + Locations.push_back({Sym, FileLine}); } } @@ -119,8 +117,8 @@ OS << Loc.FileLine.first << ":" << Loc.FileLine.second << "\n>>> "; OS << toString(File); - if (!Loc.SymName.empty()) - OS << ":(" << Loc.SymName << ')'; + if (Loc.Sym) + OS << ":(" << toString(*Loc.Sym) << ')'; } return OS.str(); } @@ -247,10 +245,10 @@ for (Symbol *B : Config->GCRoot) { if (Undefs.count(B)) - errorOrWarn(": undefined symbol: " + B->getName()); + errorOrWarn(": undefined symbol: " + toString(*B)); if (Config->WarnLocallyDefinedImported) if (Symbol *Imp = LocalImports.lookup(B)) - warn(": locally defined symbol imported: " + Imp->getName() + + warn(": locally defined symbol imported: " + toString(*Imp) + " (defined in " + toString(Imp->getFile()) + ") [LNK4217]"); } @@ -261,13 +259,13 @@ if (!Sym) continue; if (Undefs.count(Sym)) - errorOrWarn("undefined symbol: " + Sym->getName() + + errorOrWarn("undefined symbol: " + toString(*Sym) + getSymbolLocations(File, SymIndex)); if (Config->WarnLocallyDefinedImported) if (Symbol *Imp = LocalImports.lookup(Sym)) - warn(toString(File) + ": locally defined symbol imported: " + - Imp->getName() + " (defined in " + toString(Imp->getFile()) + - ") [LNK4217]"); + warn(toString(File) + + ": locally defined symbol imported: " + toString(*Imp) + + " (defined in " + toString(Imp->getFile()) + ") [LNK4217]"); } } } Index: lld/Common/Strings.cpp =================================================================== --- lld/Common/Strings.cpp +++ lld/Common/Strings.cpp @@ -16,14 +16,6 @@ #include #include -#if defined(_MSC_VER) -#include - -// DbgHelp.h must be included after Windows.h. -#include -#pragma comment(lib, "dbghelp.lib") -#endif - using namespace llvm; using namespace lld; @@ -45,18 +37,15 @@ return S; } -Optional lld::demangleMSVC(StringRef S) { -#if defined(_MSC_VER) - // UnDecorateSymbolName is not thread-safe, so we need a mutex. - static std::mutex Mu; - std::lock_guard Lock(Mu); - - char Buf[4096]; - if (S.startswith("?")) - if (size_t Len = UnDecorateSymbolName(S.str().c_str(), Buf, sizeof(Buf), 0)) - return std::string(Buf, Len); -#endif - return None; +Optional lld::demangleMSVC(StringRef Name) { + 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 S; } StringMatcher::StringMatcher(ArrayRef Pat) { Index: lld/test/COFF/undefined-symbol-cv.s =================================================================== --- lld/test/COFF/undefined-symbol-cv.s +++ lld/test/COFF/undefined-symbol-cv.s @@ -2,19 +2,19 @@ # RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s # RUN: not lld-link /out:%t.exe %t.obj 2>&1 | FileCheck %s -# CHECK: error: undefined symbol: ?foo@@YAHXZ +# CHECK: error: undefined symbol: "int __cdecl foo(void)" (?foo@@YAHXZ) # CHECK-NEXT: >>> referenced by file1.cpp:1 # CHECK-NEXT: >>> {{.*}}.obj:(main) # CHECK-NEXT: >>> referenced by file1.cpp:2 # CHECK-NEXT: >>> {{.*}}.obj:(main) # CHECK-EMPTY: -# CHECK-NEXT: error: undefined symbol: ?bar@@YAHXZ +# CHECK-NEXT: error: undefined symbol: "int __cdecl bar(void)" (?bar@@YAHXZ) # CHECK-NEXT: >>> referenced by file2.cpp:3 # CHECK-NEXT: >>> {{.*}}.obj:(main) # CHECK-NEXT: >>> referenced by file1.cpp:4 # CHECK-NEXT: >>> {{.*}}.obj:(f1) # CHECK-EMPTY: -# CHECK-NEXT: error: undefined symbol: ?baz@@YAHXZ +# CHECK-NEXT: error: undefined symbol: "int __cdecl baz(void)" (?baz@@YAHXZ) # CHECK-NEXT: >>> referenced by file1.cpp:5 # CHECK-NEXT: >>> {{.*}}.obj:(f2) Index: lld/test/COFF/undefined-symbol.s =================================================================== --- lld/test/COFF/undefined-symbol.s +++ lld/test/COFF/undefined-symbol.s @@ -2,15 +2,15 @@ # RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s # RUN: not lld-link /out:%t.exe %t.obj 2>&1 | FileCheck %s -# CHECK: error: undefined symbol: ?foo@@YAHXZ +# CHECK: error: undefined symbol: "int __cdecl foo(void)" (?foo@@YAHXZ) # CHECK-NEXT: >>> referenced by {{.*}}.obj:(main) # CHECK-NEXT: >>> referenced by {{.*}}.obj:(main) # CHECK-EMPTY: -# CHECK-NEXT: error: undefined symbol: ?bar@@YAHXZ +# CHECK-NEXT: error: undefined symbol: "int __cdecl bar(void)" (?bar@@YAHXZ) # CHECK-NEXT: >>> referenced by {{.*}}.obj:(main) # CHECK-NEXT: >>> referenced by {{.*}}.obj:(f1) # CHECK-EMPTY: -# CHECK-NEXT: error: undefined symbol: ?baz@@YAHXZ +# CHECK-NEXT: error: undefined symbol: "int __cdecl baz(void)" (?baz@@YAHXZ) # CHECK-NEXT: >>> referenced by {{.*}}.obj:(f2) .section .text,"xr",one_only,main Index: llvm/include/llvm/Demangle/Utility.h =================================================================== --- llvm/include/llvm/Demangle/Utility.h +++ llvm/include/llvm/Demangle/Utility.h @@ -70,22 +70,6 @@ BufferCapacity = BufferCapacity_; } - /// Create an OutputStream from a buffer and a size. If either of these are - /// null a buffer is allocated. - static OutputStream create(char *StartBuf, size_t *Size, size_t AllocSize) { - OutputStream Result; - - if (!StartBuf || !Size) { - StartBuf = static_cast(std::malloc(AllocSize)); - if (StartBuf == nullptr) - std::terminate(); - Size = &AllocSize; - } - - Result.reset(StartBuf, *Size); - return Result; - } - /// If a ParameterPackExpansion (or similar type) is encountered, the offset /// into the pack that we're currently printing. unsigned CurrentPackIndex = std::numeric_limits::max(); @@ -185,4 +169,19 @@ SwapAndRestore &operator=(const SwapAndRestore &) = delete; }; +inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S, + size_t InitSize) { + size_t BufferSize; + if (Buf == nullptr) { + Buf = static_cast(std::malloc(InitSize)); + if (Buf == nullptr) + return true; + BufferSize = InitSize; + } else + BufferSize = *N; + + S.reset(Buf, BufferSize); + return false; +} + #endif Index: llvm/lib/Demangle/ItaniumDemangle.cpp =================================================================== --- llvm/lib/Demangle/ItaniumDemangle.cpp +++ llvm/lib/Demangle/ItaniumDemangle.cpp @@ -310,21 +310,6 @@ return Alloc.allocate(sizeof(Node *) * sz); } }; - -bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S, - size_t InitSize) { - size_t BufferSize; - if (Buf == nullptr) { - Buf = static_cast(std::malloc(InitSize)); - if (Buf == nullptr) - return true; - BufferSize = InitSize; - } else - BufferSize = *N; - - S.reset(Buf, BufferSize); - return false; -} } // unnamed namespace //===----------------------------------------------------------------------===// Index: llvm/lib/Demangle/MicrosoftDemangle.cpp =================================================================== --- llvm/lib/Demangle/MicrosoftDemangle.cpp +++ llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -1016,7 +1016,10 @@ void Demangler::memorizeIdentifier(IdentifierNode *Identifier) { // Render this class template name into a string buffer so that we can // memorize it for the purpose of back-referencing. - OutputStream OS = OutputStream::create(nullptr, nullptr, 1024); + OutputStream OS; + if (initializeOutputStream(nullptr, nullptr, OS, 1024)) + // FIXME: Propagate out-of-memory as an error? + std::terminate(); Identifier->output(OS, OF_Default); OS << '\0'; char *Name = OS.getBuffer(); @@ -1346,7 +1349,9 @@ if (MangledName.empty()) goto StringLiteralError; - OS = OutputStream::create(nullptr, nullptr, 1024); + if (initializeOutputStream(nullptr, nullptr, OS, 1024)) + // FIXME: Propagate out-of-memory as an error? + std::terminate(); if (IsWcharT) { Result->Char = CharKind::Wchar; if (StringByteSize > 64) @@ -1466,7 +1471,10 @@ return nullptr; // Render the parent symbol's name into a buffer. - OutputStream OS = OutputStream::create(nullptr, nullptr, 1024); + OutputStream OS; + if (initializeOutputStream(nullptr, nullptr, OS, 1024)) + // FIXME: Propagate out-of-memory as an error? + std::terminate(); OS << '`'; Scope->output(OS, OF_Default); OS << '\''; @@ -2289,7 +2297,9 @@ (int)Backrefs.FunctionParamCount); // Create an output stream so we can render each type. - OutputStream OS = OutputStream::create(nullptr, 0, 1024); + OutputStream OS; + if (initializeOutputStream(nullptr, nullptr, OS, 1024)) + std::terminate(); for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) { OS.setCurrentPosition(0); @@ -2314,21 +2324,29 @@ char *llvm::microsoftDemangle(const char *MangledName, char *Buf, size_t *N, int *Status, MSDemangleFlags Flags) { + int InternalStatus = demangle_success; Demangler D; + OutputStream S; + StringView Name{MangledName}; - SymbolNode *S = D.parse(Name); + SymbolNode *AST = D.parse(Name); if (Flags & MSDF_DumpBackrefs) D.dumpBackReferences(); - OutputStream OS = OutputStream::create(Buf, N, 1024); - if (D.Error) { - OS << MangledName; - *Status = llvm::demangle_invalid_mangled_name; - } else { - S->output(OS, OF_Default); - *Status = llvm::demangle_success; + + if (D.Error) + InternalStatus = demangle_invalid_mangled_name; + else if (initializeOutputStream(Buf, N, S, 1024)) + InternalStatus = demangle_memory_alloc_failure; + else { + AST->output(S, OF_Default); + S += '\0'; + if (N != nullptr) + *N = S.getCurrentPosition(); + Buf = S.getBuffer(); } - OS << '\0'; - return OS.getBuffer(); + if (Status) + *Status = InternalStatus; + return InternalStatus == demangle_success ? Buf : nullptr; }