Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //===- DWARFContext.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 #ifndef LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
0010 #define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
0011 
0012 #include "llvm/ADT/SmallVector.h"
0013 #include "llvm/ADT/StringExtras.h"
0014 #include "llvm/ADT/StringMap.h"
0015 #include "llvm/ADT/StringRef.h"
0016 #include "llvm/DebugInfo/DIContext.h"
0017 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
0018 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
0019 #include "llvm/DebugInfo/DWARF/DWARFObject.h"
0020 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
0021 #include "llvm/Object/Binary.h"
0022 #include "llvm/Object/ObjectFile.h"
0023 #include "llvm/Support/DataExtractor.h"
0024 #include "llvm/Support/Error.h"
0025 #include "llvm/TargetParser/Host.h"
0026 #include <cstdint>
0027 #include <memory>
0028 #include <mutex>
0029 
0030 namespace llvm {
0031 
0032 class MemoryBuffer;
0033 class AppleAcceleratorTable;
0034 class DWARFCompileUnit;
0035 class DWARFDebugAbbrev;
0036 class DWARFDebugAranges;
0037 class DWARFDebugFrame;
0038 class DWARFDebugLoc;
0039 class DWARFDebugMacro;
0040 class DWARFDebugNames;
0041 class DWARFGdbIndex;
0042 class DWARFTypeUnit;
0043 class DWARFUnitIndex;
0044 
0045 /// DWARFContext
0046 /// This data structure is the top level entity that deals with dwarf debug
0047 /// information parsing. The actual data is supplied through DWARFObj.
0048 class DWARFContext : public DIContext {
0049 public:
0050   /// DWARFContextState
0051   /// This structure contains all member variables for DWARFContext that need
0052   /// to be protected in multi-threaded environments. Threading support can be
0053   /// enabled by setting the ThreadSafe to true when constructing a
0054   /// DWARFContext to allow DWARRContext to be able to be used in a
0055   /// multi-threaded environment, or not enabled to allow for maximum
0056   /// performance in single threaded environments.
0057   class DWARFContextState {
0058   protected:
0059     /// Helper enum to distinguish between macro[.dwo] and macinfo[.dwo]
0060     /// section.
0061     enum MacroSecType {
0062       MacinfoSection,
0063       MacinfoDwoSection,
0064       MacroSection,
0065       MacroDwoSection
0066     };
0067 
0068     DWARFContext &D;
0069   public:
0070     DWARFContextState(DWARFContext &DC) : D(DC) {}
0071     virtual ~DWARFContextState() = default;
0072     virtual DWARFUnitVector &getNormalUnits() = 0;
0073     virtual DWARFUnitVector &getDWOUnits(bool Lazy = false) = 0;
0074     virtual const DWARFDebugAbbrev *getDebugAbbrevDWO() = 0;
0075     virtual const DWARFUnitIndex &getCUIndex() = 0;
0076     virtual const DWARFUnitIndex &getTUIndex() = 0;
0077     virtual DWARFGdbIndex &getGdbIndex() = 0;
0078     virtual const DWARFDebugAbbrev *getDebugAbbrev() = 0;
0079     virtual const DWARFDebugLoc *getDebugLoc() = 0;
0080     virtual const DWARFDebugAranges *getDebugAranges() = 0;
0081     virtual Expected<const DWARFDebugLine::LineTable *>
0082         getLineTableForUnit(DWARFUnit *U,
0083                             function_ref<void(Error)> RecoverableErrHandler) = 0;
0084     virtual void clearLineTableForUnit(DWARFUnit *U) = 0;
0085     virtual Expected<const DWARFDebugFrame *> getDebugFrame() = 0;
0086     virtual Expected<const DWARFDebugFrame *> getEHFrame() = 0;
0087     virtual const DWARFDebugMacro *getDebugMacinfo() = 0;
0088     virtual const DWARFDebugMacro *getDebugMacinfoDWO() = 0;
0089     virtual const DWARFDebugMacro *getDebugMacro() = 0;
0090     virtual const DWARFDebugMacro *getDebugMacroDWO() = 0;
0091     virtual const DWARFDebugNames &getDebugNames() = 0;
0092     virtual const AppleAcceleratorTable &getAppleNames() = 0;
0093     virtual const AppleAcceleratorTable &getAppleTypes() = 0;
0094     virtual const AppleAcceleratorTable &getAppleNamespaces() = 0;
0095     virtual const AppleAcceleratorTable &getAppleObjC() = 0;
0096     virtual std::shared_ptr<DWARFContext>
0097         getDWOContext(StringRef AbsolutePath) = 0;
0098     virtual const DenseMap<uint64_t, DWARFTypeUnit *> &
0099     getTypeUnitMap(bool IsDWO) = 0;
0100     virtual bool isThreadSafe() const = 0;
0101 
0102     /// Parse a macro[.dwo] or macinfo[.dwo] section.
0103     std::unique_ptr<DWARFDebugMacro>
0104     parseMacroOrMacinfo(MacroSecType SectionType);
0105 
0106   };
0107   friend class DWARFContextState;
0108 
0109 private:
0110   /// All important state for a DWARFContext that needs to be threadsafe needs
0111   /// to go into DWARFContextState.
0112   std::unique_ptr<DWARFContextState> State;
0113 
0114   /// The maximum DWARF version of all units.
0115   unsigned MaxVersion = 0;
0116 
0117   std::function<void(Error)> RecoverableErrorHandler =
0118       WithColor::defaultErrorHandler;
0119   std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler;
0120 
0121   /// Read compile units from the debug_info.dwo section (if necessary)
0122   /// and type units from the debug_types.dwo section (if necessary)
0123   /// and store them in DWOUnits.
0124   /// If \p Lazy is true, set up to parse but don't actually parse them.
0125   enum { EagerParse = false, LazyParse = true };
0126   DWARFUnitVector &getDWOUnits(bool Lazy = false);
0127 
0128   std::unique_ptr<const DWARFObject> DObj;
0129 
0130   // When set parses debug_info.dwo/debug_abbrev.dwo manually and populates CU
0131   // Index, and TU Index for DWARF5.
0132   bool ParseCUTUIndexManually = false;
0133 
0134 public:
0135   DWARFContext(std::unique_ptr<const DWARFObject> DObj,
0136                std::string DWPName = "",
0137                std::function<void(Error)> RecoverableErrorHandler =
0138                    WithColor::defaultErrorHandler,
0139                std::function<void(Error)> WarningHandler =
0140                    WithColor::defaultWarningHandler,
0141                bool ThreadSafe = false);
0142   ~DWARFContext() override;
0143 
0144   DWARFContext(DWARFContext &) = delete;
0145   DWARFContext &operator=(DWARFContext &) = delete;
0146 
0147   const DWARFObject &getDWARFObj() const { return *DObj; }
0148 
0149   static bool classof(const DIContext *DICtx) {
0150     return DICtx->getKind() == CK_DWARF;
0151   }
0152 
0153   /// Dump a textual representation to \p OS. If any \p DumpOffsets are present,
0154   /// dump only the record at the specified offset.
0155   void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
0156             std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets);
0157 
0158   void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override {
0159     std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets;
0160     dump(OS, DumpOpts, DumpOffsets);
0161   }
0162 
0163   bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override;
0164 
0165   using unit_iterator_range = DWARFUnitVector::iterator_range;
0166   using compile_unit_range = DWARFUnitVector::compile_unit_range;
0167 
0168   /// Get units from .debug_info in this context.
0169   unit_iterator_range info_section_units() {
0170     DWARFUnitVector &NormalUnits = State->getNormalUnits();
0171     return unit_iterator_range(NormalUnits.begin(),
0172                                NormalUnits.begin() +
0173                                    NormalUnits.getNumInfoUnits());
0174   }
0175 
0176   const DWARFUnitVector &getNormalUnitsVector() {
0177     return State->getNormalUnits();
0178   }
0179 
0180   /// Get units from .debug_types in this context.
0181   unit_iterator_range types_section_units() {
0182     DWARFUnitVector &NormalUnits = State->getNormalUnits();
0183     return unit_iterator_range(
0184         NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end());
0185   }
0186 
0187   /// Get compile units in this context.
0188   compile_unit_range compile_units() {
0189     return make_filter_range(info_section_units(), isCompileUnit);
0190   }
0191 
0192   // If you want type_units(), it'll need to be a concat iterator of a filter of
0193   // TUs in info_section + all the (all type) units in types_section
0194 
0195   /// Get all normal compile/type units in this context.
0196   unit_iterator_range normal_units() {
0197     DWARFUnitVector &NormalUnits = State->getNormalUnits();
0198     return unit_iterator_range(NormalUnits.begin(), NormalUnits.end());
0199   }
0200 
0201   /// Get units from .debug_info..dwo in the DWO context.
0202   unit_iterator_range dwo_info_section_units() {
0203     DWARFUnitVector &DWOUnits = State->getDWOUnits();
0204     return unit_iterator_range(DWOUnits.begin(),
0205                                DWOUnits.begin() + DWOUnits.getNumInfoUnits());
0206   }
0207 
0208   const DWARFUnitVector &getDWOUnitsVector() {
0209     return State->getDWOUnits();
0210   }
0211 
0212   /// Return true of this DWARF context is a DWP file.
0213   bool isDWP() const;
0214 
0215   /// Get units from .debug_types.dwo in the DWO context.
0216   unit_iterator_range dwo_types_section_units() {
0217     DWARFUnitVector &DWOUnits = State->getDWOUnits();
0218     return unit_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(),
0219                                DWOUnits.end());
0220   }
0221 
0222   /// Get compile units in the DWO context.
0223   compile_unit_range dwo_compile_units() {
0224     return make_filter_range(dwo_info_section_units(), isCompileUnit);
0225   }
0226 
0227   // If you want dwo_type_units(), it'll need to be a concat iterator of a
0228   // filter of TUs in dwo_info_section + all the (all type) units in
0229   // dwo_types_section.
0230 
0231   /// Get all units in the DWO context.
0232   unit_iterator_range dwo_units() {
0233     DWARFUnitVector &DWOUnits = State->getDWOUnits();
0234     return unit_iterator_range(DWOUnits.begin(), DWOUnits.end());
0235   }
0236 
0237   /// Get the number of compile units in this context.
0238   unsigned getNumCompileUnits() {
0239     return State->getNormalUnits().getNumInfoUnits();
0240   }
0241 
0242   /// Get the number of type units in this context.
0243   unsigned getNumTypeUnits() {
0244     return State->getNormalUnits().getNumTypesUnits();
0245   }
0246 
0247   /// Get the number of compile units in the DWO context.
0248   unsigned getNumDWOCompileUnits() {
0249     return State->getDWOUnits().getNumInfoUnits();
0250   }
0251 
0252   /// Get the number of type units in the DWO context.
0253   unsigned getNumDWOTypeUnits() {
0254     return State->getDWOUnits().getNumTypesUnits();
0255   }
0256 
0257   /// Get the unit at the specified index.
0258   DWARFUnit *getUnitAtIndex(unsigned index) {
0259     return State->getNormalUnits()[index].get();
0260   }
0261 
0262   /// Get the unit at the specified index for the DWO units.
0263   DWARFUnit *getDWOUnitAtIndex(unsigned index) {
0264     return State->getDWOUnits()[index].get();
0265   }
0266 
0267   DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
0268   DWARFTypeUnit *getTypeUnitForHash(uint64_t Hash, bool IsDWO);
0269 
0270   /// Return the DWARF unit that includes an offset (relative to .debug_info).
0271   DWARFUnit *getUnitForOffset(uint64_t Offset);
0272 
0273   /// Return the compile unit that includes an offset (relative to .debug_info).
0274   DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset);
0275 
0276   /// Get a DIE given an exact offset.
0277   DWARFDie getDIEForOffset(uint64_t Offset);
0278 
0279   unsigned getMaxVersion() {
0280     // Ensure info units have been parsed to discover MaxVersion
0281     info_section_units();
0282     return MaxVersion;
0283   }
0284 
0285   unsigned getMaxDWOVersion() {
0286     // Ensure DWO info units have been parsed to discover MaxVersion
0287     dwo_info_section_units();
0288     return MaxVersion;
0289   }
0290 
0291   void setMaxVersionIfGreater(unsigned Version) {
0292     if (Version > MaxVersion)
0293       MaxVersion = Version;
0294   }
0295 
0296   const DWARFUnitIndex &getCUIndex();
0297   DWARFGdbIndex &getGdbIndex();
0298   const DWARFUnitIndex &getTUIndex();
0299 
0300   /// Get a pointer to the parsed DebugAbbrev object.
0301   const DWARFDebugAbbrev *getDebugAbbrev();
0302 
0303   /// Get a pointer to the parsed DebugLoc object.
0304   const DWARFDebugLoc *getDebugLoc();
0305 
0306   /// Get a pointer to the parsed dwo abbreviations object.
0307   const DWARFDebugAbbrev *getDebugAbbrevDWO();
0308 
0309   /// Get a pointer to the parsed DebugAranges object.
0310   const DWARFDebugAranges *getDebugAranges();
0311 
0312   /// Get a pointer to the parsed frame information object.
0313   Expected<const DWARFDebugFrame *> getDebugFrame();
0314 
0315   /// Get a pointer to the parsed eh frame information object.
0316   Expected<const DWARFDebugFrame *> getEHFrame();
0317 
0318   /// Get a pointer to the parsed DebugMacinfo information object.
0319   const DWARFDebugMacro *getDebugMacinfo();
0320 
0321   /// Get a pointer to the parsed DebugMacinfoDWO information object.
0322   const DWARFDebugMacro *getDebugMacinfoDWO();
0323 
0324   /// Get a pointer to the parsed DebugMacro information object.
0325   const DWARFDebugMacro *getDebugMacro();
0326 
0327   /// Get a pointer to the parsed DebugMacroDWO information object.
0328   const DWARFDebugMacro *getDebugMacroDWO();
0329 
0330   /// Get a reference to the parsed accelerator table object.
0331   const DWARFDebugNames &getDebugNames();
0332 
0333   /// Get a reference to the parsed accelerator table object.
0334   const AppleAcceleratorTable &getAppleNames();
0335 
0336   /// Get a reference to the parsed accelerator table object.
0337   const AppleAcceleratorTable &getAppleTypes();
0338 
0339   /// Get a reference to the parsed accelerator table object.
0340   const AppleAcceleratorTable &getAppleNamespaces();
0341 
0342   /// Get a reference to the parsed accelerator table object.
0343   const AppleAcceleratorTable &getAppleObjC();
0344 
0345   /// Get a pointer to a parsed line table corresponding to a compile unit.
0346   /// Report any parsing issues as warnings on stderr.
0347   const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U);
0348 
0349   /// Get a pointer to a parsed line table corresponding to a compile unit.
0350   /// Report any recoverable parsing problems using the handler.
0351   Expected<const DWARFDebugLine::LineTable *>
0352   getLineTableForUnit(DWARFUnit *U,
0353                       function_ref<void(Error)> RecoverableErrorHandler);
0354 
0355   // Clear the line table object corresponding to a compile unit for memory
0356   // management purpose. When it's referred to again, it'll be re-populated.
0357   void clearLineTableForUnit(DWARFUnit *U);
0358 
0359   DataExtractor getStringExtractor() const {
0360     return DataExtractor(DObj->getStrSection(), false, 0);
0361   }
0362   DataExtractor getStringDWOExtractor() const {
0363     return DataExtractor(DObj->getStrDWOSection(), false, 0);
0364   }
0365   DataExtractor getLineStringExtractor() const {
0366     return DataExtractor(DObj->getLineStrSection(), false, 0);
0367   }
0368 
0369   /// Wraps the returned DIEs for a given address.
0370   struct DIEsForAddress {
0371     DWARFCompileUnit *CompileUnit = nullptr;
0372     DWARFDie FunctionDIE;
0373     DWARFDie BlockDIE;
0374     explicit operator bool() const { return CompileUnit != nullptr; }
0375   };
0376 
0377   /// Get the compilation unit, the function DIE and lexical block DIE for the
0378   /// given address where applicable.
0379   /// TODO: change input parameter from "uint64_t Address"
0380   ///       into "SectionedAddress Address"
0381   /// \param[in] CheckDWO If this is false then only search for address matches
0382   ///            in the current context's DIEs. If this is true, then each
0383   ///            DWARFUnit that has a DWO file will have the debug info in the
0384   ///            DWO file searched as well. This allows for lookups to succeed
0385   ///            by searching the split DWARF debug info when using the main
0386   ///            executable's debug info.
0387   DIEsForAddress getDIEsForAddress(uint64_t Address, bool CheckDWO = false);
0388 
0389   DILineInfo getLineInfoForAddress(
0390       object::SectionedAddress Address,
0391       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
0392   DILineInfo
0393   getLineInfoForDataAddress(object::SectionedAddress Address) override;
0394   DILineInfoTable getLineInfoForAddressRange(
0395       object::SectionedAddress Address, uint64_t Size,
0396       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
0397   DIInliningInfo getInliningInfoForAddress(
0398       object::SectionedAddress Address,
0399       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
0400 
0401   std::vector<DILocal>
0402   getLocalsForAddress(object::SectionedAddress Address) override;
0403 
0404   bool isLittleEndian() const { return DObj->isLittleEndian(); }
0405   static unsigned getMaxSupportedVersion() { return 5; }
0406   static bool isSupportedVersion(unsigned version) {
0407     return version >= 2 && version <= getMaxSupportedVersion();
0408   }
0409 
0410   static SmallVector<uint8_t, 3> getSupportedAddressSizes() {
0411     return {2, 4, 8};
0412   }
0413   static bool isAddressSizeSupported(unsigned AddressSize) {
0414     return llvm::is_contained(getSupportedAddressSizes(), AddressSize);
0415   }
0416   template <typename... Ts>
0417   static Error checkAddressSizeSupported(unsigned AddressSize,
0418                                          std::error_code EC, char const *Fmt,
0419                                          const Ts &...Vals) {
0420     if (isAddressSizeSupported(AddressSize))
0421       return Error::success();
0422     std::string Buffer;
0423     raw_string_ostream Stream(Buffer);
0424     Stream << format(Fmt, Vals...)
0425            << " has unsupported address size: " << AddressSize
0426            << " (supported are ";
0427     ListSeparator LS;
0428     for (unsigned Size : DWARFContext::getSupportedAddressSizes())
0429       Stream << LS << Size;
0430     Stream << ')';
0431     return make_error<StringError>(Buffer, EC);
0432   }
0433 
0434   std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
0435 
0436   function_ref<void(Error)> getRecoverableErrorHandler() {
0437     return RecoverableErrorHandler;
0438   }
0439 
0440   function_ref<void(Error)> getWarningHandler() { return WarningHandler; }
0441 
0442   enum class ProcessDebugRelocations { Process, Ignore };
0443 
0444   static std::unique_ptr<DWARFContext>
0445   create(const object::ObjectFile &Obj,
0446          ProcessDebugRelocations RelocAction = ProcessDebugRelocations::Process,
0447          const LoadedObjectInfo *L = nullptr, std::string DWPName = "",
0448          std::function<void(Error)> RecoverableErrorHandler =
0449              WithColor::defaultErrorHandler,
0450          std::function<void(Error)> WarningHandler =
0451              WithColor::defaultWarningHandler,
0452          bool ThreadSafe = false);
0453 
0454   static std::unique_ptr<DWARFContext>
0455   create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
0456          uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost,
0457          std::function<void(Error)> RecoverableErrorHandler =
0458              WithColor::defaultErrorHandler,
0459          std::function<void(Error)> WarningHandler =
0460              WithColor::defaultWarningHandler,
0461          bool ThreadSafe = false);
0462 
0463   /// Get address size from CUs.
0464   /// TODO: refactor compile_units() to make this const.
0465   uint8_t getCUAddrSize();
0466 
0467   Triple::ArchType getArch() const {
0468     return getDWARFObj().getFile()->getArch();
0469   }
0470 
0471   /// Return the compile unit which contains instruction with provided
0472   /// address.
0473   /// TODO: change input parameter from "uint64_t Address"
0474   ///       into "SectionedAddress Address"
0475   DWARFCompileUnit *getCompileUnitForCodeAddress(uint64_t Address);
0476 
0477   /// Return the compile unit which contains data with the provided address.
0478   /// Note: This is more expensive than `getCompileUnitForAddress`, as if
0479   /// `Address` isn't found in the CU ranges (which is cheap), then it falls
0480   /// back to an expensive O(n) walk of all CU's looking for data that spans the
0481   /// address.
0482   /// TODO: change input parameter from "uint64_t Address" into
0483   ///       "SectionedAddress Address"
0484   DWARFCompileUnit *getCompileUnitForDataAddress(uint64_t Address);
0485 
0486   /// Returns whether CU/TU should be populated manually. TU Index populated
0487   /// manually only for DWARF5.
0488   bool getParseCUTUIndexManually() const { return ParseCUTUIndexManually; }
0489 
0490   /// Sets whether CU/TU should be populated manually. TU Index populated
0491   /// manually only for DWARF5.
0492   void setParseCUTUIndexManually(bool PCUTU) { ParseCUTUIndexManually = PCUTU; }
0493 
0494 private:
0495   void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die,
0496                        std::vector<DILocal> &Result);
0497 };
0498 
0499 } // end namespace llvm
0500 
0501 #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H