diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp')
| -rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 170 |
1 files changed, 99 insertions, 71 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index ef3d2cf4d55..91af09e3a64 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -14,6 +14,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" @@ -35,19 +36,45 @@ DWARFUnit::DWARFUnit(SymbolFileDWARF *dwarf) : m_dwarf(dwarf) {} DWARFUnit::~DWARFUnit() {} //---------------------------------------------------------------------- -// ParseCompileUnitDIEsIfNeeded -// +// Parses first DIE of a compile unit. +//---------------------------------------------------------------------- +void DWARFUnit::ExtractUnitDIEIfNeeded() { + if (m_first_die) + return; // Already parsed + + static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); + Timer scoped_timer( + func_cat, "%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", m_offset); + + // Set the offset to that of the first DIE and calculate the start of the + // next compilation unit header. + lldb::offset_t offset = GetFirstDIEOffset(); + + // We are in our compile unit, parse starting at the offset we were told to + // parse + const DWARFDataExtractor &data = GetData(); + DWARFFormValue::FixedFormSizes fixed_form_sizes = + DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), + IsDWARF64()); + if (offset < GetNextCompileUnitOffset() && + m_first_die.FastExtract(data, this, fixed_form_sizes, &offset)) { + AddUnitDIE(m_first_die); + return; + } + + ExtractDIEsEndCheck(offset); +} + +//---------------------------------------------------------------------- // Parses a compile unit and indexes its DIEs if it hasn't already been done. //---------------------------------------------------------------------- -size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) { - const size_t initial_die_array_size = m_die_array.size(); - if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1) +bool DWARFUnit::ExtractDIEsIfNeeded() { + if (!m_die_array.empty()) return 0; // Already parsed static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer( - func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded( cu_die_only = %i )", - m_offset, cu_die_only); + func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", m_offset); // Set the offset to that of the first DIE and calculate the start of the // next compilation unit header. @@ -56,16 +83,14 @@ size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) { DWARFDebugInfoEntry die; // Keep a flat array of the DIE for binary lookup by DIE offset - if (!cu_die_only) { - Log *log( - LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS)); - if (log) { - m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( - log, - "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at " - ".debug_info[0x%8.8x]", - GetOffset()); - } + Log *log( + LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS)); + if (log) { + m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( + log, + "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at " + ".debug_info[0x%8.8x]", + GetOffset()); } uint32_t depth = 0; @@ -90,16 +115,21 @@ size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) { const bool null_die = die.IsNULL(); if (depth == 0) { - if (initial_die_array_size == 0) - AddUnitDIE(die); - uint64_t base_addr = die.GetAttributeValueAsAddress( - m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); - if (base_addr == LLDB_INVALID_ADDRESS) - base_addr = - die.GetAttributeValueAsAddress(m_dwarf, this, DW_AT_entry_pc, 0); - SetBaseAddress(base_addr); - if (cu_die_only) - return 1; + assert(m_die_array.empty() && "Compile unit DIE already added"); + + // The average bytes per DIE entry has been seen to be around 14-20 so + // lets pre-reserve half of that since we are now stripping the NULL + // tags. + + // Only reserve the memory if we are adding children of the main + // compile unit DIE. The compile unit DIE is always the first entry, so + // if our size is 1, then we are adding the first compile unit child + // DIE and should reserve the memory. + m_die_array.reserve(GetDebugInfoSize() / 24); + m_die_array.push_back(die); + + if (!m_first_die) + AddUnitDIE(m_die_array.front()); } else { if (null_die) { if (prev_die_had_children) { @@ -145,14 +175,9 @@ size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) { } } - // Give a little bit of info if we encounter corrupt DWARF (our offset should - // always terminate at or before the start of the next compilation unit - // header). - if (offset > next_cu_offset) { - m_dwarf->GetObjectFile()->GetModule()->ReportWarning( - "DWARF compile unit extends beyond its bounds cu 0x%8.8x at " - "0x%8.8" PRIx64 "\n", - GetOffset(), offset); + if (!m_die_array.empty()) { + lldbassert(!m_first_die || m_first_die == m_die_array.front()); + m_first_die = m_die_array.front(); } // Since std::vector objects will double their size, we really need to make a @@ -164,6 +189,34 @@ size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) { m_die_array.end()); exact_size_die_array.swap(m_die_array); } + + ExtractDIEsEndCheck(offset); + + if (!m_dwo_symbol_file) + return m_die_array.size(); + + DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); + size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(); + return m_die_array.size() + dwo_die_count - + 1; // We have 2 CU die, but we want to count it only as one +} + +//-------------------------------------------------------------------------- +// Final checks for both ExtractUnitDIEIfNeeded() and ExtractDIEsIfNeeded(). +//-------------------------------------------------------------------------- +void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const { + lldb::offset_t next_cu_offset = GetNextCompileUnitOffset(); + + // Give a little bit of info if we encounter corrupt DWARF (our offset should + // always terminate at or before the start of the next compilation unit + // header). + if (offset > GetNextCompileUnitOffset()) { + m_dwarf->GetObjectFile()->GetModule()->ReportWarning( + "DWARF compile unit extends beyond its bounds cu 0x%8.8x at " + "0x%8.8" PRIx64 "\n", + GetOffset(), offset); + } + Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); if (log && log->GetVerbose()) { StreamString strm; @@ -174,30 +227,16 @@ size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) { m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX); log->PutString(strm.GetString()); } - - if (!m_dwo_symbol_file) - return m_die_array.size(); - - DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); - size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(cu_die_only); - return m_die_array.size() + dwo_die_count - - 1; // We have 2 CU die, but we want to count it only as one } -void DWARFUnit::AddUnitDIE(DWARFDebugInfoEntry &die) { - assert(m_die_array.empty() && "Compile unit DIE already added"); +void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { + uint64_t base_addr = cu_die.GetAttributeValueAsAddress( + m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); + if (base_addr == LLDB_INVALID_ADDRESS) + base_addr = cu_die.GetAttributeValueAsAddress( + m_dwarf, this, DW_AT_entry_pc, 0); + SetBaseAddress(base_addr); - // The average bytes per DIE entry has been seen to be around 14-20 so lets - // pre-reserve half of that since we are now stripping the NULL tags. - - // Only reserve the memory if we are adding children of the main compile unit - // DIE. The compile unit DIE is always the first entry, so if our size is 1, - // then we are adding the first compile unit child DIE and should reserve the - // memory. - m_die_array.reserve(GetDebugInfoSize() / 24); - m_die_array.push_back(die); - - const DWARFDebugInfoEntry &cu_die = m_die_array.front(); std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file = m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die); if (!dwo_symbol_file) @@ -289,19 +328,8 @@ void DWARFUnit::SetAddrBase(dw_addr_t addr_base, } void DWARFUnit::ClearDIEs() { - if (m_die_array.size() > 1) { - // std::vectors never get any smaller when resized to a smaller size, or - // when clear() or erase() are called, the size will report that it is - // smaller, but the memory allocated remains intact (call capacity() to see - // this). So we need to create a temporary vector and swap the contents - // which will cause just the internal pointers to be swapped so that when - // "tmp_array" goes out of scope, it will destroy the contents. - - // Save at least the compile unit DIE - DWARFDebugInfoEntry::collection tmp_array; - m_die_array.swap(tmp_array); - m_die_array.push_back(tmp_array.front()); - } + m_die_array.clear(); + m_die_array.shrink_to_fit(); if (m_dwo_symbol_file) m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(); @@ -342,7 +370,7 @@ void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf, // If the DIEs weren't parsed, then we don't want all dies for all compile // units to stay loaded when they weren't needed. So we can end up parsing // the DWARF and then throwing them all away to keep memory usage down. - const bool clear_dies = ExtractDIEsIfNeeded(false) > 1; + const bool clear_dies = ExtractDIEsIfNeeded(); die = DIEPtr(); if (die) @@ -447,7 +475,7 @@ DWARFUnit::GetDIE(dw_offset_t die_offset) { return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset); if (ContainsDIEOffset(die_offset)) { - ExtractDIEsIfNeeded(false); + ExtractDIEsIfNeeded(); DWARFDebugInfoEntry::const_iterator end = m_die_array.cend(); DWARFDebugInfoEntry::const_iterator pos = lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset); |

