1c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov//===-- LLVMSymbolize.cpp -------------------------------------------------===// 2c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov// 3c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov// The LLVM Compiler Infrastructure 4c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov// 5c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov// This file is distributed under the University of Illinois Open Source 6c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov// License. See LICENSE.TXT for details. 7c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov// 8c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov//===----------------------------------------------------------------------===// 9c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov// 10c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov// Implementation for LLVM symbolization library. 11c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov// 12c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov//===----------------------------------------------------------------------===// 13c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 14c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#include "LLVMSymbolize.h" 1551283a1513648b235925e8f931707ebdea217359Alexey Samsonov#include "llvm/ADT/STLExtras.h" 168228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov#include "llvm/Config/config.h" 1736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Object/ELFObjectFile.h" 18c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#include "llvm/Object/MachO.h" 19c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#include "llvm/Support/Casting.h" 206889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov#include "llvm/Support/Compression.h" 216889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov#include "llvm/Support/DataExtractor.h" 22c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines#include "llvm/Support/Errc.h" 23888ca964a45696a1b3e60940d3c9ad8ae677ef1cAlexey Samsonov#include "llvm/Support/FileSystem.h" 246889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov#include "llvm/Support/MemoryBuffer.h" 25c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#include "llvm/Support/Path.h" 26c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#include <sstream> 278228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov#include <stdlib.h> 28c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 29c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovnamespace llvm { 30c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovnamespace symbolize { 31c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 32c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hinesstatic bool error(std::error_code ec) { 33c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov if (!ec) 34c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov return false; 35b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n"; 36b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov return true; 37b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov} 38b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov 39dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic DILineInfoSpecifier 40dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesgetDILineInfoSpecifier(const LLVMSymbolizer::Options &Opts) { 41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return DILineInfoSpecifier( 42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, 43dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Opts.PrintFunctions); 44c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov} 45c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 46b181919d86bd46fdb6c21d782ccabf754167951aDmitry VyukovModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx) 47c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov : Module(Obj), DebugInfoContext(DICtx) { 4837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines std::unique_ptr<DataExtractor> OpdExtractor; 4937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint64_t OpdAddress = 0; 5037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // Find the .opd (function descriptor) section if any, for big-endian 5137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // PowerPC64 ELF. 5237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (Module->getArch() == Triple::ppc64) { 5337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines for (section_iterator Section : Module->sections()) { 5437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines StringRef Name; 5537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!error(Section->getName(Name)) && Name == ".opd") { 5637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines StringRef Data; 5737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!error(Section->getContents(Data))) { 5837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OpdExtractor.reset(new DataExtractor(Data, Module->isLittleEndian(), 5937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Module->getBytesInAddress())); 6037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OpdAddress = Section->getAddress(); 6137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 6237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines break; 6337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 6437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 6537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (const SymbolRef &Symbol : Module->symbols()) { 6737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines addSymbol(Symbol, OpdExtractor.get(), OpdAddress); 6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool NoSymbolTable = (Module->symbol_begin() == Module->symbol_end()); 7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (NoSymbolTable && Module->isELF()) { 7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Fallback to dynamic symbol table, if regular symbol table is stripped. 7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::pair<symbol_iterator, symbol_iterator> IDyn = 7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines getELFDynamicSymbolIterators(Module); 7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (symbol_iterator si = IDyn.first, se = IDyn.second; si != se; ++si) { 7537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines addSymbol(*si, OpdExtractor.get(), OpdAddress); 7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 77b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov } 78b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov} 79b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov 8037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesvoid ModuleInfo::addSymbol(const SymbolRef &Symbol, DataExtractor *OpdExtractor, 8137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint64_t OpdAddress) { 8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SymbolRef::Type SymbolType; 8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Symbol.getType(SymbolType))) 8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data) 8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t SymbolAddress; 8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Symbol.getAddress(SymbolAddress)) || 8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SymbolAddress == UnknownAddressOrSize) 9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 9137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (OpdExtractor) { 9237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // For big-endian PowerPC64 ELF, symbols in the .opd section refer to 9337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // function descriptors. The first word of the descriptor is a pointer to 9437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // the function's code. 9537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // For the purposes of symbolization, pretend the symbol's address is that 9637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // of the function's code, not the descriptor. 9737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint64_t OpdOffset = SymbolAddress - OpdAddress; 9837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines uint32_t OpdOffset32 = OpdOffset; 9937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (OpdOffset == OpdOffset32 && 10037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OpdExtractor->isValidOffsetForAddress(OpdOffset32)) 10137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SymbolAddress = OpdExtractor->getAddress(&OpdOffset32); 10237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint64_t SymbolSize; 10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Getting symbol size is linear for Mach-O files, so assume that symbol 10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // occupies the memory range up to the following symbol. 10636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (isa<MachOObjectFile>(Module)) 10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SymbolSize = 0; 10836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines else if (error(Symbol.getSize(SymbolSize)) || 10936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SymbolSize == UnknownAddressOrSize) 11036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 11136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringRef SymbolName; 11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (error(Symbol.getName(SymbolName))) 11336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return; 11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Mach-O symbol table names have leading underscore, skip it. 11536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Module->isMachO() && SymbolName.size() > 0 && SymbolName[0] == '_') 11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SymbolName = SymbolName.drop_front(); 11736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // FIXME: If a function has alias, there are two entries in symbol table 11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // with same address size. Make sure we choose the correct one. 11937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects; 12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SymbolDesc SD = { SymbolAddress, SymbolSize }; 12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines M.insert(std::make_pair(SD, SymbolName)); 12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 124b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukovbool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address, 125b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov std::string &Name, uint64_t &Addr, 126b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov uint64_t &Size) const { 12737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const auto &SymbolMap = Type == SymbolRef::ST_Function ? Functions : Objects; 12837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (SymbolMap.empty()) 129b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov return false; 130888ca964a45696a1b3e60940d3c9ad8ae677ef1cAlexey Samsonov SymbolDesc SD = { Address, Address }; 13137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines auto SymbolIterator = SymbolMap.upper_bound(SD); 13237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (SymbolIterator == SymbolMap.begin()) 133b6564648a5d1601bef26a1eb3c9ef04ee1d1745fAlexey Samsonov return false; 13437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines --SymbolIterator; 13537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (SymbolIterator->first.Size != 0 && 13637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SymbolIterator->first.Addr + SymbolIterator->first.Size <= Address) 137b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov return false; 13837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Name = SymbolIterator->second.str(); 13937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Addr = SymbolIterator->first.Addr; 14037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Size = SymbolIterator->first.Size; 141b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov return true; 142b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov} 143b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov 144c4439c3508aa705add9dc46106270f0b3763b882Alexey SamsonovDILineInfo ModuleInfo::symbolizeCode( 145c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const { 146c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov DILineInfo LineInfo; 147c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov if (DebugInfoContext) { 148c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov LineInfo = DebugInfoContext->getLineInfoForAddress( 149dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ModuleOffset, getDILineInfoSpecifier(Opts)); 150c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 151c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov // Override function name from symbol table if necessary. 152dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Opts.PrintFunctions != FunctionNameKind::None && Opts.UseSymbolTable) { 153c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov std::string FunctionName; 154c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov uint64_t Start, Size; 155c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset, 156c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov FunctionName, Start, Size)) { 157dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LineInfo.FunctionName = FunctionName; 158c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 159c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 160c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov return LineInfo; 161c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov} 162c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 163c4439c3508aa705add9dc46106270f0b3763b882Alexey SamsonovDIInliningInfo ModuleInfo::symbolizeInlinedCode( 164c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const { 165c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov DIInliningInfo InlinedContext; 166c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov if (DebugInfoContext) { 167c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov InlinedContext = DebugInfoContext->getInliningInfoForAddress( 168dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ModuleOffset, getDILineInfoSpecifier(Opts)); 169c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 170c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov // Make sure there is at least one frame in context. 171c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov if (InlinedContext.getNumberOfFrames() == 0) { 172c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov InlinedContext.addFrame(DILineInfo()); 173c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 174c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov // Override the function name in lower frame with name from symbol table. 175dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Opts.PrintFunctions != FunctionNameKind::None && Opts.UseSymbolTable) { 176c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov DIInliningInfo PatchedInlinedContext; 177c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) { 178c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov DILineInfo LineInfo = InlinedContext.getFrame(i); 179c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov if (i == n - 1) { 180c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov std::string FunctionName; 181c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov uint64_t Start, Size; 182c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset, 183c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov FunctionName, Start, Size)) { 184dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines LineInfo.FunctionName = FunctionName; 185c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 186c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 187c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov PatchedInlinedContext.addFrame(LineInfo); 188c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 189c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov InlinedContext = PatchedInlinedContext; 190c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 191c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov return InlinedContext; 192c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov} 193c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 194c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovbool ModuleInfo::symbolizeData(uint64_t ModuleOffset, std::string &Name, 195c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov uint64_t &Start, uint64_t &Size) const { 196c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov return getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Name, Start, 197c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov Size); 198c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov} 199c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 200638c63ccf74807bbbff444d527a0acad592b3802Alexey Samsonovconst char LLVMSymbolizer::kBadString[] = "??"; 201c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 202c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovstd::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, 203c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov uint64_t ModuleOffset) { 204c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov ModuleInfo *Info = getOrCreateModuleInfo(ModuleName); 205dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!Info) 206c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov return printDILineInfo(DILineInfo()); 207c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov if (Opts.PrintInlining) { 208c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov DIInliningInfo InlinedContext = 209c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov Info->symbolizeInlinedCode(ModuleOffset, Opts); 210c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov uint32_t FramesNum = InlinedContext.getNumberOfFrames(); 211c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov assert(FramesNum > 0); 212c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov std::string Result; 213c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov for (uint32_t i = 0; i < FramesNum; i++) { 214c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov DILineInfo LineInfo = InlinedContext.getFrame(i); 215c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov Result += printDILineInfo(LineInfo); 216c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 217c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov return Result; 218c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 219c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts); 220c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov return printDILineInfo(LineInfo); 221c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov} 222c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 223c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovstd::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName, 224c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov uint64_t ModuleOffset) { 225c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov std::string Name = kBadString; 226c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov uint64_t Start = 0; 227c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov uint64_t Size = 0; 228c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov if (Opts.UseSymbolTable) { 229c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) { 230c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov if (Info->symbolizeData(ModuleOffset, Name, Start, Size) && Opts.Demangle) 23136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Name = DemangleName(Name); 232c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 233c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 234c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov std::stringstream ss; 235c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov ss << Name << "\n" << Start << " " << Size << "\n"; 236c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov return ss.str(); 237c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov} 238c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 239e9e10d18df7ba3ec65c37eaa25131fbd5c1b130eDmitry Vyukovvoid LLVMSymbolizer::flush() { 24051283a1513648b235925e8f931707ebdea217359Alexey Samsonov DeleteContainerSeconds(Modules); 24137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ObjectPairForPathArch.clear(); 2420ed872cdd1e5d7d60983854ea49aff13aa3280c1Alexey Samsonov ObjectFileForArch.clear(); 243e9e10d18df7ba3ec65c37eaa25131fbd5c1b130eDmitry Vyukov} 244e9e10d18df7ba3ec65c37eaa25131fbd5c1b130eDmitry Vyukov 24537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// For Path="/path/to/foo" and Basename="foo" assume that debug info is in 24637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// /path/to/foo.dSYM/Contents/Resources/DWARF/foo. 24737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in 24837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// /path/to/bar.dSYM/Contents/Resources/DWARF/foo. 24937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic 25037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstd::string getDarwinDWARFResourceForPath( 25137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const std::string &Path, const std::string &Basename) { 25237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SmallString<16> ResourceName = StringRef(Path); 25337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (sys::path::extension(Path) != ".dSYM") { 25437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ResourceName += ".dSYM"; 25537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 256c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov sys::path::append(ResourceName, "Contents", "Resources", "DWARF"); 257c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov sys::path::append(ResourceName, Basename); 258c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov return ResourceName.str(); 259c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov} 260c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 2616889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonovstatic bool checkFileCRC(StringRef Path, uint32_t CRCHash) { 262c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines ErrorOr<std::unique_ptr<MemoryBuffer>> MB = 263c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines MemoryBuffer::getFileOrSTDIN(Path); 264c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (!MB) 2656889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov return false; 266c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines return !zlib::isAvailable() || CRCHash == zlib::crc32(MB.get()->getBuffer()); 2676889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov} 2686889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov 2696889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonovstatic bool findDebugBinary(const std::string &OrigPath, 2706889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov const std::string &DebuglinkName, uint32_t CRCHash, 2716889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov std::string &Result) { 2728228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov std::string OrigRealPath = OrigPath; 2738228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov#if defined(HAVE_REALPATH) 274dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (char *RP = realpath(OrigPath.c_str(), nullptr)) { 2758228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov OrigRealPath = RP; 2768228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov free(RP); 2778228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov } 2788228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov#endif 2798228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov SmallString<16> OrigDir(OrigRealPath); 2806889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov llvm::sys::path::remove_filename(OrigDir); 2816889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov SmallString<16> DebugPath = OrigDir; 2826889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov // Try /path/to/original_binary/debuglink_name 2836889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov llvm::sys::path::append(DebugPath, DebuglinkName); 2846889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov if (checkFileCRC(DebugPath, CRCHash)) { 2856889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov Result = DebugPath.str(); 2866889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov return true; 2876889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov } 2886889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov // Try /path/to/original_binary/.debug/debuglink_name 2898228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov DebugPath = OrigRealPath; 2906889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov llvm::sys::path::append(DebugPath, ".debug", DebuglinkName); 2916889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov if (checkFileCRC(DebugPath, CRCHash)) { 2926889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov Result = DebugPath.str(); 2936889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov return true; 2946889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov } 2956889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov // Try /usr/lib/debug/path/to/original_binary/debuglink_name 2966889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov DebugPath = "/usr/lib/debug"; 2976889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir), 2986889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov DebuglinkName); 2996889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov if (checkFileCRC(DebugPath, CRCHash)) { 3006889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov Result = DebugPath.str(); 3016889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov return true; 3026889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov } 3036889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov return false; 3046889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov} 3056889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov 30637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName, 3076889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov uint32_t &CRCHash) { 3086889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov if (!Obj) 3096889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov return false; 31036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (const SectionRef &Section : Obj->sections()) { 3116889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov StringRef Name; 31236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Section.getName(Name); 3136889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov Name = Name.substr(Name.find_first_not_of("._")); 3146889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov if (Name == "gnu_debuglink") { 3156889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov StringRef Data; 31636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Section.getContents(Data); 3176889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov DataExtractor DE(Data, Obj->isLittleEndian(), 0); 3186889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov uint32_t Offset = 0; 3196889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov if (const char *DebugNameStr = DE.getCStr(&Offset)) { 3206889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov // 4-byte align the offset. 3216889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov Offset = (Offset + 3) & ~0x3; 3226889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov if (DE.isValidOffsetForDataOfSize(Offset, 4)) { 3236889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov DebugName = DebugNameStr; 3246889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov CRCHash = DE.getU32(&Offset); 3256889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov return true; 3266889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov } 3276889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov } 3286889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov break; 3296889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov } 3306889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov } 3316889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov return false; 3326889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov} 3336889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov 33437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic 33537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj, 33637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const MachOObjectFile *Obj) { 33737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid(); 33837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ArrayRef<uint8_t> bin_uuid = Obj->getUuid(); 33937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (dbg_uuid.empty() || bin_uuid.empty()) 34037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return false; 34137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size()); 34237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 34337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 34437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath, 34537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const MachOObjectFile *MachExeObj, const std::string &ArchName) { 34637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // On Darwin we may find DWARF in separate object file in 34737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines // resource directory. 34837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines std::vector<std::string> DsymPaths; 34937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines StringRef Filename = sys::path::filename(ExePath); 35037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DsymPaths.push_back(getDarwinDWARFResourceForPath(ExePath, Filename)); 35137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines for (const auto &Path : Opts.DsymHints) { 35237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DsymPaths.push_back(getDarwinDWARFResourceForPath(Path, Filename)); 35337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 35437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines for (const auto &path : DsymPaths) { 35537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(path); 35637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines std::error_code EC = BinaryOrErr.getError(); 35737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (EC != errc::no_such_file_or_directory && !error(EC)) { 35837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OwningBinary<Binary> B = std::move(BinaryOrErr.get()); 35937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ObjectFile *DbgObj = 36037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines getObjectFileFromBinary(B.getBinary(), ArchName); 36137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const MachOObjectFile *MachDbgObj = 36237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines dyn_cast<const MachOObjectFile>(DbgObj); 36337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!MachDbgObj) continue; 36437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj)) { 36537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines addOwningBinary(std::move(B)); 36637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return DbgObj; 36737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 36837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 36937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 37037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return nullptr; 37137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} 37237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 37337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesLLVMSymbolizer::ObjectPair 37437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesLLVMSymbolizer::getOrCreateObjects(const std::string &Path, 37537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const std::string &ArchName) { 37637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName)); 37737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (I != ObjectPairForPathArch.end()) 3788175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov return I->second; 37937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ObjectFile *Obj = nullptr; 38037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ObjectFile *DbgObj = nullptr; 38137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(Path); 38236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!error(BinaryOrErr.getError())) { 38337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OwningBinary<Binary> &B = BinaryOrErr.get(); 38437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines Obj = getObjectFileFromBinary(B.getBinary(), ArchName); 38537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!Obj) { 38637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ObjectPair Res = std::make_pair(nullptr, nullptr); 38737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res; 38837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines return Res; 3898175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov } 39037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines addOwningBinary(std::move(B)); 39137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (auto MachObj = dyn_cast<const MachOObjectFile>(Obj)) 39237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DbgObj = lookUpDsymFile(Path, MachObj, ArchName); 3936889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov // Try to locate the debug binary using .gnu_debuglink section. 39437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!DbgObj) { 3956889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov std::string DebuglinkName; 3966889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov uint32_t CRCHash; 3976889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov std::string DebugBinaryPath; 39837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash) && 39936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) { 40036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines BinaryOrErr = createBinary(DebugBinaryPath); 40136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (!error(BinaryOrErr.getError())) { 40237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OwningBinary<Binary> B = std::move(BinaryOrErr.get()); 40337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DbgObj = getObjectFileFromBinary(B.getBinary(), ArchName); 40437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines addOwningBinary(std::move(B)); 40536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 4066889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov } 4076889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov } 4088175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov } 40937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!DbgObj) 41037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DbgObj = Obj; 41137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ObjectPair Res = std::make_pair(Obj, DbgObj); 41237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res; 4138175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov return Res; 4148175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov} 4158175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov 4168175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey SamsonovObjectFile * 41737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesLLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, 41837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const std::string &ArchName) { 419dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!Bin) 420dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 421dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ObjectFile *Res = nullptr; 4228175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) { 42337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const auto &I = ObjectFileForArch.find( 4248175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov std::make_pair(UB, ArchName)); 4258175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov if (I != ObjectFileForArch.end()) 4268175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov return I->second; 427c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines ErrorOr<std::unique_ptr<ObjectFile>> ParsedObj = 428c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines UB->getObjectForArch(Triple(ArchName).getArch()); 429c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (ParsedObj) { 430c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines Res = ParsedObj.get().get(); 431c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines ParsedBinariesAndObjects.push_back(std::move(ParsedObj.get())); 4328175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov } 4338175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov ObjectFileForArch[std::make_pair(UB, ArchName)] = Res; 4348175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov } else if (Bin->isObject()) { 4358175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov Res = cast<ObjectFile>(Bin); 4368175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov } 4378175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov return Res; 4388175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov} 4398175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov 440c4439c3508aa705add9dc46106270f0b3763b882Alexey SamsonovModuleInfo * 441c4439c3508aa705add9dc46106270f0b3763b882Alexey SamsonovLLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { 44237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines const auto &I = Modules.find(ModuleName); 443c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov if (I != Modules.end()) 444c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov return I->second; 4458175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov std::string BinaryName = ModuleName; 4468175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov std::string ArchName = Opts.DefaultArch; 447df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov size_t ColonPos = ModuleName.find_last_of(':'); 448df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov // Verify that substring after colon form a valid arch name. 4498175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov if (ColonPos != std::string::npos) { 450df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov std::string ArchStr = ModuleName.substr(ColonPos + 1); 4511e65bf2628233e98f2406ec7acc901cd3b504915NAKAMURA Takumi if (Triple(ArchStr).getArch() != Triple::UnknownArch) { 452df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov BinaryName = ModuleName.substr(0, ColonPos); 453df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov ArchName = ArchStr; 454df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov } 4558175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov } 45637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ObjectPair Objects = getOrCreateObjects(BinaryName, ArchName); 457c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 45837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (!Objects.first) { 4598175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov // Failed to find valid object file. 460dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Modules.insert(make_pair(ModuleName, (ModuleInfo *)nullptr)); 461dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return nullptr; 462c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 46337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines DIContext *Context = DIContext::getDWARFContext(*Objects.second); 4648175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov assert(Context); 46537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ModuleInfo *Info = new ModuleInfo(Objects.first, Context); 466c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov Modules.insert(make_pair(ModuleName, Info)); 467c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov return Info; 468c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov} 469c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 470c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovstd::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const { 471c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov // By default, DILineInfo contains "<invalid>" for function/filename it 472c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov // cannot fetch. We replace it to "??" to make our output closer to addr2line. 473c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov static const std::string kDILineInfoBadString = "<invalid>"; 474c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov std::stringstream Result; 475dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (Opts.PrintFunctions != FunctionNameKind::None) { 476dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::string FunctionName = LineInfo.FunctionName; 477c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov if (FunctionName == kDILineInfoBadString) 478c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov FunctionName = kBadString; 479c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov else if (Opts.Demangle) 480c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov FunctionName = DemangleName(FunctionName); 481c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov Result << FunctionName << "\n"; 482c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov } 483dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::string Filename = LineInfo.FileName; 484c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov if (Filename == kDILineInfoBadString) 485c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov Filename = kBadString; 486dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Result << Filename << ":" << LineInfo.Line << ":" << LineInfo.Column << "\n"; 487c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov return Result.str(); 488c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov} 489c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 490c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#if !defined(_MSC_VER) 491c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov// Assume that __cxa_demangle is provided by libcxxabi (except for Windows). 492c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovextern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer, 493c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov size_t *length, int *status); 494c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#endif 495c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 496c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonovstd::string LLVMSymbolizer::DemangleName(const std::string &Name) { 497c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#if !defined(_MSC_VER) 49836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // We can spoil names of symbols with C linkage, so use an heuristic 49936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // approach to check if the name should be demangled. 50036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (Name.substr(0, 2) != "_Z") 50136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return Name; 502c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov int status = 0; 503dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines char *DemangledName = __cxa_demangle(Name.c_str(), nullptr, nullptr, &status); 504c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov if (status != 0) 505c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov return Name; 506c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov std::string Result = DemangledName; 507c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov free(DemangledName); 508c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov return Result; 509c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov#else 510c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov return Name; 511c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#endif 512c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov} 513c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov 514c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov} // namespace symbolize 515c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov} // namespace llvm 516