aboutsummaryrefslogtreecommitdiffstats
path: root/tools/llvm-symbolizer/LLVMSymbolize.h
blob: c10922133f6ff04a923c14aa4df183956ddfdc56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//===-- LLVMSymbolize.h ----------------------------------------- C++ -----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Header for LLVM symbolization library.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_SYMBOLIZER_LLVMSYMBOLIZE_H
#define LLVM_TOOLS_LLVM_SYMBOLIZER_LLVMSYMBOLIZE_H

#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/DWARF/DIContext.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/MemoryBuffer.h"
#include <map>
#include <memory>
#include <string>

namespace llvm {

typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind;
using namespace object;

namespace symbolize {

class ModuleInfo;

class LLVMSymbolizer {
public:
  struct Options {
    bool UseSymbolTable : 1;
    FunctionNameKind PrintFunctions;
    bool PrintInlining : 1;
    bool Demangle : 1;
    std::string DefaultArch;
    std::vector<std::string> DsymHints;
    Options(bool UseSymbolTable = true,
            FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName,
            bool PrintInlining = true, bool Demangle = true,
            std::string DefaultArch = "")
        : UseSymbolTable(UseSymbolTable),
          PrintFunctions(PrintFunctions), PrintInlining(PrintInlining),
          Demangle(Demangle), DefaultArch(DefaultArch) {}
  };

  LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {}
  ~LLVMSymbolizer() {
    flush();
  }

  // Returns the result of symbolization for module name/offset as
  // a string (possibly containing newlines).
  std::string
  symbolizeCode(const std::string &ModuleName, uint64_t ModuleOffset);
  std::string
  symbolizeData(const std::string &ModuleName, uint64_t ModuleOffset);
  void flush();
  static std::string DemangleName(const std::string &Name);
private:
  typedef std::pair<ObjectFile*, ObjectFile*> ObjectPair;

  ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName);
  ObjectFile *lookUpDsymFile(const std::string &Path, const MachOObjectFile *ExeObj,
                             const std::string &ArchName);

  /// \brief Returns pair of pointers to object and debug object.
  ObjectPair getOrCreateObjects(const std::string &Path,
                                const std::string &ArchName);
  /// \brief Returns a parsed object file for a given architecture in a
  /// universal binary (or the binary itself if it is an object file).
  ObjectFile *getObjectFileFromBinary(Binary *Bin, const std::string &ArchName);

  std::string printDILineInfo(DILineInfo LineInfo) const;

  // Owns all the parsed binaries and object files.
  SmallVector<std::unique_ptr<Binary>, 4> ParsedBinariesAndObjects;
  SmallVector<std::unique_ptr<MemoryBuffer>, 4> MemoryBuffers;
  void addOwningBinary(OwningBinary<Binary> OwningBin) {
    std::unique_ptr<Binary> Bin;
    std::unique_ptr<MemoryBuffer> MemBuf;
    std::tie(Bin, MemBuf) = OwningBin.takeBinary();
    ParsedBinariesAndObjects.push_back(std::move(Bin));
    MemoryBuffers.push_back(std::move(MemBuf));
  }

  // Owns module info objects.
  std::map<std::string, ModuleInfo *> Modules;
  std::map<std::pair<MachOUniversalBinary *, std::string>, ObjectFile *>
      ObjectFileForArch;
  std::map<std::pair<std::string, std::string>, ObjectPair>
      ObjectPairForPathArch;

  Options Opts;
  static const char kBadString[];
};

class ModuleInfo {
public:
  ModuleInfo(ObjectFile *Obj, DIContext *DICtx);

  DILineInfo symbolizeCode(uint64_t ModuleOffset,
                           const LLVMSymbolizer::Options &Opts) const;
  DIInliningInfo symbolizeInlinedCode(
      uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const;
  bool symbolizeData(uint64_t ModuleOffset, std::string &Name, uint64_t &Start,
                     uint64_t &Size) const;

private:
  bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
                              std::string &Name, uint64_t &Addr,
                              uint64_t &Size) const;
  // For big-endian PowerPC64 ELF, OpdAddress is the address of the .opd
  // (function descriptor) section and OpdExtractor refers to its contents.
  void addSymbol(const SymbolRef &Symbol,
                 DataExtractor *OpdExtractor = nullptr,
                 uint64_t OpdAddress = 0);
  ObjectFile *Module;
  std::unique_ptr<DIContext> DebugInfoContext;

  struct SymbolDesc {
    uint64_t Addr;
    // If size is 0, assume that symbol occupies the whole memory range up to
    // the following symbol.
    uint64_t Size;
    friend bool operator<(const SymbolDesc &s1, const SymbolDesc &s2) {
      return s1.Addr < s2.Addr;
    }
  };
  std::map<SymbolDesc, StringRef> Functions;
  std::map<SymbolDesc, StringRef> Objects;
};

} // namespace symbolize
} // namespace llvm

#endif