llvm.org GIT mirror llvm / dd65b7a
[llvm-symbolizer] Use the export table if no symbols are present This lets us make guesses about symbols in third party DLLs without debug info, like MSVCR120.dll or kernel32.dll. dbghelp does the same thing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@250582 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 4 years ago
6 changed file(s) with 83 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
0 // To generate the corresponding EXE, run:
1 // clang-cl -O2 -gdwarf -c coff-dwarf.cpp && lld-link -debug coff-dwarf.obj
1 // clang-cl -MD -O2 -gdwarf -c coff-dwarf.cpp && lld-link -debug coff-dwarf.obj
22
33 extern "C" int puts(const char *str);
44
0 // To generate the corresponding EXE, run:
1 // clang-cl -MD -c coff-exports.cpp && lld-link /MANIFEST:NO coff-exports.obj
2
3 #define EXPORT __declspec(dllexport)
4
5 extern "C" int puts(const char *str);
6
7 EXPORT void __declspec(noinline) foo() {
8 puts("foo1");
9 puts("foo2");
10 }
11
12 void bar() {
13 foo();
14 }
15
16 EXPORT int main() {
17 bar();
18 return 0;
19 }
0 RUN: grep '^ADDR:' %s | sed -s 's/ADDR: //' \
1 RUN: | llvm-symbolizer --inlining --relative-address -obj="%p/Inputs/coff-exports.exe" \
2 RUN: | FileCheck %s
3
4 ADDR: 0x500A
5 ADDR: 0x5038
6 ADDR: 0x504B
7
8 We get the expected stack trace, except 'foo' appears for the 'bar' frame
9 because 'bar' isn't in the export table.
10
11 CHECK: foo(void)
12 CHECK: ??:0:0
13 CHECK: foo(void)
14 CHECK: ??:0:0
15 CHECK: main
16 CHECK: ??:0:0
8282 computeSymbolSizes(*Module);
8383 for (auto &P : Symbols)
8484 addSymbol(P.first, P.second, OpdExtractor.get(), OpdAddress);
85
86 // If this is a COFF object and we didn't find any symbols, try the export
87 // table.
88 if (Symbols.empty()) {
89 if (auto *CoffObj = dyn_cast(Obj))
90 addCoffExportSymbols(CoffObj);
91 }
92 }
93
94 void ModuleInfo::addCoffExportSymbols(const COFFObjectFile *CoffObj) {
95 // Get all export names and offsets.
96 struct OffsetNamePair {
97 uint32_t Offset;
98 StringRef Name;
99 };
100 std::vector ExportSyms;
101 for (const ExportDirectoryEntryRef &Ref : CoffObj->export_directories()) {
102 StringRef Name;
103 uint32_t Offset;
104 if (error(Ref.getSymbolName(Name)) || error(Ref.getExportRVA(Offset)))
105 return;
106 ExportSyms.push_back(OffsetNamePair{Offset, Name});
107 }
108 if (ExportSyms.empty())
109 return;
110
111 // Sort by ascending offset.
112 array_pod_sort(ExportSyms.begin(), ExportSyms.end(),
113 [](const OffsetNamePair *L, const OffsetNamePair *R) -> int {
114 return L->Offset - R->Offset;
115 });
116
117 // Approximate the symbol sizes by assuming they run to the next symbol.
118 // FIXME: This assumes all exports are functions.
119 uint64_t ImageBase = CoffObj->getImageBase();
120 for (auto I = ExportSyms.begin(), E = ExportSyms.end(); I != E; ++I) {
121 OffsetNamePair &Export = *I;
122 // FIXME: The last export has a one byte size now.
123 uint32_t NextOffset = I != E ? I->Offset : Export.Offset + 1;
124 uint64_t SymbolStart = ImageBase + Export.Offset;
125 uint64_t SymbolSize = NextOffset - Export.Offset;
126 SymbolDesc SD = {SymbolStart, SymbolSize};
127 Functions.insert(std::make_pair(SD, Export.Name));
128 }
85129 }
86130
87131 void ModuleInfo::addSymbol(const SymbolRef &Symbol, uint64_t SymbolSize,
129129 void addSymbol(const SymbolRef &Symbol, uint64_t SymbolSize,
130130 DataExtractor *OpdExtractor = nullptr,
131131 uint64_t OpdAddress = 0);
132 void addCoffExportSymbols(const COFFObjectFile *CoffObj);
132133 ObjectFile *Module;
133134 std::unique_ptr DebugInfoContext;
134135