From 27a9e1dbcf5d0fdf2457c10fecd089a8c02cdec5 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 9 Oct 2015 00:15:01 +0000 Subject: [PATCH] [llvm-symbolizer] Make --relative-address work with DWARF contexts Summary: Previously the relative address flag only affected PDB debug info. Now both DIContext implementations always expect to be passed virtual addresses. llvm-symbolizer is now responsible for adding ImageBase to module offsets when --relative-offset is passed. Reviewers: zturner Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D12883 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249784 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/PDB/PDBContext.h | 3 +-- include/llvm/Object/COFF.h | 1 + lib/DebugInfo/PDB/PDBContext.cpp | 21 ++++-------------- lib/Object/COFFObjectFile.cpp | 21 +++++++++--------- .../llvm-symbolizer/Inputs/coff-dwarf.cpp | 19 ++++++++++++++++ .../llvm-symbolizer/Inputs/coff-dwarf.exe | Bin 0 -> 18944 bytes .../llvm-symbolizer/Inputs/coff-dwarf.input | 2 ++ test/tools/llvm-symbolizer/coff-dwarf.test | 9 ++++++++ test/tools/llvm-symbolizer/pdb/pdb.test | 10 +++++++++ tools/llvm-symbolizer/LLVMSymbolize.cpp | 20 +++++++++++++++-- tools/llvm-symbolizer/LLVMSymbolize.h | 4 ++++ 11 files changed, 79 insertions(+), 31 deletions(-) create mode 100644 test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp create mode 100644 test/tools/llvm-symbolizer/Inputs/coff-dwarf.exe create mode 100644 test/tools/llvm-symbolizer/Inputs/coff-dwarf.input create mode 100644 test/tools/llvm-symbolizer/coff-dwarf.test diff --git a/include/llvm/DebugInfo/PDB/PDBContext.h b/include/llvm/DebugInfo/PDB/PDBContext.h index 2bb97463f90..9404a592244 100644 --- a/include/llvm/DebugInfo/PDB/PDBContext.h +++ b/include/llvm/DebugInfo/PDB/PDBContext.h @@ -32,8 +32,7 @@ class PDBContext : public DIContext { public: PDBContext(const object::COFFObjectFile &Object, - std::unique_ptr PDBSession, - bool RelativeAddress); + std::unique_ptr PDBSession); static bool classof(const DIContext *DICtx) { return DICtx->getKind() == CK_PDB; diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index ce9042fd3ab..ba846dd7d8b 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -773,6 +773,7 @@ public: std::error_code getSectionContents(const coff_section *Sec, ArrayRef &Res) const; + ErrorOr getImageBase() const; std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; std::error_code getHintName(uint32_t Rva, uint16_t &Hint, diff --git a/lib/DebugInfo/PDB/PDBContext.cpp b/lib/DebugInfo/PDB/PDBContext.cpp index 83f27c7fa3d..ca2ae6665ce 100644 --- a/lib/DebugInfo/PDB/PDBContext.cpp +++ b/lib/DebugInfo/PDB/PDBContext.cpp @@ -21,24 +21,11 @@ using namespace llvm; using namespace llvm::object; PDBContext::PDBContext(const COFFObjectFile &Object, - std::unique_ptr PDBSession, - bool RelativeAddress) + std::unique_ptr PDBSession) : DIContext(CK_PDB), Session(std::move(PDBSession)) { - if (!RelativeAddress) { - uint64_t ImageBase = 0; - if (Object.is64()) { - const pe32plus_header *Header = nullptr; - Object.getPE32PlusHeader(Header); - if (Header) - ImageBase = Header->ImageBase; - } else { - const pe32_header *Header = nullptr; - Object.getPE32Header(Header); - if (Header) - ImageBase = static_cast(Header->ImageBase); - } - Session->setLoadAddress(ImageBase); - } + ErrorOr ImageBase = Object.getImageBase(); + if (ImageBase) + Session->setLoadAddress(ImageBase.get()); } void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType) {} diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index d3f604a8d35..efb3ea04083 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -174,10 +174,7 @@ ErrorOr COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { // The section VirtualAddress does not include ImageBase, and we want to // return virtual addresses. - if (PE32Header) - Result += PE32Header->ImageBase; - else if (PE32PlusHeader) - Result += PE32PlusHeader->ImageBase; + Result += getImageBase().get(); return Result; } @@ -274,10 +271,7 @@ uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { // The section VirtualAddress does not include ImageBase, and we want to // return virtual addresses. - if (PE32Header) - Result += PE32Header->ImageBase; - else if (PE32PlusHeader) - Result += PE32PlusHeader->ImageBase; + Result += getImageBase().get(); return Result; } @@ -424,10 +418,17 @@ std::error_code COFFObjectFile::initSymbolTablePtr() { return std::error_code(); } +ErrorOr COFFObjectFile::getImageBase() const { + if (PE32Header) + return uint64_t(PE32Header->ImageBase); + else if (PE32PlusHeader) + return uint64_t(PE32PlusHeader->ImageBase); + return object_error::parse_failed; +} + // Returns the file offset for the given VA. std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { - uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase - : (uint64_t)PE32PlusHeader->ImageBase; + uint64_t ImageBase = getImageBase().get(); uint64_t Rva = Addr - ImageBase; assert(Rva <= UINT32_MAX); return getRvaPtr((uint32_t)Rva, Res); diff --git a/test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp b/test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp new file mode 100644 index 00000000000..9741439cdcf --- /dev/null +++ b/test/tools/llvm-symbolizer/Inputs/coff-dwarf.cpp @@ -0,0 +1,19 @@ +// To generate the corresponding EXE, run: +// clang-cl -O2 -gdwarf -c coff-dwarf.cpp && lld-link -debug coff-dwarf.obj + +extern "C" int puts(const char *str); + +void __declspec(noinline) foo() { + puts("foo1"); + puts("foo2"); +} + +// LLVM should inline this into main. +static void bar() { + foo(); +} + +int main() { + bar(); + return 0; +} diff --git a/test/tools/llvm-symbolizer/Inputs/coff-dwarf.exe b/test/tools/llvm-symbolizer/Inputs/coff-dwarf.exe new file mode 100644 index 0000000000000000000000000000000000000000..018053b979b9179a38870212ac33289972d96159 GIT binary patch literal 18944 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 == COFF::IMAGE_FILE_MACHINE_I386; } +uint64_t ModuleInfo::getModulePreferredBase() const { + if (auto *CoffObject = dyn_cast(Module)) + if (auto Base = CoffObject->getImageBase()) + return Base.get(); + return 0; +} + bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address, std::string &Name, uint64_t &Addr, uint64_t &Size) const { @@ -210,6 +217,12 @@ std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, ModuleInfo *Info = getOrCreateModuleInfo(ModuleName); if (!Info) return printDILineInfo(DILineInfo(), Info); + + // If the user is giving us relative addresses, add the preferred base of the + // object to the offset before we do the query. It's what DIContext expects. + if (Opts.RelativeAddresses) + ModuleOffset += Info->getModulePreferredBase(); + if (Opts.PrintInlining) { DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(ModuleOffset, Opts); @@ -233,6 +246,10 @@ std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName, uint64_t Size = 0; if (Opts.UseSymbolTable) { if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) { + // If the user is giving us relative addresses, add the preferred base of the + // object to the offset before we do the query. It's what DIContext expects. + if (Opts.RelativeAddresses) + ModuleOffset += Info->getModulePreferredBase(); if (Info->symbolizeData(ModuleOffset, Name, Start, Size) && Opts.Demangle) Name = DemangleName(Name, Info); } @@ -474,8 +491,7 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { PDB_ErrorCode Error = loadDataForEXE(PDB_ReaderType::DIA, Objects.first->getFileName(), Session); if (Error == PDB_ErrorCode::Success) { - Context = new PDBContext(*CoffObject, std::move(Session), - Opts.RelativeAddresses); + Context = new PDBContext(*CoffObject, std::move(Session)); } } if (!Context) diff --git a/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h index b52c76036e1..00a3860eacb 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.h +++ b/tools/llvm-symbolizer/LLVMSymbolize.h @@ -117,6 +117,10 @@ public: // Return true if this is a 32-bit x86 PE COFF module. bool isWin32Module() const; + // Returns the preferred base of the module, i.e. where the loader would place + // it in memory assuming there were no conflicts. + uint64_t getModulePreferredBase() const; + private: bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address, std::string &Name, uint64_t &Addr, -- 2.34.1