LLDB  mainline
DWARFDebugInfo.cpp
Go to the documentation of this file.
1 //===-- DWARFDebugInfo.cpp ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "SymbolFileDWARF.h"
10 
11 #include <algorithm>
12 #include <set>
13 
14 #include "lldb/Host/PosixApi.h"
15 #include "lldb/Symbol/ObjectFile.h"
17 #include "lldb/Utility/Stream.h"
18 #include "llvm/Support/Casting.h"
19 
20 #include "DWARFCompileUnit.h"
21 #include "DWARFContext.h"
22 #include "DWARFDebugAranges.h"
23 #include "DWARFDebugInfo.h"
24 #include "DWARFDebugInfoEntry.h"
25 #include "DWARFFormValue.h"
26 #include "DWARFTypeUnit.h"
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 using namespace std;
31 
32 // Constructor
35  : m_dwarf(dwarf), m_context(context), m_units(), m_cu_aranges_up() {}
36 
37 llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() {
38  if (m_cu_aranges_up)
39  return *m_cu_aranges_up;
40 
41  m_cu_aranges_up = std::make_unique<DWARFDebugAranges>();
42  const DWARFDataExtractor &debug_aranges_data =
44  if (llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data))
45  return std::move(error);
46 
47  // Make a list of all CUs represented by the arange data in the file.
48  std::set<dw_offset_t> cus_with_data;
49  for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) {
50  dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n);
51  if (offset != DW_INVALID_OFFSET)
52  cus_with_data.insert(offset);
53  }
54 
55  // Manually build arange data for everything that wasn't in the
56  // .debug_aranges table.
57  const size_t num_units = GetNumUnits();
58  for (size_t idx = 0; idx < num_units; ++idx) {
59  DWARFUnit *cu = GetUnitAtIndex(idx);
60 
61  dw_offset_t offset = cu->GetOffset();
62  if (cus_with_data.find(offset) == cus_with_data.end())
64  }
65 
66  const bool minimize = true;
67  m_cu_aranges_up->Sort(minimize);
68  return *m_cu_aranges_up;
69 }
70 
72  DWARFDataExtractor data = section == DIERef::Section::DebugTypes
75  const llvm::DWARFUnitIndex *index = nullptr;
76  if (m_context.isDwo())
77  index = &llvm::getDWARFUnitIndex(m_context.GetAsLLVM(),
78  section == DIERef::Section::DebugTypes
79  ? llvm::DW_SECT_EXT_TYPES
80  : llvm::DW_SECT_INFO);
81  lldb::offset_t offset = 0;
82  while (data.ValidOffset(offset)) {
83  llvm::Expected<DWARFUnitSP> unit_sp = DWARFUnit::extract(
84  m_dwarf, m_units.size(), data, section, &offset, index);
85 
86  if (!unit_sp) {
87  // FIXME: Propagate this error up.
88  llvm::consumeError(unit_sp.takeError());
89  return;
90  }
91 
92  // If it didn't return an error, then it should be returning a valid Unit.
93  assert(*unit_sp);
94  m_units.push_back(*unit_sp);
95  offset = (*unit_sp)->GetNextUnitOffset();
96 
97  if (auto *type_unit = llvm::dyn_cast<DWARFTypeUnit>(unit_sp->get())) {
98  m_type_hash_to_unit_index.emplace_back(type_unit->GetTypeHash(),
99  unit_sp.get()->GetID());
100  }
101  }
102 }
103 
105  llvm::call_once(m_units_once_flag, [&] {
106  ParseUnitsFor(DIERef::Section::DebugInfo);
107  ParseUnitsFor(DIERef::Section::DebugTypes);
108  llvm::sort(m_type_hash_to_unit_index, llvm::less_first());
109  });
110 }
111 
114  return m_units.size();
115 }
116 
118  DWARFUnit *cu = nullptr;
119  if (idx < GetNumUnits())
120  cu = m_units[idx].get();
121  return cu;
122 }
123 
125  dw_offset_t offset) {
127 
128  // llvm::lower_bound is not used as for DIE offsets it would still return
129  // index +1 and GetOffset() returning index itself would be a special case.
130  auto pos = llvm::upper_bound(
131  m_units, std::make_pair(section, offset),
132  [](const std::pair<DIERef::Section, dw_offset_t> &lhs,
133  const DWARFUnitSP &rhs) {
134  return lhs < std::make_pair(rhs->GetDebugSection(), rhs->GetOffset());
135  });
136  uint32_t idx = std::distance(m_units.begin(), pos);
137  if (idx == 0)
138  return DW_INVALID_OFFSET;
139  return idx - 1;
140 }
141 
143  dw_offset_t cu_offset,
144  uint32_t *idx_ptr) {
145  uint32_t idx = FindUnitIndex(section, cu_offset);
146  DWARFUnit *result = GetUnitAtIndex(idx);
147  if (result && result->GetOffset() != cu_offset) {
148  result = nullptr;
149  idx = DW_INVALID_INDEX;
150  }
151  if (idx_ptr)
152  *idx_ptr = idx;
153  return result;
154 }
155 
157  return GetUnitContainingDIEOffset(die_ref.section(), die_ref.die_offset());
158 }
159 
160 DWARFUnit *
162  dw_offset_t die_offset) {
163  uint32_t idx = FindUnitIndex(section, die_offset);
164  DWARFUnit *result = GetUnitAtIndex(idx);
165  if (result && !result->ContainsDIEOffset(die_offset))
166  return nullptr;
167  return result;
168 }
169 
171  auto pos = llvm::lower_bound(m_type_hash_to_unit_index,
172  std::make_pair(hash, 0u), llvm::less_first());
173  if (pos == m_type_hash_to_unit_index.end() || pos->first != hash)
174  return nullptr;
175  return llvm::cast<DWARFTypeUnit>(GetUnitAtIndex(pos->second));
176 }
177 
180  return !m_type_hash_to_unit_index.empty();
181 }
182 
183 DWARFDIE
185  dw_offset_t die_offset) {
186  DWARFUnit *cu = GetUnitContainingDIEOffset(section, die_offset);
187  if (cu)
188  return cu->GetDIE(die_offset);
189  return DWARFDIE();
190 }
191 
192 // GetDIE()
193 //
194 // Get the DIE (Debug Information Entry) with the specified offset.
195 DWARFDIE
197  DWARFUnit *cu = GetUnit(die_ref);
198  if (cu)
199  return cu->GetNonSkeletonUnit().GetDIE(die_ref.die_offset());
200  return DWARFDIE(); // Not found
201 }
202 
DWARFDIE GetDIE(const DIERef &die_ref)
static llvm::Expected< DWARFUnitSP > extract(SymbolFileDWARF &dwarf2Data, lldb::user_id_t uid, const lldb_private::DWARFDataExtractor &debug_info, DIERef::Section section, lldb::offset_t *offset_ptr, const llvm::DWARFUnitIndex *index)
Definition: DWARFUnit.cpp:861
A class that represents a running process on the host machine.
dw_offset_t die_offset() const
Definition: DIERef.h:45
bool ContainsDIEOffset(dw_offset_t die_offset) const
Definition: DWARFUnit.h:137
DWARFUnit & GetNonSkeletonUnit()
Definition: DWARFUnit.cpp:557
DWARFDIE GetDIE(dw_offset_t die_offset)
Definition: DWARFUnit.cpp:538
void ParseUnitHeadersIfNeeded()
Identifies a DWARF debug info entry within a given Module.
Definition: DIERef.h:26
llvm::Error Error
DWARFDebugInfo(SymbolFileDWARF &dwarf, lldb_private::DWARFContext &context)
void ParseUnitsFor(DIERef::Section section)
const DWARFDataExtractor & getOrLoadDebugInfoData()
#define DW_INVALID_INDEX
Definition: dwarf.h:35
DWARFTypeUnit * GetTypeUnitForHash(uint64_t hash)
DWARFUnit * GetUnitAtIndex(size_t idx)
llvm::DWARFContext & GetAsLLVM()
llvm::Expected< DWARFDebugAranges & > GetCompileUnitAranges()
std::vector< std::pair< uint64_t, uint32_t > > m_type_hash_to_unit_index
virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges)=0
std::unique_ptr< DWARFDebugAranges > m_cu_aranges_up
uint64_t offset_t
Definition: lldb-types.h:87
uint32_t FindUnitIndex(DIERef::Section section, dw_offset_t offset)
static llvm::raw_ostream & error(Stream &strm)
UnitColl m_units
DWARFUnit * GetUnitAtOffset(DIERef::Section section, dw_offset_t cu_offset, uint32_t *idx_ptr=nullptr)
Section section() const
Definition: DIERef.h:43
lldb_private::DWARFContext & m_context
SymbolFileDWARF & m_dwarf
dw_offset_t GetOffset() const
Definition: DWARFUnit.h:128
bool ValidOffset(lldb::offset_t offset) const
Test the validity of offset.
std::shared_ptr< DWARFUnit > DWARFUnitSP
Definition: DWARFUnit.h:23
DWARFDIE GetDIEForDIEOffset(DIERef::Section section, dw_offset_t die_offset)
const DWARFDataExtractor & getOrLoadArangesData()
DWARFUnit * GetUnitContainingDIEOffset(DIERef::Section section, dw_offset_t die_offset)
Definition: SBAddress.h:15
const DWARFDataExtractor & getOrLoadDebugTypesData()
#define DW_INVALID_OFFSET
Definition: dwarf.h:34
Section
Definition: DIERef.h:28
DWARFUnit * GetUnit(const DIERef &die_ref)
llvm::once_flag m_units_once_flag