summaryrefslogtreecommitdiff
path: root/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-08-20 20:51:52 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-08-20 20:51:52 +0000
commit5f29bb8a675e8f96452b632e7129113f7dec850e (patch)
tree3d3f2a0d3ad10872a4dcaba8ec8d1d20c87ab147 /source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
parent88c643b6fec27eec436c8d138fee6346e92337d6 (diff)
Notes
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp')
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp287
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
}