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