LLVMSymbolize.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
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"
22888ca964a45696a1b3e60940d3c9ad8ae677ef1cAlexey Samsonov#include "llvm/Support/FileSystem.h"
236889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov#include "llvm/Support/MemoryBuffer.h"
24c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#include "llvm/Support/Path.h"
25c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#include <sstream>
268228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov#include <stdlib.h>
27c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
28c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovnamespace llvm {
29c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovnamespace symbolize {
30c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
31b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukovstatic bool error(error_code ec) {
32c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov  if (!ec)
33c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov    return false;
34b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov  errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
35b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov  return true;
36b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov}
37b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov
38c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonovstatic uint32_t
39c4439c3508aa705add9dc46106270f0b3763b882Alexey SamsonovgetDILineInfoSpecifierFlags(const LLVMSymbolizer::Options &Opts) {
40c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo |
41c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov                   llvm::DILineInfoSpecifier::AbsoluteFilePath;
42c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (Opts.PrintFunctions)
43c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    Flags |= llvm::DILineInfoSpecifier::FunctionName;
44c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  return Flags;
45c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov}
46c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
47c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovstatic void patchFunctionNameInDILineInfo(const std::string &NewFunctionName,
48c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov                                          DILineInfo &LineInfo) {
49c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  std::string FileName = LineInfo.getFileName();
50c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName),
51c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov                        LineInfo.getLine(), LineInfo.getColumn());
52c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov}
53c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
54b181919d86bd46fdb6c21d782ccabf754167951aDmitry VyukovModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
55c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov    : Module(Obj), DebugInfoContext(DICtx) {
5636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const SymbolRef &Symbol : Module->symbols()) {
5736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    addSymbol(Symbol);
5836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool NoSymbolTable = (Module->symbol_begin() == Module->symbol_end());
6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (NoSymbolTable && Module->isELF()) {
6136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Fallback to dynamic symbol table, if regular symbol table is stripped.
6236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::pair<symbol_iterator, symbol_iterator> IDyn =
6336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        getELFDynamicSymbolIterators(Module);
6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (symbol_iterator si = IDyn.first, se = IDyn.second; si != se; ++si) {
6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      addSymbol(*si);
6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
67b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov  }
68b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov}
69b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov
7036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesvoid ModuleInfo::addSymbol(const SymbolRef &Symbol) {
7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  SymbolRef::Type SymbolType;
7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (error(Symbol.getType(SymbolType)))
7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return;
7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data)
7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return;
7636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uint64_t SymbolAddress;
7736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (error(Symbol.getAddress(SymbolAddress)) ||
7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      SymbolAddress == UnknownAddressOrSize)
7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return;
8036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  uint64_t SymbolSize;
8136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Getting symbol size is linear for Mach-O files, so assume that symbol
8236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // occupies the memory range up to the following symbol.
8336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (isa<MachOObjectFile>(Module))
8436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    SymbolSize = 0;
8536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  else if (error(Symbol.getSize(SymbolSize)) ||
8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines           SymbolSize == UnknownAddressOrSize)
8736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return;
8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  StringRef SymbolName;
8936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (error(Symbol.getName(SymbolName)))
9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return;
9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // Mach-O symbol table names have leading underscore, skip it.
9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (Module->isMachO() && SymbolName.size() > 0 && SymbolName[0] == '_')
9336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    SymbolName = SymbolName.drop_front();
9436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // FIXME: If a function has alias, there are two entries in symbol table
9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // with same address size. Make sure we choose the correct one.
9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  SymbolMapTy &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  SymbolDesc SD = { SymbolAddress, SymbolSize };
9836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  M.insert(std::make_pair(SD, SymbolName));
9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
10036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
101b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukovbool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
102b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov                                        std::string &Name, uint64_t &Addr,
103b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov                                        uint64_t &Size) const {
104c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov  const SymbolMapTy &M = Type == SymbolRef::ST_Function ? Functions : Objects;
105888ca964a45696a1b3e60940d3c9ad8ae677ef1cAlexey Samsonov  if (M.empty())
106b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov    return false;
107888ca964a45696a1b3e60940d3c9ad8ae677ef1cAlexey Samsonov  SymbolDesc SD = { Address, Address };
108888ca964a45696a1b3e60940d3c9ad8ae677ef1cAlexey Samsonov  SymbolMapTy::const_iterator it = M.upper_bound(SD);
109b6564648a5d1601bef26a1eb3c9ef04ee1d1745fAlexey Samsonov  if (it == M.begin())
110b6564648a5d1601bef26a1eb3c9ef04ee1d1745fAlexey Samsonov    return false;
111888ca964a45696a1b3e60940d3c9ad8ae677ef1cAlexey Samsonov  --it;
112b6564648a5d1601bef26a1eb3c9ef04ee1d1745fAlexey Samsonov  if (it->first.Size != 0 && it->first.Addr + it->first.Size <= Address)
113b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov    return false;
114b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov  Name = it->second.str();
115b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov  Addr = it->first.Addr;
116b6564648a5d1601bef26a1eb3c9ef04ee1d1745fAlexey Samsonov  Size = it->first.Size;
117b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov  return true;
118b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov}
119b181919d86bd46fdb6c21d782ccabf754167951aDmitry Vyukov
120c4439c3508aa705add9dc46106270f0b3763b882Alexey SamsonovDILineInfo ModuleInfo::symbolizeCode(
121c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov    uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
122c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  DILineInfo LineInfo;
123c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (DebugInfoContext) {
124c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    LineInfo = DebugInfoContext->getLineInfoForAddress(
125c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov        ModuleOffset, getDILineInfoSpecifierFlags(Opts));
126c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  }
127c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  // Override function name from symbol table if necessary.
128c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (Opts.PrintFunctions && Opts.UseSymbolTable) {
129c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    std::string FunctionName;
130c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    uint64_t Start, Size;
131c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov    if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
132c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov                               FunctionName, Start, Size)) {
133c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov      patchFunctionNameInDILineInfo(FunctionName, LineInfo);
134c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    }
135c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  }
136c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  return LineInfo;
137c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov}
138c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
139c4439c3508aa705add9dc46106270f0b3763b882Alexey SamsonovDIInliningInfo ModuleInfo::symbolizeInlinedCode(
140c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov    uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
141c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  DIInliningInfo InlinedContext;
142c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (DebugInfoContext) {
143c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    InlinedContext = DebugInfoContext->getInliningInfoForAddress(
144c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov        ModuleOffset, getDILineInfoSpecifierFlags(Opts));
145c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  }
146c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  // Make sure there is at least one frame in context.
147c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (InlinedContext.getNumberOfFrames() == 0) {
148c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    InlinedContext.addFrame(DILineInfo());
149c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  }
150c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  // Override the function name in lower frame with name from symbol table.
151c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (Opts.PrintFunctions && Opts.UseSymbolTable) {
152c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    DIInliningInfo PatchedInlinedContext;
153c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov    for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {
154c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov      DILineInfo LineInfo = InlinedContext.getFrame(i);
155c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov      if (i == n - 1) {
156c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov        std::string FunctionName;
157c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov        uint64_t Start, Size;
158c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov        if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
159c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov                                   FunctionName, Start, Size)) {
160c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov          patchFunctionNameInDILineInfo(FunctionName, LineInfo);
161c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov        }
162c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov      }
163c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov      PatchedInlinedContext.addFrame(LineInfo);
164c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    }
165c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    InlinedContext = PatchedInlinedContext;
166c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  }
167c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  return InlinedContext;
168c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov}
169c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
170c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovbool ModuleInfo::symbolizeData(uint64_t ModuleOffset, std::string &Name,
171c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov                               uint64_t &Start, uint64_t &Size) const {
172c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov  return getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Name, Start,
173c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov                                Size);
174c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov}
175c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
176638c63ccf74807bbbff444d527a0acad592b3802Alexey Samsonovconst char LLVMSymbolizer::kBadString[] = "??";
177c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
178c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovstd::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
179c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov                                          uint64_t ModuleOffset) {
180c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
181c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (Info == 0)
182c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    return printDILineInfo(DILineInfo());
183c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (Opts.PrintInlining) {
184c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov    DIInliningInfo InlinedContext =
185c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov        Info->symbolizeInlinedCode(ModuleOffset, Opts);
186c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    uint32_t FramesNum = InlinedContext.getNumberOfFrames();
187c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    assert(FramesNum > 0);
188c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    std::string Result;
189c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    for (uint32_t i = 0; i < FramesNum; i++) {
190c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov      DILineInfo LineInfo = InlinedContext.getFrame(i);
191c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov      Result += printDILineInfo(LineInfo);
192c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    }
193c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    return Result;
194c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  }
195c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts);
196c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  return printDILineInfo(LineInfo);
197c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov}
198c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
199c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovstd::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
200c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov                                          uint64_t ModuleOffset) {
201c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  std::string Name = kBadString;
202c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  uint64_t Start = 0;
203c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  uint64_t Size = 0;
204c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (Opts.UseSymbolTable) {
205c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) {
206c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov      if (Info->symbolizeData(ModuleOffset, Name, Start, Size) && Opts.Demangle)
20736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        Name = DemangleName(Name);
208c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    }
209c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  }
210c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  std::stringstream ss;
211c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  ss << Name << "\n" << Start << " " << Size << "\n";
212c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  return ss.str();
213c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov}
214c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
215e9e10d18df7ba3ec65c37eaa25131fbd5c1b130eDmitry Vyukovvoid LLVMSymbolizer::flush() {
21651283a1513648b235925e8f931707ebdea217359Alexey Samsonov  DeleteContainerSeconds(Modules);
2178175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  DeleteContainerPointers(ParsedBinariesAndObjects);
2180ed872cdd1e5d7d60983854ea49aff13aa3280c1Alexey Samsonov  BinaryForPath.clear();
2190ed872cdd1e5d7d60983854ea49aff13aa3280c1Alexey Samsonov  ObjectFileForArch.clear();
220e9e10d18df7ba3ec65c37eaa25131fbd5c1b130eDmitry Vyukov}
221e9e10d18df7ba3ec65c37eaa25131fbd5c1b130eDmitry Vyukov
2228175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonovstatic std::string getDarwinDWARFResourceForPath(const std::string &Path) {
223c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  StringRef Basename = sys::path::filename(Path);
224c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  const std::string &DSymDirectory = Path + ".dSYM";
225c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  SmallString<16> ResourceName = StringRef(DSymDirectory);
226c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
227c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  sys::path::append(ResourceName, Basename);
228c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  return ResourceName.str();
229c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov}
230c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
2316889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonovstatic bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
23236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<MemoryBuffer> MB;
2336889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  if (MemoryBuffer::getFileOrSTDIN(Path, MB))
2346889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    return false;
2356889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  return !zlib::isAvailable() || CRCHash == zlib::crc32(MB->getBuffer());
2366889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov}
2376889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov
2386889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonovstatic bool findDebugBinary(const std::string &OrigPath,
2396889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov                            const std::string &DebuglinkName, uint32_t CRCHash,
2406889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov                            std::string &Result) {
2418228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov  std::string OrigRealPath = OrigPath;
2428228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov#if defined(HAVE_REALPATH)
2438228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov  if (char *RP = realpath(OrigPath.c_str(), NULL)) {
2448228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov    OrigRealPath = RP;
2458228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov    free(RP);
2468228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov  }
2478228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov#endif
2488228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov  SmallString<16> OrigDir(OrigRealPath);
2496889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  llvm::sys::path::remove_filename(OrigDir);
2506889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  SmallString<16> DebugPath = OrigDir;
2516889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  // Try /path/to/original_binary/debuglink_name
2526889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  llvm::sys::path::append(DebugPath, DebuglinkName);
2536889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  if (checkFileCRC(DebugPath, CRCHash)) {
2546889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    Result = DebugPath.str();
2556889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    return true;
2566889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  }
2576889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  // Try /path/to/original_binary/.debug/debuglink_name
2588228a8dd91fbc4c1443bc3f15847ca8be24094a2Alexey Samsonov  DebugPath = OrigRealPath;
2596889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  llvm::sys::path::append(DebugPath, ".debug", DebuglinkName);
2606889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  if (checkFileCRC(DebugPath, CRCHash)) {
2616889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    Result = DebugPath.str();
2626889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    return true;
2636889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  }
2646889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  // Try /usr/lib/debug/path/to/original_binary/debuglink_name
2656889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  DebugPath = "/usr/lib/debug";
2666889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir),
2676889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov                          DebuglinkName);
2686889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  if (checkFileCRC(DebugPath, CRCHash)) {
2696889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    Result = DebugPath.str();
2706889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    return true;
2716889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  }
2726889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  return false;
2736889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov}
2746889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov
2756889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonovstatic bool getGNUDebuglinkContents(const Binary *Bin, std::string &DebugName,
2766889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov                                    uint32_t &CRCHash) {
2776889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  const ObjectFile *Obj = dyn_cast<ObjectFile>(Bin);
2786889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  if (!Obj)
2796889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    return false;
28036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  for (const SectionRef &Section : Obj->sections()) {
2816889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    StringRef Name;
28236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Section.getName(Name);
2836889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    Name = Name.substr(Name.find_first_not_of("._"));
2846889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    if (Name == "gnu_debuglink") {
2856889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov      StringRef Data;
28636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Section.getContents(Data);
2876889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov      DataExtractor DE(Data, Obj->isLittleEndian(), 0);
2886889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov      uint32_t Offset = 0;
2896889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov      if (const char *DebugNameStr = DE.getCStr(&Offset)) {
2906889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov        // 4-byte align the offset.
2916889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov        Offset = (Offset + 3) & ~0x3;
2926889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov        if (DE.isValidOffsetForDataOfSize(Offset, 4)) {
2936889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov          DebugName = DebugNameStr;
2946889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov          CRCHash = DE.getU32(&Offset);
2956889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov          return true;
2966889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov        }
2976889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov      }
2986889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov      break;
2996889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    }
3006889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  }
3016889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov  return false;
3026889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov}
3036889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov
3048175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey SamsonovLLVMSymbolizer::BinaryPair
3058175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey SamsonovLLVMSymbolizer::getOrCreateBinary(const std::string &Path) {
3068175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  BinaryMapTy::iterator I = BinaryForPath.find(Path);
3078175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  if (I != BinaryForPath.end())
3088175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    return I->second;
3098175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  Binary *Bin = 0;
3108175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  Binary *DbgBin = 0;
31136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  ErrorOr<Binary *> BinaryOrErr = createBinary(Path);
31236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (!error(BinaryOrErr.getError())) {
31336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::unique_ptr<Binary> ParsedBinary(BinaryOrErr.get());
3148175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    // Check if it's a universal binary.
31536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Bin = ParsedBinary.release();
3168175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    ParsedBinariesAndObjects.push_back(Bin);
3178175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    if (Bin->isMachO() || Bin->isMachOUniversalBinary()) {
3188175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov      // On Darwin we may find DWARF in separate object file in
3198175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov      // resource directory.
3208175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov      const std::string &ResourcePath =
3218175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov          getDarwinDWARFResourceForPath(Path);
32236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      BinaryOrErr = createBinary(ResourcePath);
32336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      error_code EC = BinaryOrErr.getError();
32436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (EC != errc::no_such_file_or_directory && !error(EC)) {
32536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        DbgBin = BinaryOrErr.get();
3268175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov        ParsedBinariesAndObjects.push_back(DbgBin);
3278175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov      }
3288175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    }
3296889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    // Try to locate the debug binary using .gnu_debuglink section.
3306889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    if (DbgBin == 0) {
3316889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov      std::string DebuglinkName;
3326889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov      uint32_t CRCHash;
3336889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov      std::string DebugBinaryPath;
3346889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov      if (getGNUDebuglinkContents(Bin, DebuglinkName, CRCHash) &&
33536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) {
33636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        BinaryOrErr = createBinary(DebugBinaryPath);
33736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        if (!error(BinaryOrErr.getError())) {
33836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          DbgBin = BinaryOrErr.get();
33936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines          ParsedBinariesAndObjects.push_back(DbgBin);
34036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        }
3416889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov      }
3426889483ca4bd5f2634c9041aa076aad01ac38b39Alexey Samsonov    }
3438175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  }
3448175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  if (DbgBin == 0)
3458175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    DbgBin = Bin;
3468175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  BinaryPair Res = std::make_pair(Bin, DbgBin);
3478175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  BinaryForPath[Path] = Res;
3488175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  return Res;
3498175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov}
3508175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov
3518175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey SamsonovObjectFile *
3528175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey SamsonovLLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName) {
3538175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  if (Bin == 0)
3548175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    return 0;
3558175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  ObjectFile *Res = 0;
3568175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
3578175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    ObjectFileForArchMapTy::iterator I = ObjectFileForArch.find(
3588175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov        std::make_pair(UB, ArchName));
3598175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    if (I != ObjectFileForArch.end())
3608175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov      return I->second;
36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::unique_ptr<ObjectFile> ParsedObj;
3628175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    if (!UB->getObjectForArch(Triple(ArchName).getArch(), ParsedObj)) {
36336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Res = ParsedObj.release();
3648175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov      ParsedBinariesAndObjects.push_back(Res);
3658175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    }
3668175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    ObjectFileForArch[std::make_pair(UB, ArchName)] = Res;
3678175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  } else if (Bin->isObject()) {
3688175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    Res = cast<ObjectFile>(Bin);
3698175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  }
3708175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  return Res;
3718175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov}
3728175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov
373c4439c3508aa705add9dc46106270f0b3763b882Alexey SamsonovModuleInfo *
374c4439c3508aa705add9dc46106270f0b3763b882Alexey SamsonovLLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
375c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  ModuleMapTy::iterator I = Modules.find(ModuleName);
376c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (I != Modules.end())
377c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    return I->second;
3788175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  std::string BinaryName = ModuleName;
3798175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  std::string ArchName = Opts.DefaultArch;
380df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov  size_t ColonPos = ModuleName.find_last_of(':');
381df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov  // Verify that substring after colon form a valid arch name.
3828175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  if (ColonPos != std::string::npos) {
383df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov    std::string ArchStr = ModuleName.substr(ColonPos + 1);
3841e65bf2628233e98f2406ec7acc901cd3b504915NAKAMURA Takumi    if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
385df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov      BinaryName = ModuleName.substr(0, ColonPos);
386df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov      ArchName = ArchStr;
387df959c70c935fb98cf5adadc3e712d54ca322a85Alexey Samsonov    }
3888175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  }
3898175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  BinaryPair Binaries = getOrCreateBinary(BinaryName);
3908175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  ObjectFile *Obj = getObjectFileFromBinary(Binaries.first, ArchName);
3918175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  ObjectFile *DbgObj = getObjectFileFromBinary(Binaries.second, ArchName);
392c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
393c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (Obj == 0) {
3948175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov    // Failed to find valid object file.
395c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov    Modules.insert(make_pair(ModuleName, (ModuleInfo *)0));
396c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    return 0;
397c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  }
3988175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  DIContext *Context = DIContext::getDWARFContext(DbgObj);
3998175bc3d3bc8567a90b9dd50d68c1423baffd63bAlexey Samsonov  assert(Context);
400c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  ModuleInfo *Info = new ModuleInfo(Obj, Context);
401c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  Modules.insert(make_pair(ModuleName, Info));
402c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  return Info;
403c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov}
404c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
405c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovstd::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const {
406c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  // By default, DILineInfo contains "<invalid>" for function/filename it
407c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  // cannot fetch. We replace it to "??" to make our output closer to addr2line.
408c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  static const std::string kDILineInfoBadString = "<invalid>";
409c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  std::stringstream Result;
410c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (Opts.PrintFunctions) {
411c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    std::string FunctionName = LineInfo.getFunctionName();
412c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    if (FunctionName == kDILineInfoBadString)
413c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov      FunctionName = kBadString;
414c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov    else if (Opts.Demangle)
415c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov      FunctionName = DemangleName(FunctionName);
416c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    Result << FunctionName << "\n";
417c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  }
418c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  std::string Filename = LineInfo.getFileName();
419c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (Filename == kDILineInfoBadString)
420c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov    Filename = kBadString;
421c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov  Result << Filename << ":" << LineInfo.getLine() << ":" << LineInfo.getColumn()
422c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov         << "\n";
423c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  return Result.str();
424c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov}
425c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
426c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#if !defined(_MSC_VER)
427c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov// Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
428c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonovextern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
429c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov                                size_t *length, int *status);
430c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#endif
431c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
432c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonovstd::string LLVMSymbolizer::DemangleName(const std::string &Name) {
433c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#if !defined(_MSC_VER)
43436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // We can spoil names of symbols with C linkage, so use an heuristic
43536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // approach to check if the name should be demangled.
43636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (Name.substr(0, 2) != "_Z")
43736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return Name;
438c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  int status = 0;
439c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  char *DemangledName = __cxa_demangle(Name.c_str(), 0, 0, &status);
440c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  if (status != 0)
441c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov    return Name;
442c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov  std::string Result = DemangledName;
443c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov  free(DemangledName);
444c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov  return Result;
445c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov#else
446c071f89a770d6c66e6b29fdf013fa88454fc0ac6Alexey Samsonov  return Name;
447c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov#endif
448c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov}
449c4c7ea3184335259da63d973acbed2043e8a6523Alexey Samsonov
450c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov} // namespace symbolize
451c4439c3508aa705add9dc46106270f0b3763b882Alexey Samsonov} // namespace llvm
452