diff options
| author | Zachary Turner <zturner@google.com> | 2015-05-06 22:26:30 +0000 |
|---|---|---|
| committer | Zachary Turner <zturner@google.com> | 2015-05-06 22:26:30 +0000 |
| commit | c007aa41b6dac766af69998a4a161eabc9ca1ccf (patch) | |
| tree | 1d4ea78e5f3dcf3c383d8a7cb5a9e13accba17fb | |
| parent | 566bc5aa8a107712e7a6d85da200df8d69ea61a0 (diff) | |
| download | bcm5719-llvm-c007aa41b6dac766af69998a4a161eabc9ca1ccf.tar.gz bcm5719-llvm-c007aa41b6dac766af69998a4a161eabc9ca1ccf.zip | |
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.
llvm-svn: 236653
| -rw-r--r-- | llvm/include/llvm/DebugInfo/PDB/PDBContext.h | 4 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/PDBContext.cpp | 70 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.c | 8 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.cpp | 18 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.exe | bin | 165888 -> 165888 bytes | |||
| -rw-r--r-- | llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.exe.input | 3 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.pdb | bin | 1552384 -> 1552384 bytes | |||
| -rw-r--r-- | llvm/test/tools/llvm-symbolizer/pdb/pdb.test | 22 | ||||
| -rw-r--r-- | llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp | 23 | ||||
| -rw-r--r-- | llvm/tools/llvm-symbolizer/LLVMSymbolize.h | 15 | ||||
| -rw-r--r-- | llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp | 14 |
11 files changed, 127 insertions, 50 deletions
diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBContext.h b/llvm/include/llvm/DebugInfo/PDB/PDBContext.h index 88a11c13caa..2bb97463f90 100644 --- a/llvm/include/llvm/DebugInfo/PDB/PDBContext.h +++ b/llvm/include/llvm/DebugInfo/PDB/PDBContext.h @@ -32,7 +32,8 @@ class PDBContext : public DIContext { public: PDBContext(const object::COFFObjectFile &Object, - std::unique_ptr<IPDBSession> PDBSession); + std::unique_ptr<IPDBSession> 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<IPDBSession> Session; }; } diff --git a/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/llvm/lib/DebugInfo/PDB/PDBContext.cpp index 328bcc65ea9..83f27c7fa3d 100644 --- a/llvm/lib/DebugInfo/PDB/PDBContext.cpp +++ b/llvm/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<IPDBSession> PDBSession) + std::unique_ptr<IPDBSession> 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<uint64_t>(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<uint64_t>(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<PDBSymbol> Symbol = + Session->findSymbolByAddress(Address, PDB_SymType::None); if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(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<PDBSymbolData>(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<PDBSymbolPublicSymbol>(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<PDBSymbolFunc>(FuncSymbol.get())) + return Func->getName(); + + return std::string(); +} diff --git a/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.c b/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.c deleted file mode 100644 index 8dd0d38704b..00000000000 --- a/llvm/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/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.cpp b/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.cpp new file mode 100644 index 00000000000..f1f98af4190 --- /dev/null +++ b/llvm/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/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.exe b/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.exe Binary files differindex 556b78c0b09..80fb34bb6dc 100644 --- a/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.exe +++ b/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.exe diff --git a/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.exe.input b/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.exe.input index 26c9beabf5f..affda60449b 100644 --- a/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.exe.input +++ b/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.exe.input @@ -1,3 +1,4 @@ -0x401020 0x401030 +0x401040 +0x401060 0x500000 diff --git a/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.pdb b/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.pdb Binary files differindex c539a3515c4..974e565e87f 100644 --- a/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.pdb +++ b/llvm/test/tools/llvm-symbolizer/pdb/Inputs/test.pdb diff --git a/llvm/test/tools/llvm-symbolizer/pdb/pdb.test b/llvm/test/tools/llvm-symbolizer/pdb/pdb.test index a8d7439e01e..b5d0f15fbcb 100644 --- a/llvm/test/tools/llvm-symbolizer/pdb/pdb.test +++ b/llvm/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/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp b/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp index 326cab5a186..afb7cc81c82 100644 --- a/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp +++ b/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -29,6 +29,11 @@ #include <sstream> #include <stdlib.h> +#if defined(_MSC_VER) +#include <Windows.h> +#include <DbgHelp.h> +#endif + namespace llvm { namespace symbolize { @@ -471,8 +476,10 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { std::unique_ptr<IPDBSession> 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/llvm/tools/llvm-symbolizer/LLVMSymbolize.h b/llvm/tools/llvm-symbolizer/LLVMSymbolize.h index ff848fceb24..1c2006fbbe7 100644 --- a/llvm/tools/llvm-symbolizer/LLVMSymbolize.h +++ b/llvm/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<std::string> 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/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp index 7a77a4476e3..9c9f3adbf60 100644 --- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -49,8 +49,13 @@ static cl::opt<FunctionNameKind> ClPrintFunctions( clEnumValEnd)); static cl::opt<bool> -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<bool> + ClPrintInlining("inlining", cl::init(true), + cl::desc("Print all inlined frames for a given address")); static cl::opt<bool> 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); |

