LLDB  mainline
DWARFDebugRanges.cpp
Go to the documentation of this file.
1 //===-- DWARFDebugRanges.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 "DWARFDebugRanges.h"
10 #include "DWARFUnit.h"
11 #include "SymbolFileDWARF.h"
12 #include "lldb/Utility/Stream.h"
13 #include <assert.h>
14 
15 using namespace lldb_private;
16 using namespace std;
17 
19  switch(addr_size) {
20  case 2:
21  return 0xffff;
22  case 4:
23  return 0xffffffff;
24  case 8:
25  return 0xffffffffffffffff;
26  }
27  llvm_unreachable("GetBaseAddressMarker unsupported address size.");
28 }
29 
31 
33  DWARFRangeList range_list;
34  lldb::offset_t offset = 0;
35  dw_offset_t debug_ranges_offset = offset;
36  while (Extract(dwarf2Data, &offset, range_list)) {
37  range_list.Sort();
38  m_range_map[debug_ranges_offset] = range_list;
39  debug_ranges_offset = offset;
40  }
41 }
42 
44  lldb::offset_t *offset_ptr,
45  DWARFRangeList &range_list) {
46  range_list.Clear();
47 
48  lldb::offset_t range_offset = *offset_ptr;
49  const DWARFDataExtractor &debug_ranges_data =
50  dwarf2Data->get_debug_ranges_data();
51  uint32_t addr_size = debug_ranges_data.GetAddressByteSize();
52  dw_addr_t base_addr = 0;
53  dw_addr_t base_addr_marker = GetBaseAddressMarker(addr_size);
54 
55  while (
56  debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) {
57  dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
58  dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
59 
60  if (!begin && !end) {
61  // End of range list
62  break;
63  }
64 
65  if (begin == base_addr_marker) {
66  base_addr = end;
67  continue;
68  }
69 
70  // Filter out empty ranges
71  if (begin < end)
72  range_list.Append(DWARFRangeList::Entry(begin + base_addr, end - begin));
73  }
74 
75  // Make sure we consumed at least something
76  return range_offset != *offset_ptr;
77 }
78 
80  const DWARFDataExtractor &debug_ranges_data,
81  lldb::offset_t *offset_ptr,
82  dw_addr_t cu_base_addr) {
83  uint32_t addr_size = s.GetAddressByteSize();
84 
85  dw_addr_t base_addr = cu_base_addr;
86  while (
87  debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) {
88  dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
89  dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
90  // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits of
91  // ones
92  if (begin == 0xFFFFFFFFull && addr_size == 4)
93  begin = LLDB_INVALID_ADDRESS;
94 
95  s.Indent();
96  if (begin == 0 && end == 0) {
97  s.PutCString(" End");
98  break;
99  } else if (begin == LLDB_INVALID_ADDRESS) {
100  // A base address selection entry
101  base_addr = end;
102  s.Address(base_addr, sizeof(dw_addr_t), " Base address = ");
103  } else {
104  // Convert from offset to an address
105  dw_addr_t begin_addr = begin + base_addr;
106  dw_addr_t end_addr = end + base_addr;
107 
108  s.AddressRange(begin_addr, end_addr, sizeof(dw_addr_t), NULL);
109  }
110  }
111 }
112 
114  dw_offset_t debug_ranges_offset,
115  DWARFRangeList &range_list) const {
116  dw_addr_t debug_ranges_address = cu->GetRangesBase() + debug_ranges_offset;
117  range_map_const_iterator pos = m_range_map.find(debug_ranges_address);
118  if (pos != m_range_map.end()) {
119  range_list = pos->second;
120 
121  // All DW_AT_ranges are relative to the base address of the compile
122  // unit. We add the compile unit base address to make sure all the
123  // addresses are properly fixed up.
124  range_list.Slide(cu->GetBaseAddress());
125  return true;
126  }
127  return false;
128 }
129 
130 uint64_t DWARFDebugRanges::GetOffset(size_t Index) const {
131  lldbassert(false && "DW_FORM_rnglistx is not present before DWARF5");
132  return 0;
133 }
134 
136  const DWARFDataExtractor &data, uint8_t addrSize,
137  lldb::offset_t *offset_ptr, std::vector<RngListEntry> &rangeList) {
138  rangeList.clear();
139 
140  bool error = false;
141  while (!error) {
142  switch (data.GetU8(offset_ptr)) {
143  case DW_RLE_end_of_list:
144  return true;
145 
146  case DW_RLE_start_length: {
147  dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
148  dw_addr_t len = data.GetULEB128(offset_ptr);
149  rangeList.push_back({DW_RLE_start_length, begin, len});
150  break;
151  }
152 
153  case DW_RLE_start_end: {
154  dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
155  dw_addr_t end = data.GetMaxU64(offset_ptr, addrSize);
156  rangeList.push_back({DW_RLE_start_end, begin, end});
157  break;
158  }
159 
160  case DW_RLE_base_address: {
161  dw_addr_t base = data.GetMaxU64(offset_ptr, addrSize);
162  rangeList.push_back({DW_RLE_base_address, base, 0});
163  break;
164  }
165 
166  case DW_RLE_offset_pair: {
167  dw_addr_t begin = data.GetULEB128(offset_ptr);
168  dw_addr_t end = data.GetULEB128(offset_ptr);
169  rangeList.push_back({DW_RLE_offset_pair, begin, end});
170  break;
171  }
172 
173  case DW_RLE_base_addressx: {
174  dw_addr_t base = data.GetULEB128(offset_ptr);
175  rangeList.push_back({DW_RLE_base_addressx, base, 0});
176  break;
177  }
178 
179  case DW_RLE_startx_endx: {
180  dw_addr_t start = data.GetULEB128(offset_ptr);
181  dw_addr_t end = data.GetULEB128(offset_ptr);
182  rangeList.push_back({DW_RLE_startx_endx, start, end});
183  break;
184  }
185 
186  case DW_RLE_startx_length: {
187  dw_addr_t start = data.GetULEB128(offset_ptr);
188  dw_addr_t length = data.GetULEB128(offset_ptr);
189  rangeList.push_back({DW_RLE_startx_length, start, length});
190  break;
191  }
192 
193  default:
194  lldbassert(0 && "unknown range list entry encoding");
195  error = true;
196  }
197  }
198 
199  return false;
200 }
201 
202 static uint64_t ReadAddressFromDebugAddrSection(const DWARFUnit *cu,
203  uint32_t index) {
204  uint32_t index_size = cu->GetAddressByteSize();
205  dw_offset_t addr_base = cu->GetAddrBase();
206  lldb::offset_t offset = addr_base + index * index_size;
207  return cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset,
208  index_size);
209 }
210 
212  dw_offset_t debug_ranges_offset,
213  DWARFRangeList &range_list) const {
214  range_list.Clear();
215  dw_addr_t debug_ranges_address = cu->GetRangesBase() + debug_ranges_offset;
216  auto pos = m_range_map.find(debug_ranges_address);
217  if (pos != m_range_map.end()) {
218  dw_addr_t BaseAddr = cu->GetBaseAddress();
219  for (const RngListEntry &E : pos->second) {
220  switch (E.encoding) {
221  case DW_RLE_start_length:
222  range_list.Append(DWARFRangeList::Entry(E.value0, E.value1));
223  break;
224  case DW_RLE_base_address:
225  BaseAddr = E.value0;
226  break;
227  case DW_RLE_start_end:
228  range_list.Append(DWARFRangeList::Entry(E.value0, E.value1 - E.value0));
229  break;
230  case DW_RLE_offset_pair:
231  range_list.Append(
232  DWARFRangeList::Entry(BaseAddr + E.value0, E.value1 - E.value0));
233  break;
234  case DW_RLE_base_addressx: {
235  BaseAddr = ReadAddressFromDebugAddrSection(cu, E.value0);
236  break;
237  }
238  case DW_RLE_startx_endx: {
239  dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
240  dw_addr_t end = ReadAddressFromDebugAddrSection(cu, E.value1);
241  range_list.Append(DWARFRangeList::Entry(start, end - start));
242  break;
243  }
244  case DW_RLE_startx_length: {
245  dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
246  range_list.Append(DWARFRangeList::Entry(start, E.value1));
247  break;
248  }
249  default:
250  llvm_unreachable("unexpected encoding");
251  }
252  }
253  return true;
254  }
255  return false;
256 }
257 
259  const DWARFDataExtractor &data = dwarf2Data->get_debug_rnglists_data();
260  lldb::offset_t offset = 0;
261 
262  uint64_t length = data.GetU32(&offset);
263  // FIXME: Handle DWARF64.
264  lldb::offset_t end = offset + length;
265 
266  // Check version.
267  if (data.GetU16(&offset) < 5)
268  return;
269 
270  uint8_t addrSize = data.GetU8(&offset);
271 
272  // We do not support non-zero segment selector size.
273  if (data.GetU8(&offset) != 0) {
274  lldbassert(0 && "not implemented");
275  return;
276  }
277 
278  uint32_t offsetsAmount = data.GetU32(&offset);
279  for (uint32_t i = 0; i < offsetsAmount; ++i)
280  Offsets.push_back(data.GetMaxU64(&offset, 4));
281 
282  lldb::offset_t listOffset = offset;
283  std::vector<RngListEntry> rangeList;
284  while (offset < end && ExtractRangeList(data, addrSize, &offset, rangeList)) {
285  m_range_map[listOffset] = rangeList;
286  listOffset = offset;
287  }
288 }
289 
290 uint64_t DWARFDebugRngLists::GetOffset(size_t Index) const {
291  return Offsets[Index];
292 }
virtual const lldb_private::DWARFDataExtractor & get_debug_addr_data()
void Address(uint64_t addr, uint32_t addr_size, const char *prefix=nullptr, const char *suffix=nullptr)
Output an address value to this stream.
Definition: Stream.cpp:79
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
uint64_t GetOffset(size_t Index) const override
dw_addr_t GetBaseAddress() const
Definition: DWARFUnit.h:101
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const override
#define lldbassert(x)
Definition: LLDBAssert.h:15
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset, DWARFRangeList &range_list) const override
void Slide(BaseType slide)
Definition: RangeMap.h:231
uint64_t dw_addr_t
Definition: dwarf.h:26
void AddressRange(uint64_t lo_addr, uint64_t hi_addr, uint32_t addr_size, const char *prefix=nullptr, const char *suffix=nullptr)
Output an address range to this stream.
Definition: Stream.cpp:92
dw_addr_t GetAddrBase() const
Definition: DWARFUnit.h:102
static dw_addr_t GetBaseAddressMarker(uint32_t addr_size)
dw_addr_t GetRangesBase() const
Definition: DWARFUnit.h:103
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
uint64_t offset_t
Definition: lldb-types.h:87
static uint64_t ReadAddressFromDebugAddrSection(const DWARFUnit *cu, uint32_t index)
const lldb_private::DWARFDataExtractor & get_debug_rnglists_data()
range_map::const_iterator range_map_const_iterator
void Extract(SymbolFileDWARF *dwarf2Data) override
bool ValidOffsetForDataOfSize(lldb::offset_t offset, lldb::offset_t length) const
Test the availability of length bytes of data from offset.
bool ExtractRangeList(const lldb_private::DWARFDataExtractor &data, uint8_t addrSize, lldb::offset_t *offset_ptr, std::vector< RngListEntry > &list)
uint8_t GetAddressByteSize() const
Definition: DWARFUnit.h:100
uint64_t GetMaxU64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an unsigned integer of size byte_size from *offset_ptr.
SymbolFileDWARF * GetSymbolFileDWARF() const
Definition: DWARFUnit.cpp:590
size_t Indent(const char *s=nullptr)
Indent the current line in the stream.
Definition: Stream.cpp:131
uint64_t GetULEB128(lldb::offset_t *offset_ptr) const
Extract a unsigned LEB128 value from *offset_ptr.
uint32_t GetAddressByteSize() const
Get the address size in bytes.
Definition: Stream.cpp:229
uint8_t GetU8(lldb::offset_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
const lldb_private::DWARFDataExtractor & get_debug_ranges_data()
void Extract(SymbolFileDWARF *dwarf2Data) override
uint64_t GetOffset(size_t Index) const override
uint16_t GetU16(lldb::offset_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
static void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor &debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr)
uint32_t GetAddressByteSize() const
Get the current address size.
void Append(const Entry &entry)
Definition: RangeMap.h:139