1 //===-- DWARFDebugInfo.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 "SymbolFileDWARF.h"
11 
12 #include <algorithm>
13 #include <set>
14 
15 #include "lldb/Core/RegularExpression.h"
16 #include "lldb/Core/Stream.h"
17 
18 #include "DWARFDebugInfo.h"
19 #include "DWARFCompileUnit.h"
20 #include "DWARFDebugAranges.h"
21 #include "DWARFDebugInfoEntry.h"
22 #include "DWARFFormValue.h"
23 
24 using namespace lldb_private;
25 using namespace std;
26 
27 //----------------------------------------------------------------------
28 // Constructor
29 //----------------------------------------------------------------------
30 DWARFDebugInfo::DWARFDebugInfo() :
31     m_dwarf2Data(NULL),
32     m_compile_units()
33 {
34 }
35 
36 //----------------------------------------------------------------------
37 // SetDwarfData
38 //----------------------------------------------------------------------
39 void
40 DWARFDebugInfo::SetDwarfData(SymbolFileDWARF* dwarf2Data)
41 {
42     m_dwarf2Data = dwarf2Data;
43     m_compile_units.clear();
44 }
45 
46 //----------------------------------------------------------------------
47 // BuildDIEAddressRangeTable
48 //----------------------------------------------------------------------
49 bool
50 DWARFDebugInfo::BuildFunctionAddressRangeTable(DWARFDebugAranges* debug_aranges)
51 {
52     const uint32_t num_compile_units = GetNumCompileUnits();
53     uint32_t idx;
54     for (idx = 0; idx < num_compile_units; ++idx)
55     {
56         DWARFCompileUnit* cu = GetCompileUnitAtIndex (idx);
57         if (cu)
58         {
59             cu->DIE()->BuildFunctionAddressRangeTable(m_dwarf2Data, cu, debug_aranges);
60         }
61     }
62     return !debug_aranges->IsEmpty();
63 }
64 
65 //----------------------------------------------------------------------
66 // LookupAddress
67 //----------------------------------------------------------------------
68 bool
69 DWARFDebugInfo::LookupAddress
70 (
71     const dw_addr_t address,
72     const dw_offset_t hint_die_offset,
73     DWARFCompileUnitSP& cu_sp,
74     DWARFDebugInfoEntry** function_die,
75     DWARFDebugInfoEntry** block_die
76 )
77 {
78 
79     if (hint_die_offset != DW_INVALID_OFFSET)
80         cu_sp = GetCompileUnit(hint_die_offset);
81     else
82     {
83         // Get a non const version of the address ranges
84         DWARFDebugAranges* debug_aranges = ((SymbolFileDWARF*)m_dwarf2Data)->DebugAranges();
85 
86         if (debug_aranges != NULL)
87         {
88             // If we have an empty address ranges section, lets build a sorted
89             // table ourselves by going through all of the debug information so we
90             // can do quick subsequent searches.
91 
92             if (debug_aranges->IsEmpty())
93             {
94                 const uint32_t num_compile_units = GetNumCompileUnits();
95                 uint32_t idx;
96                 for (idx = 0; idx < num_compile_units; ++idx)
97                 {
98                     DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx);
99                     if (cu)
100                         cu->DIE()->BuildAddressRangeTable(m_dwarf2Data, cu, debug_aranges);
101                 }
102             }
103             cu_sp = GetCompileUnit(debug_aranges->FindAddress(address));
104         }
105     }
106 
107     if (cu_sp.get())
108     {
109         if (cu_sp->LookupAddress(address, function_die, block_die))
110             return true;
111         cu_sp.reset();
112     }
113     else
114     {
115         // The hint_die_offset may have been a pointer to the actual item that
116         // we are looking for
117         DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp);
118         if (die_ptr)
119         {
120             if (cu_sp.get())
121             {
122                 if (function_die || block_die)
123                     return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die);
124 
125                 // We only wanted the compile unit that contained this address
126                 return true;
127             }
128         }
129     }
130     return false;
131 }
132 
133 
134 void
135 DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded()
136 {
137     if (m_compile_units.empty())
138     {
139         if (m_dwarf2Data != NULL)
140         {
141             uint32_t offset = 0;
142             const DataExtractor &debug_info_data = m_dwarf2Data->get_debug_info_data();
143             while (debug_info_data.ValidOffset(offset))
144             {
145                 DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data));
146                 // Out of memory?
147                 if (cu_sp.get() == NULL)
148                     break;
149 
150                 if (cu_sp->Extract(debug_info_data, &offset) == false)
151                     break;
152 
153                 m_compile_units.push_back(cu_sp);
154 
155                 offset = cu_sp->GetNextCompileUnitOffset();
156             }
157         }
158     }
159 }
160 
161 uint32_t
162 DWARFDebugInfo::GetNumCompileUnits()
163 {
164     ParseCompileUnitHeadersIfNeeded();
165     return m_compile_units.size();
166 }
167 
168 DWARFCompileUnit*
169 DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx)
170 {
171     DWARFCompileUnit* cu = NULL;
172     if (idx < GetNumCompileUnits())
173         cu = m_compile_units[idx].get();
174     return cu;
175 }
176 
177 static bool CompileUnitOffsetLessThan (const DWARFCompileUnitSP& a, const DWARFCompileUnitSP& b)
178 {
179     return a->GetOffset() < b->GetOffset();
180 }
181 
182 
183 static int
184 CompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem)
185 {
186     const dw_offset_t key_cu_offset = *(dw_offset_t*) key;
187     const dw_offset_t cu_offset = ((DWARFCompileUnitSP *)arrmem)->get()->GetOffset();
188     if (key_cu_offset < cu_offset)
189         return -1;
190     if (key_cu_offset > cu_offset)
191         return 1;
192     return 0;
193 }
194 
195 DWARFCompileUnitSP
196 DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr)
197 {
198     DWARFCompileUnitSP cu_sp;
199     uint32_t cu_idx = DW_INVALID_INDEX;
200     if (cu_offset != DW_INVALID_OFFSET)
201     {
202         ParseCompileUnitHeadersIfNeeded();
203 
204         DWARFCompileUnitSP* match = (DWARFCompileUnitSP*)bsearch(&cu_offset, &m_compile_units[0], m_compile_units.size(), sizeof(DWARFCompileUnitSP), CompareDWARFCompileUnitSPOffset);
205         if (match)
206         {
207             cu_sp = *match;
208             cu_idx = match - &m_compile_units[0];
209         }
210     }
211     if (idx_ptr)
212         *idx_ptr = cu_idx;
213     return cu_sp;
214 }
215 
216 DWARFCompileUnitSP
217 DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset)
218 {
219     DWARFCompileUnitSP cu_sp;
220     if (die_offset != DW_INVALID_OFFSET)
221     {
222         ParseCompileUnitHeadersIfNeeded();
223 
224         CompileUnitColl::const_iterator end_pos = m_compile_units.end();
225         CompileUnitColl::const_iterator pos;
226 
227         for (pos = m_compile_units.begin(); pos != end_pos; ++pos)
228         {
229             dw_offset_t cu_start_offset = (*pos)->GetOffset();
230             dw_offset_t cu_end_offset = (*pos)->GetNextCompileUnitOffset();
231             if (cu_start_offset <= die_offset && die_offset < cu_end_offset)
232             {
233                 cu_sp = *pos;
234                 break;
235             }
236         }
237     }
238     return cu_sp;
239 }
240 
241 //----------------------------------------------------------------------
242 // Compare function DWARFDebugAranges::Range structures
243 //----------------------------------------------------------------------
244 static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2)
245 {
246     return die1.GetOffset() < die2.GetOffset();
247 }
248 
249 
250 //----------------------------------------------------------------------
251 // GetDIE()
252 //
253 // Get the DIE (Debug Information Entry) with the specified offset.
254 //----------------------------------------------------------------------
255 DWARFDebugInfoEntry*
256 DWARFDebugInfo::GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
257 {
258     DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
259     if (cu_sp_ptr)
260         *cu_sp_ptr = cu_sp;
261     if (cu_sp.get())
262         return cu_sp->GetDIEPtr(die_offset);
263     return NULL;    // Not found in any compile units
264 }
265 
266 const DWARFDebugInfoEntry*
267 DWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
268 {
269     DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
270     if (cu_sp_ptr)
271         *cu_sp_ptr = cu_sp;
272     if (cu_sp.get())
273         return cu_sp->GetDIEPtrContainingOffset(die_offset);
274 
275     return NULL;    // Not found in any compile units
276 
277 }
278 
279 //----------------------------------------------------------------------
280 // DWARFDebugInfo_ParseCallback
281 //
282 // A callback function for the static DWARFDebugInfo::Parse() function
283 // that gets parses all compile units and DIE's into an internate
284 // representation for further modification.
285 //----------------------------------------------------------------------
286 
287 static dw_offset_t
288 DWARFDebugInfo_ParseCallback
289 (
290     SymbolFileDWARF* dwarf2Data,
291     DWARFCompileUnitSP& cu_sp,
292     DWARFDebugInfoEntry* die,
293     const dw_offset_t next_offset,
294     const uint32_t curr_depth,
295     void* userData
296 )
297 {
298     DWARFDebugInfo* debug_info = (DWARFDebugInfo*)userData;
299     DWARFCompileUnit* cu = cu_sp.get();
300     if (die)
301     {
302         cu->AddDIE(*die);
303     }
304     else if (cu)
305     {
306         debug_info->AddCompileUnit(cu_sp);
307     }
308 
309     // Just return the current offset to parse the next CU or DIE entry
310     return next_offset;
311 }
312 
313 //----------------------------------------------------------------------
314 // AddCompileUnit
315 //----------------------------------------------------------------------
316 void
317 DWARFDebugInfo::AddCompileUnit(DWARFCompileUnitSP& cu)
318 {
319     m_compile_units.push_back(cu);
320 }
321 
322 /*
323 void
324 DWARFDebugInfo::AddDIE(DWARFDebugInfoEntry& die)
325 {
326     m_die_array.push_back(die);
327 }
328 */
329 
330 
331 
332 
333 //----------------------------------------------------------------------
334 // Parse
335 //
336 // Parses the .debug_info section and uses the .debug_abbrev section
337 // and various other sections in the SymbolFileDWARF class and calls the
338 // supplied callback function each time a compile unit header, or debug
339 // information entry is successfully parsed. This function can be used
340 // for different tasks such as parsing the file contents into a
341 // structured data, dumping, verifying and much more.
342 //----------------------------------------------------------------------
343 void
344 DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* userData)
345 {
346     if (dwarf2Data)
347     {
348         uint32_t offset = 0;
349         uint32_t depth = 0;
350         DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data));
351         if (cu.get() == NULL)
352             return;
353         DWARFDebugInfoEntry die;
354 
355         while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset))
356         {
357             const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset();
358 
359             depth = 0;
360             // Call the callback funtion with no DIE pointer for the compile unit
361             // and get the offset that we are to continue to parse from
362             offset = callback(dwarf2Data, cu, NULL, offset, depth, userData);
363 
364             // Make sure we are within our compile unit
365             if (offset < next_cu_offset)
366             {
367                 // We are in our compile unit, parse starting at the offset
368                 // we were told to parse
369                 bool done = false;
370                 while (!done && die.Extract(dwarf2Data, cu.get(), &offset))
371                 {
372                     // Call the callback funtion with DIE pointer that falls within the compile unit
373                     offset = callback(dwarf2Data, cu, &die, offset, depth, userData);
374 
375                     if (die.IsNULL())
376                     {
377                         if (depth)
378                             --depth;
379                         else
380                             done = true;    // We are done with this compile unit!
381                     }
382                     else if (die.HasChildren())
383                         ++depth;
384                 }
385             }
386 
387             // Make sure the offset returned is valid, and if not stop parsing.
388             // Returning DW_INVALID_OFFSET from this callback is a good way to end
389             // all parsing
390             if (!dwarf2Data->get_debug_info_data().ValidOffset(offset))
391                 break;
392 
393             // See if during the callback anyone retained a copy of the compile
394             // unit other than ourselves and if so, let whomever did own the object
395             // and create a new one for our own use!
396             if (!cu.unique())
397                 cu.reset(new DWARFCompileUnit(dwarf2Data));
398 
399 
400             // Make sure we start on a propper
401             offset = next_cu_offset;
402         }
403     }
404 }
405 
406 /*
407 typedef struct AddressRangeTag
408 {
409     dw_addr_t   lo_pc;
410     dw_addr_t   hi_pc;
411     dw_offset_t die_offset;
412 } AddressRange;
413 */
414 struct DIERange
415 {
416     DIERange() :
417         range(),
418         lo_die_offset(),
419         hi_die_offset()
420     {
421     }
422 
423     DWARFDebugAranges::Range range;
424     dw_offset_t lo_die_offset;
425     dw_offset_t hi_die_offset;
426 };
427 
428 typedef struct DwarfStat
429 {
430     DwarfStat() : count(0), byte_size(0) {}
431     uint32_t count;
432     uint32_t byte_size;
433 } DwarfStat;
434 
435 typedef map<dw_attr_t, DwarfStat> DwarfAttrStatMap;
436 
437 typedef struct DIEStat
438 {
439     DIEStat() : count(0), byte_size(0), attr_stats() {}
440     uint32_t count;
441     uint32_t byte_size;
442     DwarfAttrStatMap attr_stats;
443 } DIEStat;
444 
445 typedef map<dw_tag_t, DIEStat> DIEStatMap;
446 struct VerifyInfo
447 {
448     VerifyInfo(Stream* the_strm) :
449         strm(the_strm),
450         die_ranges(),
451         addr_range_errors(0),
452         sibling_errors(0),
453         die_stats()
454     {
455     }
456 
457     Stream* strm;
458     vector<DIERange> die_ranges;
459     uint32_t addr_range_errors;
460     uint32_t sibling_errors;
461     DIEStatMap die_stats;
462 
463     DISALLOW_COPY_AND_ASSIGN(VerifyInfo);
464 
465 };
466 
467 
468 //----------------------------------------------------------------------
469 // VerifyCallback
470 //
471 // A callback function for the static DWARFDebugInfo::Parse() function
472 // that gets called each time a compile unit header or debug information
473 // entry is successfully parsed.
474 //
475 // This function will verify the DWARF information is well formed by
476 // making sure that any DW_TAG_compile_unit tags that have valid address
477 // ranges (DW_AT_low_pc and DW_AT_high_pc) have no gaps in the address
478 // ranges of it contained DW_TAG_subprogram tags. Also the sibling chain
479 // and relationships are verified to make sure nothing gets hosed up
480 // when dead stripping occurs.
481 //----------------------------------------------------------------------
482 
483 static dw_offset_t
484 VerifyCallback
485 (
486     SymbolFileDWARF* dwarf2Data,
487     DWARFCompileUnitSP& cu_sp,
488     DWARFDebugInfoEntry* die,
489     const dw_offset_t next_offset,
490     const uint32_t curr_depth,
491     void* userData
492 )
493 {
494     VerifyInfo* verifyInfo = (VerifyInfo*)userData;
495 
496     const DWARFCompileUnit* cu = cu_sp.get();
497     Stream *s = verifyInfo->strm;
498     bool verbose = s->GetVerbose();
499     if (die)
500     {
501     //  die->Dump(dwarf2Data, cu, f);
502         const DWARFAbbreviationDeclaration* abbrevDecl = die->GetAbbreviationDeclarationPtr();
503         // We have a DIE entry
504         if (abbrevDecl)
505         {
506             const dw_offset_t die_offset = die->GetOffset();
507             const dw_offset_t sibling = die->GetAttributeValueAsReference(dwarf2Data, cu, DW_AT_sibling, DW_INVALID_OFFSET);
508 
509             if (sibling != DW_INVALID_OFFSET)
510             {
511                 if (sibling <= next_offset)
512                 {
513                     if (verifyInfo->sibling_errors++ == 0)
514                         s->Printf("ERROR\n");
515                     s->Printf("    0x%8.8x: sibling attribyte (0x%8.8x) in this die is not valid: it is less than this DIE or some of its contents.\n", die->GetOffset(), sibling);
516                 }
517                 else if (sibling > verifyInfo->die_ranges.back().hi_die_offset)
518                 {
519                     if (verifyInfo->sibling_errors++ == 0)
520                         s->Printf("ERROR\n");
521                     s->Printf("    0x%8.8x: sibling attribute (0x%8.8x) in this DIE is not valid: it is greater than the end of the parent scope.\n", die->GetOffset(), sibling);
522                 }
523             }
524 
525             if ((die_offset < verifyInfo->die_ranges.back().lo_die_offset) || (die_offset >= verifyInfo->die_ranges.back().hi_die_offset))
526             {
527                 if (verifyInfo->sibling_errors++ == 0)
528                     s->Printf("ERROR\n");
529                 s->Printf("    0x%8.8x: DIE offset is not within the parent DIE range {0x%8.8x}: (0x%8.8x - 0x%8.8x)\n",
530                         die->GetOffset(),
531                         verifyInfo->die_ranges.back().range.offset,
532                         verifyInfo->die_ranges.back().lo_die_offset,
533                         verifyInfo->die_ranges.back().hi_die_offset);
534 
535             }
536 
537             dw_tag_t tag = abbrevDecl->Tag();
538 
539             // Keep some stats on this DWARF file
540             verifyInfo->die_stats[tag].count++;
541             verifyInfo->die_stats[tag].byte_size += (next_offset - die->GetOffset());
542 
543             if (verbose)
544             {
545                 DIEStat& tag_stat = verifyInfo->die_stats[tag];
546 
547                 const DataExtractor& debug_info = dwarf2Data->get_debug_info_data();
548 
549                 dw_offset_t offset = die->GetOffset();
550                 // Skip the abbreviation code so we are at the data for the attributes
551                 debug_info.Skip_LEB128(&offset);
552 
553                 const uint32_t numAttributes = abbrevDecl->NumAttributes();
554                 dw_attr_t attr;
555                 dw_form_t form;
556                 for (uint32_t idx = 0; idx < numAttributes; ++idx)
557                 {
558                     dw_offset_t start_offset = offset;
559                     abbrevDecl->GetAttrAndFormByIndexUnchecked(idx, attr, form);
560                     DWARFFormValue::SkipValue(form, debug_info, &offset, cu);
561 
562                     if (tag_stat.attr_stats.find(attr) == tag_stat.attr_stats.end())
563                     {
564                         tag_stat.attr_stats[attr].count = 0;
565                         tag_stat.attr_stats[attr].byte_size = 0;
566                     }
567 
568                     tag_stat.attr_stats[attr].count++;
569                     tag_stat.attr_stats[attr].byte_size += offset - start_offset;
570                 }
571             }
572 
573             DWARFDebugAranges::Range range;
574             range.offset = die->GetOffset();
575 
576             switch (tag)
577             {
578             case DW_TAG_compile_unit:
579                 // Check for previous subroutines that were within a previous
580                 //
581             //  VerifyAddressRangesForCU(verifyInfo);
582                 // Remember which compile unit we are dealing with so we can verify
583                 // the address ranges within it (if any) are contiguous. The DWARF
584                 // spec states that if a compile unit TAG has high and low PC
585                 // attributes, there must be no gaps in the address ranges of it's
586                 // contained subtroutines. If there are gaps, the high and low PC
587                 // must not be in the DW_TAG_compile_unit's attributes. Errors like
588                 // this can crop up when optimized code is dead stripped and the debug
589                 // information isn't properly fixed up for output.
590                 range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
591                 if (range.lo_pc != DW_INVALID_ADDRESS)
592                 {
593                     range.hi_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
594                     if (s->GetVerbose())
595                     {
596                         s->Printf("\n    CU ");
597                         range.Dump(s);
598                     }
599                 }
600                 else
601                 {
602                     range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_entry_pc, DW_INVALID_ADDRESS);
603                 }
604                 break;
605 
606             case DW_TAG_subprogram:
607                 // If the DW_TAG_compile_unit that contained this function had a
608                 // valid address range, add all of the valid subroutine address
609                 // ranges to a collection of addresses which will be sorted
610                 // and verified right before the next DW_TAG_compile_unit is
611                 // processed to make sure that there are no gaps in the address
612                 // range.
613                 range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
614                 if (range.lo_pc != DW_INVALID_ADDRESS)
615                 {
616                     range.hi_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
617                     if (range.hi_pc != DW_INVALID_ADDRESS)
618                     {
619                         range.offset = die->GetOffset();
620                         bool valid = range.ValidRange();
621                         if (!valid || s->GetVerbose())
622                         {
623                             s->Printf("\n  FUNC ");
624                             range.Dump(s);
625                             if (!valid)
626                             {
627                                 ++verifyInfo->addr_range_errors;
628                                 s->Printf(" ERROR: Invalid address range for function.");
629                             }
630                         }
631 
632                         // Only add to our subroutine ranges if our compile unit has a valid address range
633                     //  if (valid && verifyInfo->die_ranges.size() >= 2 && verifyInfo->die_ranges[1].range.ValidRange())
634                     //      verifyInfo->subroutine_ranges.InsertRange(range);
635                     }
636                 }
637                 break;
638 
639             case DW_TAG_lexical_block:
640             case DW_TAG_inlined_subroutine:
641                 {
642                     range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS);
643                     if (range.lo_pc != DW_INVALID_ADDRESS)
644                     {
645                         range.hi_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS);
646                         if (range.hi_pc != DW_INVALID_ADDRESS)
647                         {
648                             range.offset = die->GetOffset();
649                             bool valid = range.ValidRange();
650                             if (!valid || s->GetVerbose())
651                             {
652                                 s->Printf("\n  BLCK ");
653                                 range.Dump(s);
654                                 if (!valid)
655                                 {
656                                     ++verifyInfo->addr_range_errors;
657                                     s->Printf(" ERROR: Invalid address range for block or inlined subroutine.");
658                                 }
659                             }
660                         }
661                     }
662                 }
663                 break;
664             }
665 
666             if (range.ValidRange() && verifyInfo->die_ranges.back().range.ValidRange())
667             {
668                 if (!verifyInfo->die_ranges.back().range.Contains(range))
669                 {
670                     ++verifyInfo->addr_range_errors;
671                     s->Printf("\n       ");
672                     range.Dump(s);
673                     s->Printf(" ERROR: Range is not in parent");
674                     verifyInfo->die_ranges.back().range.Dump(s);
675                 }
676             }
677 
678             if (die->HasChildren())
679             {
680                 // Keep tabs on the valid address ranges for the current item to make
681                 // sure that it all fits (make sure the sibling offsets got fixed up
682                 // correctly if any functions were dead stripped).
683                 DIERange die_range;
684                 die_range.range = range;
685                 die_range.lo_die_offset = next_offset;
686                 die_range.hi_die_offset = sibling;
687                 if (die_range.hi_die_offset == DW_INVALID_OFFSET)
688                     die_range.hi_die_offset = verifyInfo->die_ranges.back().hi_die_offset;
689                 verifyInfo->die_ranges.push_back(die_range);
690             }
691         }
692         else
693         {
694             // NULL entry
695             verifyInfo->die_ranges.pop_back();
696         }
697     }
698     else
699     {
700     //  cu->Dump(ostrm_ptr); // Dump the compile unit for the DIE
701         // We have a new comile unit header
702         verifyInfo->die_ranges.clear();
703         DIERange die_range;
704         die_range.range.offset  = cu->GetOffset();
705         die_range.lo_die_offset = next_offset;
706         die_range.hi_die_offset = cu->GetNextCompileUnitOffset();
707         verifyInfo->die_ranges.push_back(die_range);
708     }
709 
710     // Just return the current offset to parse the next CU or DIE entry
711     return next_offset;
712 }
713 
714 
715 class CompareDIEStatSizes
716 {
717 public:
718     bool operator() (const DIEStatMap::const_iterator& pos1, const DIEStatMap::const_iterator& pos2) const
719     {
720         return pos1->second.byte_size <= pos2->second.byte_size;
721     }
722 };
723 
724 class CompareAttrDIEStatSizes
725 {
726 public:
727     bool operator() (const DwarfAttrStatMap::const_iterator& pos1, const DwarfAttrStatMap::const_iterator& pos2) const
728     {
729         return pos1->second.byte_size <= pos2->second.byte_size;
730     }
731 };
732 
733 //----------------------------------------------------------------------
734 // Verify
735 //
736 // Verifies the DWARF information is valid.
737 //----------------------------------------------------------------------
738 void
739 DWARFDebugInfo::Verify(Stream *s, SymbolFileDWARF* dwarf2Data)
740 {
741     s->Printf("Verifying Compile Unit Header chain.....");
742     VerifyInfo verifyInfo(s);
743     verifyInfo.addr_range_errors = 0;
744     verifyInfo.sibling_errors = 0;
745 
746     bool verbose = s->GetVerbose();
747 
748     uint32_t offset = 0;
749     if (verbose)
750         s->EOL();
751 //  vector<dw_offset_t> valid_cu_offsets;
752     DWARFCompileUnit cu (dwarf2Data);
753     bool success = true;
754     while ( success && dwarf2Data->get_debug_info_data().ValidOffset(offset+cu.Size()) )
755     {
756         success = cu.Extract (dwarf2Data->get_debug_info_data(), &offset);
757         if (!success)
758             s->Printf("ERROR\n");
759     //  else
760     //      valid_cu_offsets.push_back(cu.GetOffset());
761 
762         cu.Verify(verifyInfo.strm);
763         offset = cu.GetNextCompileUnitOffset();
764     }
765 
766     if (success)
767         s->Printf("OK\n");
768 
769     s->Printf("Verifying address ranges and siblings...");
770     if (verbose)
771         s->EOL();
772     DWARFDebugInfo::Parse(dwarf2Data, VerifyCallback, &verifyInfo);
773 
774 //  VerifyAddressRangesForCU(&verifyInfo);
775 
776     if (verifyInfo.addr_range_errors > 0)
777         s->Printf("\nERRORS - %u error(s) were found.\n", verifyInfo.addr_range_errors);
778     else
779         s->Printf("OK\n");
780 
781     uint32_t total_category_sizes[kNumTagCategories] = {0};
782     uint32_t total_category_count[kNumTagCategories] = {0};
783     uint32_t total_die_count = 0;
784     uint32_t total_die_size = 0;
785 
786     typedef set<DIEStatMap::const_iterator, CompareDIEStatSizes> DIEStatBySizeMap;
787 
788     s->PutCString(  "\n"
789                 "DWARF Statistics\n"
790                 "Count    Size     Size %   Tag\n"
791                 "-------- -------- -------- -------------------------------------------\n");
792     DIEStatBySizeMap statBySizeMap;
793     DIEStatMap::const_iterator pos;
794     DIEStatMap::const_iterator end_pos = verifyInfo.die_stats.end();
795     for (pos = verifyInfo.die_stats.begin(); pos != end_pos; ++pos)
796     {
797         const uint32_t die_count = pos->second.count;
798         const uint32_t die_size = pos->second.byte_size;
799 
800         statBySizeMap.insert(pos);
801         total_die_count += die_count;
802         total_die_size += die_size;
803         DW_TAG_CategoryEnum category = get_tag_category(pos->first);
804         total_category_sizes[category] += die_size;
805         total_category_count[category] += die_count;
806     }
807 
808     float total_die_size_float = total_die_size;
809 
810     DIEStatBySizeMap::const_reverse_iterator size_pos;
811     DIEStatBySizeMap::const_reverse_iterator size_pos_end = statBySizeMap.rend();
812     float percentage;
813     for (size_pos = statBySizeMap.rbegin(); size_pos != size_pos_end; ++size_pos)
814     {
815         pos = *size_pos;
816 
817         const DIEStat& tag_stat = pos->second;
818 
819         const uint32_t die_count = tag_stat.count;
820         const uint32_t die_size = tag_stat.byte_size;
821         percentage = ((float)die_size/total_die_size_float)*100.0;
822         s->Printf("%7u %8u %2.2f%%     %s\n", die_count, die_size, percentage, DW_TAG_value_to_name(pos->first));
823 
824         const DwarfAttrStatMap& attr_stats = tag_stat.attr_stats;
825         if (!attr_stats.empty())
826         {
827             typedef set<DwarfAttrStatMap::const_iterator, CompareAttrDIEStatSizes> DwarfAttrStatBySizeMap;
828             DwarfAttrStatBySizeMap attrStatBySizeMap;
829             DwarfAttrStatMap::const_iterator attr_stat_pos;
830             DwarfAttrStatMap::const_iterator attr_stat_pos_end = attr_stats.end();
831             for (attr_stat_pos = attr_stats.begin(); attr_stat_pos != attr_stat_pos_end; ++attr_stat_pos)
832             {
833                 attrStatBySizeMap.insert(attr_stat_pos);
834             }
835 
836             DwarfAttrStatBySizeMap::const_reverse_iterator attr_size_pos;
837             DwarfAttrStatBySizeMap::const_reverse_iterator attr_size_pos_end = attrStatBySizeMap.rend();
838             for (attr_size_pos = attrStatBySizeMap.rbegin(); attr_size_pos != attr_size_pos_end; ++attr_size_pos)
839             {
840                 attr_stat_pos = *attr_size_pos;
841                 percentage = ((float)attr_stat_pos->second.byte_size/die_size)*100.0;
842                 s->Printf("%7u %8u %2.2f%%    %s\n", attr_stat_pos->second.count, attr_stat_pos->second.byte_size, percentage, DW_AT_value_to_name(attr_stat_pos->first));
843             }
844             s->EOL();
845         }
846     }
847 
848     s->Printf("-------- -------- -------- -------------------------------------------\n");
849     s->Printf("%7u %8u 100.00% Total for all DIEs\n", total_die_count, total_die_size);
850 
851     float total_category_percentages[kNumTagCategories] =
852     {
853         ((float)total_category_sizes[TagCategoryVariable]/total_die_size_float)*100.0,
854         ((float)total_category_sizes[TagCategoryType]/total_die_size_float)*100.0,
855         ((float)total_category_sizes[TagCategoryProgram]/total_die_size_float)*100.0
856     };
857 
858     s->EOL();
859     s->Printf("%7u %8u %2.2f%%    %s\n", total_category_count[TagCategoryVariable], total_category_sizes[TagCategoryVariable],  total_category_percentages[TagCategoryVariable],    "Total for variable related DIEs");
860     s->Printf("%7u %8u %2.2f%%    %s\n", total_category_count[TagCategoryType],     total_category_sizes[TagCategoryType],      total_category_percentages[TagCategoryType],        "Total for type related DIEs");
861     s->Printf("%7u %8u %2.2f%%    %s\n", total_category_count[TagCategoryProgram],      total_category_sizes[TagCategoryProgram],   total_category_percentages[TagCategoryProgram],     "Total for program related DIEs");
862     s->Printf("\n\n");
863 }
864 
865 typedef struct DumpInfo
866 {
867     DumpInfo(Stream* init_strm, uint32_t off, uint32_t depth) :
868         strm(init_strm),
869         die_offset(off),
870         recurse_depth(depth),
871         found_depth(UINT_MAX),
872         found_die(false),
873         ancestors()
874     {
875     }
876     Stream* strm;
877     const uint32_t die_offset;
878     const uint32_t recurse_depth;
879     uint32_t found_depth;
880     bool found_die;
881     std::vector<DWARFDebugInfoEntry> ancestors;
882 
883     DISALLOW_COPY_AND_ASSIGN(DumpInfo);
884 } DumpInfo;
885 
886 //----------------------------------------------------------------------
887 // DumpCallback
888 //
889 // A callback function for the static DWARFDebugInfo::Parse() function
890 // that gets called each time a compile unit header or debug information
891 // entry is successfully parsed.
892 //
893 // This function dump DWARF information and obey recurse depth and
894 // wether a single DIE is to be dumped (or all of the data).
895 //----------------------------------------------------------------------
896 static dw_offset_t DumpCallback
897 (
898     SymbolFileDWARF* dwarf2Data,
899     DWARFCompileUnitSP& cu_sp,
900     DWARFDebugInfoEntry* die,
901     const dw_offset_t next_offset,
902     const uint32_t curr_depth,
903     void* userData
904 )
905 {
906     DumpInfo* dumpInfo = (DumpInfo*)userData;
907 
908     const DWARFCompileUnit* cu = cu_sp.get();
909 
910     Stream *s = dumpInfo->strm;
911     bool show_parents = s->GetFlags().IsSet(DWARFDebugInfo::eDumpFlag_ShowAncestors);
912 
913     if (die)
914     {
915         // Are we dumping everything?
916         if (dumpInfo->die_offset == DW_INVALID_OFFSET)
917         {
918             // Yes we are dumping everything. Obey our recurse level though
919             if (curr_depth < dumpInfo->recurse_depth)
920                 die->Dump(dwarf2Data, cu, s, 0);
921         }
922         else
923         {
924             // We are dumping a specific DIE entry by offset
925             if (dumpInfo->die_offset == die->GetOffset())
926             {
927                 // We found the DIE we were looking for, dump it!
928                 if (show_parents)
929                 {
930                     s->SetIndentLevel(0);
931                     const uint32_t num_ancestors = dumpInfo->ancestors.size();
932                     if (num_ancestors > 0)
933                     {
934                         for (uint32_t i=0; i<num_ancestors-1; ++i)
935                         {
936                             dumpInfo->ancestors[i].Dump(dwarf2Data, cu, s, 0);
937                             s->IndentMore();
938                         }
939                     }
940                 }
941 
942                 dumpInfo->found_depth = curr_depth;
943 
944                 die->Dump(dwarf2Data, cu, s, 0);
945 
946                 // Note that we found the DIE we were looking for
947                 dumpInfo->found_die = true;
948 
949                 // Since we are dumping a single DIE, if there are no children we are done!
950                 if (!die->HasChildren() || dumpInfo->recurse_depth == 0)
951                     return DW_INVALID_OFFSET;   // Return an invalid address to end parsing
952             }
953             else if (dumpInfo->found_die)
954             {
955                 // Are we done with all the children?
956                 if (curr_depth <= dumpInfo->found_depth)
957                     return DW_INVALID_OFFSET;
958 
959                 // We have already found our DIE and are printing it's children. Obey
960                 // our recurse depth and return an invalid offset if we get done
961                 // dumping all the the children
962                 if (dumpInfo->recurse_depth == UINT_MAX || curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
963                     die->Dump(dwarf2Data, cu, s, 0);
964             }
965             else if (dumpInfo->die_offset > die->GetOffset())
966             {
967                 if (show_parents)
968                     dumpInfo->ancestors.back() = *die;
969             }
970         }
971 
972         // Keep up with our indent level
973         if (die->IsNULL())
974         {
975             if (show_parents)
976                 dumpInfo->ancestors.pop_back();
977 
978             if (curr_depth <= 1)
979                 return cu->GetNextCompileUnitOffset();
980             else
981                 s->IndentLess();
982         }
983         else if (die->HasChildren())
984         {
985             if (show_parents)
986             {
987                 DWARFDebugInfoEntry null_die;
988                 dumpInfo->ancestors.push_back(null_die);
989             }
990             s->IndentMore();
991         }
992     }
993     else
994     {
995         if (cu == NULL)
996             s->PutCString("NULL - cu");
997         // We have a compile unit, reset our indent level to zero just in case
998         s->SetIndentLevel(0);
999 
1000         // See if we are dumping everything?
1001         if (dumpInfo->die_offset == DW_INVALID_OFFSET)
1002         {
1003             // We are dumping everything
1004             cu->Dump(s);
1005             return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit
1006         }
1007         else
1008         {
1009             if (show_parents)
1010             {
1011                 dumpInfo->ancestors.clear();
1012                 dumpInfo->ancestors.resize(1);
1013             }
1014 
1015             // We are dumping only a single DIE possibly with it's children and
1016             // we must find it's compile unit before we can dump it properly
1017             if (dumpInfo->die_offset < cu->GetFirstDIEOffset())
1018             {
1019                 // Not found, maybe the DIE offset provided wasn't correct?
1020             //  *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl;
1021                 return DW_INVALID_OFFSET;
1022             }
1023             else
1024             {
1025                 // See if the DIE is in this compile unit?
1026                 if (dumpInfo->die_offset < cu->GetNextCompileUnitOffset())
1027                 {
1028                     // This DIE is in this compile unit!
1029                     if (s->GetVerbose())
1030                         cu->Dump(s); // Dump the compile unit for the DIE in verbose mode
1031 
1032                     return next_offset;
1033                 //  // We found our compile unit that contains our DIE, just skip to dumping the requested DIE...
1034                 //  return dumpInfo->die_offset;
1035                 }
1036                 else
1037                 {
1038                     // Skip to the next compile unit as the DIE isn't in the current one!
1039                     return cu->GetNextCompileUnitOffset();
1040                 }
1041             }
1042         }
1043     }
1044 
1045     // Just return the current offset to parse the next CU or DIE entry
1046     return next_offset;
1047 }
1048 
1049 //----------------------------------------------------------------------
1050 // Dump
1051 //
1052 // Dump the information in the .debug_info section to the specified
1053 // ostream. If die_offset is valid, a single DIE will be dumped. If the
1054 // die_offset is invalid, all the DWARF information will be dumped. Both
1055 // cases will obey a "recurse_depth" or how deep to traverse into the
1056 // children of each DIE entry. A recurse_depth of zero will dump all
1057 // compile unit headers. A recurse_depth of 1 will dump all compile unit
1058 // headers and the DW_TAG_compile unit tags. A depth of 2 will also
1059 // dump all types and functions.
1060 //----------------------------------------------------------------------
1061 void
1062 DWARFDebugInfo::Dump
1063 (
1064     Stream *s,
1065     SymbolFileDWARF* dwarf2Data,
1066     const uint32_t die_offset,
1067     const uint32_t recurse_depth
1068 )
1069 {
1070     DumpInfo dumpInfo(s, die_offset, recurse_depth);
1071     s->PutCString(".debug_info contents");
1072     if (dwarf2Data->get_debug_info_data().GetByteSize() > 0)
1073     {
1074         if (die_offset == DW_INVALID_OFFSET)
1075             s->PutCString(":\n");
1076         else
1077         {
1078             s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset);
1079             if (recurse_depth != UINT_MAX)
1080                 s->Printf(" recursing %u levels deep.", recurse_depth);
1081             s->EOL();
1082         }
1083     }
1084     else
1085     {
1086         s->PutCString(": < EMPTY >\n");
1087         return;
1088     }
1089     DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo);
1090 }
1091 
1092 
1093 //----------------------------------------------------------------------
1094 // Dump
1095 //
1096 // Dump the contents of this DWARFDebugInfo object as has been parsed
1097 // and/or modified after it has been parsed.
1098 //----------------------------------------------------------------------
1099 void
1100 DWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recurse_depth)
1101 {
1102     DumpInfo dumpInfo(s, die_offset, recurse_depth);
1103 
1104     s->PutCString("Dumping .debug_info section from internal representation\n");
1105 
1106     CompileUnitColl::const_iterator pos;
1107     uint32_t curr_depth = 0;
1108     ParseCompileUnitHeadersIfNeeded();
1109     for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos)
1110     {
1111         const DWARFCompileUnitSP& cu_sp = *pos;
1112         DumpCallback(m_dwarf2Data, (DWARFCompileUnitSP&)cu_sp, NULL, 0, curr_depth, &dumpInfo);
1113         cu_sp->DIE()->Dump(m_dwarf2Data, cu_sp.get(), s, recurse_depth);
1114     }
1115 }
1116 
1117 
1118 //----------------------------------------------------------------------
1119 // FindCallbackString
1120 //
1121 // A callback function for the static DWARFDebugInfo::Parse() function
1122 // that gets called each time a compile unit header or debug information
1123 // entry is successfully parsed.
1124 //
1125 // This function will find the die_offset of any items whose DW_AT_name
1126 // matches the given string
1127 //----------------------------------------------------------------------
1128 typedef struct FindCallbackStringInfoTag
1129 {
1130     const char* name;
1131     bool ignore_case;
1132     RegularExpression* regex;
1133     vector<dw_offset_t>& die_offsets;
1134 } FindCallbackStringInfo;
1135 
1136 static dw_offset_t FindCallbackString
1137 (
1138     SymbolFileDWARF* dwarf2Data,
1139     DWARFCompileUnitSP& cu_sp,
1140     DWARFDebugInfoEntry* die,
1141     const dw_offset_t next_offset,
1142     const uint32_t curr_depth,
1143     void* userData
1144 )
1145 {
1146     FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData;
1147     const DWARFCompileUnit* cu = cu_sp.get();
1148 
1149     if (die)
1150     {
1151         const char* die_name = die->GetName(dwarf2Data, cu);
1152         if (die_name)
1153         {
1154             if (info->regex)
1155             {
1156                 if (info->regex->Execute(die_name))
1157                     info->die_offsets.push_back(die->GetOffset());
1158             }
1159             else
1160             {
1161                 if ((info->ignore_case ? strcasecmp(die_name, info->name) : strcmp(die_name, info->name)) == 0)
1162                     info->die_offsets.push_back(die->GetOffset());
1163             }
1164         }
1165     }
1166 
1167     // Just return the current offset to parse the next CU or DIE entry
1168     return next_offset;
1169 }
1170 
1171 //----------------------------------------------------------------------
1172 // Find
1173 //
1174 // Finds all DIE that have a specific DW_AT_name attribute by manually
1175 // searching through the debug information (not using the
1176 // .debug_pubnames section). The string must match the entire name
1177 // and case sensitive searches are an option.
1178 //----------------------------------------------------------------------
1179 bool
1180 DWARFDebugInfo::Find(const char* name, bool ignore_case, vector<dw_offset_t>& die_offsets) const
1181 {
1182     die_offsets.clear();
1183     if (name && name[0])
1184     {
1185         FindCallbackStringInfo info = { name, ignore_case, NULL, die_offsets };
1186         DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
1187     }
1188     return !die_offsets.empty();
1189 }
1190 
1191 //----------------------------------------------------------------------
1192 // Find
1193 //
1194 // Finds all DIE that have a specific DW_AT_name attribute by manually
1195 // searching through the debug information (not using the
1196 // .debug_pubnames section). The string must match the supplied regular
1197 // expression.
1198 //----------------------------------------------------------------------
1199 bool
1200 DWARFDebugInfo::Find(RegularExpression& re, vector<dw_offset_t>& die_offsets) const
1201 {
1202     die_offsets.clear();
1203     FindCallbackStringInfo info = { NULL, false, &re, die_offsets };
1204     DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
1205     return !die_offsets.empty();
1206 }
1207