DWARFDebugRanges.cpp revision 263367
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
15using namespace lldb_private;
16using namespace std;
17
18DWARFDebugRanges::DWARFDebugRanges() :
19    m_range_map()
20{
21}
22
23DWARFDebugRanges::~DWARFDebugRanges()
24{
25}
26
27void
28DWARFDebugRanges::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
85bool
86DWARFDebugRanges::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
135void
136DWARFDebugRanges::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
180bool
181DWARFDebugRanges::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