1 //===-- Variable.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/Variable.h"
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/ValueObject.h"
13 #include "lldb/Core/ValueObjectVariable.h"
14 #include "lldb/Symbol/Block.h"
15 #include "lldb/Symbol/CompileUnit.h"
16 #include "lldb/Symbol/CompilerDecl.h"
17 #include "lldb/Symbol/CompilerDeclContext.h"
18 #include "lldb/Symbol/Function.h"
19 #include "lldb/Symbol/SymbolContext.h"
20 #include "lldb/Symbol/SymbolFile.h"
21 #include "lldb/Symbol/Type.h"
22 #include "lldb/Symbol/TypeSystem.h"
23 #include "lldb/Symbol/VariableList.h"
24 #include "lldb/Target/ABI.h"
25 #include "lldb/Target/Process.h"
26 #include "lldb/Target/RegisterContext.h"
27 #include "lldb/Target/StackFrame.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Target/Thread.h"
30 #include "lldb/Utility/RegularExpression.h"
31 #include "lldb/Utility/Stream.h"
33 #include "llvm/ADT/Twine.h"
36 using namespace lldb_private
;
38 Variable::Variable(lldb::user_id_t uid
, const char *name
, const char *mangled
,
39 const lldb::SymbolFileTypeSP
&symfile_type_sp
,
40 ValueType scope
, SymbolContextScope
*context
,
41 const RangeList
&scope_range
, Declaration
*decl_ptr
,
42 const DWARFExpressionList
&location_list
, bool external
,
43 bool artificial
, bool location_is_constant_data
,
45 : UserID(uid
), m_name(name
), m_mangled(ConstString(mangled
)),
46 m_symfile_type_sp(symfile_type_sp
), m_scope(scope
),
47 m_owner_scope(context
), m_scope_range(scope_range
),
48 m_declaration(decl_ptr
), m_location_list(location_list
), m_external(external
),
49 m_artificial(artificial
), m_loc_is_const_data(location_is_constant_data
),
50 m_static_member(static_member
) {}
52 Variable::~Variable() = default;
54 lldb::LanguageType
Variable::GetLanguage() const {
55 lldb::LanguageType lang
= m_mangled
.GuessLanguage();
56 if (lang
!= lldb::eLanguageTypeUnknown
)
59 if (auto *func
= m_owner_scope
->CalculateSymbolContextFunction()) {
60 if ((lang
= func
->GetLanguage()) != lldb::eLanguageTypeUnknown
)
62 } else if (auto *comp_unit
=
63 m_owner_scope
->CalculateSymbolContextCompileUnit()) {
64 if ((lang
= comp_unit
->GetLanguage()) != lldb::eLanguageTypeUnknown
)
68 return lldb::eLanguageTypeUnknown
;
71 ConstString
Variable::GetName() const {
72 ConstString name
= m_mangled
.GetName();
78 ConstString
Variable::GetUnqualifiedName() const { return m_name
; }
80 bool Variable::NameMatches(ConstString name
) const {
83 SymbolContext variable_sc
;
84 m_owner_scope
->CalculateSymbolContext(&variable_sc
);
86 return m_mangled
.NameMatches(name
);
88 bool Variable::NameMatches(const RegularExpression
®ex
) const {
89 if (regex
.Execute(m_name
.AsCString()))
92 return m_mangled
.NameMatches(regex
);
96 Type
*Variable::GetType() {
97 if (m_symfile_type_sp
)
98 return m_symfile_type_sp
->GetType();
102 void Variable::Dump(Stream
*s
, bool show_context
) const {
103 s
->Printf("%p: ", static_cast<const void *>(this));
105 *s
<< "Variable" << (const UserID
&)*this;
108 *s
<< ", name = \"" << m_name
<< "\"";
110 if (m_symfile_type_sp
) {
111 Type
*type
= m_symfile_type_sp
->GetType();
113 s
->Format(", type = {{{0:x-16}} {1} (", type
->GetID(), type
);
114 type
->DumpTypeName(s
);
119 if (m_scope
!= eValueTypeInvalid
) {
120 s
->PutCString(", scope = ");
122 case eValueTypeVariableGlobal
:
123 s
->PutCString(m_external
? "global" : "static");
125 case eValueTypeVariableArgument
:
126 s
->PutCString("parameter");
128 case eValueTypeVariableLocal
:
129 s
->PutCString("local");
131 case eValueTypeVariableThreadLocal
:
132 s
->PutCString("thread local");
135 s
->AsRawOstream() << "??? (" << m_scope
<< ')';
139 if (show_context
&& m_owner_scope
!= nullptr) {
140 s
->PutCString(", context = ( ");
141 m_owner_scope
->DumpSymbolContext(s
);
145 bool show_fullpaths
= false;
146 m_declaration
.Dump(s
, show_fullpaths
);
148 if (m_location_list
.IsValid()) {
149 s
->PutCString(", location = ");
152 ModuleSP
module_sp(m_owner_scope
->CalculateSymbolContextModule());
154 abi
= ABI::FindPlugin(ProcessSP(), module_sp
->GetArchitecture());
156 m_location_list
.GetDescription(s
, lldb::eDescriptionLevelBrief
, abi
.get());
160 s
->PutCString(", external");
163 s
->PutCString(", artificial");
168 bool Variable::DumpDeclaration(Stream
*s
, bool show_fullpaths
,
170 bool dumped_declaration_info
= false;
173 m_owner_scope
->CalculateSymbolContext(&sc
);
175 sc
.line_entry
.Clear();
176 bool show_inlined_frames
= false;
177 const bool show_function_arguments
= true;
178 const bool show_function_name
= true;
180 dumped_declaration_info
= sc
.DumpStopContext(
181 s
, nullptr, Address(), show_fullpaths
, show_module
, show_inlined_frames
,
182 show_function_arguments
, show_function_name
);
187 if (m_declaration
.DumpStopContext(s
, false))
188 dumped_declaration_info
= true;
189 return dumped_declaration_info
;
192 size_t Variable::MemorySize() const { return sizeof(Variable
); }
194 CompilerDeclContext
Variable::GetDeclContext() {
195 Type
*type
= GetType();
197 return type
->GetSymbolFile()->GetDeclContextContainingUID(GetID());
198 return CompilerDeclContext();
201 CompilerDecl
Variable::GetDecl() {
202 Type
*type
= GetType();
203 return type
? type
->GetSymbolFile()->GetDeclForUID(GetID()) : CompilerDecl();
206 void Variable::CalculateSymbolContext(SymbolContext
*sc
) {
208 m_owner_scope
->CalculateSymbolContext(sc
);
214 bool Variable::LocationIsValidForFrame(StackFrame
*frame
) {
217 frame
->GetSymbolContext(eSymbolContextFunction
).function
;
219 TargetSP
target_sp(frame
->CalculateTarget());
221 addr_t loclist_base_load_addr
=
222 function
->GetAddressRange().GetBaseAddress().GetLoadAddress(
224 if (loclist_base_load_addr
== LLDB_INVALID_ADDRESS
)
226 // It is a location list. We just need to tell if the location list
227 // contains the current address when converted to a load address
228 return m_location_list
.ContainsAddress(
229 loclist_base_load_addr
,
230 frame
->GetFrameCodeAddress().GetLoadAddress(target_sp
.get()));
236 bool Variable::LocationIsValidForAddress(const Address
&address
) {
237 // Be sure to resolve the address to section offset prior to calling this
239 if (address
.IsSectionOffset()) {
240 // We need to check if the address is valid for both scope range and value
242 // Empty scope range means block range.
243 bool valid_in_scope_range
=
244 GetScopeRange().IsEmpty() || GetScopeRange().FindEntryThatContains(
245 address
.GetFileAddress()) != nullptr;
246 if (!valid_in_scope_range
)
249 CalculateSymbolContext(&sc
);
250 if (sc
.module_sp
== address
.GetModule()) {
251 // Is the variable is described by a single location?
252 if (m_location_list
.IsAlwaysValidSingleExpr()) {
253 // Yes it is, the location is valid.
258 addr_t loclist_base_file_addr
=
259 sc
.function
->GetAddressRange().GetBaseAddress().GetFileAddress();
260 if (loclist_base_file_addr
== LLDB_INVALID_ADDRESS
)
262 // It is a location list. We just need to tell if the location list
263 // contains the current address when converted to a load address
264 return m_location_list
.ContainsAddress(loclist_base_file_addr
,
265 address
.GetFileAddress());
272 bool Variable::IsInScope(StackFrame
*frame
) {
274 case eValueTypeRegister
:
275 case eValueTypeRegisterSet
:
276 return frame
!= nullptr;
278 case eValueTypeConstResult
:
279 case eValueTypeVariableGlobal
:
280 case eValueTypeVariableStatic
:
281 case eValueTypeVariableThreadLocal
:
284 case eValueTypeVariableArgument
:
285 case eValueTypeVariableLocal
:
287 // We don't have a location list, we just need to see if the block that
288 // this variable was defined in is currently
289 Block
*deepest_frame_block
=
290 frame
->GetSymbolContext(eSymbolContextBlock
).block
;
291 if (deepest_frame_block
) {
292 SymbolContext variable_sc
;
293 CalculateSymbolContext(&variable_sc
);
295 // Check for static or global variable defined at the compile unit
296 // level that wasn't defined in a block
297 if (variable_sc
.block
== nullptr)
300 // Check if the variable is valid in the current block
301 if (variable_sc
.block
!= deepest_frame_block
&&
302 !variable_sc
.block
->Contains(deepest_frame_block
))
305 // If no scope range is specified then it means that the scope is the
306 // same as the scope of the enclosing lexical block.
307 if (m_scope_range
.IsEmpty())
310 addr_t file_address
= frame
->GetFrameCodeAddress().GetFileAddress();
311 return m_scope_range
.FindEntryThatContains(file_address
) != nullptr;
322 Status
Variable::GetValuesForVariableExpressionPath(
323 llvm::StringRef variable_expr_path
, ExecutionContextScope
*scope
,
324 GetVariableCallback callback
, void *baton
, VariableList
&variable_list
,
325 ValueObjectList
&valobj_list
) {
327 if (!callback
|| variable_expr_path
.empty()) {
328 error
.SetErrorString("unknown error");
332 switch (variable_expr_path
.front()) {
334 error
= Variable::GetValuesForVariableExpressionPath(
335 variable_expr_path
.drop_front(), scope
, callback
, baton
, variable_list
,
338 error
.SetErrorString("unknown error");
341 for (uint32_t i
= 0; i
< valobj_list
.GetSize();) {
343 ValueObjectSP
valobj_sp(
344 valobj_list
.GetValueObjectAtIndex(i
)->Dereference(tmp_error
));
345 if (tmp_error
.Fail()) {
346 variable_list
.RemoveVariableAtIndex(i
);
347 valobj_list
.RemoveValueObjectAtIndex(i
);
349 valobj_list
.SetValueObjectAtIndex(i
, valobj_sp
);
355 error
= Variable::GetValuesForVariableExpressionPath(
356 variable_expr_path
.drop_front(), scope
, callback
, baton
, variable_list
,
358 if (error
.Success()) {
359 for (uint32_t i
= 0; i
< valobj_list
.GetSize();) {
361 ValueObjectSP
valobj_sp(
362 valobj_list
.GetValueObjectAtIndex(i
)->AddressOf(tmp_error
));
363 if (tmp_error
.Fail()) {
364 variable_list
.RemoveVariableAtIndex(i
);
365 valobj_list
.RemoveValueObjectAtIndex(i
);
367 valobj_list
.SetValueObjectAtIndex(i
, valobj_sp
);
372 error
.SetErrorString("unknown error");
378 static RegularExpression
g_regex(
379 llvm::StringRef("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)"));
380 llvm::SmallVector
<llvm::StringRef
, 2> matches
;
381 variable_list
.Clear();
382 if (!g_regex
.Execute(variable_expr_path
, &matches
)) {
383 error
.SetErrorStringWithFormatv(
384 "unable to extract a variable name from '{0}'", variable_expr_path
);
387 std::string variable_name
= matches
[1].str();
388 if (!callback(baton
, variable_name
.c_str(), variable_list
)) {
389 error
.SetErrorString("unknown error");
393 while (i
< variable_list
.GetSize()) {
394 VariableSP
var_sp(variable_list
.GetVariableAtIndex(i
));
395 ValueObjectSP valobj_sp
;
397 variable_list
.RemoveVariableAtIndex(i
);
400 ValueObjectSP
variable_valobj_sp(
401 ValueObjectVariable::Create(scope
, var_sp
));
402 if (!variable_valobj_sp
) {
403 variable_list
.RemoveVariableAtIndex(i
);
407 llvm::StringRef variable_sub_expr_path
=
408 variable_expr_path
.drop_front(variable_name
.size());
409 if (!variable_sub_expr_path
.empty()) {
410 valobj_sp
= variable_valobj_sp
->GetValueForExpressionPath(
411 variable_sub_expr_path
);
413 error
.SetErrorStringWithFormatv(
414 "invalid expression path '{0}' for variable '{1}'",
415 variable_sub_expr_path
, var_sp
->GetName().GetCString());
416 variable_list
.RemoveVariableAtIndex(i
);
420 // Just the name of a variable with no extras
421 valobj_sp
= variable_valobj_sp
;
424 valobj_list
.Append(valobj_sp
);
428 if (variable_list
.GetSize() > 0) {
434 error
.SetErrorString("unknown error");
438 bool Variable::DumpLocations(Stream
*s
, const Address
&address
) {
440 CalculateSymbolContext(&sc
);
443 ModuleSP
module_sp(m_owner_scope
->CalculateSymbolContextModule());
445 abi
= ABI::FindPlugin(ProcessSP(), module_sp
->GetArchitecture());
448 const addr_t file_addr
= address
.GetFileAddress();
450 addr_t loclist_base_file_addr
=
451 sc
.function
->GetAddressRange().GetBaseAddress().GetFileAddress();
452 if (loclist_base_file_addr
== LLDB_INVALID_ADDRESS
)
454 return m_location_list
.DumpLocations(s
, eDescriptionLevelBrief
,
455 loclist_base_file_addr
, file_addr
,
461 static void PrivateAutoComplete(
462 StackFrame
*frame
, llvm::StringRef partial_path
,
464 &prefix_path
, // Anything that has been resolved already will be in here
465 const CompilerType
&compiler_type
, CompletionRequest
&request
);
467 static void PrivateAutoCompleteMembers(
468 StackFrame
*frame
, const std::string
&partial_member_name
,
469 llvm::StringRef partial_path
,
471 &prefix_path
, // Anything that has been resolved already will be in here
472 const CompilerType
&compiler_type
, CompletionRequest
&request
) {
474 // We are in a type parsing child members
475 const uint32_t num_bases
= compiler_type
.GetNumDirectBaseClasses();
478 for (uint32_t i
= 0; i
< num_bases
; ++i
) {
479 CompilerType base_class_type
=
480 compiler_type
.GetDirectBaseClassAtIndex(i
, nullptr);
482 PrivateAutoCompleteMembers(frame
, partial_member_name
, partial_path
,
484 base_class_type
.GetCanonicalType(), request
);
488 const uint32_t num_vbases
= compiler_type
.GetNumVirtualBaseClasses();
490 if (num_vbases
> 0) {
491 for (uint32_t i
= 0; i
< num_vbases
; ++i
) {
492 CompilerType vbase_class_type
=
493 compiler_type
.GetVirtualBaseClassAtIndex(i
, nullptr);
495 PrivateAutoCompleteMembers(frame
, partial_member_name
, partial_path
,
497 vbase_class_type
.GetCanonicalType(), request
);
501 // We are in a type parsing child members
502 const uint32_t num_fields
= compiler_type
.GetNumFields();
504 if (num_fields
> 0) {
505 for (uint32_t i
= 0; i
< num_fields
; ++i
) {
506 std::string member_name
;
508 CompilerType member_compiler_type
= compiler_type
.GetFieldAtIndex(
509 i
, member_name
, nullptr, nullptr, nullptr);
511 if (partial_member_name
.empty() ||
512 llvm::StringRef(member_name
).startswith(partial_member_name
)) {
513 if (member_name
== partial_member_name
) {
516 prefix_path
+ member_name
, // Anything that has been resolved
517 // already will be in here
518 member_compiler_type
.GetCanonicalType(), request
);
520 request
.AddCompletion((prefix_path
+ member_name
).str());
527 static void PrivateAutoComplete(
528 StackFrame
*frame
, llvm::StringRef partial_path
,
530 &prefix_path
, // Anything that has been resolved already will be in here
531 const CompilerType
&compiler_type
, CompletionRequest
&request
) {
532 // printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path =
533 // '%s'\n", prefix_path.c_str(), partial_path.c_str());
534 std::string remaining_partial_path
;
536 const lldb::TypeClass type_class
= compiler_type
.GetTypeClass();
537 if (partial_path
.empty()) {
538 if (compiler_type
.IsValid()) {
539 switch (type_class
) {
541 case eTypeClassArray
:
542 case eTypeClassBlockPointer
:
543 case eTypeClassBuiltin
:
544 case eTypeClassComplexFloat
:
545 case eTypeClassComplexInteger
:
546 case eTypeClassEnumeration
:
547 case eTypeClassFunction
:
548 case eTypeClassMemberPointer
:
549 case eTypeClassReference
:
550 case eTypeClassTypedef
:
551 case eTypeClassVector
: {
552 request
.AddCompletion(prefix_path
.str());
555 case eTypeClassClass
:
556 case eTypeClassStruct
:
557 case eTypeClassUnion
:
558 if (prefix_path
.str().back() != '.')
559 request
.AddCompletion((prefix_path
+ ".").str());
562 case eTypeClassObjCObject
:
563 case eTypeClassObjCInterface
:
565 case eTypeClassObjCObjectPointer
:
566 case eTypeClassPointer
: {
567 bool omit_empty_base_classes
= true;
568 if (compiler_type
.GetNumChildren(omit_empty_base_classes
, nullptr) > 0)
569 request
.AddCompletion((prefix_path
+ "->").str());
571 request
.AddCompletion(prefix_path
.str());
577 const bool get_file_globals
= true;
579 VariableList
*variable_list
= frame
->GetVariableList(get_file_globals
,
583 for (const VariableSP
&var_sp
: *variable_list
)
584 request
.AddCompletion(var_sp
->GetName().AsCString());
589 const char ch
= partial_path
[0];
592 if (prefix_path
.str().empty()) {
593 PrivateAutoComplete(frame
, partial_path
.substr(1), "*", compiler_type
,
599 if (prefix_path
.isTriviallyEmpty()) {
600 PrivateAutoComplete(frame
, partial_path
.substr(1), std::string("&"),
601 compiler_type
, request
);
606 if (partial_path
.size() > 1 && partial_path
[1] == '>' &&
607 !prefix_path
.str().empty()) {
608 switch (type_class
) {
609 case lldb::eTypeClassPointer
: {
610 CompilerType
pointee_type(compiler_type
.GetPointeeType());
611 if (partial_path
.size() > 2 && partial_path
[2]) {
612 // If there is more after the "->", then search deeper
613 PrivateAutoComplete(frame
, partial_path
.substr(2),
615 pointee_type
.GetCanonicalType(), request
);
617 // Nothing after the "->", so list all members
618 PrivateAutoCompleteMembers(
619 frame
, std::string(), std::string(), prefix_path
+ "->",
620 pointee_type
.GetCanonicalType(), request
);
630 if (compiler_type
.IsValid()) {
631 switch (type_class
) {
632 case lldb::eTypeClassUnion
:
633 case lldb::eTypeClassStruct
:
634 case lldb::eTypeClassClass
:
635 if (partial_path
.size() > 1 && partial_path
[1]) {
636 // If there is more after the ".", then search deeper
637 PrivateAutoComplete(frame
, partial_path
.substr(1),
638 prefix_path
+ ".", compiler_type
, request
);
641 // Nothing after the ".", so list all members
642 PrivateAutoCompleteMembers(frame
, std::string(), partial_path
,
643 prefix_path
+ ".", compiler_type
,
653 if (isalpha(ch
) || ch
== '_' || ch
== '$') {
654 const size_t partial_path_len
= partial_path
.size();
656 while (pos
< partial_path_len
) {
657 const char curr_ch
= partial_path
[pos
];
658 if (isalnum(curr_ch
) || curr_ch
== '_' || curr_ch
== '$') {
665 std::string
token(std::string(partial_path
), 0, pos
);
666 remaining_partial_path
= std::string(partial_path
.substr(pos
));
668 if (compiler_type
.IsValid()) {
669 PrivateAutoCompleteMembers(frame
, token
, remaining_partial_path
,
670 prefix_path
, compiler_type
, request
);
672 // We haven't found our variable yet
673 const bool get_file_globals
= true;
675 VariableList
*variable_list
=
676 frame
->GetVariableList(get_file_globals
, nullptr);
681 for (VariableSP var_sp
: *variable_list
) {
686 llvm::StringRef variable_name
= var_sp
->GetName().GetStringRef();
687 if (variable_name
.startswith(token
)) {
688 if (variable_name
== token
) {
689 Type
*variable_type
= var_sp
->GetType();
691 CompilerType
variable_compiler_type(
692 variable_type
->GetForwardCompilerType());
694 frame
, remaining_partial_path
,
695 prefix_path
+ token
, // Anything that has been resolved
696 // already will be in here
697 variable_compiler_type
.GetCanonicalType(), request
);
699 request
.AddCompletion((prefix_path
+ variable_name
).str());
701 } else if (remaining_partial_path
.empty()) {
702 request
.AddCompletion((prefix_path
+ variable_name
).str());
713 void Variable::AutoComplete(const ExecutionContext
&exe_ctx
,
714 CompletionRequest
&request
) {
715 CompilerType compiler_type
;
717 PrivateAutoComplete(exe_ctx
.GetFramePtr(), request
.GetCursorArgumentPrefix(),
718 "", compiler_type
, request
);