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