diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:51:52 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:51:52 +0000 |
commit | 5f29bb8a675e8f96452b632e7129113f7dec850e (patch) | |
tree | 3d3f2a0d3ad10872a4dcaba8ec8d1d20c87ab147 /source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp | |
parent | 88c643b6fec27eec436c8d138fee6346e92337d6 (diff) |
Notes
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp')
-rw-r--r-- | source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp | 287 |
1 files changed, 128 insertions, 159 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index dadc30dc918ac..100f35f8c6b02 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -1,9 +1,8 @@ //===-- DWARFDebugInfo.cpp --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -16,213 +15,183 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" +#include "llvm/Support/Casting.h" #include "DWARFCompileUnit.h" -#include "DWARFDebugAranges.h" +#include "DWARFContext.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" #include "DWARFDebugInfoEntry.h" #include "DWARFFormValue.h" -#include "LogChannelDWARF.h" +#include "DWARFTypeUnit.h" using namespace lldb; using namespace lldb_private; using namespace std; -//---------------------------------------------------------------------- // Constructor -//---------------------------------------------------------------------- -DWARFDebugInfo::DWARFDebugInfo() - : m_dwarf2Data(NULL), m_compile_units(), m_cu_aranges_ap() {} - -//---------------------------------------------------------------------- -// SetDwarfData -//---------------------------------------------------------------------- -void DWARFDebugInfo::SetDwarfData(SymbolFileDWARF *dwarf2Data) { - m_dwarf2Data = dwarf2Data; - m_compile_units.clear(); -} +DWARFDebugInfo::DWARFDebugInfo(SymbolFileDWARF &dwarf, + lldb_private::DWARFContext &context) + : m_dwarf(dwarf), m_context(context), m_units(), m_cu_aranges_up() {} + +llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() { + if (m_cu_aranges_up) + return *m_cu_aranges_up; + + m_cu_aranges_up = llvm::make_unique<DWARFDebugAranges>(); + const DWARFDataExtractor &debug_aranges_data = + m_context.getOrLoadArangesData(); + if (llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data)) + return std::move(error); + + // Make a list of all CUs represented by the arange data in the file. + std::set<dw_offset_t> cus_with_data; + for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) { + dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n); + if (offset != DW_INVALID_OFFSET) + cus_with_data.insert(offset); + } -DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() { - if (m_cu_aranges_ap.get() == NULL && m_dwarf2Data) { - Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); - - m_cu_aranges_ap.reset(new DWARFDebugAranges()); - const DWARFDataExtractor &debug_aranges_data = - m_dwarf2Data->get_debug_aranges_data(); - if (debug_aranges_data.GetByteSize() > 0) { - if (log) - log->Printf( - "DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from " - ".debug_aranges", - m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str()); - m_cu_aranges_ap->Extract(debug_aranges_data); - } + // Manually build arange data for everything that wasn't in the + // .debug_aranges table. + const size_t num_units = GetNumUnits(); + for (size_t idx = 0; idx < num_units; ++idx) { + DWARFUnit *cu = GetUnitAtIndex(idx); - // Make a list of all CUs represented by the arange data in the file. - std::set<dw_offset_t> cus_with_data; - for (size_t n = 0; n < m_cu_aranges_ap.get()->GetNumRanges(); n++) { - dw_offset_t offset = m_cu_aranges_ap.get()->OffsetAtIndex(n); - if (offset != DW_INVALID_OFFSET) - cus_with_data.insert(offset); - } + dw_offset_t offset = cu->GetOffset(); + if (cus_with_data.find(offset) == cus_with_data.end()) + cu->BuildAddressRangeTable(m_cu_aranges_up.get()); + } + + const bool minimize = true; + m_cu_aranges_up->Sort(minimize); + return *m_cu_aranges_up; +} - // Manually build arange data for everything that wasn't in the - // .debug_aranges table. - bool printed = false; - const size_t num_compile_units = GetNumCompileUnits(); - for (size_t idx = 0; idx < num_compile_units; ++idx) { - DWARFUnit *cu = GetCompileUnitAtIndex(idx); - - dw_offset_t offset = cu->GetOffset(); - if (cus_with_data.find(offset) == cus_with_data.end()) { - if (log) { - if (!printed) - log->Printf( - "DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing", - m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str()); - printed = true; - } - cu->BuildAddressRangeTable(m_dwarf2Data, m_cu_aranges_ap.get()); - } +void DWARFDebugInfo::ParseUnitsFor(DIERef::Section section) { + DWARFDataExtractor data = section == DIERef::Section::DebugTypes + ? m_context.getOrLoadDebugTypesData() + : m_context.getOrLoadDebugInfoData(); + lldb::offset_t offset = 0; + while (data.ValidOffset(offset)) { + llvm::Expected<DWARFUnitSP> unit_sp = + DWARFUnit::extract(m_dwarf, m_units.size(), data, section, &offset); + + if (!unit_sp) { + // FIXME: Propagate this error up. + llvm::consumeError(unit_sp.takeError()); + return; } - const bool minimize = true; - m_cu_aranges_ap->Sort(minimize); - } - return *m_cu_aranges_ap.get(); -} + // If it didn't return an error, then it should be returning a valid Unit. + assert(*unit_sp); + m_units.push_back(*unit_sp); + offset = (*unit_sp)->GetNextUnitOffset(); -void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() { - if (m_compile_units.empty()) { - if (m_dwarf2Data != NULL) { - lldb::offset_t offset = 0; - DWARFUnitSP cu_sp; - const auto &debug_info_data = m_dwarf2Data->get_debug_info_data(); - while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, debug_info_data, - &offset))) { - m_compile_units.push_back(cu_sp); - - offset = cu_sp->GetNextCompileUnitOffset(); - } + if (auto *type_unit = llvm::dyn_cast<DWARFTypeUnit>(unit_sp->get())) { + m_type_hash_to_unit_index.emplace_back(type_unit->GetTypeHash(), + unit_sp.get()->GetID()); } } } -size_t DWARFDebugInfo::GetNumCompileUnits() { - ParseCompileUnitHeadersIfNeeded(); - return m_compile_units.size(); -} +void DWARFDebugInfo::ParseUnitHeadersIfNeeded() { + if (!m_units.empty()) + return; -DWARFUnit *DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) { - DWARFUnit *cu = NULL; - if (idx < GetNumCompileUnits()) - cu = m_compile_units[idx].get(); - return cu; + ParseUnitsFor(DIERef::Section::DebugInfo); + ParseUnitsFor(DIERef::Section::DebugTypes); + llvm::sort(m_type_hash_to_unit_index, llvm::less_first()); } -bool DWARFDebugInfo::ContainsCompileUnit(const DWARFUnit *cu) const { - // Not a verify efficient function, but it is handy for use in assertions to - // make sure that a compile unit comes from a debug information file. - CompileUnitColl::const_iterator end_pos = m_compile_units.end(); - CompileUnitColl::const_iterator pos; +size_t DWARFDebugInfo::GetNumUnits() { + ParseUnitHeadersIfNeeded(); + return m_units.size(); +} - for (pos = m_compile_units.begin(); pos != end_pos; ++pos) { - if (pos->get() == cu) - return true; - } - return false; +DWARFUnit *DWARFDebugInfo::GetUnitAtIndex(user_id_t idx) { + DWARFUnit *cu = nullptr; + if (idx < GetNumUnits()) + cu = m_units[idx].get(); + return cu; } -bool DWARFDebugInfo::OffsetLessThanCompileUnitOffset( - dw_offset_t offset, const DWARFUnitSP &cu_sp) { - return offset < cu_sp->GetOffset(); +uint32_t DWARFDebugInfo::FindUnitIndex(DIERef::Section section, + dw_offset_t offset) { + ParseUnitHeadersIfNeeded(); + + // llvm::lower_bound is not used as for DIE offsets it would still return + // index +1 and GetOffset() returning index itself would be a special case. + auto pos = llvm::upper_bound( + m_units, std::make_pair(section, offset), + [](const std::pair<DIERef::Section, dw_offset_t> &lhs, + const DWARFUnitSP &rhs) { + return lhs < std::make_pair(rhs->GetDebugSection(), rhs->GetOffset()); + }); + uint32_t idx = std::distance(m_units.begin(), pos); + if (idx == 0) + return DW_INVALID_OFFSET; + return idx - 1; } -DWARFUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, - uint32_t *idx_ptr) { - DWARFUnitSP cu_sp; - uint32_t cu_idx = DW_INVALID_INDEX; - if (cu_offset != DW_INVALID_OFFSET) { - ParseCompileUnitHeadersIfNeeded(); - - // Watch out for single compile unit executable as they are pretty common - const size_t num_cus = m_compile_units.size(); - if (num_cus == 1) { - if (m_compile_units[0]->GetOffset() == cu_offset) { - cu_sp = m_compile_units[0]; - cu_idx = 0; - } - } else if (num_cus) { - CompileUnitColl::const_iterator end_pos = m_compile_units.end(); - CompileUnitColl::const_iterator begin_pos = m_compile_units.begin(); - CompileUnitColl::const_iterator pos = std::upper_bound( - begin_pos, end_pos, cu_offset, OffsetLessThanCompileUnitOffset); - if (pos != begin_pos) { - --pos; - if ((*pos)->GetOffset() == cu_offset) { - cu_sp = *pos; - cu_idx = std::distance(begin_pos, pos); - } - } - } +DWARFUnit *DWARFDebugInfo::GetUnitAtOffset(DIERef::Section section, + dw_offset_t cu_offset, + uint32_t *idx_ptr) { + uint32_t idx = FindUnitIndex(section, cu_offset); + DWARFUnit *result = GetUnitAtIndex(idx); + if (result && result->GetOffset() != cu_offset) { + result = nullptr; + idx = DW_INVALID_INDEX; } if (idx_ptr) - *idx_ptr = cu_idx; - return cu_sp.get(); + *idx_ptr = idx; + return result; } -DWARFUnit *DWARFDebugInfo::GetCompileUnit(const DIERef &die_ref) { - if (die_ref.cu_offset == DW_INVALID_OFFSET) - return GetCompileUnitContainingDIEOffset(die_ref.die_offset); - else - return GetCompileUnit(die_ref.cu_offset); +DWARFUnit *DWARFDebugInfo::GetUnit(const DIERef &die_ref) { + return GetUnitContainingDIEOffset(die_ref.section(), die_ref.die_offset()); } DWARFUnit * -DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) { - ParseCompileUnitHeadersIfNeeded(); - - DWARFUnitSP cu_sp; - - // Watch out for single compile unit executable as they are pretty common - const size_t num_cus = m_compile_units.size(); - if (num_cus == 1) { - if (m_compile_units[0]->ContainsDIEOffset(die_offset)) - return m_compile_units[0].get(); - } else if (num_cus) { - CompileUnitColl::const_iterator end_pos = m_compile_units.end(); - CompileUnitColl::const_iterator begin_pos = m_compile_units.begin(); - CompileUnitColl::const_iterator pos = std::upper_bound( - begin_pos, end_pos, die_offset, OffsetLessThanCompileUnitOffset); - if (pos != begin_pos) { - --pos; - if ((*pos)->ContainsDIEOffset(die_offset)) - return (*pos).get(); - } - } +DWARFDebugInfo::GetUnitContainingDIEOffset(DIERef::Section section, + dw_offset_t die_offset) { + uint32_t idx = FindUnitIndex(section, die_offset); + DWARFUnit *result = GetUnitAtIndex(idx); + if (result && !result->ContainsDIEOffset(die_offset)) + return nullptr; + return result; +} + +DWARFTypeUnit *DWARFDebugInfo::GetTypeUnitForHash(uint64_t hash) { + auto pos = llvm::lower_bound(m_type_hash_to_unit_index, + std::make_pair(hash, 0u), llvm::less_first()); + if (pos == m_type_hash_to_unit_index.end() || pos->first != hash) + return nullptr; + return llvm::cast<DWARFTypeUnit>(GetUnitAtIndex(pos->second)); +} - return nullptr; +bool DWARFDebugInfo::ContainsTypeUnits() { + ParseUnitHeadersIfNeeded(); + return !m_type_hash_to_unit_index.empty(); } DWARFDIE -DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) { - DWARFUnit *cu = GetCompileUnitContainingDIEOffset(die_offset); +DWARFDebugInfo::GetDIEForDIEOffset(DIERef::Section section, + dw_offset_t die_offset) { + DWARFUnit *cu = GetUnitContainingDIEOffset(section, die_offset); if (cu) return cu->GetDIE(die_offset); return DWARFDIE(); } -//---------------------------------------------------------------------- // GetDIE() // // Get the DIE (Debug Information Entry) with the specified offset. -//---------------------------------------------------------------------- DWARFDIE DWARFDebugInfo::GetDIE(const DIERef &die_ref) { - DWARFUnit *cu = GetCompileUnit(die_ref); + DWARFUnit *cu = GetUnit(die_ref); if (cu) - return cu->GetDIE(die_ref.die_offset); + return cu->GetDIE(die_ref.die_offset()); return DWARFDIE(); // Not found } |