blob: c633c894a44e90825e133b484c9f32ec438a3ac6 [file] [log] [blame]
Stephen Hinesc6ca60f2023-05-09 02:19:22 -07001//===- Symbolize.h ----------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Header for LLVM symbolization library.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H
14#define LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H
15
16#include "llvm/ADT/StringMap.h"
17#include "llvm/ADT/ilist_node.h"
18#include "llvm/ADT/simple_ilist.h"
19#include "llvm/DebugInfo/DIContext.h"
20#include "llvm/Object/Binary.h"
21#include "llvm/Object/BuildID.h"
22#include "llvm/Support/Error.h"
23#include <algorithm>
24#include <cstdint>
25#include <map>
26#include <memory>
27#include <string>
28#include <utility>
29#include <vector>
30
31namespace llvm {
32namespace object {
33class ELFObjectFileBase;
34class MachOObjectFile;
35class ObjectFile;
36struct SectionedAddress;
37} // namespace object
38
39namespace symbolize {
40
41class SymbolizableModule;
42
43using namespace object;
44
45using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
46using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
47
48class CachedBinary;
49
50class LLVMSymbolizer {
51public:
52 struct Options {
53 FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName;
54 FileLineInfoKind PathStyle = FileLineInfoKind::AbsoluteFilePath;
55 bool UseSymbolTable = true;
56 bool Demangle = true;
57 bool RelativeAddresses = false;
58 bool UntagAddresses = false;
59 bool UseDIA = false;
60 std::string DefaultArch;
61 std::vector<std::string> DsymHints;
62 std::string FallbackDebugPath;
63 std::string DWPName;
64 std::vector<std::string> DebugFileDirectory;
65 size_t MaxCacheSize =
66 sizeof(size_t) == 4
67 ? 512 * 1024 * 1024 /* 512 MiB */
68 : static_cast<size_t>(4ULL * 1024 * 1024 * 1024) /* 4 GiB */;
69 };
70
71 LLVMSymbolizer();
72 LLVMSymbolizer(const Options &Opts);
73
74 ~LLVMSymbolizer();
75
76 // Overloads accepting ObjectFile does not support COFF currently
77 Expected<DILineInfo> symbolizeCode(const ObjectFile &Obj,
78 object::SectionedAddress ModuleOffset);
79 Expected<DILineInfo> symbolizeCode(const std::string &ModuleName,
80 object::SectionedAddress ModuleOffset);
81 Expected<DILineInfo> symbolizeCode(ArrayRef<uint8_t> BuildID,
82 object::SectionedAddress ModuleOffset);
83 Expected<DIInliningInfo>
84 symbolizeInlinedCode(const ObjectFile &Obj,
85 object::SectionedAddress ModuleOffset);
86 Expected<DIInliningInfo>
87 symbolizeInlinedCode(const std::string &ModuleName,
88 object::SectionedAddress ModuleOffset);
89 Expected<DIInliningInfo>
90 symbolizeInlinedCode(ArrayRef<uint8_t> BuildID,
91 object::SectionedAddress ModuleOffset);
92
93 Expected<DIGlobal> symbolizeData(const ObjectFile &Obj,
94 object::SectionedAddress ModuleOffset);
95 Expected<DIGlobal> symbolizeData(const std::string &ModuleName,
96 object::SectionedAddress ModuleOffset);
97 Expected<DIGlobal> symbolizeData(ArrayRef<uint8_t> BuildID,
98 object::SectionedAddress ModuleOffset);
99 Expected<std::vector<DILocal>>
100 symbolizeFrame(const ObjectFile &Obj, object::SectionedAddress ModuleOffset);
101 Expected<std::vector<DILocal>>
102 symbolizeFrame(const std::string &ModuleName,
103 object::SectionedAddress ModuleOffset);
104 Expected<std::vector<DILocal>>
105 symbolizeFrame(ArrayRef<uint8_t> BuildID,
106 object::SectionedAddress ModuleOffset);
107 void flush();
108
109 // Evict entries from the binary cache until it is under the maximum size
110 // given in the options. Calling this invalidates references in the DI...
111 // objects returned by the methods above.
112 void pruneCache();
113
114 static std::string
115 DemangleName(const std::string &Name,
116 const SymbolizableModule *DbiModuleDescriptor);
117
118 void setBuildIDFetcher(std::unique_ptr<BuildIDFetcher> Fetcher) {
119 BIDFetcher = std::move(Fetcher);
120 }
121
122private:
123 // Bundles together object file with code/data and object file with
124 // corresponding debug info. These objects can be the same.
125 using ObjectPair = std::pair<const ObjectFile *, const ObjectFile *>;
126
127 template <typename T>
128 Expected<DILineInfo>
129 symbolizeCodeCommon(const T &ModuleSpecifier,
130 object::SectionedAddress ModuleOffset);
131 template <typename T>
132 Expected<DIInliningInfo>
133 symbolizeInlinedCodeCommon(const T &ModuleSpecifier,
134 object::SectionedAddress ModuleOffset);
135 template <typename T>
136 Expected<DIGlobal> symbolizeDataCommon(const T &ModuleSpecifier,
137 object::SectionedAddress ModuleOffset);
138 template <typename T>
139 Expected<std::vector<DILocal>>
140 symbolizeFrameCommon(const T &ModuleSpecifier,
141 object::SectionedAddress ModuleOffset);
142
143 /// Returns a SymbolizableModule or an error if loading debug info failed.
144 /// Only one attempt is made to load a module, and errors during loading are
145 /// only reported once. Subsequent calls to get module info for a module that
146 /// failed to load will return nullptr.
147 Expected<SymbolizableModule *>
148 getOrCreateModuleInfo(const std::string &ModuleName);
149 Expected<SymbolizableModule *> getOrCreateModuleInfo(const ObjectFile &Obj);
150
151 /// Returns a SymbolizableModule or an error if loading debug info failed.
152 /// Unlike the above, errors are reported each time, since they are more
153 /// likely to be transient.
154 Expected<SymbolizableModule *>
155 getOrCreateModuleInfo(ArrayRef<uint8_t> BuildID);
156
157 Expected<SymbolizableModule *>
158 createModuleInfo(const ObjectFile *Obj, std::unique_ptr<DIContext> Context,
159 StringRef ModuleName);
160
161 ObjectFile *lookUpDsymFile(const std::string &Path,
162 const MachOObjectFile *ExeObj,
163 const std::string &ArchName);
164 ObjectFile *lookUpDebuglinkObject(const std::string &Path,
165 const ObjectFile *Obj,
166 const std::string &ArchName);
167 ObjectFile *lookUpBuildIDObject(const std::string &Path,
168 const ELFObjectFileBase *Obj,
169 const std::string &ArchName);
170
171 bool findDebugBinary(const std::string &OrigPath,
172 const std::string &DebuglinkName, uint32_t CRCHash,
173 std::string &Result);
174
175 bool getOrFindDebugBinary(const ArrayRef<uint8_t> BuildID,
176 std::string &Result);
177
178 /// Returns pair of pointers to object and debug object.
179 Expected<ObjectPair> getOrCreateObjectPair(const std::string &Path,
180 const std::string &ArchName);
181
182 /// Return a pointer to object file at specified path, for a specified
183 /// architecture (e.g. if path refers to a Mach-O universal binary, only one
184 /// object file from it will be returned).
185 Expected<ObjectFile *> getOrCreateObject(const std::string &Path,
186 const std::string &ArchName);
187
188 /// Update the LRU cache order when a binary is accessed.
189 void recordAccess(CachedBinary &Bin);
190
191 std::map<std::string, std::unique_ptr<SymbolizableModule>, std::less<>>
192 Modules;
193 StringMap<std::string> BuildIDPaths;
194
195 /// Contains cached results of getOrCreateObjectPair().
196 std::map<std::pair<std::string, std::string>, ObjectPair>
197 ObjectPairForPathArch;
198
199 /// Contains parsed binary for each path, or parsing error.
200 std::map<std::string, CachedBinary> BinaryForPath;
201
202 /// A list of cached binaries in LRU order.
203 simple_ilist<CachedBinary> LRUBinaries;
204 /// Sum of the sizes of the cached binaries.
205 size_t CacheSize = 0;
206
207 /// Parsed object file for path/architecture pair, where "path" refers
208 /// to Mach-O universal binary.
209 std::map<std::pair<std::string, std::string>, std::unique_ptr<ObjectFile>>
210 ObjectForUBPathAndArch;
211
212 Options Opts;
213
214 std::unique_ptr<BuildIDFetcher> BIDFetcher;
215};
216
217// A binary intrusively linked into a LRU cache list. If the binary is empty,
218// then the entry marks that an error occurred, and it is not part of the LRU
219// list.
220class CachedBinary : public ilist_node<CachedBinary> {
221public:
222 CachedBinary() = default;
223 CachedBinary(OwningBinary<Binary> Bin) : Bin(std::move(Bin)) {}
224
225 OwningBinary<Binary> &operator*() { return Bin; }
226 OwningBinary<Binary> *operator->() { return &Bin; }
227
228 // Add an action to be performed when the binary is evicted, before all
229 // previously registered evictors.
230 void pushEvictor(std::function<void()> Evictor);
231
232 // Run all registered evictors in the reverse of the order in which they were
233 // added.
234 void evict() {
235 if (Evictor)
236 Evictor();
237 }
238
239 size_t size() { return Bin.getBinary()->getData().size(); }
240
241private:
242 OwningBinary<Binary> Bin;
243 std::function<void()> Evictor;
244};
245
246} // end namespace symbolize
247} // end namespace llvm
248
249#endif // LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H