Index: include/llvm/DebugInfo/PDB/PDBContext.h =================================================================== --- include/llvm/DebugInfo/PDB/PDBContext.h +++ include/llvm/DebugInfo/PDB/PDBContext.h @@ -32,7 +32,8 @@ public: PDBContext(const object::COFFObjectFile &Object, - std::unique_ptr PDBSession); + std::unique_ptr PDBSession, + bool RelativeAddress); static bool classof(const DIContext *DICtx) { return DICtx->getKind() == CK_PDB; Index: lib/DebugInfo/PDB/PDBContext.cpp =================================================================== --- lib/DebugInfo/PDB/PDBContext.cpp +++ lib/DebugInfo/PDB/PDBContext.cpp @@ -14,43 +14,71 @@ #include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" #include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" #include "llvm/Object/COFF.h" using namespace llvm; using namespace llvm::object; PDBContext::PDBContext(const COFFObjectFile &Object, - std::unique_ptr PDBSession) + std::unique_ptr PDBSession, + bool RelativeAddress) : DIContext(CK_PDB), Session(std::move(PDBSession)) { - 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); + 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); } - Session->setLoadAddress(ImageBase); } void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType) {} DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier) { - auto Symbol = Session->findSymbolByAddress(Address, PDB_SymType::None); + std::unique_ptr Symbol = + Session->findSymbolByAddress(Address, PDB_SymType::None); uint32_t Length = 1; DILineInfo Result; - if (auto Func = dyn_cast_or_null(Symbol.get())) { - if (Specifier.FNKind == DINameKind::LinkageName) - Result.FunctionName = Func->getUndecoratedName(); - else if (Specifier.FNKind == DINameKind::ShortName) - Result.FunctionName = Func->getName(); + if (Specifier.FNKind != DINameKind::None) { + std::string FunctionName; + if (Specifier.FNKind == DINameKind::LinkageName) { + // It is not possible to get the mangled linkage name through a + // PDBSymbolFunc. For that we have to specifically request a + // PDBSymbolPublicSymbol. + auto PublicSym = + Session->findSymbolByAddress(Address, PDB_SymType::PublicSymbol); + if (PublicSym) { + auto PS = dyn_cast(PublicSym.get()); + assert(PS); + FunctionName = PS->getName(); + } + } + + // This could happen either if there was no public symbol (e.g. not + // external) or the user requested the short name. In the former case, + // although they technically requested the linkage name, if the linkage + // name is not available we fallback to at least returning a non-empty + // string. + if (FunctionName.empty()) { + if (auto Func = dyn_cast_or_null(Symbol.get())) + FunctionName = Func->getName(); + } + if (!FunctionName.empty()) + Result.FunctionName = FunctionName; + } + if (auto Func = dyn_cast_or_null(Symbol.get())) { Length = Func->getLength(); } else if (auto Data = dyn_cast_or_null(Symbol.get())) { Length = Data->getLength(); Index: tools/llvm-symbolizer/LLVMSymbolize.h =================================================================== --- tools/llvm-symbolizer/LLVMSymbolize.h +++ tools/llvm-symbolizer/LLVMSymbolize.h @@ -35,19 +35,20 @@ class LLVMSymbolizer { public: struct Options { - bool UseSymbolTable : 1; FunctionNameKind PrintFunctions; + bool UseSymbolTable : 1; bool PrintInlining : 1; bool Demangle : 1; + bool RelativeAddresses : 1; std::string DefaultArch; std::vector DsymHints; - Options(bool UseSymbolTable = true, - FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName, - bool PrintInlining = true, bool Demangle = true, + Options(FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName, + bool UseSymbolTable = true, bool PrintInlining = true, + bool Demangle = true, bool RelativeAddresses = false, std::string DefaultArch = "") - : UseSymbolTable(UseSymbolTable), - PrintFunctions(PrintFunctions), PrintInlining(PrintInlining), - Demangle(Demangle), DefaultArch(DefaultArch) {} + : PrintFunctions(PrintFunctions), UseSymbolTable(UseSymbolTable), + PrintInlining(PrintInlining), Demangle(Demangle), + RelativeAddresses(RelativeAddresses), DefaultArch(DefaultArch) {} }; LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {} Index: tools/llvm-symbolizer/LLVMSymbolize.cpp =================================================================== --- tools/llvm-symbolizer/LLVMSymbolize.cpp +++ tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -29,6 +29,11 @@ #include #include +#if defined(_MSC_VER) +#include +#include +#endif + namespace llvm { namespace symbolize { @@ -471,8 +476,10 @@ std::unique_ptr Session; PDB_ErrorCode Error = loadDataForEXE(PDB_ReaderType::DIA, Objects.first->getFileName(), Session); - if (Error == PDB_ErrorCode::Success) - Context = new PDBContext(*CoffObject, std::move(Session)); + if (Error == PDB_ErrorCode::Success) { + Context = new PDBContext(*CoffObject, std::move(Session), + Opts.RelativeAddresses); + } } if (!Context) Context = new DWARFContextInMemory(*Objects.second); @@ -522,7 +529,17 @@ free(DemangledName); return Result; #else - return Name; + char DemangledName[1024] = {0}; + DWORD result = ::UnDecorateSymbolName( + Name.c_str(), DemangledName, 1023, + UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected + UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc + UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications + UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers + UNDNAME_NO_MS_KEYWORDS | // Strip all MS extension keywords + UNDNAME_NO_FUNCTION_RETURNS); // Strip function return types + + return (result == 0) ? Name : std::string(DemangledName); #endif } Index: tools/llvm-symbolizer/llvm-symbolizer.cpp =================================================================== --- tools/llvm-symbolizer/llvm-symbolizer.cpp +++ tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -49,8 +49,13 @@ clEnumValEnd)); static cl::opt -ClPrintInlining("inlining", cl::init(true), - cl::desc("Print all inlined frames for a given address")); + ClUseRelativeAddress("relative-address", cl::init(false), + cl::desc("Interpret addresses as relative addresses"), + cl::ReallyHidden); + +static cl::opt + ClPrintInlining("inlining", cl::init(true), + cl::desc("Print all inlined frames for a given address")); static cl::opt ClDemangle("demangle", cl::init(true), cl::desc("Demangle function names")); @@ -127,8 +132,9 @@ llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded); cl::ParseCommandLineOptions(argc, argv, "llvm-symbolizer\n"); - LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions, - ClPrintInlining, ClDemangle, ClDefaultArch); + LLVMSymbolizer::Options Opts(ClPrintFunctions, ClUseSymbolTable, + ClPrintInlining, ClDemangle, + ClUseRelativeAddress, ClDefaultArch); for (const auto &hint : ClDsymHint) { if (sys::path::extension(hint) == ".dSYM") { Opts.DsymHints.push_back(hint);