1 //===-- DWARFDebugRanges.cpp ------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "DWARFDebugRanges.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 18 DWARFDebugRanges::DWARFDebugRanges() : m_range_map() {} 19 20 DWARFDebugRanges::~DWARFDebugRanges() {} 21 22 void DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data) { 23 DWARFRangeList range_list; 24 lldb::offset_t offset = 0; 25 dw_offset_t debug_ranges_offset = offset; 26 while (Extract(dwarf2Data, &offset, range_list)) { 27 range_list.Sort(); 28 m_range_map[debug_ranges_offset] = range_list; 29 debug_ranges_offset = offset; 30 } 31 } 32 33 bool DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data, 34 lldb::offset_t *offset_ptr, 35 DWARFRangeList &range_list) { 36 range_list.Clear(); 37 38 lldb::offset_t range_offset = *offset_ptr; 39 const DWARFDataExtractor &debug_ranges_data = 40 dwarf2Data->get_debug_ranges_data(); 41 uint32_t addr_size = debug_ranges_data.GetAddressByteSize(); 42 43 while ( 44 debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) { 45 dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 46 dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 47 if (!begin && !end) { 48 // End of range list 49 break; 50 } 51 // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits 52 // of ones 53 switch (addr_size) { 54 case 2: 55 if (begin == 0xFFFFull) 56 begin = LLDB_INVALID_ADDRESS; 57 break; 58 59 case 4: 60 if (begin == 0xFFFFFFFFull) 61 begin = LLDB_INVALID_ADDRESS; 62 break; 63 64 case 8: 65 break; 66 67 default: 68 llvm_unreachable("DWARFRangeList::Extract() unsupported address size."); 69 } 70 71 // Filter out empty ranges 72 if (begin < end) 73 range_list.Append(DWARFRangeList::Entry(begin, end - begin)); 74 } 75 76 // Make sure we consumed at least something 77 return range_offset != *offset_ptr; 78 } 79 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(); 85 86 dw_addr_t base_addr = cu_base_addr; 87 while ( 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 92 // of ones 93 if (begin == 0xFFFFFFFFull && addr_size == 4) 94 begin = LLDB_INVALID_ADDRESS; 95 96 s.Indent(); 97 if (begin == 0 && end == 0) { 98 s.PutCString(" End"); 99 break; 100 } else if (begin == LLDB_INVALID_ADDRESS) { 101 // A base address selection entry 102 base_addr = end; 103 s.Address(base_addr, sizeof(dw_addr_t), " Base address = "); 104 } else { 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; 108 109 s.AddressRange(begin_addr, end_addr, sizeof(dw_addr_t), NULL); 110 } 111 } 112 } 113 114 bool DWARFDebugRanges::FindRanges(dw_addr_t debug_ranges_base, 115 dw_offset_t debug_ranges_offset, 116 DWARFRangeList &range_list) const { 117 dw_addr_t debug_ranges_address = debug_ranges_base + 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; 121 return true; 122 } 123 return false; 124 } 125