Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 1 | //===-- DWARFDebugAranges.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 "DWARFDebugAranges.h" |
| 11 | |
| 12 | #include <assert.h> |
| 13 | |
| 14 | #include <algorithm> |
| 15 | |
| 16 | #include "lldb/Core/Stream.h" |
| 17 | |
| 18 | #include "SymbolFileDWARF.h" |
| 19 | #include "DWARFDebugInfo.h" |
| 20 | #include "DWARFCompileUnit.h" |
| 21 | |
| 22 | using namespace lldb_private; |
| 23 | |
| 24 | //---------------------------------------------------------------------- |
| 25 | // Constructor |
| 26 | //---------------------------------------------------------------------- |
| 27 | DWARFDebugAranges::DWARFDebugAranges() : |
| 28 | m_aranges() |
| 29 | { |
| 30 | } |
| 31 | |
| 32 | |
| 33 | //---------------------------------------------------------------------- |
| 34 | // Compare function DWARFDebugAranges::Range structures |
| 35 | //---------------------------------------------------------------------- |
| 36 | static bool RangeLessThan (const DWARFDebugAranges::Range& range1, const DWARFDebugAranges::Range& range2) |
| 37 | { |
| 38 | // printf("RangeLessThan -- 0x%8.8x < 0x%8.8x ? %d\n", range1.lo_pc, range1.lo_pc, range1.lo_pc < range2.lo_pc); |
| 39 | return range1.lo_pc < range2.lo_pc; |
| 40 | } |
| 41 | |
| 42 | //---------------------------------------------------------------------- |
| 43 | // CountArangeDescriptors |
| 44 | //---------------------------------------------------------------------- |
| 45 | class CountArangeDescriptors |
| 46 | { |
| 47 | public: |
| 48 | CountArangeDescriptors (uint32_t& count_ref) : count(count_ref) |
| 49 | { |
| 50 | // printf("constructor CountArangeDescriptors()\n"); |
| 51 | } |
| 52 | void operator() (const DWARFDebugArangeSet& set) |
| 53 | { |
| 54 | count += set.NumDescriptors(); |
| 55 | } |
| 56 | uint32_t& count; |
| 57 | }; |
| 58 | |
| 59 | //---------------------------------------------------------------------- |
| 60 | // AddArangeDescriptors |
| 61 | //---------------------------------------------------------------------- |
| 62 | class AddArangeDescriptors |
| 63 | { |
| 64 | public: |
| 65 | AddArangeDescriptors (DWARFDebugAranges::RangeColl& ranges) : range_collection(ranges) {} |
| 66 | void operator() (const DWARFDebugArangeSet& set) |
| 67 | { |
| 68 | const DWARFDebugArangeSet::Descriptor* arange_desc_ptr; |
| 69 | DWARFDebugAranges::Range range; |
| 70 | range.offset = set.GetCompileUnitDIEOffset(); |
| 71 | |
Greg Clayton | 54e7afa | 2010-07-09 20:39:50 +0000 | [diff] [blame] | 72 | for (uint32_t i=0; (arange_desc_ptr = set.GetDescriptor(i)) != NULL; ++i) |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 73 | { |
| 74 | range.lo_pc = arange_desc_ptr->address; |
| 75 | range.hi_pc = arange_desc_ptr->address + arange_desc_ptr->length; |
| 76 | |
| 77 | // Insert each item in increasing address order so binary searching |
| 78 | // can later be done! |
| 79 | DWARFDebugAranges::RangeColl::iterator insert_pos = lower_bound(range_collection.begin(), range_collection.end(), range, RangeLessThan); |
| 80 | range_collection.insert(insert_pos, range); |
| 81 | } |
| 82 | } |
| 83 | DWARFDebugAranges::RangeColl& range_collection; |
| 84 | }; |
| 85 | |
| 86 | //---------------------------------------------------------------------- |
| 87 | // PrintRange |
| 88 | //---------------------------------------------------------------------- |
| 89 | static void PrintRange(const DWARFDebugAranges::Range& range) |
| 90 | { |
| 91 | // Cast the address values in case the address type is compiled as 32 bit |
Eli Friedman | 7991225 | 2010-07-09 23:04:08 +0000 | [diff] [blame] | 92 | printf("0x%8.8x: [0x%8.8llx - 0x%8.8llx)\n", range.offset, (long long)range.lo_pc, (long long)range.hi_pc); |
Chris Lattner | 24943d2 | 2010-06-08 16:52:24 +0000 | [diff] [blame] | 93 | } |
| 94 | |
| 95 | //---------------------------------------------------------------------- |
| 96 | // Extract |
| 97 | //---------------------------------------------------------------------- |
| 98 | bool |
| 99 | DWARFDebugAranges::Extract(const DataExtractor &debug_aranges_data) |
| 100 | { |
| 101 | if (debug_aranges_data.ValidOffset(0)) |
| 102 | { |
| 103 | uint32_t offset = 0; |
| 104 | |
| 105 | typedef std::vector<DWARFDebugArangeSet> SetCollection; |
| 106 | typedef SetCollection::const_iterator SetCollectionIter; |
| 107 | SetCollection sets; |
| 108 | |
| 109 | DWARFDebugArangeSet set; |
| 110 | Range range; |
| 111 | while (set.Extract(debug_aranges_data, &offset)) |
| 112 | sets.push_back(set); |
| 113 | |
| 114 | uint32_t count = 0; |
| 115 | |
| 116 | for_each(sets.begin(), sets.end(), CountArangeDescriptors(count)); |
| 117 | |
| 118 | if (count > 0) |
| 119 | { |
| 120 | m_aranges.reserve(count); |
| 121 | AddArangeDescriptors range_adder(m_aranges); |
| 122 | for_each(sets.begin(), sets.end(), range_adder); |
| 123 | } |
| 124 | |
| 125 | // puts("\n\nDWARFDebugAranges list is:\n"); |
| 126 | // for_each(m_aranges.begin(), m_aranges.end(), PrintRange); |
| 127 | } |
| 128 | return false; |
| 129 | } |
| 130 | |
| 131 | //---------------------------------------------------------------------- |
| 132 | // Generate |
| 133 | //---------------------------------------------------------------------- |
| 134 | bool |
| 135 | DWARFDebugAranges::Generate(SymbolFileDWARF* dwarf2Data) |
| 136 | { |
| 137 | Clear(); |
| 138 | DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo(); |
| 139 | if (debug_info) |
| 140 | { |
| 141 | uint32_t cu_idx = 0; |
| 142 | const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits(); |
| 143 | for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) |
| 144 | { |
| 145 | DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); |
| 146 | if (cu) |
| 147 | cu->DIE()->BuildAddressRangeTable(dwarf2Data, cu, this); |
| 148 | } |
| 149 | } |
| 150 | return !IsEmpty(); |
| 151 | } |
| 152 | |
| 153 | |
| 154 | void |
| 155 | DWARFDebugAranges::Print() const |
| 156 | { |
| 157 | puts("\n\nDWARFDebugAranges address range list is:\n"); |
| 158 | for_each(m_aranges.begin(), m_aranges.end(), PrintRange); |
| 159 | } |
| 160 | |
| 161 | |
| 162 | void |
| 163 | DWARFDebugAranges::Range::Dump(Stream *s) const |
| 164 | { |
| 165 | s->Printf("{0x%8.8x}: [0x%8.8llx - 0x%8.8llx)\n", offset, lo_pc, hi_pc); |
| 166 | } |
| 167 | |
| 168 | //---------------------------------------------------------------------- |
| 169 | // Dump |
| 170 | //---------------------------------------------------------------------- |
| 171 | void |
| 172 | DWARFDebugAranges::Dump(SymbolFileDWARF* dwarf2Data, Stream *s) |
| 173 | { |
| 174 | const DataExtractor &debug_aranges_data = dwarf2Data->get_debug_aranges_data(); |
| 175 | if (debug_aranges_data.ValidOffset(0)) |
| 176 | { |
| 177 | uint32_t offset = 0; |
| 178 | |
| 179 | DWARFDebugArangeSet set; |
| 180 | while (set.Extract(debug_aranges_data, &offset)) |
| 181 | set.Dump(s); |
| 182 | } |
| 183 | else |
| 184 | s->PutCString("< EMPTY >\n"); |
| 185 | } |
| 186 | |
| 187 | |
| 188 | //---------------------------------------------------------------------- |
| 189 | // AppendDebugRanges |
| 190 | //---------------------------------------------------------------------- |
| 191 | //void |
| 192 | //DWARFDebugAranges::AppendDebugRanges(BinaryStreamBuf& debug_ranges, dw_addr_t cu_base_addr, uint32_t addr_size) const |
| 193 | //{ |
| 194 | // if (!m_aranges.empty()) |
| 195 | // { |
| 196 | // RangeCollIterator end = m_aranges.end(); |
| 197 | // RangeCollIterator pos; |
| 198 | // RangeCollIterator lo_pos = end; |
| 199 | // for (pos = m_aranges.begin(); pos != end; ++pos) |
| 200 | // { |
| 201 | // if (lo_pos == end) |
| 202 | // lo_pos = pos; |
| 203 | // |
| 204 | // RangeCollIterator next = pos + 1; |
| 205 | // if (next != end) |
| 206 | // { |
| 207 | // // Check to see if we can combine two consecutive ranges? |
| 208 | // if (pos->hi_pc == next->lo_pc) |
| 209 | // continue; // We can combine them! |
| 210 | // } |
| 211 | // |
| 212 | // if (cu_base_addr == 0 || cu_base_addr == DW_INVALID_ADDRESS) |
| 213 | // { |
| 214 | // debug_ranges.AppendMax64(lo_pos->lo_pc, addr_size); |
| 215 | // debug_ranges.AppendMax64(pos->hi_pc, addr_size); |
| 216 | // } |
| 217 | // else |
| 218 | // { |
| 219 | // assert(lo_pos->lo_pc >= cu_base_addr); |
| 220 | // assert(pos->hi_pc >= cu_base_addr); |
| 221 | // debug_ranges.AppendMax64(lo_pos->lo_pc - cu_base_addr, addr_size); |
| 222 | // debug_ranges.AppendMax64(pos->hi_pc - cu_base_addr, addr_size); |
| 223 | // } |
| 224 | // |
| 225 | // // Reset the low part of the next address range |
| 226 | // lo_pos = end; |
| 227 | // } |
| 228 | // } |
| 229 | // // Terminate the .debug_ranges with two zero addresses |
| 230 | // debug_ranges.AppendMax64(0, addr_size); |
| 231 | // debug_ranges.AppendMax64(0, addr_size); |
| 232 | // |
| 233 | //} |
| 234 | // |
| 235 | //---------------------------------------------------------------------- |
| 236 | // ArangeSetContainsAddress |
| 237 | //---------------------------------------------------------------------- |
| 238 | class ArangeSetContainsAddress |
| 239 | { |
| 240 | public: |
| 241 | ArangeSetContainsAddress (dw_addr_t the_address) : address(the_address), offset(DW_INVALID_OFFSET) {} |
| 242 | bool operator() (const DWARFDebugArangeSet& set) |
| 243 | { |
| 244 | offset = set.FindAddress(address); |
| 245 | return (offset != DW_INVALID_OFFSET); |
| 246 | } |
| 247 | const dw_addr_t address; |
| 248 | dw_offset_t offset; |
| 249 | }; |
| 250 | |
| 251 | |
| 252 | //---------------------------------------------------------------------- |
| 253 | // InsertRange |
| 254 | //---------------------------------------------------------------------- |
| 255 | void |
| 256 | DWARFDebugAranges::InsertRange(dw_offset_t offset, dw_addr_t low_pc, dw_addr_t high_pc) |
| 257 | { |
| 258 | // Insert each item in increasing address order so binary searching |
| 259 | // can later be done! |
| 260 | DWARFDebugAranges::Range range(low_pc, high_pc, offset); |
| 261 | InsertRange(range); |
| 262 | } |
| 263 | |
| 264 | //---------------------------------------------------------------------- |
| 265 | // InsertRange |
| 266 | //---------------------------------------------------------------------- |
| 267 | void |
| 268 | DWARFDebugAranges::InsertRange(const DWARFDebugAranges::Range& range) |
| 269 | { |
| 270 | // Insert each item in increasing address order so binary searching |
| 271 | // can later be done! |
| 272 | RangeColl::iterator insert_pos = lower_bound(m_aranges.begin(), m_aranges.end(), range, RangeLessThan); |
| 273 | m_aranges.insert(insert_pos, range); |
| 274 | } |
| 275 | |
| 276 | |
| 277 | //---------------------------------------------------------------------- |
| 278 | // FindAddress |
| 279 | //---------------------------------------------------------------------- |
| 280 | dw_offset_t |
| 281 | DWARFDebugAranges::FindAddress(dw_addr_t address) const |
| 282 | { |
| 283 | if ( !m_aranges.empty() ) |
| 284 | { |
| 285 | DWARFDebugAranges::Range range(address); |
| 286 | DWARFDebugAranges::RangeCollIterator begin = m_aranges.begin(); |
| 287 | DWARFDebugAranges::RangeCollIterator end = m_aranges.end(); |
| 288 | DWARFDebugAranges::RangeCollIterator pos = lower_bound(begin, end, range, RangeLessThan); |
| 289 | |
| 290 | if ((pos != end) && (pos->lo_pc <= address && address < pos->hi_pc)) |
| 291 | { |
| 292 | // printf("FindAddress(1) found 0x%8.8x in compile unit: 0x%8.8x\n", address, pos->offset); |
| 293 | return pos->offset; |
| 294 | } |
| 295 | else if (pos != begin) |
| 296 | { |
| 297 | --pos; |
| 298 | if ((pos->lo_pc <= address) && (address < pos->hi_pc)) |
| 299 | { |
| 300 | // printf("FindAddress(2) found 0x%8.8x in compile unit: 0x%8.8x\n", address, pos->offset); |
| 301 | return (*pos).offset; |
| 302 | } |
| 303 | } |
| 304 | } |
| 305 | return DW_INVALID_OFFSET; |
| 306 | } |
| 307 | |
| 308 | //---------------------------------------------------------------------- |
| 309 | // AllRangesAreContiguous |
| 310 | //---------------------------------------------------------------------- |
| 311 | bool |
| 312 | DWARFDebugAranges::AllRangesAreContiguous(dw_addr_t& lo_pc, dw_addr_t& hi_pc) const |
| 313 | { |
| 314 | if (m_aranges.empty()) |
| 315 | return false; |
| 316 | |
| 317 | DWARFDebugAranges::RangeCollIterator begin = m_aranges.begin(); |
| 318 | DWARFDebugAranges::RangeCollIterator end = m_aranges.end(); |
| 319 | DWARFDebugAranges::RangeCollIterator pos; |
| 320 | dw_addr_t next_addr = 0; |
| 321 | |
| 322 | for (pos = begin; pos != end; ++pos) |
| 323 | { |
| 324 | if ((pos != begin) && (pos->lo_pc != next_addr)) |
| 325 | return false; |
| 326 | next_addr = pos->hi_pc; |
| 327 | } |
| 328 | lo_pc = m_aranges.front().lo_pc; // We checked for empty at the start of function so front() will be valid |
| 329 | hi_pc = m_aranges.back().hi_pc; // We checked for empty at the start of function so back() will be valid |
| 330 | return true; |
| 331 | } |
| 332 | |
| 333 | bool |
| 334 | DWARFDebugAranges::GetMaxRange(dw_addr_t& lo_pc, dw_addr_t& hi_pc) const |
| 335 | { |
| 336 | if (m_aranges.empty()) |
| 337 | return false; |
| 338 | |
| 339 | lo_pc = m_aranges.front().lo_pc; // We checked for empty at the start of function so front() will be valid |
| 340 | hi_pc = m_aranges.back().hi_pc; // We checked for empty at the start of function so back() will be valid |
| 341 | return true; |
| 342 | } |
| 343 | |