From 0fea775e5ca33be3eb28744447fa263d9dee1f5f Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Fri, 17 Oct 2014 00:50:19 +0000 Subject: [PATCH] [llvm-symbolizer] Introduce the -dsym-hint option. llvm-symbolizer will consult one of the .dSYM paths passed via -dsym-hint if it fails to find the .dSYM bundle at the default location. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220004 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/CommandGuide/llvm-symbolizer.rst | 7 + .../llvm-symbolizer/Inputs/dsym-test-exe | Bin 0 -> 4584 bytes .../Contents/Info.plist | 20 +++ .../Resources/DWARF/dsym-test-exe-second | Bin 0 -> 8833 bytes .../Inputs/dsym-test-exe-second | Bin 0 -> 4584 bytes .../dsym-test-exe.dSYM/Contents/Info.plist | 20 +++ .../Contents/Resources/DWARF/dsym-test-exe | Bin 0 -> 8833 bytes test/tools/llvm-symbolizer/Inputs/dsym-test.c | 8 ++ test/tools/llvm-symbolizer/dsym.test | 14 ++ tools/llvm-symbolizer/LLVMSymbolize.cpp | 126 ++++++++++++------ tools/llvm-symbolizer/LLVMSymbolize.h | 20 ++- tools/llvm-symbolizer/llvm-symbolizer.cpp | 14 ++ 12 files changed, 178 insertions(+), 51 deletions(-) create mode 100755 test/tools/llvm-symbolizer/Inputs/dsym-test-exe create mode 100644 test/tools/llvm-symbolizer/Inputs/dsym-test-exe-differentname.dSYM/Contents/Info.plist create mode 100644 test/tools/llvm-symbolizer/Inputs/dsym-test-exe-differentname.dSYM/Contents/Resources/DWARF/dsym-test-exe-second create mode 100755 test/tools/llvm-symbolizer/Inputs/dsym-test-exe-second create mode 100644 test/tools/llvm-symbolizer/Inputs/dsym-test-exe.dSYM/Contents/Info.plist create mode 100644 test/tools/llvm-symbolizer/Inputs/dsym-test-exe.dSYM/Contents/Resources/DWARF/dsym-test-exe create mode 100644 test/tools/llvm-symbolizer/Inputs/dsym-test.c create mode 100644 test/tools/llvm-symbolizer/dsym.test diff --git a/docs/CommandGuide/llvm-symbolizer.rst b/docs/CommandGuide/llvm-symbolizer.rst index ce2d9c00435..96720e633f2 100644 --- a/docs/CommandGuide/llvm-symbolizer.rst +++ b/docs/CommandGuide/llvm-symbolizer.rst @@ -92,6 +92,13 @@ OPTIONS input (see example above). If architecture is not specified in either way, address will not be symbolized. Defaults to empty string. +.. option:: -dsym-hint= + + (Darwin-only flag). If the debug info for a binary isn't present in the default + location, look for the debug info at the .dSYM path provided via the + ``-dsym-hint`` flag. This flag can be used multiple times. + + EXIT STATUS ----------- diff --git a/test/tools/llvm-symbolizer/Inputs/dsym-test-exe b/test/tools/llvm-symbolizer/Inputs/dsym-test-exe new file mode 100755 index 0000000000000000000000000000000000000000..ba3154cd516ef87f62b3dc2020130e3f967f445c GIT binary patch literal 4584 zcmeHL&ubG=5T0$Utv1+HdQcRsTBRz@77-2TLB-G(OD#2pT98MQ-I#?<7P1>nddkIv zh~ST-;7Kov2X7t~4_*XMUZoeoi~m3o@%uI}W)p&l=N*`R^Ua%`dHcOwzI@*P@oPlH zNQktCL}VPE0k|tuh(z|o7vM^*T$;~rWLK{-+iONI9EjK_gF>Zp+4Wp+N%(%MHzyk7 zY%&bTkwQ}{up5B}So-_5@B!?%SCR0E8`V7ZB#pJcf+Ie0RPGMplS-9gqwB0X1Y$nw3@C3 zOgjMQIbLpfThErxPCR|^{L77_?}w+6!_h=`VKV$=2Qvqo!T0h#-hb3MCj;jm&utj5 z@$)dcvoZgA(+})Q`f?iQa0)1b9fxz?93K4c6B=j2Lx`M;;ERZ3iy4R+h#80(h#80( zh#80(h#80(h#BZ-U~S>vx3^4w%>LwZ^8;1XL58sCO0_~Ya|SE@iB>j@sUVY3F{!Qw z(_(BAJ2Yc+Rg6Z;NF_%`A4Y|mp`fpaRHdx!hFz=&wkq3s%dW}cO5Ul;F^)}0>rmJQ zC(yz6*Cb{61-8~(lgKfI^a^u3vGVP)h@=8+%Uy1CG#-=Z`|vz)DPhQ)Pv>&n=a4iW zWPtH~_;ds_M@`t#{lv?7M6t!BwntdUjkb7W`bCJl{a*ni|L2VHy0 + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + com.apple.xcode.dsym.dsym-test-exe-differentname + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + dSYM + CFBundleSignature + ???? + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/test/tools/llvm-symbolizer/Inputs/dsym-test-exe-differentname.dSYM/Contents/Resources/DWARF/dsym-test-exe-second b/test/tools/llvm-symbolizer/Inputs/dsym-test-exe-differentname.dSYM/Contents/Resources/DWARF/dsym-test-exe-second new file mode 100644 index 0000000000000000000000000000000000000000..c30dba3ff98a05988144a6279c56dc7faa192da3 GIT binary patch literal 8833 zcmeHN&rcIU6rOD~ZMxeE#zag! z=z)tzO+0b(Ks)EC3{2UlQC_cNHi9BQANa;fM{z9V%i--3$1I&eB`Zym1rLM8=dVSAsw~dbZ&F&dADMQ6n)Y%D2K@QG;(VyVVL+*|N|!5I(eS+ee7l?v*FZqbP1yDA zzW%w{TQ{=PvqC%2t3fxe-xVH=y0LL?BhLqT5v9}jGV|B?Q)pBl57>xj_z?h*2lI=f z0id*C=+zaf>3YSe{hcrExifyzZPxDbRWy6Wa1P{`R=xaEJQ(dD2tK}?2l#Y|M_qE9 z1nnRQKFhS(iu(22fq3MbB>Kb&_&=VCpPa4fELwf4r~Fh4=Uv5DyA=xoo`j=0jTOu@B) z@BloVj7ITP_W~5$H6Y{&tHn-1{Rui7;1!;PbAJVQ7&^!l)FKMH>})mk96E|JjkOpP zXX(mf_$54#w2%pCLZqL${)`=i07eP43Mn`n#bMWQ+ypyFBjjjE5Vd~~g~0a&i-wB5 z@jSG9+Zed*;U$R&y_kh*^IHQMJdad!xy74m&8RqL$yP@bDRnS!!3p&6XeyORCoYW- zse`)a7zGuEneRwq#Hras4QVCsI>3-zu}s)RNjjB$QgbvrowTf4F^Q=s-BQVNm^}>B z(My*37`9tjnwZecoy-hsC`t$P5uS~AHwamK`uYj35fcf9>5(5r86aePaDu(Ho(@J}Sv`nUegh8U^9Kb=^5y^l literal 0 HcmV?d00001 diff --git a/test/tools/llvm-symbolizer/Inputs/dsym-test-exe-second b/test/tools/llvm-symbolizer/Inputs/dsym-test-exe-second new file mode 100755 index 0000000000000000000000000000000000000000..ba3154cd516ef87f62b3dc2020130e3f967f445c GIT binary patch literal 4584 zcmeHL&ubG=5T0$Utv1+HdQcRsTBRz@77-2TLB-G(OD#2pT98MQ-I#?<7P1>nddkIv zh~ST-;7Kov2X7t~4_*XMUZoeoi~m3o@%uI}W)p&l=N*`R^Ua%`dHcOwzI@*P@oPlH zNQktCL}VPE0k|tuh(z|o7vM^*T$;~rWLK{-+iONI9EjK_gF>Zp+4Wp+N%(%MHzyk7 zY%&bTkwQ}{up5B}So-_5@B!?%SCR0E8`V7ZB#pJcf+Ie0RPGMplS-9gqwB0X1Y$nw3@C3 zOgjMQIbLpfThErxPCR|^{L77_?}w+6!_h=`VKV$=2Qvqo!T0h#-hb3MCj;jm&utj5 z@$)dcvoZgA(+})Q`f?iQa0)1b9fxz?93K4c6B=j2Lx`M;;ERZ3iy4R+h#80(h#80( zh#80(h#80(h#BZ-U~S>vx3^4w%>LwZ^8;1XL58sCO0_~Ya|SE@iB>j@sUVY3F{!Qw z(_(BAJ2Yc+Rg6Z;NF_%`A4Y|mp`fpaRHdx!hFz=&wkq3s%dW}cO5Ul;F^)}0>rmJQ zC(yz6*Cb{61-8~(lgKfI^a^u3vGVP)h@=8+%Uy1CG#-=Z`|vz)DPhQ)Pv>&n=a4iW zWPtH~_;ds_M@`t#{lv?7M6t!BwntdUjkb7W`bCJl{a*ni|L2VHy0 + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + com.apple.xcode.dsym.dsym-test-exe + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + dSYM + CFBundleSignature + ???? + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/test/tools/llvm-symbolizer/Inputs/dsym-test-exe.dSYM/Contents/Resources/DWARF/dsym-test-exe b/test/tools/llvm-symbolizer/Inputs/dsym-test-exe.dSYM/Contents/Resources/DWARF/dsym-test-exe new file mode 100644 index 0000000000000000000000000000000000000000..c30dba3ff98a05988144a6279c56dc7faa192da3 GIT binary patch literal 8833 zcmeHN&rcIU6rOD~ZMxeE#zag! z=z)tzO+0b(Ks)EC3{2UlQC_cNHi9BQANa;fM{z9V%i--3$1I&eB`Zym1rLM8=dVSAsw~dbZ&F&dADMQ6n)Y%D2K@QG;(VyVVL+*|N|!5I(eS+ee7l?v*FZqbP1yDA zzW%w{TQ{=PvqC%2t3fxe-xVH=y0LL?BhLqT5v9}jGV|B?Q)pBl57>xj_z?h*2lI=f z0id*C=+zaf>3YSe{hcrExifyzZPxDbRWy6Wa1P{`R=xaEJQ(dD2tK}?2l#Y|M_qE9 z1nnRQKFhS(iu(22fq3MbB>Kb&_&=VCpPa4fELwf4r~Fh4=Uv5DyA=xoo`j=0jTOu@B) z@BloVj7ITP_W~5$H6Y{&tHn-1{Rui7;1!;PbAJVQ7&^!l)FKMH>})mk96E|JjkOpP zXX(mf_$54#w2%pCLZqL${)`=i07eP43Mn`n#bMWQ+ypyFBjjjE5Vd~~g~0a&i-wB5 z@jSG9+Zed*;U$R&y_kh*^IHQMJdad!xy74m&8RqL$yP@bDRnS!!3p&6XeyORCoYW- zse`)a7zGuEneRwq#Hras4QVCsI>3-zu}s)RNjjB$QgbvrowTf4F^Q=s-BQVNm^}>B z(My*37`9tjnwZecoy-hsC`t$P5uS~AHwamK`uYj35fcf9>5(5r86aePaDu(Ho(@J}Sv`nUegh8U^9Kb=^5y^l literal 0 HcmV?d00001 diff --git a/test/tools/llvm-symbolizer/Inputs/dsym-test.c b/test/tools/llvm-symbolizer/Inputs/dsym-test.c new file mode 100644 index 00000000000..84d5ad9e914 --- /dev/null +++ b/test/tools/llvm-symbolizer/Inputs/dsym-test.c @@ -0,0 +1,8 @@ +// clang -c dsym-test.c -g +// clang dsym-test.o -g -o dsym-test-exe +// dsymutil dsym-test-exe +// clang dsym-test.o -g -o dsym-test-exe-second +// dsymutil dsym-test-exe-second -o dsym-test-exe-differentname.dSYM +int main() { + return 0; +} diff --git a/test/tools/llvm-symbolizer/dsym.test b/test/tools/llvm-symbolizer/dsym.test new file mode 100644 index 00000000000..326602d3f73 --- /dev/null +++ b/test/tools/llvm-symbolizer/dsym.test @@ -0,0 +1,14 @@ +RUN: echo "%p/Inputs/dsym-test-exe 0x0000000100000f90" > %t.input +RUN: echo "%p/Inputs/dsym-test-exe-second 0x0000000100000f90" >> %t.input +RUN: llvm-symbolizer < %t.input | FileCheck %s --check-prefix=CHECK-NOHINT +RUN: llvm-symbolizer -dsym-hint=%p/Inputs/dsym-test-exe-differentname.dSYM < %t.input | FileCheck %s --check-prefix=CHECK-HINT + +CHECK-NOHINT: main +CHECK-NOHINT: dsym-test.c +CHECK-NOHINT: main +CHECK-NOHINT: ??:0:0 + +CHECK-HINT: main +CHECK-HINT: dsym-test.c +CHECK-HINT: main +CHECK-HINT: dsym-test.c diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp index f1dccfdc40a..31bbedf8f03 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.cpp +++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -207,14 +207,21 @@ std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName, void LLVMSymbolizer::flush() { DeleteContainerSeconds(Modules); - BinaryForPath.clear(); + ObjectPairForPathArch.clear(); ObjectFileForArch.clear(); } -static std::string getDarwinDWARFResourceForPath(const std::string &Path) { - StringRef Basename = sys::path::filename(Path); - const std::string &DSymDirectory = Path + ".dSYM"; - SmallString<16> ResourceName = StringRef(DSymDirectory); +// For Path="/path/to/foo" and Basename="foo" assume that debug info is in +// /path/to/foo.dSYM/Contents/Resources/DWARF/foo. +// For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in +// /path/to/bar.dSYM/Contents/Resources/DWARF/foo. +static +std::string getDarwinDWARFResourceForPath( + const std::string &Path, const std::string &Basename) { + SmallString<16> ResourceName = StringRef(Path); + if (sys::path::extension(Path) != ".dSYM") { + ResourceName += ".dSYM"; + } sys::path::append(ResourceName, "Contents", "Resources", "DWARF"); sys::path::append(ResourceName, Basename); return ResourceName.str(); @@ -265,9 +272,8 @@ static bool findDebugBinary(const std::string &OrigPath, return false; } -static bool getGNUDebuglinkContents(const Binary *Bin, std::string &DebugName, +static bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName, uint32_t &CRCHash) { - const ObjectFile *Obj = dyn_cast(Bin); if (!Obj) return false; for (const SectionRef &Section : Obj->sections()) { @@ -294,57 +300,91 @@ static bool getGNUDebuglinkContents(const Binary *Bin, std::string &DebugName, return false; } -LLVMSymbolizer::BinaryPair -LLVMSymbolizer::getOrCreateBinary(const std::string &Path) { - const auto &I = BinaryForPath.find(Path); - if (I != BinaryForPath.end()) - return I->second; - Binary *Bin = nullptr; - Binary *DbgBin = nullptr; - ErrorOr> BinaryOrErr = createBinary(Path); - if (!error(BinaryOrErr.getError())) { - OwningBinary &ParsedBinary = BinaryOrErr.get(); - // Check if it's a universal binary. - Bin = ParsedBinary.getBinary().get(); - addOwningBinary(std::move(ParsedBinary)); - if (Bin->isMachO() || Bin->isMachOUniversalBinary()) { - // On Darwin we may find DWARF in separate object file in - // resource directory. - const std::string &ResourcePath = - getDarwinDWARFResourceForPath(Path); - BinaryOrErr = createBinary(ResourcePath); - std::error_code EC = BinaryOrErr.getError(); - if (EC != errc::no_such_file_or_directory && !error(EC)) { - OwningBinary B = std::move(BinaryOrErr.get()); - DbgBin = B.getBinary().get(); +static +bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj, + const MachOObjectFile *Obj) { + ArrayRef dbg_uuid = DbgObj->getUuid(); + ArrayRef bin_uuid = Obj->getUuid(); + if (dbg_uuid.empty() || bin_uuid.empty()) + return false; + return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size()); +} + +ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath, + const MachOObjectFile *MachExeObj, const std::string &ArchName) { + // On Darwin we may find DWARF in separate object file in + // resource directory. + std::vector DsymPaths; + StringRef Filename = sys::path::filename(ExePath); + DsymPaths.push_back(getDarwinDWARFResourceForPath(ExePath, Filename)); + for (const auto &Path : Opts.DsymHints) { + DsymPaths.push_back(getDarwinDWARFResourceForPath(Path, Filename)); + } + for (const auto &path : DsymPaths) { + ErrorOr> BinaryOrErr = createBinary(path); + std::error_code EC = BinaryOrErr.getError(); + if (EC != errc::no_such_file_or_directory && !error(EC)) { + OwningBinary B = std::move(BinaryOrErr.get()); + ObjectFile *DbgObj = + getObjectFileFromBinary(B.getBinary().get(), ArchName); + const MachOObjectFile *MachDbgObj = + dyn_cast(DbgObj); + if (!MachDbgObj) continue; + if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj)) { addOwningBinary(std::move(B)); + return DbgObj; } } + } + return nullptr; +} + +LLVMSymbolizer::ObjectPair +LLVMSymbolizer::getOrCreateObjects(const std::string &Path, + const std::string &ArchName) { + const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName)); + if (I != ObjectPairForPathArch.end()) + return I->second; + ObjectFile *Obj = nullptr; + ObjectFile *DbgObj = nullptr; + ErrorOr> BinaryOrErr = createBinary(Path); + if (!error(BinaryOrErr.getError())) { + OwningBinary &B = BinaryOrErr.get(); + Obj = getObjectFileFromBinary(B.getBinary().get(), ArchName); + if (!Obj) { + ObjectPair Res = std::make_pair(nullptr, nullptr); + ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res; + return Res; + } + addOwningBinary(std::move(B)); + if (auto MachObj = dyn_cast(Obj)) + DbgObj = lookUpDsymFile(Path, MachObj, ArchName); // Try to locate the debug binary using .gnu_debuglink section. - if (!DbgBin) { + if (!DbgObj) { std::string DebuglinkName; uint32_t CRCHash; std::string DebugBinaryPath; - if (getGNUDebuglinkContents(Bin, DebuglinkName, CRCHash) && + if (getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash) && findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) { BinaryOrErr = createBinary(DebugBinaryPath); if (!error(BinaryOrErr.getError())) { OwningBinary B = std::move(BinaryOrErr.get()); - DbgBin = B.getBinary().get(); + DbgObj = getObjectFileFromBinary(B.getBinary().get(), ArchName); addOwningBinary(std::move(B)); } } } } - if (!DbgBin) - DbgBin = Bin; - BinaryPair Res = std::make_pair(Bin, DbgBin); - BinaryForPath[Path] = Res; + if (!DbgObj) + DbgObj = Obj; + ObjectPair Res = std::make_pair(Obj, DbgObj); + ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res; return Res; } ObjectFile * -LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName) { +LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, + const std::string &ArchName) { if (!Bin) return nullptr; ObjectFile *Res = nullptr; @@ -382,18 +422,16 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { ArchName = ArchStr; } } - BinaryPair Binaries = getOrCreateBinary(BinaryName); - ObjectFile *Obj = getObjectFileFromBinary(Binaries.first, ArchName); - ObjectFile *DbgObj = getObjectFileFromBinary(Binaries.second, ArchName); + ObjectPair Objects = getOrCreateObjects(BinaryName, ArchName); - if (!Obj) { + if (!Objects.first) { // Failed to find valid object file. Modules.insert(make_pair(ModuleName, (ModuleInfo *)nullptr)); return nullptr; } - DIContext *Context = DIContext::getDWARFContext(*DbgObj); + DIContext *Context = DIContext::getDWARFContext(*Objects.second); assert(Context); - ModuleInfo *Info = new ModuleInfo(Obj, Context); + ModuleInfo *Info = new ModuleInfo(Objects.first, Context); Modules.insert(make_pair(ModuleName, Info)); return Info; } diff --git a/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h index 17b78dc5204..52f1fc99171 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.h +++ b/tools/llvm-symbolizer/LLVMSymbolize.h @@ -39,13 +39,14 @@ public: bool PrintInlining : 1; bool Demangle : 1; std::string DefaultArch; + std::vector DsymHints; Options(bool UseSymbolTable = true, FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName, bool PrintInlining = true, bool Demangle = true, std::string DefaultArch = "") - : UseSymbolTable(UseSymbolTable), PrintFunctions(PrintFunctions), - PrintInlining(PrintInlining), Demangle(Demangle), - DefaultArch(DefaultArch) {} + : UseSymbolTable(UseSymbolTable), + PrintFunctions(PrintFunctions), PrintInlining(PrintInlining), + Demangle(Demangle), DefaultArch(DefaultArch) {} }; LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {} @@ -62,11 +63,15 @@ public: void flush(); static std::string DemangleName(const std::string &Name); private: - typedef std::pair BinaryPair; + typedef std::pair ObjectPair; ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName); - /// \brief Returns pair of pointers to binary and debug binary. - BinaryPair getOrCreateBinary(const std::string &Path); + ObjectFile *lookUpDsymFile(const std::string &Path, const MachOObjectFile *ExeObj, + const std::string &ArchName); + + /// \brief Returns pair of pointers to object and debug object. + ObjectPair getOrCreateObjects(const std::string &Path, + const std::string &ArchName); /// \brief Returns a parsed object file for a given architecture in a /// universal binary (or the binary itself if it is an object file). ObjectFile *getObjectFileFromBinary(Binary *Bin, const std::string &ArchName); @@ -83,9 +88,10 @@ private: // Owns module info objects. std::map Modules; - std::map BinaryForPath; std::map, ObjectFile *> ObjectFileForArch; + std::map, ObjectPair> + ObjectPairForPathArch; Options Opts; static const char kBadString[]; diff --git a/tools/llvm-symbolizer/llvm-symbolizer.cpp b/tools/llvm-symbolizer/llvm-symbolizer.cpp index 29db172531b..d554022e450 100644 --- a/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" @@ -61,6 +62,11 @@ ClBinaryName("obj", cl::init(""), cl::desc("Path to object file to be symbolized (if not provided, " "object file should be specified for each input line)")); +static cl::list +ClDsymHint("dsym-hint", cl::ZeroOrMore, + cl::desc("Path to .dSYM bundles to search for debug info for the " + "object files")); + static bool parseCommand(bool &IsData, std::string &ModuleName, uint64_t &ModuleOffset) { const char *kDataCmd = "DATA "; @@ -119,6 +125,14 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "llvm-symbolizer\n"); LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions, ClPrintInlining, ClDemangle, ClDefaultArch); + for (const auto &hint : ClDsymHint) { + if (sys::path::extension(hint) == ".dSYM") { + Opts.DsymHints.push_back(hint); + } else { + errs() << "Warning: invalid dSYM hint: \"" << hint << + "\" (must have the '.dSYM' extension).\n"; + } + } LLVMSymbolizer Symbolizer(Opts); bool IsData = false;