LLDB  mainline
DWARFDebugInfo.cpp
Go to the documentation of this file.
1 //===-- DWARFDebugInfo.cpp --------------------------------------*- C++ -*-===//
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 
19 #include "DWARFCompileUnit.h"
20 #include "DWARFContext.h"
21 #include "DWARFDebugAranges.h"
22 #include "DWARFDebugInfo.h"
23 #include "DWARFDebugInfoEntry.h"
24 #include "DWARFFormValue.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 using namespace std;
29 
30 // Constructor
32  : m_dwarf2Data(NULL), m_context(context), m_compile_units(),
33  m_cu_aranges_up() {}
34 
35 // SetDwarfData
37  m_dwarf2Data = dwarf2Data;
38  m_compile_units.clear();
39 }
40 
41 llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() {
42  if (m_cu_aranges_up)
43  return *m_cu_aranges_up;
44 
45  assert(m_dwarf2Data);
46 
47  m_cu_aranges_up = llvm::make_unique<DWARFDebugAranges>();
48  const DWARFDataExtractor *debug_aranges_data =
50  if (debug_aranges_data) {
51  llvm::Error error = m_cu_aranges_up->extract(*debug_aranges_data);
52  if (error)
53  return std::move(error);
54  }
55 
56  // Make a list of all CUs represented by the arange data in the file.
57  std::set<dw_offset_t> cus_with_data;
58  for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) {
59  dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n);
60  if (offset != DW_INVALID_OFFSET)
61  cus_with_data.insert(offset);
62  }
63 
64  // Manually build arange data for everything that wasn't in the
65  // .debug_aranges table.
66  const size_t num_compile_units = GetNumCompileUnits();
67  for (size_t idx = 0; idx < num_compile_units; ++idx) {
69 
70  dw_offset_t offset = cu->GetOffset();
71  if (cus_with_data.find(offset) == cus_with_data.end())
73  }
74 
75  const bool minimize = true;
76  m_cu_aranges_up->Sort(minimize);
77  return *m_cu_aranges_up;
78 }
79 
80 void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() {
81  if (!m_compile_units.empty())
82  return;
83  if (!m_dwarf2Data)
84  return;
85 
86  lldb::offset_t offset = 0;
87  const auto &debug_info_data = m_dwarf2Data->get_debug_info_data();
88 
89  while (debug_info_data.ValidOffset(offset)) {
90  llvm::Expected<DWARFUnitSP> cu_sp = DWARFCompileUnit::extract(
91  m_dwarf2Data, m_compile_units.size(), debug_info_data, &offset);
92 
93  if (!cu_sp) {
94  // FIXME: Propagate this error up.
95  llvm::consumeError(cu_sp.takeError());
96  return;
97  }
98 
99  // If it didn't return an error, then it should be returning a valid
100  // CompileUnit.
101  assert(*cu_sp);
102 
103  m_compile_units.push_back(*cu_sp);
104 
105  offset = (*cu_sp)->GetNextCompileUnitOffset();
106  }
107 }
108 
110  ParseCompileUnitHeadersIfNeeded();
111  return m_compile_units.size();
112 }
113 
115  DWARFUnit *cu = NULL;
116  if (idx < GetNumCompileUnits())
117  cu = m_compile_units[idx].get();
118  return cu;
119 }
120 
122  dw_offset_t offset, const DWARFUnitSP &cu_sp) {
123  return offset < cu_sp->GetOffset();
124 }
125 
126 uint32_t DWARFDebugInfo::FindCompileUnitIndex(dw_offset_t offset) {
127  ParseCompileUnitHeadersIfNeeded();
128 
129  // llvm::lower_bound is not used as for DIE offsets it would still return
130  // index +1 and GetOffset() returning index itself would be a special case.
131  auto pos = llvm::upper_bound(m_compile_units, offset,
133  uint32_t idx = std::distance(m_compile_units.begin(), pos);
134  if (idx == 0)
135  return DW_INVALID_OFFSET;
136  return idx - 1;
137 }
138 
140  uint32_t *idx_ptr) {
141  uint32_t idx = FindCompileUnitIndex(cu_offset);
142  DWARFUnit *result = GetCompileUnitAtIndex(idx);
143  if (result && result->GetOffset() != cu_offset) {
144  result = nullptr;
145  idx = DW_INVALID_INDEX;
146  }
147  if (idx_ptr)
148  *idx_ptr = idx;
149  return result;
150 }
151 
153  if (die_ref.cu_offset == DW_INVALID_OFFSET)
155  else
156  return GetCompileUnitAtOffset(die_ref.cu_offset);
157 }
158 
159 DWARFUnit *
161  uint32_t idx = FindCompileUnitIndex(die_offset);
162  DWARFUnit *result = GetCompileUnitAtIndex(idx);
163  if (result && !result->ContainsDIEOffset(die_offset))
164  return nullptr;
165  return result;
166 }
167 
168 DWARFDIE
171  if (cu)
172  return cu->GetDIE(die_offset);
173  return DWARFDIE();
174 }
175 
176 // GetDIE()
177 //
178 // Get the DIE (Debug Information Entry) with the specified offset.
179 DWARFDIE
181  DWARFUnit *cu = GetCompileUnit(die_ref);
182  if (cu)
183  return cu->GetDIE(die_ref.die_offset);
184  return DWARFDIE(); // Not found
185 }
186 
DWARFDIE GetDIE(const DIERef &die_ref)
DWARFDebugInfo(lldb_private::DWARFContext &context)
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
bool ContainsDIEOffset(dw_offset_t die_offset) const
Definition: DWARFUnit.h:85
DWARFDIE GetDIE(dw_offset_t die_offset)
Definition: DWARFUnit.cpp:530
CompileUnitColl m_compile_units
llvm::Error Error
DWARFUnit * GetCompileUnitContainingDIEOffset(dw_offset_t die_offset)
Definition: DIERef.h:18
DWARFUnit * GetCompileUnitAtIndex(lldb::user_id_t idx)
#define DW_INVALID_INDEX
Definition: dwarf.h:35
static bool OffsetLessThanCompileUnitOffset(dw_offset_t offset, const DWARFUnitSP &cu_sp)
dw_offset_t die_offset
Definition: DIERef.h:48
llvm::Expected< DWARFDebugAranges & > GetCompileUnitAranges()
uint64_t user_id_t
Definition: lldb-types.h:84
std::unique_ptr< DWARFDebugAranges > m_cu_aranges_up
uint64_t offset_t
Definition: lldb-types.h:87
lldb_private::DWARFContext & m_context
dw_offset_t GetOffset() const
Definition: DWARFUnit.h:76
size_t GetNumCompileUnits()
DWARFUnit * GetCompileUnitAtOffset(dw_offset_t cu_offset, uint32_t *idx_ptr=NULL)
void BuildAddressRangeTable(SymbolFileDWARF *dwarf, DWARFDebugAranges *debug_aranges)
Definition: DWARFUnit.cpp:408
std::shared_ptr< DWARFUnit > DWARFUnitSP
Definition: DWARFUnit.h:22
dw_offset_t cu_offset
Definition: DIERef.h:47
DWARFDIE GetDIEForDIEOffset(dw_offset_t die_offset)
Definition: SBAddress.h:15
DWARFUnit * GetCompileUnit(const DIERef &die_ref)
SymbolFileDWARF * m_dwarf2Data
#define DW_INVALID_OFFSET
Definition: dwarf.h:34
void SetDwarfData(SymbolFileDWARF *dwarf2Data)
virtual const lldb_private::DWARFDataExtractor & get_debug_info_data()
const DWARFDataExtractor * getOrLoadArangesData()
static llvm::Expected< DWARFUnitSP > extract(SymbolFileDWARF *dwarf2Data, lldb::user_id_t uid, const lldb_private::DWARFDataExtractor &debug_info, lldb::offset_t *offset_ptr)