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