1*dda28197Spatrick //===-- DWARFDebugRanges.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 "DWARFDebugRanges.h"
10061da546Spatrick #include "DWARFUnit.h"
11061da546Spatrick #include "lldb/Utility/Stream.h"
12061da546Spatrick
13061da546Spatrick using namespace lldb_private;
14061da546Spatrick
GetBaseAddressMarker(uint32_t addr_size)15061da546Spatrick static dw_addr_t GetBaseAddressMarker(uint32_t addr_size) {
16061da546Spatrick switch(addr_size) {
17061da546Spatrick case 2:
18061da546Spatrick return 0xffff;
19061da546Spatrick case 4:
20061da546Spatrick return 0xffffffff;
21061da546Spatrick case 8:
22061da546Spatrick return 0xffffffffffffffff;
23061da546Spatrick }
24061da546Spatrick llvm_unreachable("GetBaseAddressMarker unsupported address size.");
25061da546Spatrick }
26061da546Spatrick
DWARFDebugRanges()27061da546Spatrick DWARFDebugRanges::DWARFDebugRanges() : m_range_map() {}
28061da546Spatrick
Extract(DWARFContext & context)29061da546Spatrick void DWARFDebugRanges::Extract(DWARFContext &context) {
30061da546Spatrick DWARFRangeList range_list;
31061da546Spatrick lldb::offset_t offset = 0;
32061da546Spatrick dw_offset_t debug_ranges_offset = offset;
33061da546Spatrick while (Extract(context, &offset, range_list)) {
34061da546Spatrick range_list.Sort();
35061da546Spatrick m_range_map[debug_ranges_offset] = range_list;
36061da546Spatrick debug_ranges_offset = offset;
37061da546Spatrick }
38061da546Spatrick }
39061da546Spatrick
Extract(DWARFContext & context,lldb::offset_t * offset_ptr,DWARFRangeList & range_list)40061da546Spatrick bool DWARFDebugRanges::Extract(DWARFContext &context,
41061da546Spatrick lldb::offset_t *offset_ptr,
42061da546Spatrick DWARFRangeList &range_list) {
43061da546Spatrick range_list.Clear();
44061da546Spatrick
45061da546Spatrick lldb::offset_t range_offset = *offset_ptr;
46061da546Spatrick const DWARFDataExtractor &debug_ranges_data = context.getOrLoadRangesData();
47061da546Spatrick uint32_t addr_size = debug_ranges_data.GetAddressByteSize();
48061da546Spatrick dw_addr_t base_addr = 0;
49061da546Spatrick dw_addr_t base_addr_marker = GetBaseAddressMarker(addr_size);
50061da546Spatrick
51061da546Spatrick while (
52061da546Spatrick debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) {
53061da546Spatrick dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
54061da546Spatrick dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
55061da546Spatrick
56061da546Spatrick if (!begin && !end) {
57061da546Spatrick // End of range list
58061da546Spatrick break;
59061da546Spatrick }
60061da546Spatrick
61061da546Spatrick if (begin == base_addr_marker) {
62061da546Spatrick base_addr = end;
63061da546Spatrick continue;
64061da546Spatrick }
65061da546Spatrick
66061da546Spatrick // Filter out empty ranges
67061da546Spatrick if (begin < end)
68061da546Spatrick range_list.Append(DWARFRangeList::Entry(begin + base_addr, end - begin));
69061da546Spatrick }
70061da546Spatrick
71061da546Spatrick // Make sure we consumed at least something
72061da546Spatrick return range_offset != *offset_ptr;
73061da546Spatrick }
74061da546Spatrick
Dump(Stream & s,const DWARFDataExtractor & debug_ranges_data,lldb::offset_t * offset_ptr,dw_addr_t cu_base_addr)75061da546Spatrick void DWARFDebugRanges::Dump(Stream &s,
76061da546Spatrick const DWARFDataExtractor &debug_ranges_data,
77061da546Spatrick lldb::offset_t *offset_ptr,
78061da546Spatrick dw_addr_t cu_base_addr) {
79061da546Spatrick uint32_t addr_size = s.GetAddressByteSize();
80061da546Spatrick
81061da546Spatrick dw_addr_t base_addr = cu_base_addr;
82061da546Spatrick while (
83061da546Spatrick debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) {
84061da546Spatrick dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
85061da546Spatrick dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
86061da546Spatrick // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits of
87061da546Spatrick // ones
88061da546Spatrick if (begin == 0xFFFFFFFFull && addr_size == 4)
89061da546Spatrick begin = LLDB_INVALID_ADDRESS;
90061da546Spatrick
91061da546Spatrick s.Indent();
92061da546Spatrick if (begin == 0 && end == 0) {
93061da546Spatrick s.PutCString(" End");
94061da546Spatrick break;
95061da546Spatrick } else if (begin == LLDB_INVALID_ADDRESS) {
96061da546Spatrick // A base address selection entry
97061da546Spatrick base_addr = end;
98061da546Spatrick DumpAddress(s.AsRawOstream(), base_addr, sizeof(dw_addr_t),
99061da546Spatrick " Base address = ");
100061da546Spatrick } else {
101061da546Spatrick // Convert from offset to an address
102061da546Spatrick dw_addr_t begin_addr = begin + base_addr;
103061da546Spatrick dw_addr_t end_addr = end + base_addr;
104061da546Spatrick
105061da546Spatrick DumpAddressRange(s.AsRawOstream(), begin_addr, end_addr,
106061da546Spatrick sizeof(dw_addr_t), nullptr);
107061da546Spatrick }
108061da546Spatrick }
109061da546Spatrick }
110061da546Spatrick
FindRanges(const DWARFUnit * cu,dw_offset_t debug_ranges_offset,DWARFRangeList & range_list) const111061da546Spatrick bool DWARFDebugRanges::FindRanges(const DWARFUnit *cu,
112061da546Spatrick dw_offset_t debug_ranges_offset,
113061da546Spatrick DWARFRangeList &range_list) const {
114061da546Spatrick dw_addr_t debug_ranges_address = cu->GetRangesBase() + debug_ranges_offset;
115061da546Spatrick range_map_const_iterator pos = m_range_map.find(debug_ranges_address);
116061da546Spatrick if (pos != m_range_map.end()) {
117061da546Spatrick range_list = pos->second;
118061da546Spatrick
119061da546Spatrick // All DW_AT_ranges are relative to the base address of the compile
120061da546Spatrick // unit. We add the compile unit base address to make sure all the
121061da546Spatrick // addresses are properly fixed up.
122061da546Spatrick range_list.Slide(cu->GetBaseAddress());
123061da546Spatrick return true;
124061da546Spatrick }
125061da546Spatrick return false;
126061da546Spatrick }
127