blob: 39c5a7fd1895070cc72090852d8dc65cf7edc46b [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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
22using namespace lldb_private;
23
24//----------------------------------------------------------------------
25// Constructor
26//----------------------------------------------------------------------
27DWARFDebugAranges::DWARFDebugAranges() :
28 m_aranges()
29{
30}
31
32
33//----------------------------------------------------------------------
34// Compare function DWARFDebugAranges::Range structures
35//----------------------------------------------------------------------
36static 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//----------------------------------------------------------------------
45class CountArangeDescriptors
46{
47public:
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//----------------------------------------------------------------------
62class AddArangeDescriptors
63{
64public:
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 Clayton54e7afa2010-07-09 20:39:50 +000072 for (uint32_t i=0; (arange_desc_ptr = set.GetDescriptor(i)) != NULL; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +000073 {
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//----------------------------------------------------------------------
89static void PrintRange(const DWARFDebugAranges::Range& range)
90{
91 // Cast the address values in case the address type is compiled as 32 bit
Eli Friedman79912252010-07-09 23:04:08 +000092 printf("0x%8.8x: [0x%8.8llx - 0x%8.8llx)\n", range.offset, (long long)range.lo_pc, (long long)range.hi_pc);
Chris Lattner24943d22010-06-08 16:52:24 +000093}
94
95//----------------------------------------------------------------------
96// Extract
97//----------------------------------------------------------------------
98bool
99DWARFDebugAranges::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//----------------------------------------------------------------------
134bool
135DWARFDebugAranges::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
154void
155DWARFDebugAranges::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
162void
163DWARFDebugAranges::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//----------------------------------------------------------------------
171void
172DWARFDebugAranges::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//----------------------------------------------------------------------
238class ArangeSetContainsAddress
239{
240public:
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//----------------------------------------------------------------------
255void
256DWARFDebugAranges::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//----------------------------------------------------------------------
267void
268DWARFDebugAranges::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//----------------------------------------------------------------------
280dw_offset_t
281DWARFDebugAranges::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//----------------------------------------------------------------------
311bool
312DWARFDebugAranges::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
333bool
334DWARFDebugAranges::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