brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.9 KiB · b5199a8 Raw
401 lines · c
1//===-- DWARFUnit.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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFUNIT_H10#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFUNIT_H11 12#include "DWARFDIE.h"13#include "DWARFDebugInfoEntry.h"14#include "lldb/Expression/DWARFExpression.h"15#include "lldb/Utility/XcodeSDK.h"16#include "lldb/lldb-enumerations.h"17#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"18#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"19#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"20#include "llvm/Support/Mutex.h"21#include "llvm/Support/RWMutex.h"22#include <atomic>23#include <optional>24 25namespace lldb_private::plugin {26namespace dwarf {27class DWARFUnit;28class DWARFCompileUnit;29class NameToDIE;30class SymbolFileDWARF;31class SymbolFileDWARFDwo;32 33typedef std::shared_ptr<DWARFUnit> DWARFUnitSP;34 35enum DWARFProducer {36  eProducerInvalid = 0,37  eProducerClang,38  eProducerGCC,39  eProducerSwift,40  eProducerOther41};42 43class DWARFUnit : public DWARFExpression::Delegate, public UserID {44  using die_iterator_range =45      llvm::iterator_range<DWARFDebugInfoEntry::collection::iterator>;46 47public:48  static llvm::Expected<DWARFUnitSP>49  extract(SymbolFileDWARF &dwarf2Data, lldb::user_id_t uid,50          const DWARFDataExtractor &debug_info, DIERef::Section section,51          lldb::offset_t *offset_ptr);52  virtual ~DWARFUnit();53 54  bool IsDWOUnit() { return m_is_dwo; }55  /// Get the DWO ID from the DWARFUnitHeader for DWARF5, or from the unit DIE's56  /// DW_AT_dwo_id or DW_AT_GNU_dwo_id for DWARF4 and earlier.57  std::optional<uint64_t> GetDWOId();58  /// Get the DWO ID from the DWARFUnitHeader only. DWARF5 skeleton units have59  /// the DWO ID in the compile unit header and we sometimes only want to access60  /// this cheap value without causing the more expensive attribute fetches that61  /// GetDWOId() uses.62  std::optional<uint64_t> GetHeaderDWOId() { return m_header.getDWOId(); }63  void ExtractUnitDIEIfNeeded();64  void ExtractUnitDIENoDwoIfNeeded();65  void ExtractDIEsIfNeeded();66 67  class ScopedExtractDIEs {68    DWARFUnit *m_cu;69 70  public:71    bool m_clear_dies = false;72    ScopedExtractDIEs(DWARFUnit &cu);73    ~ScopedExtractDIEs();74    ScopedExtractDIEs(const ScopedExtractDIEs &) = delete;75    const ScopedExtractDIEs &operator=(const ScopedExtractDIEs &) = delete;76    ScopedExtractDIEs(ScopedExtractDIEs &&rhs);77    ScopedExtractDIEs &operator=(ScopedExtractDIEs &&rhs);78  };79  ScopedExtractDIEs ExtractDIEsScoped();80 81  bool Verify(Stream *s) const;82  virtual void Dump(Stream *s) const = 0;83  /// Get the data that contains the DIE information for this unit.84  ///85  /// This will return the correct bytes that contain the data for86  /// this DWARFUnit. It could be .debug_info or .debug_types87  /// depending on where the data for this unit originates.88  ///89  /// \return90  ///   The correct data for the DIE information in this unit.91  const DWARFDataExtractor &GetData() const;92 93  /// Get the size in bytes of the unit header.94  ///95  /// \return96  ///     Byte size of the unit header97  uint32_t GetHeaderByteSize() const;98 99  // Offset of the initial length field.100  dw_offset_t GetOffset() const { return m_header.getOffset(); }101  /// Get the size in bytes of the length field in the header.102  ///103  /// In DWARF32 this is just 4 bytes104  ///105  /// \return106  ///     Byte size of the compile unit header length field107  size_t GetLengthByteSize() const { return 4; }108 109  bool ContainsDIEOffset(dw_offset_t die_offset) const {110    return die_offset >= GetFirstDIEOffset() &&111           die_offset < GetNextUnitOffset();112  }113  dw_offset_t GetFirstDIEOffset() const {114    return GetOffset() + GetHeaderByteSize();115  }116  dw_offset_t GetNextUnitOffset() const { return m_header.getNextUnitOffset(); }117  // Size of the CU data (without initial length and without header).118  size_t GetDebugInfoSize() const;119  // Size of the CU data incl. header but without initial length.120  dw_offset_t GetLength() const { return m_header.getLength(); }121  uint16_t GetVersion() const override { return m_header.getVersion(); }122  const llvm::dwarf::FormParams &GetFormParams() const {123    return m_header.getFormParams();124  }125  const llvm::DWARFAbbreviationDeclarationSet *GetAbbreviations() const;126  dw_offset_t GetAbbrevOffset() const;127  uint8_t GetAddressByteSize() const override {128    return m_header.getAddressByteSize();129  }130  dw_addr_t GetAddrBase() const { return m_addr_base.value_or(0); }131  dw_addr_t GetBaseAddress() const override { return m_base_addr; }132  dw_offset_t GetLineTableOffset();133  dw_addr_t GetRangesBase() const { return m_ranges_base; }134  dw_addr_t GetStrOffsetsBase() const { return m_str_offsets_base; }135  void SetAddrBase(dw_addr_t addr_base);136  void SetLoclistsBase(dw_addr_t loclists_base);137  void SetRangesBase(dw_addr_t ranges_base);138  void SetStrOffsetsBase(dw_offset_t str_offsets_base);139  virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0;140 141  dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const override;142 143  lldb::ByteOrder GetByteOrder() const;144 145  const DWARFDebugAranges &GetFunctionAranges();146 147  void SetBaseAddress(dw_addr_t base_addr);148 149  DWARFBaseDIE GetUnitDIEOnly() { return {this, GetUnitDIEPtrOnly()}; }150 151  DWARFDIE DIE() { return DWARFDIE(this, DIEPtr()); }152 153  DWARFDIE GetDIE(dw_offset_t die_offset);154 155  /// Returns the AT_Name of the DIE at `die_offset`, if it exists, without156  /// parsing the entire compile unit. An empty is string is returned upon157  /// error or if the attribute is not present.158  llvm::StringRef PeekDIEName(dw_offset_t die_offset);159 160  llvm::Expected<std::pair<uint64_t, bool>>161  GetDIEBitSizeAndSign(uint64_t relative_die_offset) const override;162 163  lldb::offset_t GetVendorDWARFOpcodeSize(const DataExtractor &data,164                                          const lldb::offset_t data_offset,165                                          const uint8_t op) const override;166 167  virtual bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes,168                                      lldb::offset_t &offset,169                                      RegisterContext *reg_ctx,170                                      lldb::RegisterKind reg_kind,171                                      std::vector<Value> &stack) const override;172 173  bool ParseDWARFLocationList(const DataExtractor &data,174                              DWARFExpressionList &loc_list) const;175 176  DWARFUnit &GetNonSkeletonUnit();177 178  static uint8_t GetAddressByteSize(const DWARFUnit *cu);179 180  static uint8_t GetDefaultAddressSize();181 182  lldb_private::CompileUnit *GetLLDBCompUnit() const { return m_lldb_cu; }183 184  void SetLLDBCompUnit(lldb_private::CompileUnit *cu) { m_lldb_cu = cu; }185 186  /// Get the skeleton compile unit for a DWO file.187  ///188  /// We need to keep track of the skeleton compile unit for a DWO file so189  /// we can access it. Sometimes this value is cached when the skeleton190  /// compile unit is first parsed, but if a .dwp file parses all of the191  /// DWARFUnits in the file, the skeleton compile unit might not have been192  /// parsed yet, to there might not be a backlink. This accessor handles193  /// both cases correctly and avoids crashes.194  DWARFCompileUnit *GetSkeletonUnit();195 196  bool LinkToSkeletonUnit(DWARFUnit &skeleton_unit);197 198  bool Supports_unnamed_objc_bitfields();199 200  SymbolFileDWARF &GetSymbolFileDWARF() const { return m_dwarf; }201 202  DWARFProducer GetProducer();203 204  llvm::VersionTuple GetProducerVersion();205 206  uint64_t GetDWARFLanguageType();207 208  bool GetIsOptimized();209 210  const FileSpec &GetCompilationDirectory();211  const FileSpec &GetAbsolutePath();212  FileSpec GetFile(size_t file_idx);213  FileSpec::Style GetPathStyle();214 215  SymbolFileDWARFDwo *GetDwoSymbolFile(bool load_all_debug_info = true);216 217  die_iterator_range dies() {218    ExtractDIEsIfNeeded();219    return die_iterator_range(m_die_array.begin(), m_die_array.end());220  }221 222  DIERef::Section GetDebugSection() const { return m_section; }223 224  uint8_t GetUnitType() const { return m_header.getUnitType(); }225  bool IsTypeUnit() const { return m_header.isTypeUnit(); }226  /// Note that this check only works for DWARF5+.227  bool IsSkeletonUnit() const {228    return GetUnitType() == llvm::dwarf::DW_UT_skeleton;229  }230 231  std::optional<uint64_t> GetStringOffsetSectionItem(uint32_t index) const;232 233  /// Return a list of address ranges resulting from a (possibly encoded)234  /// range list starting at a given offset in the appropriate ranges section.235  llvm::Expected<llvm::DWARFAddressRangesVector>236  FindRnglistFromOffset(dw_offset_t offset);237 238  /// Return a list of address ranges retrieved from an encoded range239  /// list whose offset is found via a table lookup given an index (DWARF v5240  /// and later).241  llvm::Expected<llvm::DWARFAddressRangesVector>242  FindRnglistFromIndex(uint32_t index);243 244  /// Return a rangelist's offset based on an index. The index designates245  /// an entry in the rangelist table's offset array and is supplied by246  /// DW_FORM_rnglistx.247  llvm::Expected<uint64_t> GetRnglistOffset(uint32_t Index);248 249  std::optional<uint64_t> GetLoclistOffset(uint32_t Index) {250    if (!m_loclist_table_header)251      return std::nullopt;252 253    std::optional<uint64_t> Offset = m_loclist_table_header->getOffsetEntry(254        m_dwarf.GetDWARFContext().getOrLoadLocListsData().GetAsLLVM(), Index);255    if (!Offset)256      return std::nullopt;257    return *Offset + m_loclists_base;258  }259 260  /// Return the location table for parsing the given location list data. The261  /// format is chosen according to the unit type. Never returns null.262  std::unique_ptr<llvm::DWARFLocationTable>263  GetLocationTable(const DataExtractor &data) const;264 265  DWARFDataExtractor GetLocationData() const;266 267  /// Returns true if any DIEs in the unit match any DW_TAG values in \a tags.268  ///269  /// \param[in] tags270  ///   An array of dw_tag_t values to check all abbrevitions for.271  ///272  /// \returns273  ///   True if any DIEs match any tag in \a tags, false otherwise.274  bool HasAny(llvm::ArrayRef<dw_tag_t> tags);275 276  /// Get the fission .dwo file specific error for this compile unit.277  ///278  /// The skeleton compile unit only can have a DWO error. Any other type279  /// of DWARFUnit will not have a valid DWO error.280  ///281  /// \returns282  ///   A valid DWO error if there is a problem with anything in the283  ///   locating or parsing inforamtion in the .dwo file284  const Status &GetDwoError() const { return m_dwo_error; }285 286  /// Set the fission .dwo file specific error for this compile unit.287  ///288  /// This helps tracks issues that arise when trying to locate or parse a289  /// .dwo file. Things like a missing .dwo file, DWO ID mismatch, and other290  /// .dwo errors can be stored in each compile unit so the issues can be291  /// communicated to the user.292  void SetDwoError(Status &&error) { m_dwo_error = std::move(error); }293 294protected:295  DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,296            const llvm::DWARFUnitHeader &header,297            const llvm::DWARFAbbreviationDeclarationSet &abbrevs,298            DIERef::Section section, bool is_dwo);299 300  llvm::Error ExtractHeader(SymbolFileDWARF &dwarf,301                            const DWARFDataExtractor &data,302                            lldb::offset_t *offset_ptr);303 304  // Get the DWARF unit DWARF debug information entry. Parse the single DIE305  // if needed.306  const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {307    ExtractUnitDIENoDwoIfNeeded();308    // m_first_die_mutex is not required as m_first_die is never cleared.309    if (!m_first_die)310      return nullptr;311    return &m_first_die;312  }313 314  // Get all DWARF debug informration entries. Parse all DIEs if needed.315  const DWARFDebugInfoEntry *DIEPtr() {316    ExtractDIEsIfNeeded();317    if (m_die_array.empty())318      return nullptr;319    return &m_die_array[0];320  }321 322  const std::optional<llvm::DWARFDebugRnglistTable> &GetRnglistTable();323 324  DWARFDataExtractor GetRnglistData() const;325 326  SymbolFileDWARF &m_dwarf;327  std::shared_ptr<DWARFUnit> m_dwo;328  llvm::DWARFUnitHeader m_header;329  const llvm::DWARFAbbreviationDeclarationSet *m_abbrevs = nullptr;330  lldb_private::CompileUnit *m_lldb_cu = nullptr;331  // If this is a DWO file, we have a backlink to our skeleton compile unit.332  std::atomic<DWARFUnit *> m_skeleton_unit = nullptr;333  // The compile unit debug information entry item334  DWARFDebugInfoEntry::collection m_die_array;335  mutable llvm::sys::RWMutex m_die_array_mutex;336  // It is used for tracking of ScopedExtractDIEs instances.337  mutable llvm::sys::Mutex m_die_array_scoped_mutex;338  mutable int m_die_array_scoped_count = 0;339  // ScopedExtractDIEs instances should not call ClearDIEsRWLocked()340  // as someone called ExtractDIEsIfNeeded().341  std::atomic<bool> m_cancel_scopes;342  // GetUnitDIEPtrOnly() needs to return pointer to the first DIE.343  // But the first element of m_die_array after ExtractUnitDIEIfNeeded()344  // would possibly move in memory after later ExtractDIEsIfNeeded().345  DWARFDebugInfoEntry m_first_die;346  llvm::sys::RWMutex m_first_die_mutex;347  // A table similar to the .debug_aranges table, but this one points to the348  // exact DW_TAG_subprogram DIEs349  std::unique_ptr<DWARFDebugAranges> m_func_aranges_up;350  dw_addr_t m_base_addr = 0;351  DWARFProducer m_producer = eProducerInvalid;352  llvm::VersionTuple m_producer_version;353  std::optional<uint64_t> m_language_type;354  LazyBool m_is_optimized = eLazyBoolCalculate;355  std::optional<FileSpec> m_comp_dir;356  std::optional<FileSpec> m_file_spec;357  std::optional<dw_addr_t> m_addr_base; ///< Value of DW_AT_addr_base.358  dw_addr_t m_loclists_base = 0;        ///< Value of DW_AT_loclists_base.359  dw_addr_t m_ranges_base = 0;          ///< Value of DW_AT_rnglists_base.360  std::optional<uint64_t> m_gnu_addr_base;361  std::optional<uint64_t> m_gnu_ranges_base;362 363  /// Value of DW_AT_stmt_list.364  dw_offset_t m_line_table_offset = DW_INVALID_OFFSET;365 366  dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base.367  dw_offset_t m_str_offset_size = 4;  // Size in bytes of a string offset.368 369  std::optional<llvm::DWARFDebugRnglistTable> m_rnglist_table;370  bool m_rnglist_table_done = false;371  std::optional<llvm::DWARFListTableHeader> m_loclist_table_header;372 373  const DIERef::Section m_section;374  bool m_is_dwo;375  bool m_has_parsed_non_skeleton_unit;376  /// Value of DW_AT_GNU_dwo_id (v4) or dwo_id from CU header (v5).377  std::optional<uint64_t> m_dwo_id;378  /// If we get an error when trying to load a .dwo file, save that error here.379  /// Errors include .dwo/.dwp file not found, or the .dwp/.dwp file was found380  /// but DWO ID doesn't match, etc.381  Status m_dwo_error;382 383private:384  void ParseProducerInfo();385  void ExtractDIEsRWLocked();386  void ClearDIEsRWLocked();387 388  void AddUnitDIE(const DWARFDebugInfoEntry &cu_die);389  void SetDwoStrOffsetsBase();390 391  void ComputeCompDirAndGuessPathStyle();392  void ComputeAbsolutePath();393 394  DWARFUnit(const DWARFUnit &) = delete;395  const DWARFUnit &operator=(const DWARFUnit &) = delete;396};397} // namespace dwarf398} // namespace lldb_private::plugin399 400#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFUNIT_H401