1dda28197Spatrick //===-- DWARFDebugInfo.cpp ------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "SymbolFileDWARF.h"
10061da546Spatrick
11061da546Spatrick #include <algorithm>
12061da546Spatrick #include <set>
13061da546Spatrick
14061da546Spatrick #include "lldb/Host/PosixApi.h"
15061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
16061da546Spatrick #include "lldb/Utility/RegularExpression.h"
17061da546Spatrick #include "lldb/Utility/Stream.h"
18061da546Spatrick #include "llvm/Support/Casting.h"
19061da546Spatrick
20061da546Spatrick #include "DWARFCompileUnit.h"
21061da546Spatrick #include "DWARFContext.h"
22061da546Spatrick #include "DWARFDebugAranges.h"
23061da546Spatrick #include "DWARFDebugInfo.h"
24061da546Spatrick #include "DWARFDebugInfoEntry.h"
25061da546Spatrick #include "DWARFFormValue.h"
26061da546Spatrick #include "DWARFTypeUnit.h"
27061da546Spatrick
28061da546Spatrick using namespace lldb;
29061da546Spatrick using namespace lldb_private;
30061da546Spatrick
31061da546Spatrick // Constructor
DWARFDebugInfo(SymbolFileDWARF & dwarf,lldb_private::DWARFContext & context)32061da546Spatrick DWARFDebugInfo::DWARFDebugInfo(SymbolFileDWARF &dwarf,
33061da546Spatrick lldb_private::DWARFContext &context)
34061da546Spatrick : m_dwarf(dwarf), m_context(context), m_units(), m_cu_aranges_up() {}
35061da546Spatrick
GetCompileUnitAranges()36be691f3bSpatrick const DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() {
37061da546Spatrick if (m_cu_aranges_up)
38061da546Spatrick return *m_cu_aranges_up;
39061da546Spatrick
40061da546Spatrick m_cu_aranges_up = std::make_unique<DWARFDebugAranges>();
41061da546Spatrick const DWARFDataExtractor &debug_aranges_data =
42061da546Spatrick m_context.getOrLoadArangesData();
43061da546Spatrick
44be691f3bSpatrick // Extract what we can from the .debug_aranges first.
45be691f3bSpatrick m_cu_aranges_up->extract(debug_aranges_data);
46be691f3bSpatrick
47be691f3bSpatrick // Make a list of all CUs represented by the .debug_aranges data.
48061da546Spatrick std::set<dw_offset_t> cus_with_data;
49061da546Spatrick for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) {
50061da546Spatrick dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n);
51061da546Spatrick if (offset != DW_INVALID_OFFSET)
52061da546Spatrick cus_with_data.insert(offset);
53061da546Spatrick }
54061da546Spatrick
55be691f3bSpatrick // Manually build arange data for everything that wasn't in .debug_aranges.
56*f6aab3d8Srobert // The .debug_aranges accelerator is not guaranteed to be complete.
57*f6aab3d8Srobert // Tools such as dsymutil can provide stronger guarantees than required by the
58*f6aab3d8Srobert // standard. Without that guarantee, we have to iterate over every CU in the
59*f6aab3d8Srobert // .debug_info and make sure there's a corresponding entry in the table and if
60*f6aab3d8Srobert // not, add one for every subprogram.
61*f6aab3d8Srobert ObjectFile *OF = m_dwarf.GetObjectFile();
62*f6aab3d8Srobert if (!OF || !OF->CanTrustAddressRanges()) {
63061da546Spatrick const size_t num_units = GetNumUnits();
64061da546Spatrick for (size_t idx = 0; idx < num_units; ++idx) {
65061da546Spatrick DWARFUnit *cu = GetUnitAtIndex(idx);
66061da546Spatrick
67061da546Spatrick dw_offset_t offset = cu->GetOffset();
68061da546Spatrick if (cus_with_data.find(offset) == cus_with_data.end())
69061da546Spatrick cu->BuildAddressRangeTable(m_cu_aranges_up.get());
70061da546Spatrick }
71*f6aab3d8Srobert }
72061da546Spatrick
73061da546Spatrick const bool minimize = true;
74061da546Spatrick m_cu_aranges_up->Sort(minimize);
75061da546Spatrick return *m_cu_aranges_up;
76061da546Spatrick }
77061da546Spatrick
ParseUnitsFor(DIERef::Section section)78061da546Spatrick void DWARFDebugInfo::ParseUnitsFor(DIERef::Section section) {
79061da546Spatrick DWARFDataExtractor data = section == DIERef::Section::DebugTypes
80061da546Spatrick ? m_context.getOrLoadDebugTypesData()
81061da546Spatrick : m_context.getOrLoadDebugInfoData();
82061da546Spatrick lldb::offset_t offset = 0;
83061da546Spatrick while (data.ValidOffset(offset)) {
84dda28197Spatrick llvm::Expected<DWARFUnitSP> unit_sp = DWARFUnit::extract(
85be691f3bSpatrick m_dwarf, m_units.size(), data, section, &offset);
86061da546Spatrick
87061da546Spatrick if (!unit_sp) {
88061da546Spatrick // FIXME: Propagate this error up.
89061da546Spatrick llvm::consumeError(unit_sp.takeError());
90061da546Spatrick return;
91061da546Spatrick }
92061da546Spatrick
93061da546Spatrick // If it didn't return an error, then it should be returning a valid Unit.
94061da546Spatrick assert(*unit_sp);
95061da546Spatrick m_units.push_back(*unit_sp);
96061da546Spatrick offset = (*unit_sp)->GetNextUnitOffset();
97061da546Spatrick
98061da546Spatrick if (auto *type_unit = llvm::dyn_cast<DWARFTypeUnit>(unit_sp->get())) {
99061da546Spatrick m_type_hash_to_unit_index.emplace_back(type_unit->GetTypeHash(),
100061da546Spatrick unit_sp.get()->GetID());
101061da546Spatrick }
102061da546Spatrick }
103061da546Spatrick }
104061da546Spatrick
ParseUnitHeadersIfNeeded()105061da546Spatrick void DWARFDebugInfo::ParseUnitHeadersIfNeeded() {
106dda28197Spatrick llvm::call_once(m_units_once_flag, [&] {
107061da546Spatrick ParseUnitsFor(DIERef::Section::DebugInfo);
108061da546Spatrick ParseUnitsFor(DIERef::Section::DebugTypes);
109061da546Spatrick llvm::sort(m_type_hash_to_unit_index, llvm::less_first());
110dda28197Spatrick });
111061da546Spatrick }
112061da546Spatrick
GetNumUnits()113061da546Spatrick size_t DWARFDebugInfo::GetNumUnits() {
114061da546Spatrick ParseUnitHeadersIfNeeded();
115061da546Spatrick return m_units.size();
116061da546Spatrick }
117061da546Spatrick
GetUnitAtIndex(size_t idx)118dda28197Spatrick DWARFUnit *DWARFDebugInfo::GetUnitAtIndex(size_t idx) {
119061da546Spatrick DWARFUnit *cu = nullptr;
120061da546Spatrick if (idx < GetNumUnits())
121061da546Spatrick cu = m_units[idx].get();
122061da546Spatrick return cu;
123061da546Spatrick }
124061da546Spatrick
FindUnitIndex(DIERef::Section section,dw_offset_t offset)125061da546Spatrick uint32_t DWARFDebugInfo::FindUnitIndex(DIERef::Section section,
126061da546Spatrick dw_offset_t offset) {
127061da546Spatrick ParseUnitHeadersIfNeeded();
128061da546Spatrick
129061da546Spatrick // llvm::lower_bound is not used as for DIE offsets it would still return
130061da546Spatrick // index +1 and GetOffset() returning index itself would be a special case.
131061da546Spatrick auto pos = llvm::upper_bound(
132061da546Spatrick m_units, std::make_pair(section, offset),
133061da546Spatrick [](const std::pair<DIERef::Section, dw_offset_t> &lhs,
134061da546Spatrick const DWARFUnitSP &rhs) {
135061da546Spatrick return lhs < std::make_pair(rhs->GetDebugSection(), rhs->GetOffset());
136061da546Spatrick });
137061da546Spatrick uint32_t idx = std::distance(m_units.begin(), pos);
138061da546Spatrick if (idx == 0)
139061da546Spatrick return DW_INVALID_OFFSET;
140061da546Spatrick return idx - 1;
141061da546Spatrick }
142061da546Spatrick
GetUnitAtOffset(DIERef::Section section,dw_offset_t cu_offset,uint32_t * idx_ptr)143061da546Spatrick DWARFUnit *DWARFDebugInfo::GetUnitAtOffset(DIERef::Section section,
144061da546Spatrick dw_offset_t cu_offset,
145061da546Spatrick uint32_t *idx_ptr) {
146061da546Spatrick uint32_t idx = FindUnitIndex(section, cu_offset);
147061da546Spatrick DWARFUnit *result = GetUnitAtIndex(idx);
148061da546Spatrick if (result && result->GetOffset() != cu_offset) {
149061da546Spatrick result = nullptr;
150061da546Spatrick idx = DW_INVALID_INDEX;
151061da546Spatrick }
152061da546Spatrick if (idx_ptr)
153061da546Spatrick *idx_ptr = idx;
154061da546Spatrick return result;
155061da546Spatrick }
156061da546Spatrick
GetUnit(const DIERef & die_ref)157061da546Spatrick DWARFUnit *DWARFDebugInfo::GetUnit(const DIERef &die_ref) {
158061da546Spatrick return GetUnitContainingDIEOffset(die_ref.section(), die_ref.die_offset());
159061da546Spatrick }
160061da546Spatrick
161061da546Spatrick DWARFUnit *
GetUnitContainingDIEOffset(DIERef::Section section,dw_offset_t die_offset)162061da546Spatrick DWARFDebugInfo::GetUnitContainingDIEOffset(DIERef::Section section,
163061da546Spatrick dw_offset_t die_offset) {
164061da546Spatrick uint32_t idx = FindUnitIndex(section, die_offset);
165061da546Spatrick DWARFUnit *result = GetUnitAtIndex(idx);
166061da546Spatrick if (result && !result->ContainsDIEOffset(die_offset))
167061da546Spatrick return nullptr;
168061da546Spatrick return result;
169061da546Spatrick }
170061da546Spatrick
GetTypeUnitForHash(uint64_t hash)171061da546Spatrick DWARFTypeUnit *DWARFDebugInfo::GetTypeUnitForHash(uint64_t hash) {
172061da546Spatrick auto pos = llvm::lower_bound(m_type_hash_to_unit_index,
173061da546Spatrick std::make_pair(hash, 0u), llvm::less_first());
174061da546Spatrick if (pos == m_type_hash_to_unit_index.end() || pos->first != hash)
175061da546Spatrick return nullptr;
176061da546Spatrick return llvm::cast<DWARFTypeUnit>(GetUnitAtIndex(pos->second));
177061da546Spatrick }
178061da546Spatrick
ContainsTypeUnits()179061da546Spatrick bool DWARFDebugInfo::ContainsTypeUnits() {
180061da546Spatrick ParseUnitHeadersIfNeeded();
181061da546Spatrick return !m_type_hash_to_unit_index.empty();
182061da546Spatrick }
183061da546Spatrick
184061da546Spatrick // GetDIE()
185061da546Spatrick //
186061da546Spatrick // Get the DIE (Debug Information Entry) with the specified offset.
187061da546Spatrick DWARFDIE
GetDIE(const DIERef & die_ref)188061da546Spatrick DWARFDebugInfo::GetDIE(const DIERef &die_ref) {
189061da546Spatrick DWARFUnit *cu = GetUnit(die_ref);
190061da546Spatrick if (cu)
191dda28197Spatrick return cu->GetNonSkeletonUnit().GetDIE(die_ref.die_offset());
192061da546Spatrick return DWARFDIE(); // Not found
193061da546Spatrick }
194