DWARFDebugInfo.cpp revision 309124
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
27using namespace lldb;
28using namespace lldb_private;
29using namespace std;
30
31//----------------------------------------------------------------------
32// Constructor
33//----------------------------------------------------------------------
34DWARFDebugInfo::DWARFDebugInfo() :
35    m_dwarf2Data(NULL),
36    m_compile_units(),
37    m_cu_aranges_ap ()
38{
39}
40
41//----------------------------------------------------------------------
42// SetDwarfData
43//----------------------------------------------------------------------
44void
45DWARFDebugInfo::SetDwarfData(SymbolFileDWARF* dwarf2Data)
46{
47    m_dwarf2Data = dwarf2Data;
48    m_compile_units.clear();
49}
50
51
52DWARFDebugAranges &
53DWARFDebugInfo::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
106void
107DWARFDebugInfo::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
133size_t
134DWARFDebugInfo::GetNumCompileUnits()
135{
136    ParseCompileUnitHeadersIfNeeded();
137    return m_compile_units.size();
138}
139
140DWARFCompileUnit*
141DWARFDebugInfo::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
149bool
150DWARFDebugInfo::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
165bool
166DWARFDebugInfo::OffsetLessThanCompileUnitOffset (dw_offset_t offset, const DWARFCompileUnitSP& cu_sp)
167{
168    return offset < cu_sp->GetOffset();
169}
170
171DWARFCompileUnit *
172DWARFDebugInfo::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
211DWARFCompileUnit *
212DWARFDebugInfo::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
220DWARFCompileUnit*
221DWARFDebugInfo::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
250DWARFDIE
251DWARFDebugInfo::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//----------------------------------------------------------------------
264DWARFDIE
265DWARFDebugInfo::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//----------------------------------------------------------------------
283void
284DWARFDebugInfo::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
346typedef 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//----------------------------------------------------------------------
377static 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//----------------------------------------------------------------------
553void
554DWARFDebugInfo::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//----------------------------------------------------------------------
591void
592DWARFDebugInfo::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//----------------------------------------------------------------------
623typedef struct FindCallbackStringInfoTag
624{
625    const char* name;
626    bool ignore_case;
627    RegularExpression* regex;
628    vector<dw_offset_t>& die_offsets;
629} FindCallbackStringInfo;
630
631static 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//----------------------------------------------------------------------
673bool
674DWARFDebugInfo::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//----------------------------------------------------------------------
693bool
694DWARFDebugInfo::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