Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:46

0001 //===- Symbolize.h ----------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Header for LLVM symbolization library.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H
0014 #define LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H
0015 
0016 #include "llvm/ADT/StringMap.h"
0017 #include "llvm/ADT/ilist_node.h"
0018 #include "llvm/ADT/simple_ilist.h"
0019 #include "llvm/DebugInfo/DIContext.h"
0020 #include "llvm/Object/Binary.h"
0021 #include "llvm/Object/BuildID.h"
0022 #include "llvm/Support/Error.h"
0023 #include <algorithm>
0024 #include <cstdint>
0025 #include <map>
0026 #include <memory>
0027 #include <string>
0028 #include <utility>
0029 #include <vector>
0030 
0031 namespace llvm {
0032 namespace object {
0033 class ELFObjectFileBase;
0034 class MachOObjectFile;
0035 class ObjectFile;
0036 struct SectionedAddress;
0037 } // namespace object
0038 
0039 namespace symbolize {
0040 
0041 class SymbolizableModule;
0042 
0043 using namespace object;
0044 
0045 using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
0046 using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
0047 
0048 class CachedBinary;
0049 
0050 class LLVMSymbolizer {
0051 public:
0052   struct Options {
0053     FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName;
0054     FileLineInfoKind PathStyle = FileLineInfoKind::AbsoluteFilePath;
0055     bool SkipLineZero = false;
0056     bool UseSymbolTable = true;
0057     bool Demangle = true;
0058     bool RelativeAddresses = false;
0059     bool UntagAddresses = false;
0060     bool UseDIA = false;
0061     std::string DefaultArch;
0062     std::vector<std::string> DsymHints;
0063     std::string FallbackDebugPath;
0064     std::string DWPName;
0065     std::vector<std::string> DebugFileDirectory;
0066     size_t MaxCacheSize =
0067         sizeof(size_t) == 4
0068             ? 512 * 1024 * 1024 /* 512 MiB */
0069             : static_cast<size_t>(4ULL * 1024 * 1024 * 1024) /* 4 GiB */;
0070   };
0071 
0072   LLVMSymbolizer();
0073   LLVMSymbolizer(const Options &Opts);
0074 
0075   ~LLVMSymbolizer();
0076 
0077   // Overloads accepting ObjectFile does not support COFF currently
0078   Expected<DILineInfo> symbolizeCode(const ObjectFile &Obj,
0079                                      object::SectionedAddress ModuleOffset);
0080   Expected<DILineInfo> symbolizeCode(StringRef ModuleName,
0081                                      object::SectionedAddress ModuleOffset);
0082   Expected<DILineInfo> symbolizeCode(ArrayRef<uint8_t> BuildID,
0083                                      object::SectionedAddress ModuleOffset);
0084   Expected<DIInliningInfo>
0085   symbolizeInlinedCode(const ObjectFile &Obj,
0086                        object::SectionedAddress ModuleOffset);
0087   Expected<DIInliningInfo>
0088   symbolizeInlinedCode(StringRef ModuleName,
0089                        object::SectionedAddress ModuleOffset);
0090   Expected<DIInliningInfo>
0091   symbolizeInlinedCode(ArrayRef<uint8_t> BuildID,
0092                        object::SectionedAddress ModuleOffset);
0093 
0094   Expected<DIGlobal> symbolizeData(const ObjectFile &Obj,
0095                                    object::SectionedAddress ModuleOffset);
0096   Expected<DIGlobal> symbolizeData(StringRef ModuleName,
0097                                    object::SectionedAddress ModuleOffset);
0098   Expected<DIGlobal> symbolizeData(ArrayRef<uint8_t> BuildID,
0099                                    object::SectionedAddress ModuleOffset);
0100   Expected<std::vector<DILocal>>
0101   symbolizeFrame(const ObjectFile &Obj, object::SectionedAddress ModuleOffset);
0102   Expected<std::vector<DILocal>>
0103   symbolizeFrame(StringRef ModuleName, object::SectionedAddress ModuleOffset);
0104   Expected<std::vector<DILocal>>
0105   symbolizeFrame(ArrayRef<uint8_t> BuildID,
0106                  object::SectionedAddress ModuleOffset);
0107 
0108   Expected<std::vector<DILineInfo>>
0109   findSymbol(const ObjectFile &Obj, StringRef Symbol, uint64_t Offset);
0110   Expected<std::vector<DILineInfo>>
0111   findSymbol(StringRef ModuleName, StringRef Symbol, uint64_t Offset);
0112   Expected<std::vector<DILineInfo>>
0113   findSymbol(ArrayRef<uint8_t> BuildID, StringRef Symbol, uint64_t Offset);
0114 
0115   void flush();
0116 
0117   // Evict entries from the binary cache until it is under the maximum size
0118   // given in the options. Calling this invalidates references in the DI...
0119   // objects returned by the methods above.
0120   void pruneCache();
0121 
0122   static std::string
0123   DemangleName(StringRef Name, const SymbolizableModule *DbiModuleDescriptor);
0124 
0125   void setBuildIDFetcher(std::unique_ptr<BuildIDFetcher> Fetcher) {
0126     BIDFetcher = std::move(Fetcher);
0127   }
0128 
0129   /// Returns a SymbolizableModule or an error if loading debug info failed.
0130   /// Only one attempt is made to load a module, and errors during loading are
0131   /// only reported once. Subsequent calls to get module info for a module that
0132   /// failed to load will return nullptr.
0133   Expected<SymbolizableModule *> getOrCreateModuleInfo(StringRef ModuleName);
0134 
0135 private:
0136   // Bundles together object file with code/data and object file with
0137   // corresponding debug info. These objects can be the same.
0138   using ObjectPair = std::pair<const ObjectFile *, const ObjectFile *>;
0139 
0140   template <typename T>
0141   Expected<DILineInfo>
0142   symbolizeCodeCommon(const T &ModuleSpecifier,
0143                       object::SectionedAddress ModuleOffset);
0144   template <typename T>
0145   Expected<DIInliningInfo>
0146   symbolizeInlinedCodeCommon(const T &ModuleSpecifier,
0147                              object::SectionedAddress ModuleOffset);
0148   template <typename T>
0149   Expected<DIGlobal> symbolizeDataCommon(const T &ModuleSpecifier,
0150                                          object::SectionedAddress ModuleOffset);
0151   template <typename T>
0152   Expected<std::vector<DILocal>>
0153   symbolizeFrameCommon(const T &ModuleSpecifier,
0154                        object::SectionedAddress ModuleOffset);
0155   template <typename T>
0156   Expected<std::vector<DILineInfo>>
0157   findSymbolCommon(const T &ModuleSpecifier, StringRef Symbol, uint64_t Offset);
0158 
0159   Expected<SymbolizableModule *> getOrCreateModuleInfo(const ObjectFile &Obj);
0160 
0161   /// Returns a SymbolizableModule or an error if loading debug info failed.
0162   /// Unlike the above, errors are reported each time, since they are more
0163   /// likely to be transient.
0164   Expected<SymbolizableModule *>
0165   getOrCreateModuleInfo(ArrayRef<uint8_t> BuildID);
0166 
0167   Expected<SymbolizableModule *>
0168   createModuleInfo(const ObjectFile *Obj, std::unique_ptr<DIContext> Context,
0169                    StringRef ModuleName);
0170 
0171   ObjectFile *lookUpDsymFile(const std::string &Path,
0172                              const MachOObjectFile *ExeObj,
0173                              const std::string &ArchName);
0174   ObjectFile *lookUpDebuglinkObject(const std::string &Path,
0175                                     const ObjectFile *Obj,
0176                                     const std::string &ArchName);
0177   ObjectFile *lookUpBuildIDObject(const std::string &Path,
0178                                   const ELFObjectFileBase *Obj,
0179                                   const std::string &ArchName);
0180 
0181   bool findDebugBinary(const std::string &OrigPath,
0182                        const std::string &DebuglinkName, uint32_t CRCHash,
0183                        std::string &Result);
0184 
0185   bool getOrFindDebugBinary(const ArrayRef<uint8_t> BuildID,
0186                             std::string &Result);
0187 
0188   /// Returns pair of pointers to object and debug object.
0189   Expected<ObjectPair> getOrCreateObjectPair(const std::string &Path,
0190                                              const std::string &ArchName);
0191 
0192   /// Return a pointer to object file at specified path, for a specified
0193   /// architecture (e.g. if path refers to a Mach-O universal binary, only one
0194   /// object file from it will be returned).
0195   Expected<ObjectFile *> getOrCreateObject(const std::string &Path,
0196                                            const std::string &ArchName);
0197 
0198   /// Update the LRU cache order when a binary is accessed.
0199   void recordAccess(CachedBinary &Bin);
0200 
0201   std::map<std::string, std::unique_ptr<SymbolizableModule>, std::less<>>
0202       Modules;
0203   StringMap<std::string> BuildIDPaths;
0204 
0205   /// Contains cached results of getOrCreateObjectPair().
0206   std::map<std::pair<std::string, std::string>, ObjectPair>
0207       ObjectPairForPathArch;
0208 
0209   /// Contains parsed binary for each path, or parsing error.
0210   std::map<std::string, CachedBinary, std::less<>> BinaryForPath;
0211 
0212   /// A list of cached binaries in LRU order.
0213   simple_ilist<CachedBinary> LRUBinaries;
0214   /// Sum of the sizes of the cached binaries.
0215   size_t CacheSize = 0;
0216 
0217   /// Parsed object file for path/architecture pair, where "path" refers
0218   /// to Mach-O universal binary.
0219   std::map<std::pair<std::string, std::string>, std::unique_ptr<ObjectFile>>
0220       ObjectForUBPathAndArch;
0221 
0222   Options Opts;
0223 
0224   std::unique_ptr<BuildIDFetcher> BIDFetcher;
0225 };
0226 
0227 // A binary intrusively linked into a LRU cache list. If the binary is empty,
0228 // then the entry marks that an error occurred, and it is not part of the LRU
0229 // list.
0230 class CachedBinary : public ilist_node<CachedBinary> {
0231 public:
0232   CachedBinary() = default;
0233   CachedBinary(OwningBinary<Binary> Bin) : Bin(std::move(Bin)) {}
0234 
0235   OwningBinary<Binary> &operator*() { return Bin; }
0236   OwningBinary<Binary> *operator->() { return &Bin; }
0237 
0238   // Add an action to be performed when the binary is evicted, before all
0239   // previously registered evictors.
0240   void pushEvictor(std::function<void()> Evictor);
0241 
0242   // Run all registered evictors in the reverse of the order in which they were
0243   // added.
0244   void evict() {
0245     if (Evictor)
0246       Evictor();
0247   }
0248 
0249   size_t size() { return Bin.getBinary()->getData().size(); }
0250 
0251 private:
0252   OwningBinary<Binary> Bin;
0253   std::function<void()> Evictor;
0254 };
0255 
0256 } // end namespace symbolize
0257 } // end namespace llvm
0258 
0259 #endif // LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H