//===- Symbolize.h ----------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Header for LLVM symbolization library. // //===----------------------------------------------------------------------===// #ifndef LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H #define LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H #include "llvm/ADT/StringMap.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/simple_ilist.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/Object/Binary.h" #include "llvm/Object/BuildID.h" #include "llvm/Support/Error.h" #include #include #include #include #include #include #include namespace llvm { namespace object { class ELFObjectFileBase; class MachOObjectFile; class ObjectFile; struct SectionedAddress; } // namespace object namespace symbolize { class SymbolizableModule; using namespace object; using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind; using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind; class CachedBinary; class LLVMSymbolizer { public: struct Options { FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName; FileLineInfoKind PathStyle = FileLineInfoKind::AbsoluteFilePath; bool UseSymbolTable = true; bool Demangle = true; bool RelativeAddresses = false; bool UntagAddresses = false; bool UseDIA = false; std::string DefaultArch; std::vector DsymHints; std::string FallbackDebugPath; std::string DWPName; std::vector DebugFileDirectory; size_t MaxCacheSize = sizeof(size_t) == 4 ? 512 * 1024 * 1024 /* 512 MiB */ : static_cast(4ULL * 1024 * 1024 * 1024) /* 4 GiB */; }; LLVMSymbolizer(); LLVMSymbolizer(const Options &Opts); ~LLVMSymbolizer(); // Overloads accepting ObjectFile does not support COFF currently Expected symbolizeCode(const ObjectFile &Obj, object::SectionedAddress ModuleOffset); Expected symbolizeCode(const std::string &ModuleName, object::SectionedAddress ModuleOffset); Expected symbolizeCode(ArrayRef BuildID, object::SectionedAddress ModuleOffset); Expected symbolizeInlinedCode(const ObjectFile &Obj, object::SectionedAddress ModuleOffset); Expected symbolizeInlinedCode(const std::string &ModuleName, object::SectionedAddress ModuleOffset); Expected symbolizeInlinedCode(ArrayRef BuildID, object::SectionedAddress ModuleOffset); Expected symbolizeData(const ObjectFile &Obj, object::SectionedAddress ModuleOffset); Expected symbolizeData(const std::string &ModuleName, object::SectionedAddress ModuleOffset); Expected symbolizeData(ArrayRef BuildID, object::SectionedAddress ModuleOffset); Expected> symbolizeFrame(const ObjectFile &Obj, object::SectionedAddress ModuleOffset); Expected> symbolizeFrame(const std::string &ModuleName, object::SectionedAddress ModuleOffset); Expected> symbolizeFrame(ArrayRef BuildID, object::SectionedAddress ModuleOffset); Expected> findSymbol(const ObjectFile &Obj, StringRef Symbol, uint64_t Offset); Expected> findSymbol(const std::string &ModuleName, StringRef Symbol, uint64_t Offset); Expected> findSymbol(ArrayRef BuildID, StringRef Symbol, uint64_t Offset); void flush(); // Evict entries from the binary cache until it is under the maximum size // given in the options. Calling this invalidates references in the DI... // objects returned by the methods above. void pruneCache(); static std::string DemangleName(const std::string &Name, const SymbolizableModule *DbiModuleDescriptor); void setBuildIDFetcher(std::unique_ptr Fetcher) { BIDFetcher = std::move(Fetcher); } /// Returns a SymbolizableModule or an error if loading debug info failed. /// Only one attempt is made to load a module, and errors during loading are /// only reported once. Subsequent calls to get module info for a module that /// failed to load will return nullptr. Expected getOrCreateModuleInfo(const std::string &ModuleName); private: // Bundles together object file with code/data and object file with // corresponding debug info. These objects can be the same. using ObjectPair = std::pair; template Expected symbolizeCodeCommon(const T &ModuleSpecifier, object::SectionedAddress ModuleOffset); template Expected symbolizeInlinedCodeCommon(const T &ModuleSpecifier, object::SectionedAddress ModuleOffset); template Expected symbolizeDataCommon(const T &ModuleSpecifier, object::SectionedAddress ModuleOffset); template Expected> symbolizeFrameCommon(const T &ModuleSpecifier, object::SectionedAddress ModuleOffset); template Expected> findSymbolCommon(const T &ModuleSpecifier, StringRef Symbol, uint64_t Offset); Expected getOrCreateModuleInfo(const ObjectFile &Obj); /// Returns a SymbolizableModule or an error if loading debug info failed. /// Unlike the above, errors are reported each time, since they are more /// likely to be transient. Expected getOrCreateModuleInfo(ArrayRef BuildID); Expected createModuleInfo(const ObjectFile *Obj, std::unique_ptr Context, StringRef ModuleName); ObjectFile *lookUpDsymFile(const std::string &Path, const MachOObjectFile *ExeObj, const std::string &ArchName); ObjectFile *lookUpDebuglinkObject(const std::string &Path, const ObjectFile *Obj, const std::string &ArchName); ObjectFile *lookUpBuildIDObject(const std::string &Path, const ELFObjectFileBase *Obj, const std::string &ArchName); bool findDebugBinary(const std::string &OrigPath, const std::string &DebuglinkName, uint32_t CRCHash, std::string &Result); bool getOrFindDebugBinary(const ArrayRef BuildID, std::string &Result); /// Returns pair of pointers to object and debug object. Expected getOrCreateObjectPair(const std::string &Path, const std::string &ArchName); /// Return a pointer to object file at specified path, for a specified /// architecture (e.g. if path refers to a Mach-O universal binary, only one /// object file from it will be returned). Expected getOrCreateObject(const std::string &Path, const std::string &ArchName); /// Update the LRU cache order when a binary is accessed. void recordAccess(CachedBinary &Bin); std::map, std::less<>> Modules; StringMap BuildIDPaths; /// Contains cached results of getOrCreateObjectPair(). std::map, ObjectPair> ObjectPairForPathArch; /// Contains parsed binary for each path, or parsing error. std::map BinaryForPath; /// A list of cached binaries in LRU order. simple_ilist LRUBinaries; /// Sum of the sizes of the cached binaries. size_t CacheSize = 0; /// Parsed object file for path/architecture pair, where "path" refers /// to Mach-O universal binary. std::map, std::unique_ptr> ObjectForUBPathAndArch; Options Opts; std::unique_ptr BIDFetcher; }; // A binary intrusively linked into a LRU cache list. If the binary is empty, // then the entry marks that an error occurred, and it is not part of the LRU // list. class CachedBinary : public ilist_node { public: CachedBinary() = default; CachedBinary(OwningBinary Bin) : Bin(std::move(Bin)) {} OwningBinary &operator*() { return Bin; } OwningBinary *operator->() { return &Bin; } // Add an action to be performed when the binary is evicted, before all // previously registered evictors. void pushEvictor(std::function Evictor); // Run all registered evictors in the reverse of the order in which they were // added. void evict() { if (Evictor) Evictor(); } size_t size() { return Bin.getBinary()->getData().size(); } private: OwningBinary Bin; std::function Evictor; }; } // end namespace symbolize } // end namespace llvm #endif // LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H