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