diff options
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp')
| -rw-r--r-- | source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 108 |
1 files changed, 79 insertions, 29 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index f44b2bb97b2b..7afc71bc24f0 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -191,13 +191,6 @@ void DWARFUnit::ExtractDIEsRWLocked() { IsDWARF64()); while (offset < next_cu_offset && die.FastExtract(data, this, fixed_form_sizes, &offset)) { - // if (log) - // log->Printf("0x%8.8x: %*.*s%s%s", - // die.GetOffset(), - // depth * 2, depth * 2, "", - // DW_TAG_value_to_name (die.Tag()), - // die.HasChildren() ? " *" : ""); - const bool null_die = die.IsNULL(); if (depth == 0) { assert(m_die_array.empty() && "Compile unit DIE already added"); @@ -223,7 +216,7 @@ void DWARFUnit::ExtractDIEsRWLocked() { // the list (saves up to 25% in C++ code), we need a way to let the // DIE know that it actually doesn't have children. if (!m_die_array.empty()) - m_die_array.back().SetEmptyChildren(true); + m_die_array.back().SetHasChildren(false); } } else { die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]); @@ -244,9 +237,6 @@ void DWARFUnit::ExtractDIEsRWLocked() { if (depth > 0) --depth; - if (depth == 0) - break; // We are done with this compile unit! - prev_die_had_children = false; } else { die_index_stack.back() = m_die_array.size() - 1; @@ -258,10 +248,17 @@ void DWARFUnit::ExtractDIEsRWLocked() { } prev_die_had_children = die_has_children; } + + if (depth == 0) + break; // We are done with this compile unit! } if (!m_die_array.empty()) { - lldbassert(!m_first_die || m_first_die == m_die_array.front()); + if (m_first_die) { + // Only needed for the assertion. + m_first_die.SetHasChildren(m_die_array.front().HasChildren()); + lldbassert(m_first_die == m_die_array.front()); + } m_first_die = m_die_array.front(); } @@ -301,8 +298,46 @@ void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const { } } +// This is used when a split dwarf is enabled. +// A skeleton compilation unit may contain the DW_AT_str_offsets_base attribute +// that points to the first string offset of the CU contribution to the +// .debug_str_offsets. At the same time, the corresponding split debug unit also +// may use DW_FORM_strx* forms pointing to its own .debug_str_offsets.dwo and +// for that case, we should find the offset (skip the section header). +static void SetDwoStrOffsetsBase(DWARFUnit *dwo_cu) { + lldb::offset_t baseOffset = 0; + + const DWARFDataExtractor &strOffsets = + dwo_cu->GetSymbolFileDWARF()->get_debug_str_offsets_data(); + uint64_t length = strOffsets.GetU32(&baseOffset); + if (length == 0xffffffff) + length = strOffsets.GetU64(&baseOffset); + + // Check version. + if (strOffsets.GetU16(&baseOffset) < 5) + return; + + // Skip padding. + baseOffset += 2; + + dwo_cu->SetStrOffsetsBase(baseOffset); +} + // m_die_array_mutex must be already held as read/write. void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { + dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned( + m_dwarf, this, DW_AT_addr_base, LLDB_INVALID_ADDRESS); + if (addr_base != LLDB_INVALID_ADDRESS) + SetAddrBase(addr_base); + + dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned( + m_dwarf, this, DW_AT_rnglists_base, LLDB_INVALID_ADDRESS); + if (ranges_base != LLDB_INVALID_ADDRESS) + SetRangesBase(ranges_base); + + SetStrOffsetsBase(cu_die.GetAttributeValueAsUnsigned( + m_dwarf, this, DW_AT_str_offsets_base, 0)); + uint64_t base_addr = cu_die.GetAttributeValueAsAddress( m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); if (base_addr == LLDB_INVALID_ADDRESS) @@ -333,11 +368,25 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { m_dwo_symbol_file = std::move(dwo_symbol_file); - dw_addr_t addr_base = - cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_addr_base, 0); - dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned( - m_dwarf, this, DW_AT_GNU_ranges_base, 0); - dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset); + // Here for DWO CU we want to use the address base set in the skeleton unit + // (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base + // otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_* + // attributes which were applicable to the DWO units. The corresponding + // DW_AT_* attributes standardized in DWARF v5 are also applicable to the main + // unit in contrast. + if (addr_base == LLDB_INVALID_ADDRESS) + addr_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, + DW_AT_GNU_addr_base, 0); + dwo_cu->SetAddrBase(addr_base); + + if (ranges_base == LLDB_INVALID_ADDRESS) + ranges_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, + DW_AT_GNU_ranges_base, 0); + dwo_cu->SetRangesBase(ranges_base); + + dwo_cu->SetBaseObjOffset(m_offset); + + SetDwoStrOffsetsBase(dwo_cu); } DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { @@ -395,14 +444,20 @@ dw_offset_t DWARFUnit::GetAbbrevOffset() const { return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; } -void DWARFUnit::SetAddrBase(dw_addr_t addr_base, - dw_addr_t ranges_base, - dw_offset_t base_obj_offset) { - m_addr_base = addr_base; +void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; } + +void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) { m_ranges_base = ranges_base; +} + +void DWARFUnit::SetBaseObjOffset(dw_offset_t base_obj_offset) { m_base_obj_offset = base_obj_offset; } +void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) { + m_str_offsets_base = str_offsets_base; +} + // It may be called only with m_die_array_mutex held R/W. void DWARFUnit::ClearDIEsRWLocked() { m_die_array.clear(); @@ -586,9 +641,7 @@ void DWARFUnit::SetUserData(void *d) { } bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { - if (GetProducer() == eProducerLLVMGCC) - return false; - return true; + return GetProducer() != eProducerLLVMGCC; } bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { @@ -600,11 +653,8 @@ bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { bool DWARFUnit::Supports_unnamed_objc_bitfields() { if (GetProducer() == eProducerClang) { const uint32_t major_version = GetProducerVersionMajor(); - if (major_version > 425 || - (major_version == 425 && GetProducerVersionUpdate() >= 13)) - return true; - else - return false; + return major_version > 425 || + (major_version == 425 && GetProducerVersionUpdate() >= 13); } return true; // Assume all other compilers didn't have incorrect ObjC bitfield // info |
