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 
26 using namespace lldb;
27 using namespace lldb_private;
28 
SymbolContext()29 SymbolContext::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 
SymbolContext(const ModuleSP & m,CompileUnit * cu,Function * f,Block * b,LineEntry * le,Symbol * s)40 SymbolContext::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 
SymbolContext(const TargetSP & t,const ModuleSP & m,CompileUnit * cu,Function * f,Block * b,LineEntry * le,Symbol * s)53 SymbolContext::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 
SymbolContext(const SymbolContext & rhs)66 SymbolContext::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 
SymbolContext(SymbolContextScope * sc_scope)78 SymbolContext::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 
~SymbolContext()90 SymbolContext::~SymbolContext ()
91 {
92 }
93 
94 const SymbolContext&
operator =(const SymbolContext & rhs)95 SymbolContext::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 
110 void
Clear(bool clear_target)111 SymbolContext::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 
123 bool
DumpStopContext(Stream * s,ExecutionContextScope * exe_scope,const Address & addr,bool show_fullpaths,bool show_module,bool show_inlined_frames) const124 SymbolContext::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 
233 void
GetDescription(Stream * s,lldb::DescriptionLevel level,Target * target) const234 SymbolContext::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 
308 uint32_t
GetResolvedMask() const309 SymbolContext::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 
322 void
Dump(Stream * s,Target * target) const323 SymbolContext::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 
378 bool
operator ==(const SymbolContext & lhs,const SymbolContext & rhs)379 lldb_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 
389 bool
operator !=(const SymbolContext & lhs,const SymbolContext & rhs)390 lldb_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 
400 bool
GetAddressRange(uint32_t scope,uint32_t range_idx,bool use_inline_block_range,AddressRange & range) const401 SymbolContext::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 
451 bool
GetParentOfInlinedScope(const Address & curr_frame_pc,SymbolContext & next_frame_sc,Address & next_frame_pc) const452 SymbolContext::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 
540 Block *
GetFunctionBlock()541 SymbolContext::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 
568 bool
GetFunctionMethodInfo(lldb::LanguageType & language,bool & is_instance_method,ConstString & language_object_name)569 SymbolContext::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 
594 ConstString
GetFunctionName(Mangled::NamePreference preference) const595 SymbolContext::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 
623 LineEntry
GetFunctionStartLineEntry() const624 SymbolContext::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 
SymbolContextSpecifier(const TargetSP & target_sp)656 SymbolContextSpecifier::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 
~SymbolContextSpecifier()670 SymbolContextSpecifier::~SymbolContextSpecifier()
671 {
672 }
673 
674 bool
AddLineSpecification(uint32_t line_no,SpecificationType type)675 SymbolContextSpecifier::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 
698 bool
AddSpecification(const char * spec_string,SpecificationType type)699 SymbolContextSpecifier::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 
753 void
Clear()754 SymbolContextSpecifier::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 
767 bool
SymbolContextMatches(SymbolContext & sc)768 SymbolContextSpecifier::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 
867 bool
AddressMatches(lldb::addr_t addr)868 SymbolContextSpecifier::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 
884 void
GetDescription(Stream * s,lldb::DescriptionLevel level) const885 SymbolContextSpecifier::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 
SymbolContextList()969 SymbolContextList::SymbolContextList() :
970     m_symbol_contexts()
971 {
972 }
973 
~SymbolContextList()974 SymbolContextList::~SymbolContextList()
975 {
976 }
977 
978 void
Append(const SymbolContext & sc)979 SymbolContextList::Append(const SymbolContext& sc)
980 {
981     m_symbol_contexts.push_back(sc);
982 }
983 
984 void
Append(const SymbolContextList & sc_list)985 SymbolContextList::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 
993 uint32_t
AppendIfUnique(const SymbolContextList & sc_list,bool merge_symbol_into_function)994 SymbolContextList::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 
1006 bool
AppendIfUnique(const SymbolContext & sc,bool merge_symbol_into_function)1007 SymbolContextList::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 
1051 bool
MergeSymbolContextIntoFunctionContext(const SymbolContext & symbol_sc,uint32_t start_idx,uint32_t stop_idx)1052 SymbolContextList::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 
1094 void
Clear()1095 SymbolContextList::Clear()
1096 {
1097     m_symbol_contexts.clear();
1098 }
1099 
1100 void
Dump(Stream * s,Target * target) const1101 SymbolContextList::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 
1119 bool
GetContextAtIndex(size_t idx,SymbolContext & sc) const1120 SymbolContextList::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 
1130 bool
GetLastContext(SymbolContext & sc) const1131 SymbolContextList::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 
1141 bool
RemoveContextAtIndex(size_t idx)1142 SymbolContextList::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 
1152 uint32_t
GetSize() const1153 SymbolContextList::GetSize() const
1154 {
1155     return m_symbol_contexts.size();
1156 }
1157 
1158 uint32_t
NumLineEntriesWithLine(uint32_t line) const1159 SymbolContextList::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 
1171 void
GetDescription(Stream * s,lldb::DescriptionLevel level,Target * target) const1172 SymbolContextList::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 
1181 bool
operator ==(const SymbolContextList & lhs,const SymbolContextList & rhs)1182 lldb_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 
1200 bool
operator !=(const SymbolContextList & lhs,const SymbolContextList & rhs)1201 lldb_private::operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs)
1202 {
1203     return !(lhs == rhs);
1204 }
1205 
1206