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