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:
63   dw_offset_t GetOffset() const { return m_offset; }
64   uint16_t GetVersion() const { return m_version; }
65   uint16_t GetAddressByteSize() const { return m_addr_size; }
66   dw_offset_t GetLength() const { return m_length; }
67   dw_offset_t GetAbbrOffset() const { return m_abbr_offset; }
68   uint8_t GetUnitType() const { return m_unit_type; }
69   const llvm::DWARFUnitIndex::Entry *GetIndexEntry() const {
70     return m_index_entry;
71   }
72   uint64_t GetTypeHash() const { return m_type_hash; }
73   dw_offset_t GetTypeOffset() const { return m_type_offset; }
74   std::optional<uint64_t> GetDWOId() const { return m_dwo_id; }
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   }
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 
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.
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
147   size_t GetLengthByteSize() const { return 4; }
148 
149   bool ContainsDIEOffset(dw_offset_t die_offset) const {
150     return die_offset >= GetFirstDIEOffset() &&
151            die_offset < GetNextUnitOffset();
152   }
153   dw_offset_t GetFirstDIEOffset() const {
154     return GetOffset() + GetHeaderByteSize();
155   }
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.
160   dw_offset_t GetLength() const { return m_header.GetLength(); }
161   uint16_t GetVersion() const { return m_header.GetVersion(); }
162   const llvm::DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
163   dw_offset_t GetAbbrevOffset() const;
164   uint8_t GetAddressByteSize() const { return m_header.GetAddressByteSize(); }
165   dw_addr_t GetAddrBase() const { return m_addr_base.value_or(0); }
166   dw_addr_t GetBaseAddress() const { return m_base_addr; }
167   dw_offset_t GetLineTableOffset();
168   dw_addr_t GetRangesBase() const { return m_ranges_base; }
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 
184   DWARFBaseDIE GetUnitDIEOnly() { return {this, GetUnitDIEPtrOnly()}; }
185 
186   DWARFDIE DIE() { return DWARFDIE(this, DIEPtr()); }
187 
188   DWARFDIE GetDIE(dw_offset_t die_offset);
189 
190   DWARFUnit &GetNonSkeletonUnit();
191 
192   static uint8_t GetAddressByteSize(const DWARFUnit *cu);
193 
194   static uint8_t GetDefaultAddressSize();
195 
196   void *GetUserData() const;
197 
198   void SetUserData(void *d);
199 
200   bool Supports_DW_AT_APPLE_objc_complete_type();
201 
202   bool DW_AT_decl_file_attributes_are_invalid();
203 
204   bool Supports_unnamed_objc_bitfields();
205 
206   SymbolFileDWARF &GetSymbolFileDWARF() const { return m_dwarf; }
207 
208   DWARFProducer GetProducer();
209 
210   llvm::VersionTuple GetProducerVersion();
211 
212   uint64_t GetDWARFLanguageType();
213 
214   bool GetIsOptimized();
215 
216   const FileSpec &GetCompilationDirectory();
217   const FileSpec &GetAbsolutePath();
218   FileSpec GetFile(size_t file_idx);
219   FileSpec::Style GetPathStyle();
220 
221   SymbolFileDWARFDwo *GetDwoSymbolFile();
222 
223   die_iterator_range dies() {
224     ExtractDIEsIfNeeded();
225     return die_iterator_range(m_die_array.begin(), m_die_array.end());
226   }
227 
228   DIERef::Section GetDebugSection() const { return m_section; }
229 
230   uint8_t GetUnitType() const { return m_header.GetUnitType(); }
231   bool IsTypeUnit() const { return m_header.IsTypeUnit(); }
232   /// Note that this check only works for DWARF5+.
233   bool IsSkeletonUnit() const {
234     return GetUnitType() == llvm::dwarf::DW_UT_skeleton;
235   }
236 
237   std::optional<uint64_t> GetStringOffsetSectionItem(uint32_t index) const;
238 
239   /// Return a list of address ranges resulting from a (possibly encoded)
240   /// range list starting at a given offset in the appropriate ranges section.
241   llvm::Expected<DWARFRangeList> FindRnglistFromOffset(dw_offset_t offset);
242 
243   /// Return a list of address ranges retrieved from an encoded range
244   /// list whose offset is found via a table lookup given an index (DWARF v5
245   /// and later).
246   llvm::Expected<DWARFRangeList> FindRnglistFromIndex(uint32_t index);
247 
248   /// Return a rangelist's offset based on an index. The index designates
249   /// an entry in the rangelist table's offset array and is supplied by
250   /// DW_FORM_rnglistx.
251   llvm::Expected<uint64_t> GetRnglistOffset(uint32_t Index);
252 
253   std::optional<uint64_t> GetLoclistOffset(uint32_t Index) {
254     if (!m_loclist_table_header)
255       return std::nullopt;
256 
257     std::optional<uint64_t> Offset = m_loclist_table_header->getOffsetEntry(
258         m_dwarf.GetDWARFContext().getOrLoadLocListsData().GetAsLLVM(), Index);
259     if (!Offset)
260       return std::nullopt;
261     return *Offset + m_loclists_base;
262   }
263 
264   /// Return the location table for parsing the given location list data. The
265   /// format is chosen according to the unit type. Never returns null.
266   std::unique_ptr<llvm::DWARFLocationTable>
267   GetLocationTable(const DataExtractor &data) const;
268 
269   DWARFDataExtractor GetLocationData() const;
270 
271   /// Returns true if any DIEs in the unit match any DW_TAG values in \a tags.
272   ///
273   /// \param[in] tags
274   ///   An array of dw_tag_t values to check all abbrevitions for.
275   ///
276   /// \returns
277   ///   True if any DIEs match any tag in \a tags, false otherwise.
278   bool HasAny(llvm::ArrayRef<dw_tag_t> tags);
279 
280   /// Get the fission .dwo file specific error for this compile unit.
281   ///
282   /// The skeleton compile unit only can have a DWO error. Any other type
283   /// of DWARFUnit will not have a valid DWO error.
284   ///
285   /// \returns
286   ///   A valid DWO error if there is a problem with anything in the
287   ///   locating or parsing inforamtion in the .dwo file
288   const Status &GetDwoError() const { return m_dwo_error; }
289 
290   /// Set the fission .dwo file specific error for this compile unit.
291   ///
292   /// This helps tracks issues that arise when trying to locate or parse a
293   /// .dwo file. Things like a missing .dwo file, DWO ID mismatch, and other
294   /// .dwo errors can be stored in each compile unit so the issues can be
295   /// communicated to the user.
296   void SetDwoError(const Status &error) { m_dwo_error = error; }
297 
298 protected:
299   DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
300             const DWARFUnitHeader &header,
301             const llvm::DWARFAbbreviationDeclarationSet &abbrevs,
302             DIERef::Section section, bool is_dwo);
303 
304   llvm::Error ExtractHeader(SymbolFileDWARF &dwarf,
305                             const DWARFDataExtractor &data,
306                             lldb::offset_t *offset_ptr);
307 
308   // Get the DWARF unit DWARF debug information entry. Parse the single DIE
309   // if needed.
310   const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {
311     ExtractUnitDIENoDwoIfNeeded();
312     // m_first_die_mutex is not required as m_first_die is never cleared.
313     if (!m_first_die)
314       return nullptr;
315     return &m_first_die;
316   }
317 
318   // Get all DWARF debug informration entries. Parse all DIEs if needed.
319   const DWARFDebugInfoEntry *DIEPtr() {
320     ExtractDIEsIfNeeded();
321     if (m_die_array.empty())
322       return nullptr;
323     return &m_die_array[0];
324   }
325 
326   const std::optional<llvm::DWARFDebugRnglistTable> &GetRnglistTable();
327 
328   DWARFDataExtractor GetRnglistData() const;
329 
330   SymbolFileDWARF &m_dwarf;
331   std::shared_ptr<DWARFUnit> m_dwo;
332   DWARFUnitHeader m_header;
333   const llvm::DWARFAbbreviationDeclarationSet *m_abbrevs = nullptr;
334   void *m_user_data = nullptr;
335   // The compile unit debug information entry item
336   DWARFDebugInfoEntry::collection m_die_array;
337   mutable llvm::sys::RWMutex m_die_array_mutex;
338   // It is used for tracking of ScopedExtractDIEs instances.
339   mutable llvm::sys::RWMutex m_die_array_scoped_mutex;
340   // ScopedExtractDIEs instances should not call ClearDIEsRWLocked()
341   // as someone called ExtractDIEsIfNeeded().
342   std::atomic<bool> m_cancel_scopes;
343   // GetUnitDIEPtrOnly() needs to return pointer to the first DIE.
344   // But the first element of m_die_array after ExtractUnitDIEIfNeeded()
345   // would possibly move in memory after later ExtractDIEsIfNeeded().
346   DWARFDebugInfoEntry m_first_die;
347   llvm::sys::RWMutex m_first_die_mutex;
348   // A table similar to the .debug_aranges table, but this one points to the
349   // exact DW_TAG_subprogram DIEs
350   std::unique_ptr<DWARFDebugAranges> m_func_aranges_up;
351   dw_addr_t m_base_addr = 0;
352   DWARFProducer m_producer = eProducerInvalid;
353   llvm::VersionTuple m_producer_version;
354   std::optional<uint64_t> m_language_type;
355   LazyBool m_is_optimized = eLazyBoolCalculate;
356   std::optional<FileSpec> m_comp_dir;
357   std::optional<FileSpec> m_file_spec;
358   std::optional<dw_addr_t> m_addr_base; ///< Value of DW_AT_addr_base.
359   dw_addr_t m_loclists_base = 0;        ///< Value of DW_AT_loclists_base.
360   dw_addr_t m_ranges_base = 0;          ///< Value of DW_AT_rnglists_base.
361   std::optional<uint64_t> m_gnu_addr_base;
362   std::optional<uint64_t> m_gnu_ranges_base;
363 
364   /// Value of DW_AT_stmt_list.
365   dw_offset_t m_line_table_offset = DW_INVALID_OFFSET;
366 
367   dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base.
368 
369   std::optional<llvm::DWARFDebugRnglistTable> m_rnglist_table;
370   bool m_rnglist_table_done = false;
371   std::optional<llvm::DWARFListTableHeader> m_loclist_table_header;
372 
373   const DIERef::Section m_section;
374   bool m_is_dwo;
375   bool m_has_parsed_non_skeleton_unit;
376   /// Value of DW_AT_GNU_dwo_id (v4) or dwo_id from CU header (v5).
377   std::optional<uint64_t> m_dwo_id;
378   /// If we get an error when trying to load a .dwo file, save that error here.
379   /// Errors include .dwo/.dwp file not found, or the .dwp/.dwp file was found
380   /// but DWO ID doesn't match, etc.
381   Status m_dwo_error;
382 
383 private:
384   void ParseProducerInfo();
385   void ExtractDIEsRWLocked();
386   void ClearDIEsRWLocked();
387 
388   void AddUnitDIE(const DWARFDebugInfoEntry &cu_die);
389   void SetDwoStrOffsetsBase();
390 
391   void ComputeCompDirAndGuessPathStyle();
392   void ComputeAbsolutePath();
393 
394   DWARFUnit(const DWARFUnit &) = delete;
395   const DWARFUnit &operator=(const DWARFUnit &) = delete;
396 };
397 } // namespace dwarf
398 } // namespace lldb_private::plugin
399 
400 #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFUNIT_H
401