summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp2
-rw-r--r--llvm/test/tools/llvm-symbolizer/Inputs/coff-exports.cpp20
-rw-r--r--llvm/test/tools/llvm-symbolizer/Inputs/coff-exports.exebin0 -> 8192 bytes
-rw-r--r--llvm/test/tools/llvm-symbolizer/coff-exports.test17
-rw-r--r--llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp44
-rw-r--r--llvm/tools/llvm-symbolizer/LLVMSymbolize.h1
6 files changed, 83 insertions, 1 deletions
diff --git a/llvm/test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp b/llvm/test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp
index 9741439cdcf..3a832a9fcff 100644
--- a/llvm/test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp
+++ b/llvm/test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp
@@ -1,5 +1,5 @@
// To generate the corresponding EXE, run:
-// clang-cl -O2 -gdwarf -c coff-dwarf.cpp && lld-link -debug coff-dwarf.obj
+// clang-cl -MD -O2 -gdwarf -c coff-dwarf.cpp && lld-link -debug coff-dwarf.obj
extern "C" int puts(const char *str);
diff --git a/llvm/test/tools/llvm-symbolizer/Inputs/coff-exports.cpp b/llvm/test/tools/llvm-symbolizer/Inputs/coff-exports.cpp
new file mode 100644
index 00000000000..23b44b32902
--- /dev/null
+++ b/llvm/test/tools/llvm-symbolizer/Inputs/coff-exports.cpp
@@ -0,0 +1,20 @@
+// To generate the corresponding EXE, run:
+// clang-cl -MD -c coff-exports.cpp && lld-link /MANIFEST:NO coff-exports.obj
+
+#define EXPORT __declspec(dllexport)
+
+extern "C" int puts(const char *str);
+
+EXPORT void __declspec(noinline) foo() {
+ puts("foo1");
+ puts("foo2");
+}
+
+void bar() {
+ foo();
+}
+
+EXPORT int main() {
+ bar();
+ return 0;
+}
diff --git a/llvm/test/tools/llvm-symbolizer/Inputs/coff-exports.exe b/llvm/test/tools/llvm-symbolizer/Inputs/coff-exports.exe
new file mode 100644
index 00000000000..939205e3f82
--- /dev/null
+++ b/llvm/test/tools/llvm-symbolizer/Inputs/coff-exports.exe
Binary files differ
diff --git a/llvm/test/tools/llvm-symbolizer/coff-exports.test b/llvm/test/tools/llvm-symbolizer/coff-exports.test
new file mode 100644
index 00000000000..7283acda2fc
--- /dev/null
+++ b/llvm/test/tools/llvm-symbolizer/coff-exports.test
@@ -0,0 +1,17 @@
+RUN: grep '^ADDR:' %s | sed -s 's/ADDR: //' \
+RUN: | llvm-symbolizer --inlining --relative-address -obj="%p/Inputs/coff-exports.exe" \
+RUN: | FileCheck %s
+
+ADDR: 0x500A
+ADDR: 0x5038
+ADDR: 0x504B
+
+We get the expected stack trace, except 'foo' appears for the 'bar' frame
+because 'bar' isn't in the export table.
+
+CHECK: foo(void)
+CHECK: ??:0:0
+CHECK: foo(void)
+CHECK: ??:0:0
+CHECK: main
+CHECK: ??:0:0
diff --git a/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp b/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp
index 996520b8430..ae164b07b96 100644
--- a/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp
+++ b/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp
@@ -83,6 +83,50 @@ ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
computeSymbolSizes(*Module);
for (auto &P : Symbols)
addSymbol(P.first, P.second, OpdExtractor.get(), OpdAddress);
+
+ // If this is a COFF object and we didn't find any symbols, try the export
+ // table.
+ if (Symbols.empty()) {
+ if (auto *CoffObj = dyn_cast<COFFObjectFile>(Obj))
+ addCoffExportSymbols(CoffObj);
+ }
+}
+
+void ModuleInfo::addCoffExportSymbols(const COFFObjectFile *CoffObj) {
+ // Get all export names and offsets.
+ struct OffsetNamePair {
+ uint32_t Offset;
+ StringRef Name;
+ };
+ std::vector<OffsetNamePair> ExportSyms;
+ for (const ExportDirectoryEntryRef &Ref : CoffObj->export_directories()) {
+ StringRef Name;
+ uint32_t Offset;
+ if (error(Ref.getSymbolName(Name)) || error(Ref.getExportRVA(Offset)))
+ return;
+ ExportSyms.push_back(OffsetNamePair{Offset, Name});
+ }
+ if (ExportSyms.empty())
+ return;
+
+ // Sort by ascending offset.
+ array_pod_sort(ExportSyms.begin(), ExportSyms.end(),
+ [](const OffsetNamePair *L, const OffsetNamePair *R) -> int {
+ return L->Offset - R->Offset;
+ });
+
+ // Approximate the symbol sizes by assuming they run to the next symbol.
+ // FIXME: This assumes all exports are functions.
+ uint64_t ImageBase = CoffObj->getImageBase();
+ for (auto I = ExportSyms.begin(), E = ExportSyms.end(); I != E; ++I) {
+ OffsetNamePair &Export = *I;
+ // FIXME: The last export has a one byte size now.
+ uint32_t NextOffset = I != E ? I->Offset : Export.Offset + 1;
+ uint64_t SymbolStart = ImageBase + Export.Offset;
+ uint64_t SymbolSize = NextOffset - Export.Offset;
+ SymbolDesc SD = {SymbolStart, SymbolSize};
+ Functions.insert(std::make_pair(SD, Export.Name));
+ }
}
void ModuleInfo::addSymbol(const SymbolRef &Symbol, uint64_t SymbolSize,
diff --git a/llvm/tools/llvm-symbolizer/LLVMSymbolize.h b/llvm/tools/llvm-symbolizer/LLVMSymbolize.h
index 00a3860eacb..17df56e695a 100644
--- a/llvm/tools/llvm-symbolizer/LLVMSymbolize.h
+++ b/llvm/tools/llvm-symbolizer/LLVMSymbolize.h
@@ -130,6 +130,7 @@ private:
void addSymbol(const SymbolRef &Symbol, uint64_t SymbolSize,
DataExtractor *OpdExtractor = nullptr,
uint64_t OpdAddress = 0);
+ void addCoffExportSymbols(const COFFObjectFile *CoffObj);
ObjectFile *Module;
std::unique_ptr<DIContext> DebugInfoContext;
OpenPOWER on IntegriCloud