1//===-- SymbolContext.cpp ---------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Symbol/SymbolContext.h"
11
12#include "lldb/Core/Log.h"
13#include "lldb/Core/Module.h"
14#include "lldb/Core/ModuleSpec.h"
15#include "lldb/Host/Host.h"
16#include "lldb/Interpreter/Args.h"
17#include "lldb/Symbol/Block.h"
18#include "lldb/Symbol/ClangASTContext.h"
19#include "lldb/Symbol/CompileUnit.h"
20#include "lldb/Symbol/ObjectFile.h"
21#include "lldb/Symbol/Symbol.h"
22#include "lldb/Symbol/SymbolFile.h"
23#include "lldb/Symbol/SymbolVendor.h"
24#include "lldb/Target/Target.h"
25
26using namespace lldb;
27using namespace lldb_private;
28
29SymbolContext::SymbolContext() :
30    target_sp   (),
31    module_sp   (),
32    comp_unit   (NULL),
33    function    (NULL),
34    block       (NULL),
35    line_entry  (),
36    symbol      (NULL)
37{
38}
39
40SymbolContext::SymbolContext(const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
41    target_sp   (),
42    module_sp   (m),
43    comp_unit   (cu),
44    function    (f),
45    block       (b),
46    line_entry  (),
47    symbol      (s)
48{
49    if (le)
50        line_entry = *le;
51}
52
53SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) :
54    target_sp   (t),
55    module_sp   (m),
56    comp_unit   (cu),
57    function    (f),
58    block       (b),
59    line_entry  (),
60    symbol      (s)
61{
62    if (le)
63        line_entry = *le;
64}
65
66SymbolContext::SymbolContext(const SymbolContext& rhs) :
67    target_sp   (rhs.target_sp),
68    module_sp   (rhs.module_sp),
69    comp_unit   (rhs.comp_unit),
70    function    (rhs.function),
71    block       (rhs.block),
72    line_entry  (rhs.line_entry),
73    symbol      (rhs.symbol)
74{
75}
76
77
78SymbolContext::SymbolContext (SymbolContextScope *sc_scope) :
79    target_sp   (),
80    module_sp   (),
81    comp_unit   (NULL),
82    function    (NULL),
83    block       (NULL),
84    line_entry  (),
85    symbol      (NULL)
86{
87    sc_scope->CalculateSymbolContext (this);
88}
89
90SymbolContext::~SymbolContext ()
91{
92}
93
94const SymbolContext&
95SymbolContext::operator= (const SymbolContext& rhs)
96{
97    if (this != &rhs)
98    {
99        target_sp   = rhs.target_sp;
100        module_sp   = rhs.module_sp;
101        comp_unit   = rhs.comp_unit;
102        function    = rhs.function;
103        block       = rhs.block;
104        line_entry  = rhs.line_entry;
105        symbol      = rhs.symbol;
106    }
107    return *this;
108}
109
110void
111SymbolContext::Clear(bool clear_target)
112{
113    if (clear_target)
114        target_sp.reset();
115    module_sp.reset();
116    comp_unit   = NULL;
117    function    = NULL;
118    block       = NULL;
119    line_entry.Clear();
120    symbol      = NULL;
121}
122
123bool
124SymbolContext::DumpStopContext
125(
126    Stream *s,
127    ExecutionContextScope *exe_scope,
128    const Address &addr,
129    bool show_fullpaths,
130    bool show_module,
131    bool show_inlined_frames
132) const
133{
134    bool dumped_something = false;
135    if (show_module && module_sp)
136    {
137        if (show_fullpaths)
138            *s << module_sp->GetFileSpec();
139        else
140            *s << module_sp->GetFileSpec().GetFilename();
141        s->PutChar('`');
142        dumped_something = true;
143    }
144
145    if (function != NULL)
146    {
147        SymbolContext inline_parent_sc;
148        Address inline_parent_addr;
149        if (function->GetMangled().GetName())
150        {
151            dumped_something = true;
152            function->GetMangled().GetName().Dump(s);
153        }
154
155        if (addr.IsValid())
156        {
157            const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetOffset();
158            if (function_offset)
159            {
160                dumped_something = true;
161                s->Printf(" + %" PRIu64, function_offset);
162            }
163        }
164
165        if (GetParentOfInlinedScope (addr, inline_parent_sc, inline_parent_addr))
166        {
167            dumped_something = true;
168            Block *inlined_block = block->GetContainingInlinedBlock();
169            const InlineFunctionInfo* inlined_block_info = inlined_block->GetInlinedFunctionInfo();
170            s->Printf (" [inlined] %s", inlined_block_info->GetName().GetCString());
171
172            lldb_private::AddressRange block_range;
173            if (inlined_block->GetRangeContainingAddress(addr, block_range))
174            {
175                const addr_t inlined_function_offset = addr.GetOffset() - block_range.GetBaseAddress().GetOffset();
176                if (inlined_function_offset)
177                {
178                    s->Printf(" + %" PRIu64, inlined_function_offset);
179                }
180            }
181            const Declaration &call_site = inlined_block_info->GetCallSite();
182            if (call_site.IsValid())
183            {
184                s->PutCString(" at ");
185                call_site.DumpStopContext (s, show_fullpaths);
186            }
187            if (show_inlined_frames)
188            {
189                s->EOL();
190                s->Indent();
191                return inline_parent_sc.DumpStopContext (s, exe_scope, inline_parent_addr, show_fullpaths, show_module, show_inlined_frames);
192            }
193        }
194        else
195        {
196            if (line_entry.IsValid())
197            {
198                dumped_something = true;
199                s->PutCString(" at ");
200                if (line_entry.DumpStopContext(s, show_fullpaths))
201                    dumped_something = true;
202            }
203        }
204    }
205    else if (symbol != NULL)
206    {
207        if (symbol->GetMangled().GetName())
208        {
209            dumped_something = true;
210            if (symbol->GetType() == eSymbolTypeTrampoline)
211                s->PutCString("symbol stub for: ");
212            symbol->GetMangled().GetName().Dump(s);
213        }
214
215        if (addr.IsValid() && symbol->ValueIsAddress())
216        {
217            const addr_t symbol_offset = addr.GetOffset() - symbol->GetAddress().GetOffset();
218            if (symbol_offset)
219            {
220                dumped_something = true;
221                s->Printf(" + %" PRIu64, symbol_offset);
222            }
223        }
224    }
225    else if (addr.IsValid())
226    {
227        addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress);
228        dumped_something = true;
229    }
230    return dumped_something;
231}
232
233void
234SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target) const
235{
236    if (module_sp)
237    {
238        s->Indent("     Module: file = \"");
239        module_sp->GetFileSpec().Dump(s);
240        *s << '"';
241        if (module_sp->GetArchitecture().IsValid())
242            s->Printf (", arch = \"%s\"", module_sp->GetArchitecture().GetArchitectureName());
243        s->EOL();
244    }
245
246    if (comp_unit != NULL)
247    {
248        s->Indent("CompileUnit: ");
249        comp_unit->GetDescription (s, level);
250        s->EOL();
251    }
252
253    if (function != NULL)
254    {
255        s->Indent("   Function: ");
256        function->GetDescription (s, level, target);
257        s->EOL();
258
259        Type *func_type = function->GetType();
260        if (func_type)
261        {
262            s->Indent("   FuncType: ");
263            func_type->GetDescription (s, level, false);
264            s->EOL();
265        }
266    }
267
268    if (block != NULL)
269    {
270        std::vector<Block *> blocks;
271        blocks.push_back (block);
272        Block *parent_block = block->GetParent();
273
274        while (parent_block)
275        {
276            blocks.push_back (parent_block);
277            parent_block = parent_block->GetParent();
278        }
279        std::vector<Block *>::reverse_iterator pos;
280        std::vector<Block *>::reverse_iterator begin = blocks.rbegin();
281        std::vector<Block *>::reverse_iterator end = blocks.rend();
282        for (pos = begin; pos != end; ++pos)
283        {
284            if (pos == begin)
285                s->Indent("     Blocks: ");
286            else
287                s->Indent("             ");
288            (*pos)->GetDescription(s, function, level, target);
289            s->EOL();
290        }
291    }
292
293    if (line_entry.IsValid())
294    {
295        s->Indent("  LineEntry: ");
296        line_entry.GetDescription (s, level, comp_unit, target, false);
297        s->EOL();
298    }
299
300    if (symbol != NULL)
301    {
302        s->Indent("     Symbol: ");
303        symbol->GetDescription(s, level, target);
304        s->EOL();
305    }
306}
307
308uint32_t
309SymbolContext::GetResolvedMask () const
310{
311    uint32_t resolved_mask = 0;
312    if (target_sp)              resolved_mask |= eSymbolContextTarget;
313    if (module_sp)              resolved_mask |= eSymbolContextModule;
314    if (comp_unit)              resolved_mask |= eSymbolContextCompUnit;
315    if (function)               resolved_mask |= eSymbolContextFunction;
316    if (block)                  resolved_mask |= eSymbolContextBlock;
317    if (line_entry.IsValid())   resolved_mask |= eSymbolContextLineEntry;
318    if (symbol)                 resolved_mask |= eSymbolContextSymbol;
319    return resolved_mask;
320}
321
322void
323SymbolContext::Dump(Stream *s, Target *target) const
324{
325    *s << (void *)this << ": ";
326    s->Indent();
327    s->PutCString("SymbolContext");
328    s->IndentMore();
329    s->EOL();
330    s->IndentMore();
331    s->Indent();
332    *s << "Module       = " << (void *)module_sp.get() << ' ';
333    if (module_sp)
334        module_sp->GetFileSpec().Dump(s);
335    s->EOL();
336    s->Indent();
337    *s << "CompileUnit  = " << (void *)comp_unit;
338    if (comp_unit != NULL)
339        *s << " {0x" << comp_unit->GetID() << "} " << *(static_cast<FileSpec*> (comp_unit));
340    s->EOL();
341    s->Indent();
342    *s << "Function     = " << (void *)function;
343    if (function != NULL)
344    {
345        *s << " {0x" << function->GetID() << "} " << function->GetType()->GetName() << ", address-range = ";
346        function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress);
347        s->EOL();
348        s->Indent();
349        Type* func_type = function->GetType();
350        if (func_type)
351        {
352            *s << "        Type = ";
353            func_type->Dump (s, false);
354        }
355    }
356    s->EOL();
357    s->Indent();
358    *s << "Block        = " << (void *)block;
359    if (block != NULL)
360        *s << " {0x" << block->GetID() << '}';
361    // Dump the block and pass it a negative depth to we print all the parent blocks
362    //if (block != NULL)
363    //  block->Dump(s, function->GetFileAddress(), INT_MIN);
364    s->EOL();
365    s->Indent();
366    *s << "LineEntry    = ";
367    line_entry.Dump (s, target, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true);
368    s->EOL();
369    s->Indent();
370    *s << "Symbol       = " << (void *)symbol;
371    if (symbol != NULL && symbol->GetMangled())
372        *s << ' ' << symbol->GetMangled().GetName().AsCString();
373    s->EOL();
374    s->IndentLess();
375    s->IndentLess();
376}
377
378bool
379lldb_private::operator== (const SymbolContext& lhs, const SymbolContext& rhs)
380{
381    return  lhs.function == rhs.function
382            && lhs.symbol == rhs.symbol
383            && lhs.module_sp.get() == rhs.module_sp.get()
384            && lhs.comp_unit == rhs.comp_unit
385            && lhs.target_sp.get() == rhs.target_sp.get()
386            && LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0;
387}
388
389bool
390lldb_private::operator!= (const SymbolContext& lhs, const SymbolContext& rhs)
391{
392    return  lhs.function != rhs.function
393            || lhs.symbol != rhs.symbol
394            || lhs.module_sp.get() != rhs.module_sp.get()
395            || lhs.comp_unit != rhs.comp_unit
396            || lhs.target_sp.get() != rhs.target_sp.get()
397            || LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0;
398}
399
400bool
401SymbolContext::GetAddressRange (uint32_t scope,
402                                uint32_t range_idx,
403                                bool use_inline_block_range,
404                                AddressRange &range) const
405{
406    if ((scope & eSymbolContextLineEntry) && line_entry.IsValid())
407    {
408        range = line_entry.range;
409        return true;
410    }
411
412    if ((scope & eSymbolContextBlock) && (block != NULL))
413    {
414        if (use_inline_block_range)
415        {
416            Block *inline_block = block->GetContainingInlinedBlock();
417            if (inline_block)
418                return inline_block->GetRangeAtIndex (range_idx, range);
419        }
420        else
421        {
422            return block->GetRangeAtIndex (range_idx, range);
423        }
424    }
425
426    if ((scope & eSymbolContextFunction) && (function != NULL))
427    {
428        if (range_idx == 0)
429        {
430            range = function->GetAddressRange();
431            return true;
432        }
433    }
434
435    if ((scope & eSymbolContextSymbol) && (symbol != NULL))
436    {
437        if (range_idx == 0)
438        {
439            if (symbol->ValueIsAddress())
440            {
441                range.GetBaseAddress() = symbol->GetAddress();
442                range.SetByteSize (symbol->GetByteSize());
443                return true;
444            }
445        }
446    }
447    range.Clear();
448    return false;
449}
450
451bool
452SymbolContext::GetParentOfInlinedScope (const Address &curr_frame_pc,
453                                        SymbolContext &next_frame_sc,
454                                        Address &next_frame_pc) const
455{
456    next_frame_sc.Clear(false);
457    next_frame_pc.Clear();
458
459    if (block)
460    {
461        //const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress();
462
463        // In order to get the parent of an inlined function we first need to
464        // see if we are in an inlined block as "this->block" could be an
465        // inlined block, or a parent of "block" could be. So lets check if
466        // this block or one of this blocks parents is an inlined function.
467        Block *curr_inlined_block = block->GetContainingInlinedBlock();
468        if (curr_inlined_block)
469        {
470            // "this->block" is contained in an inline function block, so to
471            // get the scope above the inlined block, we get the parent of the
472            // inlined block itself
473            Block *next_frame_block = curr_inlined_block->GetParent();
474            // Now calculate the symbol context of the containing block
475            next_frame_block->CalculateSymbolContext (&next_frame_sc);
476
477            // If we get here we weren't able to find the return line entry using the nesting of the blocks and
478            // the line table.  So just use the call site info from our inlined block.
479
480            AddressRange range;
481            if (curr_inlined_block->GetRangeContainingAddress (curr_frame_pc, range))
482            {
483                // To see there this new frame block it, we need to look at the
484                // call site information from
485                const InlineFunctionInfo* curr_inlined_block_inlined_info = curr_inlined_block->GetInlinedFunctionInfo();
486                next_frame_pc = range.GetBaseAddress();
487                next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc;
488                next_frame_sc.line_entry.file = curr_inlined_block_inlined_info->GetCallSite().GetFile();
489                next_frame_sc.line_entry.line = curr_inlined_block_inlined_info->GetCallSite().GetLine();
490                next_frame_sc.line_entry.column = curr_inlined_block_inlined_info->GetCallSite().GetColumn();
491                return true;
492            }
493            else
494            {
495                Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
496
497                if (log)
498                {
499                    log->Printf ("warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64,
500                                 curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress());
501                }
502#ifdef LLDB_CONFIGURATION_DEBUG
503                else
504                {
505                    ObjectFile *objfile = NULL;
506                    if (module_sp)
507                    {
508                        SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
509                        if (symbol_vendor)
510                        {
511                            SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
512                            if (symbol_file)
513                                objfile = symbol_file->GetObjectFile();
514                        }
515                    }
516                    if (objfile)
517                    {
518                        Host::SystemLog (Host::eSystemLogWarning,
519                                         "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 " in %s\n",
520                                         curr_inlined_block->GetID(),
521                                         curr_frame_pc.GetFileAddress(),
522                                         objfile->GetFileSpec().GetPath().c_str());
523                    }
524                    else
525                    {
526                        Host::SystemLog (Host::eSystemLogWarning,
527                                         "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 "\n",
528                                         curr_inlined_block->GetID(),
529                                         curr_frame_pc.GetFileAddress());
530                    }
531                }
532#endif
533            }
534        }
535    }
536
537    return false;
538}
539
540Block *
541SymbolContext::GetFunctionBlock ()
542{
543    if (function)
544    {
545        if (block)
546        {
547            // If this symbol context has a block, check to see if this block
548            // is itself, or is contained within a block with inlined function
549            // information. If so, then the inlined block is the block that
550            // defines the function.
551            Block *inlined_block = block->GetContainingInlinedBlock();
552            if (inlined_block)
553                return inlined_block;
554
555            // The block in this symbol context is not inside an inlined
556            // block, so the block that defines the function is the function's
557            // top level block, which is returned below.
558        }
559
560        // There is no block information in this symbol context, so we must
561        // assume that the block that is desired is the top level block of
562        // the function itself.
563        return &function->GetBlock(true);
564    }
565    return NULL;
566}
567
568bool
569SymbolContext::GetFunctionMethodInfo (lldb::LanguageType &language,
570                                      bool &is_instance_method,
571                                      ConstString &language_object_name)
572
573
574{
575    Block *function_block = GetFunctionBlock ();
576    if (function_block)
577    {
578        clang::DeclContext *decl_context = function_block->GetClangDeclContext();
579
580        if (decl_context)
581        {
582            return ClangASTContext::GetClassMethodInfoForDeclContext (decl_context,
583                                                                      language,
584                                                                      is_instance_method,
585                                                                      language_object_name);
586        }
587    }
588    language = eLanguageTypeUnknown;
589    is_instance_method = false;
590    language_object_name.Clear();
591    return false;
592}
593
594ConstString
595SymbolContext::GetFunctionName (Mangled::NamePreference preference) const
596{
597    if (function)
598    {
599        if (block)
600        {
601            Block *inlined_block = block->GetContainingInlinedBlock();
602
603            if (inlined_block)
604            {
605                const InlineFunctionInfo *inline_info = inlined_block->GetInlinedFunctionInfo();
606                if (inline_info)
607                    return inline_info->GetName();
608            }
609        }
610        return function->GetMangled().GetName(preference);
611    }
612    else if (symbol && symbol->ValueIsAddress())
613    {
614        return symbol->GetMangled().GetName(preference);
615    }
616    else
617    {
618        // No function, return an empty string.
619        return ConstString();
620    }
621}
622
623LineEntry
624SymbolContext::GetFunctionStartLineEntry () const
625{
626    LineEntry line_entry;
627    Address start_addr;
628    if (block)
629    {
630        Block *inlined_block = block->GetContainingInlinedBlock();
631        if (inlined_block)
632        {
633            if (inlined_block->GetStartAddress (start_addr))
634            {
635                if (start_addr.CalculateSymbolContextLineEntry (line_entry))
636                    return line_entry;
637            }
638            return LineEntry();
639        }
640    }
641
642    if (function)
643    {
644        if (function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry(line_entry))
645            return line_entry;
646    }
647    return LineEntry();
648}
649
650//----------------------------------------------------------------------
651//
652//  SymbolContextSpecifier
653//
654//----------------------------------------------------------------------
655
656SymbolContextSpecifier::SymbolContextSpecifier (const TargetSP &target_sp) :
657    m_target_sp (target_sp),
658    m_module_spec (),
659    m_module_sp (),
660    m_file_spec_ap (),
661    m_start_line (0),
662    m_end_line (0),
663    m_function_spec (),
664    m_class_name (),
665    m_address_range_ap (),
666    m_type (eNothingSpecified)
667{
668}
669
670SymbolContextSpecifier::~SymbolContextSpecifier()
671{
672}
673
674bool
675SymbolContextSpecifier::AddLineSpecification (uint32_t line_no, SpecificationType type)
676{
677    bool return_value = true;
678    switch (type)
679    {
680    case eNothingSpecified:
681        Clear();
682        break;
683    case eLineStartSpecified:
684        m_start_line = line_no;
685        m_type |= eLineStartSpecified;
686        break;
687    case eLineEndSpecified:
688        m_end_line = line_no;
689        m_type |= eLineEndSpecified;
690        break;
691    default:
692        return_value = false;
693        break;
694    }
695    return return_value;
696}
697
698bool
699SymbolContextSpecifier::AddSpecification (const char *spec_string, SpecificationType type)
700{
701    bool return_value = true;
702    switch (type)
703    {
704    case eNothingSpecified:
705        Clear();
706        break;
707    case eModuleSpecified:
708        {
709            // See if we can find the Module, if so stick it in the SymbolContext.
710            FileSpec module_file_spec(spec_string, false);
711            ModuleSpec module_spec (module_file_spec);
712            lldb::ModuleSP module_sp (m_target_sp->GetImages().FindFirstModule (module_spec));
713            m_type |= eModuleSpecified;
714            if (module_sp)
715                m_module_sp = module_sp;
716            else
717                m_module_spec.assign (spec_string);
718        }
719        break;
720    case eFileSpecified:
721        // CompUnits can't necessarily be resolved here, since an inlined function might show up in
722        // a number of CompUnits.  Instead we just convert to a FileSpec and store it away.
723        m_file_spec_ap.reset (new FileSpec (spec_string, false));
724        m_type |= eFileSpecified;
725        break;
726    case eLineStartSpecified:
727        m_start_line = Args::StringToSInt32(spec_string, 0, 0, &return_value);
728        if (return_value)
729            m_type |= eLineStartSpecified;
730        break;
731    case eLineEndSpecified:
732        m_end_line = Args::StringToSInt32(spec_string, 0, 0, &return_value);
733        if (return_value)
734            m_type |= eLineEndSpecified;
735        break;
736    case eFunctionSpecified:
737        m_function_spec.assign(spec_string);
738        m_type |= eFunctionSpecified;
739        break;
740    case eClassOrNamespaceSpecified:
741        Clear();
742        m_class_name.assign (spec_string);
743        m_type = eClassOrNamespaceSpecified;
744        break;
745    case eAddressRangeSpecified:
746        // Not specified yet...
747        break;
748    }
749
750    return return_value;
751}
752
753void
754SymbolContextSpecifier::Clear()
755{
756    m_module_spec.clear();
757    m_file_spec_ap.reset();
758    m_function_spec.clear();
759    m_class_name.clear();
760    m_start_line = 0;
761    m_end_line = 0;
762    m_address_range_ap.reset();
763
764    m_type = eNothingSpecified;
765}
766
767bool
768SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc)
769{
770    if (m_type == eNothingSpecified)
771        return true;
772
773    if (m_target_sp.get() != sc.target_sp.get())
774        return false;
775
776    if (m_type & eModuleSpecified)
777    {
778        if (sc.module_sp)
779        {
780            if (m_module_sp.get() != NULL)
781            {
782                if (m_module_sp.get() != sc.module_sp.get())
783                    return false;
784            }
785            else
786            {
787                FileSpec module_file_spec (m_module_spec.c_str(), false);
788                if (!FileSpec::Equal (module_file_spec, sc.module_sp->GetFileSpec(), false))
789                    return false;
790            }
791        }
792    }
793    if (m_type & eFileSpecified)
794    {
795        if (m_file_spec_ap.get())
796        {
797            // If we don't have a block or a comp_unit, then we aren't going to match a source file.
798            if (sc.block == NULL && sc.comp_unit == NULL)
799                return false;
800
801            // Check if the block is present, and if so is it inlined:
802            bool was_inlined = false;
803            if (sc.block != NULL)
804            {
805                const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
806                if (inline_info != NULL)
807                {
808                    was_inlined = true;
809                    if (!FileSpec::Equal (inline_info->GetDeclaration().GetFile(), *(m_file_spec_ap.get()), false))
810                        return false;
811                }
812            }
813
814            // Next check the comp unit, but only if the SymbolContext was not inlined.
815            if (!was_inlined && sc.comp_unit != NULL)
816            {
817                if (!FileSpec::Equal (*(sc.comp_unit), *(m_file_spec_ap.get()), false))
818                    return false;
819            }
820        }
821    }
822    if (m_type & eLineStartSpecified
823        || m_type & eLineEndSpecified)
824    {
825        if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line)
826            return false;
827    }
828
829    if (m_type & eFunctionSpecified)
830    {
831        // First check the current block, and if it is inlined, get the inlined function name:
832        bool was_inlined = false;
833        ConstString func_name(m_function_spec.c_str());
834
835        if (sc.block != NULL)
836        {
837            const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo();
838            if (inline_info != NULL)
839            {
840                was_inlined = true;
841                const Mangled &name = inline_info->GetMangled();
842                if (!name.NameMatches (func_name))
843                    return false;
844            }
845        }
846        //  If it wasn't inlined, check the name in the function or symbol:
847        if (!was_inlined)
848        {
849            if (sc.function != NULL)
850            {
851                if (!sc.function->GetMangled().NameMatches(func_name))
852                    return false;
853            }
854            else if (sc.symbol != NULL)
855            {
856                if (!sc.symbol->GetMangled().NameMatches(func_name))
857                    return false;
858            }
859        }
860
861
862    }
863
864    return true;
865}
866
867bool
868SymbolContextSpecifier::AddressMatches(lldb::addr_t addr)
869{
870    if (m_type & eAddressRangeSpecified)
871    {
872
873    }
874    else
875    {
876        Address match_address (addr, NULL);
877        SymbolContext sc;
878        m_target_sp->GetImages().ResolveSymbolContextForAddress(match_address, eSymbolContextEverything, sc);
879        return SymbolContextMatches(sc);
880    }
881    return true;
882}
883
884void
885SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level) const
886{
887    char path_str[PATH_MAX + 1];
888
889    if (m_type == eNothingSpecified)
890    {
891        s->Printf ("Nothing specified.\n");
892    }
893
894    if (m_type == eModuleSpecified)
895    {
896        s->Indent();
897        if (m_module_sp)
898        {
899            m_module_sp->GetFileSpec().GetPath (path_str, PATH_MAX);
900            s->Printf ("Module: %s\n", path_str);
901        }
902        else
903            s->Printf ("Module: %s\n", m_module_spec.c_str());
904    }
905
906    if (m_type == eFileSpecified  && m_file_spec_ap.get() != NULL)
907    {
908        m_file_spec_ap->GetPath (path_str, PATH_MAX);
909        s->Indent();
910        s->Printf ("File: %s", path_str);
911        if (m_type == eLineStartSpecified)
912        {
913            s->Printf (" from line %lu", m_start_line);
914            if (m_type == eLineEndSpecified)
915                s->Printf ("to line %lu", m_end_line);
916            else
917                s->Printf ("to end");
918        }
919        else if (m_type == eLineEndSpecified)
920        {
921            s->Printf (" from start to line %ld", m_end_line);
922        }
923        s->Printf (".\n");
924    }
925
926    if (m_type == eLineStartSpecified)
927    {
928        s->Indent();
929        s->Printf ("From line %lu", m_start_line);
930        if (m_type == eLineEndSpecified)
931            s->Printf ("to line %lu", m_end_line);
932        else
933            s->Printf ("to end");
934        s->Printf (".\n");
935    }
936    else if (m_type == eLineEndSpecified)
937    {
938        s->Printf ("From start to line %ld.\n", m_end_line);
939    }
940
941    if (m_type == eFunctionSpecified)
942    {
943        s->Indent();
944        s->Printf ("Function: %s.\n", m_function_spec.c_str());
945    }
946
947    if (m_type == eClassOrNamespaceSpecified)
948    {
949        s->Indent();
950        s->Printf ("Class name: %s.\n", m_class_name.c_str());
951    }
952
953    if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != NULL)
954    {
955        s->Indent();
956        s->PutCString ("Address range: ");
957        m_address_range_ap->Dump (s, m_target_sp.get(), Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress);
958        s->PutCString ("\n");
959    }
960}
961
962//----------------------------------------------------------------------
963//
964//  SymbolContextList
965//
966//----------------------------------------------------------------------
967
968
969SymbolContextList::SymbolContextList() :
970    m_symbol_contexts()
971{
972}
973
974SymbolContextList::~SymbolContextList()
975{
976}
977
978void
979SymbolContextList::Append(const SymbolContext& sc)
980{
981    m_symbol_contexts.push_back(sc);
982}
983
984void
985SymbolContextList::Append (const SymbolContextList& sc_list)
986{
987    collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
988    for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
989        m_symbol_contexts.push_back (*pos);
990}
991
992
993uint32_t
994SymbolContextList::AppendIfUnique (const SymbolContextList& sc_list, bool merge_symbol_into_function)
995{
996    uint32_t unique_sc_add_count = 0;
997    collection::const_iterator pos, end = sc_list.m_symbol_contexts.end();
998    for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos)
999    {
1000        if (AppendIfUnique (*pos, merge_symbol_into_function))
1001            ++unique_sc_add_count;
1002    }
1003    return unique_sc_add_count;
1004}
1005
1006bool
1007SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_into_function)
1008{
1009    collection::iterator pos, end = m_symbol_contexts.end();
1010    for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1011    {
1012        if (*pos == sc)
1013            return false;
1014    }
1015    if (merge_symbol_into_function
1016        && sc.symbol    != NULL
1017        && sc.comp_unit == NULL
1018        && sc.function  == NULL
1019        && sc.block     == NULL
1020        && sc.line_entry.IsValid() == false)
1021    {
1022        if (sc.symbol->ValueIsAddress())
1023        {
1024            for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1025            {
1026                // Don't merge symbols into inlined function symbol contexts
1027                if (pos->block && pos->block->GetContainingInlinedBlock())
1028                    continue;
1029
1030                if (pos->function)
1031                {
1032                    if (pos->function->GetAddressRange().GetBaseAddress() == sc.symbol->GetAddress())
1033                    {
1034                        // Do we already have a function with this symbol?
1035                        if (pos->symbol == sc.symbol)
1036                            return false;
1037                        if (pos->symbol == NULL)
1038                        {
1039                            pos->symbol = sc.symbol;
1040                            return false;
1041                        }
1042                    }
1043                }
1044            }
1045        }
1046    }
1047    m_symbol_contexts.push_back(sc);
1048    return true;
1049}
1050
1051bool
1052SymbolContextList::MergeSymbolContextIntoFunctionContext (const SymbolContext& symbol_sc,
1053                                                          uint32_t start_idx,
1054                                                          uint32_t stop_idx)
1055{
1056    if (symbol_sc.symbol    != NULL
1057        && symbol_sc.comp_unit == NULL
1058        && symbol_sc.function  == NULL
1059        && symbol_sc.block     == NULL
1060        && symbol_sc.line_entry.IsValid() == false)
1061    {
1062        if (symbol_sc.symbol->ValueIsAddress())
1063        {
1064            const size_t end = std::min<size_t>(m_symbol_contexts.size(), stop_idx);
1065            for (size_t i=start_idx; i<end; ++i)
1066            {
1067                const SymbolContext &function_sc = m_symbol_contexts[i];
1068                // Don't merge symbols into inlined function symbol contexts
1069                if (function_sc.block && function_sc.block->GetContainingInlinedBlock())
1070                    continue;
1071
1072                if (function_sc.function)
1073                {
1074                    if (function_sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddress())
1075                    {
1076                        // Do we already have a function with this symbol?
1077                        if (function_sc.symbol == symbol_sc.symbol)
1078                            return true; // Already have a symbol context with this symbol, return true
1079
1080                        if (function_sc.symbol == NULL)
1081                        {
1082                            // We successfully merged this symbol into an existing symbol context
1083                            m_symbol_contexts[i].symbol = symbol_sc.symbol;
1084                            return true;
1085                        }
1086                    }
1087                }
1088            }
1089        }
1090    }
1091    return false;
1092}
1093
1094void
1095SymbolContextList::Clear()
1096{
1097    m_symbol_contexts.clear();
1098}
1099
1100void
1101SymbolContextList::Dump(Stream *s, Target *target) const
1102{
1103
1104    *s << (void *)this << ": ";
1105    s->Indent();
1106    s->PutCString("SymbolContextList");
1107    s->EOL();
1108    s->IndentMore();
1109
1110    collection::const_iterator pos, end = m_symbol_contexts.end();
1111    for (pos = m_symbol_contexts.begin(); pos != end; ++pos)
1112    {
1113        //pos->Dump(s, target);
1114        pos->GetDescription(s, eDescriptionLevelVerbose, target);
1115    }
1116    s->IndentLess();
1117}
1118
1119bool
1120SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext& sc) const
1121{
1122    if (idx < m_symbol_contexts.size())
1123    {
1124        sc = m_symbol_contexts[idx];
1125        return true;
1126    }
1127    return false;
1128}
1129
1130bool
1131SymbolContextList::GetLastContext(SymbolContext& sc) const
1132{
1133    if (!m_symbol_contexts.empty())
1134    {
1135        sc = m_symbol_contexts.back();
1136        return true;
1137    }
1138    return false;
1139}
1140
1141bool
1142SymbolContextList::RemoveContextAtIndex (size_t idx)
1143{
1144    if (idx < m_symbol_contexts.size())
1145    {
1146        m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
1147        return true;
1148    }
1149    return false;
1150}
1151
1152uint32_t
1153SymbolContextList::GetSize() const
1154{
1155    return m_symbol_contexts.size();
1156}
1157
1158uint32_t
1159SymbolContextList::NumLineEntriesWithLine (uint32_t line) const
1160{
1161    uint32_t match_count = 0;
1162    const size_t size = m_symbol_contexts.size();
1163    for (size_t idx = 0; idx<size; ++idx)
1164    {
1165        if (m_symbol_contexts[idx].line_entry.line == line)
1166            ++match_count;
1167    }
1168    return match_count;
1169}
1170
1171void
1172SymbolContextList::GetDescription(Stream *s,
1173                                  lldb::DescriptionLevel level,
1174                                  Target *target) const
1175{
1176    const size_t size = m_symbol_contexts.size();
1177    for (size_t idx = 0; idx<size; ++idx)
1178        m_symbol_contexts[idx].GetDescription (s, level, target);
1179}
1180
1181bool
1182lldb_private::operator== (const SymbolContextList& lhs, const SymbolContextList& rhs)
1183{
1184    const uint32_t size = lhs.GetSize();
1185    if (size != rhs.GetSize())
1186        return false;
1187
1188    SymbolContext lhs_sc;
1189    SymbolContext rhs_sc;
1190    for (uint32_t i=0; i<size; ++i)
1191    {
1192        lhs.GetContextAtIndex(i, lhs_sc);
1193        rhs.GetContextAtIndex(i, rhs_sc);
1194        if (lhs_sc != rhs_sc)
1195            return false;
1196    }
1197    return true;
1198}
1199
1200bool
1201lldb_private::operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs)
1202{
1203    return !(lhs == rhs);
1204}
1205
1206