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