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