1 //===-- DWARFDebugRanges.cpp ------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "DWARFDebugRanges.h"
11 #include "DWARFUnit.h"
12 #include "SymbolFileDWARF.h"
13 #include "lldb/Utility/Stream.h"
16 using namespace lldb_private;
19 static dw_addr_t GetBaseAddressMarker(uint32_t addr_size) {
26 return 0xffffffffffffffff;
28 llvm_unreachable("GetBaseAddressMarker unsupported address size.");
31 DWARFDebugRanges::DWARFDebugRanges() : m_range_map() {}
33 void DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data) {
34 DWARFRangeList range_list;
35 lldb::offset_t offset = 0;
36 dw_offset_t debug_ranges_offset = offset;
37 while (Extract(dwarf2Data, &offset, range_list)) {
39 m_range_map[debug_ranges_offset] = range_list;
40 debug_ranges_offset = offset;
44 bool DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data,
45 lldb::offset_t *offset_ptr,
46 DWARFRangeList &range_list) {
49 lldb::offset_t range_offset = *offset_ptr;
50 const DWARFDataExtractor &debug_ranges_data =
51 dwarf2Data->get_debug_ranges_data();
52 uint32_t addr_size = debug_ranges_data.GetAddressByteSize();
53 dw_addr_t base_addr = 0;
54 dw_addr_t base_addr_marker = GetBaseAddressMarker(addr_size);
57 debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) {
58 dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
59 dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
66 if (begin == base_addr_marker) {
71 // Filter out empty ranges
73 range_list.Append(DWARFRangeList::Entry(begin + base_addr, end - begin));
76 // Make sure we consumed at least something
77 return range_offset != *offset_ptr;
80 void DWARFDebugRanges::Dump(Stream &s,
81 const DWARFDataExtractor &debug_ranges_data,
82 lldb::offset_t *offset_ptr,
83 dw_addr_t cu_base_addr) {
84 uint32_t addr_size = s.GetAddressByteSize();
86 dw_addr_t base_addr = cu_base_addr;
88 debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) {
89 dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
90 dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
91 // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits of
93 if (begin == 0xFFFFFFFFull && addr_size == 4)
94 begin = LLDB_INVALID_ADDRESS;
97 if (begin == 0 && end == 0) {
100 } else if (begin == LLDB_INVALID_ADDRESS) {
101 // A base address selection entry
103 s.Address(base_addr, sizeof(dw_addr_t), " Base address = ");
105 // Convert from offset to an address
106 dw_addr_t begin_addr = begin + base_addr;
107 dw_addr_t end_addr = end + base_addr;
109 s.AddressRange(begin_addr, end_addr, sizeof(dw_addr_t), NULL);
114 bool DWARFDebugRanges::FindRanges(const DWARFUnit *cu,
115 dw_offset_t debug_ranges_offset,
116 DWARFRangeList &range_list) const {
117 dw_addr_t debug_ranges_address = cu->GetRangesBase() + debug_ranges_offset;
118 range_map_const_iterator pos = m_range_map.find(debug_ranges_address);
119 if (pos != m_range_map.end()) {
120 range_list = pos->second;
122 // All DW_AT_ranges are relative to the base address of the compile
123 // unit. We add the compile unit base address to make sure all the
124 // addresses are properly fixed up.
125 range_list.Slide(cu->GetBaseAddress());
131 uint64_t DWARFDebugRanges::GetOffset(size_t Index) const {
132 lldbassert(false && "DW_FORM_rnglistx is not present before DWARF5");
136 bool DWARFDebugRngLists::ExtractRangeList(
137 const DWARFDataExtractor &data, uint8_t addrSize,
138 lldb::offset_t *offset_ptr, std::vector<RngListEntry> &rangeList) {
143 switch (data.GetU8(offset_ptr)) {
144 case DW_RLE_end_of_list:
147 case DW_RLE_start_length: {
148 dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
149 dw_addr_t len = data.GetULEB128(offset_ptr);
150 rangeList.push_back({DW_RLE_start_length, begin, len});
154 case DW_RLE_start_end: {
155 dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
156 dw_addr_t end = data.GetMaxU64(offset_ptr, addrSize);
157 rangeList.push_back({DW_RLE_start_end, begin, end});
161 case DW_RLE_base_address: {
162 dw_addr_t base = data.GetMaxU64(offset_ptr, addrSize);
163 rangeList.push_back({DW_RLE_base_address, base, 0});
167 case DW_RLE_offset_pair: {
168 dw_addr_t begin = data.GetULEB128(offset_ptr);
169 dw_addr_t end = data.GetULEB128(offset_ptr);
170 rangeList.push_back({DW_RLE_offset_pair, begin, end});
174 case DW_RLE_base_addressx: {
175 dw_addr_t base = data.GetULEB128(offset_ptr);
176 rangeList.push_back({DW_RLE_base_addressx, base, 0});
180 case DW_RLE_startx_endx: {
181 dw_addr_t start = data.GetULEB128(offset_ptr);
182 dw_addr_t end = data.GetULEB128(offset_ptr);
183 rangeList.push_back({DW_RLE_startx_endx, start, end});
187 case DW_RLE_startx_length: {
188 dw_addr_t start = data.GetULEB128(offset_ptr);
189 dw_addr_t length = data.GetULEB128(offset_ptr);
190 rangeList.push_back({DW_RLE_startx_length, start, length});
195 lldbassert(0 && "unknown range list entry encoding");
203 static uint64_t ReadAddressFromDebugAddrSection(const DWARFUnit *cu,
205 uint32_t index_size = cu->GetAddressByteSize();
206 dw_offset_t addr_base = cu->GetAddrBase();
207 lldb::offset_t offset = addr_base + index * index_size;
208 return cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset,
212 bool DWARFDebugRngLists::FindRanges(const DWARFUnit *cu,
213 dw_offset_t debug_ranges_offset,
214 DWARFRangeList &range_list) const {
216 dw_addr_t debug_ranges_address = cu->GetRangesBase() + debug_ranges_offset;
217 auto pos = m_range_map.find(debug_ranges_address);
218 if (pos != m_range_map.end()) {
219 dw_addr_t BaseAddr = cu->GetBaseAddress();
220 for (const RngListEntry &E : pos->second) {
221 switch (E.encoding) {
222 case DW_RLE_start_length:
223 range_list.Append(DWARFRangeList::Entry(E.value0, E.value1));
225 case DW_RLE_base_address:
228 case DW_RLE_start_end:
229 range_list.Append(DWARFRangeList::Entry(E.value0, E.value1 - E.value0));
231 case DW_RLE_offset_pair:
233 DWARFRangeList::Entry(BaseAddr + E.value0, E.value1 - E.value0));
235 case DW_RLE_base_addressx: {
236 BaseAddr = ReadAddressFromDebugAddrSection(cu, E.value0);
239 case DW_RLE_startx_endx: {
240 dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
241 dw_addr_t end = ReadAddressFromDebugAddrSection(cu, E.value1);
242 range_list.Append(DWARFRangeList::Entry(start, end - start));
245 case DW_RLE_startx_length: {
246 dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
247 range_list.Append(DWARFRangeList::Entry(start, E.value1));
251 llvm_unreachable("unexpected encoding");
259 void DWARFDebugRngLists::Extract(SymbolFileDWARF *dwarf2Data) {
260 const DWARFDataExtractor &data = dwarf2Data->get_debug_rnglists_data();
261 lldb::offset_t offset = 0;
263 uint64_t length = data.GetU32(&offset);
264 bool isDwarf64 = (length == 0xffffffff);
266 length = data.GetU64(&offset);
267 lldb::offset_t end = offset + length;
270 if (data.GetU16(&offset) < 5)
273 uint8_t addrSize = data.GetU8(&offset);
275 // We do not support non-zero segment selector size.
276 if (data.GetU8(&offset) != 0) {
277 lldbassert(0 && "not implemented");
281 uint32_t offsetsAmount = data.GetU32(&offset);
282 for (uint32_t i = 0; i < offsetsAmount; ++i)
283 Offsets.push_back(data.GetMaxU64(&offset, isDwarf64 ? 8 : 4));
285 lldb::offset_t listOffset = offset;
286 std::vector<RngListEntry> rangeList;
287 while (offset < end && ExtractRangeList(data, addrSize, &offset, rangeList)) {
288 m_range_map[listOffset] = rangeList;
293 uint64_t DWARFDebugRngLists::GetOffset(size_t Index) const {
294 return Offsets[Index];