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 #include "lldb/Symbol/ObjectFile.h"
18 
19 #include "DWARFDebugAranges.h"
20 #include "DWARFDebugInfo.h"
21 #include "DWARFCompileUnit.h"
22 #include "DWARFDebugAranges.h"
23 #include "DWARFDebugInfoEntry.h"
24 #include "DWARFFormValue.h"
25 #include "LogChannelDWARF.h"
26 
27 using namespace lldb;
28 using namespace lldb_private;
29 using namespace std;
30 
31 //----------------------------------------------------------------------
32 // Constructor
33 //----------------------------------------------------------------------
34 DWARFDebugInfo::DWARFDebugInfo() :
35     m_dwarf2Data(NULL),
36     m_compile_units(),
37     m_cu_aranges_ap ()
38 {
39 }
40 
41 //----------------------------------------------------------------------
42 // SetDwarfData
43 //----------------------------------------------------------------------
44 void
45 DWARFDebugInfo::SetDwarfData(SymbolFileDWARF* dwarf2Data)
46 {
47     m_dwarf2Data = dwarf2Data;
48     m_compile_units.clear();
49 }
50 
51 
52 DWARFDebugAranges &
53 DWARFDebugInfo::GetCompileUnitAranges ()
54 {
55     if (m_cu_aranges_ap.get() == NULL && m_dwarf2Data)
56     {
57         Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
58 
59         m_cu_aranges_ap.reset (new DWARFDebugAranges());
60         const DWARFDataExtractor &debug_aranges_data = m_dwarf2Data->get_debug_aranges_data();
61         if (debug_aranges_data.GetByteSize() > 0)
62         {
63             if (log)
64                 log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from .debug_aranges",
65                              m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
66             m_cu_aranges_ap->Extract (debug_aranges_data);
67 
68         }
69 
70         // Make a list of all CUs represented by the arange data in the file.
71         std::set<dw_offset_t> cus_with_data;
72         for (size_t n=0;n<m_cu_aranges_ap.get()->GetNumRanges();n++)
73         {
74             dw_offset_t offset = m_cu_aranges_ap.get()->OffsetAtIndex(n);
75             if (offset != DW_INVALID_OFFSET)
76                 cus_with_data.insert (offset);
77         }
78 
79         // Manually build arange data for everything that wasn't in the .debug_aranges table.
80         bool printed = false;
81         const size_t num_compile_units = GetNumCompileUnits();
82         for (size_t idx = 0; idx < num_compile_units; ++idx)
83         {
84             DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx);
85 
86             dw_offset_t offset = cu->GetOffset();
87             if (cus_with_data.find(offset) == cus_with_data.end())
88             {
89                 if (log)
90                 {
91                     if (!printed)
92                         log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing",
93                                      m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
94                     printed = true;
95                 }
96                 cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get());
97             }
98         }
99 
100         const bool minimize = true;
101         m_cu_aranges_ap->Sort (minimize);
102     }
103     return *m_cu_aranges_ap.get();
104 }
105 
106 void
107 DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded()
108 {
109     if (m_compile_units.empty())
110     {
111         if (m_dwarf2Data != NULL)
112         {
113             lldb::offset_t offset = 0;
114             const DWARFDataExtractor &debug_info_data = m_dwarf2Data->get_debug_info_data();
115             while (debug_info_data.ValidOffset(offset))
116             {
117                 DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data));
118                 // Out of memory?
119                 if (cu_sp.get() == NULL)
120                     break;
121 
122                 if (cu_sp->Extract(debug_info_data, &offset) == false)
123                     break;
124 
125                 m_compile_units.push_back(cu_sp);
126 
127                 offset = cu_sp->GetNextCompileUnitOffset();
128             }
129         }
130     }
131 }
132 
133 size_t
134 DWARFDebugInfo::GetNumCompileUnits()
135 {
136     ParseCompileUnitHeadersIfNeeded();
137     return m_compile_units.size();
138 }
139 
140 DWARFCompileUnit*
141 DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx)
142 {
143     DWARFCompileUnit* cu = NULL;
144     if (idx < GetNumCompileUnits())
145         cu = m_compile_units[idx].get();
146     return cu;
147 }
148 
149 bool
150 DWARFDebugInfo::ContainsCompileUnit (const DWARFCompileUnit *cu) const
151 {
152     // Not a verify efficient function, but it is handy for use in assertions
153     // to make sure that a compile unit comes from a debug information file.
154     CompileUnitColl::const_iterator end_pos = m_compile_units.end();
155     CompileUnitColl::const_iterator pos;
156 
157     for (pos = m_compile_units.begin(); pos != end_pos; ++pos)
158     {
159         if (pos->get() == cu)
160             return true;
161     }
162     return false;
163 }
164 
165 bool
166 DWARFDebugInfo::OffsetLessThanCompileUnitOffset (dw_offset_t offset, const DWARFCompileUnitSP& cu_sp)
167 {
168     return offset < cu_sp->GetOffset();
169 }
170 
171 DWARFCompileUnit *
172 DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr)
173 {
174     DWARFCompileUnitSP cu_sp;
175     uint32_t cu_idx = DW_INVALID_INDEX;
176     if (cu_offset != DW_INVALID_OFFSET)
177     {
178         ParseCompileUnitHeadersIfNeeded();
179 
180         // Watch out for single compile unit executable as they are pretty common
181         const size_t num_cus = m_compile_units.size();
182         if (num_cus == 1)
183         {
184             if (m_compile_units[0]->GetOffset() == cu_offset)
185             {
186                 cu_sp = m_compile_units[0];
187                 cu_idx = 0;
188             }
189         }
190         else if (num_cus)
191         {
192             CompileUnitColl::const_iterator end_pos = m_compile_units.end();
193             CompileUnitColl::const_iterator begin_pos = m_compile_units.begin();
194             CompileUnitColl::const_iterator pos = std::upper_bound(begin_pos, end_pos, cu_offset, OffsetLessThanCompileUnitOffset);
195             if (pos != begin_pos)
196             {
197                 --pos;
198                 if ((*pos)->GetOffset() == cu_offset)
199                 {
200                     cu_sp = *pos;
201                     cu_idx = std::distance(begin_pos, pos);
202                 }
203             }
204         }
205     }
206     if (idx_ptr)
207         *idx_ptr = cu_idx;
208     return cu_sp.get();
209 }
210 
211 DWARFCompileUnit *
212 DWARFDebugInfo::GetCompileUnit (const DIERef& die_ref)
213 {
214     if (die_ref.cu_offset == DW_INVALID_OFFSET)
215         return GetCompileUnitContainingDIEOffset(die_ref.die_offset);
216     else
217         return GetCompileUnit(die_ref.cu_offset);
218 }
219 
220 DWARFCompileUnit*
221 DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset)
222 {
223     ParseCompileUnitHeadersIfNeeded();
224 
225     DWARFCompileUnitSP cu_sp;
226 
227     // Watch out for single compile unit executable as they are pretty common
228     const size_t num_cus = m_compile_units.size();
229     if (num_cus == 1)
230     {
231         if (m_compile_units[0]->ContainsDIEOffset(die_offset))
232             return m_compile_units[0].get();
233     }
234     else if (num_cus)
235     {
236         CompileUnitColl::const_iterator end_pos = m_compile_units.end();
237         CompileUnitColl::const_iterator begin_pos = m_compile_units.begin();
238         CompileUnitColl::const_iterator pos = std::upper_bound(begin_pos, end_pos, die_offset, OffsetLessThanCompileUnitOffset);
239         if (pos != begin_pos)
240         {
241             --pos;
242             if ((*pos)->ContainsDIEOffset(die_offset))
243                 return (*pos).get();
244         }
245     }
246 
247     return nullptr;
248 }
249 
250 DWARFDIE
251 DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset)
252 {
253     DWARFCompileUnit* cu = GetCompileUnitContainingDIEOffset(die_offset);
254     if (cu)
255         return cu->GetDIE(die_offset);
256     return DWARFDIE();
257 }
258 
259 //----------------------------------------------------------------------
260 // GetDIE()
261 //
262 // Get the DIE (Debug Information Entry) with the specified offset.
263 //----------------------------------------------------------------------
264 DWARFDIE
265 DWARFDebugInfo::GetDIE(const DIERef& die_ref)
266 {
267     DWARFCompileUnit *cu = GetCompileUnit(die_ref);
268     if (cu)
269         return cu->GetDIE (die_ref.die_offset);
270     return DWARFDIE();    // Not found
271 }
272 
273 //----------------------------------------------------------------------
274 // Parse
275 //
276 // Parses the .debug_info section and uses the .debug_abbrev section
277 // and various other sections in the SymbolFileDWARF class and calls the
278 // supplied callback function each time a compile unit header, or debug
279 // information entry is successfully parsed. This function can be used
280 // for different tasks such as parsing the file contents into a
281 // structured data, dumping, verifying and much more.
282 //----------------------------------------------------------------------
283 void
284 DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* userData)
285 {
286     if (dwarf2Data)
287     {
288         lldb::offset_t offset = 0;
289         uint32_t depth = 0;
290         DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data));
291         if (cu.get() == NULL)
292             return;
293         DWARFDebugInfoEntry die;
294 
295         while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset))
296         {
297             const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset();
298 
299             depth = 0;
300             // Call the callback function with no DIE pointer for the compile unit
301             // and get the offset that we are to continue to parse from
302             offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData);
303 
304             // Make sure we are within our compile unit
305             if (offset < next_cu_offset)
306             {
307                 // We are in our compile unit, parse starting at the offset
308                 // we were told to parse
309                 bool done = false;
310                 while (!done && die.Extract(dwarf2Data, cu.get(), &offset))
311                 {
312                     // Call the callback function with DIE pointer that falls within the compile unit
313                     offset = callback(dwarf2Data, cu.get(), &die, offset, depth, userData);
314 
315                     if (die.IsNULL())
316                     {
317                         if (depth)
318                             --depth;
319                         else
320                             done = true;    // We are done with this compile unit!
321                     }
322                     else if (die.HasChildren())
323                         ++depth;
324                 }
325             }
326 
327             // Make sure the offset returned is valid, and if not stop parsing.
328             // Returning DW_INVALID_OFFSET from this callback is a good way to end
329             // all parsing
330             if (!dwarf2Data->get_debug_info_data().ValidOffset(offset))
331                 break;
332 
333             // See if during the callback anyone retained a copy of the compile
334             // unit other than ourselves and if so, let whomever did own the object
335             // and create a new one for our own use!
336             if (!cu.unique())
337                 cu.reset(new DWARFCompileUnit(dwarf2Data));
338 
339 
340             // Make sure we start on a proper
341             offset = next_cu_offset;
342         }
343     }
344 }
345 
346 typedef struct DumpInfo
347 {
348     DumpInfo(Stream* init_strm, uint32_t off, uint32_t depth) :
349         strm(init_strm),
350         die_offset(off),
351         recurse_depth(depth),
352         found_depth(UINT32_MAX),
353         found_die(false),
354         ancestors()
355     {
356     }
357     Stream* strm;
358     const uint32_t die_offset;
359     const uint32_t recurse_depth;
360     uint32_t found_depth;
361     bool found_die;
362     std::vector<DWARFDebugInfoEntry> ancestors;
363 
364     DISALLOW_COPY_AND_ASSIGN(DumpInfo);
365 } DumpInfo;
366 
367 //----------------------------------------------------------------------
368 // DumpCallback
369 //
370 // A callback function for the static DWARFDebugInfo::Parse() function
371 // that gets called each time a compile unit header or debug information
372 // entry is successfully parsed.
373 //
374 // This function dump DWARF information and obey recurse depth and
375 // whether a single DIE is to be dumped (or all of the data).
376 //----------------------------------------------------------------------
377 static dw_offset_t DumpCallback
378 (
379     SymbolFileDWARF* dwarf2Data,
380     DWARFCompileUnit* cu,
381     DWARFDebugInfoEntry* die,
382     const dw_offset_t next_offset,
383     const uint32_t curr_depth,
384     void* userData
385 )
386 {
387     DumpInfo* dumpInfo = (DumpInfo*)userData;
388     Stream *s = dumpInfo->strm;
389     bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors);
390 
391     if (die)
392     {
393         // Are we dumping everything?
394         if (dumpInfo->die_offset == DW_INVALID_OFFSET)
395         {
396             // Yes we are dumping everything. Obey our recurse level though
397             if (curr_depth < dumpInfo->recurse_depth)
398                 die->Dump(dwarf2Data, cu, *s, 0);
399         }
400         else
401         {
402             // We are dumping a specific DIE entry by offset
403             if (dumpInfo->die_offset == die->GetOffset())
404             {
405                 // We found the DIE we were looking for, dump it!
406                 if (show_parents)
407                 {
408                     s->SetIndentLevel(0);
409                     const uint32_t num_ancestors = dumpInfo->ancestors.size();
410                     if (num_ancestors > 0)
411                     {
412                         for (uint32_t i=0; i<num_ancestors-1; ++i)
413                         {
414                             dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0);
415                             s->IndentMore();
416                         }
417                     }
418                 }
419 
420                 dumpInfo->found_depth = curr_depth;
421 
422                 die->Dump(dwarf2Data, cu, *s, 0);
423 
424                 // Note that we found the DIE we were looking for
425                 dumpInfo->found_die = true;
426 
427                 // Since we are dumping a single DIE, if there are no children we are done!
428                 if (!die->HasChildren() || dumpInfo->recurse_depth == 0)
429                     return DW_INVALID_OFFSET;   // Return an invalid address to end parsing
430             }
431             else if (dumpInfo->found_die)
432             {
433                 // Are we done with all the children?
434                 if (curr_depth <= dumpInfo->found_depth)
435                     return DW_INVALID_OFFSET;
436 
437                 // We have already found our DIE and are printing it's children. Obey
438                 // our recurse depth and return an invalid offset if we get done
439                 // dumping all of the children
440                 if (dumpInfo->recurse_depth == UINT32_MAX || curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
441                     die->Dump(dwarf2Data, cu, *s, 0);
442             }
443             else if (dumpInfo->die_offset > die->GetOffset())
444             {
445                 if (show_parents)
446                     dumpInfo->ancestors.back() = *die;
447             }
448         }
449 
450         // Keep up with our indent level
451         if (die->IsNULL())
452         {
453             if (show_parents)
454                 dumpInfo->ancestors.pop_back();
455 
456             if (curr_depth <= 1)
457                 return cu->GetNextCompileUnitOffset();
458             else
459                 s->IndentLess();
460         }
461         else if (die->HasChildren())
462         {
463             if (show_parents)
464             {
465                 DWARFDebugInfoEntry null_die;
466                 dumpInfo->ancestors.push_back(null_die);
467             }
468             s->IndentMore();
469         }
470     }
471     else
472     {
473         if (cu == NULL)
474             s->PutCString("NULL - cu");
475         // We have a compile unit, reset our indent level to zero just in case
476         s->SetIndentLevel(0);
477 
478         // See if we are dumping everything?
479         if (dumpInfo->die_offset == DW_INVALID_OFFSET)
480         {
481             // We are dumping everything
482             if (cu)
483             {
484                 cu->Dump(s);
485                 return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit
486             }
487             else
488             {
489                 return DW_INVALID_OFFSET;
490             }
491         }
492         else
493         {
494             if (show_parents)
495             {
496                 dumpInfo->ancestors.clear();
497                 dumpInfo->ancestors.resize(1);
498             }
499 
500             // We are dumping only a single DIE possibly with it's children and
501             // we must find it's compile unit before we can dump it properly
502             if (cu && dumpInfo->die_offset < cu->GetFirstDIEOffset())
503             {
504                 // Not found, maybe the DIE offset provided wasn't correct?
505             //  *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl;
506                 return DW_INVALID_OFFSET;
507             }
508             else
509             {
510                 // See if the DIE is in this compile unit?
511                 if (cu && dumpInfo->die_offset < cu->GetNextCompileUnitOffset())
512                 {
513                     // This DIE is in this compile unit!
514                     if (s->GetVerbose())
515                         cu->Dump(s); // Dump the compile unit for the DIE in verbose mode
516 
517                     return next_offset;
518                 //  // We found our compile unit that contains our DIE, just skip to dumping the requested DIE...
519                 //  return dumpInfo->die_offset;
520                 }
521                 else
522                 {
523                     // Skip to the next compile unit as the DIE isn't in the current one!
524                     if (cu)
525                     {
526                         return cu->GetNextCompileUnitOffset();
527                     }
528                     else
529                     {
530                         return DW_INVALID_OFFSET;
531                     }
532                 }
533             }
534         }
535     }
536 
537     // Just return the current offset to parse the next CU or DIE entry
538     return next_offset;
539 }
540 
541 //----------------------------------------------------------------------
542 // Dump
543 //
544 // Dump the information in the .debug_info section to the specified
545 // ostream. If die_offset is valid, a single DIE will be dumped. If the
546 // die_offset is invalid, all the DWARF information will be dumped. Both
547 // cases will obey a "recurse_depth" or how deep to traverse into the
548 // children of each DIE entry. A recurse_depth of zero will dump all
549 // compile unit headers. A recurse_depth of 1 will dump all compile unit
550 // headers and the DW_TAG_compile unit tags. A depth of 2 will also
551 // dump all types and functions.
552 //----------------------------------------------------------------------
553 void
554 DWARFDebugInfo::Dump
555 (
556     Stream *s,
557     SymbolFileDWARF* dwarf2Data,
558     const uint32_t die_offset,
559     const uint32_t recurse_depth
560 )
561 {
562     DumpInfo dumpInfo(s, die_offset, recurse_depth);
563     s->PutCString(".debug_info contents");
564     if (dwarf2Data->get_debug_info_data().GetByteSize() > 0)
565     {
566         if (die_offset == DW_INVALID_OFFSET)
567             s->PutCString(":\n");
568         else
569         {
570             s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset);
571             if (recurse_depth != UINT32_MAX)
572                 s->Printf(" recursing %u levels deep.", recurse_depth);
573             s->EOL();
574         }
575     }
576     else
577     {
578         s->PutCString(": < EMPTY >\n");
579         return;
580     }
581     DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo);
582 }
583 
584 
585 //----------------------------------------------------------------------
586 // Dump
587 //
588 // Dump the contents of this DWARFDebugInfo object as has been parsed
589 // and/or modified after it has been parsed.
590 //----------------------------------------------------------------------
591 void
592 DWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recurse_depth)
593 {
594     DumpInfo dumpInfo(s, die_offset, recurse_depth);
595 
596     s->PutCString("Dumping .debug_info section from internal representation\n");
597 
598     CompileUnitColl::const_iterator pos;
599     uint32_t curr_depth = 0;
600     ParseCompileUnitHeadersIfNeeded();
601     for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos)
602     {
603         DWARFCompileUnit *cu = pos->get();
604         DumpCallback(m_dwarf2Data, cu, NULL, 0, curr_depth, &dumpInfo);
605 
606         const DWARFDIE die = cu->DIE();
607         if (die)
608             die.Dump(s, recurse_depth);
609     }
610 }
611 
612 
613 //----------------------------------------------------------------------
614 // FindCallbackString
615 //
616 // A callback function for the static DWARFDebugInfo::Parse() function
617 // that gets called each time a compile unit header or debug information
618 // entry is successfully parsed.
619 //
620 // This function will find the die_offset of any items whose DW_AT_name
621 // matches the given string
622 //----------------------------------------------------------------------
623 typedef struct FindCallbackStringInfoTag
624 {
625     const char* name;
626     bool ignore_case;
627     RegularExpression* regex;
628     vector<dw_offset_t>& die_offsets;
629 } FindCallbackStringInfo;
630 
631 static dw_offset_t FindCallbackString
632 (
633     SymbolFileDWARF* dwarf2Data,
634     DWARFCompileUnit* cu,
635     DWARFDebugInfoEntry* die,
636     const dw_offset_t next_offset,
637     const uint32_t curr_depth,
638     void* userData
639 )
640 {
641     FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData;
642 
643     if (die)
644     {
645         const char* die_name = die->GetName(dwarf2Data, cu);
646         if (die_name)
647         {
648             if (info->regex)
649             {
650                 if (info->regex->Execute(die_name))
651                     info->die_offsets.push_back(die->GetOffset());
652             }
653             else
654             {
655                 if ((info->ignore_case ? strcasecmp(die_name, info->name) : strcmp(die_name, info->name)) == 0)
656                     info->die_offsets.push_back(die->GetOffset());
657             }
658         }
659     }
660 
661     // Just return the current offset to parse the next CU or DIE entry
662     return next_offset;
663 }
664 
665 //----------------------------------------------------------------------
666 // Find
667 //
668 // Finds all DIE that have a specific DW_AT_name attribute by manually
669 // searching through the debug information (not using the
670 // .debug_pubnames section). The string must match the entire name
671 // and case sensitive searches are an option.
672 //----------------------------------------------------------------------
673 bool
674 DWARFDebugInfo::Find(const char* name, bool ignore_case, vector<dw_offset_t>& die_offsets) const
675 {
676     die_offsets.clear();
677     if (name && name[0])
678     {
679         FindCallbackStringInfo info = { name, ignore_case, NULL, die_offsets };
680         DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
681     }
682     return !die_offsets.empty();
683 }
684 
685 //----------------------------------------------------------------------
686 // Find
687 //
688 // Finds all DIE that have a specific DW_AT_name attribute by manually
689 // searching through the debug information (not using the
690 // .debug_pubnames section). The string must match the supplied regular
691 // expression.
692 //----------------------------------------------------------------------
693 bool
694 DWARFDebugInfo::Find(RegularExpression& re, vector<dw_offset_t>& die_offsets) const
695 {
696     die_offsets.clear();
697     FindCallbackStringInfo info = { NULL, false, &re, die_offsets };
698     DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
699     return !die_offsets.empty();
700 }
701