51#define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextLastItem) << 1)
52#define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1)
53#define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1)
54#define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1)
55#define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1)
60 bool artificial,
bool behaves_like_zeroth_frame,
64 m_id(
pc, cfa, nullptr, thread_sp->GetProcess().get()),
78 if (sc_ptr !=
nullptr) {
87 addr_t pc,
bool behaves_like_zeroth_frame,
92 m_id(
pc, cfa, nullptr, thread_sp->GetProcess().get()),
99 if (sc_ptr !=
nullptr) {
104 if (reg_context_sp && !
m_sc.target_sp) {
105 m_sc.target_sp = reg_context_sp->CalculateTarget();
107 m_flags.Set(eSymbolContextTarget);
114 const Address &pc_addr,
bool behaves_like_zeroth_frame,
120 nullptr, thread_sp->GetProcess().get()),
127 if (sc_ptr !=
nullptr) {
132 if (!
m_sc.target_sp && reg_context_sp) {
133 m_sc.target_sp = reg_context_sp->CalculateTarget();
135 m_flags.Set(eSymbolContextTarget);
139 if (!
m_sc.module_sp ||
m_sc.module_sp != pc_module_sp) {
141 m_sc.module_sp = pc_module_sp;
142 m_flags.Set(eSymbolContextModule);
144 m_sc.module_sp.reset();
152 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
157 if (
m_id.GetSymbolContextScope()) {
165 if (scope ==
nullptr) {
167 if (
m_flags.IsClear(eSymbolContextSymbol))
184 return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex(
191 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
193 m_id.SetSymbolContextScope(symbol_scope);
197 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
206 TargetSP target_sp(thread_sp->CalculateTarget());
208 const bool allow_section_end =
true;
214 m_sc.module_sp = module_sp;
215 m_flags.Set(eSymbolContextModule);
254 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
263 thread_sp->ClearStackFrames();
268 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
283 if (
m_sc.block ==
nullptr &&
m_flags.IsClear(eSymbolContextBlock))
287 Block *inline_block =
m_sc.block->GetContainingInlinedBlock();
296 return &
m_sc.function->GetBlock(
false);
308 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
310 if ((
m_flags.Get() & resolve_scope) != resolve_scope) {
311 uint32_t resolved = 0;
314 if (!
m_sc.target_sp) {
317 resolved |= eSymbolContextTarget;
331 if (
m_sc.module_sp) {
336 SymbolContextItem actual_resolve_scope = SymbolContextItem(0);
338 if (resolve_scope & eSymbolContextCompUnit) {
339 if (
m_flags.IsClear(eSymbolContextCompUnit)) {
341 resolved |= eSymbolContextCompUnit;
343 actual_resolve_scope |= eSymbolContextCompUnit;
347 if (resolve_scope & eSymbolContextFunction) {
348 if (
m_flags.IsClear(eSymbolContextFunction)) {
350 resolved |= eSymbolContextFunction;
352 actual_resolve_scope |= eSymbolContextFunction;
356 if (resolve_scope & eSymbolContextBlock) {
357 if (
m_flags.IsClear(eSymbolContextBlock)) {
359 resolved |= eSymbolContextBlock;
361 actual_resolve_scope |= eSymbolContextBlock;
365 if (resolve_scope & eSymbolContextSymbol) {
366 if (
m_flags.IsClear(eSymbolContextSymbol)) {
368 resolved |= eSymbolContextSymbol;
370 actual_resolve_scope |= eSymbolContextSymbol;
374 if (resolve_scope & eSymbolContextLineEntry) {
375 if (
m_flags.IsClear(eSymbolContextLineEntry)) {
376 if (
m_sc.line_entry.IsValid())
377 resolved |= eSymbolContextLineEntry;
379 actual_resolve_scope |= eSymbolContextLineEntry;
383 if (actual_resolve_scope) {
389 resolved |=
m_sc.module_sp->ResolveSymbolContextForAddress(
390 lookup_addr, actual_resolve_scope, sc);
394 if ((resolved & eSymbolContextCompUnit) &&
m_sc.comp_unit ==
nullptr)
396 if ((resolved & eSymbolContextFunction) &&
m_sc.function ==
nullptr)
398 if ((resolved & eSymbolContextBlock) &&
m_sc.block ==
nullptr)
400 if ((resolved & eSymbolContextSymbol) &&
m_sc.symbol ==
nullptr)
402 if ((resolved & eSymbolContextLineEntry) &&
403 !
m_sc.line_entry.IsValid()) {
405 m_sc.line_entry.ApplyFileMappings(
m_sc.target_sp);
412 if (
m_sc.target_sp) {
413 resolved |=
m_sc.target_sp->GetImages().ResolveSymbolContextForAddress(
414 lookup_addr, resolve_scope,
m_sc);
423 m_flags.Set(resolve_scope | resolved);
433 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
441 const bool get_child_variables =
true;
442 const bool can_create =
true;
443 const bool stop_if_child_block_is_inlined_function =
true;
445 can_create, get_child_variables,
446 stop_if_child_block_is_inlined_function,
454 if (
m_flags.IsClear(eSymbolContextCompUnit))
457 if (
m_sc.comp_unit) {
459 m_sc.comp_unit->GetVariableList(
true));
471 if (
m_sc.module_sp) {
483 bool must_have_valid_location) {
484 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
493 const bool can_create =
true;
494 const bool get_parent_variables =
true;
495 const bool stop_if_block_is_inlined_function =
true;
496 m_sc.block->AppendVariables(
497 can_create, get_parent_variables, stop_if_block_is_inlined_function,
498 [
this, must_have_valid_location](
Variable *v) {
499 return v->
IsInScope(
this) && (!must_have_valid_location ||
505 if (
m_sc.comp_unit && get_file_globals) {
507 m_sc.comp_unit->GetVariableList(
true));
508 if (global_variable_list_sp)
509 var_list_sp->AddVariables(global_variable_list_sp.get());
533 const bool check_ptr_vs_member =
535 const bool no_fragile_ivar =
537 const bool no_synth_child =
549 var_expr, std::move(*lex_or_err), shared_from_this(), use_dynamic,
550 !no_synth_child, !no_fragile_ivar, check_ptr_vs_member);
551 if (!tree_or_error) {
559 use_dynamic, !no_synth_child, !no_fragile_ivar,
560 check_ptr_vs_member);
562 auto valobj_or_error = interpreter.
Evaluate((*tree_or_error).get());
563 if (!valobj_or_error) {
568 var_sp = (*valobj_or_error)->GetVariable();
569 return *valobj_or_error;
575 llvm::StringRef original_var_expr = var_expr;
580 if (var_expr.empty()) {
586 const bool check_ptr_vs_member =
588 const bool no_fragile_ivar =
590 const bool no_synth_child =
596 bool address_of =
false;
598 const bool get_file_globals =
true;
608 std::string var_expr_storage;
609 if (var_expr[0] ==
'*') {
611 var_expr = var_expr.drop_front();
612 }
else if (var_expr[0] ==
'&') {
614 var_expr = var_expr.drop_front();
617 size_t separator_idx = var_expr.find_first_of(
".-[=+~|&^%#@!/?,<>{}");
620 ConstString name_const_string(var_expr.substr(0, separator_idx));
622 var_sp = variable_list->
FindVariable(name_const_string,
false);
624 bool synthetically_added_instance_object =
false;
627 var_expr = var_expr.drop_front(name_const_string.
GetLength());
634 llvm::StringRef instance_var_name =
m_sc.GetInstanceVariableName();
635 if (!instance_var_name.empty()) {
639 if (
Type *var_type = var_sp->GetType())
640 if (
auto compiler_type = var_type->GetForwardCompilerType())
641 if (!compiler_type.IsPointerType())
642 var_expr_storage =
".";
644 if (var_expr_storage.empty())
645 var_expr_storage =
"->";
646 var_expr_storage += var_expr;
647 var_expr = var_expr_storage;
648 synthetically_added_instance_object =
true;
656 for (
const VariableSP &variable_sp : *variable_list) {
659 if (!variable_sp->GetName().IsEmpty())
662 Type *var_type = variable_sp->GetType();
671 valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string);
677 if (var_sp && !valobj_sp) {
684 "no variable named '{0}' found in this frame", name_const_string);
689 while (!var_expr.empty()) {
692 const char separator_type = var_expr[0];
693 bool expr_is_ptr =
false;
694 switch (separator_type) {
697 if (var_expr.size() >= 2 && var_expr[1] !=
'>')
700 if (no_fragile_ivar) {
703 const uint32_t pointer_type_flags =
704 valobj_sp->GetCompilerType().GetTypeInfo(
nullptr);
705 if ((pointer_type_flags & eTypeIsObjC) &&
706 (pointer_type_flags & eTypeIsPointer)) {
715 if (!valobj_sp->IsPointerType() && valobj_sp->HasSyntheticValue()) {
718 valobj_sp->GetSyntheticValue()->Dereference(deref_error);
719 synth_deref_sp && deref_error.
Success()) {
720 valobj_sp = std::move(synth_deref_sp);
722 if (!valobj_sp || deref_error.
Fail()) {
724 "Failed to dereference synthetic value: {0}", deref_error);
737 var_expr = var_expr.drop_front();
740 var_expr = var_expr.drop_front();
741 separator_idx = var_expr.find_first_of(
".-[");
742 ConstString child_name(var_expr.substr(0, var_expr.find_first_of(
".-[")));
744 if (check_ptr_vs_member) {
748 const bool actual_is_ptr = valobj_sp->IsPointerType();
750 if (actual_is_ptr != expr_is_ptr) {
753 valobj_sp->GetExpressionPath(var_expr_path_strm);
756 "\"%s\" is a pointer and . was used to attempt to access "
757 "\"%s\". Did you mean \"%s->%s\"?",
759 var_expr_path_strm.
GetData(), var_expr.str().c_str());
762 "\"%s\" is not a pointer and -> was used to attempt to "
763 "access \"%s\". Did you mean \"%s.%s\"?",
765 var_expr_path_strm.
GetData(), var_expr.str().c_str());
769 child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name);
770 if (!child_valobj_sp) {
771 if (!no_synth_child) {
772 child_valobj_sp = valobj_sp->GetSyntheticValue();
775 child_valobj_sp->GetChildMemberWithName(child_name);
778 if (no_synth_child || !child_valobj_sp) {
780 if (synthetically_added_instance_object) {
785 "no variable or instance variable named '%s' found in "
789 valobj_sp->GetExpressionPath(var_expr_path_strm);
792 "\"%s\" is not a member of \"(%s) %s\"",
794 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
798 "incomplete expression path after \"%s\" in \"%s\"",
800 original_var_expr.str().c_str());
806 synthetically_added_instance_object =
false;
808 var_expr = var_expr.drop_front(child_name.
GetLength());
811 child_valobj_sp->GetDynamicValue(use_dynamic));
812 if (dynamic_value_sp)
813 child_valobj_sp = dynamic_value_sp;
820 if (var_expr.size() <= 2) {
822 "invalid square bracket encountered after \"%s\" in \"%s\"",
823 var_expr_path_strm.
GetData(), var_expr.str().c_str());
828 var_expr = var_expr.drop_front();
829 long child_index = 0;
832 size_t end_pos = var_expr.find_first_of(
']');
833 if (end_pos == llvm::StringRef::npos) {
835 "missing closing square bracket in expression \"%s\"",
839 llvm::StringRef index_expr = var_expr.take_front(end_pos);
840 llvm::StringRef original_index_expr = index_expr;
842 var_expr = var_expr.drop_front(end_pos + 1);
844 if (index_expr.consumeInteger(0, child_index)) {
848 "invalid index expression \"%s\"", index_expr.str().c_str());
852 if (index_expr.empty()) {
855 if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {
861 if (!temp || deref_error.
Fail()) {
862 valobj_sp->GetExpressionPath(var_expr_path_strm);
864 "could not dereference \"(%s) %s\"",
865 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
871 }
else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() &&
879 valobj_sp->GetExpressionPath(var_expr_path_strm);
881 "could not get item 0 for \"(%s) %s\"",
882 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
890 bool is_incomplete_array =
false;
891 if (valobj_sp->IsPointerType()) {
892 bool is_objc_pointer =
true;
894 if (valobj_sp->GetCompilerType().GetMinimumLanguage() !=
896 is_objc_pointer =
false;
897 else if (!valobj_sp->GetCompilerType().IsPointerType())
898 is_objc_pointer =
false;
900 if (no_synth_child && is_objc_pointer) {
902 "\"(%s) %s\" is an Objective-C pointer, and cannot be "
904 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
908 }
else if (is_objc_pointer) {
913 || synthetic == valobj_sp)
916 valobj_sp->GetExpressionPath(var_expr_path_strm);
918 "\"(%s) %s\" is not an array type",
919 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
921 }
else if (
static_cast<uint32_t
>(child_index) >=
923 ->GetNumChildrenIgnoringErrors()
926 valobj_sp->GetExpressionPath(var_expr_path_strm);
928 "array index %ld is not valid for \"(%s) %s\"", child_index,
929 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
932 child_valobj_sp = synthetic->GetChildAtIndex(child_index);
933 if (!child_valobj_sp) {
934 valobj_sp->GetExpressionPath(var_expr_path_strm);
936 "array index %ld is not valid for \"(%s) %s\"", child_index,
937 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
943 valobj_sp->GetSyntheticArrayMember(child_index,
true);
944 if (!child_valobj_sp) {
945 valobj_sp->GetExpressionPath(var_expr_path_strm);
947 "failed to use pointer as array for index %ld for "
950 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
954 }
else if (valobj_sp->GetCompilerType().IsArrayType(
955 nullptr,
nullptr, &is_incomplete_array)) {
958 child_valobj_sp = valobj_sp->GetChildAtIndex(child_index);
959 if (!child_valobj_sp && (is_incomplete_array || !no_synth_child))
961 valobj_sp->GetSyntheticArrayMember(child_index,
true);
963 if (!child_valobj_sp) {
964 valobj_sp->GetExpressionPath(var_expr_path_strm);
966 "array index %ld is not valid for \"(%s) %s\"", child_index,
967 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
970 }
else if (valobj_sp->GetCompilerType().IsScalarType()) {
972 child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(
973 child_index, child_index,
true);
974 if (!child_valobj_sp) {
975 valobj_sp->GetExpressionPath(var_expr_path_strm);
977 "bitfield range %ld-%ld is not valid for \"(%s) %s\"",
978 child_index, child_index,
979 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
984 if (no_synth_child ||
986 || synthetic == valobj_sp)
989 valobj_sp->GetExpressionPath(var_expr_path_strm);
991 "\"(%s) %s\" is not an array type",
992 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
994 }
else if (
static_cast<uint32_t
>(child_index) >=
995 synthetic->GetNumChildrenIgnoringErrors()
997 valobj_sp->GetExpressionPath(var_expr_path_strm);
999 "array index %ld is not valid for \"(%s) %s\"", child_index,
1000 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
1001 var_expr_path_strm.
GetData());
1003 child_valobj_sp = synthetic->GetChildAtIndex(child_index);
1004 if (!child_valobj_sp) {
1005 valobj_sp->GetExpressionPath(var_expr_path_strm);
1007 "array index %ld is not valid for \"(%s) %s\"", child_index,
1008 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
1009 var_expr_path_strm.
GetData());
1014 if (!child_valobj_sp) {
1021 child_valobj_sp->GetDynamicValue(use_dynamic));
1022 if (dynamic_value_sp)
1023 child_valobj_sp = dynamic_value_sp;
1031 if (index_expr.front() !=
'-') {
1033 "invalid range expression \"'%s'\"",
1034 original_index_expr.str().c_str());
1038 index_expr = index_expr.drop_front();
1039 long final_index = 0;
1040 if (index_expr.getAsInteger(0, final_index)) {
1042 "invalid range expression \"'%s'\"",
1043 original_index_expr.str().c_str());
1048 if (child_index > final_index) {
1049 long temp = child_index;
1050 child_index = final_index;
1054 if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {
1061 if (!temp || deref_error.
Fail()) {
1062 valobj_sp->GetExpressionPath(var_expr_path_strm);
1064 "could not dereference \"(%s) %s\"",
1065 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
1066 var_expr_path_strm.
GetData());
1071 }
else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) {
1078 valobj_sp->GetExpressionPath(var_expr_path_strm);
1080 "could not get item 0 for \"(%s) %s\"",
1081 valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
1082 var_expr_path_strm.
GetData());
1090 valobj_sp->GetSyntheticBitFieldChild(child_index, final_index,
true);
1091 if (!child_valobj_sp) {
1092 valobj_sp->GetExpressionPath(var_expr_path_strm);
1094 "bitfield range %ld-%ld is not valid for \"(%s) %s\"", child_index,
1095 final_index, valobj_sp->GetTypeName().AsCString(
"<invalid type>"),
1096 var_expr_path_strm.
GetData());
1099 if (!child_valobj_sp) {
1106 child_valobj_sp->GetDynamicValue(use_dynamic));
1107 if (dynamic_value_sp)
1108 child_valobj_sp = dynamic_value_sp;
1117 valobj_sp->GetExpressionPath(var_expr_path_strm);
1119 "unexpected char '%c' encountered after \"%s\" in \"%s\"",
1120 separator_type, var_expr_path_strm.
GetData(),
1121 var_expr.str().c_str());
1127 if (child_valobj_sp)
1128 valobj_sp = child_valobj_sp;
1133 if (!deref_valobj_sp && !no_synth_child) {
1134 if (
ValueObjectSP synth_obj_sp = valobj_sp->GetSyntheticValue()) {
1136 deref_valobj_sp = synth_obj_sp->Dereference(
error);
1139 valobj_sp = deref_valobj_sp;
1140 }
else if (address_of) {
1142 valobj_sp = address_of_valobj_sp;
1149 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
1152 "No frame base available for this historical stack frame.");
1157 if (
m_sc.function) {
1164 if (!
m_sc.function->GetFrameBaseExpression().IsAlwaysValidSingleExpr())
1168 llvm::Expected<Value> expr_value =
1169 m_sc.function->GetFrameBaseExpression().Evaluate(
1170 &exe_ctx,
nullptr, loclist_base_addr,
nullptr,
nullptr);
1185 return llvm::Error::success();
1189 if (!
m_sc.function) {
1196 return &
m_sc.function->GetFrameBaseExpression();
1200 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
1211 return m_sc.line_entry.IsValid();
1224 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
1231 const uint32_t var_idx =
1233 const uint32_t num_variables = var_list->
GetSize();
1234 if (var_idx < num_variables) {
1248 ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(use_dynamic);
1256 if (
m_sc.block ==
nullptr)
1259 return m_sc.block->GetContainingInlinedBlock() !=
nullptr;
1275 return recognized_frame_sp->ShouldHide();
1284 if (
auto runtime_sp =
1286 return runtime_sp->GetLanguageSpecificData(
1292 const char *name =
nullptr;
1294 eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol);
1297 if (inlined_block) {
1305 if (name ==
nullptr) {
1310 if (name ==
nullptr) {
1319 const char *name =
nullptr;
1321 eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol);
1324 if (inlined_block) {
1332 if (name ==
nullptr) {
1337 if (name ==
nullptr) {
1367std::pair<const Instruction::Operand *, int64_t>
1370 switch (operand.
m_type) {
1376 return std::make_pair(
nullptr, 0);
1388 if (!immediate_child) {
1389 return std::make_pair(
nullptr, 0);
1397 std::pair<const Instruction::Operand *, int64_t> base_and_offset =
1398 GetBaseExplainingValue(*variable_child, register_context,
1400 if (!base_and_offset.first) {
1401 return std::make_pair(
nullptr, 0);
1404 base_and_offset.second -= immediate_child->
m_immediate;
1406 base_and_offset.second += immediate_child->
m_immediate;
1408 return base_and_offset;
1414 return std::make_pair(
nullptr, 0);
1418 return std::make_pair(
nullptr, 0);
1421 return std::make_pair(&operand, 0);
1423 return std::make_pair(
nullptr, 0);
1427 return std::make_pair(
nullptr, 0);
1430std::pair<const Instruction::Operand *, int64_t>
1435 return GetBaseExplainingValue(operand.
m_children[0], register_context,
1438 return std::make_pair(
nullptr, 0);
1445 const ArchSpec &target_arch = target_sp->GetArchitecture();
1451 const char *plugin_name =
nullptr;
1452 const char *flavor =
nullptr;
1453 const char *cpu =
nullptr;
1454 const char *features =
nullptr;
1455 const bool force_live_memory =
true;
1458 target_arch, plugin_name, flavor, cpu, features, *target_sp, pc_range,
1461 if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
1466 disassembler_sp->GetInstructionList().GetInstructionAtIndex(0);
1468 llvm::SmallVector<Instruction::Operand, 3> operands;
1470 if (!instruction_sp->ParseOperands(operands)) {
1476 if (!register_context_sp) {
1481 std::pair<const Instruction::Operand *, int64_t> base_and_offset =
1482 GetBaseExplainingDereference(operand, *register_context_sp, addr);
1484 if (!base_and_offset.first) {
1488 switch (base_and_offset.first->m_type) {
1491 if (target_sp->ResolveLoadAddress(base_and_offset.first->m_immediate +
1492 base_and_offset.second,
1494 auto c_type_system_or_err =
1496 if (
auto err = c_type_system_or_err.takeError()) {
1498 "Unable to guess value for given address: {0}");
1501 auto ts = *c_type_system_or_err;
1516 base_and_offset.second);
1531 llvm::expectedToOptional(parent->GetByteSize()).value_or(0)) {
1535 if (parent->IsPointerOrReferenceType()) {
1539 for (
int ci = 0, ce = parent->GetNumChildrenIgnoringErrors(); ci != ce;
1547 int64_t child_offset = child_sp->GetByteOffset();
1548 int64_t child_size =
1549 llvm::expectedToOptional(child_sp->GetByteSize()).value_or(0);
1551 if (offset >= child_offset && offset < (child_offset + child_size)) {
1552 return GetValueForOffset(frame, child_sp, offset - child_offset);
1570 if (!base->IsPointerOrReferenceType()) {
1583 llvm::expectedToOptional(pointee->GetByteSize()).value_or(0)) {
1585 llvm::expectedToOptional(pointee->GetByteSize()).value_or(1);
1586 int64_t index = offset / size;
1587 offset = offset % size;
1588 const bool can_create =
true;
1589 pointee = base->GetSyntheticArrayMember(index, can_create);
1592 if (!pointee ||
error.Fail()) {
1596 return GetValueForOffset(frame, pointee, offset);
1668 if (var_sp->LocationExpressionList().MatchesOperand(frame, op))
1672 const uint32_t current_inst =
1678 for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) {
1686 if (instruction_sp->IsCall()) {
1692 const char *return_register_name;
1693 if (!abi_sp->GetPointerReturnRegister(return_register_name)) {
1699 return_register_name);
1700 if (!return_register_info) {
1716 llvm::SmallVector<Instruction::Operand, 1> operands;
1717 if (!instruction_sp->ParseOperands(operands) || operands.size() != 1) {
1721 switch (operands[0].m_type) {
1726 if (!
pc.GetModule())
1728 Address address(operands[0].m_immediate,
1729 pc.GetModule()->GetSectionList());
1730 if (!address.IsValid())
1733 address, eSymbolContextFunction, sc);
1747 std::string name_str(
1749 name_str.append(
"()");
1752 &frame, name_str, return_value_address, return_type);
1753 return GetValueForDereferincingOffset(frame, return_value_sp, offset);
1760 llvm::SmallVector<Instruction::Operand, 2> operands;
1761 if (!instruction_sp->ParseOperands(operands) || operands.size() != 2) {
1770 if (clobbered_reg_matcher(operands[0])) {
1771 origin_operand = &operands[1];
1772 }
else if (clobbered_reg_matcher(operands[1])) {
1773 origin_operand = &operands[0];
1781 int64_t origin_offset = 0;
1783 if (
FetchRegOp(origin_register)(*origin_operand)) {
1784 source_path = DoGuessValueAt(frame, origin_register, 0, disassembler,
1785 variables, instruction_sp->GetAddress());
1788 FetchRegOp(origin_register))(*origin_operand) ||
1793 FetchImmOp(origin_offset)))(*origin_operand)) {
1795 DoGuessValueAt(frame, origin_register, origin_offset, disassembler,
1796 variables, instruction_sp->GetAddress());
1800 source_path = GetValueForDereferincingOffset(frame, source_path, offset);
1816 const ArchSpec &target_arch = target_sp->GetArchitecture();
1835 const char *plugin_name =
nullptr;
1836 const char *flavor =
nullptr;
1837 const char *cpu =
nullptr;
1838 const char *features =
nullptr;
1839 const bool force_live_memory =
true;
1841 target_arch, plugin_name, flavor, cpu, features, *target_sp,
1844 if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {
1848 const bool get_file_globals =
false;
1855 return DoGuessValueAt(*
this, reg, offset, *disassembler_sp, *variables,
1868 if (!target_sp && !process_sp)
1876 const bool can_create =
true;
1877 const bool get_parent_variables =
true;
1878 const bool stop_if_block_is_inlined_function =
true;
1881 can_create, get_parent_variables, stop_if_block_is_inlined_function,
1882 [
this](
Variable *v) { return v->IsInScope(this); },
1898 ProcessSP process_sp(thread_sp->CalculateProcess());
1900 target_sp = process_sp->CalculateTarget();
1909 process_sp = thread_sp->CalculateProcess();
1923 llvm::StringRef frame_marker) {
1930 nullptr,
false,
false)) {
1938 const char *frame_marker) {
1939 if (strm ==
nullptr)
1950 frame_format = &format_entry;
1953 frame_format = &format_entry;
1957 Dump(strm,
true,
false);
1963 bool show_fullpaths) {
1964 if (strm ==
nullptr)
1967 if (show_frame_index)
1971 strm->
Printf(
"0x%0*" PRIx64
" ",
1976 const bool show_module =
true;
1977 const bool show_inline =
true;
1978 const bool show_function_arguments =
true;
1979 const bool show_function_name =
true;
1982 show_inline, show_function_arguments,
1983 show_function_name);
1987 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
1999 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
2037 bool show_unique,
const char *frame_marker) {
2038 if (show_frame_info) {
2045 bool have_source =
false, have_debuginfo =
false;
2050 const uint32_t source_lines_before =
2052 const uint32_t source_lines_after =
2057 if (
m_sc.comp_unit &&
m_sc.line_entry.IsValid()) {
2058 have_debuginfo =
true;
2059 if (source_lines_before > 0 || source_lines_after > 0) {
2061 uint32_t start_line =
m_sc.line_entry.line;
2062 if (!start_line &&
m_sc.function) {
2063 m_sc.function->GetStartLineSourceInfo(source_file_sp, start_line);
2068 source_file_sp, start_line,
m_sc.line_entry.column,
2069 source_lines_before, source_lines_after,
"->", &strm);
2073 if (!
m_sc.line_entry.line)
2074 strm <<
"note: This address is not associated with a specific line "
2075 "of code. This may be due to compiler optimizations.\n";
2078 switch (disasm_display) {
2095 if (disasm_lines > 0) {
2097 const char *plugin_name =
nullptr;
2098 const char *flavor =
nullptr;
2099 const bool mixed_source_and_assembly =
false;
2101 target->
GetDebugger(), target_arch, plugin_name, flavor,
2105 mixed_source_and_assembly, 0,
2117 auto process =
GetThread()->GetProcess();
2121 auto &manager = process->GetTarget().GetFrameRecognizerManager();
2122 auto new_generation = manager.GetGeneration();
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG_ERROR(log, error,...)
#define RESOLVED_GLOBAL_VARIABLES
#define RESOLVED_FRAME_ID_SYMBOL_SCOPE
#define RESOLVED_FRAME_CODE_ADDR
#define RESOLVED_VARIABLES
A section + offset based address range class.
Address & GetBaseAddress()
Get accessor for the base address of the range.
void SetByteSize(lldb::addr_t byte_size)
Set accessor for the byte size of this range.
A section + offset based address class.
lldb::addr_t GetOpcodeLoadAddress(Target *target, AddressClass addr_class=AddressClass::eInvalid) const
Get the load address as an opcode load address.
bool SetOpcodeLoadAddress(lldb::addr_t load_addr, Target *target, AddressClass addr_class=AddressClass::eInvalid, bool allow_section_end=false)
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
lldb::addr_t GetOffset() const
Get the section relative offset value.
bool IsValid() const
Check if the object state is valid.
bool SetOffset(lldb::addr_t offset)
Set accessor for the offset.
An architecture specification class.
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
uint32_t GetMaximumOpcodeByteSize() const
A class that describes a single lexical block.
Block * GetContainingInlinedBlock()
Get the inlined block that contains this block.
const InlineFunctionInfo * GetInlinedFunctionInfo() const
Get const accessor for any inlined function information.
Function * CalculateSymbolContextFunction() override
uint32_t AppendVariables(bool can_create, bool get_parent_variables, bool stop_if_block_is_inlined_function, const std::function< bool(Variable *)> &filter, VariableList *variable_list)
Appends the variables from this block, and optionally from all parent blocks, to variable_list.
uint32_t AppendBlockVariables(bool can_create, bool get_child_block_variables, bool stop_if_child_block_is_inlined_function, const std::function< bool(Variable *)> &filter, VariableList *variable_list)
Get the variable list for this block and optionally all child blocks if get_child_variables is true.
A class that describes a compilation unit.
lldb::LanguageType GetLanguage()
Generic representation of a type in a programming language.
CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) const
Create related types using the current type's AST.
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
bool IsAnonymousType() const
bool IsFunctionType() const
CompilerType GetFunctionReturnType() const
A uniqued constant string class.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
size_t GetLength() const
Get the length in bytes of string value.
const char * GetCString() const
Get the string value as a C string.
"lldb/Expression/DWARFExpressionList.h" Encapsulates a range map from file address range to a single ...
A class to manage flag bits.
uint64_t GetDisassemblyLineCount() const
FormatEntity::Entry GetFrameFormatUnique() const
uint64_t GetStopSourceLineCount(bool before) const
FormatEntity::Entry GetFrameFormat() const
lldb::StopDisassemblyType GetStopDisassemblyDisplay() const
static lldb::DisassemblerSP DisassembleRange(const ArchSpec &arch, const char *plugin_name, const char *flavor, const char *cpu, const char *features, Target &target, llvm::ArrayRef< AddressRange > disasm_ranges, bool force_live_memory=false)
static bool Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name, const char *flavor, const char *cpu, const char *features, const ExecutionContext &exe_ctx, const Address &start, Limit limit, bool mixed_source_and_assembly, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm)
InstructionList & GetInstructionList()
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
ExecutionContextScope * GetBestExecutionContextScope() const
void SetContext(const lldb::TargetSP &target_sp, bool get_process)
Target * GetTargetPtr() const
Returns a pointer to the target object.
Target & GetTargetRef() const
Returns a reference to the target object.
A class that describes a function.
CompilerType GetCompilerType()
bool GetRangeContainingLoadAddress(lldb::addr_t load_addr, Target &target, AddressRange &range)
ConstString GetName() const
const Mangled & GetMangled() const
AddressRanges GetAddressRanges()
ConstString GetDisplayName() const
A class that describes information for an inlined function.
ConstString GetDisplayName() const
ConstString GetName() const
lldb::InstructionSP GetInstructionAtIndex(size_t idx) const
lldb::LanguageType GuessLanguage() const
Try to guess the language from the mangling.
const RegisterInfo * GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx=0)
virtual bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value)=0
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
size_t DisplaySourceLinesWithLineNumbers(lldb::SupportFileSP support_file_sp, uint32_t line, uint32_t column, uint32_t context_before, uint32_t context_after, const char *current_line_cstr, Stream *s, const SymbolContextList *bp_locs=nullptr)
This base class provides an interface to stack frames.
void SetSymbolContextScope(SymbolContextScope *symbol_scope)
uint16_t m_frame_recognizer_generation
lldb::VariableListSP m_variable_list_sp
void UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame)
bool m_artificial
Is this an artificial stack frame (e.g.
lldb::ThreadSP GetThread() const
Address m_frame_code_addr
The frame code address (might not be the same as the actual PC for inlined frames) as a section/offse...
@ eExpressionPathOptionsNoFragileObjcIvar
@ eExpressionPathOptionCheckPtrVsMember
@ eExpressionPathOptionsInspectAnonymousUnions
@ eExpressionPathOptionsAllowDirectIVarAccess
@ eExpressionPathOptionsNoSyntheticChildren
virtual const char * GetFunctionName()
Get the frame's demangled name.
virtual bool IsHidden()
Query whether this frame should be hidden from backtraces.
VariableList * GetVariableList(bool get_file_globals, Status *error_ptr)
Retrieve the list of variables whose scope either:
bool IsSynthetic() const
Query whether this frame is synthetic.
DWARFExpressionList * GetFrameBaseExpression(Status *error_ptr)
Get the DWARFExpressionList corresponding to the Canonical Frame Address.
void UpdateCurrentFrameFromPreviousFrame(StackFrame &prev_frame)
ValueObjectList m_variable_list_value_objects
Value objects for each variable in m_variable_list_sp.
bool m_cfa_is_valid
Does this frame have a CFA? Different from CFA == LLDB_INVALID_ADDRESS.
llvm::Error GetFrameBaseValue(Scalar &value)
Return the Canonical Frame Address (DWARF term) for this frame.
lldb::ThreadWP m_thread_wp
For StackFrame and derived classes only.
std::optional< lldb::RecognizedStackFrameSP > m_recognized_frame_sp
void DumpUsingSettingsFormat(Stream *strm, bool show_unique=false, const char *frame_marker=nullptr)
Print a description for this frame using the frame-format formatter settings.
virtual bool IsInlined()
Query whether this frame is a concrete frame on the call stack, or if it is an inlined frame derived ...
lldb::ValueObjectSP GetValueForVariableExpressionPath(llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic, uint32_t options, lldb::VariableSP &var_sp, Status &error)
Create a ValueObject for a variable name / pathname, possibly including simple dereference/child sele...
SourceLanguage GuessLanguage()
Similar to GetLanguage(), but is allowed to take a potentially incorrect guess if exact information i...
lldb::RegisterContextSP GetRegisterContext()
Get the RegisterContext for this frame, if possible.
lldb::RegisterContextSP m_reg_context_sp
lldb::ValueObjectSP GuessValueForRegisterAndOffset(ConstString reg, int64_t offset)
Attempt to reconstruct the ValueObject for the address contained in a given register plus an offset.
lldb::VariableListSP GetInScopeVariableList(bool get_file_globals, bool must_have_valid_location=false)
Retrieve the list of variables that are in scope at this StackFrame's pc.
StructuredData::ObjectSP GetLanguageSpecificData()
Language plugins can use this API to report language-specific runtime information about this compile ...
Address GetFrameCodeAddressForSymbolication()
Get the current code Address suitable for symbolication, may not be the same as GetFrameCodeAddress()...
@ History
A historical stack frame – possibly without CFA or registers or local variables.
@ Regular
A regular stack frame with access to registers and local variables.
@ Synthetic
An synthetic stack frame (e.g.
uint32_t m_concrete_frame_index
lldb::ValueObjectSP DILGetValueForVariableExpressionPath(llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic, uint32_t options, lldb::VariableSP &var_sp, Status &error)
bool m_behaves_like_zeroth_frame
Whether this frame behaves like the zeroth frame, in the sense that its pc value might not immediatel...
lldb::ValueObjectSP GuessValueForAddress(lldb::addr_t addr)
Attempt to econstruct the ValueObject for a given raw address touched by the current instruction.
bool ChangePC(lldb::addr_t pc)
Change the pc value for a given thread.
lldb::ValueObjectSP LegacyGetValueForVariableExpressionPath(llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic, uint32_t options, lldb::VariableSP &var_sp, Status &error)
Private methods, called from GetValueForVariableExpressionPath.
lldb::ThreadSP CalculateThread() override
SourceLanguage GetLanguage()
Query this frame to determine what the default language should be when parsing expressions given the ...
lldb::ValueObjectSP GetValueObjectForFrameVariable(const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic)
Create a ValueObject for a given Variable in this StackFrame.
bool HasCachedData() const
StreamString m_disassembly
lldb::StackFrameSP CalculateStackFrame() override
const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame's current pc value.
virtual const char * GetDisplayFunctionName()
Get the frame's demangled display name.
Status m_frame_base_error
bool IsHistorical() const
Query whether this frame is part of a historical backtrace.
const char * Disassemble()
Return the disassembly for the instructions of this StackFrame's function as a single C string.
virtual bool IsArtificial() const
Query whether this frame is artificial (e.g a synthesized result of inferring missing tail call frame...
void CalculateExecutionContext(ExecutionContext &exe_ctx) override
Reconstruct the object's execution context into sc.
void Dump(Stream *strm, bool show_frame_index, bool show_fullpaths)
Print a description for this frame using a default format.
uint32_t GetFrameIndex() const
Query this frame to find what frame it is in this Thread's StackFrameList.
bool HasDebugInformation()
Determine whether this StackFrame has debug information available or not.
bool GetStatus(Stream &strm, bool show_frame_info, bool show_source, bool show_unique=false, const char *frame_marker=nullptr)
Print a description of this stack frame and/or the source context/assembly for this stack frame.
StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx, lldb::user_id_t concrete_frame_idx, lldb::addr_t cfa, bool cfa_is_valid, lldb::addr_t pc, Kind frame_kind, bool artificial, bool behaves_like_zeroth_frame, const SymbolContext *sc_ptr)
Construct a StackFrame object without supplying a RegisterContextSP.
Block * GetFrameBlock()
Get the current lexical scope block for this StackFrame, if possible.
bool DumpUsingFormat(Stream &strm, const lldb_private::FormatEntity::Entry *format, llvm::StringRef frame_marker={})
Print a description of this frame using the provided frame format.
lldb::ProcessSP CalculateProcess() override
lldb::RecognizedStackFrameSP GetRecognizedFrame()
std::recursive_mutex m_mutex
lldb::ValueObjectSP FindVariable(ConstString name)
Attempt to reconstruct the ValueObject for a variable with a given name from within the current Stack...
const Address & GetFrameCodeAddress()
Get an Address for the current pc value in this StackFrame.
lldb::TargetSP CalculateTarget() override
lldb::addr_t GetPC() const
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
bool Fail() const
Test for error condition.
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
bool Success() const
Test for success condition.
const char * GetData() const
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
size_t EOL()
Output and End of Line character to the stream.
std::shared_ptr< Object > ObjectSP
"lldb/Symbol/SymbolContextScope.h" Inherit from this if your object is part of a symbol context and c...
Defines a symbol context baton that can be handed other debug core functions.
Function * function
The Function for a given query.
Block * block
The Block for a given query.
lldb::ModuleSP module_sp
The Module for a given query.
CompileUnit * comp_unit
The CompileUnit for a given query.
Symbol * symbol
The Symbol for a given query.
lldb::TargetSP target_sp
The Target for a given query.
LineEntry line_entry
The LineEntry for a given query.
Provides public interface for all SymbolFiles.
Status GetFrameVariableError(StackFrame &frame)
Get an error that describes why variables might be missing for a given symbol context.
ConstString GetName() const
ConstString GetDisplayName() const
const char * GetDisassemblyFeatures() const
const char * GetDisassemblyCPU() const
bool GetUseDIL(ExecutionContext *exe_ctx) const
SourceManager & GetSourceManager()
Debugger & GetDebugger() const
const ArchSpec & GetArchitecture() const
CompilerType GetForwardCompilerType()
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size, lldb::addr_t address=LLDB_INVALID_ADDRESS)
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, llvm::StringRef name, const Address &address, lldb::TypeSP &type_sp)
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp)
lldb::VariableSP FindVariable(ConstString name, bool include_static_members=true)
uint32_t FindIndexForVariable(Variable *variable)
bool IsInScope(StackFrame *frame)
bool LocationIsValidForFrame(StackFrame *frame)
static llvm::Expected< DILLexer > Create(llvm::StringRef expr)
Lexes all the tokens in expr and calls the private constructor with the lexed tokens.
static llvm::Expected< ASTNodeUP > Parse(llvm::StringRef dil_input_expr, DILLexer lexer, std::shared_ptr< StackFrame > frame_sp, lldb::DynamicValueType use_dynamic, bool use_synthetic, bool fragile_ivar, bool check_ptr_vs_member)
llvm::Expected< lldb::ValueObjectSP > Evaluate(const ASTNode *node)
#define LLDB_INVALID_ADDRESS
std::function< bool(const Instruction::Operand &)> MatchRegOp(const RegisterInfo &info)
std::function< bool(const Instruction::Operand &)> FetchRegOp(ConstString ®)
std::function< bool(const Instruction::Operand &)> FetchImmOp(int64_t &imm)
std::function< bool(const Instruction::Operand &)> MatchOpType(Instruction::Operand::Type type)
std::function< bool(const Instruction::Operand &)> MatchBinaryOp(std::function< bool(const Instruction::Operand &)> base, std::function< bool(const Instruction::Operand &)> left, std::function< bool(const Instruction::Operand &)> right)
std::function< bool(const Instruction::Operand &)> MatchUnaryOp(std::function< bool(const Instruction::Operand &)> base, std::function< bool(const Instruction::Operand &)> child)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::shared_ptr< lldb_private::ABI > ABISP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::RecognizedStackFrame > RecognizedStackFrameSP
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::shared_ptr< lldb_private::SupportFile > SupportFileSP
LanguageType
Programming language type.
@ eLanguageTypeUnknown
Unknown or invalid language value.
@ eLanguageTypeC
Non-standardized C, such as K&R.
@ eLanguageTypeObjC
Objective-C.
std::shared_ptr< lldb_private::Instruction > InstructionSP
std::shared_ptr< lldb_private::Process > ProcessSP
StopDisassemblyType
Used to determine when to show disassembly.
@ eStopDisassemblyTypeNever
@ eStopDisassemblyTypeNoSource
@ eStopDisassemblyTypeAlways
@ eStopDisassemblyTypeNoDebugInfo
std::shared_ptr< lldb_private::Disassembler > DisassemblerSP
std::shared_ptr< lldb_private::VariableList > VariableListSP
std::shared_ptr< lldb_private::Variable > VariableSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
std::shared_ptr< lldb_private::Module > ModuleSP
enum lldb_private::Instruction::Operand::Type m_type
static Operand BuildImmediate(lldb::addr_t imm, bool neg)
static Operand BuildDereference(const Operand &ref)
std::vector< Operand > m_children
static Operand BuildSum(const Operand &lhs, const Operand &rhs)
static Operand BuildRegister(ConstString &r)
Every register is described in detail including its name, alternate name (optional),...
A type-erased pair of llvm::dwarf::SourceLanguageName and version.
lldb::LanguageType AsLanguageType() const