1254721Semaste//===-- DWARFDebugInfo.cpp --------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "SymbolFileDWARF.h"
11254721Semaste
12254721Semaste#include <algorithm>
13254721Semaste#include <set>
14254721Semaste
15254721Semaste#include "lldb/Core/RegularExpression.h"
16254721Semaste#include "lldb/Core/Stream.h"
17254721Semaste#include "lldb/Symbol/ObjectFile.h"
18254721Semaste
19254721Semaste#include "DWARFDebugAranges.h"
20254721Semaste#include "DWARFDebugInfo.h"
21254721Semaste#include "DWARFCompileUnit.h"
22254721Semaste#include "DWARFDebugAranges.h"
23254721Semaste#include "DWARFDebugInfoEntry.h"
24254721Semaste#include "DWARFFormValue.h"
25254721Semaste#include "LogChannelDWARF.h"
26254721Semaste
27254721Semasteusing namespace lldb;
28254721Semasteusing namespace lldb_private;
29254721Semasteusing namespace std;
30254721Semaste
31254721Semaste//----------------------------------------------------------------------
32254721Semaste// Constructor
33254721Semaste//----------------------------------------------------------------------
34254721SemasteDWARFDebugInfo::DWARFDebugInfo() :
35254721Semaste    m_dwarf2Data(NULL),
36254721Semaste    m_compile_units(),
37254721Semaste    m_cu_aranges_ap ()
38254721Semaste{
39254721Semaste}
40254721Semaste
41254721Semaste//----------------------------------------------------------------------
42254721Semaste// SetDwarfData
43254721Semaste//----------------------------------------------------------------------
44254721Semastevoid
45254721SemasteDWARFDebugInfo::SetDwarfData(SymbolFileDWARF* dwarf2Data)
46254721Semaste{
47254721Semaste    m_dwarf2Data = dwarf2Data;
48254721Semaste    m_compile_units.clear();
49254721Semaste}
50254721Semaste
51254721Semaste
52254721SemasteDWARFDebugAranges &
53254721SemasteDWARFDebugInfo::GetCompileUnitAranges ()
54254721Semaste{
55254721Semaste    if (m_cu_aranges_ap.get() == NULL && m_dwarf2Data)
56254721Semaste    {
57254721Semaste        Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
58254721Semaste
59254721Semaste        m_cu_aranges_ap.reset (new DWARFDebugAranges());
60263363Semaste        const DWARFDataExtractor &debug_aranges_data = m_dwarf2Data->get_debug_aranges_data();
61254721Semaste        if (debug_aranges_data.GetByteSize() > 0)
62254721Semaste        {
63254721Semaste            if (log)
64254721Semaste                log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from .debug_aranges",
65254721Semaste                             m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
66254721Semaste            m_cu_aranges_ap->Extract (debug_aranges_data);
67254721Semaste
68254721Semaste        }
69263363Semaste
70263363Semaste        // Make a list of all CUs represented by the arange data in the file.
71263363Semaste        std::set<dw_offset_t> cus_with_data;
72263363Semaste        for (size_t n=0;n<m_cu_aranges_ap.get()->GetNumRanges();n++)
73254721Semaste        {
74263363Semaste            dw_offset_t offset = m_cu_aranges_ap.get()->OffsetAtIndex(n);
75263363Semaste            if (offset != DW_INVALID_OFFSET)
76263363Semaste                cus_with_data.insert (offset);
77263363Semaste        }
78263363Semaste
79263363Semaste        // Manually build arange data for everything that wasn't in the .debug_aranges table.
80263363Semaste        bool printed = false;
81263363Semaste        const size_t num_compile_units = GetNumCompileUnits();
82263363Semaste        const bool clear_dies_if_already_not_parsed = true;
83263363Semaste        for (size_t idx = 0; idx < num_compile_units; ++idx)
84263363Semaste        {
85263363Semaste            DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx);
86263363Semaste
87263363Semaste            dw_offset_t offset = cu->GetOffset();
88263363Semaste            if (cus_with_data.find(offset) == cus_with_data.end())
89254721Semaste            {
90263363Semaste                if (log)
91263363Semaste                {
92263363Semaste                    if (!printed)
93263363Semaste                        log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing",
94263363Semaste                                     m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
95263363Semaste                    printed = true;
96263363Semaste                }
97263363Semaste                cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get(), clear_dies_if_already_not_parsed);
98254721Semaste            }
99254721Semaste        }
100254721Semaste
101254721Semaste        const bool minimize = true;
102254721Semaste        m_cu_aranges_ap->Sort (minimize);
103254721Semaste    }
104254721Semaste    return *m_cu_aranges_ap.get();
105254721Semaste}
106254721Semaste
107254721Semaste
108254721Semaste//----------------------------------------------------------------------
109254721Semaste// LookupAddress
110254721Semaste//----------------------------------------------------------------------
111254721Semastebool
112254721SemasteDWARFDebugInfo::LookupAddress
113254721Semaste(
114254721Semaste    const dw_addr_t address,
115254721Semaste    const dw_offset_t hint_die_offset,
116254721Semaste    DWARFCompileUnitSP& cu_sp,
117254721Semaste    DWARFDebugInfoEntry** function_die,
118254721Semaste    DWARFDebugInfoEntry** block_die
119254721Semaste)
120254721Semaste{
121254721Semaste
122254721Semaste    if (hint_die_offset != DW_INVALID_OFFSET)
123254721Semaste        cu_sp = GetCompileUnit(hint_die_offset);
124254721Semaste    else
125254721Semaste    {
126254721Semaste        DWARFDebugAranges &cu_aranges = GetCompileUnitAranges ();
127254721Semaste        const dw_offset_t cu_offset = cu_aranges.FindAddress (address);
128254721Semaste        cu_sp = GetCompileUnit(cu_offset);
129254721Semaste    }
130254721Semaste
131254721Semaste    if (cu_sp.get())
132254721Semaste    {
133254721Semaste        if (cu_sp->LookupAddress(address, function_die, block_die))
134254721Semaste            return true;
135254721Semaste        cu_sp.reset();
136254721Semaste    }
137254721Semaste    else
138254721Semaste    {
139254721Semaste        // The hint_die_offset may have been a pointer to the actual item that
140254721Semaste        // we are looking for
141254721Semaste        DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp);
142254721Semaste        if (die_ptr)
143254721Semaste        {
144254721Semaste            if (cu_sp.get())
145254721Semaste            {
146254721Semaste                if (function_die || block_die)
147254721Semaste                    return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die);
148254721Semaste
149254721Semaste                // We only wanted the compile unit that contained this address
150254721Semaste                return true;
151254721Semaste            }
152254721Semaste        }
153254721Semaste    }
154254721Semaste    return false;
155254721Semaste}
156254721Semaste
157254721Semaste
158254721Semastevoid
159254721SemasteDWARFDebugInfo::ParseCompileUnitHeadersIfNeeded()
160254721Semaste{
161254721Semaste    if (m_compile_units.empty())
162254721Semaste    {
163254721Semaste        if (m_dwarf2Data != NULL)
164254721Semaste        {
165254721Semaste            lldb::offset_t offset = 0;
166263363Semaste            const DWARFDataExtractor &debug_info_data = m_dwarf2Data->get_debug_info_data();
167254721Semaste            while (debug_info_data.ValidOffset(offset))
168254721Semaste            {
169254721Semaste                DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data));
170254721Semaste                // Out of memory?
171254721Semaste                if (cu_sp.get() == NULL)
172254721Semaste                    break;
173254721Semaste
174254721Semaste                if (cu_sp->Extract(debug_info_data, &offset) == false)
175254721Semaste                    break;
176254721Semaste
177254721Semaste                m_compile_units.push_back(cu_sp);
178254721Semaste
179254721Semaste                offset = cu_sp->GetNextCompileUnitOffset();
180254721Semaste            }
181254721Semaste        }
182254721Semaste    }
183254721Semaste}
184254721Semaste
185254721Semastesize_t
186254721SemasteDWARFDebugInfo::GetNumCompileUnits()
187254721Semaste{
188254721Semaste    ParseCompileUnitHeadersIfNeeded();
189254721Semaste    return m_compile_units.size();
190254721Semaste}
191254721Semaste
192254721SemasteDWARFCompileUnit*
193254721SemasteDWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx)
194254721Semaste{
195254721Semaste    DWARFCompileUnit* cu = NULL;
196254721Semaste    if (idx < GetNumCompileUnits())
197254721Semaste        cu = m_compile_units[idx].get();
198254721Semaste    return cu;
199254721Semaste}
200254721Semaste
201254721Semastebool
202254721SemasteDWARFDebugInfo::ContainsCompileUnit (const DWARFCompileUnit *cu) const
203254721Semaste{
204254721Semaste    // Not a verify efficient function, but it is handy for use in assertions
205254721Semaste    // to make sure that a compile unit comes from a debug information file.
206254721Semaste    CompileUnitColl::const_iterator end_pos = m_compile_units.end();
207254721Semaste    CompileUnitColl::const_iterator pos;
208254721Semaste
209254721Semaste    for (pos = m_compile_units.begin(); pos != end_pos; ++pos)
210254721Semaste    {
211254721Semaste        if (pos->get() == cu)
212254721Semaste            return true;
213254721Semaste    }
214254721Semaste    return false;
215254721Semaste}
216254721Semaste
217254721Semaste
218254721Semastestatic bool CompileUnitOffsetLessThan (const DWARFCompileUnitSP& a, const DWARFCompileUnitSP& b)
219254721Semaste{
220254721Semaste    return a->GetOffset() < b->GetOffset();
221254721Semaste}
222254721Semaste
223254721Semaste
224254721Semastestatic int
225254721SemasteCompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem)
226254721Semaste{
227254721Semaste    const dw_offset_t key_cu_offset = *(dw_offset_t*) key;
228254721Semaste    const dw_offset_t cu_offset = ((DWARFCompileUnitSP *)arrmem)->get()->GetOffset();
229254721Semaste    if (key_cu_offset < cu_offset)
230254721Semaste        return -1;
231254721Semaste    if (key_cu_offset > cu_offset)
232254721Semaste        return 1;
233254721Semaste    return 0;
234254721Semaste}
235254721Semaste
236254721SemasteDWARFCompileUnitSP
237254721SemasteDWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr)
238254721Semaste{
239254721Semaste    DWARFCompileUnitSP cu_sp;
240254721Semaste    uint32_t cu_idx = DW_INVALID_INDEX;
241254721Semaste    if (cu_offset != DW_INVALID_OFFSET)
242254721Semaste    {
243254721Semaste        ParseCompileUnitHeadersIfNeeded();
244254721Semaste
245254721Semaste        DWARFCompileUnitSP* match = (DWARFCompileUnitSP*)bsearch(&cu_offset, &m_compile_units[0], m_compile_units.size(), sizeof(DWARFCompileUnitSP), CompareDWARFCompileUnitSPOffset);
246254721Semaste        if (match)
247254721Semaste        {
248254721Semaste            cu_sp = *match;
249254721Semaste            cu_idx = match - &m_compile_units[0];
250254721Semaste        }
251254721Semaste    }
252254721Semaste    if (idx_ptr)
253254721Semaste        *idx_ptr = cu_idx;
254254721Semaste    return cu_sp;
255254721Semaste}
256254721Semaste
257254721SemasteDWARFCompileUnitSP
258254721SemasteDWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset)
259254721Semaste{
260254721Semaste    DWARFCompileUnitSP cu_sp;
261254721Semaste    if (die_offset != DW_INVALID_OFFSET)
262254721Semaste    {
263254721Semaste        ParseCompileUnitHeadersIfNeeded();
264254721Semaste
265254721Semaste        CompileUnitColl::const_iterator end_pos = m_compile_units.end();
266254721Semaste        CompileUnitColl::const_iterator pos;
267254721Semaste
268254721Semaste        for (pos = m_compile_units.begin(); pos != end_pos; ++pos)
269254721Semaste        {
270254721Semaste            dw_offset_t cu_start_offset = (*pos)->GetOffset();
271254721Semaste            dw_offset_t cu_end_offset = (*pos)->GetNextCompileUnitOffset();
272254721Semaste            if (cu_start_offset <= die_offset && die_offset < cu_end_offset)
273254721Semaste            {
274254721Semaste                cu_sp = *pos;
275254721Semaste                break;
276254721Semaste            }
277254721Semaste        }
278254721Semaste    }
279254721Semaste    return cu_sp;
280254721Semaste}
281254721Semaste
282254721Semaste//----------------------------------------------------------------------
283254721Semaste// Compare function DWARFDebugAranges::Range structures
284254721Semaste//----------------------------------------------------------------------
285254721Semastestatic bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2)
286254721Semaste{
287254721Semaste    return die1.GetOffset() < die2.GetOffset();
288254721Semaste}
289254721Semaste
290254721Semaste
291254721Semaste//----------------------------------------------------------------------
292254721Semaste// GetDIE()
293254721Semaste//
294254721Semaste// Get the DIE (Debug Information Entry) with the specified offset.
295254721Semaste//----------------------------------------------------------------------
296254721SemasteDWARFDebugInfoEntry*
297254721SemasteDWARFDebugInfo::GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
298254721Semaste{
299254721Semaste    DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
300254721Semaste    if (cu_sp_ptr)
301254721Semaste        *cu_sp_ptr = cu_sp;
302254721Semaste    if (cu_sp.get())
303254721Semaste        return cu_sp->GetDIEPtr(die_offset);
304254721Semaste    return NULL;    // Not found in any compile units
305254721Semaste}
306254721Semaste
307254721SemasteDWARFDebugInfoEntry*
308254721SemasteDWARFDebugInfo::GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle)
309254721Semaste{
310254721Semaste    assert (cu_handle);
311254721Semaste    DWARFDebugInfoEntry* die = NULL;
312254721Semaste    if (*cu_handle)
313254721Semaste        die = (*cu_handle)->GetDIEPtr(die_offset);
314254721Semaste
315254721Semaste    if (die == NULL)
316254721Semaste    {
317254721Semaste        DWARFCompileUnitSP cu_sp (GetCompileUnitContainingDIE(die_offset));
318254721Semaste        if (cu_sp.get())
319254721Semaste        {
320254721Semaste            *cu_handle = cu_sp.get();
321254721Semaste            die = cu_sp->GetDIEPtr(die_offset);
322254721Semaste        }
323254721Semaste    }
324254721Semaste    if (die == NULL)
325254721Semaste        *cu_handle = NULL;
326254721Semaste    return die;
327254721Semaste}
328254721Semaste
329254721Semaste
330254721Semasteconst DWARFDebugInfoEntry*
331254721SemasteDWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
332254721Semaste{
333254721Semaste    DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
334254721Semaste    if (cu_sp_ptr)
335254721Semaste        *cu_sp_ptr = cu_sp;
336254721Semaste    if (cu_sp.get())
337254721Semaste        return cu_sp->GetDIEPtrContainingOffset(die_offset);
338254721Semaste
339254721Semaste    return NULL;    // Not found in any compile units
340254721Semaste
341254721Semaste}
342254721Semaste
343254721Semaste//----------------------------------------------------------------------
344254721Semaste// DWARFDebugInfo_ParseCallback
345254721Semaste//
346254721Semaste// A callback function for the static DWARFDebugInfo::Parse() function
347254721Semaste// that gets parses all compile units and DIE's into an internate
348254721Semaste// representation for further modification.
349254721Semaste//----------------------------------------------------------------------
350254721Semaste
351254721Semastestatic dw_offset_t
352254721SemasteDWARFDebugInfo_ParseCallback
353254721Semaste(
354254721Semaste    SymbolFileDWARF* dwarf2Data,
355254721Semaste    DWARFCompileUnitSP& cu_sp,
356254721Semaste    DWARFDebugInfoEntry* die,
357254721Semaste    const dw_offset_t next_offset,
358254721Semaste    const uint32_t curr_depth,
359254721Semaste    void* userData
360254721Semaste)
361254721Semaste{
362254721Semaste    DWARFDebugInfo* debug_info = (DWARFDebugInfo*)userData;
363254721Semaste    DWARFCompileUnit* cu = cu_sp.get();
364254721Semaste    if (die)
365254721Semaste    {
366254721Semaste        cu->AddDIE(*die);
367254721Semaste    }
368254721Semaste    else if (cu)
369254721Semaste    {
370254721Semaste        debug_info->AddCompileUnit(cu_sp);
371254721Semaste    }
372254721Semaste
373254721Semaste    // Just return the current offset to parse the next CU or DIE entry
374254721Semaste    return next_offset;
375254721Semaste}
376254721Semaste
377254721Semaste//----------------------------------------------------------------------
378254721Semaste// AddCompileUnit
379254721Semaste//----------------------------------------------------------------------
380254721Semastevoid
381254721SemasteDWARFDebugInfo::AddCompileUnit(DWARFCompileUnitSP& cu)
382254721Semaste{
383254721Semaste    m_compile_units.push_back(cu);
384254721Semaste}
385254721Semaste
386254721Semaste/*
387254721Semastevoid
388254721SemasteDWARFDebugInfo::AddDIE(DWARFDebugInfoEntry& die)
389254721Semaste{
390254721Semaste    m_die_array.push_back(die);
391254721Semaste}
392254721Semaste*/
393254721Semaste
394254721Semaste
395254721Semaste
396254721Semaste
397254721Semaste//----------------------------------------------------------------------
398254721Semaste// Parse
399254721Semaste//
400254721Semaste// Parses the .debug_info section and uses the .debug_abbrev section
401254721Semaste// and various other sections in the SymbolFileDWARF class and calls the
402254721Semaste// supplied callback function each time a compile unit header, or debug
403254721Semaste// information entry is successfully parsed. This function can be used
404254721Semaste// for different tasks such as parsing the file contents into a
405254721Semaste// structured data, dumping, verifying and much more.
406254721Semaste//----------------------------------------------------------------------
407254721Semastevoid
408254721SemasteDWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* userData)
409254721Semaste{
410254721Semaste    if (dwarf2Data)
411254721Semaste    {
412254721Semaste        lldb::offset_t offset = 0;
413254721Semaste        uint32_t depth = 0;
414254721Semaste        DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data));
415254721Semaste        if (cu.get() == NULL)
416254721Semaste            return;
417254721Semaste        DWARFDebugInfoEntry die;
418254721Semaste
419254721Semaste        while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset))
420254721Semaste        {
421254721Semaste            const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset();
422254721Semaste
423254721Semaste            depth = 0;
424254721Semaste            // Call the callback function with no DIE pointer for the compile unit
425254721Semaste            // and get the offset that we are to continue to parse from
426254721Semaste            offset = callback(dwarf2Data, cu, NULL, offset, depth, userData);
427254721Semaste
428254721Semaste            // Make sure we are within our compile unit
429254721Semaste            if (offset < next_cu_offset)
430254721Semaste            {
431254721Semaste                // We are in our compile unit, parse starting at the offset
432254721Semaste                // we were told to parse
433254721Semaste                bool done = false;
434254721Semaste                while (!done && die.Extract(dwarf2Data, cu.get(), &offset))
435254721Semaste                {
436254721Semaste                    // Call the callback function with DIE pointer that falls within the compile unit
437254721Semaste                    offset = callback(dwarf2Data, cu, &die, offset, depth, userData);
438254721Semaste
439254721Semaste                    if (die.IsNULL())
440254721Semaste                    {
441254721Semaste                        if (depth)
442254721Semaste                            --depth;
443254721Semaste                        else
444254721Semaste                            done = true;    // We are done with this compile unit!
445254721Semaste                    }
446254721Semaste                    else if (die.HasChildren())
447254721Semaste                        ++depth;
448254721Semaste                }
449254721Semaste            }
450254721Semaste
451254721Semaste            // Make sure the offset returned is valid, and if not stop parsing.
452254721Semaste            // Returning DW_INVALID_OFFSET from this callback is a good way to end
453254721Semaste            // all parsing
454254721Semaste            if (!dwarf2Data->get_debug_info_data().ValidOffset(offset))
455254721Semaste                break;
456254721Semaste
457254721Semaste            // See if during the callback anyone retained a copy of the compile
458254721Semaste            // unit other than ourselves and if so, let whomever did own the object
459254721Semaste            // and create a new one for our own use!
460254721Semaste            if (!cu.unique())
461254721Semaste                cu.reset(new DWARFCompileUnit(dwarf2Data));
462254721Semaste
463254721Semaste
464254721Semaste            // Make sure we start on a proper
465254721Semaste            offset = next_cu_offset;
466254721Semaste        }
467254721Semaste    }
468254721Semaste}
469254721Semaste
470254721Semastetypedef struct DumpInfo
471254721Semaste{
472254721Semaste    DumpInfo(Stream* init_strm, uint32_t off, uint32_t depth) :
473254721Semaste        strm(init_strm),
474254721Semaste        die_offset(off),
475254721Semaste        recurse_depth(depth),
476254721Semaste        found_depth(UINT32_MAX),
477254721Semaste        found_die(false),
478254721Semaste        ancestors()
479254721Semaste    {
480254721Semaste    }
481254721Semaste    Stream* strm;
482254721Semaste    const uint32_t die_offset;
483254721Semaste    const uint32_t recurse_depth;
484254721Semaste    uint32_t found_depth;
485254721Semaste    bool found_die;
486254721Semaste    std::vector<DWARFDebugInfoEntry> ancestors;
487254721Semaste
488254721Semaste    DISALLOW_COPY_AND_ASSIGN(DumpInfo);
489254721Semaste} DumpInfo;
490254721Semaste
491254721Semaste//----------------------------------------------------------------------
492254721Semaste// DumpCallback
493254721Semaste//
494254721Semaste// A callback function for the static DWARFDebugInfo::Parse() function
495254721Semaste// that gets called each time a compile unit header or debug information
496254721Semaste// entry is successfully parsed.
497254721Semaste//
498254721Semaste// This function dump DWARF information and obey recurse depth and
499254721Semaste// whether a single DIE is to be dumped (or all of the data).
500254721Semaste//----------------------------------------------------------------------
501254721Semastestatic dw_offset_t DumpCallback
502254721Semaste(
503254721Semaste    SymbolFileDWARF* dwarf2Data,
504254721Semaste    DWARFCompileUnitSP& cu_sp,
505254721Semaste    DWARFDebugInfoEntry* die,
506254721Semaste    const dw_offset_t next_offset,
507254721Semaste    const uint32_t curr_depth,
508254721Semaste    void* userData
509254721Semaste)
510254721Semaste{
511254721Semaste    DumpInfo* dumpInfo = (DumpInfo*)userData;
512254721Semaste
513254721Semaste    const DWARFCompileUnit* cu = cu_sp.get();
514254721Semaste
515254721Semaste    Stream *s = dumpInfo->strm;
516254721Semaste    bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors);
517254721Semaste
518254721Semaste    if (die)
519254721Semaste    {
520254721Semaste        // Are we dumping everything?
521254721Semaste        if (dumpInfo->die_offset == DW_INVALID_OFFSET)
522254721Semaste        {
523254721Semaste            // Yes we are dumping everything. Obey our recurse level though
524254721Semaste            if (curr_depth < dumpInfo->recurse_depth)
525254721Semaste                die->Dump(dwarf2Data, cu, *s, 0);
526254721Semaste        }
527254721Semaste        else
528254721Semaste        {
529254721Semaste            // We are dumping a specific DIE entry by offset
530254721Semaste            if (dumpInfo->die_offset == die->GetOffset())
531254721Semaste            {
532254721Semaste                // We found the DIE we were looking for, dump it!
533254721Semaste                if (show_parents)
534254721Semaste                {
535254721Semaste                    s->SetIndentLevel(0);
536254721Semaste                    const uint32_t num_ancestors = dumpInfo->ancestors.size();
537254721Semaste                    if (num_ancestors > 0)
538254721Semaste                    {
539254721Semaste                        for (uint32_t i=0; i<num_ancestors-1; ++i)
540254721Semaste                        {
541254721Semaste                            dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0);
542254721Semaste                            s->IndentMore();
543254721Semaste                        }
544254721Semaste                    }
545254721Semaste                }
546254721Semaste
547254721Semaste                dumpInfo->found_depth = curr_depth;
548254721Semaste
549254721Semaste                die->Dump(dwarf2Data, cu, *s, 0);
550254721Semaste
551254721Semaste                // Note that we found the DIE we were looking for
552254721Semaste                dumpInfo->found_die = true;
553254721Semaste
554254721Semaste                // Since we are dumping a single DIE, if there are no children we are done!
555254721Semaste                if (!die->HasChildren() || dumpInfo->recurse_depth == 0)
556254721Semaste                    return DW_INVALID_OFFSET;   // Return an invalid address to end parsing
557254721Semaste            }
558254721Semaste            else if (dumpInfo->found_die)
559254721Semaste            {
560254721Semaste                // Are we done with all the children?
561254721Semaste                if (curr_depth <= dumpInfo->found_depth)
562254721Semaste                    return DW_INVALID_OFFSET;
563254721Semaste
564254721Semaste                // We have already found our DIE and are printing it's children. Obey
565254721Semaste                // our recurse depth and return an invalid offset if we get done
566254721Semaste                // dumping all the the children
567254721Semaste                if (dumpInfo->recurse_depth == UINT32_MAX || curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
568254721Semaste                    die->Dump(dwarf2Data, cu, *s, 0);
569254721Semaste            }
570254721Semaste            else if (dumpInfo->die_offset > die->GetOffset())
571254721Semaste            {
572254721Semaste                if (show_parents)
573254721Semaste                    dumpInfo->ancestors.back() = *die;
574254721Semaste            }
575254721Semaste        }
576254721Semaste
577254721Semaste        // Keep up with our indent level
578254721Semaste        if (die->IsNULL())
579254721Semaste        {
580254721Semaste            if (show_parents)
581254721Semaste                dumpInfo->ancestors.pop_back();
582254721Semaste
583254721Semaste            if (curr_depth <= 1)
584254721Semaste                return cu->GetNextCompileUnitOffset();
585254721Semaste            else
586254721Semaste                s->IndentLess();
587254721Semaste        }
588254721Semaste        else if (die->HasChildren())
589254721Semaste        {
590254721Semaste            if (show_parents)
591254721Semaste            {
592254721Semaste                DWARFDebugInfoEntry null_die;
593254721Semaste                dumpInfo->ancestors.push_back(null_die);
594254721Semaste            }
595254721Semaste            s->IndentMore();
596254721Semaste        }
597254721Semaste    }
598254721Semaste    else
599254721Semaste    {
600254721Semaste        if (cu == NULL)
601254721Semaste            s->PutCString("NULL - cu");
602254721Semaste        // We have a compile unit, reset our indent level to zero just in case
603254721Semaste        s->SetIndentLevel(0);
604254721Semaste
605254721Semaste        // See if we are dumping everything?
606254721Semaste        if (dumpInfo->die_offset == DW_INVALID_OFFSET)
607254721Semaste        {
608254721Semaste            // We are dumping everything
609254721Semaste            cu->Dump(s);
610254721Semaste            return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit
611254721Semaste        }
612254721Semaste        else
613254721Semaste        {
614254721Semaste            if (show_parents)
615254721Semaste            {
616254721Semaste                dumpInfo->ancestors.clear();
617254721Semaste                dumpInfo->ancestors.resize(1);
618254721Semaste            }
619254721Semaste
620254721Semaste            // We are dumping only a single DIE possibly with it's children and
621254721Semaste            // we must find it's compile unit before we can dump it properly
622254721Semaste            if (dumpInfo->die_offset < cu->GetFirstDIEOffset())
623254721Semaste            {
624254721Semaste                // Not found, maybe the DIE offset provided wasn't correct?
625254721Semaste            //  *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl;
626254721Semaste                return DW_INVALID_OFFSET;
627254721Semaste            }
628254721Semaste            else
629254721Semaste            {
630254721Semaste                // See if the DIE is in this compile unit?
631254721Semaste                if (dumpInfo->die_offset < cu->GetNextCompileUnitOffset())
632254721Semaste                {
633254721Semaste                    // This DIE is in this compile unit!
634254721Semaste                    if (s->GetVerbose())
635254721Semaste                        cu->Dump(s); // Dump the compile unit for the DIE in verbose mode
636254721Semaste
637254721Semaste                    return next_offset;
638254721Semaste                //  // We found our compile unit that contains our DIE, just skip to dumping the requested DIE...
639254721Semaste                //  return dumpInfo->die_offset;
640254721Semaste                }
641254721Semaste                else
642254721Semaste                {
643254721Semaste                    // Skip to the next compile unit as the DIE isn't in the current one!
644254721Semaste                    return cu->GetNextCompileUnitOffset();
645254721Semaste                }
646254721Semaste            }
647254721Semaste        }
648254721Semaste    }
649254721Semaste
650254721Semaste    // Just return the current offset to parse the next CU or DIE entry
651254721Semaste    return next_offset;
652254721Semaste}
653254721Semaste
654254721Semaste//----------------------------------------------------------------------
655254721Semaste// Dump
656254721Semaste//
657254721Semaste// Dump the information in the .debug_info section to the specified
658254721Semaste// ostream. If die_offset is valid, a single DIE will be dumped. If the
659254721Semaste// die_offset is invalid, all the DWARF information will be dumped. Both
660254721Semaste// cases will obey a "recurse_depth" or how deep to traverse into the
661254721Semaste// children of each DIE entry. A recurse_depth of zero will dump all
662254721Semaste// compile unit headers. A recurse_depth of 1 will dump all compile unit
663254721Semaste// headers and the DW_TAG_compile unit tags. A depth of 2 will also
664254721Semaste// dump all types and functions.
665254721Semaste//----------------------------------------------------------------------
666254721Semastevoid
667254721SemasteDWARFDebugInfo::Dump
668254721Semaste(
669254721Semaste    Stream *s,
670254721Semaste    SymbolFileDWARF* dwarf2Data,
671254721Semaste    const uint32_t die_offset,
672254721Semaste    const uint32_t recurse_depth
673254721Semaste)
674254721Semaste{
675254721Semaste    DumpInfo dumpInfo(s, die_offset, recurse_depth);
676254721Semaste    s->PutCString(".debug_info contents");
677254721Semaste    if (dwarf2Data->get_debug_info_data().GetByteSize() > 0)
678254721Semaste    {
679254721Semaste        if (die_offset == DW_INVALID_OFFSET)
680254721Semaste            s->PutCString(":\n");
681254721Semaste        else
682254721Semaste        {
683254721Semaste            s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset);
684254721Semaste            if (recurse_depth != UINT32_MAX)
685254721Semaste                s->Printf(" recursing %u levels deep.", recurse_depth);
686254721Semaste            s->EOL();
687254721Semaste        }
688254721Semaste    }
689254721Semaste    else
690254721Semaste    {
691254721Semaste        s->PutCString(": < EMPTY >\n");
692254721Semaste        return;
693254721Semaste    }
694254721Semaste    DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo);
695254721Semaste}
696254721Semaste
697254721Semaste
698254721Semaste//----------------------------------------------------------------------
699254721Semaste// Dump
700254721Semaste//
701254721Semaste// Dump the contents of this DWARFDebugInfo object as has been parsed
702254721Semaste// and/or modified after it has been parsed.
703254721Semaste//----------------------------------------------------------------------
704254721Semastevoid
705254721SemasteDWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recurse_depth)
706254721Semaste{
707254721Semaste    DumpInfo dumpInfo(s, die_offset, recurse_depth);
708254721Semaste
709254721Semaste    s->PutCString("Dumping .debug_info section from internal representation\n");
710254721Semaste
711254721Semaste    CompileUnitColl::const_iterator pos;
712254721Semaste    uint32_t curr_depth = 0;
713254721Semaste    ParseCompileUnitHeadersIfNeeded();
714254721Semaste    for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos)
715254721Semaste    {
716254721Semaste        const DWARFCompileUnitSP& cu_sp = *pos;
717254721Semaste        DumpCallback(m_dwarf2Data, (DWARFCompileUnitSP&)cu_sp, NULL, 0, curr_depth, &dumpInfo);
718254721Semaste
719254721Semaste        const DWARFDebugInfoEntry* die = cu_sp->DIE();
720254721Semaste        if (die)
721254721Semaste            die->Dump(m_dwarf2Data, cu_sp.get(), *s, recurse_depth);
722254721Semaste    }
723254721Semaste}
724254721Semaste
725254721Semaste
726254721Semaste//----------------------------------------------------------------------
727254721Semaste// FindCallbackString
728254721Semaste//
729254721Semaste// A callback function for the static DWARFDebugInfo::Parse() function
730254721Semaste// that gets called each time a compile unit header or debug information
731254721Semaste// entry is successfully parsed.
732254721Semaste//
733254721Semaste// This function will find the die_offset of any items whose DW_AT_name
734254721Semaste// matches the given string
735254721Semaste//----------------------------------------------------------------------
736254721Semastetypedef struct FindCallbackStringInfoTag
737254721Semaste{
738254721Semaste    const char* name;
739254721Semaste    bool ignore_case;
740254721Semaste    RegularExpression* regex;
741254721Semaste    vector<dw_offset_t>& die_offsets;
742254721Semaste} FindCallbackStringInfo;
743254721Semaste
744254721Semastestatic dw_offset_t FindCallbackString
745254721Semaste(
746254721Semaste    SymbolFileDWARF* dwarf2Data,
747254721Semaste    DWARFCompileUnitSP& cu_sp,
748254721Semaste    DWARFDebugInfoEntry* die,
749254721Semaste    const dw_offset_t next_offset,
750254721Semaste    const uint32_t curr_depth,
751254721Semaste    void* userData
752254721Semaste)
753254721Semaste{
754254721Semaste    FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData;
755254721Semaste    const DWARFCompileUnit* cu = cu_sp.get();
756254721Semaste
757254721Semaste    if (die)
758254721Semaste    {
759254721Semaste        const char* die_name = die->GetName(dwarf2Data, cu);
760254721Semaste        if (die_name)
761254721Semaste        {
762254721Semaste            if (info->regex)
763254721Semaste            {
764254721Semaste                if (info->regex->Execute(die_name))
765254721Semaste                    info->die_offsets.push_back(die->GetOffset());
766254721Semaste            }
767254721Semaste            else
768254721Semaste            {
769254721Semaste                if ((info->ignore_case ? strcasecmp(die_name, info->name) : strcmp(die_name, info->name)) == 0)
770254721Semaste                    info->die_offsets.push_back(die->GetOffset());
771254721Semaste            }
772254721Semaste        }
773254721Semaste    }
774254721Semaste
775254721Semaste    // Just return the current offset to parse the next CU or DIE entry
776254721Semaste    return next_offset;
777254721Semaste}
778254721Semaste
779254721Semaste//----------------------------------------------------------------------
780254721Semaste// Find
781254721Semaste//
782254721Semaste// Finds all DIE that have a specific DW_AT_name attribute by manually
783254721Semaste// searching through the debug information (not using the
784254721Semaste// .debug_pubnames section). The string must match the entire name
785254721Semaste// and case sensitive searches are an option.
786254721Semaste//----------------------------------------------------------------------
787254721Semastebool
788254721SemasteDWARFDebugInfo::Find(const char* name, bool ignore_case, vector<dw_offset_t>& die_offsets) const
789254721Semaste{
790254721Semaste    die_offsets.clear();
791254721Semaste    if (name && name[0])
792254721Semaste    {
793254721Semaste        FindCallbackStringInfo info = { name, ignore_case, NULL, die_offsets };
794254721Semaste        DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
795254721Semaste    }
796254721Semaste    return !die_offsets.empty();
797254721Semaste}
798254721Semaste
799254721Semaste//----------------------------------------------------------------------
800254721Semaste// Find
801254721Semaste//
802254721Semaste// Finds all DIE that have a specific DW_AT_name attribute by manually
803254721Semaste// searching through the debug information (not using the
804254721Semaste// .debug_pubnames section). The string must match the supplied regular
805254721Semaste// expression.
806254721Semaste//----------------------------------------------------------------------
807254721Semastebool
808254721SemasteDWARFDebugInfo::Find(RegularExpression& re, vector<dw_offset_t>& die_offsets) const
809254721Semaste{
810254721Semaste    die_offsets.clear();
811254721Semaste    FindCallbackStringInfo info = { NULL, false, &re, die_offsets };
812254721Semaste    DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
813254721Semaste    return !die_offsets.empty();
814254721Semaste}
815