From: Zachary Turner Date: Wed, 6 May 2015 22:26:30 +0000 (+0000) Subject: A few fixes for llvm-symbolizer on Windows. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=43afa429082f1a90e2ca22d73456c2219ec8d774;p=oota-llvm.git A few fixes for llvm-symbolizer on Windows. Specifically, this patch correctly respects the -demangle option, and additionally adds a hidden --relative-address option allows input addresses to be relative to the module load address instead of absolute addresses into the image. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236653 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/DebugInfo/PDB/PDBContext.h b/include/llvm/DebugInfo/PDB/PDBContext.h index 88a11c13caa..2bb97463f90 100644 --- a/include/llvm/DebugInfo/PDB/PDBContext.h +++ b/include/llvm/DebugInfo/PDB/PDBContext.h @@ -32,7 +32,8 @@ class PDBContext : public DIContext { public: PDBContext(const object::COFFObjectFile &Object, - std::unique_ptr PDBSession); + std::unique_ptr PDBSession, + bool RelativeAddress); static bool classof(const DIContext *DICtx) { return DICtx->getKind() == CK_PDB; @@ -51,6 +52,7 @@ public: DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; private: + std::string getFunctionName(uint64_t Address, DINameKind NameKind) const; std::unique_ptr Session; }; } diff --git a/lib/DebugInfo/PDB/PDBContext.cpp b/lib/DebugInfo/PDB/PDBContext.cpp index 328bcc65ea9..83f27c7fa3d 100644 --- a/lib/DebugInfo/PDB/PDBContext.cpp +++ b/lib/DebugInfo/PDB/PDBContext.cpp @@ -14,43 +14,44 @@ #include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" #include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" #include "llvm/Object/COFF.h" using namespace llvm; using namespace llvm::object; PDBContext::PDBContext(const COFFObjectFile &Object, - std::unique_ptr PDBSession) + std::unique_ptr PDBSession, + bool RelativeAddress) : DIContext(CK_PDB), Session(std::move(PDBSession)) { - uint64_t ImageBase = 0; - if (Object.is64()) { - const pe32plus_header *Header = nullptr; - Object.getPE32PlusHeader(Header); - if (Header) - ImageBase = Header->ImageBase; - } else { - const pe32_header *Header = nullptr; - Object.getPE32Header(Header); - if (Header) - ImageBase = static_cast(Header->ImageBase); + if (!RelativeAddress) { + uint64_t ImageBase = 0; + if (Object.is64()) { + const pe32plus_header *Header = nullptr; + Object.getPE32PlusHeader(Header); + if (Header) + ImageBase = Header->ImageBase; + } else { + const pe32_header *Header = nullptr; + Object.getPE32Header(Header); + if (Header) + ImageBase = static_cast(Header->ImageBase); + } + Session->setLoadAddress(ImageBase); } - Session->setLoadAddress(ImageBase); } void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType) {} DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier) { - auto Symbol = Session->findSymbolByAddress(Address, PDB_SymType::None); + DILineInfo Result; + Result.FunctionName = getFunctionName(Address, Specifier.FNKind); uint32_t Length = 1; - DILineInfo Result; + std::unique_ptr Symbol = + Session->findSymbolByAddress(Address, PDB_SymType::None); if (auto Func = dyn_cast_or_null(Symbol.get())) { - if (Specifier.FNKind == DINameKind::LinkageName) - Result.FunctionName = Func->getUndecoratedName(); - else if (Specifier.FNKind == DINameKind::ShortName) - Result.FunctionName = Func->getName(); - Length = Func->getLength(); } else if (auto Data = dyn_cast_or_null(Symbol.get())) { Length = Data->getLength(); @@ -101,3 +102,32 @@ PDBContext::getInliningInfoForAddress(uint64_t Address, InlineInfo.addFrame(Frame); return InlineInfo; } + +std::string PDBContext::getFunctionName(uint64_t Address, + DINameKind NameKind) const { + if (NameKind == DINameKind::None) + return std::string(); + + if (NameKind == DINameKind::LinkageName) { + // It is not possible to get the mangled linkage name through a + // PDBSymbolFunc. For that we have to specifically request a + // PDBSymbolPublicSymbol. + auto PublicSym = + Session->findSymbolByAddress(Address, PDB_SymType::PublicSymbol); + if (auto PS = dyn_cast_or_null(PublicSym.get())) + return PS->getName(); + } + + auto FuncSymbol = + Session->findSymbolByAddress(Address, PDB_SymType::Function); + + // This could happen either if there was no public symbol (e.g. not + // external) or the user requested the short name. In the former case, + // although they technically requested the linkage name, if the linkage + // name is not available we fallback to at least returning a non-empty + // string. + if (auto Func = dyn_cast_or_null(FuncSymbol.get())) + return Func->getName(); + + return std::string(); +} diff --git a/test/tools/llvm-symbolizer/pdb/Inputs/test.c b/test/tools/llvm-symbolizer/pdb/Inputs/test.c deleted file mode 100644 index 8dd0d38704b..00000000000 --- a/test/tools/llvm-symbolizer/pdb/Inputs/test.c +++ /dev/null @@ -1,8 +0,0 @@ -// To generate the corresponding EXE/PDB, run: -// cl /Zi test.c -void foo() { -} - -int main() { - foo(); -} diff --git a/test/tools/llvm-symbolizer/pdb/Inputs/test.cpp b/test/tools/llvm-symbolizer/pdb/Inputs/test.cpp new file mode 100644 index 00000000000..f1f98af4190 --- /dev/null +++ b/test/tools/llvm-symbolizer/pdb/Inputs/test.cpp @@ -0,0 +1,18 @@ +// To generate the corresponding EXE/PDB, run: +// cl /Zi test.cpp + +namespace NS { +struct Foo { + void bar() {} +}; +} + +void foo() { +} + +int main() { + foo(); + + NS::Foo f; + f.bar(); +} diff --git a/test/tools/llvm-symbolizer/pdb/Inputs/test.exe b/test/tools/llvm-symbolizer/pdb/Inputs/test.exe index 556b78c0b09..80fb34bb6dc 100644 Binary files a/test/tools/llvm-symbolizer/pdb/Inputs/test.exe and b/test/tools/llvm-symbolizer/pdb/Inputs/test.exe differ diff --git a/test/tools/llvm-symbolizer/pdb/Inputs/test.exe.input b/test/tools/llvm-symbolizer/pdb/Inputs/test.exe.input index 26c9beabf5f..affda60449b 100644 --- a/test/tools/llvm-symbolizer/pdb/Inputs/test.exe.input +++ b/test/tools/llvm-symbolizer/pdb/Inputs/test.exe.input @@ -1,3 +1,4 @@ -0x401020 0x401030 +0x401040 +0x401060 0x500000 diff --git a/test/tools/llvm-symbolizer/pdb/Inputs/test.pdb b/test/tools/llvm-symbolizer/pdb/Inputs/test.pdb index c539a3515c4..974e565e87f 100644 Binary files a/test/tools/llvm-symbolizer/pdb/Inputs/test.pdb and b/test/tools/llvm-symbolizer/pdb/Inputs/test.pdb differ diff --git a/test/tools/llvm-symbolizer/pdb/pdb.test b/test/tools/llvm-symbolizer/pdb/pdb.test index a8d7439e01e..b5d0f15fbcb 100644 --- a/test/tools/llvm-symbolizer/pdb/pdb.test +++ b/test/tools/llvm-symbolizer/pdb/pdb.test @@ -1,8 +1,18 @@ -RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" < "%p/Inputs/test.exe.input" | FileCheck %s --check-prefix=CHECK +RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" < "%p/Inputs/test.exe.input" | \ +RUN: FileCheck %s --check-prefix=CHECK +RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" -demangle=false < \ +RUN: "%p/Inputs/test.exe.input" | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE -CHECK: _foo -CHECK-NEXT: test.c:3:0 +CHECK: foo(void) +CHECK-NEXT: test.cpp:10 CHECK: _main -CHECK-NEXT: test.c:6:0 -CHECK: ?? -CHECK-NEXT: ??:0:0 +CHECK-NEXT: test.cpp:13:0 +CHECK: NS::Foo::bar(void) +CHECK-NEXT: test.cpp:6:0 + +CHECK-NO-DEMANGLE: foo +CHECK-NO-DEMANGLE-NEXT: test.cpp:10 +CHECK-NO-DEMANGLE: _main +CHECK-LINKAGE-NAME-NEXT: test.cpp:13:0 +CHECK-NO-DEMANGLE: bar +CHECK-LINKAGE-NAME-NEXT: test.cpp:6:0 diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp index 326cab5a186..afb7cc81c82 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.cpp +++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -29,6 +29,11 @@ #include #include +#if defined(_MSC_VER) +#include +#include +#endif + namespace llvm { namespace symbolize { @@ -471,8 +476,10 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { std::unique_ptr Session; PDB_ErrorCode Error = loadDataForEXE(PDB_ReaderType::DIA, Objects.first->getFileName(), Session); - if (Error == PDB_ErrorCode::Success) - Context = new PDBContext(*CoffObject, std::move(Session)); + if (Error == PDB_ErrorCode::Success) { + Context = new PDBContext(*CoffObject, std::move(Session), + Opts.RelativeAddresses); + } } if (!Context) Context = new DWARFContextInMemory(*Objects.second); @@ -522,7 +529,17 @@ std::string LLVMSymbolizer::DemangleName(const std::string &Name) { free(DemangledName); return Result; #else - return Name; + char DemangledName[1024] = {0}; + DWORD result = ::UnDecorateSymbolName( + Name.c_str(), DemangledName, 1023, + UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected + UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc + UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications + UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers + UNDNAME_NO_MS_KEYWORDS | // Strip all MS extension keywords + UNDNAME_NO_FUNCTION_RETURNS); // Strip function return types + + return (result == 0) ? Name : std::string(DemangledName); #endif } diff --git a/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h index ff848fceb24..1c2006fbbe7 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.h +++ b/tools/llvm-symbolizer/LLVMSymbolize.h @@ -35,19 +35,20 @@ class ModuleInfo; class LLVMSymbolizer { public: struct Options { - bool UseSymbolTable : 1; FunctionNameKind PrintFunctions; + bool UseSymbolTable : 1; bool PrintInlining : 1; bool Demangle : 1; + bool RelativeAddresses : 1; std::string DefaultArch; std::vector DsymHints; - Options(bool UseSymbolTable = true, - FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName, - bool PrintInlining = true, bool Demangle = true, + Options(FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName, + bool UseSymbolTable = true, bool PrintInlining = true, + bool Demangle = true, bool RelativeAddresses = false, std::string DefaultArch = "") - : UseSymbolTable(UseSymbolTable), - PrintFunctions(PrintFunctions), PrintInlining(PrintInlining), - Demangle(Demangle), DefaultArch(DefaultArch) {} + : PrintFunctions(PrintFunctions), UseSymbolTable(UseSymbolTable), + PrintInlining(PrintInlining), Demangle(Demangle), + RelativeAddresses(RelativeAddresses), DefaultArch(DefaultArch) {} }; LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {} diff --git a/tools/llvm-symbolizer/llvm-symbolizer.cpp b/tools/llvm-symbolizer/llvm-symbolizer.cpp index 7a77a4476e3..9c9f3adbf60 100644 --- a/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -49,8 +49,13 @@ static cl::opt ClPrintFunctions( clEnumValEnd)); static cl::opt -ClPrintInlining("inlining", cl::init(true), - cl::desc("Print all inlined frames for a given address")); + ClUseRelativeAddress("relative-address", cl::init(false), + cl::desc("Interpret addresses as relative addresses"), + cl::ReallyHidden); + +static cl::opt + ClPrintInlining("inlining", cl::init(true), + cl::desc("Print all inlined frames for a given address")); static cl::opt ClDemangle("demangle", cl::init(true), cl::desc("Demangle function names")); @@ -127,8 +132,9 @@ int main(int argc, char **argv) { llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded); cl::ParseCommandLineOptions(argc, argv, "llvm-symbolizer\n"); - LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions, - ClPrintInlining, ClDemangle, ClDefaultArch); + LLVMSymbolizer::Options Opts(ClPrintFunctions, ClUseSymbolTable, + ClPrintInlining, ClDemangle, + ClUseRelativeAddress, ClDefaultArch); for (const auto &hint : ClDsymHint) { if (sys::path::extension(hint) == ".dSYM") { Opts.DsymHints.push_back(hint);