From 6889483ca4bd5f2634c9041aa076aad01ac38b39 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Wed, 14 Aug 2013 17:09:30 +0000 Subject: [PATCH] llvm-symbolizer: add support for .gnu_debuglink section git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188386 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../dwarfdump-test.elf-x86-64.debuglink | Bin 0 -> 8668 bytes test/DebugInfo/llvm-symbolizer.test | 4 + tools/llvm-symbolizer/LLVMSymbolize.cpp | 83 ++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100755 test/DebugInfo/Inputs/dwarfdump-test.elf-x86-64.debuglink diff --git a/test/DebugInfo/Inputs/dwarfdump-test.elf-x86-64.debuglink b/test/DebugInfo/Inputs/dwarfdump-test.elf-x86-64.debuglink new file mode 100755 index 0000000000000000000000000000000000000000..8c08037ea3717323779d6bf12602355d851fe717 GIT binary patch literal 8668 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 %t.input +RUN: echo "%p/Inputs/dwarfdump-test.elf-x86-64.debuglink 0x400559" >> %t.input RUN: echo "%p/Inputs/dwarfdump-test.elf-x86-64 0x400436" >> %t.input RUN: echo "%p/Inputs/dwarfdump-test4.elf-x86-64 0x62c" >> %t.input RUN: echo "%p/Inputs/dwarfdump-inl-test.elf-x86-64 0x710" >> %t.input @@ -13,6 +14,9 @@ RUN: --default-arch=i386 < %t.input | FileCheck %s CHECK: main CHECK-NEXT: /tmp/dbginfo{{[/\\]}}dwarfdump-test.cc:16 +CHECK: main +CHECK-NEXT: /tmp/dbginfo{{[/\\]}}dwarfdump-test.cc:16 + CHECK: _start CHECK: _Z1cv diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp index 0346fb2b0a5..c8edde7ee2e 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.cpp +++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -15,7 +15,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Object/MachO.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include @@ -215,6 +218,74 @@ static std::string getDarwinDWARFResourceForPath(const std::string &Path) { return ResourceName.str(); } +static bool checkFileCRC(StringRef Path, uint32_t CRCHash) { + OwningPtr MB; + if (MemoryBuffer::getFileOrSTDIN(Path, MB)) + return false; + return !zlib::isAvailable() || CRCHash == zlib::crc32(MB->getBuffer()); +} + +static bool findDebugBinary(const std::string &OrigPath, + const std::string &DebuglinkName, uint32_t CRCHash, + std::string &Result) { + SmallString<16> OrigDir(OrigPath); + llvm::sys::path::remove_filename(OrigDir); + SmallString<16> DebugPath = OrigDir; + // Try /path/to/original_binary/debuglink_name + llvm::sys::path::append(DebugPath, DebuglinkName); + if (checkFileCRC(DebugPath, CRCHash)) { + Result = DebugPath.str(); + return true; + } + // Try /path/to/original_binary/.debug/debuglink_name + DebugPath = OrigPath; + llvm::sys::path::append(DebugPath, ".debug", DebuglinkName); + if (checkFileCRC(DebugPath, CRCHash)) { + Result = DebugPath.str(); + return true; + } + // Try /usr/lib/debug/path/to/original_binary/debuglink_name + DebugPath = "/usr/lib/debug"; + llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir), + DebuglinkName); + if (checkFileCRC(DebugPath, CRCHash)) { + Result = DebugPath.str(); + return true; + } + return false; +} + +static bool getGNUDebuglinkContents(const Binary *Bin, std::string &DebugName, + uint32_t &CRCHash) { + const ObjectFile *Obj = dyn_cast(Bin); + if (!Obj) + return false; + error_code EC; + for (section_iterator I = Obj->begin_sections(), E = Obj->end_sections(); + I != E; I.increment(EC)) { + StringRef Name; + I->getName(Name); + Name = Name.substr(Name.find_first_not_of("._")); + if (Name == "gnu_debuglink") { + StringRef Data; + I->getContents(Data); + DataExtractor DE(Data, Obj->isLittleEndian(), 0); + uint32_t Offset = 0; + if (const char *DebugNameStr = DE.getCStr(&Offset)) { + // 4-byte align the offset. + Offset = (Offset + 3) & ~0x3; + if (DE.isValidOffsetForDataOfSize(Offset, 4)) { + DebugName = DebugNameStr; + CRCHash = DE.getU32(&Offset); + return true; + } + } + break; + } + } + return false; +} + LLVMSymbolizer::BinaryPair LLVMSymbolizer::getOrCreateBinary(const std::string &Path) { BinaryMapTy::iterator I = BinaryForPath.find(Path); @@ -241,6 +312,18 @@ LLVMSymbolizer::getOrCreateBinary(const std::string &Path) { ParsedBinariesAndObjects.push_back(DbgBin); } } + // Try to locate the debug binary using .gnu_debuglink section. + if (DbgBin == 0) { + std::string DebuglinkName; + uint32_t CRCHash; + std::string DebugBinaryPath; + if (getGNUDebuglinkContents(Bin, DebuglinkName, CRCHash) && + findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath) && + !error(createBinary(DebugBinaryPath, ParsedDbgBinary))) { + DbgBin = ParsedDbgBinary.take(); + ParsedBinariesAndObjects.push_back(DbgBin); + } + } } if (DbgBin == 0) DbgBin = Bin; -- 2.34.1