1254721Semaste//===-- DWARFDebugRanges.cpp ------------------------------------*- C++ -*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9254721Semaste#include "DWARFDebugRanges.h" 10344779Sdim#include "DWARFUnit.h" 11321369Sdim#include "lldb/Utility/Stream.h" 12254721Semaste 13254721Semasteusing namespace lldb_private; 14254721Semaste 15327952Sdimstatic dw_addr_t GetBaseAddressMarker(uint32_t addr_size) { 16327952Sdim switch(addr_size) { 17327952Sdim case 2: 18327952Sdim return 0xffff; 19327952Sdim case 4: 20327952Sdim return 0xffffffff; 21327952Sdim case 8: 22327952Sdim return 0xffffffffffffffff; 23327952Sdim } 24327952Sdim llvm_unreachable("GetBaseAddressMarker unsupported address size."); 25327952Sdim} 26327952Sdim 27314564SdimDWARFDebugRanges::DWARFDebugRanges() : m_range_map() {} 28254721Semaste 29353358Sdimvoid DWARFDebugRanges::Extract(DWARFContext &context) { 30314564Sdim DWARFRangeList range_list; 31314564Sdim lldb::offset_t offset = 0; 32314564Sdim dw_offset_t debug_ranges_offset = offset; 33353358Sdim while (Extract(context, &offset, range_list)) { 34314564Sdim range_list.Sort(); 35314564Sdim m_range_map[debug_ranges_offset] = range_list; 36314564Sdim debug_ranges_offset = offset; 37314564Sdim } 38254721Semaste} 39254721Semaste 40353358Sdimbool DWARFDebugRanges::Extract(DWARFContext &context, 41314564Sdim lldb::offset_t *offset_ptr, 42314564Sdim DWARFRangeList &range_list) { 43314564Sdim range_list.Clear(); 44254721Semaste 45314564Sdim lldb::offset_t range_offset = *offset_ptr; 46353358Sdim const DWARFDataExtractor &debug_ranges_data = context.getOrLoadRangesData(); 47314564Sdim uint32_t addr_size = debug_ranges_data.GetAddressByteSize(); 48327952Sdim dw_addr_t base_addr = 0; 49327952Sdim dw_addr_t base_addr_marker = GetBaseAddressMarker(addr_size); 50254721Semaste 51314564Sdim while ( 52314564Sdim debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) { 53314564Sdim dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 54314564Sdim dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 55327952Sdim 56314564Sdim if (!begin && !end) { 57314564Sdim // End of range list 58314564Sdim break; 59314564Sdim } 60254721Semaste 61327952Sdim if (begin == base_addr_marker) { 62327952Sdim base_addr = end; 63327952Sdim continue; 64254721Semaste } 65254721Semaste 66314564Sdim // Filter out empty ranges 67314564Sdim if (begin < end) 68327952Sdim range_list.Append(DWARFRangeList::Entry(begin + base_addr, end - begin)); 69314564Sdim } 70314564Sdim 71314564Sdim // Make sure we consumed at least something 72314564Sdim return range_offset != *offset_ptr; 73254721Semaste} 74254721Semaste 75314564Sdimvoid DWARFDebugRanges::Dump(Stream &s, 76314564Sdim const DWARFDataExtractor &debug_ranges_data, 77314564Sdim lldb::offset_t *offset_ptr, 78314564Sdim dw_addr_t cu_base_addr) { 79314564Sdim uint32_t addr_size = s.GetAddressByteSize(); 80254721Semaste 81314564Sdim dw_addr_t base_addr = cu_base_addr; 82314564Sdim while ( 83314564Sdim debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) { 84314564Sdim dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 85314564Sdim dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 86341825Sdim // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits of 87341825Sdim // ones 88314564Sdim if (begin == 0xFFFFFFFFull && addr_size == 4) 89314564Sdim begin = LLDB_INVALID_ADDRESS; 90254721Semaste 91314564Sdim s.Indent(); 92314564Sdim if (begin == 0 && end == 0) { 93314564Sdim s.PutCString(" End"); 94314564Sdim break; 95314564Sdim } else if (begin == LLDB_INVALID_ADDRESS) { 96314564Sdim // A base address selection entry 97314564Sdim base_addr = end; 98360784Sdim DumpAddress(s.AsRawOstream(), base_addr, sizeof(dw_addr_t), 99360784Sdim " Base address = "); 100314564Sdim } else { 101314564Sdim // Convert from offset to an address 102314564Sdim dw_addr_t begin_addr = begin + base_addr; 103314564Sdim dw_addr_t end_addr = end + base_addr; 104254721Semaste 105360784Sdim DumpAddressRange(s.AsRawOstream(), begin_addr, end_addr, 106360784Sdim sizeof(dw_addr_t), nullptr); 107254721Semaste } 108314564Sdim } 109254721Semaste} 110254721Semaste 111344779Sdimbool DWARFDebugRanges::FindRanges(const DWARFUnit *cu, 112314564Sdim dw_offset_t debug_ranges_offset, 113314564Sdim DWARFRangeList &range_list) const { 114344779Sdim dw_addr_t debug_ranges_address = cu->GetRangesBase() + debug_ranges_offset; 115314564Sdim range_map_const_iterator pos = m_range_map.find(debug_ranges_address); 116314564Sdim if (pos != m_range_map.end()) { 117314564Sdim range_list = pos->second; 118344779Sdim 119344779Sdim // All DW_AT_ranges are relative to the base address of the compile 120344779Sdim // unit. We add the compile unit base address to make sure all the 121344779Sdim // addresses are properly fixed up. 122344779Sdim range_list.Slide(cu->GetBaseAddress()); 123314564Sdim return true; 124314564Sdim } 125314564Sdim return false; 126254721Semaste} 127