LLDB mainline
DWARFUnit.cpp
Go to the documentation of this file.
1//===-- DWARFUnit.cpp -----------------------------------------------------===//
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#include "DWARFUnit.h"
10
11#include "lldb/Core/Module.h"
15#include "lldb/Utility/Timer.h"
16#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
17#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
18#include "llvm/Object/Error.h"
19
20#include "DWARFCompileUnit.h"
21#include "DWARFDebugAranges.h"
22#include "DWARFDebugInfo.h"
23#include "DWARFTypeUnit.h"
24#include "LogChannelDWARF.h"
25#include "SymbolFileDWARFDwo.h"
26#include <optional>
27
28using namespace lldb;
29using namespace lldb_private;
30using namespace lldb_private::dwarf;
31using namespace lldb_private::plugin::dwarf;
32
33extern int g_verbose;
34
36 const DWARFUnitHeader &header,
37 const llvm::DWARFAbbreviationDeclarationSet &abbrevs,
38 DIERef::Section section, bool is_dwo)
39 : UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs),
40 m_cancel_scopes(false), m_section(section), m_is_dwo(is_dwo),
41 m_has_parsed_non_skeleton_unit(false), m_dwo_id(header.GetDWOId()) {}
42
43DWARFUnit::~DWARFUnit() = default;
44
45// Parses first DIE of a compile unit, excluding DWO.
47 {
48 llvm::sys::ScopedReader lock(m_first_die_mutex);
49 if (m_first_die)
50 return; // Already parsed
51 }
52 llvm::sys::ScopedWriter lock(m_first_die_mutex);
53 if (m_first_die)
54 return; // Already parsed
55
57
58 // Set the offset to that of the first DIE and calculate the start of the
59 // next compilation unit header.
61
62 // We are in our compile unit, parse starting at the offset we were told to
63 // parse
64 const DWARFDataExtractor &data = GetData();
65 if (offset < GetNextUnitOffset() &&
66 m_first_die.Extract(data, this, &offset)) {
68 return;
69 }
70}
71
72// Parses first DIE of a compile unit including DWO.
75
77 return;
78
81
82 if (!m_dwo_id)
83 return; // No DWO file.
84
85 std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
87 if (!dwo_symbol_file)
88 return;
89
90 DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(*m_dwo_id);
91
92 if (!dwo_cu) {
94 "unable to load .dwo file from \"{0}\" due to ID ({1:x16}) mismatch "
95 "for skeleton DIE at {2:x8}",
96 dwo_symbol_file->GetObjectFile()->GetFileSpec().GetPath().c_str(),
98 return; // Can't fetch the compile unit from the dwo file.
99 }
100 // If the skeleton compile unit gets its unit DIE parsed first, then this
101 // will fill in the DWO file's back pointer to this skeleton compile unit.
102 // If the DWO files get parsed on their own first the skeleton back link
103 // can be done manually in DWARFUnit::GetSkeletonCompileUnit() which will
104 // do a reverse lookup and cache the result.
105 dwo_cu->SetSkeletonUnit(this);
106
107 DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
108 if (!dwo_cu_die.IsValid()) {
109 // Can't fetch the compile unit DIE from the dwo file.
111 "unable to extract compile unit DIE from .dwo file for skeleton "
112 "DIE at {0:x16}",
114 return;
115 }
116
117 // Here for DWO CU we want to use the address base set in the skeleton unit
118 // (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base
119 // otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_*
120 // attributes which were applicable to the DWO units. The corresponding
121 // DW_AT_* attributes standardized in DWARF v5 are also applicable to the
122 // main unit in contrast.
123 if (m_addr_base)
124 dwo_cu->SetAddrBase(*m_addr_base);
125 else if (m_gnu_addr_base)
127
128 if (GetVersion() <= 4 && m_gnu_ranges_base)
130 else if (dwo_symbol_file->GetDWARFContext()
131 .getOrLoadRngListsData()
132 .GetByteSize() > 0)
133 dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
134
135 if (GetVersion() >= 5 &&
136 dwo_symbol_file->GetDWARFContext().getOrLoadLocListsData().GetByteSize() >
137 0)
138 dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
139
141
142 m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu);
143}
144
145// Parses a compile unit and indexes its DIEs if it hasn't already been done.
146// It will leave this compile unit extracted forever.
148 m_cancel_scopes = true;
149
150 {
151 llvm::sys::ScopedReader lock(m_die_array_mutex);
152 if (!m_die_array.empty())
153 return; // Already parsed
154 }
155 llvm::sys::ScopedWriter lock(m_die_array_mutex);
156 if (!m_die_array.empty())
157 return; // Already parsed
158
160}
161
162// Parses a compile unit and indexes its DIEs if it hasn't already been done.
163// It will clear this compile unit after returned instance gets out of scope,
164// no other ScopedExtractDIEs instance is running for this compile unit
165// and no ExtractDIEsIfNeeded() has been executed during this ScopedExtractDIEs
166// lifetime.
168 ScopedExtractDIEs scoped(*this);
169
170 {
171 llvm::sys::ScopedReader lock(m_die_array_mutex);
172 if (!m_die_array.empty())
173 return scoped; // Already parsed
174 }
175 llvm::sys::ScopedWriter lock(m_die_array_mutex);
176 if (!m_die_array.empty())
177 return scoped; // Already parsed
178
179 // Otherwise m_die_array would be already populated.
181
183 scoped.m_clear_dies = true;
184 return scoped;
185}
186
188 m_cu->m_die_array_scoped_mutex.lock_shared();
189}
190
192 if (!m_cu)
193 return;
194 m_cu->m_die_array_scoped_mutex.unlock_shared();
195 if (!m_clear_dies || m_cu->m_cancel_scopes)
196 return;
197 // Be sure no other ScopedExtractDIEs is running anymore.
198 llvm::sys::ScopedWriter lock_scoped(m_cu->m_die_array_scoped_mutex);
199 llvm::sys::ScopedWriter lock(m_cu->m_die_array_mutex);
200 if (m_cu->m_cancel_scopes)
201 return;
202 m_cu->ClearDIEsRWLocked();
203}
204
206 : m_cu(rhs.m_cu), m_clear_dies(rhs.m_clear_dies) {
207 rhs.m_cu = nullptr;
208}
209
212 m_cu = rhs.m_cu;
213 rhs.m_cu = nullptr;
214 m_clear_dies = rhs.m_clear_dies;
215 return *this;
216}
217
218// Parses a compile unit and indexes its DIEs, m_die_array_mutex must be
219// held R/W and m_die_array must be empty.
221 llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex);
222
225 "%s",
226 llvm::formatv("{0:x16}: DWARFUnit::ExtractDIEsIfNeeded()", GetOffset())
227 .str()
228 .c_str());
229
230 // Set the offset to that of the first DIE and calculate the start of the
231 // next compilation unit header.
233 lldb::offset_t next_cu_offset = GetNextUnitOffset();
234
236
237 uint32_t depth = 0;
238 // We are in our compile unit, parse starting at the offset we were told to
239 // parse
240 const DWARFDataExtractor &data = GetData();
241 std::vector<uint32_t> die_index_stack;
242 die_index_stack.reserve(32);
243 die_index_stack.push_back(0);
244 bool prev_die_had_children = false;
245 while (offset < next_cu_offset && die.Extract(data, this, &offset)) {
246 const bool null_die = die.IsNULL();
247 if (depth == 0) {
248 assert(m_die_array.empty() && "Compile unit DIE already added");
249
250 // The average bytes per DIE entry has been seen to be around 14-20 so
251 // lets pre-reserve half of that since we are now stripping the NULL
252 // tags.
253
254 // Only reserve the memory if we are adding children of the main
255 // compile unit DIE. The compile unit DIE is always the first entry, so
256 // if our size is 1, then we are adding the first compile unit child
257 // DIE and should reserve the memory.
258 m_die_array.reserve(GetDebugInfoSize() / 24);
259 m_die_array.push_back(die);
260
261 if (!m_first_die)
262 AddUnitDIE(m_die_array.front());
263
264 // With -fsplit-dwarf-inlining, clang will emit non-empty skeleton compile
265 // units. We are not able to access these DIE *and* the dwo file
266 // simultaneously. We also don't need to do that as the dwo file will
267 // contain a superset of information. So, we don't even attempt to parse
268 // any remaining DIEs.
269 if (m_dwo) {
270 m_die_array.front().SetHasChildren(false);
271 break;
272 }
273
274 } else {
275 if (null_die) {
276 if (prev_die_had_children) {
277 // This will only happen if a DIE says is has children but all it
278 // contains is a NULL tag. Since we are removing the NULL DIEs from
279 // the list (saves up to 25% in C++ code), we need a way to let the
280 // DIE know that it actually doesn't have children.
281 if (!m_die_array.empty())
282 m_die_array.back().SetHasChildren(false);
283 }
284 } else {
285 die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]);
286
287 if (die_index_stack.back())
288 m_die_array[die_index_stack.back()].SetSiblingIndex(
289 m_die_array.size() - die_index_stack.back());
290
291 // Only push the DIE if it isn't a NULL DIE
292 m_die_array.push_back(die);
293 }
294 }
295
296 if (null_die) {
297 // NULL DIE.
298 if (!die_index_stack.empty())
299 die_index_stack.pop_back();
300
301 if (depth > 0)
302 --depth;
303 prev_die_had_children = false;
304 } else {
305 die_index_stack.back() = m_die_array.size() - 1;
306 // Normal DIE
307 const bool die_has_children = die.HasChildren();
308 if (die_has_children) {
309 die_index_stack.push_back(0);
310 ++depth;
311 }
312 prev_die_had_children = die_has_children;
313 }
314
315 if (depth == 0)
316 break; // We are done with this compile unit!
317 }
318
319 if (!m_die_array.empty()) {
320 // The last die cannot have children (if it did, it wouldn't be the last
321 // one). This only makes a difference for malformed dwarf that does not have
322 // a terminating null die.
323 m_die_array.back().SetHasChildren(false);
324
325 if (m_first_die) {
326 // Only needed for the assertion.
327 m_first_die.SetHasChildren(m_die_array.front().HasChildren());
329 }
330 m_first_die = m_die_array.front();
331 }
332
333 m_die_array.shrink_to_fit();
334
335 if (m_dwo)
336 m_dwo->ExtractDIEsIfNeeded();
337}
338
339// This is used when a split dwarf is enabled.
340// A skeleton compilation unit may contain the DW_AT_str_offsets_base attribute
341// that points to the first string offset of the CU contribution to the
342// .debug_str_offsets. At the same time, the corresponding split debug unit also
343// may use DW_FORM_strx* forms pointing to its own .debug_str_offsets.dwo and
344// for that case, we should find the offset (skip the section header).
346 lldb::offset_t baseOffset = 0;
347
348 if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) {
349 if (const auto *contribution =
350 entry->getContribution(llvm::DW_SECT_STR_OFFSETS))
351 baseOffset = contribution->getOffset();
352 else
353 return;
354 }
355
356 if (GetVersion() >= 5) {
357 const DWARFDataExtractor &strOffsets =
359 uint64_t length = strOffsets.GetU32(&baseOffset);
360 if (length == 0xffffffff)
361 length = strOffsets.GetU64(&baseOffset);
362
363 // Check version.
364 if (strOffsets.GetU16(&baseOffset) < 5)
365 return;
366
367 // Skip padding.
368 baseOffset += 2;
369 }
370
371 SetStrOffsetsBase(baseOffset);
372}
373
374std::optional<uint64_t> DWARFUnit::GetDWOId() {
376 return m_dwo_id;
377}
378
379// m_die_array_mutex must be already held as read/write.
381 DWARFAttributes attributes = cu_die.GetAttributes(this);
382
383 // Extract DW_AT_addr_base first, as other attributes may need it.
384 for (size_t i = 0; i < attributes.Size(); ++i) {
385 if (attributes.AttributeAtIndex(i) != DW_AT_addr_base)
386 continue;
387 DWARFFormValue form_value;
388 if (attributes.ExtractFormValueAtIndex(i, form_value)) {
389 SetAddrBase(form_value.Unsigned());
390 break;
391 }
392 }
393
394 for (size_t i = 0; i < attributes.Size(); ++i) {
395 dw_attr_t attr = attributes.AttributeAtIndex(i);
396 DWARFFormValue form_value;
397 if (!attributes.ExtractFormValueAtIndex(i, form_value))
398 continue;
399 switch (attr) {
400 default:
401 break;
402 case DW_AT_loclists_base:
403 SetLoclistsBase(form_value.Unsigned());
404 break;
405 case DW_AT_rnglists_base:
406 SetRangesBase(form_value.Unsigned());
407 break;
408 case DW_AT_str_offsets_base:
409 SetStrOffsetsBase(form_value.Unsigned());
410 break;
411 case DW_AT_low_pc:
412 SetBaseAddress(form_value.Address());
413 break;
414 case DW_AT_entry_pc:
415 // If the value was already set by DW_AT_low_pc, don't update it.
417 SetBaseAddress(form_value.Address());
418 break;
419 case DW_AT_stmt_list:
420 m_line_table_offset = form_value.Unsigned();
421 break;
422 case DW_AT_GNU_addr_base:
423 m_gnu_addr_base = form_value.Unsigned();
424 break;
425 case DW_AT_GNU_ranges_base:
426 m_gnu_ranges_base = form_value.Unsigned();
427 break;
428 case DW_AT_GNU_dwo_id:
429 m_dwo_id = form_value.Unsigned();
430 break;
431 }
432 }
433
434 if (m_is_dwo) {
437 return;
438 }
439}
440
443}
444
445const llvm::DWARFAbbreviationDeclarationSet *
447 return m_abbrevs;
448}
449
451 return m_abbrevs ? m_abbrevs->getOffset() : DW_INVALID_OFFSET;
452}
453
456 return m_line_table_offset;
457}
458
459void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; }
460
461// Parse the rangelist table header, including the optional array of offsets
462// following it (DWARF v5 and later).
463template <typename ListTableType>
464static llvm::Expected<ListTableType>
465ParseListTableHeader(const llvm::DWARFDataExtractor &data, uint64_t offset,
466 DwarfFormat format) {
467 // We are expected to be called with Offset 0 or pointing just past the table
468 // header. Correct Offset in the latter case so that it points to the start
469 // of the header.
470 if (offset == 0) {
471 // This means DW_AT_rnglists_base is missing and therefore DW_FORM_rnglistx
472 // cannot be handled. Returning a default-constructed ListTableType allows
473 // DW_FORM_sec_offset to be supported.
474 return ListTableType();
475 }
476
477 uint64_t HeaderSize = llvm::DWARFListTableHeader::getHeaderSize(format);
478 if (offset < HeaderSize)
479 return llvm::createStringError(std::errc::invalid_argument,
480 "did not detect a valid"
481 " list table with base = 0x%" PRIx64 "\n",
482 offset);
483 offset -= HeaderSize;
484 ListTableType Table;
485 if (llvm::Error E = Table.extractHeaderAndOffsets(data, &offset))
486 return std::move(E);
487 return Table;
488}
489
491 uint64_t offset = 0;
492 if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) {
493 const auto *contribution = entry->getContribution(llvm::DW_SECT_LOCLISTS);
494 if (!contribution) {
495 GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
496 "Failed to find location list contribution for CU with DWO Id "
497 "{0:x16}",
498 *GetDWOId());
499 return;
500 }
501 offset += contribution->getOffset();
502 }
503 m_loclists_base = loclists_base;
504
505 uint64_t header_size = llvm::DWARFListTableHeader::getHeaderSize(DWARF32);
506 if (loclists_base < header_size)
507 return;
508
509 m_loclist_table_header.emplace(".debug_loclists", "locations");
510 offset += loclists_base - header_size;
511 if (llvm::Error E = m_loclist_table_header->extract(
513 &offset)) {
514 GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
515 "Failed to extract location list table at offset {0:x16} (location "
516 "list base: {1:x16}): {2}",
517 offset, loclists_base, toString(std::move(E)).c_str());
518 }
519}
520
521std::unique_ptr<llvm::DWARFLocationTable>
523 llvm::DWARFDataExtractor llvm_data(
525 data.GetAddressByteSize());
526
527 if (m_is_dwo || GetVersion() >= 5)
528 return std::make_unique<llvm::DWARFDebugLoclists>(llvm_data, GetVersion());
529 return std::make_unique<llvm::DWARFDebugLoc>(llvm_data);
530}
531
534 const DWARFDataExtractor &data =
536 if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) {
537 if (const auto *contribution = entry->getContribution(
538 GetVersion() >= 5 ? llvm::DW_SECT_LOCLISTS : llvm::DW_SECT_EXT_LOC))
539 return DWARFDataExtractor(data, contribution->getOffset(),
540 contribution->getLength32());
541 return DWARFDataExtractor();
542 }
543 return data;
544}
545
548 const DWARFDataExtractor &data = Ctx.getOrLoadRngListsData();
549 if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) {
550 if (const auto *contribution =
551 entry->getContribution(llvm::DW_SECT_RNGLISTS))
552 return DWARFDataExtractor(data, contribution->getOffset(),
553 contribution->getLength32());
554 GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
555 "Failed to find range list contribution for CU with signature {0:x16}",
556 entry->getSignature());
557
558 return DWARFDataExtractor();
559 }
560 return data;
561}
562
565
566 m_ranges_base = ranges_base;
567}
568
569const std::optional<llvm::DWARFDebugRnglistTable> &
571 if (GetVersion() >= 5 && !m_rnglist_table_done) {
573 if (auto table_or_error =
574 ParseListTableHeader<llvm::DWARFDebugRnglistTable>(
575 GetRnglistData().GetAsLLVMDWARF(), m_ranges_base, DWARF32))
576 m_rnglist_table = std::move(table_or_error.get());
577 else
578 GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
579 "Failed to extract range list table at offset {0:x16}: {1}",
580 m_ranges_base, toString(table_or_error.takeError()).c_str());
581 }
582 return m_rnglist_table;
583}
584
585// This function is called only for DW_FORM_rnglistx.
586llvm::Expected<uint64_t> DWARFUnit::GetRnglistOffset(uint32_t Index) {
587 if (!GetRnglistTable())
588 return llvm::createStringError(std::errc::invalid_argument,
589 "missing or invalid range list table");
590 if (!m_ranges_base)
591 return llvm::createStringError(
592 std::errc::invalid_argument,
593 llvm::formatv("DW_FORM_rnglistx cannot be used without "
594 "DW_AT_rnglists_base for CU at {0:x16}",
595 GetOffset())
596 .str()
597 .c_str());
598 if (std::optional<uint64_t> off = GetRnglistTable()->getOffsetEntry(
599 GetRnglistData().GetAsLLVM(), Index))
600 return *off + m_ranges_base;
601 return llvm::createStringError(
602 std::errc::invalid_argument,
603 "invalid range list table index %u; OffsetEntryCount is %u, "
604 "DW_AT_rnglists_base is %" PRIu64,
605 Index, GetRnglistTable()->getOffsetEntryCount(), m_ranges_base);
606}
607
609 m_str_offsets_base = str_offsets_base;
610}
611
613 uint32_t index_size = GetAddressByteSize();
614 dw_offset_t addr_base = GetAddrBase();
615 dw_addr_t offset = addr_base + static_cast<dw_addr_t>(index) * index_size;
616 const DWARFDataExtractor &data =
618 if (data.ValidOffsetForDataOfSize(offset, index_size))
619 return data.GetMaxU64_unchecked(&offset, index_size);
621}
622
623// It may be called only with m_die_array_mutex held R/W.
625 m_die_array.clear();
626 m_die_array.shrink_to_fit();
627
628 if (m_dwo && !m_dwo->m_cancel_scopes)
629 m_dwo->ClearDIEsRWLocked();
630}
631
634}
635
636void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; }
637
638// Compare function DWARFDebugAranges::Range structures
640 const dw_offset_t die_offset) {
641 return die.GetOffset() < die_offset;
642}
643
644// GetDIE()
645//
646// Get the DIE (Debug Information Entry) with the specified offset by first
647// checking if the DIE is contained within this compile unit and grabbing the
648// DIE from this compile unit. Otherwise we grab the DIE from the DWARF file.
651 if (die_offset == DW_INVALID_OFFSET)
652 return DWARFDIE(); // Not found
653
654 if (!ContainsDIEOffset(die_offset)) {
655 GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
656 "GetDIE for DIE {0:x16} is outside of its CU {0:x16}", die_offset,
657 GetOffset());
658 return DWARFDIE(); // Not found
659 }
660
664 lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset);
665
666 if (pos != end && die_offset == (*pos).GetOffset())
667 return DWARFDIE(this, &(*pos));
668 return DWARFDIE(); // Not found
669}
670
671llvm::StringRef DWARFUnit::PeekDIEName(dw_offset_t die_offset) {
673 if (!die.Extract(GetData(), this, &die_offset))
674 return llvm::StringRef();
675
676 // Does die contain a DW_AT_Name?
677 if (const char *name =
678 die.GetAttributeValueAsString(this, DW_AT_name, nullptr))
679 return name;
680
681 // Does its DW_AT_specification or DW_AT_abstract_origin contain an AT_Name?
682 for (auto attr : {DW_AT_specification, DW_AT_abstract_origin}) {
683 DWARFFormValue form_value;
684 if (!die.GetAttributeValue(this, attr, form_value))
685 continue;
686 auto [unit, offset] = form_value.ReferencedUnitAndOffset();
687 if (unit)
688 if (auto name = unit->PeekDIEName(offset); !name.empty())
689 return name;
690 }
691
692 return llvm::StringRef();
693}
694
697 if (m_dwo)
698 return *m_dwo;
699 return *this;
700}
701
703 if (cu)
704 return cu->GetAddressByteSize();
706}
707
708uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; }
709
711 if (m_skeleton_unit == nullptr && IsDWOUnit()) {
712 SymbolFileDWARFDwo *dwo =
713 llvm::dyn_cast_or_null<SymbolFileDWARFDwo>(&GetSymbolFileDWARF());
714 // Do a reverse lookup if the skeleton compile unit wasn't set.
715 if (dwo)
717 }
718 return llvm::dyn_cast_or_null<DWARFCompileUnit>(m_skeleton_unit);
719}
720
722 // If someone is re-setting the skeleton compile unit backlink, make sure
723 // it is setting it to a valid value when it wasn't valid, or if the
724 // value in m_skeleton_unit was valid, it should be the same value.
725 assert(skeleton_unit);
726 assert(m_skeleton_unit == nullptr || m_skeleton_unit == skeleton_unit);
727 m_skeleton_unit = skeleton_unit;
728}
729
731 return GetProducer() != eProducerLLVMGCC;
732}
733
735 // llvm-gcc makes completely invalid decl file attributes and won't ever be
736 // fixed, so we need to know to ignore these.
737 return GetProducer() == eProducerLLVMGCC;
738}
739
742 return GetProducerVersion() >= llvm::VersionTuple(425, 0, 13);
743 // Assume all other compilers didn't have incorrect ObjC bitfield info.
744 return true;
745}
746
750 if (!die)
751 return;
752
753 llvm::StringRef producer(
754 die->GetAttributeValueAsString(this, DW_AT_producer, nullptr));
755 if (producer.empty())
756 return;
757
758 static const RegularExpression g_swiftlang_version_regex(
759 llvm::StringRef(R"(swiftlang-([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?))"));
760 static const RegularExpression g_clang_version_regex(
761 llvm::StringRef(R"(clang-([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?))"));
762 static const RegularExpression g_llvm_gcc_regex(
763 llvm::StringRef(R"(4\.[012]\.[01] )"
764 R"(\‍(Based on Apple Inc\. build [0-9]+\) )"
765 R"(\‍(LLVM build [\.0-9]+\)$)"));
766
767 llvm::SmallVector<llvm::StringRef, 3> matches;
768 if (g_swiftlang_version_regex.Execute(producer, &matches)) {
769 m_producer_version.tryParse(matches[1]);
771 } else if (producer.contains("clang")) {
772 if (g_clang_version_regex.Execute(producer, &matches))
773 m_producer_version.tryParse(matches[1]);
775 } else if (producer.contains("GNU")) {
777 } else if (g_llvm_gcc_regex.Execute(producer)) {
779 }
780}
781
785 return m_producer;
786}
787
788llvm::VersionTuple DWARFUnit::GetProducerVersion() {
789 if (m_producer_version.empty())
791 return m_producer_version;
792}
793
795 if (m_language_type)
796 return *m_language_type;
797
799 if (!die)
800 m_language_type = 0;
801 else
802 m_language_type = die->GetAttributeValueAsUnsigned(this, DW_AT_language, 0);
803 return *m_language_type;
804}
805
809 if (die) {
811 if (die->GetAttributeValueAsUnsigned(this, DW_AT_APPLE_optimized, 0) ==
812 1) {
814 }
815 }
816 }
818}
819
821 if (!m_comp_dir)
823 return m_comp_dir->GetPathStyle();
824}
825
827 if (!m_comp_dir)
829 return *m_comp_dir;
830}
831
833 if (!m_file_spec)
835 return *m_file_spec;
836}
837
838FileSpec DWARFUnit::GetFile(size_t file_idx) {
839 return m_dwarf.GetFile(*this, file_idx);
840}
841
842// DWARF2/3 suggests the form hostname:pathname for compilation directory.
843// Remove the host part if present.
844static llvm::StringRef
845removeHostnameFromPathname(llvm::StringRef path_from_dwarf) {
846 if (!path_from_dwarf.contains(':'))
847 return path_from_dwarf;
848 llvm::StringRef host, path;
849 std::tie(host, path) = path_from_dwarf.split(':');
850
851 if (host.contains('/'))
852 return path_from_dwarf;
853
854 // check whether we have a windows path, and so the first character is a
855 // drive-letter not a hostname.
856 if (host.size() == 1 && llvm::isAlpha(host[0]) &&
857 (path.starts_with("\\") || path.starts_with("/")))
858 return path_from_dwarf;
859
860 return path;
861}
862
866 if (!die)
867 return;
868
869 llvm::StringRef comp_dir = removeHostnameFromPathname(
870 die->GetAttributeValueAsString(this, DW_AT_comp_dir, nullptr));
871 if (!comp_dir.empty()) {
872 FileSpec::Style comp_dir_style =
873 FileSpec::GuessPathStyle(comp_dir).value_or(FileSpec::Style::native);
874 m_comp_dir = FileSpec(comp_dir, comp_dir_style);
875 } else {
876 // Try to detect the style based on the DW_AT_name attribute, but just store
877 // the detected style in the m_comp_dir field.
878 const char *name =
879 die->GetAttributeValueAsString(this, DW_AT_name, nullptr);
881 "", FileSpec::GuessPathStyle(name).value_or(FileSpec::Style::native));
882 }
883}
884
888 if (!die)
889 return;
890
892 FileSpec(die->GetAttributeValueAsString(this, DW_AT_name, nullptr),
893 GetPathStyle());
894
895 if (m_file_spec->IsRelative())
896 m_file_spec->MakeAbsolute(GetCompilationDirectory());
897}
898
900 if (load_all_debug_info)
902 if (m_dwo)
903 return &llvm::cast<SymbolFileDWARFDwo>(m_dwo->GetSymbolFileDWARF());
904 return nullptr;
905}
906
908 if (m_func_aranges_up == nullptr) {
909 m_func_aranges_up = std::make_unique<DWARFDebugAranges>();
910 const DWARFDebugInfoEntry *die = DIEPtr();
911 if (die)
913
914 if (m_dwo) {
915 const DWARFDebugInfoEntry *dwo_die = m_dwo->DIEPtr();
916 if (dwo_die)
918 m_func_aranges_up.get());
919 }
920
921 const bool minimize = false;
922 m_func_aranges_up->Sort(minimize);
923 }
924 return *m_func_aranges_up;
925}
926
928 const llvm::DWARFUnitIndex::Entry *index_entry) {
929 // We should only be calling this function when the index entry is not set and
930 // we have a valid one to set it to.
931 assert(index_entry);
932 assert(!m_index_entry);
933
934 if (m_abbr_offset)
935 return llvm::createStringError(
936 llvm::inconvertibleErrorCode(),
937 "Package unit with a non-zero abbreviation offset");
938
939 auto *unit_contrib = index_entry->getContribution();
940 if (!unit_contrib || unit_contrib->getLength32() != m_length + 4)
941 return llvm::createStringError(llvm::inconvertibleErrorCode(),
942 "Inconsistent DWARF package unit index");
943
944 auto *abbr_entry = index_entry->getContribution(llvm::DW_SECT_ABBREV);
945 if (!abbr_entry)
946 return llvm::createStringError(
947 llvm::inconvertibleErrorCode(),
948 "DWARF package index missing abbreviation column");
949
950 m_abbr_offset = abbr_entry->getOffset();
951 m_index_entry = index_entry;
952 return llvm::Error::success();
953}
954
955llvm::Expected<DWARFUnitHeader>
957 DIERef::Section section, DWARFContext &context,
958 lldb::offset_t *offset_ptr) {
959 DWARFUnitHeader header;
960 header.m_offset = *offset_ptr;
961 header.m_length = data.GetDWARFInitialLength(offset_ptr);
962 header.m_version = data.GetU16(offset_ptr);
963 if (header.m_version == 5) {
964 header.m_unit_type = data.GetU8(offset_ptr);
965 header.m_addr_size = data.GetU8(offset_ptr);
966 header.m_abbr_offset = data.GetDWARFOffset(offset_ptr);
967 if (header.m_unit_type == llvm::dwarf::DW_UT_skeleton ||
968 header.m_unit_type == llvm::dwarf::DW_UT_split_compile)
969 header.m_dwo_id = data.GetU64(offset_ptr);
970 } else {
971 header.m_abbr_offset = data.GetDWARFOffset(offset_ptr);
972 header.m_addr_size = data.GetU8(offset_ptr);
973 header.m_unit_type =
974 section == DIERef::Section::DebugTypes ? DW_UT_type : DW_UT_compile;
975 }
976
977 if (header.IsTypeUnit()) {
978 header.m_type_hash = data.GetU64(offset_ptr);
979 header.m_type_offset = data.GetDWARFOffset(offset_ptr);
980 }
981
982 bool length_OK = data.ValidOffset(header.GetNextUnitOffset() - 1);
983 bool version_OK = SymbolFileDWARF::SupportedVersion(header.m_version);
984 bool addr_size_OK = (header.m_addr_size == 2) || (header.m_addr_size == 4) ||
985 (header.m_addr_size == 8);
986 bool type_offset_OK =
987 !header.IsTypeUnit() || (header.m_type_offset <= header.GetLength());
988
989 if (!length_OK)
990 return llvm::make_error<llvm::object::GenericBinaryError>(
991 "Invalid unit length");
992 if (!version_OK)
993 return llvm::make_error<llvm::object::GenericBinaryError>(
994 "Unsupported unit version");
995 if (!addr_size_OK)
996 return llvm::make_error<llvm::object::GenericBinaryError>(
997 "Invalid unit address size");
998 if (!type_offset_OK)
999 return llvm::make_error<llvm::object::GenericBinaryError>(
1000 "Type offset out of range");
1001
1002 return header;
1003}
1004
1005llvm::Expected<DWARFUnitSP>
1007 const DWARFDataExtractor &debug_info,
1008 DIERef::Section section, lldb::offset_t *offset_ptr) {
1009 assert(debug_info.ValidOffset(*offset_ptr));
1010
1011 DWARFContext &context = dwarf.GetDWARFContext();
1012 auto expected_header =
1013 DWARFUnitHeader::extract(debug_info, section, context, offset_ptr);
1014 if (!expected_header)
1015 return expected_header.takeError();
1016
1017 if (context.isDwo()) {
1018 const llvm::DWARFUnitIndex::Entry *entry = nullptr;
1019 const llvm::DWARFUnitIndex &index = expected_header->IsTypeUnit()
1020 ? context.GetAsLLVM().getTUIndex()
1021 : context.GetAsLLVM().getCUIndex();
1022 if (index) {
1023 if (expected_header->IsTypeUnit())
1024 entry = index.getFromHash(expected_header->GetTypeHash());
1025 else if (auto dwo_id = expected_header->GetDWOId())
1026 entry = index.getFromHash(*dwo_id);
1027 }
1028 if (!entry)
1029 entry = index.getFromOffset(expected_header->GetOffset());
1030 if (entry)
1031 if (llvm::Error err = expected_header->ApplyIndexEntry(entry))
1032 return std::move(err);
1033 }
1034
1035 const llvm::DWARFDebugAbbrev *abbr = dwarf.DebugAbbrev();
1036 if (!abbr)
1037 return llvm::make_error<llvm::object::GenericBinaryError>(
1038 "No debug_abbrev data");
1039
1040 bool abbr_offset_OK =
1041 dwarf.GetDWARFContext().getOrLoadAbbrevData().ValidOffset(
1042 expected_header->GetAbbrOffset());
1043 if (!abbr_offset_OK)
1044 return llvm::make_error<llvm::object::GenericBinaryError>(
1045 "Abbreviation offset for unit is not valid");
1046
1047 llvm::Expected<const llvm::DWARFAbbreviationDeclarationSet *> abbrevs_or_err =
1048 abbr->getAbbreviationDeclarationSet(expected_header->GetAbbrOffset());
1049 if (!abbrevs_or_err)
1050 return abbrevs_or_err.takeError();
1051
1052 const llvm::DWARFAbbreviationDeclarationSet *abbrevs = *abbrevs_or_err;
1053 if (!abbrevs)
1054 return llvm::make_error<llvm::object::GenericBinaryError>(
1055 "No abbrev exists at the specified offset.");
1056
1057 bool is_dwo = dwarf.GetDWARFContext().isDwo();
1058 if (expected_header->IsTypeUnit())
1059 return DWARFUnitSP(new DWARFTypeUnit(dwarf, uid, *expected_header, *abbrevs,
1060 section, is_dwo));
1061 return DWARFUnitSP(new DWARFCompileUnit(dwarf, uid, *expected_header,
1062 *abbrevs, section, is_dwo));
1063}
1064
1069}
1070
1072 switch (m_header.GetUnitType()) {
1073 case llvm::dwarf::DW_UT_compile:
1074 case llvm::dwarf::DW_UT_partial:
1075 return GetVersion() < 5 ? 11 : 12;
1076 case llvm::dwarf::DW_UT_skeleton:
1077 case llvm::dwarf::DW_UT_split_compile:
1078 return 20;
1079 case llvm::dwarf::DW_UT_type:
1080 case llvm::dwarf::DW_UT_split_type:
1081 return GetVersion() < 5 ? 23 : 24;
1082 }
1083 llvm_unreachable("invalid UnitType.");
1084}
1085
1086std::optional<uint64_t>
1088 offset_t offset = GetStrOffsetsBase() + index * 4;
1090}
1091
1092llvm::Expected<DWARFRangeList>
1094 if (GetVersion() <= 4) {
1095 const DWARFDebugRanges *debug_ranges = m_dwarf.GetDebugRanges();
1096 if (!debug_ranges)
1097 return llvm::make_error<llvm::object::GenericBinaryError>(
1098 "No debug_ranges section");
1099 return debug_ranges->FindRanges(this, offset);
1100 }
1101
1102 if (!GetRnglistTable())
1103 return llvm::createStringError(std::errc::invalid_argument,
1104 "missing or invalid range list table");
1105
1106 llvm::DWARFDataExtractor data = GetRnglistData().GetAsLLVMDWARF();
1107
1108 // As DW_AT_rnglists_base may be missing we need to call setAddressSize.
1109 data.setAddressSize(m_header.GetAddressByteSize());
1110 auto range_list_or_error = GetRnglistTable()->findList(data, offset);
1111 if (!range_list_or_error)
1112 return range_list_or_error.takeError();
1113
1114 llvm::Expected<llvm::DWARFAddressRangesVector> llvm_ranges =
1115 range_list_or_error->getAbsoluteRanges(
1116 llvm::object::SectionedAddress{GetBaseAddress()},
1117 GetAddressByteSize(), [&](uint32_t index) {
1118 uint32_t index_size = GetAddressByteSize();
1119 dw_offset_t addr_base = GetAddrBase();
1120 lldb::offset_t offset =
1121 addr_base + static_cast<lldb::offset_t>(index) * index_size;
1122 return llvm::object::SectionedAddress{
1124 &offset, index_size)};
1125 });
1126 if (!llvm_ranges)
1127 return llvm_ranges.takeError();
1128
1129 DWARFRangeList ranges;
1130 for (const llvm::DWARFAddressRange &llvm_range : *llvm_ranges) {
1131 ranges.Append(DWARFRangeList::Entry(llvm_range.LowPC,
1132 llvm_range.HighPC - llvm_range.LowPC));
1133 }
1134 return ranges;
1135}
1136
1137llvm::Expected<DWARFRangeList> DWARFUnit::FindRnglistFromIndex(uint32_t index) {
1138 llvm::Expected<uint64_t> maybe_offset = GetRnglistOffset(index);
1139 if (!maybe_offset)
1140 return maybe_offset.takeError();
1141 return FindRnglistFromOffset(*maybe_offset);
1142}
1143
1144bool DWARFUnit::HasAny(llvm::ArrayRef<dw_tag_t> tags) {
1146 if (m_dwo)
1147 return m_dwo->HasAny(tags);
1148
1149 for (const auto &die : m_die_array) {
1150 for (const auto tag : tags) {
1151 if (tag == die.Tag())
1152 return true;
1153 }
1154 }
1155 return false;
1156}
static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, const dw_offset_t die_offset)
Definition: DWARFUnit.cpp:639
static llvm::Expected< ListTableType > ParseListTableHeader(const llvm::DWARFDataExtractor &data, uint64_t offset, DwarfFormat format)
Definition: DWARFUnit.cpp:465
static llvm::StringRef removeHostnameFromPathname(llvm::StringRef path_from_dwarf)
Definition: DWARFUnit.cpp:845
int g_verbose
#define lldbassert(x)
Definition: LLDBAssert.h:15
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end)
Definition: Statistics.cpp:38
static std::optional< uint64_t > GetDWOId(DWARFCompileUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die)
Return the DW_AT_(GNU_)dwo_id.
#define LLDB_SCOPED_TIMERF(...)
Definition: Timer.h:86
uint64_t GetDWARFInitialLength(lldb::offset_t *offset_ptr) const
llvm::DWARFDataExtractor GetAsLLVMDWARF() const
dw_offset_t GetDWARFOffset(lldb::offset_t *offset_ptr) const
An data extractor class.
Definition: DataExtractor.h:48
uint64_t GetU64(lldb::offset_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
const void * GetData(lldb::offset_t *offset_ptr, lldb::offset_t length) const
Extract length bytes from *offset_ptr.
uint64_t GetMaxU64_unchecked(lldb::offset_t *offset_ptr, size_t byte_size) const
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
uint16_t GetU16(lldb::offset_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
bool ValidOffset(lldb::offset_t offset) const
Test the validity of offset.
uint32_t GetAddressByteSize() const
Get the current address size.
uint64_t GetMaxU64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an unsigned integer of size byte_size from *offset_ptr.
lldb::ByteOrder GetByteOrder() const
Get the current byte order value.
uint8_t GetU8(lldb::offset_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
A class that measures elapsed time in an exception safe way.
Definition: Statistics.h:68
A file utility class.
Definition: FileSpec.h:56
static std::optional< Style > GuessPathStyle(llvm::StringRef absolute_path)
Attempt to guess path style for a given path string.
Definition: FileSpec.cpp:310
llvm::sys::path::Style Style
Definition: FileSpec.h:58
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
Definition: ModuleChild.cpp:24
virtual lldb::ByteOrder GetByteOrder() const =0
Gets whether endian swapping should occur when extracting data from this object file.
void Append(const Entry &entry)
Definition: RangeMap.h:179
bool Execute(llvm::StringRef string, llvm::SmallVectorImpl< llvm::StringRef > *matches=nullptr) const
Execute a regular expression match using the compiled regular expression that is already in this obje...
void Clear()
Clear the object state.
Definition: Status.cpp:167
static Status createWithFormat(const char *format, Args &&...args)
Definition: Status.h:68
ObjectFile * GetObjectFile() override
Definition: SymbolFile.h:525
dw_attr_t AttributeAtIndex(uint32_t i) const
bool ExtractFormValueAtIndex(uint32_t i, DWARFFormValue &form_value) const
const DWARFDataExtractor & getOrLoadLocListsData()
const DWARFDataExtractor & getOrLoadStrOffsetsData()
const DWARFDataExtractor & getOrLoadDebugTypesData()
const DWARFDataExtractor & getOrLoadDebugInfoData()
const DWARFDataExtractor & getOrLoadRngListsData()
const DWARFDataExtractor & getOrLoadLocData()
const DWARFDataExtractor & getOrLoadAddrData()
DWARFDebugInfoEntry objects assume that they are living in one big vector and do pointer arithmetic o...
const char * GetAttributeValueAsString(const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value, bool check_specification_or_abstract_origin=false) const
dw_offset_t GetAttributeValue(const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &formValue, dw_offset_t *end_attr_offset_ptr=nullptr, bool check_specification_or_abstract_origin=false) const
DWARFAttributes GetAttributes(DWARFUnit *cu, Recurse recurse=Recurse::yes) const
void BuildFunctionAddressRangeTable(DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const
This function is builds a table very similar to the standard .debug_aranges table,...
uint64_t GetAttributeValueAsUnsigned(const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_specification_or_abstract_origin=false) const
bool Extract(const DWARFDataExtractor &data, const DWARFUnit *cu, lldb::offset_t *offset_ptr)
DWARFRangeList FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset) const
std::pair< DWARFUnit *, uint64_t > ReferencedUnitAndOffset() const
If this is a reference to another DIE, return the corresponding DWARFUnit and DIE offset such that Un...
Base class describing the header of any kind of "unit." Some information is specific to certain unit ...
Definition: DWARFUnit.h:44
const llvm::DWARFUnitIndex::Entry * GetIndexEntry() const
Definition: DWARFUnit.h:69
llvm::Error ApplyIndexEntry(const llvm::DWARFUnitIndex::Entry *index_entry)
Definition: DWARFUnit.cpp:927
static llvm::Expected< DWARFUnitHeader > extract(const DWARFDataExtractor &data, DIERef::Section section, DWARFContext &dwarf_context, lldb::offset_t *offset_ptr)
Definition: DWARFUnit.cpp:956
std::optional< uint64_t > m_dwo_id
Definition: DWARFUnit.h:58
const ScopedExtractDIEs & operator=(const ScopedExtractDIEs &)=delete
std::optional< dw_addr_t > m_addr_base
Value of DW_AT_addr_base.
Definition: DWARFUnit.h:383
std::unique_ptr< llvm::DWARFLocationTable > GetLocationTable(const DataExtractor &data) const
Return the location table for parsing the given location list data.
Definition: DWARFUnit.cpp:522
std::optional< FileSpec > m_file_spec
Definition: DWARFUnit.h:382
size_t GetLengthByteSize() const
Get the size in bytes of the length field in the header.
Definition: DWARFUnit.h:153
std::optional< llvm::DWARFDebugRnglistTable > m_rnglist_table
Definition: DWARFUnit.h:394
const DWARFDebugInfoEntry * GetUnitDIEPtrOnly()
Definition: DWARFUnit.h:333
llvm::sys::RWMutex m_die_array_mutex
Definition: DWARFUnit.h:362
dw_offset_t m_line_table_offset
Value of DW_AT_stmt_list.
Definition: DWARFUnit.h:390
llvm::sys::RWMutex m_die_array_scoped_mutex
Definition: DWARFUnit.h:364
void SetStrOffsetsBase(dw_offset_t str_offsets_base)
Definition: DWARFUnit.cpp:608
std::atomic< bool > m_cancel_scopes
Definition: DWARFUnit.h:367
Status m_dwo_error
If we get an error when trying to load a .dwo file, save that error here.
Definition: DWARFUnit.h:406
void SetLoclistsBase(dw_addr_t loclists_base)
Definition: DWARFUnit.cpp:490
SymbolFileDWARF & GetSymbolFileDWARF() const
Definition: DWARFUnit.h:229
const DWARFDebugAranges & GetFunctionAranges()
Definition: DWARFUnit.cpp:907
const DWARFDataExtractor & GetData() const
Get the data that contains the DIE information for this unit.
Definition: DWARFUnit.cpp:1065
static llvm::Expected< DWARFUnitSP > extract(SymbolFileDWARF &dwarf2Data, lldb::user_id_t uid, const DWARFDataExtractor &debug_info, DIERef::Section section, lldb::offset_t *offset_ptr)
Definition: DWARFUnit.cpp:1006
DWARFCompileUnit * GetSkeletonUnit()
Get the skeleton compile unit for a DWO file.
Definition: DWARFUnit.cpp:710
dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const
Definition: DWARFUnit.cpp:612
const DWARFDebugInfoEntry * DIEPtr()
Definition: DWARFUnit.h:342
bool ContainsDIEOffset(dw_offset_t die_offset) const
Definition: DWARFUnit.h:155
std::optional< FileSpec > m_comp_dir
Definition: DWARFUnit.h:381
dw_offset_t GetFirstDIEOffset() const
Definition: DWARFUnit.h:159
std::optional< uint64_t > m_language_type
Definition: DWARFUnit.h:379
llvm::StringRef PeekDIEName(dw_offset_t die_offset)
Returns the AT_Name of the DIE at die_offset, if it exists, without parsing the entire compile unit.
Definition: DWARFUnit.cpp:671
DWARFDebugInfoEntry::collection m_die_array
Definition: DWARFUnit.h:361
void SetBaseAddress(dw_addr_t base_addr)
Definition: DWARFUnit.cpp:636
std::optional< uint64_t > m_gnu_ranges_base
Definition: DWARFUnit.h:387
const llvm::DWARFAbbreviationDeclarationSet * m_abbrevs
Definition: DWARFUnit.h:356
const DIERef::Section m_section
Definition: DWARFUnit.h:398
dw_offset_t GetNextUnitOffset() const
Definition: DWARFUnit.h:162
DWARFDataExtractor GetLocationData() const
Definition: DWARFUnit.cpp:532
const std::optional< llvm::DWARFDebugRnglistTable > & GetRnglistTable()
Definition: DWARFUnit.cpp:570
llvm::Expected< uint64_t > GetRnglistOffset(uint32_t Index)
Return a rangelist's offset based on an index.
Definition: DWARFUnit.cpp:586
std::unique_ptr< DWARFDebugAranges > m_func_aranges_up
Definition: DWARFUnit.h:375
void SetSkeletonUnit(DWARFUnit *skeleton_unit)
Definition: DWARFUnit.cpp:721
dw_addr_t m_ranges_base
Value of DW_AT_rnglists_base.
Definition: DWARFUnit.h:385
dw_addr_t m_loclists_base
Value of DW_AT_loclists_base.
Definition: DWARFUnit.h:384
void SetRangesBase(dw_addr_t ranges_base)
Definition: DWARFUnit.cpp:563
uint32_t GetHeaderByteSize() const
Get the size in bytes of the unit header.
Definition: DWARFUnit.cpp:1071
void SetAddrBase(dw_addr_t addr_base)
Definition: DWARFUnit.cpp:459
llvm::Expected< DWARFRangeList > FindRnglistFromIndex(uint32_t index)
Return a list of address ranges retrieved from an encoded range list whose offset is found via a tabl...
Definition: DWARFUnit.cpp:1137
std::optional< llvm::DWARFListTableHeader > m_loclist_table_header
Definition: DWARFUnit.h:396
llvm::VersionTuple GetProducerVersion()
Definition: DWARFUnit.cpp:788
std::optional< uint64_t > m_dwo_id
Value of DW_AT_GNU_dwo_id (v4) or dwo_id from CU header (v5).
Definition: DWARFUnit.h:402
std::shared_ptr< DWARFUnit > m_dwo
Definition: DWARFUnit.h:354
std::optional< uint64_t > m_gnu_addr_base
Definition: DWARFUnit.h:386
llvm::VersionTuple m_producer_version
Definition: DWARFUnit.h:378
std::optional< uint64_t > GetStringOffsetSectionItem(uint32_t index) const
Definition: DWARFUnit.cpp:1087
DWARFDIE GetDIE(dw_offset_t die_offset)
Definition: DWARFUnit.cpp:650
lldb::ByteOrder GetByteOrder() const
Definition: DWARFUnit.cpp:632
void AddUnitDIE(const DWARFDebugInfoEntry &cu_die)
Definition: DWARFUnit.cpp:380
void SetDwoError(const Status &error)
Set the fission .dwo file specific error for this compile unit.
Definition: DWARFUnit.h:319
llvm::sys::RWMutex m_first_die_mutex
Definition: DWARFUnit.h:372
SymbolFileDWARFDwo * GetDwoSymbolFile(bool load_all_debug_info=true)
Definition: DWARFUnit.cpp:899
const FileSpec & GetCompilationDirectory()
Definition: DWARFUnit.cpp:826
std::optional< uint64_t > GetDWOId()
Get the DWO ID from the DWARFUnitHeader for DWARF5, or from the unit DIE's DW_AT_dwo_id or DW_AT_GNU_...
Definition: DWARFUnit.cpp:374
const llvm::DWARFAbbreviationDeclarationSet * GetAbbreviations() const
Definition: DWARFUnit.cpp:446
bool HasAny(llvm::ArrayRef< dw_tag_t > tags)
Returns true if any DIEs in the unit match any DW_TAG values in tags.
Definition: DWARFUnit.cpp:1144
llvm::Expected< DWARFRangeList > FindRnglistFromOffset(dw_offset_t offset)
Return a list of address ranges resulting from a (possibly encoded) range list starting at a given of...
Definition: DWARFUnit.cpp:1093
DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, const DWARFUnitHeader &header, const llvm::DWARFAbbreviationDeclarationSet &abbrevs, DIERef::Section section, bool is_dwo)
Definition: DWARFUnit.cpp:35
DWARFDataExtractor GetRnglistData() const
Definition: DWARFUnit.cpp:546
FileSpec GetFile(size_t file_idx)
Definition: DWARFUnit.cpp:838
static bool SupportedVersion(uint16_t version)
DWARFUnit * GetSkeletonUnit(DWARFUnit *dwo_unit)
Given a DWO DWARFUnit, find the corresponding skeleton DWARFUnit in the main symbol file.
FileSpec GetFile(DWARFUnit &unit, size_t file_idx)
std::shared_ptr< SymbolFileDWARFDwo > GetDwoSymbolFileForCompileUnit(DWARFUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die)
uint64_t dw_offset_t
Definition: dwarf.h:31
#define DW_INVALID_OFFSET
Definition: dwarf.h:36
llvm::dwarf::Attribute dw_attr_t
Definition: dwarf.h:24
uint64_t dw_addr_t
Definition: dwarf.h:27
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
std::shared_ptr< DWARFUnit > DWARFUnitSP
Definition: DWARFUnit.h:30
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
const char * toString(AppleArm64ExceptionClass EC)
Definition: SBAddress.h:15
uint64_t offset_t
Definition: lldb-types.h:83
ByteOrder
Byte ordering definitions.
@ eByteOrderLittle
uint64_t user_id_t
Definition: lldb-types.h:80
A mix in class that contains a generic user ID.
Definition: UserID.h:31