From dd65b7a9f542ec5588abff7ffa47b8653fa53fea Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 16 Oct 2015 23:43:22 +0000 Subject: [PATCH] [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 --- .../llvm-symbolizer/Inputs/coff-dwarf.cpp | 2 +- .../llvm-symbolizer/Inputs/coff-exports.cpp | 20 ++++++++ .../llvm-symbolizer/Inputs/coff-exports.exe | Bin 0 -> 8192 bytes test/tools/llvm-symbolizer/coff-exports.test | 17 +++++++ tools/llvm-symbolizer/LLVMSymbolize.cpp | 44 ++++++++++++++++++ tools/llvm-symbolizer/LLVMSymbolize.h | 1 + 6 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 test/tools/llvm-symbolizer/Inputs/coff-exports.cpp create mode 100644 test/tools/llvm-symbolizer/Inputs/coff-exports.exe create mode 100644 test/tools/llvm-symbolizer/coff-exports.test diff --git a/test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp b/test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp index 9741439cdcf..3a832a9fcff 100644 --- a/test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp +++ b/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/test/tools/llvm-symbolizer/Inputs/coff-exports.cpp b/test/tools/llvm-symbolizer/Inputs/coff-exports.cpp new file mode 100644 index 00000000000..23b44b32902 --- /dev/null +++ b/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/test/tools/llvm-symbolizer/Inputs/coff-exports.exe b/test/tools/llvm-symbolizer/Inputs/coff-exports.exe new file mode 100644 index 0000000000000000000000000000000000000000..939205e3f82eef981eeb865f95d8410d18514b1b GIT binary patch literal 8192 zcmeHMe{56N6~1=-f|KGTt1xrB0v-)j1|ynW`?T)GmKaqLa22*w)$$B1!pC%BGDLtz;A?w_#N@O@nqFZ{Kzl4_eU!sk*l2dopbJY&%O8Dd!MhJwk_TT{IC?LBJ{1TpuIb2Zu#>maxu2od}!wS}~NoZBz{~)o;yDkA=ByW(-uzfBJ( zJw90m7)#gc;dDwJI213JETf4?yr@pp<_L$zvl;{g;1+9Tsb7X2q&hEz)`p~@I2r4# z?bqW?lfM%}{T3xmqjT3Zb#hhZGc%c#_WRBL4t{;@tr$C?fGxo7wN@ z(Z|gg(}YQ1RrNyiuYdmB^8L#gJF(4qI`~Iby%}?IQ_b1S*jFI*uCD{GhFGDCK%9M6 z1)cD&^^7^7<2}I?h!grAAbqaaKqstd$43kFDj?nytOGis57G%e4YX}!YzK4^cnPu( zI^HeptD6`*MSkEkWQ6>{Ihz?9hHeFlkTb*q_Cqc}C;TylLmvjFA$y<`o`sATcKo`iwJBR4L7;NN@#2ME_ z^5El$R?%11_!M2aDu0w2vTc1`RS(h2O11yWNyC^>ReRHyp((Zt<7pP=sgk z95QjmegKt<&`YK{J72&kL+C2mY{p<&!iJ$-ETO2|!Amwzzl|v*%CzX;fybrK=J;{U zrvY3W1vrR1k0LBa$X3PnMT#uEd6H%&oCbJO!mFBPe@O$|3j~x$)&AZhWKMKVlF_d_kX9g`ZFNgg;rxi9cqz3wi{VOa-I~H!NHTw@1Q-C7o&@}pk*a= zi!N?;yV5Nwuh})h6(NHP^%T}?7z*r*xZd$0t49&OuQ}`k0L9jaXZD5vP*wv_lg*uY zvV>I`SM5uYzhv`T%`sQCA43F1Xofkpd`P%QW7lhyWyC&$>f^~~M~?oiMz4U0d^>%k zv`4c|7%A=8cX#1qP+R93u9yZJ0`cC-#2v|ghb1vz;m*|Hpth`Y1&h<2%j+JBiOJ4Idy%DQuQ8OUaxSNi}&KCvbLtCq@+P>k+n>^Kg_s=P} zuV+`%8l|xy%g%A-59IkShQ{HlRK)5`cG2Zi$w||c8RJy8R@dnX!9cl^Iiw$3t6YM< zc!00sCF8F2V54?Y=N{Hi>Uu}zKAIZ!@7%0wGkb0ZX2c4iS61zlg;-Xqg{3HVLF4U2Qjujd@JF~ zI9JZ7_Vc6<35&o1)DY}Gn-EfK98*}TJN4CdK8*Pr@sNAPHvJlgWq(d<+gjbglULNl zEnGRK+PmPJ+NGcOEjT`V!T!C*j^^2lEv>gp7I|u8bwl<+w8tR1 z;;C*>?F|}RNT4ZsMAd$m?uo;rclZJAa0R>l2u7^!`L!4)zkKFP>C0!-aoYT&+BzEh zD7E0gVbrIZM*ve5Tq&V#W5&@MXLLKPgCLY`}4umLZjbmhK`f&-y3^Y!{%ZJ6tfAnKBk*iRey z69Zo|@Th^42Ikt`tn+r6R?AYXHx%~Ek|=(?rK4jD>oEB`0#W(?P!FouR+G=S#utxD zflx3M@a^!2yL;ef`{577rON2F_qg3zlbZImpV@Ekmtx^E}dLyAQlZeHnu#s8?!(Obj)) + addCoffExportSymbols(CoffObj); + } +} + +void ModuleInfo::addCoffExportSymbols(const COFFObjectFile *CoffObj) { + // Get all export names and offsets. + struct OffsetNamePair { + uint32_t Offset; + StringRef Name; + }; + std::vector 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/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h index 00a3860eacb..17df56e695a 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.h +++ b/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 DebugInfoContext; -- 2.34.1