1 //===-- SymbolContext.cpp -------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Symbol/SymbolContext.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/Module.h"
13 #include "lldb/Core/ModuleSpec.h"
14 #include "lldb/Host/Host.h"
15 #include "lldb/Symbol/Block.h"
16 #include "lldb/Symbol/CompileUnit.h"
17 #include "lldb/Symbol/ObjectFile.h"
18 #include "lldb/Symbol/Symbol.h"
19 #include "lldb/Symbol/SymbolFile.h"
20 #include "lldb/Symbol/SymbolVendor.h"
21 #include "lldb/Symbol/Variable.h"
22 #include "lldb/Target/Language.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Utility/LLDBLog.h"
25 #include "lldb/Utility/Log.h"
26 #include "lldb/Utility/StreamString.h"
27 #include "lldb/lldb-enumerations.h"
30 using namespace lldb_private
;
32 SymbolContext::SymbolContext() : target_sp(), module_sp(), line_entry() {}
34 SymbolContext::SymbolContext(const ModuleSP
&m
, CompileUnit
*cu
, Function
*f
,
35 Block
*b
, LineEntry
*le
, Symbol
*s
)
36 : target_sp(), module_sp(m
), comp_unit(cu
), function(f
), block(b
),
37 line_entry(), symbol(s
) {
42 SymbolContext::SymbolContext(const TargetSP
&t
, const ModuleSP
&m
,
43 CompileUnit
*cu
, Function
*f
, Block
*b
,
44 LineEntry
*le
, Symbol
*s
)
45 : target_sp(t
), module_sp(m
), comp_unit(cu
), function(f
), block(b
),
46 line_entry(), symbol(s
) {
51 SymbolContext::SymbolContext(SymbolContextScope
*sc_scope
)
52 : target_sp(), module_sp(), line_entry() {
53 sc_scope
->CalculateSymbolContext(this);
56 SymbolContext::~SymbolContext() = default;
58 void SymbolContext::Clear(bool clear_target
) {
70 bool SymbolContext::DumpStopContext(Stream
*s
, ExecutionContextScope
*exe_scope
,
71 const Address
&addr
, bool show_fullpaths
,
72 bool show_module
, bool show_inlined_frames
,
73 bool show_function_arguments
,
74 bool show_function_name
) const {
75 bool dumped_something
= false;
76 if (show_module
&& module_sp
) {
78 *s
<< module_sp
->GetFileSpec();
80 *s
<< module_sp
->GetFileSpec().GetFilename();
82 dumped_something
= true;
85 if (function
!= nullptr) {
86 SymbolContext inline_parent_sc
;
87 Address inline_parent_addr
;
88 if (!show_function_name
) {
90 dumped_something
= true;
93 if (!show_function_arguments
)
94 name
= function
->GetNameNoArguments();
96 name
= function
->GetName();
101 if (addr
.IsValid()) {
102 const addr_t function_offset
=
104 function
->GetAddressRange().GetBaseAddress().GetOffset();
105 if (!show_function_name
) {
106 // Print +offset even if offset is 0
107 dumped_something
= true;
108 s
->Printf("+%" PRIu64
">", function_offset
);
109 } else if (function_offset
) {
110 dumped_something
= true;
111 s
->Printf(" + %" PRIu64
, function_offset
);
115 if (GetParentOfInlinedScope(addr
, inline_parent_sc
, inline_parent_addr
)) {
116 dumped_something
= true;
117 Block
*inlined_block
= block
->GetContainingInlinedBlock();
118 const InlineFunctionInfo
*inlined_block_info
=
119 inlined_block
->GetInlinedFunctionInfo();
120 s
->Printf(" [inlined] %s", inlined_block_info
->GetName().GetCString());
122 lldb_private::AddressRange block_range
;
123 if (inlined_block
->GetRangeContainingAddress(addr
, block_range
)) {
124 const addr_t inlined_function_offset
=
125 addr
.GetOffset() - block_range
.GetBaseAddress().GetOffset();
126 if (inlined_function_offset
) {
127 s
->Printf(" + %" PRIu64
, inlined_function_offset
);
130 // "line_entry" will always be valid as GetParentOfInlinedScope(...) will
131 // fill it in correctly with the calling file and line. Previous code
132 // was extracting the calling file and line from inlined_block_info and
133 // using it right away which is not correct. On the first call to this
134 // function "line_entry" will contain the actual line table entry. On
135 // susequent calls "line_entry" will contain the calling file and line
136 // from the previous inline info.
137 if (line_entry
.IsValid()) {
138 s
->PutCString(" at ");
139 line_entry
.DumpStopContext(s
, show_fullpaths
);
142 if (show_inlined_frames
) {
145 const bool show_function_name
= true;
146 return inline_parent_sc
.DumpStopContext(
147 s
, exe_scope
, inline_parent_addr
, show_fullpaths
, show_module
,
148 show_inlined_frames
, show_function_arguments
, show_function_name
);
151 if (line_entry
.IsValid()) {
152 dumped_something
= true;
153 s
->PutCString(" at ");
154 if (line_entry
.DumpStopContext(s
, show_fullpaths
))
155 dumped_something
= true;
158 } else if (symbol
!= nullptr) {
159 if (!show_function_name
) {
161 dumped_something
= true;
162 } else if (symbol
->GetName()) {
163 dumped_something
= true;
164 if (symbol
->GetType() == eSymbolTypeTrampoline
)
165 s
->PutCString("symbol stub for: ");
166 symbol
->GetName().Dump(s
);
169 if (addr
.IsValid() && symbol
->ValueIsAddress()) {
170 const addr_t symbol_offset
=
171 addr
.GetOffset() - symbol
->GetAddressRef().GetOffset();
172 if (!show_function_name
) {
173 // Print +offset even if offset is 0
174 dumped_something
= true;
175 s
->Printf("+%" PRIu64
">", symbol_offset
);
176 } else if (symbol_offset
) {
177 dumped_something
= true;
178 s
->Printf(" + %" PRIu64
, symbol_offset
);
181 } else if (addr
.IsValid()) {
182 addr
.Dump(s
, exe_scope
, Address::DumpStyleModuleWithFileAddress
);
183 dumped_something
= true;
185 return dumped_something
;
188 void SymbolContext::GetDescription(Stream
*s
, lldb::DescriptionLevel level
,
189 Target
*target
) const {
191 s
->Indent(" Module: file = \"");
192 module_sp
->GetFileSpec().Dump(s
->AsRawOstream());
194 if (module_sp
->GetArchitecture().IsValid())
195 s
->Printf(", arch = \"%s\"",
196 module_sp
->GetArchitecture().GetArchitectureName());
200 if (comp_unit
!= nullptr) {
201 s
->Indent("CompileUnit: ");
202 comp_unit
->GetDescription(s
, level
);
206 if (function
!= nullptr) {
207 s
->Indent(" Function: ");
208 function
->GetDescription(s
, level
, target
);
211 Type
*func_type
= function
->GetType();
213 s
->Indent(" FuncType: ");
214 func_type
->GetDescription(s
, level
, false, target
);
219 if (block
!= nullptr) {
220 std::vector
<Block
*> blocks
;
221 blocks
.push_back(block
);
222 Block
*parent_block
= block
->GetParent();
224 while (parent_block
) {
225 blocks
.push_back(parent_block
);
226 parent_block
= parent_block
->GetParent();
228 std::vector
<Block
*>::reverse_iterator pos
;
229 std::vector
<Block
*>::reverse_iterator begin
= blocks
.rbegin();
230 std::vector
<Block
*>::reverse_iterator end
= blocks
.rend();
231 for (pos
= begin
; pos
!= end
; ++pos
) {
233 s
->Indent(" Blocks: ");
236 (*pos
)->GetDescription(s
, function
, level
, target
);
241 if (line_entry
.IsValid()) {
242 s
->Indent(" LineEntry: ");
243 line_entry
.GetDescription(s
, level
, comp_unit
, target
, false);
247 if (symbol
!= nullptr) {
248 s
->Indent(" Symbol: ");
249 symbol
->GetDescription(s
, level
, target
);
253 if (variable
!= nullptr) {
254 s
->Indent(" Variable: ");
256 s
->Printf("id = {0x%8.8" PRIx64
"}, ", variable
->GetID());
258 switch (variable
->GetScope()) {
259 case eValueTypeVariableGlobal
:
260 s
->PutCString("kind = global, ");
263 case eValueTypeVariableStatic
:
264 s
->PutCString("kind = static, ");
267 case eValueTypeVariableArgument
:
268 s
->PutCString("kind = argument, ");
271 case eValueTypeVariableLocal
:
272 s
->PutCString("kind = local, ");
275 case eValueTypeVariableThreadLocal
:
276 s
->PutCString("kind = thread local, ");
283 s
->Printf("name = \"%s\"\n", variable
->GetName().GetCString());
287 uint32_t SymbolContext::GetResolvedMask() const {
288 uint32_t resolved_mask
= 0;
290 resolved_mask
|= eSymbolContextTarget
;
292 resolved_mask
|= eSymbolContextModule
;
294 resolved_mask
|= eSymbolContextCompUnit
;
296 resolved_mask
|= eSymbolContextFunction
;
298 resolved_mask
|= eSymbolContextBlock
;
299 if (line_entry
.IsValid())
300 resolved_mask
|= eSymbolContextLineEntry
;
302 resolved_mask
|= eSymbolContextSymbol
;
304 resolved_mask
|= eSymbolContextVariable
;
305 return resolved_mask
;
308 void SymbolContext::Dump(Stream
*s
, Target
*target
) const {
311 s
->PutCString("SymbolContext");
316 *s
<< "Module = " << module_sp
.get() << ' ';
318 module_sp
->GetFileSpec().Dump(s
->AsRawOstream());
321 *s
<< "CompileUnit = " << comp_unit
;
322 if (comp_unit
!= nullptr)
323 s
->Format(" {{{0:x-16}} {1}", comp_unit
->GetID(),
324 comp_unit
->GetPrimaryFile());
327 *s
<< "Function = " << function
;
328 if (function
!= nullptr) {
329 s
->Format(" {{{0:x-16}} {1}, address-range = ", function
->GetID(),
330 function
->GetType()->GetName());
331 function
->GetAddressRange().Dump(s
, target
, Address::DumpStyleLoadAddress
,
332 Address::DumpStyleModuleWithFileAddress
);
335 Type
*func_type
= function
->GetType();
338 func_type
->Dump(s
, false);
343 *s
<< "Block = " << block
;
344 if (block
!= nullptr)
345 s
->Format(" {{{0:x-16}}", block
->GetID());
348 *s
<< "LineEntry = ";
349 line_entry
.Dump(s
, target
, true, Address::DumpStyleLoadAddress
,
350 Address::DumpStyleModuleWithFileAddress
, true);
353 *s
<< "Symbol = " << symbol
;
354 if (symbol
!= nullptr && symbol
->GetMangled())
355 *s
<< ' ' << symbol
->GetName().AsCString();
357 *s
<< "Variable = " << variable
;
358 if (variable
!= nullptr) {
359 s
->Format(" {{{0:x-16}} {1}", variable
->GetID(),
360 variable
->GetType()->GetName());
367 bool lldb_private::operator==(const SymbolContext
&lhs
,
368 const SymbolContext
&rhs
) {
369 return lhs
.function
== rhs
.function
&& lhs
.symbol
== rhs
.symbol
&&
370 lhs
.module_sp
.get() == rhs
.module_sp
.get() &&
371 lhs
.comp_unit
== rhs
.comp_unit
&&
372 lhs
.target_sp
.get() == rhs
.target_sp
.get() &&
373 LineEntry::Compare(lhs
.line_entry
, rhs
.line_entry
) == 0 &&
374 lhs
.variable
== rhs
.variable
;
377 bool lldb_private::operator!=(const SymbolContext
&lhs
,
378 const SymbolContext
&rhs
) {
379 return !(lhs
== rhs
);
382 bool SymbolContext::GetAddressRange(uint32_t scope
, uint32_t range_idx
,
383 bool use_inline_block_range
,
384 AddressRange
&range
) const {
385 if ((scope
& eSymbolContextLineEntry
) && line_entry
.IsValid()) {
386 range
= line_entry
.range
;
390 if ((scope
& eSymbolContextBlock
) && (block
!= nullptr)) {
391 if (use_inline_block_range
) {
392 Block
*inline_block
= block
->GetContainingInlinedBlock();
394 return inline_block
->GetRangeAtIndex(range_idx
, range
);
396 return block
->GetRangeAtIndex(range_idx
, range
);
400 if ((scope
& eSymbolContextFunction
) && (function
!= nullptr)) {
401 if (range_idx
== 0) {
402 range
= function
->GetAddressRange();
407 if ((scope
& eSymbolContextSymbol
) && (symbol
!= nullptr)) {
408 if (range_idx
== 0) {
409 if (symbol
->ValueIsAddress()) {
410 range
.GetBaseAddress() = symbol
->GetAddressRef();
411 range
.SetByteSize(symbol
->GetByteSize());
420 LanguageType
SymbolContext::GetLanguage() const {
422 if (function
&& (lang
= function
->GetLanguage()) != eLanguageTypeUnknown
) {
424 } else if (variable
&&
425 (lang
= variable
->GetLanguage()) != eLanguageTypeUnknown
) {
427 } else if (symbol
&& (lang
= symbol
->GetLanguage()) != eLanguageTypeUnknown
) {
429 } else if (comp_unit
&&
430 (lang
= comp_unit
->GetLanguage()) != eLanguageTypeUnknown
) {
433 // If all else fails, try to guess the language from the name.
434 return symbol
->GetMangled().GuessLanguage();
436 return eLanguageTypeUnknown
;
439 bool SymbolContext::GetParentOfInlinedScope(const Address
&curr_frame_pc
,
440 SymbolContext
&next_frame_sc
,
441 Address
&next_frame_pc
) const {
442 next_frame_sc
.Clear(false);
443 next_frame_pc
.Clear();
446 // const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress();
448 // In order to get the parent of an inlined function we first need to see
449 // if we are in an inlined block as "this->block" could be an inlined
450 // block, or a parent of "block" could be. So lets check if this block or
451 // one of this blocks parents is an inlined function.
452 Block
*curr_inlined_block
= block
->GetContainingInlinedBlock();
453 if (curr_inlined_block
) {
454 // "this->block" is contained in an inline function block, so to get the
455 // scope above the inlined block, we get the parent of the inlined block
457 Block
*next_frame_block
= curr_inlined_block
->GetParent();
458 // Now calculate the symbol context of the containing block
459 next_frame_block
->CalculateSymbolContext(&next_frame_sc
);
461 // If we get here we weren't able to find the return line entry using the
462 // nesting of the blocks and the line table. So just use the call site
463 // info from our inlined block.
466 if (curr_inlined_block
->GetRangeContainingAddress(curr_frame_pc
, range
)) {
467 // To see there this new frame block it, we need to look at the call
468 // site information from
469 const InlineFunctionInfo
*curr_inlined_block_inlined_info
=
470 curr_inlined_block
->GetInlinedFunctionInfo();
471 next_frame_pc
= range
.GetBaseAddress();
472 next_frame_sc
.line_entry
.range
.GetBaseAddress() = next_frame_pc
;
473 next_frame_sc
.line_entry
.file
=
474 curr_inlined_block_inlined_info
->GetCallSite().GetFile();
475 next_frame_sc
.line_entry
.original_file
=
476 curr_inlined_block_inlined_info
->GetCallSite().GetFile();
477 next_frame_sc
.line_entry
.line
=
478 curr_inlined_block_inlined_info
->GetCallSite().GetLine();
479 next_frame_sc
.line_entry
.column
=
480 curr_inlined_block_inlined_info
->GetCallSite().GetColumn();
483 Log
*log
= GetLog(LLDBLog::Symbols
);
488 "warning: inlined block 0x%8.8" PRIx64
489 " doesn't have a range that contains file address 0x%" PRIx64
,
490 curr_inlined_block
->GetID(), curr_frame_pc
.GetFileAddress());
492 #ifdef LLDB_CONFIGURATION_DEBUG
494 ObjectFile
*objfile
= nullptr;
496 if (SymbolFile
*symbol_file
= module_sp
->GetSymbolFile())
497 objfile
= symbol_file
->GetObjectFile();
500 Debugger::ReportWarning(llvm::formatv(
501 "inlined block {0:x} doesn't have a range that contains file "
502 "address {1:x} in {2}",
503 curr_inlined_block
->GetID(), curr_frame_pc
.GetFileAddress(),
504 objfile
->GetFileSpec().GetPath()));
506 Debugger::ReportWarning(llvm::formatv(
507 "inlined block {0:x} doesn't have a range that contains file "
509 curr_inlined_block
->GetID(), curr_frame_pc
.GetFileAddress()));
520 Block
*SymbolContext::GetFunctionBlock() {
523 // If this symbol context has a block, check to see if this block is
524 // itself, or is contained within a block with inlined function
525 // information. If so, then the inlined block is the block that defines
527 Block
*inlined_block
= block
->GetContainingInlinedBlock();
529 return inlined_block
;
531 // The block in this symbol context is not inside an inlined block, so
532 // the block that defines the function is the function's top level block,
533 // which is returned below.
536 // There is no block information in this symbol context, so we must assume
537 // that the block that is desired is the top level block of the function
539 return &function
->GetBlock(true);
544 llvm::StringRef
SymbolContext::GetInstanceVariableName() {
545 LanguageType lang_type
= eLanguageTypeUnknown
;
547 if (Block
*function_block
= GetFunctionBlock())
548 if (CompilerDeclContext decl_ctx
= function_block
->GetDeclContext())
549 lang_type
= decl_ctx
.GetLanguage();
551 if (lang_type
== eLanguageTypeUnknown
)
552 lang_type
= GetLanguage();
554 if (auto *lang
= Language::FindPlugin(lang_type
))
555 return lang
->GetInstanceVariableName();
560 void SymbolContext::SortTypeList(TypeMap
&type_map
, TypeList
&type_list
) const {
561 Block
*curr_block
= block
;
562 bool isInlinedblock
= false;
563 if (curr_block
!= nullptr &&
564 curr_block
->GetContainingInlinedBlock() != nullptr)
565 isInlinedblock
= true;
567 // Find all types that match the current block if we have one and put them
568 // first in the list. Keep iterating up through all blocks.
569 while (curr_block
!= nullptr && !isInlinedblock
) {
571 [curr_block
, &type_list
](const lldb::TypeSP
&type_sp
) -> bool {
572 SymbolContextScope
*scs
= type_sp
->GetSymbolContextScope();
573 if (scs
&& curr_block
== scs
->CalculateSymbolContextBlock())
574 type_list
.Insert(type_sp
);
575 return true; // Keep iterating
578 // Remove any entries that are now in "type_list" from "type_map" since we
579 // can't remove from type_map while iterating
580 type_list
.ForEach([&type_map
](const lldb::TypeSP
&type_sp
) -> bool {
581 type_map
.Remove(type_sp
);
582 return true; // Keep iterating
584 curr_block
= curr_block
->GetParent();
586 // Find all types that match the current function, if we have onem, and put
587 // them next in the list.
588 if (function
!= nullptr && !type_map
.Empty()) {
589 const size_t old_type_list_size
= type_list
.GetSize();
590 type_map
.ForEach([this, &type_list
](const lldb::TypeSP
&type_sp
) -> bool {
591 SymbolContextScope
*scs
= type_sp
->GetSymbolContextScope();
592 if (scs
&& function
== scs
->CalculateSymbolContextFunction())
593 type_list
.Insert(type_sp
);
594 return true; // Keep iterating
597 // Remove any entries that are now in "type_list" from "type_map" since we
598 // can't remove from type_map while iterating
599 const size_t new_type_list_size
= type_list
.GetSize();
600 if (new_type_list_size
> old_type_list_size
) {
601 for (size_t i
= old_type_list_size
; i
< new_type_list_size
; ++i
)
602 type_map
.Remove(type_list
.GetTypeAtIndex(i
));
605 // Find all types that match the current compile unit, if we have one, and
606 // put them next in the list.
607 if (comp_unit
!= nullptr && !type_map
.Empty()) {
608 const size_t old_type_list_size
= type_list
.GetSize();
610 type_map
.ForEach([this, &type_list
](const lldb::TypeSP
&type_sp
) -> bool {
611 SymbolContextScope
*scs
= type_sp
->GetSymbolContextScope();
612 if (scs
&& comp_unit
== scs
->CalculateSymbolContextCompileUnit())
613 type_list
.Insert(type_sp
);
614 return true; // Keep iterating
617 // Remove any entries that are now in "type_list" from "type_map" since we
618 // can't remove from type_map while iterating
619 const size_t new_type_list_size
= type_list
.GetSize();
620 if (new_type_list_size
> old_type_list_size
) {
621 for (size_t i
= old_type_list_size
; i
< new_type_list_size
; ++i
)
622 type_map
.Remove(type_list
.GetTypeAtIndex(i
));
625 // Find all types that match the current module, if we have one, and put them
627 if (module_sp
&& !type_map
.Empty()) {
628 const size_t old_type_list_size
= type_list
.GetSize();
629 type_map
.ForEach([this, &type_list
](const lldb::TypeSP
&type_sp
) -> bool {
630 SymbolContextScope
*scs
= type_sp
->GetSymbolContextScope();
631 if (scs
&& module_sp
== scs
->CalculateSymbolContextModule())
632 type_list
.Insert(type_sp
);
633 return true; // Keep iterating
635 // Remove any entries that are now in "type_list" from "type_map" since we
636 // can't remove from type_map while iterating
637 const size_t new_type_list_size
= type_list
.GetSize();
638 if (new_type_list_size
> old_type_list_size
) {
639 for (size_t i
= old_type_list_size
; i
< new_type_list_size
; ++i
)
640 type_map
.Remove(type_list
.GetTypeAtIndex(i
));
643 // Any types that are left get copied into the list an any order.
644 if (!type_map
.Empty()) {
645 type_map
.ForEach([&type_list
](const lldb::TypeSP
&type_sp
) -> bool {
646 type_list
.Insert(type_sp
);
647 return true; // Keep iterating
653 SymbolContext::GetFunctionName(Mangled::NamePreference preference
) const {
656 Block
*inlined_block
= block
->GetContainingInlinedBlock();
659 const InlineFunctionInfo
*inline_info
=
660 inlined_block
->GetInlinedFunctionInfo();
662 return inline_info
->GetName();
665 return function
->GetMangled().GetName(preference
);
666 } else if (symbol
&& symbol
->ValueIsAddress()) {
667 return symbol
->GetMangled().GetName(preference
);
669 // No function, return an empty string.
670 return ConstString();
674 LineEntry
SymbolContext::GetFunctionStartLineEntry() const {
675 LineEntry line_entry
;
678 Block
*inlined_block
= block
->GetContainingInlinedBlock();
680 if (inlined_block
->GetStartAddress(start_addr
)) {
681 if (start_addr
.CalculateSymbolContextLineEntry(line_entry
))
689 if (function
->GetAddressRange()
691 .CalculateSymbolContextLineEntry(line_entry
))
697 bool SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line
,
700 if (!line_entry
.IsValid()) {
701 error
.SetErrorString("Symbol context has no line table.");
705 range
= line_entry
.range
;
706 if (line_entry
.line
> end_line
) {
707 error
.SetErrorStringWithFormat(
708 "end line option %d must be after the current line: %d", end_line
,
713 uint32_t line_index
= 0;
717 line_index
= comp_unit
->FindLineEntry(line_index
, line_entry
.line
, nullptr,
719 if (line_index
== UINT32_MAX
)
721 if (LineEntry::Compare(this_line
, line_entry
) == 0) {
729 // Can't find the index of the SymbolContext's line entry in the
730 // SymbolContext's CompUnit.
731 error
.SetErrorString(
732 "Can't find the current line entry in the CompUnit - can't process "
733 "the end-line option");
737 line_index
= comp_unit
->FindLineEntry(line_index
, end_line
, nullptr, false,
739 if (line_index
== UINT32_MAX
) {
740 error
.SetErrorStringWithFormat(
741 "could not find a line table entry corresponding "
742 "to end line number %d",
747 Block
*func_block
= GetFunctionBlock();
748 if (func_block
&& func_block
->GetRangeIndexContainingAddress(
749 end_entry
.range
.GetBaseAddress()) == UINT32_MAX
) {
750 error
.SetErrorStringWithFormat(
751 "end line number %d is not contained within the current function.",
756 lldb::addr_t range_size
= end_entry
.range
.GetBaseAddress().GetFileAddress() -
757 range
.GetBaseAddress().GetFileAddress();
758 range
.SetByteSize(range_size
);
762 const Symbol
*SymbolContext::FindBestGlobalDataSymbol(ConstString name
,
770 Target
&target
= *target_sp
;
771 Module
*module
= module_sp
.get();
773 auto ProcessMatches
= [this, &name
, &target
,
774 module
](const SymbolContextList
&sc_list
,
775 Status
&error
) -> const Symbol
* {
776 llvm::SmallVector
<const Symbol
*, 1> external_symbols
;
777 llvm::SmallVector
<const Symbol
*, 1> internal_symbols
;
778 for (const SymbolContext
&sym_ctx
: sc_list
) {
779 if (sym_ctx
.symbol
) {
780 const Symbol
*symbol
= sym_ctx
.symbol
;
781 const Address sym_address
= symbol
->GetAddress();
783 if (sym_address
.IsValid()) {
784 switch (symbol
->GetType()) {
785 case eSymbolTypeData
:
786 case eSymbolTypeRuntime
:
787 case eSymbolTypeAbsolute
:
788 case eSymbolTypeObjCClass
:
789 case eSymbolTypeObjCMetaClass
:
790 case eSymbolTypeObjCIVar
:
791 if (symbol
->GetDemangledNameIsSynthesized()) {
792 // If the demangled name was synthesized, then don't use it for
793 // expressions. Only let the symbol match if the mangled named
794 // matches for these symbols.
795 if (symbol
->GetMangled().GetMangledName() != name
)
798 if (symbol
->IsExternal()) {
799 external_symbols
.push_back(symbol
);
801 internal_symbols
.push_back(symbol
);
804 case eSymbolTypeReExported
: {
805 ConstString reexport_name
= symbol
->GetReExportedSymbolName();
807 ModuleSP reexport_module_sp
;
808 ModuleSpec reexport_module_spec
;
809 reexport_module_spec
.GetPlatformFileSpec() =
810 symbol
->GetReExportedSymbolSharedLibrary();
811 if (reexport_module_spec
.GetPlatformFileSpec()) {
813 target
.GetImages().FindFirstModule(reexport_module_spec
);
814 if (!reexport_module_sp
) {
815 reexport_module_spec
.GetPlatformFileSpec().ClearDirectory();
817 target
.GetImages().FindFirstModule(reexport_module_spec
);
820 // Don't allow us to try and resolve a re-exported symbol if it
821 // is the same as the current symbol
822 if (name
== symbol
->GetReExportedSymbolName() &&
823 module
== reexport_module_sp
.get())
826 return FindBestGlobalDataSymbol(symbol
->GetReExportedSymbolName(),
831 case eSymbolTypeCode
: // We already lookup functions elsewhere
832 case eSymbolTypeVariable
:
833 case eSymbolTypeLocal
:
834 case eSymbolTypeParam
:
835 case eSymbolTypeTrampoline
:
836 case eSymbolTypeInvalid
:
837 case eSymbolTypeException
:
838 case eSymbolTypeSourceFile
:
839 case eSymbolTypeHeaderFile
:
840 case eSymbolTypeObjectFile
:
841 case eSymbolTypeCommonBlock
:
842 case eSymbolTypeBlock
:
843 case eSymbolTypeVariableType
:
844 case eSymbolTypeLineEntry
:
845 case eSymbolTypeLineHeader
:
846 case eSymbolTypeScopeBegin
:
847 case eSymbolTypeScopeEnd
:
848 case eSymbolTypeAdditional
:
849 case eSymbolTypeCompiler
:
850 case eSymbolTypeInstrumentation
:
851 case eSymbolTypeUndefined
:
852 case eSymbolTypeResolver
:
859 if (external_symbols
.size() > 1) {
861 ss
.Printf("Multiple external symbols found for '%s'\n", name
.AsCString());
862 for (const Symbol
*symbol
: external_symbols
) {
863 symbol
->GetDescription(&ss
, eDescriptionLevelFull
, &target
);
866 error
.SetErrorString(ss
.GetData());
868 } else if (external_symbols
.size()) {
869 return external_symbols
[0];
870 } else if (internal_symbols
.size() > 1) {
872 ss
.Printf("Multiple internal symbols found for '%s'\n", name
.AsCString());
873 for (const Symbol
*symbol
: internal_symbols
) {
874 symbol
->GetDescription(&ss
, eDescriptionLevelVerbose
, &target
);
877 error
.SetErrorString(ss
.GetData());
879 } else if (internal_symbols
.size()) {
880 return internal_symbols
[0];
887 SymbolContextList sc_list
;
888 module
->FindSymbolsWithNameAndType(name
, eSymbolTypeAny
, sc_list
);
889 const Symbol
*const module_symbol
= ProcessMatches(sc_list
, error
);
891 if (!error
.Success()) {
893 } else if (module_symbol
) {
894 return module_symbol
;
899 SymbolContextList sc_list
;
900 target
.GetImages().FindSymbolsWithNameAndType(name
, eSymbolTypeAny
,
902 const Symbol
*const target_symbol
= ProcessMatches(sc_list
, error
);
904 if (!error
.Success()) {
906 } else if (target_symbol
) {
907 return target_symbol
;
911 return nullptr; // no error; we just didn't find anything
915 // SymbolContextSpecifier
918 SymbolContextSpecifier::SymbolContextSpecifier(const TargetSP
&target_sp
)
919 : m_target_sp(target_sp
), m_module_spec(), m_module_sp(), m_file_spec_up(),
920 m_start_line(0), m_end_line(0), m_function_spec(), m_class_name(),
921 m_address_range_up(), m_type(eNothingSpecified
) {}
923 SymbolContextSpecifier::~SymbolContextSpecifier() = default;
925 bool SymbolContextSpecifier::AddLineSpecification(uint32_t line_no
,
926 SpecificationType type
) {
927 bool return_value
= true;
929 case eNothingSpecified
:
932 case eLineStartSpecified
:
933 m_start_line
= line_no
;
934 m_type
|= eLineStartSpecified
;
936 case eLineEndSpecified
:
937 m_end_line
= line_no
;
938 m_type
|= eLineEndSpecified
;
941 return_value
= false;
947 bool SymbolContextSpecifier::AddSpecification(const char *spec_string
,
948 SpecificationType type
) {
949 bool return_value
= true;
951 case eNothingSpecified
:
954 case eModuleSpecified
: {
955 // See if we can find the Module, if so stick it in the SymbolContext.
956 FileSpec
module_file_spec(spec_string
);
957 ModuleSpec
module_spec(module_file_spec
);
958 lldb::ModuleSP module_sp
=
959 m_target_sp
? m_target_sp
->GetImages().FindFirstModule(module_spec
)
961 m_type
|= eModuleSpecified
;
963 m_module_sp
= module_sp
;
965 m_module_spec
.assign(spec_string
);
968 // CompUnits can't necessarily be resolved here, since an inlined function
969 // might show up in a number of CompUnits. Instead we just convert to a
970 // FileSpec and store it away.
971 m_file_spec_up
= std::make_unique
<FileSpec
>(spec_string
);
972 m_type
|= eFileSpecified
;
974 case eLineStartSpecified
:
975 if ((return_value
= llvm::to_integer(spec_string
, m_start_line
)))
976 m_type
|= eLineStartSpecified
;
978 case eLineEndSpecified
:
979 if ((return_value
= llvm::to_integer(spec_string
, m_end_line
)))
980 m_type
|= eLineEndSpecified
;
982 case eFunctionSpecified
:
983 m_function_spec
.assign(spec_string
);
984 m_type
|= eFunctionSpecified
;
986 case eClassOrNamespaceSpecified
:
988 m_class_name
.assign(spec_string
);
989 m_type
= eClassOrNamespaceSpecified
;
991 case eAddressRangeSpecified
:
992 // Not specified yet...
999 void SymbolContextSpecifier::Clear() {
1000 m_module_spec
.clear();
1001 m_file_spec_up
.reset();
1002 m_function_spec
.clear();
1003 m_class_name
.clear();
1006 m_address_range_up
.reset();
1008 m_type
= eNothingSpecified
;
1011 bool SymbolContextSpecifier::SymbolContextMatches(const SymbolContext
&sc
) {
1012 if (m_type
== eNothingSpecified
)
1015 // Only compare targets if this specifier has one and it's not the Dummy
1016 // target. Otherwise if a specifier gets made in the dummy target and
1017 // copied over we'll artificially fail the comparision.
1018 if (m_target_sp
&& !m_target_sp
->IsDummyTarget() &&
1019 m_target_sp
!= sc
.target_sp
)
1022 if (m_type
& eModuleSpecified
) {
1024 if (m_module_sp
.get() != nullptr) {
1025 if (m_module_sp
.get() != sc
.module_sp
.get())
1028 FileSpec
module_file_spec(m_module_spec
);
1029 if (!FileSpec::Match(module_file_spec
, sc
.module_sp
->GetFileSpec()))
1034 if (m_type
& eFileSpecified
) {
1035 if (m_file_spec_up
) {
1036 // If we don't have a block or a comp_unit, then we aren't going to match
1038 if (sc
.block
== nullptr && sc
.comp_unit
== nullptr)
1041 // Check if the block is present, and if so is it inlined:
1042 bool was_inlined
= false;
1043 if (sc
.block
!= nullptr) {
1044 const InlineFunctionInfo
*inline_info
=
1045 sc
.block
->GetInlinedFunctionInfo();
1046 if (inline_info
!= nullptr) {
1048 if (!FileSpec::Match(*m_file_spec_up
,
1049 inline_info
->GetDeclaration().GetFile()))
1054 // Next check the comp unit, but only if the SymbolContext was not
1056 if (!was_inlined
&& sc
.comp_unit
!= nullptr) {
1057 if (!FileSpec::Match(*m_file_spec_up
, sc
.comp_unit
->GetPrimaryFile()))
1062 if (m_type
& eLineStartSpecified
|| m_type
& eLineEndSpecified
) {
1063 if (sc
.line_entry
.line
< m_start_line
|| sc
.line_entry
.line
> m_end_line
)
1067 if (m_type
& eFunctionSpecified
) {
1068 // First check the current block, and if it is inlined, get the inlined
1070 bool was_inlined
= false;
1071 ConstString
func_name(m_function_spec
.c_str());
1073 if (sc
.block
!= nullptr) {
1074 const InlineFunctionInfo
*inline_info
=
1075 sc
.block
->GetInlinedFunctionInfo();
1076 if (inline_info
!= nullptr) {
1078 const Mangled
&name
= inline_info
->GetMangled();
1079 if (!name
.NameMatches(func_name
))
1083 // If it wasn't inlined, check the name in the function or symbol:
1085 if (sc
.function
!= nullptr) {
1086 if (!sc
.function
->GetMangled().NameMatches(func_name
))
1088 } else if (sc
.symbol
!= nullptr) {
1089 if (!sc
.symbol
->GetMangled().NameMatches(func_name
))
1098 bool SymbolContextSpecifier::AddressMatches(lldb::addr_t addr
) {
1099 if (m_type
& eAddressRangeSpecified
) {
1102 Address
match_address(addr
, nullptr);
1104 m_target_sp
->GetImages().ResolveSymbolContextForAddress(
1105 match_address
, eSymbolContextEverything
, sc
);
1106 return SymbolContextMatches(sc
);
1111 void SymbolContextSpecifier::GetDescription(
1112 Stream
*s
, lldb::DescriptionLevel level
) const {
1113 char path_str
[PATH_MAX
+ 1];
1115 if (m_type
== eNothingSpecified
) {
1116 s
->Printf("Nothing specified.\n");
1119 if (m_type
== eModuleSpecified
) {
1122 m_module_sp
->GetFileSpec().GetPath(path_str
, PATH_MAX
);
1123 s
->Printf("Module: %s\n", path_str
);
1125 s
->Printf("Module: %s\n", m_module_spec
.c_str());
1128 if (m_type
== eFileSpecified
&& m_file_spec_up
!= nullptr) {
1129 m_file_spec_up
->GetPath(path_str
, PATH_MAX
);
1131 s
->Printf("File: %s", path_str
);
1132 if (m_type
== eLineStartSpecified
) {
1133 s
->Printf(" from line %" PRIu64
"", (uint64_t)m_start_line
);
1134 if (m_type
== eLineEndSpecified
)
1135 s
->Printf("to line %" PRIu64
"", (uint64_t)m_end_line
);
1137 s
->Printf("to end");
1138 } else if (m_type
== eLineEndSpecified
) {
1139 s
->Printf(" from start to line %" PRIu64
"", (uint64_t)m_end_line
);
1144 if (m_type
== eLineStartSpecified
) {
1146 s
->Printf("From line %" PRIu64
"", (uint64_t)m_start_line
);
1147 if (m_type
== eLineEndSpecified
)
1148 s
->Printf("to line %" PRIu64
"", (uint64_t)m_end_line
);
1150 s
->Printf("to end");
1152 } else if (m_type
== eLineEndSpecified
) {
1153 s
->Printf("From start to line %" PRIu64
".\n", (uint64_t)m_end_line
);
1156 if (m_type
== eFunctionSpecified
) {
1158 s
->Printf("Function: %s.\n", m_function_spec
.c_str());
1161 if (m_type
== eClassOrNamespaceSpecified
) {
1163 s
->Printf("Class name: %s.\n", m_class_name
.c_str());
1166 if (m_type
== eAddressRangeSpecified
&& m_address_range_up
!= nullptr) {
1168 s
->PutCString("Address range: ");
1169 m_address_range_up
->Dump(s
, m_target_sp
.get(),
1170 Address::DumpStyleLoadAddress
,
1171 Address::DumpStyleFileAddress
);
1172 s
->PutCString("\n");
1177 // SymbolContextList
1180 SymbolContextList::SymbolContextList() : m_symbol_contexts() {}
1182 SymbolContextList::~SymbolContextList() = default;
1184 void SymbolContextList::Append(const SymbolContext
&sc
) {
1185 m_symbol_contexts
.push_back(sc
);
1188 void SymbolContextList::Append(const SymbolContextList
&sc_list
) {
1189 collection::const_iterator pos
, end
= sc_list
.m_symbol_contexts
.end();
1190 for (pos
= sc_list
.m_symbol_contexts
.begin(); pos
!= end
; ++pos
)
1191 m_symbol_contexts
.push_back(*pos
);
1194 uint32_t SymbolContextList::AppendIfUnique(const SymbolContextList
&sc_list
,
1195 bool merge_symbol_into_function
) {
1196 uint32_t unique_sc_add_count
= 0;
1197 collection::const_iterator pos
, end
= sc_list
.m_symbol_contexts
.end();
1198 for (pos
= sc_list
.m_symbol_contexts
.begin(); pos
!= end
; ++pos
) {
1199 if (AppendIfUnique(*pos
, merge_symbol_into_function
))
1200 ++unique_sc_add_count
;
1202 return unique_sc_add_count
;
1205 bool SymbolContextList::AppendIfUnique(const SymbolContext
&sc
,
1206 bool merge_symbol_into_function
) {
1207 collection::iterator pos
, end
= m_symbol_contexts
.end();
1208 for (pos
= m_symbol_contexts
.begin(); pos
!= end
; ++pos
) {
1212 if (merge_symbol_into_function
&& sc
.symbol
!= nullptr &&
1213 sc
.comp_unit
== nullptr && sc
.function
== nullptr &&
1214 sc
.block
== nullptr && !sc
.line_entry
.IsValid()) {
1215 if (sc
.symbol
->ValueIsAddress()) {
1216 for (pos
= m_symbol_contexts
.begin(); pos
!= end
; ++pos
) {
1217 // Don't merge symbols into inlined function symbol contexts
1218 if (pos
->block
&& pos
->block
->GetContainingInlinedBlock())
1221 if (pos
->function
) {
1222 if (pos
->function
->GetAddressRange().GetBaseAddress() ==
1223 sc
.symbol
->GetAddressRef()) {
1224 // Do we already have a function with this symbol?
1225 if (pos
->symbol
== sc
.symbol
)
1227 if (pos
->symbol
== nullptr) {
1228 pos
->symbol
= sc
.symbol
;
1236 m_symbol_contexts
.push_back(sc
);
1240 void SymbolContextList::Clear() { m_symbol_contexts
.clear(); }
1242 void SymbolContextList::Dump(Stream
*s
, Target
*target
) const {
1246 s
->PutCString("SymbolContextList");
1250 collection::const_iterator pos
, end
= m_symbol_contexts
.end();
1251 for (pos
= m_symbol_contexts
.begin(); pos
!= end
; ++pos
) {
1252 // pos->Dump(s, target);
1253 pos
->GetDescription(s
, eDescriptionLevelVerbose
, target
);
1258 bool SymbolContextList::GetContextAtIndex(size_t idx
, SymbolContext
&sc
) const {
1259 if (idx
< m_symbol_contexts
.size()) {
1260 sc
= m_symbol_contexts
[idx
];
1266 bool SymbolContextList::RemoveContextAtIndex(size_t idx
) {
1267 if (idx
< m_symbol_contexts
.size()) {
1268 m_symbol_contexts
.erase(m_symbol_contexts
.begin() + idx
);
1274 uint32_t SymbolContextList::GetSize() const { return m_symbol_contexts
.size(); }
1276 bool SymbolContextList::IsEmpty() const { return m_symbol_contexts
.empty(); }
1278 uint32_t SymbolContextList::NumLineEntriesWithLine(uint32_t line
) const {
1279 uint32_t match_count
= 0;
1280 const size_t size
= m_symbol_contexts
.size();
1281 for (size_t idx
= 0; idx
< size
; ++idx
) {
1282 if (m_symbol_contexts
[idx
].line_entry
.line
== line
)
1288 void SymbolContextList::GetDescription(Stream
*s
, lldb::DescriptionLevel level
,
1289 Target
*target
) const {
1290 const size_t size
= m_symbol_contexts
.size();
1291 for (size_t idx
= 0; idx
< size
; ++idx
)
1292 m_symbol_contexts
[idx
].GetDescription(s
, level
, target
);
1295 bool lldb_private::operator==(const SymbolContextList
&lhs
,
1296 const SymbolContextList
&rhs
) {
1297 const uint32_t size
= lhs
.GetSize();
1298 if (size
!= rhs
.GetSize())
1301 SymbolContext lhs_sc
;
1302 SymbolContext rhs_sc
;
1303 for (uint32_t i
= 0; i
< size
; ++i
) {
1304 lhs
.GetContextAtIndex(i
, lhs_sc
);
1305 rhs
.GetContextAtIndex(i
, rhs_sc
);
1306 if (lhs_sc
!= rhs_sc
)
1312 bool lldb_private::operator!=(const SymbolContextList
&lhs
,
1313 const SymbolContextList
&rhs
) {
1314 return !(lhs
== rhs
);