Bug Summary

File:tools/lldb/source/Symbol/SymbolContext.cpp
Location:line 1092, column 69
Description:Called C++ object pointer is null

Annotated Source Code

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