1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
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 | |
27 | using namespace lldb; |
28 | using namespace lldb_private; |
29 | |
30 | SymbolContext::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 | |
42 | SymbolContext::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 | |
56 | SymbolContext::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 | |
70 | SymbolContext::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 | |
83 | SymbolContext::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 | |
96 | SymbolContext::~SymbolContext () |
97 | { |
98 | } |
99 | |
100 | const SymbolContext& |
101 | SymbolContext::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 | |
117 | void |
118 | SymbolContext::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 | |
131 | bool |
132 | SymbolContext::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 | |
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 | |
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 | |
270 | void |
271 | SymbolContext::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 | |
376 | uint32_t |
377 | SymbolContext::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 | |
391 | void |
392 | SymbolContext::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 | |
431 | |
432 | |
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 | |
453 | bool |
454 | lldb_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 | |
465 | bool |
466 | lldb_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 | |
477 | bool |
478 | SymbolContext::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 | |
528 | bool |
529 | SymbolContext::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 | |
539 | |
540 | |
541 | |
542 | |
543 | |
544 | Block *curr_inlined_block = block->GetContainingInlinedBlock(); |
545 | if (curr_inlined_block) |
546 | { |
547 | |
548 | |
549 | |
550 | Block *next_frame_block = curr_inlined_block->GetParent(); |
551 | |
552 | next_frame_block->CalculateSymbolContext (&next_frame_sc); |
553 | |
554 | |
555 | |
556 | |
557 | AddressRange range; |
558 | if (curr_inlined_block->GetRangeContainingAddress (curr_frame_pc, range)) |
559 | { |
560 | |
561 | |
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 | |
617 | Block * |
618 | SymbolContext::GetFunctionBlock () |
619 | { |
620 | if (function) |
621 | { |
622 | if (block) |
623 | { |
624 | |
625 | |
626 | |
627 | |
628 | Block *inlined_block = block->GetContainingInlinedBlock(); |
629 | if (inlined_block) |
630 | return inlined_block; |
631 | |
632 | |
633 | |
634 | |
635 | } |
636 | |
637 | |
638 | |
639 | |
640 | return &function->GetBlock(true); |
641 | } |
642 | return nullptr; |
643 | } |
644 | |
645 | bool |
646 | SymbolContext::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 | |
662 | class TypeMoveMatchingBlock |
663 | { |
664 | public: |
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 | |
682 | private: |
683 | const Block * const curr_block; |
684 | TypeMap &type_map; |
685 | TypeList &type_list; |
686 | }; |
687 | |
688 | class TypeMoveMatchingFunction |
689 | { |
690 | public: |
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 | |
708 | private: |
709 | const Function * const func; |
710 | TypeMap &type_map; |
711 | TypeList &type_list; |
712 | }; |
713 | |
714 | class TypeMoveMatchingCompileUnit |
715 | { |
716 | public: |
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 | |
734 | private: |
735 | const CompileUnit * const comp_unit; |
736 | TypeMap &type_map; |
737 | TypeList &type_list; |
738 | }; |
739 | |
740 | class TypeMoveMatchingModule |
741 | { |
742 | public: |
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 | |
760 | private: |
761 | lldb::ModuleSP modulesp; |
762 | TypeMap &type_map; |
763 | TypeList &type_list; |
764 | }; |
765 | |
766 | class TypeMaptoList |
767 | { |
768 | public: |
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 | |
787 | private: |
788 | TypeMap &type_map; |
789 | TypeList &type_list; |
790 | }; |
791 | |
792 | void |
793 | SymbolContext::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 | |
830 | ConstString |
831 | SymbolContext::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 | |
855 | return ConstString(); |
856 | } |
857 | } |
858 | |
859 | LineEntry |
860 | SymbolContext::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 | |
889 | |
890 | |
891 | |
892 | SymbolContextSpecifier::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 | |
906 | SymbolContextSpecifier::~SymbolContextSpecifier() |
907 | { |
908 | } |
909 | |
910 | bool |
911 | SymbolContextSpecifier::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 | |
934 | bool |
935 | SymbolContextSpecifier::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 | |
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 | |
958 | |
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 | |
983 | break; |
984 | } |
985 | |
986 | return return_value; |
987 | } |
988 | |
989 | void |
990 | SymbolContextSpecifier::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 | |
1003 | bool |
1004 | SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) |
1005 | { |
1006 | if (m_type == eNothingSpecified) |
| |
1007 | return true; |
1008 | |
1009 | if (m_target_sp.get() != sc.target_sp.get()) |
| |
1010 | return false; |
1011 | |
1012 | if (m_type & eModuleSpecified) |
| |
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) |
| |
1030 | { |
1031 | if (m_file_spec_ap.get()) |
1032 | { |
1033 | |
1034 | if (sc.block == nullptr && sc.comp_unit == nullptr) |
1035 | return false; |
1036 | |
1037 | |
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 | |
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 |
| |
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) |
| |
1066 | { |
1067 | |
1068 | bool was_inlined = false; |
1069 | ConstString func_name(m_function_spec.c_str()); |
1070 | |
1071 | if (sc.block != nullptr) |
| |
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 | |
1083 | if (!was_inlined) |
| |
1084 | { |
1085 | if (sc.function != nullptr) |
| 9 | | Assuming pointer value is null | |
|
| |
1086 | { |
1087 | if (!sc.function->GetMangled().NameMatches(func_name, sc.function->GetLanguage())) |
1088 | return false; |
1089 | } |
1090 | else if (sc.symbol != nullptr) |
| |
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 | |
1103 | bool |
1104 | SymbolContextSpecifier::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 | |
1120 | void |
1121 | SymbolContextSpecifier::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 | |
1201 | |
1202 | |
1203 | |
1204 | |
1205 | SymbolContextList::SymbolContextList() : |
1206 | m_symbol_contexts() |
1207 | { |
1208 | } |
1209 | |
1210 | SymbolContextList::~SymbolContextList() |
1211 | { |
1212 | } |
1213 | |
1214 | void |
1215 | SymbolContextList::Append(const SymbolContext& sc) |
1216 | { |
1217 | m_symbol_contexts.push_back(sc); |
1218 | } |
1219 | |
1220 | void |
1221 | SymbolContextList::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 | |
1229 | uint32_t |
1230 | SymbolContextList::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 | |
1242 | bool |
1243 | SymbolContextList::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 | |
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 | |
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 | |
1287 | bool |
1288 | SymbolContextList::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 | |
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 | |
1313 | if (function_sc.symbol == symbol_sc.symbol) |
1314 | return true; |
1315 | |
1316 | if (function_sc.symbol == nullptr) |
1317 | { |
1318 | |
1319 | m_symbol_contexts[i].symbol = symbol_sc.symbol; |
1320 | return true; |
1321 | } |
1322 | } |
1323 | } |
1324 | } |
1325 | } |
1326 | } |
1327 | return false; |
1328 | } |
1329 | |
1330 | void |
1331 | SymbolContextList::Clear() |
1332 | { |
1333 | m_symbol_contexts.clear(); |
1334 | } |
1335 | |
1336 | void |
1337 | SymbolContextList::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 | |
1350 | pos->GetDescription(s, eDescriptionLevelVerbose, target); |
1351 | } |
1352 | s->IndentLess(); |
1353 | } |
1354 | |
1355 | bool |
1356 | SymbolContextList::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 | |
1366 | bool |
1367 | SymbolContextList::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 | |
1377 | bool |
1378 | SymbolContextList::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 | |
1388 | uint32_t |
1389 | SymbolContextList::GetSize() const |
1390 | { |
1391 | return m_symbol_contexts.size(); |
1392 | } |
1393 | |
1394 | uint32_t |
1395 | SymbolContextList::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 | |
1407 | void |
1408 | SymbolContextList::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 | |
1417 | bool |
1418 | lldb_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 | |
1436 | bool |
1437 | lldb_private::operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs) |
1438 | { |
1439 | return !(lhs == rhs); |
1440 | } |
1441 | |