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/DWARFAddressRange.h" 17 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 18 #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" 19 #include "llvm/Support/RWMutex.h" 20 #include <atomic> 21 #include <optional> 22 23 namespace lldb_private::plugin { 24 namespace dwarf { 25 class DWARFUnit; 26 class DWARFCompileUnit; 27 class NameToDIE; 28 class SymbolFileDWARF; 29 class SymbolFileDWARFDwo; 30 31 typedef std::shared_ptr<DWARFUnit> DWARFUnitSP; 32 33 enum DWARFProducer { 34 eProducerInvalid = 0, 35 eProducerClang, 36 eProducerGCC, 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 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. 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. 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 105 size_t GetLengthByteSize() const { return 4; } 106 107 bool ContainsDIEOffset(dw_offset_t die_offset) const { 108 return die_offset >= GetFirstDIEOffset() && 109 die_offset < GetNextUnitOffset(); 110 } 111 dw_offset_t GetFirstDIEOffset() const { 112 return GetOffset() + GetHeaderByteSize(); 113 } 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. 118 dw_offset_t GetLength() const { return m_header.getLength(); } 119 uint16_t GetVersion() const { return m_header.getVersion(); } 120 const llvm::DWARFAbbreviationDeclarationSet *GetAbbreviations() const; 121 dw_offset_t GetAbbrevOffset() const; 122 uint8_t GetAddressByteSize() const { return m_header.getAddressByteSize(); } 123 dw_addr_t GetAddrBase() const { return m_addr_base.value_or(0); } 124 dw_addr_t GetBaseAddress() const { return m_base_addr; } 125 dw_offset_t GetLineTableOffset(); 126 dw_addr_t GetRangesBase() const { return m_ranges_base; } 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 142 DWARFBaseDIE GetUnitDIEOnly() { return {this, GetUnitDIEPtrOnly()}; } 143 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 159 lldb_private::CompileUnit *GetLLDBCompUnit() const { return m_lldb_cu; } 160 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 bool LinkToSkeletonUnit(DWARFUnit &skeleton_unit); 174 175 bool Supports_unnamed_objc_bitfields(); 176 177 SymbolFileDWARF &GetSymbolFileDWARF() const { return m_dwarf; } 178 179 DWARFProducer GetProducer(); 180 181 llvm::VersionTuple GetProducerVersion(); 182 183 uint64_t GetDWARFLanguageType(); 184 185 bool GetIsOptimized(); 186 187 const FileSpec &GetCompilationDirectory(); 188 const FileSpec &GetAbsolutePath(); 189 FileSpec GetFile(size_t file_idx); 190 FileSpec::Style GetPathStyle(); 191 192 SymbolFileDWARFDwo *GetDwoSymbolFile(bool load_all_debug_info = true); 193 194 die_iterator_range dies() { 195 ExtractDIEsIfNeeded(); 196 return die_iterator_range(m_die_array.begin(), m_die_array.end()); 197 } 198 199 DIERef::Section GetDebugSection() const { return m_section; } 200 201 uint8_t GetUnitType() const { return m_header.getUnitType(); } 202 bool IsTypeUnit() const { return m_header.isTypeUnit(); } 203 /// Note that this check only works for DWARF5+. 204 bool IsSkeletonUnit() const { 205 return GetUnitType() == llvm::dwarf::DW_UT_skeleton; 206 } 207 208 std::optional<uint64_t> GetStringOffsetSectionItem(uint32_t index) const; 209 210 /// Return a list of address ranges resulting from a (possibly encoded) 211 /// range list starting at a given offset in the appropriate ranges section. 212 llvm::Expected<llvm::DWARFAddressRangesVector> 213 FindRnglistFromOffset(dw_offset_t offset); 214 215 /// Return a list of address ranges retrieved from an encoded range 216 /// list whose offset is found via a table lookup given an index (DWARF v5 217 /// and later). 218 llvm::Expected<llvm::DWARFAddressRangesVector> 219 FindRnglistFromIndex(uint32_t index); 220 221 /// Return a rangelist's offset based on an index. The index designates 222 /// an entry in the rangelist table's offset array and is supplied by 223 /// DW_FORM_rnglistx. 224 llvm::Expected<uint64_t> GetRnglistOffset(uint32_t Index); 225 226 std::optional<uint64_t> GetLoclistOffset(uint32_t Index) { 227 if (!m_loclist_table_header) 228 return std::nullopt; 229 230 std::optional<uint64_t> Offset = m_loclist_table_header->getOffsetEntry( 231 m_dwarf.GetDWARFContext().getOrLoadLocListsData().GetAsLLVM(), Index); 232 if (!Offset) 233 return std::nullopt; 234 return *Offset + m_loclists_base; 235 } 236 237 /// Return the location table for parsing the given location list data. The 238 /// format is chosen according to the unit type. Never returns null. 239 std::unique_ptr<llvm::DWARFLocationTable> 240 GetLocationTable(const DataExtractor &data) const; 241 242 DWARFDataExtractor GetLocationData() const; 243 244 /// Returns true if any DIEs in the unit match any DW_TAG values in \a tags. 245 /// 246 /// \param[in] tags 247 /// An array of dw_tag_t values to check all abbrevitions for. 248 /// 249 /// \returns 250 /// True if any DIEs match any tag in \a tags, false otherwise. 251 bool HasAny(llvm::ArrayRef<dw_tag_t> tags); 252 253 /// Get the fission .dwo file specific error for this compile unit. 254 /// 255 /// The skeleton compile unit only can have a DWO error. Any other type 256 /// of DWARFUnit will not have a valid DWO error. 257 /// 258 /// \returns 259 /// A valid DWO error if there is a problem with anything in the 260 /// locating or parsing inforamtion in the .dwo file 261 const Status &GetDwoError() const { return m_dwo_error; } 262 263 /// Set the fission .dwo file specific error for this compile unit. 264 /// 265 /// This helps tracks issues that arise when trying to locate or parse a 266 /// .dwo file. Things like a missing .dwo file, DWO ID mismatch, and other 267 /// .dwo errors can be stored in each compile unit so the issues can be 268 /// communicated to the user. 269 void SetDwoError(Status &&error) { m_dwo_error = std::move(error); } 270 271 protected: 272 DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, 273 const llvm::DWARFUnitHeader &header, 274 const llvm::DWARFAbbreviationDeclarationSet &abbrevs, 275 DIERef::Section section, bool is_dwo); 276 277 llvm::Error ExtractHeader(SymbolFileDWARF &dwarf, 278 const DWARFDataExtractor &data, 279 lldb::offset_t *offset_ptr); 280 281 // Get the DWARF unit DWARF debug information entry. Parse the single DIE 282 // if needed. 283 const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() { 284 ExtractUnitDIENoDwoIfNeeded(); 285 // m_first_die_mutex is not required as m_first_die is never cleared. 286 if (!m_first_die) 287 return nullptr; 288 return &m_first_die; 289 } 290 291 // Get all DWARF debug informration entries. Parse all DIEs if needed. 292 const DWARFDebugInfoEntry *DIEPtr() { 293 ExtractDIEsIfNeeded(); 294 if (m_die_array.empty()) 295 return nullptr; 296 return &m_die_array[0]; 297 } 298 299 const std::optional<llvm::DWARFDebugRnglistTable> &GetRnglistTable(); 300 301 DWARFDataExtractor GetRnglistData() const; 302 303 SymbolFileDWARF &m_dwarf; 304 std::shared_ptr<DWARFUnit> m_dwo; 305 llvm::DWARFUnitHeader m_header; 306 const llvm::DWARFAbbreviationDeclarationSet *m_abbrevs = nullptr; 307 lldb_private::CompileUnit *m_lldb_cu = nullptr; 308 // If this is a DWO file, we have a backlink to our skeleton compile unit. 309 std::atomic<DWARFUnit *> m_skeleton_unit = nullptr; 310 // The compile unit debug information entry item 311 DWARFDebugInfoEntry::collection m_die_array; 312 mutable llvm::sys::RWMutex m_die_array_mutex; 313 // It is used for tracking of ScopedExtractDIEs instances. 314 mutable llvm::sys::RWMutex m_die_array_scoped_mutex; 315 // ScopedExtractDIEs instances should not call ClearDIEsRWLocked() 316 // as someone called ExtractDIEsIfNeeded(). 317 std::atomic<bool> m_cancel_scopes; 318 // GetUnitDIEPtrOnly() needs to return pointer to the first DIE. 319 // But the first element of m_die_array after ExtractUnitDIEIfNeeded() 320 // would possibly move in memory after later ExtractDIEsIfNeeded(). 321 DWARFDebugInfoEntry m_first_die; 322 llvm::sys::RWMutex m_first_die_mutex; 323 // A table similar to the .debug_aranges table, but this one points to the 324 // exact DW_TAG_subprogram DIEs 325 std::unique_ptr<DWARFDebugAranges> m_func_aranges_up; 326 dw_addr_t m_base_addr = 0; 327 DWARFProducer m_producer = eProducerInvalid; 328 llvm::VersionTuple m_producer_version; 329 std::optional<uint64_t> m_language_type; 330 LazyBool m_is_optimized = eLazyBoolCalculate; 331 std::optional<FileSpec> m_comp_dir; 332 std::optional<FileSpec> m_file_spec; 333 std::optional<dw_addr_t> m_addr_base; ///< Value of DW_AT_addr_base. 334 dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base. 335 dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base. 336 std::optional<uint64_t> m_gnu_addr_base; 337 std::optional<uint64_t> m_gnu_ranges_base; 338 339 /// Value of DW_AT_stmt_list. 340 dw_offset_t m_line_table_offset = DW_INVALID_OFFSET; 341 342 dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base. 343 344 std::optional<llvm::DWARFDebugRnglistTable> m_rnglist_table; 345 bool m_rnglist_table_done = false; 346 std::optional<llvm::DWARFListTableHeader> m_loclist_table_header; 347 348 const DIERef::Section m_section; 349 bool m_is_dwo; 350 bool m_has_parsed_non_skeleton_unit; 351 /// Value of DW_AT_GNU_dwo_id (v4) or dwo_id from CU header (v5). 352 std::optional<uint64_t> m_dwo_id; 353 /// If we get an error when trying to load a .dwo file, save that error here. 354 /// Errors include .dwo/.dwp file not found, or the .dwp/.dwp file was found 355 /// but DWO ID doesn't match, etc. 356 Status m_dwo_error; 357 358 private: 359 void ParseProducerInfo(); 360 void ExtractDIEsRWLocked(); 361 void ClearDIEsRWLocked(); 362 363 void AddUnitDIE(const DWARFDebugInfoEntry &cu_die); 364 void SetDwoStrOffsetsBase(); 365 366 void ComputeCompDirAndGuessPathStyle(); 367 void ComputeAbsolutePath(); 368 369 DWARFUnit(const DWARFUnit &) = delete; 370 const DWARFUnit &operator=(const DWARFUnit &) = delete; 371 }; 372 } // namespace dwarf 373 } // namespace lldb_private::plugin 374 375 #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFUNIT_H 376