SymbolContext.cpp revision 256281
1130803Smarcel//===-- SymbolContext.cpp ---------------------------------------*- C++ -*-===//
2130803Smarcel//
3130803Smarcel//                     The LLVM Compiler Infrastructure
4130803Smarcel//
5130803Smarcel// This file is distributed under the University of Illinois Open Source
6130803Smarcel// License. See LICENSE.TXT for details.
7130803Smarcel//
8130803Smarcel//===----------------------------------------------------------------------===//
9130803Smarcel
10130803Smarcel#include "lldb/Symbol/SymbolContext.h"
11130803Smarcel
12130803Smarcel#include "lldb/Core/Log.h"
13130803Smarcel#include "lldb/Core/Module.h"
14130803Smarcel#include "lldb/Core/ModuleSpec.h"
15130803Smarcel#include "lldb/Host/Host.h"
16130803Smarcel#include "lldb/Interpreter/Args.h"
17130803Smarcel#include "lldb/Symbol/Block.h"
18130803Smarcel#include "lldb/Symbol/ClangASTContext.h"
19130803Smarcel#include "lldb/Symbol/CompileUnit.h"
20130803Smarcel#include "lldb/Symbol/ObjectFile.h"
21130803Smarcel#include "lldb/Symbol/Symbol.h"
22130803Smarcel#include "lldb/Symbol/SymbolFile.h"
23130803Smarcel#include "lldb/Symbol/SymbolVendor.h"
24130803Smarcel#include "lldb/Target/Target.h"
25130803Smarcel
26130803Smarcelusing namespace lldb;
27130803Smarcelusing namespace lldb_private;
28130803Smarcel
29130803SmarcelSymbolContext::SymbolContext() :
30130803Smarcel    target_sp   (),
31130803Smarcel    module_sp   (),
32130803Smarcel    comp_unit   (NULL),
33130803Smarcel    function    (NULL),
34130803Smarcel    block       (NULL),
35130803Smarcel    line_entry  (),
36130803Smarcel    symbol      (NULL)
37130803Smarcel{
38130803Smarcel}
39130803Smarcel
40130803SmarcelSymbolContext::SymbolContext(const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
41130803Smarcel    target_sp   (),
42130803Smarcel    module_sp   (m),
43130803Smarcel    comp_unit   (cu),
44130803Smarcel    function    (f),
45130803Smarcel    block       (b),
46130803Smarcel    line_entry  (),
47130803Smarcel    symbol      (s)
48130803Smarcel{
49130803Smarcel    if (le)
50130803Smarcel        line_entry = *le;
51130803Smarcel}
52130803Smarcel
53130803SmarcelSymbolContext::SymbolContext(const TargetSP &t, const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
54130803Smarcel    target_sp   (t),
55130803Smarcel    module_sp   (m),
56130803Smarcel    comp_unit   (cu),
57130803Smarcel    function    (f),
58130803Smarcel    block       (b),
59130803Smarcel    line_entry  (),
60130803Smarcel    symbol      (s)
61130803Smarcel{
62130803Smarcel    if (le)
63130803Smarcel        line_entry = *le;
64130803Smarcel}
65130803Smarcel
66130803SmarcelSymbolContext::SymbolContext(const SymbolContext& rhs) :
67130803Smarcel    target_sp   (rhs.target_sp),
68130803Smarcel    module_sp   (rhs.module_sp),
69130803Smarcel    comp_unit   (rhs.comp_unit),
70130803Smarcel    function    (rhs.function),
71130803Smarcel    block       (rhs.block),
72130803Smarcel    line_entry  (rhs.line_entry),
73130803Smarcel    symbol      (rhs.symbol)
74130803Smarcel{
75130803Smarcel}
76130803Smarcel
77130803Smarcel
78130803SmarcelSymbolContext::SymbolContext (SymbolContextScope *sc_scope) :
79130803Smarcel    target_sp   (),
80130803Smarcel    module_sp   (),
81130803Smarcel    comp_unit   (NULL),
82130803Smarcel    function    (NULL),
83130803Smarcel    block       (NULL),
84130803Smarcel    line_entry  (),
85130803Smarcel    symbol      (NULL)
86130803Smarcel{
87130803Smarcel    sc_scope->CalculateSymbolContext (this);
88130803Smarcel}
89130803Smarcel
90130803SmarcelSymbolContext::~SymbolContext ()
91130803Smarcel{
92130803Smarcel}
93130803Smarcel
94130803Smarcelconst SymbolContext&
95130803SmarcelSymbolContext::operator= (const SymbolContext& rhs)
96130803Smarcel{
97130803Smarcel    if (this != &rhs)
98130803Smarcel    {
99130803Smarcel        target_sp   = rhs.target_sp;
100130803Smarcel        module_sp   = rhs.module_sp;
101130803Smarcel        comp_unit   = rhs.comp_unit;
102130803Smarcel        function    = rhs.function;
103130803Smarcel        block       = rhs.block;
104130803Smarcel        line_entry  = rhs.line_entry;
105130803Smarcel        symbol      = rhs.symbol;
106130803Smarcel    }
107130803Smarcel    return *this;
108130803Smarcel}
109130803Smarcel
110130803Smarcelvoid
111130803SmarcelSymbolContext::Clear(bool clear_target)
112130803Smarcel{
113130803Smarcel    if (clear_target)
114130803Smarcel        target_sp.reset();
115130803Smarcel    module_sp.reset();
116130803Smarcel    comp_unit   = NULL;
117130803Smarcel    function    = NULL;
118130803Smarcel    block       = NULL;
119130803Smarcel    line_entry.Clear();
120130803Smarcel    symbol      = NULL;
121130803Smarcel}
122130803Smarcel
123130803Smarcelbool
124130803SmarcelSymbolContext::DumpStopContext
125130803Smarcel(
126130803Smarcel    Stream *s,
127130803Smarcel    ExecutionContextScope *exe_scope,
128130803Smarcel    const Address &addr,
129130803Smarcel    bool show_fullpaths,
130130803Smarcel    bool show_module,
131130803Smarcel    bool show_inlined_frames
132130803Smarcel) const
133130803Smarcel{
134130803Smarcel    bool dumped_something = false;
135130803Smarcel    if (show_module && module_sp)
136130803Smarcel    {
137130803Smarcel        if (show_fullpaths)
138130803Smarcel            *s << module_sp->GetFileSpec();
139130803Smarcel        else
140130803Smarcel            *s << module_sp->GetFileSpec().GetFilename();
141130803Smarcel        s->PutChar('`');
142130803Smarcel        dumped_something = true;
143130803Smarcel    }
144130803Smarcel
145130803Smarcel    if (function != NULL)
146130803Smarcel    {
147130803Smarcel        SymbolContext inline_parent_sc;
148130803Smarcel        Address inline_parent_addr;
149130803Smarcel        if (function->GetMangled().GetName())
150130803Smarcel        {
151130803Smarcel            dumped_something = true;
152130803Smarcel            function->GetMangled().GetName().Dump(s);
153130803Smarcel        }
154130803Smarcel
155130803Smarcel        if (addr.IsValid())
156130803Smarcel        {
157130803Smarcel            const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetOffset();
158130803Smarcel            if (function_offset)
159130803Smarcel            {
160130803Smarcel                dumped_something = true;
161130803Smarcel                s->Printf(" + %" PRIu64, function_offset);
162130803Smarcel            }
163130803Smarcel        }
164130803Smarcel
165130803Smarcel        if (GetParentOfInlinedScope (addr, inline_parent_sc, inline_parent_addr))
166130803Smarcel        {
167130803Smarcel            dumped_something = true;
168130803Smarcel            Block *inlined_block = block->GetContainingInlinedBlock();
169130803Smarcel            const InlineFunctionInfo* inlined_block_info = inlined_block->GetInlinedFunctionInfo();
170130803Smarcel            s->Printf (" [inlined] %s", inlined_block_info->GetName().GetCString());
171130803Smarcel
172130803Smarcel            lldb_private::AddressRange block_range;
173130803Smarcel            if (inlined_block->GetRangeContainingAddress(addr, block_range))
174130803Smarcel            {
175130803Smarcel                const addr_t inlined_function_offset = addr.GetOffset() - block_range.GetBaseAddress().GetOffset();
176130803Smarcel                if (inlined_function_offset)
177130803Smarcel                {
178130803Smarcel                    s->Printf(" + %" PRIu64, inlined_function_offset);
179130803Smarcel                }
180130803Smarcel            }
181130803Smarcel            const Declaration &call_site = inlined_block_info->GetCallSite();
182130803Smarcel            if (call_site.IsValid())
183130803Smarcel            {
184130803Smarcel                s->PutCString(" at ");
185130803Smarcel                call_site.DumpStopContext (s, show_fullpaths);
186130803Smarcel            }
187130803Smarcel            if (show_inlined_frames)
188130803Smarcel            {
189130803Smarcel                s->EOL();
190130803Smarcel                s->Indent();
191130803Smarcel                return inline_parent_sc.DumpStopContext (s, exe_scope, inline_parent_addr, show_fullpaths, show_module, show_inlined_frames);
192130803Smarcel            }
193130803Smarcel        }
194130803Smarcel        else
195130803Smarcel        {
196130803Smarcel            if (line_entry.IsValid())
197130803Smarcel            {
198130803Smarcel                dumped_something = true;
199130803Smarcel                s->PutCString(" at ");
200130803Smarcel                if (line_entry.DumpStopContext(s, show_fullpaths))
201130803Smarcel                    dumped_something = true;
202130803Smarcel            }
203130803Smarcel        }
204130803Smarcel    }
205130803Smarcel    else if (symbol != NULL)
206130803Smarcel    {
207130803Smarcel        if (symbol->GetMangled().GetName())
208130803Smarcel        {
209130803Smarcel            dumped_something = true;
210130803Smarcel            if (symbol->GetType() == eSymbolTypeTrampoline)
211130803Smarcel                s->PutCString("symbol stub for: ");
212130803Smarcel            symbol->GetMangled().GetName().Dump(s);
213130803Smarcel        }
214130803Smarcel
215130803Smarcel        if (addr.IsValid() && symbol->ValueIsAddress())
216130803Smarcel        {
217130803Smarcel            const addr_t symbol_offset = addr.GetOffset() - symbol->GetAddress().GetOffset();
218130803Smarcel            if (symbol_offset)
219130803Smarcel            {
220130803Smarcel                dumped_something = true;
221130803Smarcel                s->Printf(" + %" PRIu64, symbol_offset);
222130803Smarcel            }
223130803Smarcel        }
224130803Smarcel    }
225130803Smarcel    else if (addr.IsValid())
226130803Smarcel    {
227130803Smarcel        addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress);
228130803Smarcel        dumped_something = true;
229130803Smarcel    }
230130803Smarcel    return dumped_something;
231130803Smarcel}
232130803Smarcel
233130803Smarcelvoid
234130803SmarcelSymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target) const
235130803Smarcel{
236130803Smarcel    if (module_sp)
237130803Smarcel    {
238130803Smarcel        s->Indent("     Module: file = \"");
239130803Smarcel        module_sp->GetFileSpec().Dump(s);
240130803Smarcel        *s << '"';
241130803Smarcel        if (module_sp->GetArchitecture().IsValid())
242130803Smarcel            s->Printf (", arch = \"%s\"", module_sp->GetArchitecture().GetArchitectureName());
243130803Smarcel        s->EOL();
244130803Smarcel    }
245130803Smarcel
246130803Smarcel    if (comp_unit != NULL)
247130803Smarcel    {
248130803Smarcel        s->Indent("CompileUnit: ");
249130803Smarcel        comp_unit->GetDescription (s, level);
250130803Smarcel        s->EOL();
251130803Smarcel    }
252130803Smarcel
253130803Smarcel    if (function != NULL)
254130803Smarcel    {
255130803Smarcel        s->Indent("   Function: ");
256130803Smarcel        function->GetDescription (s, level, target);
257130803Smarcel        s->EOL();
258130803Smarcel
259130803Smarcel        Type *func_type = function->GetType();
260130803Smarcel        if (func_type)
261130803Smarcel        {
262130803Smarcel            s->Indent("   FuncType: ");
263130803Smarcel            func_type->GetDescription (s, level, false);
264130803Smarcel            s->EOL();
265130803Smarcel        }
266130803Smarcel    }
267130803Smarcel
268130803Smarcel    if (block != NULL)
269130803Smarcel    {
270130803Smarcel        std::vector<Block *> blocks;
271130803Smarcel        blocks.push_back (block);
272130803Smarcel        Block *parent_block = block->GetParent();
273130803Smarcel
274130803Smarcel        while (parent_block)
275130803Smarcel        {
276130803Smarcel            blocks.push_back (parent_block);
277130803Smarcel            parent_block = parent_block->GetParent();
278130803Smarcel        }
279130803Smarcel        std::vector<Block *>::reverse_iterator pos;
280130803Smarcel        std::vector<Block *>::reverse_iterator begin = blocks.rbegin();
281130803Smarcel        std::vector<Block *>::reverse_iterator end = blocks.rend();
282130803Smarcel        for (pos = begin; pos != end; ++pos)
283130803Smarcel        {
284130803Smarcel            if (pos == begin)
285130803Smarcel                s->Indent("     Blocks: ");
286130803Smarcel            else
287130803Smarcel                s->Indent("             ");
288130803Smarcel            (*pos)->GetDescription(s, function, level, target);
289130803Smarcel            s->EOL();
290130803Smarcel        }
291130803Smarcel    }
292130803Smarcel
293130803Smarcel    if (line_entry.IsValid())
294130803Smarcel    {
295130803Smarcel        s->Indent("  LineEntry: ");
296130803Smarcel        line_entry.GetDescription (s, level, comp_unit, target, false);
297130803Smarcel        s->EOL();
298130803Smarcel    }
299130803Smarcel
300130803Smarcel    if (symbol != NULL)
301130803Smarcel    {
302130803Smarcel        s->Indent("     Symbol: ");
303130803Smarcel        symbol->GetDescription(s, level, target);
304130803Smarcel        s->EOL();
305130803Smarcel    }
306130803Smarcel}
307130803Smarcel
308130803Smarceluint32_t
309130803SmarcelSymbolContext::GetResolvedMask () const
310130803Smarcel{
311130803Smarcel    uint32_t resolved_mask = 0;
312130803Smarcel    if (target_sp)              resolved_mask |= eSymbolContextTarget;
313130803Smarcel    if (module_sp)              resolved_mask |= eSymbolContextModule;
314130803Smarcel    if (comp_unit)              resolved_mask |= eSymbolContextCompUnit;
315130803Smarcel    if (function)               resolved_mask |= eSymbolContextFunction;
316130803Smarcel    if (block)                  resolved_mask |= eSymbolContextBlock;
317130803Smarcel    if (line_entry.IsValid())   resolved_mask |= eSymbolContextLineEntry;
318130803Smarcel    if (symbol)                 resolved_mask |= eSymbolContextSymbol;
319130803Smarcel    return resolved_mask;
320130803Smarcel}
321130803Smarcel
322130803Smarcelvoid
323130803SmarcelSymbolContext::Dump(Stream *s, Target *target) const
324130803Smarcel{
325130803Smarcel    *s << (void *)this << ": ";
326130803Smarcel    s->Indent();
327130803Smarcel    s->PutCString("SymbolContext");
328130803Smarcel    s->IndentMore();
329130803Smarcel    s->EOL();
330130803Smarcel    s->IndentMore();
331130803Smarcel    s->Indent();
332130803Smarcel    *s << "Module       = " << (void *)module_sp.get() << ' ';
333130803Smarcel    if (module_sp)
334130803Smarcel        module_sp->GetFileSpec().Dump(s);
335130803Smarcel    s->EOL();
336130803Smarcel    s->Indent();
337130803Smarcel    *s << "CompileUnit  = " << (void *)comp_unit;
338130803Smarcel    if (comp_unit != NULL)
339130803Smarcel        *s << " {0x" << comp_unit->GetID() << "} " << *(static_cast<FileSpec*> (comp_unit));
340130803Smarcel    s->EOL();
341130803Smarcel    s->Indent();
342130803Smarcel    *s << "Function     = " << (void *)function;
343130803Smarcel    if (function != NULL)
344130803Smarcel    {
345130803Smarcel        *s << " {0x" << function->GetID() << "} " << function->GetType()->GetName() << ", address-range = ";
346130803Smarcel        function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
347130803Smarcel        s->EOL();
348130803Smarcel        s->Indent();
349130803Smarcel        Type* func_type = function->GetType();
350130803Smarcel        if (func_type)
351130803Smarcel        {
352130803Smarcel            *s << "        Type = ";
353130803Smarcel            func_type->Dump (s, false);
354130803Smarcel        }
355130803Smarcel    }
356130803Smarcel    s->EOL();
357130803Smarcel    s->Indent();
358130803Smarcel    *s << "Block        = " << (void *)block;
359130803Smarcel    if (block != NULL)
360130803Smarcel        *s << " {0x" << block->GetID() << '}';
361130803Smarcel    // Dump the block and pass it a negative depth to we print all the parent blocks
362130803Smarcel    //if (block != NULL)
363130803Smarcel    //  block->Dump(s, function->GetFileAddress(), INT_MIN);
364130803Smarcel    s->EOL();
365130803Smarcel    s->Indent();
366130803Smarcel    *s << "LineEntry    = ";
367130803Smarcel    line_entry.Dump (s, target, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true);
368130803Smarcel    s->EOL();
369130803Smarcel    s->Indent();
370130803Smarcel    *s << "Symbol       = " << (void *)symbol;
371130803Smarcel    if (symbol != NULL && symbol->GetMangled())
372130803Smarcel        *s << ' ' << symbol->GetMangled().GetName().AsCString();
373130803Smarcel    s->EOL();
374130803Smarcel    s->IndentLess();
375130803Smarcel    s->IndentLess();
376130803Smarcel}
377130803Smarcel
378130803Smarcelbool
379130803Smarcellldb_private::operator== (const SymbolContext& lhs, const SymbolContext& rhs)
380130803Smarcel{
381130803Smarcel    return  lhs.function == rhs.function
382130803Smarcel            && lhs.symbol == rhs.symbol
383130803Smarcel            && lhs.module_sp.get() == rhs.module_sp.get()
384130803Smarcel            && lhs.comp_unit == rhs.comp_unit
385130803Smarcel            && lhs.target_sp.get() == rhs.target_sp.get()
386130803Smarcel            && LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0;
387130803Smarcel}
388130803Smarcel
389130803Smarcelbool
390130803Smarcellldb_private::operator!= (const SymbolContext& lhs, const SymbolContext& rhs)
391130803Smarcel{
392130803Smarcel    return  lhs.function != rhs.function
393130803Smarcel            || lhs.symbol != rhs.symbol
394130803Smarcel            || lhs.module_sp.get() != rhs.module_sp.get()
395130803Smarcel            || lhs.comp_unit != rhs.comp_unit
396130803Smarcel            || lhs.target_sp.get() != rhs.target_sp.get()
397130803Smarcel            || LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0;
398130803Smarcel}
399130803Smarcel
400130803Smarcelbool
401130803SmarcelSymbolContext::GetAddressRange (uint32_t scope,
402130803Smarcel                                uint32_t range_idx,
403130803Smarcel                                bool use_inline_block_range,
404130803Smarcel                                AddressRange &range) const
405130803Smarcel{
406130803Smarcel    if ((scope & eSymbolContextLineEntry) && line_entry.IsValid())
407130803Smarcel    {
408130803Smarcel        range = line_entry.range;
409130803Smarcel        return true;
410130803Smarcel    }
411130803Smarcel
412130803Smarcel    if ((scope & eSymbolContextBlock) && (block != NULL))
413130803Smarcel    {
414130803Smarcel        if (use_inline_block_range)
415130803Smarcel        {
416130803Smarcel            Block *inline_block = block->GetContainingInlinedBlock();
417130803Smarcel            if (inline_block)
418130803Smarcel                return inline_block->GetRangeAtIndex (range_idx, range);
419130803Smarcel        }
420130803Smarcel        else
421130803Smarcel        {
422130803Smarcel            return block->GetRangeAtIndex (range_idx, range);
423130803Smarcel        }
424130803Smarcel    }
425130803Smarcel
426130803Smarcel    if ((scope & eSymbolContextFunction) && (function != NULL))
427130803Smarcel    {
428130803Smarcel        if (range_idx == 0)
429130803Smarcel        {
430130803Smarcel            range = function->GetAddressRange();
431130803Smarcel            return true;
432130803Smarcel        }
433130803Smarcel    }
434130803Smarcel
435130803Smarcel    if ((scope & eSymbolContextSymbol) && (symbol != NULL))
436130803Smarcel    {
437130803Smarcel        if (range_idx == 0)
438130803Smarcel        {
439130803Smarcel            if (symbol->ValueIsAddress())
440130803Smarcel            {
441130803Smarcel                range.GetBaseAddress() = symbol->GetAddress();
442130803Smarcel                range.SetByteSize (symbol->GetByteSize());
443130803Smarcel                return true;
444130803Smarcel            }
445130803Smarcel        }
446130803Smarcel    }
447130803Smarcel    range.Clear();
448130803Smarcel    return false;
449130803Smarcel}
450130803Smarcel
451130803Smarcelbool
452130803SmarcelSymbolContext::GetParentOfInlinedScope (const Address &curr_frame_pc,
453130803Smarcel                                        SymbolContext &next_frame_sc,
454130803Smarcel                                        Address &next_frame_pc) const
455130803Smarcel{
456130803Smarcel    next_frame_sc.Clear(false);
457130803Smarcel    next_frame_pc.Clear();
458130803Smarcel
459130803Smarcel    if (block)
460130803Smarcel    {
461130803Smarcel        //const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress();
462130803Smarcel
463130803Smarcel        // In order to get the parent of an inlined function we first need to
464130803Smarcel        // see if we are in an inlined block as "this->block" could be an
465130803Smarcel        // inlined block, or a parent of "block" could be. So lets check if
466130803Smarcel        // this block or one of this blocks parents is an inlined function.
467130803Smarcel        Block *curr_inlined_block = block->GetContainingInlinedBlock();
468130803Smarcel        if (curr_inlined_block)
469130803Smarcel        {
470130803Smarcel            // "this->block" is contained in an inline function block, so to
471130803Smarcel            // get the scope above the inlined block, we get the parent of the
472130803Smarcel            // inlined block itself
473130803Smarcel            Block *next_frame_block = curr_inlined_block->GetParent();
474130803Smarcel            // Now calculate the symbol context of the containing block
475130803Smarcel            next_frame_block->CalculateSymbolContext (&next_frame_sc);
476130803Smarcel
477130803Smarcel            // If we get here we weren't able to find the return line entry using the nesting of the blocks and
478130803Smarcel            // the line table.  So just use the call site info from our inlined block.
479130803Smarcel
480130803Smarcel            AddressRange range;
481130803Smarcel            if (curr_inlined_block->GetRangeContainingAddress (curr_frame_pc, range))
482130803Smarcel            {
483130803Smarcel                // To see there this new frame block it, we need to look at the
484130803Smarcel                // call site information from
485130803Smarcel                const InlineFunctionInfo* curr_inlined_block_inlined_info = curr_inlined_block->GetInlinedFunctionInfo();
486130803Smarcel                next_frame_pc = range.GetBaseAddress();
487130803Smarcel                next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc;
488130803Smarcel                next_frame_sc.line_entry.file = curr_inlined_block_inlined_info->GetCallSite().GetFile();
489130803Smarcel                next_frame_sc.line_entry.line = curr_inlined_block_inlined_info->GetCallSite().GetLine();
490130803Smarcel                next_frame_sc.line_entry.column = curr_inlined_block_inlined_info->GetCallSite().GetColumn();
491130803Smarcel                return true;
492130803Smarcel            }
493130803Smarcel            else
494130803Smarcel            {
495130803Smarcel                Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
496130803Smarcel
497130803Smarcel                if (log)
498130803Smarcel                {
499130803Smarcel                    log->Printf ("warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64,
500130803Smarcel                                 curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress());
501130803Smarcel                }
502130803Smarcel#ifdef LLDB_CONFIGURATION_DEBUG
503130803Smarcel                else
504130803Smarcel                {
505130803Smarcel                    ObjectFile *objfile = NULL;
506130803Smarcel                    if (module_sp)
507130803Smarcel                    {
508130803Smarcel                        SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
509130803Smarcel                        if (symbol_vendor)
510130803Smarcel                        {
511130803Smarcel                            SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
512130803Smarcel                            if (symbol_file)
513130803Smarcel                                objfile = symbol_file->GetObjectFile();
514130803Smarcel                        }
515130803Smarcel                    }
516130803Smarcel                    if (objfile)
517130803Smarcel                    {
518130803Smarcel                        Host::SystemLog (Host::eSystemLogWarning,
519130803Smarcel                                         "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 " in %s\n",
520130803Smarcel                                         curr_inlined_block->GetID(),
521130803Smarcel                                         curr_frame_pc.GetFileAddress(),
522130803Smarcel                                         objfile->GetFileSpec().GetPath().c_str());
523130803Smarcel                    }
524130803Smarcel                    else
525130803Smarcel                    {
526130803Smarcel                        Host::SystemLog (Host::eSystemLogWarning,
527130803Smarcel                                         "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 "\n",
528130803Smarcel                                         curr_inlined_block->GetID(),
529130803Smarcel                                         curr_frame_pc.GetFileAddress());
530130803Smarcel                    }
531130803Smarcel                }
532130803Smarcel#endif
533130803Smarcel            }
534130803Smarcel        }
535130803Smarcel    }
536130803Smarcel
537130803Smarcel    return false;
538130803Smarcel}
539130803Smarcel
540130803SmarcelBlock *
541130803SmarcelSymbolContext::GetFunctionBlock ()
542130803Smarcel{
543130803Smarcel    if (function)
544130803Smarcel    {
545130803Smarcel        if (block)
546130803Smarcel        {
547130803Smarcel            // If this symbol context has a block, check to see if this block
548130803Smarcel            // is itself, or is contained within a block with inlined function
549130803Smarcel            // information. If so, then the inlined block is the block that
550130803Smarcel            // defines the function.
551130803Smarcel            Block *inlined_block = block->GetContainingInlinedBlock();
552130803Smarcel            if (inlined_block)
553130803Smarcel                return inlined_block;
554130803Smarcel
555130803Smarcel            // The block in this symbol context is not inside an inlined
556130803Smarcel            // block, so the block that defines the function is the function's
557130803Smarcel            // top level block, which is returned below.
558130803Smarcel        }
559130803Smarcel
560130803Smarcel        // There is no block information in this symbol context, so we must
561130803Smarcel        // assume that the block that is desired is the top level block of
562130803Smarcel        // the function itself.
563130803Smarcel        return &function->GetBlock(true);
564130803Smarcel    }
565130803Smarcel    return NULL;
566130803Smarcel}
567130803Smarcel
568130803Smarcelbool
569130803SmarcelSymbolContext::GetFunctionMethodInfo (lldb::LanguageType &language,
570130803Smarcel                                      bool &is_instance_method,
571130803Smarcel                                      ConstString &language_object_name)
572130803Smarcel
573130803Smarcel
574130803Smarcel{
575130803Smarcel    Block *function_block = GetFunctionBlock ();
576130803Smarcel    if (function_block)
577130803Smarcel    {
578130803Smarcel        clang::DeclContext *decl_context = function_block->GetClangDeclContext();
579130803Smarcel
580130803Smarcel        if (decl_context)
581130803Smarcel        {
582130803Smarcel            return ClangASTContext::GetClassMethodInfoForDeclContext (decl_context,
583130803Smarcel                                                                      language,
584130803Smarcel                                                                      is_instance_method,
585130803Smarcel                                                                      language_object_name);
586130803Smarcel        }
587130803Smarcel    }
588130803Smarcel    language = eLanguageTypeUnknown;
589130803Smarcel    is_instance_method = false;
590130803Smarcel    language_object_name.Clear();
591130803Smarcel    return false;
592130803Smarcel}
593130803Smarcel
594130803SmarcelConstString
595130803SmarcelSymbolContext::GetFunctionName (Mangled::NamePreference preference) const
596130803Smarcel{
597130803Smarcel    if (function)
598130803Smarcel    {
599130803Smarcel        if (block)
600130803Smarcel        {
601130803Smarcel            Block *inlined_block = block->GetContainingInlinedBlock();
602130803Smarcel
603130803Smarcel            if (inlined_block)
604130803Smarcel            {
605130803Smarcel                const InlineFunctionInfo *inline_info = inlined_block->GetInlinedFunctionInfo();
606130803Smarcel                if (inline_info)
607130803Smarcel                    return inline_info->GetName();
608130803Smarcel            }
609130803Smarcel        }
610130803Smarcel        return function->GetMangled().GetName(preference);
611130803Smarcel    }
612130803Smarcel    else if (symbol && symbol->ValueIsAddress())
613130803Smarcel    {
614130803Smarcel        return symbol->GetMangled().GetName(preference);
615130803Smarcel    }
616130803Smarcel    else
617130803Smarcel    {
618130803Smarcel        // No function, return an empty string.
619130803Smarcel        return ConstString();
620130803Smarcel    }
621130803Smarcel}
622130803Smarcel
623130803SmarcelLineEntry
624130803SmarcelSymbolContext::GetFunctionStartLineEntry () const
625130803Smarcel{
626130803Smarcel    LineEntry line_entry;
627130803Smarcel    Address start_addr;
628130803Smarcel    if (block)
629130803Smarcel    {
630130803Smarcel        Block *inlined_block = block->GetContainingInlinedBlock();
631130803Smarcel        if (inlined_block)
632130803Smarcel        {
633130803Smarcel            if (inlined_block->GetStartAddress (start_addr))
634130803Smarcel            {
635130803Smarcel                if (start_addr.CalculateSymbolContextLineEntry (line_entry))
636130803Smarcel                    return line_entry;
637130803Smarcel            }
638130803Smarcel            return LineEntry();
639130803Smarcel        }
640130803Smarcel    }
641130803Smarcel
642130803Smarcel    if (function)
643130803Smarcel    {
644130803Smarcel        if (function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry(line_entry))
645130803Smarcel            return line_entry;
646130803Smarcel    }
647130803Smarcel    return LineEntry();
648130803Smarcel}
649130803Smarcel
650130803Smarcel//----------------------------------------------------------------------
651130803Smarcel//
652130803Smarcel//  SymbolContextSpecifier
653130803Smarcel//
654130803Smarcel//----------------------------------------------------------------------
655130803Smarcel
656130803SmarcelSymbolContextSpecifier::SymbolContextSpecifier (const TargetSP &target_sp) :
657130803Smarcel    m_target_sp (target_sp),
658130803Smarcel    m_module_spec (),
659130803Smarcel    m_module_sp (),
660130803Smarcel    m_file_spec_ap (),
661130803Smarcel    m_start_line (0),
662130803Smarcel    m_end_line (0),
663130803Smarcel    m_function_spec (),
664130803Smarcel    m_class_name (),
665130803Smarcel    m_address_range_ap (),
666130803Smarcel    m_type (eNothingSpecified)
667130803Smarcel{
668130803Smarcel}
669130803Smarcel
670130803SmarcelSymbolContextSpecifier::~SymbolContextSpecifier()
671130803Smarcel{
672130803Smarcel}
673130803Smarcel
674130803Smarcelbool
675130803SmarcelSymbolContextSpecifier::AddLineSpecification (uint32_t line_no, SpecificationType type)
676130803Smarcel{
677130803Smarcel    bool return_value = true;
678130803Smarcel    switch (type)
679130803Smarcel    {
680130803Smarcel    case eNothingSpecified:
681130803Smarcel        Clear();
682130803Smarcel        break;
683130803Smarcel    case eLineStartSpecified:
684130803Smarcel        m_start_line = line_no;
685130803Smarcel        m_type |= eLineStartSpecified;
686130803Smarcel        break;
687130803Smarcel    case eLineEndSpecified:
688130803Smarcel        m_end_line = line_no;
689130803Smarcel        m_type |= eLineEndSpecified;
690130803Smarcel        break;
691130803Smarcel    default:
692130803Smarcel        return_value = false;
693130803Smarcel        break;
694130803Smarcel    }
695130803Smarcel    return return_value;
696130803Smarcel}
697130803Smarcel
698130803Smarcelbool
699130803SmarcelSymbolContextSpecifier::AddSpecification (const char *spec_string, SpecificationType type)
700130803Smarcel{
701130803Smarcel    bool return_value = true;
702130803Smarcel    switch (type)
703130803Smarcel    {
704130803Smarcel    case eNothingSpecified:
705130803Smarcel        Clear();
706130803Smarcel        break;
707130803Smarcel    case eModuleSpecified:
708130803Smarcel        {
709130803Smarcel            // See if we can find the Module, if so stick it in the SymbolContext.
710130803Smarcel            FileSpec module_file_spec(spec_string, false);
711130803Smarcel            ModuleSpec module_spec (module_file_spec);
712130803Smarcel            lldb::ModuleSP module_sp (m_target_sp->GetImages().FindFirstModule (module_spec));
713130803Smarcel            m_type |= eModuleSpecified;
714130803Smarcel            if (module_sp)
715130803Smarcel                m_module_sp = module_sp;
716130803Smarcel            else
717130803Smarcel                m_module_spec.assign (spec_string);
718130803Smarcel        }
719130803Smarcel        break;
720130803Smarcel    case eFileSpecified:
721130803Smarcel        // CompUnits can't necessarily be resolved here, since an inlined function might show up in
722130803Smarcel        // a number of CompUnits.  Instead we just convert to a FileSpec and store it away.
723130803Smarcel        m_file_spec_ap.reset (new FileSpec (spec_string, false));
724130803Smarcel        m_type |= eFileSpecified;
725130803Smarcel        break;
726130803Smarcel    case eLineStartSpecified:
727130803Smarcel        m_start_line = Args::StringToSInt32(spec_string, 0, 0, &return_value);
728130803Smarcel        if (return_value)
729130803Smarcel            m_type |= eLineStartSpecified;
730130803Smarcel        break;
731130803Smarcel    case eLineEndSpecified:
732130803Smarcel        m_end_line = Args::StringToSInt32(spec_string, 0, 0, &return_value);
733130803Smarcel        if (return_value)
734130803Smarcel            m_type |= eLineEndSpecified;
735130803Smarcel        break;
736130803Smarcel    case eFunctionSpecified:
737130803Smarcel        m_function_spec.assign(spec_string);
738130803Smarcel        m_type |= eFunctionSpecified;
739130803Smarcel        break;
740130803Smarcel    case eClassOrNamespaceSpecified:
741130803Smarcel        Clear();
742130803Smarcel        m_class_name.assign (spec_string);
743130803Smarcel        m_type = eClassOrNamespaceSpecified;
744130803Smarcel        break;
745130803Smarcel    case eAddressRangeSpecified:
746130803Smarcel        // Not specified yet...
747130803Smarcel        break;
748130803Smarcel    }
749130803Smarcel
750130803Smarcel    return return_value;
751130803Smarcel}
752130803Smarcel
753130803Smarcelvoid
754130803SmarcelSymbolContextSpecifier::Clear()
755130803Smarcel{
756130803Smarcel    m_module_spec.clear();
757130803Smarcel    m_file_spec_ap.reset();
758130803Smarcel    m_function_spec.clear();
759130803Smarcel    m_class_name.clear();
760130803Smarcel    m_start_line = 0;
761130803Smarcel    m_end_line = 0;
762130803Smarcel    m_address_range_ap.reset();
763130803Smarcel
764130803Smarcel    m_type = eNothingSpecified;
765130803Smarcel}
766130803Smarcel
767130803Smarcelbool
768130803SmarcelSymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
769130803Smarcel{
770130803Smarcel    if (m_type == eNothingSpecified)
771130803Smarcel        return true;
772130803Smarcel
773130803Smarcel    if (m_target_sp.get() != sc.target_sp.get())
774130803Smarcel        return false;
775130803Smarcel
776130803Smarcel    if (m_type & eModuleSpecified)
777130803Smarcel    {
778130803Smarcel        if (sc.module_sp)
779130803Smarcel        {
780130803Smarcel            if (m_module_sp.get() != NULL)
781130803Smarcel            {
782130803Smarcel                if (m_module_sp.get() != sc.module_sp.get())
783130803Smarcel                    return false;
784130803Smarcel            }
785130803Smarcel            else
786130803Smarcel            {
787130803Smarcel                FileSpec module_file_spec (m_module_spec.c_str(), false);
788130803Smarcel                if (!FileSpec::Equal (module_file_spec, sc.module_sp->GetFileSpec(), false))
789130803Smarcel                    return false;
790130803Smarcel            }
791130803Smarcel        }
792130803Smarcel    }
793130803Smarcel    if (m_type & eFileSpecified)
794130803Smarcel    {
795130803Smarcel        if (m_file_spec_ap.get())
796130803Smarcel        {
797130803Smarcel            // If we don't have a block or a comp_unit, then we aren't going to match a source file.
798130803Smarcel            if (sc.block == NULL && sc.comp_unit == NULL)
799130803Smarcel                return false;
800130803Smarcel
801130803Smarcel            // Check if the block is present, and if so is it inlined:
802130803Smarcel            bool was_inlined = false;
803130803Smarcel            if (sc.block != NULL)
804130803Smarcel            {
805130803Smarcel                const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
806130803Smarcel                if (inline_info != NULL)
807130803Smarcel                {
808130803Smarcel                    was_inlined = true;
809130803Smarcel                    if (!FileSpec::Equal (inline_info->GetDeclaration().GetFile(), *(m_file_spec_ap.get()), false))
810130803Smarcel                        return false;
811130803Smarcel                }
812130803Smarcel            }
813130803Smarcel
814130803Smarcel            // Next check the comp unit, but only if the SymbolContext was not inlined.
815130803Smarcel            if (!was_inlined && sc.comp_unit != NULL)
816130803Smarcel            {
817130803Smarcel                if (!FileSpec::Equal (*(sc.comp_unit), *(m_file_spec_ap.get()), false))
818130803Smarcel                    return false;
819130803Smarcel            }
820130803Smarcel        }
821130803Smarcel    }
822130803Smarcel    if (m_type & eLineStartSpecified
823130803Smarcel        || m_type & eLineEndSpecified)
824130803Smarcel    {
825130803Smarcel        if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line)
826130803Smarcel            return false;
827130803Smarcel    }
828130803Smarcel
829130803Smarcel    if (m_type & eFunctionSpecified)
830130803Smarcel    {
831130803Smarcel        // First check the current block, and if it is inlined, get the inlined function name:
832130803Smarcel        bool was_inlined = false;
833130803Smarcel        ConstString func_name(m_function_spec.c_str());
834130803Smarcel
835130803Smarcel        if (sc.block != NULL)
836130803Smarcel        {
837130803Smarcel            const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
838130803Smarcel            if (inline_info != NULL)
839130803Smarcel            {
840130803Smarcel                was_inlined = true;
841130803Smarcel                const Mangled &name = inline_info->GetMangled();
842130803Smarcel                if (!name.NameMatches (func_name))
843130803Smarcel                    return false;
844130803Smarcel            }
845130803Smarcel        }
846130803Smarcel        //  If it wasn't inlined, check the name in the function or symbol:
847130803Smarcel        if (!was_inlined)
848130803Smarcel        {
849130803Smarcel            if (sc.function != NULL)
850130803Smarcel            {
851130803Smarcel                if (!sc.function->GetMangled().NameMatches(func_name))
852130803Smarcel                    return false;
853130803Smarcel            }
854130803Smarcel            else if (sc.symbol != NULL)
855130803Smarcel            {
856130803Smarcel                if (!sc.symbol->GetMangled().NameMatches(func_name))
857130803Smarcel                    return false;
858130803Smarcel            }
859130803Smarcel        }
860130803Smarcel
861130803Smarcel
862130803Smarcel    }
863130803Smarcel
864130803Smarcel    return true;
865130803Smarcel}
866130803Smarcel
867130803Smarcelbool
868130803SmarcelSymbolContextSpecifier::AddressMatches(lldb::addr_t addr)
869130803Smarcel{
870130803Smarcel    if (m_type & eAddressRangeSpecified)
871130803Smarcel    {
872130803Smarcel
873130803Smarcel    }
874130803Smarcel    else
875130803Smarcel    {
876130803Smarcel        Address match_address (addr, NULL);
877130803Smarcel        SymbolContext sc;
878130803Smarcel        m_target_sp->GetImages().ResolveSymbolContextForAddress(match_address, eSymbolContextEverything, sc);
879130803Smarcel        return SymbolContextMatches(sc);
880130803Smarcel    }
881130803Smarcel    return true;
882130803Smarcel}
883130803Smarcel
884130803Smarcelvoid
885130803SmarcelSymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level) const
886130803Smarcel{
887130803Smarcel    char path_str[PATH_MAX + 1];
888130803Smarcel
889130803Smarcel    if (m_type == eNothingSpecified)
890130803Smarcel    {
891130803Smarcel        s->Printf ("Nothing specified.\n");
892130803Smarcel    }
893130803Smarcel
894130803Smarcel    if (m_type == eModuleSpecified)
895130803Smarcel    {
896130803Smarcel        s->Indent();
897130803Smarcel        if (m_module_sp)
898130803Smarcel        {
899130803Smarcel            m_module_sp->GetFileSpec().GetPath (path_str, PATH_MAX);
900130803Smarcel            s->Printf ("Module: %s\n", path_str);
901130803Smarcel        }
902130803Smarcel        else
903130803Smarcel            s->Printf ("Module: %s\n", m_module_spec.c_str());
904130803Smarcel    }
905130803Smarcel
906130803Smarcel    if (m_type == eFileSpecified  && m_file_spec_ap.get() != NULL)
907130803Smarcel    {
908130803Smarcel        m_file_spec_ap->GetPath (path_str, PATH_MAX);
909130803Smarcel        s->Indent();
910130803Smarcel        s->Printf ("File: %s", path_str);
911130803Smarcel        if (m_type == eLineStartSpecified)
912130803Smarcel        {
913130803Smarcel            s->Printf (" from line %lu", m_start_line);
914130803Smarcel            if (m_type == eLineEndSpecified)
915130803Smarcel                s->Printf ("to line %lu", m_end_line);
916130803Smarcel            else
917130803Smarcel                s->Printf ("to end");
918130803Smarcel        }
919130803Smarcel        else if (m_type == eLineEndSpecified)
920130803Smarcel        {
921130803Smarcel            s->Printf (" from start to line %ld", m_end_line);
922130803Smarcel        }
923130803Smarcel        s->Printf (".\n");
924130803Smarcel    }
925130803Smarcel
926130803Smarcel    if (m_type == eLineStartSpecified)
927130803Smarcel    {
928130803Smarcel        s->Indent();
929130803Smarcel        s->Printf ("From line %lu", m_start_line);
930130803Smarcel        if (m_type == eLineEndSpecified)
931130803Smarcel            s->Printf ("to line %lu", m_end_line);
932130803Smarcel        else
933130803Smarcel            s->Printf ("to end");
934130803Smarcel        s->Printf (".\n");
935130803Smarcel    }
936130803Smarcel    else if (m_type == eLineEndSpecified)
937130803Smarcel    {
938130803Smarcel        s->Printf ("From start to line %ld.\n", m_end_line);
939130803Smarcel    }
940130803Smarcel
941130803Smarcel    if (m_type == eFunctionSpecified)
942130803Smarcel    {
943130803Smarcel        s->Indent();
944130803Smarcel        s->Printf ("Function: %s.\n", m_function_spec.c_str());
945130803Smarcel    }
946130803Smarcel
947130803Smarcel    if (m_type == eClassOrNamespaceSpecified)
948130803Smarcel    {
949130803Smarcel        s->Indent();
950130803Smarcel        s->Printf ("Class name: %s.\n", m_class_name.c_str());
951130803Smarcel    }
952130803Smarcel
953130803Smarcel    if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != NULL)
954130803Smarcel    {
955130803Smarcel        s->Indent();
956130803Smarcel        s->PutCString ("Address range: ");
957130803Smarcel        m_address_range_ap->Dump (s, m_target_sp.get(), Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
958130803Smarcel        s->PutCString ("\n");
959130803Smarcel    }
960130803Smarcel}
961130803Smarcel
962130803Smarcel//----------------------------------------------------------------------
963130803Smarcel//
964130803Smarcel//  SymbolContextList
965130803Smarcel//
966130803Smarcel//----------------------------------------------------------------------
967130803Smarcel
968130803Smarcel
969130803SmarcelSymbolContextList::SymbolContextList() :
970130803Smarcel    m_symbol_contexts()
971130803Smarcel{
972130803Smarcel}
973130803Smarcel
974130803SmarcelSymbolContextList::~SymbolContextList()
975130803Smarcel{
976130803Smarcel}
977130803Smarcel
978130803Smarcelvoid
979130803SmarcelSymbolContextList::Append(const SymbolContext& sc)
980130803Smarcel{
981130803Smarcel    m_symbol_contexts.push_back(sc);
982130803Smarcel}
983130803Smarcel
984130803Smarcelvoid
985130803SmarcelSymbolContextList::Append (const SymbolContextList& sc_list)
986130803Smarcel{
987130803Smarcel    collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
988130803Smarcel    for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
989130803Smarcel        m_symbol_contexts.push_back (*pos);
990130803Smarcel}
991130803Smarcel
992130803Smarcel
993130803Smarceluint32_t
994130803SmarcelSymbolContextList::AppendIfUnique (const SymbolContextList& sc_list, bool merge_symbol_into_function)
995130803Smarcel{
996130803Smarcel    uint32_t unique_sc_add_count = 0;
997130803Smarcel    collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
998130803Smarcel    for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
999130803Smarcel    {
1000130803Smarcel        if (AppendIfUnique (*pos, merge_symbol_into_function))
1001130803Smarcel            ++unique_sc_add_count;
1002130803Smarcel    }
1003130803Smarcel    return unique_sc_add_count;
1004130803Smarcel}
1005130803Smarcel
1006130803Smarcelbool
1007130803SmarcelSymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_into_function)
1008130803Smarcel{
1009130803Smarcel    collection::iterator pos, end = m_symbol_contexts.end();
1010130803Smarcel    for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1011130803Smarcel    {
1012130803Smarcel        if (*pos == sc)
1013130803Smarcel            return false;
1014130803Smarcel    }
1015130803Smarcel    if (merge_symbol_into_function
1016130803Smarcel        && sc.symbol    != NULL
1017130803Smarcel        && sc.comp_unit == NULL
1018130803Smarcel        && sc.function  == NULL
1019130803Smarcel        && sc.block     == NULL
1020130803Smarcel        && sc.line_entry.IsValid() == false)
1021130803Smarcel    {
1022130803Smarcel        if (sc.symbol->ValueIsAddress())
1023130803Smarcel        {
1024130803Smarcel            for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1025130803Smarcel            {
1026130803Smarcel                // Don't merge symbols into inlined function symbol contexts
1027130803Smarcel                if (pos->block && pos->block->GetContainingInlinedBlock())
1028130803Smarcel                    continue;
1029130803Smarcel
1030130803Smarcel                if (pos->function)
1031130803Smarcel                {
1032130803Smarcel                    if (pos->function->GetAddressRange().GetBaseAddress() == sc.symbol->GetAddress())
1033130803Smarcel                    {
1034130803Smarcel                        // Do we already have a function with this symbol?
1035130803Smarcel                        if (pos->symbol == sc.symbol)
1036130803Smarcel                            return false;
1037130803Smarcel                        if (pos->symbol == NULL)
1038130803Smarcel                        {
1039130803Smarcel                            pos->symbol = sc.symbol;
1040130803Smarcel                            return false;
1041130803Smarcel                        }
1042130803Smarcel                    }
1043130803Smarcel                }
1044130803Smarcel            }
1045130803Smarcel        }
1046130803Smarcel    }
1047130803Smarcel    m_symbol_contexts.push_back(sc);
1048130803Smarcel    return true;
1049130803Smarcel}
1050130803Smarcel
1051130803Smarcelbool
1052130803SmarcelSymbolContextList::MergeSymbolContextIntoFunctionContext (const SymbolContext& symbol_sc,
1053130803Smarcel                                                          uint32_t start_idx,
1054130803Smarcel                                                          uint32_t stop_idx)
1055130803Smarcel{
1056130803Smarcel    if (symbol_sc.symbol    != NULL
1057130803Smarcel        && symbol_sc.comp_unit == NULL
1058130803Smarcel        && symbol_sc.function  == NULL
1059130803Smarcel        && symbol_sc.block     == NULL
1060130803Smarcel        && symbol_sc.line_entry.IsValid() == false)
1061130803Smarcel    {
1062130803Smarcel        if (symbol_sc.symbol->ValueIsAddress())
1063130803Smarcel        {
1064130803Smarcel            const size_t end = std::min<size_t>(m_symbol_contexts.size(), stop_idx);
1065130803Smarcel            for (size_t i=start_idx; i<end; ++i)
1066130803Smarcel            {
1067130803Smarcel                const SymbolContext &function_sc = m_symbol_contexts[i];
1068130803Smarcel                // Don't merge symbols into inlined function symbol contexts
1069130803Smarcel                if (function_sc.block && function_sc.block->GetContainingInlinedBlock())
1070130803Smarcel                    continue;
1071130803Smarcel
1072130803Smarcel                if (function_sc.function)
1073130803Smarcel                {
1074130803Smarcel                    if (function_sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress())
1075130803Smarcel                    {
1076130803Smarcel                        // Do we already have a function with this symbol?
1077130803Smarcel                        if (function_sc.symbol == symbol_sc.symbol)
1078130803Smarcel                            return true; // Already have a symbol context with this symbol, return true
1079130803Smarcel
1080130803Smarcel                        if (function_sc.symbol == NULL)
1081130803Smarcel                        {
1082130803Smarcel                            // We successfully merged this symbol into an existing symbol context
1083130803Smarcel                            m_symbol_contexts[i].symbol = symbol_sc.symbol;
1084130803Smarcel                            return true;
1085130803Smarcel                        }
1086130803Smarcel                    }
1087130803Smarcel                }
1088130803Smarcel            }
1089130803Smarcel        }
1090130803Smarcel    }
1091130803Smarcel    return false;
1092130803Smarcel}
1093130803Smarcel
1094130803Smarcelvoid
1095130803SmarcelSymbolContextList::Clear()
1096130803Smarcel{
1097130803Smarcel    m_symbol_contexts.clear();
1098130803Smarcel}
1099130803Smarcel
1100130803Smarcelvoid
1101130803SmarcelSymbolContextList::Dump(Stream *s, Target *target) const
1102130803Smarcel{
1103130803Smarcel
1104130803Smarcel    *s << (void *)this << ": ";
1105130803Smarcel    s->Indent();
1106130803Smarcel    s->PutCString("SymbolContextList");
1107130803Smarcel    s->EOL();
1108130803Smarcel    s->IndentMore();
1109130803Smarcel
1110130803Smarcel    collection::const_iterator pos, end = m_symbol_contexts.end();
1111130803Smarcel    for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1112130803Smarcel    {
1113130803Smarcel        //pos->Dump(s, target);
1114130803Smarcel        pos->GetDescription(s, eDescriptionLevelVerbose, target);
1115130803Smarcel    }
1116130803Smarcel    s->IndentLess();
1117130803Smarcel}
1118130803Smarcel
1119130803Smarcelbool
1120130803SmarcelSymbolContextList::GetContextAtIndex(size_t idx, SymbolContext& sc) const
1121130803Smarcel{
1122130803Smarcel    if (idx < m_symbol_contexts.size())
1123130803Smarcel    {
1124130803Smarcel        sc = m_symbol_contexts[idx];
1125130803Smarcel        return true;
1126130803Smarcel    }
1127130803Smarcel    return false;
1128130803Smarcel}
1129130803Smarcel
1130130803Smarcelbool
1131130803SmarcelSymbolContextList::GetLastContext(SymbolContext& sc) const
1132130803Smarcel{
1133130803Smarcel    if (!m_symbol_contexts.empty())
1134130803Smarcel    {
1135130803Smarcel        sc = m_symbol_contexts.back();
1136130803Smarcel        return true;
1137130803Smarcel    }
1138130803Smarcel    return false;
1139130803Smarcel}
1140130803Smarcel
1141130803Smarcelbool
1142130803SmarcelSymbolContextList::RemoveContextAtIndex (size_t idx)
1143130803Smarcel{
1144130803Smarcel    if (idx < m_symbol_contexts.size())
1145130803Smarcel    {
1146130803Smarcel        m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
1147130803Smarcel        return true;
1148130803Smarcel    }
1149130803Smarcel    return false;
1150130803Smarcel}
1151130803Smarcel
1152130803Smarceluint32_t
1153130803SmarcelSymbolContextList::GetSize() const
1154130803Smarcel{
1155130803Smarcel    return m_symbol_contexts.size();
1156130803Smarcel}
1157130803Smarcel
1158130803Smarceluint32_t
1159130803SmarcelSymbolContextList::NumLineEntriesWithLine (uint32_t line) const
1160130803Smarcel{
1161130803Smarcel    uint32_t match_count = 0;
1162130803Smarcel    const size_t size = m_symbol_contexts.size();
1163130803Smarcel    for (size_t idx = 0; idx<size; ++idx)
1164130803Smarcel    {
1165130803Smarcel        if (m_symbol_contexts[idx].line_entry.line == line)
1166130803Smarcel            ++match_count;
1167130803Smarcel    }
1168130803Smarcel    return match_count;
1169130803Smarcel}
1170130803Smarcel
1171130803Smarcelvoid
1172130803SmarcelSymbolContextList::GetDescription(Stream *s,
1173130803Smarcel                                  lldb::DescriptionLevel level,
1174130803Smarcel                                  Target *target) const
1175130803Smarcel{
1176130803Smarcel    const size_t size = m_symbol_contexts.size();
1177130803Smarcel    for (size_t idx = 0; idx<size; ++idx)
1178130803Smarcel        m_symbol_contexts[idx].GetDescription (s, level, target);
1179130803Smarcel}
1180130803Smarcel
1181130803Smarcelbool
1182130803Smarcellldb_private::operator== (const SymbolContextList& lhs, const SymbolContextList& rhs)
1183130803Smarcel{
1184130803Smarcel    const uint32_t size = lhs.GetSize();
1185130803Smarcel    if (size != rhs.GetSize())
1186130803Smarcel        return false;
1187130803Smarcel
1188130803Smarcel    SymbolContext lhs_sc;
1189130803Smarcel    SymbolContext rhs_sc;
1190130803Smarcel    for (uint32_t i=0; i<size; ++i)
1191130803Smarcel    {
1192130803Smarcel        lhs.GetContextAtIndex(i, lhs_sc);
1193130803Smarcel        rhs.GetContextAtIndex(i, rhs_sc);
1194130803Smarcel        if (lhs_sc != rhs_sc)
1195130803Smarcel            return false;
1196130803Smarcel    }
1197130803Smarcel    return true;
1198130803Smarcel}
1199130803Smarcel
1200130803Smarcelbool
1201130803Smarcellldb_private::operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs)
1202130803Smarcel{
1203130803Smarcel    return !(lhs == rhs);
1204130803Smarcel}
1205130803Smarcel
1206130803Smarcel