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