DWARFDebugRanges.cpp revision 341825
1254721Semaste//===-- DWARFDebugRanges.cpp ------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "DWARFDebugRanges.h" 11254721Semaste#include "SymbolFileDWARF.h" 12321369Sdim#include "lldb/Utility/Stream.h" 13254721Semaste#include <assert.h> 14254721Semaste 15254721Semasteusing namespace lldb_private; 16254721Semasteusing namespace std; 17254721Semaste 18327952Sdimstatic dw_addr_t GetBaseAddressMarker(uint32_t addr_size) { 19327952Sdim switch(addr_size) { 20327952Sdim case 2: 21327952Sdim return 0xffff; 22327952Sdim case 4: 23327952Sdim return 0xffffffff; 24327952Sdim case 8: 25327952Sdim return 0xffffffffffffffff; 26327952Sdim } 27327952Sdim llvm_unreachable("GetBaseAddressMarker unsupported address size."); 28327952Sdim} 29327952Sdim 30314564SdimDWARFDebugRanges::DWARFDebugRanges() : m_range_map() {} 31254721Semaste 32314564SdimDWARFDebugRanges::~DWARFDebugRanges() {} 33254721Semaste 34314564Sdimvoid DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data) { 35314564Sdim DWARFRangeList range_list; 36314564Sdim lldb::offset_t offset = 0; 37314564Sdim dw_offset_t debug_ranges_offset = offset; 38314564Sdim while (Extract(dwarf2Data, &offset, range_list)) { 39314564Sdim range_list.Sort(); 40314564Sdim m_range_map[debug_ranges_offset] = range_list; 41314564Sdim debug_ranges_offset = offset; 42314564Sdim } 43254721Semaste} 44254721Semaste 45314564Sdimbool DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data, 46314564Sdim lldb::offset_t *offset_ptr, 47314564Sdim DWARFRangeList &range_list) { 48314564Sdim range_list.Clear(); 49254721Semaste 50314564Sdim lldb::offset_t range_offset = *offset_ptr; 51314564Sdim const DWARFDataExtractor &debug_ranges_data = 52314564Sdim dwarf2Data->get_debug_ranges_data(); 53314564Sdim uint32_t addr_size = debug_ranges_data.GetAddressByteSize(); 54327952Sdim dw_addr_t base_addr = 0; 55327952Sdim dw_addr_t base_addr_marker = GetBaseAddressMarker(addr_size); 56254721Semaste 57314564Sdim while ( 58314564Sdim debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) { 59314564Sdim dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 60314564Sdim dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 61327952Sdim 62314564Sdim if (!begin && !end) { 63314564Sdim // End of range list 64314564Sdim break; 65314564Sdim } 66254721Semaste 67327952Sdim if (begin == base_addr_marker) { 68327952Sdim base_addr = end; 69327952Sdim continue; 70254721Semaste } 71254721Semaste 72314564Sdim // Filter out empty ranges 73314564Sdim if (begin < end) 74327952Sdim range_list.Append(DWARFRangeList::Entry(begin + base_addr, end - begin)); 75314564Sdim } 76314564Sdim 77314564Sdim // Make sure we consumed at least something 78314564Sdim return range_offset != *offset_ptr; 79254721Semaste} 80254721Semaste 81314564Sdimvoid DWARFDebugRanges::Dump(Stream &s, 82314564Sdim const DWARFDataExtractor &debug_ranges_data, 83314564Sdim lldb::offset_t *offset_ptr, 84314564Sdim dw_addr_t cu_base_addr) { 85314564Sdim uint32_t addr_size = s.GetAddressByteSize(); 86254721Semaste 87314564Sdim dw_addr_t base_addr = cu_base_addr; 88314564Sdim while ( 89314564Sdim debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) { 90314564Sdim dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 91314564Sdim dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 92341825Sdim // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits of 93341825Sdim // ones 94314564Sdim if (begin == 0xFFFFFFFFull && addr_size == 4) 95314564Sdim begin = LLDB_INVALID_ADDRESS; 96254721Semaste 97314564Sdim s.Indent(); 98314564Sdim if (begin == 0 && end == 0) { 99314564Sdim s.PutCString(" End"); 100314564Sdim break; 101314564Sdim } else if (begin == LLDB_INVALID_ADDRESS) { 102314564Sdim // A base address selection entry 103314564Sdim base_addr = end; 104314564Sdim s.Address(base_addr, sizeof(dw_addr_t), " Base address = "); 105314564Sdim } else { 106314564Sdim // Convert from offset to an address 107314564Sdim dw_addr_t begin_addr = begin + base_addr; 108314564Sdim dw_addr_t end_addr = end + base_addr; 109254721Semaste 110321369Sdim s.AddressRange(begin_addr, end_addr, sizeof(dw_addr_t), NULL); 111254721Semaste } 112314564Sdim } 113254721Semaste} 114254721Semaste 115314564Sdimbool DWARFDebugRanges::FindRanges(dw_addr_t debug_ranges_base, 116314564Sdim dw_offset_t debug_ranges_offset, 117314564Sdim DWARFRangeList &range_list) const { 118314564Sdim dw_addr_t debug_ranges_address = debug_ranges_base + debug_ranges_offset; 119314564Sdim range_map_const_iterator pos = m_range_map.find(debug_ranges_address); 120314564Sdim if (pos != m_range_map.end()) { 121314564Sdim range_list = pos->second; 122314564Sdim return true; 123314564Sdim } 124314564Sdim return false; 125254721Semaste} 126