llvm.org GIT mirror llvm / 43afa42
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 Zachary Turner 4 years ago
11 changed file(s) with 127 addition(s) and 50 deletion(s). Raw diff Collapse all Expand all
3131
3232 public:
3333 PDBContext(const object::COFFObjectFile &Object,
34 std::unique_ptr PDBSession);
34 std::unique_ptr PDBSession,
35 bool RelativeAddress);
3536
3637 static bool classof(const DIContext *DICtx) {
3738 return DICtx->getKind() == CK_PDB;
5051 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
5152
5253 private:
54 std::string getFunctionName(uint64_t Address, DINameKind NameKind) const;
5355 std::unique_ptr Session;
5456 };
5557 }
1313 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
1414 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
1515 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
16 #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
1617 #include "llvm/Object/COFF.h"
1718
1819 using namespace llvm;
1920 using namespace llvm::object;
2021
2122 PDBContext::PDBContext(const COFFObjectFile &Object,
22 std::unique_ptr PDBSession)
23 std::unique_ptr PDBSession,
24 bool RelativeAddress)
2325 : DIContext(CK_PDB), Session(std::move(PDBSession)) {
24 uint64_t ImageBase = 0;
25 if (Object.is64()) {
26 const pe32plus_header *Header = nullptr;
27 Object.getPE32PlusHeader(Header);
28 if (Header)
29 ImageBase = Header->ImageBase;
30 } else {
31 const pe32_header *Header = nullptr;
32 Object.getPE32Header(Header);
33 if (Header)
34 ImageBase = static_cast(Header->ImageBase);
26 if (!RelativeAddress) {
27 uint64_t ImageBase = 0;
28 if (Object.is64()) {
29 const pe32plus_header *Header = nullptr;
30 Object.getPE32PlusHeader(Header);
31 if (Header)
32 ImageBase = Header->ImageBase;
33 } else {
34 const pe32_header *Header = nullptr;
35 Object.getPE32Header(Header);
36 if (Header)
37 ImageBase = static_cast(Header->ImageBase);
38 }
39 Session->setLoadAddress(ImageBase);
3540 }
36 Session->setLoadAddress(ImageBase);
3741 }
3842
3943 void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType) {}
4044
4145 DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
4246 DILineInfoSpecifier Specifier) {
43 auto Symbol = Session->findSymbolByAddress(Address, PDB_SymType::None);
47 DILineInfo Result;
48 Result.FunctionName = getFunctionName(Address, Specifier.FNKind);
4449
4550 uint32_t Length = 1;
46 DILineInfo Result;
51 std::unique_ptr Symbol =
52 Session->findSymbolByAddress(Address, PDB_SymType::None);
4753 if (auto Func = dyn_cast_or_null(Symbol.get())) {
48 if (Specifier.FNKind == DINameKind::LinkageName)
49 Result.FunctionName = Func->getUndecoratedName();
50 else if (Specifier.FNKind == DINameKind::ShortName)
51 Result.FunctionName = Func->getName();
52
5354 Length = Func->getLength();
5455 } else if (auto Data = dyn_cast_or_null(Symbol.get())) {
5556 Length = Data->getLength();
100101 InlineInfo.addFrame(Frame);
101102 return InlineInfo;
102103 }
104
105 std::string PDBContext::getFunctionName(uint64_t Address,
106 DINameKind NameKind) const {
107 if (NameKind == DINameKind::None)
108 return std::string();
109
110 if (NameKind == DINameKind::LinkageName) {
111 // It is not possible to get the mangled linkage name through a
112 // PDBSymbolFunc. For that we have to specifically request a
113 // PDBSymbolPublicSymbol.
114 auto PublicSym =
115 Session->findSymbolByAddress(Address, PDB_SymType::PublicSymbol);
116 if (auto PS = dyn_cast_or_null(PublicSym.get()))
117 return PS->getName();
118 }
119
120 auto FuncSymbol =
121 Session->findSymbolByAddress(Address, PDB_SymType::Function);
122
123 // This could happen either if there was no public symbol (e.g. not
124 // external) or the user requested the short name. In the former case,
125 // although they technically requested the linkage name, if the linkage
126 // name is not available we fallback to at least returning a non-empty
127 // string.
128 if (auto Func = dyn_cast_or_null(FuncSymbol.get()))
129 return Func->getName();
130
131 return std::string();
132 }
+0
-8
test/tools/llvm-symbolizer/pdb/Inputs/test.c less more
None // To generate the corresponding EXE/PDB, run:
1 // cl /Zi test.c
2 void foo() {
3 }
4
5 int main() {
6 foo();
7 }
0 // To generate the corresponding EXE/PDB, run:
1 // cl /Zi test.cpp
2
3 namespace NS {
4 struct Foo {
5 void bar() {}
6 };
7 }
8
9 void foo() {
10 }
11
12 int main() {
13 foo();
14
15 NS::Foo f;
16 f.bar();
17 }
None 0x401020
1 0x401030
1 0x401040
2 0x401060
23 0x500000
None RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" < "%p/Inputs/test.exe.input" | FileCheck %s --check-prefix=CHECK
0 RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" < "%p/Inputs/test.exe.input" | \
1 RUN: FileCheck %s --check-prefix=CHECK
2 RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" -demangle=false < \
3 RUN: "%p/Inputs/test.exe.input" | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE
14
2 CHECK: _foo
3 CHECK-NEXT: test.c:3:0
5 CHECK: foo(void)
6 CHECK-NEXT: test.cpp:10
47 CHECK: _main
5 CHECK-NEXT: test.c:6:0
6 CHECK: ??
7 CHECK-NEXT: ??:0:0
8 CHECK-NEXT: test.cpp:13:0
9 CHECK: NS::Foo::bar(void)
10 CHECK-NEXT: test.cpp:6:0
11
12 CHECK-NO-DEMANGLE: foo
13 CHECK-NO-DEMANGLE-NEXT: test.cpp:10
14 CHECK-NO-DEMANGLE: _main
15 CHECK-LINKAGE-NAME-NEXT: test.cpp:13:0
16 CHECK-NO-DEMANGLE: bar
17 CHECK-LINKAGE-NAME-NEXT: test.cpp:6:0
2727 #include "llvm/Support/Path.h"
2828 #include
2929 #include
30
31 #if defined(_MSC_VER)
32 #include
33 #include
34 #endif
3035
3136 namespace llvm {
3237 namespace symbolize {
470475 std::unique_ptr Session;
471476 PDB_ErrorCode Error = loadDataForEXE(PDB_ReaderType::DIA,
472477 Objects.first->getFileName(), Session);
473 if (Error == PDB_ErrorCode::Success)
474 Context = new PDBContext(*CoffObject, std::move(Session));
478 if (Error == PDB_ErrorCode::Success) {
479 Context = new PDBContext(*CoffObject, std::move(Session),
480 Opts.RelativeAddresses);
481 }
475482 }
476483 if (!Context)
477484 Context = new DWARFContextInMemory(*Objects.second);
521528 free(DemangledName);
522529 return Result;
523530 #else
524 return Name;
531 char DemangledName[1024] = {0};
532 DWORD result = ::UnDecorateSymbolName(
533 Name.c_str(), DemangledName, 1023,
534 UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected
535 UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc
536 UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications
537 UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers
538 UNDNAME_NO_MS_KEYWORDS | // Strip all MS extension keywords
539 UNDNAME_NO_FUNCTION_RETURNS); // Strip function return types
540
541 return (result == 0) ? Name : std::string(DemangledName);
525542 #endif
526543 }
527544
3434 class LLVMSymbolizer {
3535 public:
3636 struct Options {
37 FunctionNameKind PrintFunctions;
3738 bool UseSymbolTable : 1;
38 FunctionNameKind PrintFunctions;
3939 bool PrintInlining : 1;
4040 bool Demangle : 1;
41 bool RelativeAddresses : 1;
4142 std::string DefaultArch;
4243 std::vector DsymHints;
43 Options(bool UseSymbolTable = true,
44 FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName,
45 bool PrintInlining = true, bool Demangle = true,
44 Options(FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName,
45 bool UseSymbolTable = true, bool PrintInlining = true,
46 bool Demangle = true, bool RelativeAddresses = false,
4647 std::string DefaultArch = "")
47 : UseSymbolTable(UseSymbolTable),
48 PrintFunctions(PrintFunctions), PrintInlining(PrintInlining),
49 Demangle(Demangle), DefaultArch(DefaultArch) {}
48 : PrintFunctions(PrintFunctions), UseSymbolTable(UseSymbolTable),
49 PrintInlining(PrintInlining), Demangle(Demangle),
50 RelativeAddresses(RelativeAddresses), DefaultArch(DefaultArch) {}
5051 };
5152
5253 LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {}
4848 clEnumValEnd));
4949
5050 static cl::opt
51 ClPrintInlining("inlining", cl::init(true),
52 cl::desc("Print all inlined frames for a given address"));
51 ClUseRelativeAddress("relative-address", cl::init(false),
52 cl::desc("Interpret addresses as relative addresses"),
53 cl::ReallyHidden);
54
55 static cl::opt
56 ClPrintInlining("inlining", cl::init(true),
57 cl::desc("Print all inlined frames for a given address"));
5358
5459 static cl::opt
5560 ClDemangle("demangle", cl::init(true), cl::desc("Demangle function names"));
126131 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
127132
128133 cl::ParseCommandLineOptions(argc, argv, "llvm-symbolizer\n");
129 LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions,
130 ClPrintInlining, ClDemangle, ClDefaultArch);
134 LLVMSymbolizer::Options Opts(ClPrintFunctions, ClUseSymbolTable,
135 ClPrintInlining, ClDemangle,
136 ClUseRelativeAddress, ClDefaultArch);
131137 for (const auto &hint : ClDsymHint) {
132138 if (sys::path::extension(hint) == ".dSYM") {
133139 Opts.DsymHints.push_back(hint);