| //===-- DWARFDebugRanges.cpp ------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "DWARFDebugRanges.h" |
| #include "SymbolFileDWARF.h" |
| #include "lldb/Core/Stream.h" |
| #include <assert.h> |
| |
| using namespace lldb_private; |
| using namespace std; |
| |
| DWARFDebugRanges::DWARFDebugRanges() : |
| m_range_map() |
| { |
| } |
| |
| DWARFDebugRanges::~DWARFDebugRanges() |
| { |
| } |
| |
| void |
| DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data) |
| { |
| RangeList range_list; |
| dw_offset_t offset = 0; |
| dw_offset_t debug_ranges_offset = offset; |
| while (Extract(dwarf2Data, &offset, range_list)) |
| { |
| m_range_map[debug_ranges_offset] = range_list; |
| debug_ranges_offset = offset; |
| } |
| } |
| |
| //void |
| //DWARFDebugRanges::RangeList::AddOffset(dw_addr_t offset) |
| //{ |
| // if (!ranges.empty()) |
| // { |
| // Range::iterator pos = ranges.begin(); |
| // Range::iterator end_pos = ranges.end(); |
| // for (pos = ranges.begin(); pos != end_pos; ++pos) |
| // { |
| // // assert for unsigned overflows |
| // assert (~pos->begin_offset >= offset); |
| // assert (~pos->end_offset >= offset); |
| // pos->begin_offset += offset; |
| // pos->end_offset += offset; |
| // } |
| // } |
| //} |
| // |
| //void |
| //DWARFDebugRanges::RangeList::SubtractOffset(dw_addr_t offset) |
| //{ |
| // if (!ranges.empty()) |
| // { |
| // Range::iterator pos = ranges.begin(); |
| // Range::iterator end_pos = ranges.end(); |
| // for (pos = ranges.begin(); pos != end_pos; ++pos) |
| // { |
| // assert (pos->begin_offset >= offset); |
| // assert (pos->end_offset >= offset); |
| // pos->begin_offset -= offset; |
| // pos->end_offset -= offset; |
| // } |
| // } |
| //} |
| // |
| // |
| //const DWARFDebugRanges::Range* |
| //DWARFDebugRanges::RangeList::RangeAtIndex(size_t i) const |
| //{ |
| // if (i < ranges.size()) |
| // return &ranges[i]; |
| // return NULL; |
| //} |
| |
| bool |
| DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, uint32_t* offset_ptr, RangeList &range_list) |
| { |
| range_list.Clear(); |
| |
| uint32_t range_offset = *offset_ptr; |
| const DataExtractor& debug_ranges_data = dwarf2Data->get_debug_ranges_data(); |
| uint32_t addr_size = debug_ranges_data.GetAddressByteSize(); |
| |
| while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) |
| { |
| dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); |
| dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); |
| if (!begin && !end) |
| { |
| // End of range list |
| break; |
| } |
| // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits |
| // of ones |
| switch (addr_size) |
| { |
| case 2: |
| if (begin == 0xFFFFull) |
| begin = DW_INVALID_ADDRESS; |
| break; |
| |
| case 4: |
| if (begin == 0xFFFFFFFFull) |
| begin = DW_INVALID_ADDRESS; |
| break; |
| |
| case 8: |
| break; |
| |
| default: |
| assert(!"DWARFDebugRanges::RangeList::Extract() unsupported address size."); |
| break; |
| } |
| |
| // Filter out empty ranges |
| if (begin < end) |
| range_list.Append(Range(begin, end - begin)); |
| } |
| |
| // Make sure we consumed at least something |
| return range_offset != *offset_ptr; |
| } |
| |
| // |
| //dw_addr_t |
| //DWARFDebugRanges::RangeList::LowestAddress(const dw_addr_t cu_base_addr) const |
| //{ |
| // dw_addr_t addr = DW_INVALID_ADDRESS; |
| // dw_addr_t curr_base_addr = cu_base_addr; |
| // if (!ranges.empty()) |
| // { |
| // Range::const_iterator pos = ranges.begin(); |
| // Range::const_iterator end_pos = ranges.end(); |
| // for (pos = ranges.begin(); pos != end_pos; ++pos) |
| // { |
| // if (pos->begin_offset == DW_INVALID_ADDRESS) |
| // curr_base_addr = pos->end_offset; |
| // else if (curr_base_addr != DW_INVALID_ADDRESS) |
| // { |
| // dw_addr_t curr_addr = curr_base_addr + pos->begin_offset; |
| // if (addr > curr_addr) |
| // addr = curr_addr; |
| // } |
| // } |
| // } |
| // return addr; |
| //} |
| // |
| //dw_addr_t |
| //DWARFDebugRanges::RangeList::HighestAddress(const dw_addr_t cu_base_addr) const |
| //{ |
| // dw_addr_t addr = 0; |
| // dw_addr_t curr_base_addr = cu_base_addr; |
| // if (!ranges.empty()) |
| // { |
| // Range::const_iterator pos = ranges.begin(); |
| // Range::const_iterator end_pos = ranges.end(); |
| // for (pos = ranges.begin(); pos != end_pos; ++pos) |
| // { |
| // if (pos->begin_offset == DW_INVALID_ADDRESS) |
| // curr_base_addr = pos->end_offset; |
| // else if (curr_base_addr != DW_INVALID_ADDRESS) |
| // { |
| // dw_addr_t curr_addr = curr_base_addr + pos->end_offset; |
| // if (addr < curr_addr) |
| // addr = curr_addr; |
| // } |
| // } |
| // } |
| // if (addr != 0) |
| // return addr; |
| // return DW_INVALID_ADDRESS; |
| //} |
| // |
| |
| void |
| DWARFDebugRanges::Dump(Stream &s, const DataExtractor& debug_ranges_data, uint32_t* offset_ptr, dw_addr_t cu_base_addr) |
| { |
| uint32_t addr_size = s.GetAddressByteSize(); |
| bool verbose = s.GetVerbose(); |
| |
| dw_addr_t base_addr = cu_base_addr; |
| while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) |
| { |
| dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); |
| dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size); |
| // Extend 4 byte addresses that consits of 32 bits of 1's to be 64 bits |
| // of ones |
| if (begin == 0xFFFFFFFFull && addr_size == 4) |
| begin = DW_INVALID_ADDRESS; |
| |
| s.Indent(); |
| if (verbose) |
| { |
| s.AddressRange(begin, end, sizeof (dw_addr_t), " offsets = "); |
| } |
| |
| |
| if (begin == 0 && end == 0) |
| { |
| s.PutCString(" End"); |
| break; |
| } |
| else if (begin == DW_INVALID_ADDRESS) |
| { |
| // A base address selection entry |
| base_addr = end; |
| s.Address(base_addr, sizeof (dw_addr_t), " Base address = "); |
| } |
| else |
| { |
| // Convert from offset to an address |
| dw_addr_t begin_addr = begin + base_addr; |
| dw_addr_t end_addr = end + base_addr; |
| |
| s.AddressRange(begin_addr, end_addr, sizeof (dw_addr_t), verbose ? " ==> addrs = " : NULL); |
| } |
| } |
| } |
| |
| bool |
| DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, RangeList& range_list) const |
| { |
| range_map_const_iterator pos = m_range_map.find(debug_ranges_offset); |
| if (pos != m_range_map.end()) |
| { |
| range_list = pos->second; |
| return true; |
| } |
| return false; |
| } |
| |
| |
| |