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/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 25 namespace lldb_private::plugin { 26 namespace dwarf { 27 class DWARFUnit; 28 class DWARFCompileUnit; 29 class NameToDIE; 30 class SymbolFileDWARF; 31 class SymbolFileDWARFDwo; 32 33 typedef std::shared_ptr<DWARFUnit> DWARFUnitSP; 34 35 enum DWARFProducer { 36 eProducerInvalid = 0, 37 eProducerClang, 38 eProducerGCC, 39 eProducerSwift, 40 eProducerOther 41 }; 42 43 class DWARFUnit : public DWARFExpression::Delegate, public UserID { 44 using die_iterator_range = 45 llvm::iterator_range<DWARFDebugInfoEntry::collection::iterator>; 46 47 public: 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 IsDWOUnit()54 bool IsDWOUnit() { return m_is_dwo; } 55 /// Get the DWO ID from the DWARFUnitHeader for DWARF5, or from the unit DIE's 56 /// 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 have 59 /// the DWO ID in the compile unit header and we sometimes only want to access 60 /// this cheap value without causing the more expensive attribute fetches that 61 /// GetDWOId() uses. GetHeaderDWOId()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 for 86 /// this DWARFUnit. It could be .debug_info or .debug_types 87 /// depending on where the data for this unit originates. 88 /// 89 /// \return 90 /// 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 /// \return 96 /// Byte size of the unit header 97 uint32_t GetHeaderByteSize() const; 98 99 // Offset of the initial length field. GetOffset()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 bytes 104 /// 105 /// \return 106 /// Byte size of the compile unit header length field GetLengthByteSize()107 size_t GetLengthByteSize() const { return 4; } 108 ContainsDIEOffset(dw_offset_t die_offset)109 bool ContainsDIEOffset(dw_offset_t die_offset) const { 110 return die_offset >= GetFirstDIEOffset() && 111 die_offset < GetNextUnitOffset(); 112 } GetFirstDIEOffset()113 dw_offset_t GetFirstDIEOffset() const { 114 return GetOffset() + GetHeaderByteSize(); 115 } GetNextUnitOffset()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. GetLength()120 dw_offset_t GetLength() const { return m_header.getLength(); } GetVersion()121 uint16_t GetVersion() const override { return m_header.getVersion(); } GetFormParams()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; GetAddressByteSize()127 uint8_t GetAddressByteSize() const override { 128 return m_header.getAddressByteSize(); 129 } GetAddrBase()130 dw_addr_t GetAddrBase() const { return m_addr_base.value_or(0); } GetBaseAddress()131 dw_addr_t GetBaseAddress() const override { return m_base_addr; } 132 dw_offset_t GetLineTableOffset(); GetRangesBase()133 dw_addr_t GetRangesBase() const { return m_ranges_base; } GetStrOffsetsBase()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 GetUnitDIEOnly()149 DWARFBaseDIE GetUnitDIEOnly() { return {this, GetUnitDIEPtrOnly()}; } 150 DIE()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, without 156 /// parsing the entire compile unit. An empty is string is returned upon 157 /// 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 bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes, 168 lldb::offset_t &offset, 169 std::vector<Value> &stack) const override; 170 171 bool ParseDWARFLocationList(const DataExtractor &data, 172 DWARFExpressionList &loc_list) const; 173 174 DWARFUnit &GetNonSkeletonUnit(); 175 176 static uint8_t GetAddressByteSize(const DWARFUnit *cu); 177 178 static uint8_t GetDefaultAddressSize(); 179 GetLLDBCompUnit()180 lldb_private::CompileUnit *GetLLDBCompUnit() const { return m_lldb_cu; } 181 SetLLDBCompUnit(lldb_private::CompileUnit * cu)182 void SetLLDBCompUnit(lldb_private::CompileUnit *cu) { m_lldb_cu = cu; } 183 184 /// Get the skeleton compile unit for a DWO file. 185 /// 186 /// We need to keep track of the skeleton compile unit for a DWO file so 187 /// we can access it. Sometimes this value is cached when the skeleton 188 /// compile unit is first parsed, but if a .dwp file parses all of the 189 /// DWARFUnits in the file, the skeleton compile unit might not have been 190 /// parsed yet, to there might not be a backlink. This accessor handles 191 /// both cases correctly and avoids crashes. 192 DWARFCompileUnit *GetSkeletonUnit(); 193 194 bool LinkToSkeletonUnit(DWARFUnit &skeleton_unit); 195 196 bool Supports_unnamed_objc_bitfields(); 197 GetSymbolFileDWARF()198 SymbolFileDWARF &GetSymbolFileDWARF() const { return m_dwarf; } 199 200 DWARFProducer GetProducer(); 201 202 llvm::VersionTuple GetProducerVersion(); 203 204 uint64_t GetDWARFLanguageType(); 205 206 bool GetIsOptimized(); 207 208 const FileSpec &GetCompilationDirectory(); 209 const FileSpec &GetAbsolutePath(); 210 FileSpec GetFile(size_t file_idx); 211 FileSpec::Style GetPathStyle(); 212 213 SymbolFileDWARFDwo *GetDwoSymbolFile(bool load_all_debug_info = true); 214 dies()215 die_iterator_range dies() { 216 ExtractDIEsIfNeeded(); 217 return die_iterator_range(m_die_array.begin(), m_die_array.end()); 218 } 219 GetDebugSection()220 DIERef::Section GetDebugSection() const { return m_section; } 221 GetUnitType()222 uint8_t GetUnitType() const { return m_header.getUnitType(); } IsTypeUnit()223 bool IsTypeUnit() const { return m_header.isTypeUnit(); } 224 /// Note that this check only works for DWARF5+. IsSkeletonUnit()225 bool IsSkeletonUnit() const { 226 return GetUnitType() == llvm::dwarf::DW_UT_skeleton; 227 } 228 229 std::optional<uint64_t> GetStringOffsetSectionItem(uint32_t index) const; 230 231 /// Return a list of address ranges resulting from a (possibly encoded) 232 /// range list starting at a given offset in the appropriate ranges section. 233 llvm::Expected<llvm::DWARFAddressRangesVector> 234 FindRnglistFromOffset(dw_offset_t offset); 235 236 /// Return a list of address ranges retrieved from an encoded range 237 /// list whose offset is found via a table lookup given an index (DWARF v5 238 /// and later). 239 llvm::Expected<llvm::DWARFAddressRangesVector> 240 FindRnglistFromIndex(uint32_t index); 241 242 /// Return a rangelist's offset based on an index. The index designates 243 /// an entry in the rangelist table's offset array and is supplied by 244 /// DW_FORM_rnglistx. 245 llvm::Expected<uint64_t> GetRnglistOffset(uint32_t Index); 246 GetLoclistOffset(uint32_t Index)247 std::optional<uint64_t> GetLoclistOffset(uint32_t Index) { 248 if (!m_loclist_table_header) 249 return std::nullopt; 250 251 std::optional<uint64_t> Offset = m_loclist_table_header->getOffsetEntry( 252 m_dwarf.GetDWARFContext().getOrLoadLocListsData().GetAsLLVM(), Index); 253 if (!Offset) 254 return std::nullopt; 255 return *Offset + m_loclists_base; 256 } 257 258 /// Return the location table for parsing the given location list data. The 259 /// format is chosen according to the unit type. Never returns null. 260 std::unique_ptr<llvm::DWARFLocationTable> 261 GetLocationTable(const DataExtractor &data) const; 262 263 DWARFDataExtractor GetLocationData() const; 264 265 /// Returns true if any DIEs in the unit match any DW_TAG values in \a tags. 266 /// 267 /// \param[in] tags 268 /// An array of dw_tag_t values to check all abbrevitions for. 269 /// 270 /// \returns 271 /// True if any DIEs match any tag in \a tags, false otherwise. 272 bool HasAny(llvm::ArrayRef<dw_tag_t> tags); 273 274 /// Get the fission .dwo file specific error for this compile unit. 275 /// 276 /// The skeleton compile unit only can have a DWO error. Any other type 277 /// of DWARFUnit will not have a valid DWO error. 278 /// 279 /// \returns 280 /// A valid DWO error if there is a problem with anything in the 281 /// locating or parsing inforamtion in the .dwo file GetDwoError()282 const Status &GetDwoError() const { return m_dwo_error; } 283 284 /// Set the fission .dwo file specific error for this compile unit. 285 /// 286 /// This helps tracks issues that arise when trying to locate or parse a 287 /// .dwo file. Things like a missing .dwo file, DWO ID mismatch, and other 288 /// .dwo errors can be stored in each compile unit so the issues can be 289 /// communicated to the user. SetDwoError(Status && error)290 void SetDwoError(Status &&error) { m_dwo_error = std::move(error); } 291 292 protected: 293 DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, 294 const llvm::DWARFUnitHeader &header, 295 const llvm::DWARFAbbreviationDeclarationSet &abbrevs, 296 DIERef::Section section, bool is_dwo); 297 298 llvm::Error ExtractHeader(SymbolFileDWARF &dwarf, 299 const DWARFDataExtractor &data, 300 lldb::offset_t *offset_ptr); 301 302 // Get the DWARF unit DWARF debug information entry. Parse the single DIE 303 // if needed. GetUnitDIEPtrOnly()304 const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() { 305 ExtractUnitDIENoDwoIfNeeded(); 306 // m_first_die_mutex is not required as m_first_die is never cleared. 307 if (!m_first_die) 308 return nullptr; 309 return &m_first_die; 310 } 311 312 // Get all DWARF debug informration entries. Parse all DIEs if needed. DIEPtr()313 const DWARFDebugInfoEntry *DIEPtr() { 314 ExtractDIEsIfNeeded(); 315 if (m_die_array.empty()) 316 return nullptr; 317 return &m_die_array[0]; 318 } 319 320 const std::optional<llvm::DWARFDebugRnglistTable> &GetRnglistTable(); 321 322 DWARFDataExtractor GetRnglistData() const; 323 324 SymbolFileDWARF &m_dwarf; 325 std::shared_ptr<DWARFUnit> m_dwo; 326 llvm::DWARFUnitHeader m_header; 327 const llvm::DWARFAbbreviationDeclarationSet *m_abbrevs = nullptr; 328 lldb_private::CompileUnit *m_lldb_cu = nullptr; 329 // If this is a DWO file, we have a backlink to our skeleton compile unit. 330 std::atomic<DWARFUnit *> m_skeleton_unit = nullptr; 331 // The compile unit debug information entry item 332 DWARFDebugInfoEntry::collection m_die_array; 333 mutable llvm::sys::RWMutex m_die_array_mutex; 334 // It is used for tracking of ScopedExtractDIEs instances. 335 mutable llvm::sys::Mutex m_die_array_scoped_mutex; 336 mutable int m_die_array_scoped_count = 0; 337 // ScopedExtractDIEs instances should not call ClearDIEsRWLocked() 338 // as someone called ExtractDIEsIfNeeded(). 339 std::atomic<bool> m_cancel_scopes; 340 // GetUnitDIEPtrOnly() needs to return pointer to the first DIE. 341 // But the first element of m_die_array after ExtractUnitDIEIfNeeded() 342 // would possibly move in memory after later ExtractDIEsIfNeeded(). 343 DWARFDebugInfoEntry m_first_die; 344 llvm::sys::RWMutex m_first_die_mutex; 345 // A table similar to the .debug_aranges table, but this one points to the 346 // exact DW_TAG_subprogram DIEs 347 std::unique_ptr<DWARFDebugAranges> m_func_aranges_up; 348 dw_addr_t m_base_addr = 0; 349 DWARFProducer m_producer = eProducerInvalid; 350 llvm::VersionTuple m_producer_version; 351 std::optional<uint64_t> m_language_type; 352 LazyBool m_is_optimized = eLazyBoolCalculate; 353 std::optional<FileSpec> m_comp_dir; 354 std::optional<FileSpec> m_file_spec; 355 std::optional<dw_addr_t> m_addr_base; ///< Value of DW_AT_addr_base. 356 dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base. 357 dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base. 358 std::optional<uint64_t> m_gnu_addr_base; 359 std::optional<uint64_t> m_gnu_ranges_base; 360 361 /// Value of DW_AT_stmt_list. 362 dw_offset_t m_line_table_offset = DW_INVALID_OFFSET; 363 364 dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base. 365 366 std::optional<llvm::DWARFDebugRnglistTable> m_rnglist_table; 367 bool m_rnglist_table_done = false; 368 std::optional<llvm::DWARFListTableHeader> m_loclist_table_header; 369 370 const DIERef::Section m_section; 371 bool m_is_dwo; 372 bool m_has_parsed_non_skeleton_unit; 373 /// Value of DW_AT_GNU_dwo_id (v4) or dwo_id from CU header (v5). 374 std::optional<uint64_t> m_dwo_id; 375 /// If we get an error when trying to load a .dwo file, save that error here. 376 /// Errors include .dwo/.dwp file not found, or the .dwp/.dwp file was found 377 /// but DWO ID doesn't match, etc. 378 Status m_dwo_error; 379 380 private: 381 void ParseProducerInfo(); 382 void ExtractDIEsRWLocked(); 383 void ClearDIEsRWLocked(); 384 385 void AddUnitDIE(const DWARFDebugInfoEntry &cu_die); 386 void SetDwoStrOffsetsBase(); 387 388 void ComputeCompDirAndGuessPathStyle(); 389 void ComputeAbsolutePath(); 390 391 DWARFUnit(const DWARFUnit &) = delete; 392 const DWARFUnit &operator=(const DWARFUnit &) = delete; 393 }; 394 } // namespace dwarf 395 } // namespace lldb_private::plugin 396 397 #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFUNIT_H 398