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/Core/Stream.h" 13 #include <assert.h> 14 15 using namespace lldb_private; 16 using namespace std; 17 18 DWARFDebugRanges::DWARFDebugRanges() : 19 m_range_map() 20 { 21 } 22 23 DWARFDebugRanges::~DWARFDebugRanges() 24 { 25 } 26 27 void 28 DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data) 29 { 30 DWARFRangeList range_list; 31 lldb::offset_t offset = 0; 32 dw_offset_t debug_ranges_offset = offset; 33 while (Extract(dwarf2Data, &offset, range_list)) 34 { 35 range_list.Sort(); 36 m_range_map[debug_ranges_offset] = range_list; 37 debug_ranges_offset = offset; 38 } 39 } 40 41 bool 42 DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, DWARFRangeList &range_list) 43 { 44 range_list.Clear(); 45 46 lldb::offset_t range_offset = *offset_ptr; 47 const DWARFDataExtractor& debug_ranges_data = dwarf2Data->get_debug_ranges_data(); 48 uint32_t addr_size = debug_ranges_data.GetAddressByteSize(); 49 50 while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) 51 { 52 dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 53 dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 54 if (!begin && !end) 55 { 56 // End of range list 57 break; 58 } 59 // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits 60 // of ones 61 switch (addr_size) 62 { 63 case 2: 64 if (begin == 0xFFFFull) 65 begin = LLDB_INVALID_ADDRESS; 66 break; 67 68 case 4: 69 if (begin == 0xFFFFFFFFull) 70 begin = LLDB_INVALID_ADDRESS; 71 break; 72 73 case 8: 74 break; 75 76 default: 77 assert(!"DWARFRangeList::Extract() unsupported address size."); 78 break; 79 } 80 81 // Filter out empty ranges 82 if (begin < end) 83 range_list.Append(DWARFRangeList::Entry(begin, end - begin)); 84 } 85 86 // Make sure we consumed at least something 87 return range_offset != *offset_ptr; 88 } 89 90 91 void 92 DWARFDebugRanges::Dump(Stream &s, const DWARFDataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr) 93 { 94 uint32_t addr_size = s.GetAddressByteSize(); 95 bool verbose = s.GetVerbose(); 96 97 dw_addr_t base_addr = cu_base_addr; 98 while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) 99 { 100 dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 101 dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 102 // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits 103 // of ones 104 if (begin == 0xFFFFFFFFull && addr_size == 4) 105 begin = LLDB_INVALID_ADDRESS; 106 107 s.Indent(); 108 if (verbose) 109 { 110 s.AddressRange(begin, end, sizeof (dw_addr_t), " offsets = "); 111 } 112 113 114 if (begin == 0 && end == 0) 115 { 116 s.PutCString(" End"); 117 break; 118 } 119 else if (begin == LLDB_INVALID_ADDRESS) 120 { 121 // A base address selection entry 122 base_addr = end; 123 s.Address(base_addr, sizeof (dw_addr_t), " Base address = "); 124 } 125 else 126 { 127 // Convert from offset to an address 128 dw_addr_t begin_addr = begin + base_addr; 129 dw_addr_t end_addr = end + base_addr; 130 131 s.AddressRange(begin_addr, end_addr, sizeof (dw_addr_t), verbose ? " ==> addrs = " : NULL); 132 } 133 } 134 } 135 136 bool 137 DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, DWARFRangeList& range_list) const 138 { 139 range_map_const_iterator pos = m_range_map.find(debug_ranges_offset); 140 if (pos != m_range_map.end()) 141 { 142 range_list = pos->second; 143 return true; 144 } 145 return false; 146 } 147 148 149 150