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
25namespace lldb_private::plugin {
26namespace dwarf {
27class DWARFUnit;
28class DWARFCompileUnit;
29class NameToDIE;
30class SymbolFileDWARF;
31class SymbolFileDWARFDwo;
32
33typedef std::shared_ptr<DWARFUnit> DWARFUnitSP;
34
35enum DWARFProducer {
36 eProducerInvalid = 0,
37 eProducerClang,
38 eProducerGCC,
39 eProducerSwift,
40 eProducerOther
41};
42
43class DWARFUnit : public DWARFExpression::Delegate, public UserID {
44 using die_iterator_range =
45 llvm::iterator_range<DWARFDebugInfoEntry::collection::iterator>;
46
47public:
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
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.
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.
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
107 size_t GetLengthByteSize() const { return 4; }
108
109 bool ContainsDIEOffset(dw_offset_t die_offset) const {
110 return die_offset >= GetFirstDIEOffset() &&
111 die_offset < GetNextUnitOffset();
112 }
113 dw_offset_t GetFirstDIEOffset() const {
114 return GetOffset() + GetHeaderByteSize();
115 }
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.
120 dw_offset_t GetLength() const { return m_header.getLength(); }
121 uint16_t GetVersion() const override { return m_header.getVersion(); }
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;
127 uint8_t GetAddressByteSize() const override {
128 return m_header.getAddressByteSize();
129 }
130 dw_addr_t GetAddrBase() const { return m_addr_base.value_or(u: 0); }
131 dw_addr_t GetBaseAddress() const override { return m_base_addr; }
132 dw_offset_t GetLineTableOffset();
133 dw_addr_t GetRangesBase() const { return m_ranges_base; }
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
149 DWARFBaseDIE GetUnitDIEOnly() { return {this, GetUnitDIEPtrOnly()}; }
150
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
180 lldb_private::CompileUnit *GetLLDBCompUnit() const { return m_lldb_cu; }
181
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
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
215 die_iterator_range dies() {
216 ExtractDIEsIfNeeded();
217 return die_iterator_range(m_die_array.begin(), m_die_array.end());
218 }
219
220 DIERef::Section GetDebugSection() const { return m_section; }
221
222 uint8_t GetUnitType() const { return m_header.getUnitType(); }
223 bool IsTypeUnit() const { return m_header.isTypeUnit(); }
224 /// Note that this check only works for DWARF5+.
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
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 Data: 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
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.
290 void SetDwoError(Status &&error) { m_dwo_error = std::move(error); }
291
292protected:
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.
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.
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
380private:
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

source code of lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h