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