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 RangeList 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 //void 42 //DWARFDebugRanges::RangeList::AddOffset(dw_addr_t offset) 43 //{ 44 // if (!ranges.empty()) 45 // { 46 // Range::iterator pos = ranges.begin(); 47 // Range::iterator end_pos = ranges.end(); 48 // for (pos = ranges.begin(); pos != end_pos; ++pos) 49 // { 50 // // assert for unsigned overflows 51 // assert (~pos->begin_offset >= offset); 52 // assert (~pos->end_offset >= offset); 53 // pos->begin_offset += offset; 54 // pos->end_offset += offset; 55 // } 56 // } 57 //} 58 // 59 //void 60 //DWARFDebugRanges::RangeList::SubtractOffset(dw_addr_t offset) 61 //{ 62 // if (!ranges.empty()) 63 // { 64 // Range::iterator pos = ranges.begin(); 65 // Range::iterator end_pos = ranges.end(); 66 // for (pos = ranges.begin(); pos != end_pos; ++pos) 67 // { 68 // assert (pos->begin_offset >= offset); 69 // assert (pos->end_offset >= offset); 70 // pos->begin_offset -= offset; 71 // pos->end_offset -= offset; 72 // } 73 // } 74 //} 75 // 76 // 77 //const DWARFDebugRanges::Range* 78 //DWARFDebugRanges::RangeList::RangeAtIndex(size_t i) const 79 //{ 80 // if (i < ranges.size()) 81 // return &ranges[i]; 82 // return NULL; 83 //} 84 85 bool 86 DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, RangeList &range_list) 87 { 88 range_list.Clear(); 89 90 lldb::offset_t range_offset = *offset_ptr; 91 const DWARFDataExtractor& debug_ranges_data = dwarf2Data->get_debug_ranges_data(); 92 uint32_t addr_size = debug_ranges_data.GetAddressByteSize(); 93 94 while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) 95 { 96 dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 97 dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 98 if (!begin && !end) 99 { 100 // End of range list 101 break; 102 } 103 // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits 104 // of ones 105 switch (addr_size) 106 { 107 case 2: 108 if (begin == 0xFFFFull) 109 begin = LLDB_INVALID_ADDRESS; 110 break; 111 112 case 4: 113 if (begin == 0xFFFFFFFFull) 114 begin = LLDB_INVALID_ADDRESS; 115 break; 116 117 case 8: 118 break; 119 120 default: 121 assert(!"DWARFDebugRanges::RangeList::Extract() unsupported address size."); 122 break; 123 } 124 125 // Filter out empty ranges 126 if (begin < end) 127 range_list.Append(Range(begin, end - begin)); 128 } 129 130 // Make sure we consumed at least something 131 return range_offset != *offset_ptr; 132 } 133 134 135 void 136 DWARFDebugRanges::Dump(Stream &s, const DWARFDataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr) 137 { 138 uint32_t addr_size = s.GetAddressByteSize(); 139 bool verbose = s.GetVerbose(); 140 141 dw_addr_t base_addr = cu_base_addr; 142 while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) 143 { 144 dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 145 dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); 146 // Extend 4 byte addresses that consits of 32 bits of 1's to be 64 bits 147 // of ones 148 if (begin == 0xFFFFFFFFull && addr_size == 4) 149 begin = LLDB_INVALID_ADDRESS; 150 151 s.Indent(); 152 if (verbose) 153 { 154 s.AddressRange(begin, end, sizeof (dw_addr_t), " offsets = "); 155 } 156 157 158 if (begin == 0 && end == 0) 159 { 160 s.PutCString(" End"); 161 break; 162 } 163 else if (begin == LLDB_INVALID_ADDRESS) 164 { 165 // A base address selection entry 166 base_addr = end; 167 s.Address(base_addr, sizeof (dw_addr_t), " Base address = "); 168 } 169 else 170 { 171 // Convert from offset to an address 172 dw_addr_t begin_addr = begin + base_addr; 173 dw_addr_t end_addr = end + base_addr; 174 175 s.AddressRange(begin_addr, end_addr, sizeof (dw_addr_t), verbose ? " ==> addrs = " : NULL); 176 } 177 } 178 } 179 180 bool 181 DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, RangeList& range_list) const 182 { 183 range_map_const_iterator pos = m_range_map.find(debug_ranges_offset); 184 if (pos != m_range_map.end()) 185 { 186 range_list = pos->second; 187 return true; 188 } 189 return false; 190 } 191 192 193 194