Path: blob/main/contrib/llvm-project/lldb/source/Target/StackFrame.cpp
39587 views
//===-- StackFrame.cpp ----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Target/StackFrame.h"9#include "lldb/Core/Debugger.h"10#include "lldb/Core/Disassembler.h"11#include "lldb/Core/FormatEntity.h"12#include "lldb/Core/Mangled.h"13#include "lldb/Core/Module.h"14#include "lldb/Core/Value.h"15#include "lldb/Core/ValueObjectConstResult.h"16#include "lldb/Core/ValueObjectMemory.h"17#include "lldb/Core/ValueObjectVariable.h"18#include "lldb/Symbol/CompileUnit.h"19#include "lldb/Symbol/Function.h"20#include "lldb/Symbol/Symbol.h"21#include "lldb/Symbol/SymbolContextScope.h"22#include "lldb/Symbol/SymbolFile.h"23#include "lldb/Symbol/Type.h"24#include "lldb/Symbol/VariableList.h"25#include "lldb/Target/ABI.h"26#include "lldb/Target/ExecutionContext.h"27#include "lldb/Target/Process.h"28#include "lldb/Target/RegisterContext.h"29#include "lldb/Target/StackFrameRecognizer.h"30#include "lldb/Target/Target.h"31#include "lldb/Target/Thread.h"32#include "lldb/Utility/LLDBLog.h"33#include "lldb/Utility/Log.h"34#include "lldb/Utility/RegisterValue.h"3536#include "lldb/lldb-enumerations.h"3738#include <memory>3940using namespace lldb;41using namespace lldb_private;4243// The first bits in the flags are reserved for the SymbolContext::Scope bits44// so we know if we have tried to look up information in our internal symbol45// context (m_sc) already.46#define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextLastItem) << 1)47#define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1)48#define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1)49#define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1)50#define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1)5152StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,53user_id_t unwind_frame_index, addr_t cfa,54bool cfa_is_valid, addr_t pc, StackFrame::Kind kind,55bool behaves_like_zeroth_frame,56const SymbolContext *sc_ptr)57: m_thread_wp(thread_sp), m_frame_index(frame_idx),58m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(),59m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), m_flags(),60m_frame_base(), m_frame_base_error(), m_cfa_is_valid(cfa_is_valid),61m_stack_frame_kind(kind),62m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),63m_variable_list_sp(), m_variable_list_value_objects(),64m_recognized_frame_sp(), m_disassembly(), m_mutex() {65// If we don't have a CFA value, use the frame index for our StackID so that66// recursive functions properly aren't confused with one another on a history67// stack.68if (IsHistorical() && !m_cfa_is_valid) {69m_id.SetCFA(m_frame_index);70}7172if (sc_ptr != nullptr) {73m_sc = *sc_ptr;74m_flags.Set(m_sc.GetResolvedMask());75}76}7778StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,79user_id_t unwind_frame_index,80const RegisterContextSP ®_context_sp, addr_t cfa,81addr_t pc, bool behaves_like_zeroth_frame,82const SymbolContext *sc_ptr)83: m_thread_wp(thread_sp), m_frame_index(frame_idx),84m_concrete_frame_index(unwind_frame_index),85m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr),86m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(),87m_frame_base_error(), m_cfa_is_valid(true),88m_stack_frame_kind(StackFrame::Kind::Regular),89m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),90m_variable_list_sp(), m_variable_list_value_objects(),91m_recognized_frame_sp(), m_disassembly(), m_mutex() {92if (sc_ptr != nullptr) {93m_sc = *sc_ptr;94m_flags.Set(m_sc.GetResolvedMask());95}9697if (reg_context_sp && !m_sc.target_sp) {98m_sc.target_sp = reg_context_sp->CalculateTarget();99if (m_sc.target_sp)100m_flags.Set(eSymbolContextTarget);101}102}103104StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,105user_id_t unwind_frame_index,106const RegisterContextSP ®_context_sp, addr_t cfa,107const Address &pc_addr, bool behaves_like_zeroth_frame,108const SymbolContext *sc_ptr)109: m_thread_wp(thread_sp), m_frame_index(frame_idx),110m_concrete_frame_index(unwind_frame_index),111m_reg_context_sp(reg_context_sp),112m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa,113nullptr),114m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(),115m_frame_base_error(), m_cfa_is_valid(true),116m_stack_frame_kind(StackFrame::Kind::Regular),117m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),118m_variable_list_sp(), m_variable_list_value_objects(),119m_recognized_frame_sp(), m_disassembly(), m_mutex() {120if (sc_ptr != nullptr) {121m_sc = *sc_ptr;122m_flags.Set(m_sc.GetResolvedMask());123}124125if (!m_sc.target_sp && reg_context_sp) {126m_sc.target_sp = reg_context_sp->CalculateTarget();127if (m_sc.target_sp)128m_flags.Set(eSymbolContextTarget);129}130131ModuleSP pc_module_sp(pc_addr.GetModule());132if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp) {133if (pc_module_sp) {134m_sc.module_sp = pc_module_sp;135m_flags.Set(eSymbolContextModule);136} else {137m_sc.module_sp.reset();138}139}140}141142StackFrame::~StackFrame() = default;143144StackID &StackFrame::GetStackID() {145std::lock_guard<std::recursive_mutex> guard(m_mutex);146// Make sure we have resolved the StackID object's symbol context scope if we147// already haven't looked it up.148149if (m_flags.IsClear(RESOLVED_FRAME_ID_SYMBOL_SCOPE)) {150if (m_id.GetSymbolContextScope()) {151// We already have a symbol context scope, we just don't have our flag152// bit set.153m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE);154} else {155// Calculate the frame block and use this for the stack ID symbol context156// scope if we have one.157SymbolContextScope *scope = GetFrameBlock();158if (scope == nullptr) {159// We don't have a block, so use the symbol160if (m_flags.IsClear(eSymbolContextSymbol))161GetSymbolContext(eSymbolContextSymbol);162163// It is ok if m_sc.symbol is nullptr here164scope = m_sc.symbol;165}166// Set the symbol context scope (the accessor will set the167// RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags).168SetSymbolContextScope(scope);169}170}171return m_id;172}173174uint32_t StackFrame::GetFrameIndex() const {175ThreadSP thread_sp = GetThread();176if (thread_sp)177return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex(178m_frame_index);179else180return m_frame_index;181}182183void StackFrame::SetSymbolContextScope(SymbolContextScope *symbol_scope) {184std::lock_guard<std::recursive_mutex> guard(m_mutex);185m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE);186m_id.SetSymbolContextScope(symbol_scope);187}188189const Address &StackFrame::GetFrameCodeAddress() {190std::lock_guard<std::recursive_mutex> guard(m_mutex);191if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) &&192!m_frame_code_addr.IsSectionOffset()) {193m_flags.Set(RESOLVED_FRAME_CODE_ADDR);194195// Resolve the PC into a temporary address because if ResolveLoadAddress196// fails to resolve the address, it will clear the address object...197ThreadSP thread_sp(GetThread());198if (thread_sp) {199TargetSP target_sp(thread_sp->CalculateTarget());200if (target_sp) {201const bool allow_section_end = true;202if (m_frame_code_addr.SetOpcodeLoadAddress(203m_frame_code_addr.GetOffset(), target_sp.get(),204AddressClass::eCode, allow_section_end)) {205ModuleSP module_sp(m_frame_code_addr.GetModule());206if (module_sp) {207m_sc.module_sp = module_sp;208m_flags.Set(eSymbolContextModule);209}210}211}212}213}214return m_frame_code_addr;215}216217// This can't be rewritten into a call to218// RegisterContext::GetPCForSymbolication because this219// StackFrame may have been constructed with a special pc,220// e.g. tail-call artificial frames.221Address StackFrame::GetFrameCodeAddressForSymbolication() {222Address lookup_addr(GetFrameCodeAddress());223if (!lookup_addr.IsValid())224return lookup_addr;225if (m_behaves_like_zeroth_frame)226return lookup_addr;227228addr_t offset = lookup_addr.GetOffset();229if (offset > 0) {230lookup_addr.SetOffset(offset - 1);231} else {232// lookup_addr is the start of a section. We need do the math on the233// actual load address and re-compute the section. We're working with234// a 'noreturn' function at the end of a section.235TargetSP target_sp = CalculateTarget();236if (target_sp) {237addr_t addr_minus_one = lookup_addr.GetOpcodeLoadAddress(238target_sp.get(), AddressClass::eCode) -2391;240lookup_addr.SetOpcodeLoadAddress(addr_minus_one, target_sp.get());241}242}243return lookup_addr;244}245246bool StackFrame::ChangePC(addr_t pc) {247std::lock_guard<std::recursive_mutex> guard(m_mutex);248// We can't change the pc value of a history stack frame - it is immutable.249if (IsHistorical())250return false;251m_frame_code_addr.SetRawAddress(pc);252m_sc.Clear(false);253m_flags.Reset(0);254ThreadSP thread_sp(GetThread());255if (thread_sp)256thread_sp->ClearStackFrames();257return true;258}259260const char *StackFrame::Disassemble() {261std::lock_guard<std::recursive_mutex> guard(m_mutex);262if (!m_disassembly.Empty())263return m_disassembly.GetData();264265ExecutionContext exe_ctx(shared_from_this());266if (Target *target = exe_ctx.GetTargetPtr()) {267Disassembler::Disassemble(target->GetDebugger(), target->GetArchitecture(),268*this, m_disassembly);269}270271return m_disassembly.Empty() ? nullptr : m_disassembly.GetData();272}273274Block *StackFrame::GetFrameBlock() {275if (m_sc.block == nullptr && m_flags.IsClear(eSymbolContextBlock))276GetSymbolContext(eSymbolContextBlock);277278if (m_sc.block) {279Block *inline_block = m_sc.block->GetContainingInlinedBlock();280if (inline_block) {281// Use the block with the inlined function info as the frame block we282// want this frame to have only the variables for the inlined function283// and its non-inlined block child blocks.284return inline_block;285} else {286// This block is not contained within any inlined function blocks with so287// we want to use the top most function block.288return &m_sc.function->GetBlock(false);289}290}291return nullptr;292}293294// Get the symbol context if we already haven't done so by resolving the295// PC address as much as possible. This way when we pass around a296// StackFrame object, everyone will have as much information as possible and no297// one will ever have to look things up manually.298const SymbolContext &299StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) {300std::lock_guard<std::recursive_mutex> guard(m_mutex);301// Copy our internal symbol context into "sc".302if ((m_flags.Get() & resolve_scope) != resolve_scope) {303uint32_t resolved = 0;304305// If the target was requested add that:306if (!m_sc.target_sp) {307m_sc.target_sp = CalculateTarget();308if (m_sc.target_sp)309resolved |= eSymbolContextTarget;310}311312// Resolve our PC to section offset if we haven't already done so and if we313// don't have a module. The resolved address section will contain the314// module to which it belongs315if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR))316GetFrameCodeAddress();317318// If this is not frame zero, then we need to subtract 1 from the PC value319// when doing address lookups since the PC will be on the instruction320// following the function call instruction...321Address lookup_addr(GetFrameCodeAddressForSymbolication());322323if (m_sc.module_sp) {324// We have something in our stack frame symbol context, lets check if we325// haven't already tried to lookup one of those things. If we haven't326// then we will do the query.327328SymbolContextItem actual_resolve_scope = SymbolContextItem(0);329330if (resolve_scope & eSymbolContextCompUnit) {331if (m_flags.IsClear(eSymbolContextCompUnit)) {332if (m_sc.comp_unit)333resolved |= eSymbolContextCompUnit;334else335actual_resolve_scope |= eSymbolContextCompUnit;336}337}338339if (resolve_scope & eSymbolContextFunction) {340if (m_flags.IsClear(eSymbolContextFunction)) {341if (m_sc.function)342resolved |= eSymbolContextFunction;343else344actual_resolve_scope |= eSymbolContextFunction;345}346}347348if (resolve_scope & eSymbolContextBlock) {349if (m_flags.IsClear(eSymbolContextBlock)) {350if (m_sc.block)351resolved |= eSymbolContextBlock;352else353actual_resolve_scope |= eSymbolContextBlock;354}355}356357if (resolve_scope & eSymbolContextSymbol) {358if (m_flags.IsClear(eSymbolContextSymbol)) {359if (m_sc.symbol)360resolved |= eSymbolContextSymbol;361else362actual_resolve_scope |= eSymbolContextSymbol;363}364}365366if (resolve_scope & eSymbolContextLineEntry) {367if (m_flags.IsClear(eSymbolContextLineEntry)) {368if (m_sc.line_entry.IsValid())369resolved |= eSymbolContextLineEntry;370else371actual_resolve_scope |= eSymbolContextLineEntry;372}373}374375if (actual_resolve_scope) {376// We might be resolving less information than what is already in our377// current symbol context so resolve into a temporary symbol context378// "sc" so we don't clear out data we have already found in "m_sc"379SymbolContext sc;380// Set flags that indicate what we have tried to resolve381resolved |= m_sc.module_sp->ResolveSymbolContextForAddress(382lookup_addr, actual_resolve_scope, sc);383// Only replace what we didn't already have as we may have information384// for an inlined function scope that won't match what a standard385// lookup by address would match386if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == nullptr)387m_sc.comp_unit = sc.comp_unit;388if ((resolved & eSymbolContextFunction) && m_sc.function == nullptr)389m_sc.function = sc.function;390if ((resolved & eSymbolContextBlock) && m_sc.block == nullptr)391m_sc.block = sc.block;392if ((resolved & eSymbolContextSymbol) && m_sc.symbol == nullptr)393m_sc.symbol = sc.symbol;394if ((resolved & eSymbolContextLineEntry) &&395!m_sc.line_entry.IsValid()) {396m_sc.line_entry = sc.line_entry;397m_sc.line_entry.ApplyFileMappings(m_sc.target_sp);398}399}400} else {401// If we don't have a module, then we can't have the compile unit,402// function, block, line entry or symbol, so we can safely call403// ResolveSymbolContextForAddress with our symbol context member m_sc.404if (m_sc.target_sp) {405resolved |= m_sc.target_sp->GetImages().ResolveSymbolContextForAddress(406lookup_addr, resolve_scope, m_sc);407}408}409410// Update our internal flags so we remember what we have tried to locate so411// we don't have to keep trying when more calls to this function are made.412// We might have dug up more information that was requested (for example if413// we were asked to only get the block, we will have gotten the compile414// unit, and function) so set any additional bits that we resolved415m_flags.Set(resolve_scope | resolved);416}417418// Return the symbol context with everything that was possible to resolve419// resolved.420return m_sc;421}422423VariableList *StackFrame::GetVariableList(bool get_file_globals,424Status *error_ptr) {425std::lock_guard<std::recursive_mutex> guard(m_mutex);426if (m_flags.IsClear(RESOLVED_VARIABLES)) {427m_flags.Set(RESOLVED_VARIABLES);428m_variable_list_sp = std::make_shared<VariableList>();429430Block *frame_block = GetFrameBlock();431432if (frame_block) {433const bool get_child_variables = true;434const bool can_create = true;435const bool stop_if_child_block_is_inlined_function = true;436frame_block->AppendBlockVariables(can_create, get_child_variables,437stop_if_child_block_is_inlined_function,438[](Variable *v) { return true; },439m_variable_list_sp.get());440}441}442443if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) && get_file_globals) {444m_flags.Set(RESOLVED_GLOBAL_VARIABLES);445446if (m_flags.IsClear(eSymbolContextCompUnit))447GetSymbolContext(eSymbolContextCompUnit);448449if (m_sc.comp_unit) {450VariableListSP global_variable_list_sp(451m_sc.comp_unit->GetVariableList(true));452if (m_variable_list_sp)453m_variable_list_sp->AddVariables(global_variable_list_sp.get());454else455m_variable_list_sp = global_variable_list_sp;456}457}458459if (error_ptr && m_variable_list_sp->GetSize() == 0) {460// Check with the symbol file to check if there is an error for why we461// don't have variables that the user might need to know about.462GetSymbolContext(eSymbolContextEverything);463if (m_sc.module_sp) {464SymbolFile *sym_file = m_sc.module_sp->GetSymbolFile();465if (sym_file)466*error_ptr = sym_file->GetFrameVariableError(*this);467}468}469470return m_variable_list_sp.get();471}472473VariableListSP474StackFrame::GetInScopeVariableList(bool get_file_globals,475bool must_have_valid_location) {476std::lock_guard<std::recursive_mutex> guard(m_mutex);477// We can't fetch variable information for a history stack frame.478if (IsHistorical())479return VariableListSP();480481VariableListSP var_list_sp(new VariableList);482GetSymbolContext(eSymbolContextCompUnit | eSymbolContextBlock);483484if (m_sc.block) {485const bool can_create = true;486const bool get_parent_variables = true;487const bool stop_if_block_is_inlined_function = true;488m_sc.block->AppendVariables(489can_create, get_parent_variables, stop_if_block_is_inlined_function,490[this, must_have_valid_location](Variable *v) {491return v->IsInScope(this) && (!must_have_valid_location ||492v->LocationIsValidForFrame(this));493},494var_list_sp.get());495}496497if (m_sc.comp_unit && get_file_globals) {498VariableListSP global_variable_list_sp(499m_sc.comp_unit->GetVariableList(true));500if (global_variable_list_sp)501var_list_sp->AddVariables(global_variable_list_sp.get());502}503504return var_list_sp;505}506507ValueObjectSP StackFrame::GetValueForVariableExpressionPath(508llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,509VariableSP &var_sp, Status &error) {510llvm::StringRef original_var_expr = var_expr;511// We can't fetch variable information for a history stack frame.512if (IsHistorical())513return ValueObjectSP();514515if (var_expr.empty()) {516error.SetErrorStringWithFormat("invalid variable path '%s'",517var_expr.str().c_str());518return ValueObjectSP();519}520521const bool check_ptr_vs_member =522(options & eExpressionPathOptionCheckPtrVsMember) != 0;523const bool no_fragile_ivar =524(options & eExpressionPathOptionsNoFragileObjcIvar) != 0;525const bool no_synth_child =526(options & eExpressionPathOptionsNoSyntheticChildren) != 0;527// const bool no_synth_array = (options &528// eExpressionPathOptionsNoSyntheticArrayRange) != 0;529error.Clear();530bool deref = false;531bool address_of = false;532ValueObjectSP valobj_sp;533const bool get_file_globals = true;534// When looking up a variable for an expression, we need only consider the535// variables that are in scope.536VariableListSP var_list_sp(GetInScopeVariableList(get_file_globals));537VariableList *variable_list = var_list_sp.get();538539if (!variable_list)540return ValueObjectSP();541542// If first character is a '*', then show pointer contents543std::string var_expr_storage;544if (var_expr[0] == '*') {545deref = true;546var_expr = var_expr.drop_front(); // Skip the '*'547} else if (var_expr[0] == '&') {548address_of = true;549var_expr = var_expr.drop_front(); // Skip the '&'550}551552size_t separator_idx = var_expr.find_first_of(".-[=+~|&^%#@!/?,<>{}");553StreamString var_expr_path_strm;554555ConstString name_const_string(var_expr.substr(0, separator_idx));556557var_sp = variable_list->FindVariable(name_const_string, false);558559bool synthetically_added_instance_object = false;560561if (var_sp) {562var_expr = var_expr.drop_front(name_const_string.GetLength());563}564565if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess)) {566// Check for direct ivars access which helps us with implicit access to567// ivars using "this" or "self".568GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock);569llvm::StringRef instance_var_name = m_sc.GetInstanceVariableName();570if (!instance_var_name.empty()) {571var_sp = variable_list->FindVariable(ConstString(instance_var_name));572if (var_sp) {573separator_idx = 0;574if (Type *var_type = var_sp->GetType())575if (auto compiler_type = var_type->GetForwardCompilerType())576if (!compiler_type.IsPointerType())577var_expr_storage = ".";578579if (var_expr_storage.empty())580var_expr_storage = "->";581var_expr_storage += var_expr;582var_expr = var_expr_storage;583synthetically_added_instance_object = true;584}585}586}587588if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions)) {589// Check if any anonymous unions are there which contain a variable with590// the name we need591for (const VariableSP &variable_sp : *variable_list) {592if (!variable_sp)593continue;594if (!variable_sp->GetName().IsEmpty())595continue;596597Type *var_type = variable_sp->GetType();598if (!var_type)599continue;600601if (!var_type->GetForwardCompilerType().IsAnonymousType())602continue;603valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic);604if (!valobj_sp)605return valobj_sp;606valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string);607if (valobj_sp)608break;609}610}611612if (var_sp && !valobj_sp) {613valobj_sp = GetValueObjectForFrameVariable(var_sp, use_dynamic);614if (!valobj_sp)615return valobj_sp;616}617if (!valobj_sp) {618error.SetErrorStringWithFormat("no variable named '%s' found in this frame",619name_const_string.GetCString());620return ValueObjectSP();621}622623// We are dumping at least one child624while (!var_expr.empty()) {625// Calculate the next separator index ahead of time626ValueObjectSP child_valobj_sp;627const char separator_type = var_expr[0];628bool expr_is_ptr = false;629switch (separator_type) {630case '-':631expr_is_ptr = true;632if (var_expr.size() >= 2 && var_expr[1] != '>')633return ValueObjectSP();634635if (no_fragile_ivar) {636// Make sure we aren't trying to deref an objective637// C ivar if this is not allowed638const uint32_t pointer_type_flags =639valobj_sp->GetCompilerType().GetTypeInfo(nullptr);640if ((pointer_type_flags & eTypeIsObjC) &&641(pointer_type_flags & eTypeIsPointer)) {642// This was an objective C object pointer and it was requested we643// skip any fragile ivars so return nothing here644return ValueObjectSP();645}646}647648// If we have a non pointer type with a sythetic value then lets check if649// we have an sythetic dereference specified.650if (!valobj_sp->IsPointerType() && valobj_sp->HasSyntheticValue()) {651Status deref_error;652if (valobj_sp->GetCompilerType().IsReferenceType()) {653valobj_sp = valobj_sp->GetSyntheticValue()->Dereference(deref_error);654if (!valobj_sp || deref_error.Fail()) {655error.SetErrorStringWithFormatv(656"Failed to dereference reference type: %s", deref_error);657return ValueObjectSP();658}659}660661valobj_sp = valobj_sp->Dereference(deref_error);662if (!valobj_sp || deref_error.Fail()) {663error.SetErrorStringWithFormatv(664"Failed to dereference sythetic value: {0}", deref_error);665return ValueObjectSP();666}667// Some synthetic plug-ins fail to set the error in Dereference668if (!valobj_sp) {669error.SetErrorString("Failed to dereference sythetic value");670return ValueObjectSP();671}672expr_is_ptr = false;673}674675var_expr = var_expr.drop_front(); // Remove the '-'676[[fallthrough]];677case '.': {678var_expr = var_expr.drop_front(); // Remove the '.' or '>'679separator_idx = var_expr.find_first_of(".-[");680ConstString child_name(var_expr.substr(0, var_expr.find_first_of(".-[")));681682if (check_ptr_vs_member) {683// We either have a pointer type and need to verify valobj_sp is a684// pointer, or we have a member of a class/union/struct being accessed685// with the . syntax and need to verify we don't have a pointer.686const bool actual_is_ptr = valobj_sp->IsPointerType();687688if (actual_is_ptr != expr_is_ptr) {689// Incorrect use of "." with a pointer, or "->" with a690// class/union/struct instance or reference.691valobj_sp->GetExpressionPath(var_expr_path_strm);692if (actual_is_ptr)693error.SetErrorStringWithFormat(694"\"%s\" is a pointer and . was used to attempt to access "695"\"%s\". Did you mean \"%s->%s\"?",696var_expr_path_strm.GetData(), child_name.GetCString(),697var_expr_path_strm.GetData(), var_expr.str().c_str());698else699error.SetErrorStringWithFormat(700"\"%s\" is not a pointer and -> was used to attempt to "701"access \"%s\". Did you mean \"%s.%s\"?",702var_expr_path_strm.GetData(), child_name.GetCString(),703var_expr_path_strm.GetData(), var_expr.str().c_str());704return ValueObjectSP();705}706}707child_valobj_sp = valobj_sp->GetChildMemberWithName(child_name);708if (!child_valobj_sp) {709if (!no_synth_child) {710child_valobj_sp = valobj_sp->GetSyntheticValue();711if (child_valobj_sp)712child_valobj_sp =713child_valobj_sp->GetChildMemberWithName(child_name);714}715716if (no_synth_child || !child_valobj_sp) {717// No child member with name "child_name"718if (synthetically_added_instance_object) {719// We added a "this->" or "self->" to the beginning of the720// expression and this is the first pointer ivar access, so just721// return the normal error722error.SetErrorStringWithFormat(723"no variable or instance variable named '%s' found in "724"this frame",725name_const_string.GetCString());726} else {727valobj_sp->GetExpressionPath(var_expr_path_strm);728if (child_name) {729error.SetErrorStringWithFormat(730"\"%s\" is not a member of \"(%s) %s\"",731child_name.GetCString(),732valobj_sp->GetTypeName().AsCString("<invalid type>"),733var_expr_path_strm.GetData());734} else {735error.SetErrorStringWithFormat(736"incomplete expression path after \"%s\" in \"%s\"",737var_expr_path_strm.GetData(),738original_var_expr.str().c_str());739}740}741return ValueObjectSP();742}743}744synthetically_added_instance_object = false;745// Remove the child name from the path746var_expr = var_expr.drop_front(child_name.GetLength());747if (use_dynamic != eNoDynamicValues) {748ValueObjectSP dynamic_value_sp(749child_valobj_sp->GetDynamicValue(use_dynamic));750if (dynamic_value_sp)751child_valobj_sp = dynamic_value_sp;752}753} break;754755case '[': {756// Array member access, or treating pointer as an array Need at least two757// brackets and a number758if (var_expr.size() <= 2) {759error.SetErrorStringWithFormat(760"invalid square bracket encountered after \"%s\" in \"%s\"",761var_expr_path_strm.GetData(), var_expr.str().c_str());762return ValueObjectSP();763}764765// Drop the open brace.766var_expr = var_expr.drop_front();767long child_index = 0;768769// If there's no closing brace, this is an invalid expression.770size_t end_pos = var_expr.find_first_of(']');771if (end_pos == llvm::StringRef::npos) {772error.SetErrorStringWithFormat(773"missing closing square bracket in expression \"%s\"",774var_expr_path_strm.GetData());775return ValueObjectSP();776}777llvm::StringRef index_expr = var_expr.take_front(end_pos);778llvm::StringRef original_index_expr = index_expr;779// Drop all of "[index_expr]"780var_expr = var_expr.drop_front(end_pos + 1);781782if (index_expr.consumeInteger(0, child_index)) {783// If there was no integer anywhere in the index expression, this is784// erroneous expression.785error.SetErrorStringWithFormat("invalid index expression \"%s\"",786index_expr.str().c_str());787return ValueObjectSP();788}789790if (index_expr.empty()) {791// The entire index expression was a single integer.792793if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {794// what we have is *ptr[low]. the most similar C++ syntax is to deref795// ptr and extract bit low out of it. reading array item low would be796// done by saying ptr[low], without a deref * sign797Status deref_error;798ValueObjectSP temp(valobj_sp->Dereference(deref_error));799if (!temp || deref_error.Fail()) {800valobj_sp->GetExpressionPath(var_expr_path_strm);801error.SetErrorStringWithFormat(802"could not dereference \"(%s) %s\"",803valobj_sp->GetTypeName().AsCString("<invalid type>"),804var_expr_path_strm.GetData());805return ValueObjectSP();806}807valobj_sp = temp;808deref = false;809} else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() &&810deref) {811// what we have is *arr[low]. the most similar C++ syntax is to get812// arr[0] (an operation that is equivalent to deref-ing arr) and813// extract bit low out of it. reading array item low would be done by814// saying arr[low], without a deref * sign815ValueObjectSP temp(valobj_sp->GetChildAtIndex(0));816if (!temp) {817valobj_sp->GetExpressionPath(var_expr_path_strm);818error.SetErrorStringWithFormat(819"could not get item 0 for \"(%s) %s\"",820valobj_sp->GetTypeName().AsCString("<invalid type>"),821var_expr_path_strm.GetData());822return ValueObjectSP();823}824valobj_sp = temp;825deref = false;826}827828bool is_incomplete_array = false;829if (valobj_sp->IsPointerType()) {830bool is_objc_pointer = true;831832if (valobj_sp->GetCompilerType().GetMinimumLanguage() !=833eLanguageTypeObjC)834is_objc_pointer = false;835else if (!valobj_sp->GetCompilerType().IsPointerType())836is_objc_pointer = false;837838if (no_synth_child && is_objc_pointer) {839error.SetErrorStringWithFormat(840"\"(%s) %s\" is an Objective-C pointer, and cannot be "841"subscripted",842valobj_sp->GetTypeName().AsCString("<invalid type>"),843var_expr_path_strm.GetData());844845return ValueObjectSP();846} else if (is_objc_pointer) {847// dereferencing ObjC variables is not valid.. so let's try and848// recur to synthetic children849ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();850if (!synthetic /* no synthetic */851|| synthetic == valobj_sp) /* synthetic is the same as852the original object */853{854valobj_sp->GetExpressionPath(var_expr_path_strm);855error.SetErrorStringWithFormat(856"\"(%s) %s\" is not an array type",857valobj_sp->GetTypeName().AsCString("<invalid type>"),858var_expr_path_strm.GetData());859} else if (static_cast<uint32_t>(child_index) >=860synthetic861->GetNumChildrenIgnoringErrors() /* synthetic does862not have that863many values */) {864valobj_sp->GetExpressionPath(var_expr_path_strm);865error.SetErrorStringWithFormat(866"array index %ld is not valid for \"(%s) %s\"", child_index,867valobj_sp->GetTypeName().AsCString("<invalid type>"),868var_expr_path_strm.GetData());869} else {870child_valobj_sp = synthetic->GetChildAtIndex(child_index);871if (!child_valobj_sp) {872valobj_sp->GetExpressionPath(var_expr_path_strm);873error.SetErrorStringWithFormat(874"array index %ld is not valid for \"(%s) %s\"", child_index,875valobj_sp->GetTypeName().AsCString("<invalid type>"),876var_expr_path_strm.GetData());877}878}879} else {880child_valobj_sp =881valobj_sp->GetSyntheticArrayMember(child_index, true);882if (!child_valobj_sp) {883valobj_sp->GetExpressionPath(var_expr_path_strm);884error.SetErrorStringWithFormat(885"failed to use pointer as array for index %ld for "886"\"(%s) %s\"",887child_index,888valobj_sp->GetTypeName().AsCString("<invalid type>"),889var_expr_path_strm.GetData());890}891}892} else if (valobj_sp->GetCompilerType().IsArrayType(893nullptr, nullptr, &is_incomplete_array)) {894// Pass false to dynamic_value here so we can tell the difference895// between no dynamic value and no member of this type...896child_valobj_sp = valobj_sp->GetChildAtIndex(child_index);897if (!child_valobj_sp && (is_incomplete_array || !no_synth_child))898child_valobj_sp =899valobj_sp->GetSyntheticArrayMember(child_index, true);900901if (!child_valobj_sp) {902valobj_sp->GetExpressionPath(var_expr_path_strm);903error.SetErrorStringWithFormat(904"array index %ld is not valid for \"(%s) %s\"", child_index,905valobj_sp->GetTypeName().AsCString("<invalid type>"),906var_expr_path_strm.GetData());907}908} else if (valobj_sp->GetCompilerType().IsScalarType()) {909// this is a bitfield asking to display just one bit910child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(911child_index, child_index, true);912if (!child_valobj_sp) {913valobj_sp->GetExpressionPath(var_expr_path_strm);914error.SetErrorStringWithFormat(915"bitfield range %ld-%ld is not valid for \"(%s) %s\"",916child_index, child_index,917valobj_sp->GetTypeName().AsCString("<invalid type>"),918var_expr_path_strm.GetData());919}920} else {921ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();922if (no_synth_child /* synthetic is forbidden */ ||923!synthetic /* no synthetic */924|| synthetic == valobj_sp) /* synthetic is the same as the925original object */926{927valobj_sp->GetExpressionPath(var_expr_path_strm);928error.SetErrorStringWithFormat(929"\"(%s) %s\" is not an array type",930valobj_sp->GetTypeName().AsCString("<invalid type>"),931var_expr_path_strm.GetData());932} else if (static_cast<uint32_t>(child_index) >=933synthetic->GetNumChildrenIgnoringErrors() /* synthetic934does not have that many values */) {935valobj_sp->GetExpressionPath(var_expr_path_strm);936error.SetErrorStringWithFormat(937"array index %ld is not valid for \"(%s) %s\"", child_index,938valobj_sp->GetTypeName().AsCString("<invalid type>"),939var_expr_path_strm.GetData());940} else {941child_valobj_sp = synthetic->GetChildAtIndex(child_index);942if (!child_valobj_sp) {943valobj_sp->GetExpressionPath(var_expr_path_strm);944error.SetErrorStringWithFormat(945"array index %ld is not valid for \"(%s) %s\"", child_index,946valobj_sp->GetTypeName().AsCString("<invalid type>"),947var_expr_path_strm.GetData());948}949}950}951952if (!child_valobj_sp) {953// Invalid array index...954return ValueObjectSP();955}956957if (use_dynamic != eNoDynamicValues) {958ValueObjectSP dynamic_value_sp(959child_valobj_sp->GetDynamicValue(use_dynamic));960if (dynamic_value_sp)961child_valobj_sp = dynamic_value_sp;962}963// Break out early from the switch since we were able to find the child964// member965break;966}967968// this is most probably a BitField, let's take a look969if (index_expr.front() != '-') {970error.SetErrorStringWithFormat("invalid range expression \"'%s'\"",971original_index_expr.str().c_str());972return ValueObjectSP();973}974975index_expr = index_expr.drop_front();976long final_index = 0;977if (index_expr.getAsInteger(0, final_index)) {978error.SetErrorStringWithFormat("invalid range expression \"'%s'\"",979original_index_expr.str().c_str());980return ValueObjectSP();981}982983// if the format given is [high-low], swap range984if (child_index > final_index) {985long temp = child_index;986child_index = final_index;987final_index = temp;988}989990if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {991// what we have is *ptr[low-high]. the most similar C++ syntax is to992// deref ptr and extract bits low thru high out of it. reading array993// items low thru high would be done by saying ptr[low-high], without a994// deref * sign995Status deref_error;996ValueObjectSP temp(valobj_sp->Dereference(deref_error));997if (!temp || deref_error.Fail()) {998valobj_sp->GetExpressionPath(var_expr_path_strm);999error.SetErrorStringWithFormat(1000"could not dereference \"(%s) %s\"",1001valobj_sp->GetTypeName().AsCString("<invalid type>"),1002var_expr_path_strm.GetData());1003return ValueObjectSP();1004}1005valobj_sp = temp;1006deref = false;1007} else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) {1008// what we have is *arr[low-high]. the most similar C++ syntax is to1009// get arr[0] (an operation that is equivalent to deref-ing arr) and1010// extract bits low thru high out of it. reading array items low thru1011// high would be done by saying arr[low-high], without a deref * sign1012ValueObjectSP temp(valobj_sp->GetChildAtIndex(0));1013if (!temp) {1014valobj_sp->GetExpressionPath(var_expr_path_strm);1015error.SetErrorStringWithFormat(1016"could not get item 0 for \"(%s) %s\"",1017valobj_sp->GetTypeName().AsCString("<invalid type>"),1018var_expr_path_strm.GetData());1019return ValueObjectSP();1020}1021valobj_sp = temp;1022deref = false;1023}10241025child_valobj_sp =1026valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true);1027if (!child_valobj_sp) {1028valobj_sp->GetExpressionPath(var_expr_path_strm);1029error.SetErrorStringWithFormat(1030"bitfield range %ld-%ld is not valid for \"(%s) %s\"", child_index,1031final_index, valobj_sp->GetTypeName().AsCString("<invalid type>"),1032var_expr_path_strm.GetData());1033}10341035if (!child_valobj_sp) {1036// Invalid bitfield range...1037return ValueObjectSP();1038}10391040if (use_dynamic != eNoDynamicValues) {1041ValueObjectSP dynamic_value_sp(1042child_valobj_sp->GetDynamicValue(use_dynamic));1043if (dynamic_value_sp)1044child_valobj_sp = dynamic_value_sp;1045}1046// Break out early from the switch since we were able to find the child1047// member1048break;1049}1050default:1051// Failure...1052{1053valobj_sp->GetExpressionPath(var_expr_path_strm);1054error.SetErrorStringWithFormat(1055"unexpected char '%c' encountered after \"%s\" in \"%s\"",1056separator_type, var_expr_path_strm.GetData(),1057var_expr.str().c_str());10581059return ValueObjectSP();1060}1061}10621063if (child_valobj_sp)1064valobj_sp = child_valobj_sp;1065}1066if (valobj_sp) {1067if (deref) {1068ValueObjectSP deref_valobj_sp(valobj_sp->Dereference(error));1069valobj_sp = deref_valobj_sp;1070} else if (address_of) {1071ValueObjectSP address_of_valobj_sp(valobj_sp->AddressOf(error));1072valobj_sp = address_of_valobj_sp;1073}1074}1075return valobj_sp;1076}10771078bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) {1079std::lock_guard<std::recursive_mutex> guard(m_mutex);1080if (!m_cfa_is_valid) {1081m_frame_base_error.SetErrorString(1082"No frame base available for this historical stack frame.");1083return false;1084}10851086if (m_flags.IsClear(GOT_FRAME_BASE)) {1087if (m_sc.function) {1088m_frame_base.Clear();1089m_frame_base_error.Clear();10901091m_flags.Set(GOT_FRAME_BASE);1092ExecutionContext exe_ctx(shared_from_this());1093addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;1094if (!m_sc.function->GetFrameBaseExpression().IsAlwaysValidSingleExpr())1095loclist_base_addr =1096m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(1097exe_ctx.GetTargetPtr());10981099llvm::Expected<Value> expr_value =1100m_sc.function->GetFrameBaseExpression().Evaluate(1101&exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr);1102if (!expr_value)1103m_frame_base_error = expr_value.takeError();1104else1105m_frame_base = expr_value->ResolveValue(&exe_ctx);1106} else {1107m_frame_base_error.SetErrorString("No function in symbol context.");1108}1109}11101111if (m_frame_base_error.Success())1112frame_base = m_frame_base;11131114if (error_ptr)1115*error_ptr = m_frame_base_error;1116return m_frame_base_error.Success();1117}11181119DWARFExpressionList *StackFrame::GetFrameBaseExpression(Status *error_ptr) {1120if (!m_sc.function) {1121if (error_ptr) {1122error_ptr->SetErrorString("No function in symbol context.");1123}1124return nullptr;1125}11261127return &m_sc.function->GetFrameBaseExpression();1128}11291130RegisterContextSP StackFrame::GetRegisterContext() {1131std::lock_guard<std::recursive_mutex> guard(m_mutex);1132if (!m_reg_context_sp) {1133ThreadSP thread_sp(GetThread());1134if (thread_sp)1135m_reg_context_sp = thread_sp->CreateRegisterContextForFrame(this);1136}1137return m_reg_context_sp;1138}11391140bool StackFrame::HasDebugInformation() {1141GetSymbolContext(eSymbolContextLineEntry);1142return m_sc.line_entry.IsValid();1143}11441145ValueObjectSP1146StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,1147DynamicValueType use_dynamic) {1148ValueObjectSP valobj_sp;1149{ // Scope for stack frame mutex. We need to drop this mutex before we figure1150// out the dynamic value. That will require converting the StackID in the1151// VO back to a StackFrame, which will in turn require locking the1152// StackFrameList. If we still hold the StackFrame mutex, we could suffer1153// lock inversion against the pattern of getting the StackFrameList and1154// then the stack frame, which is fairly common.1155std::lock_guard<std::recursive_mutex> guard(m_mutex);1156if (IsHistorical()) {1157return valobj_sp;1158}1159VariableList *var_list = GetVariableList(true, nullptr);1160if (var_list) {1161// Make sure the variable is a frame variable1162const uint32_t var_idx = var_list->FindIndexForVariable(variable_sp.get());1163const uint32_t num_variables = var_list->GetSize();1164if (var_idx < num_variables) {1165valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex(var_idx);1166if (!valobj_sp) {1167if (m_variable_list_value_objects.GetSize() < num_variables)1168m_variable_list_value_objects.Resize(num_variables);1169valobj_sp = ValueObjectVariable::Create(this, variable_sp);1170m_variable_list_value_objects.SetValueObjectAtIndex(var_idx,1171valobj_sp);1172}1173}1174}1175} // End of StackFrame mutex scope.1176if (use_dynamic != eNoDynamicValues && valobj_sp) {1177ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(use_dynamic);1178if (dynamic_sp)1179return dynamic_sp;1180}1181return valobj_sp;1182}11831184bool StackFrame::IsInlined() {1185if (m_sc.block == nullptr)1186GetSymbolContext(eSymbolContextBlock);1187if (m_sc.block)1188return m_sc.block->GetContainingInlinedBlock() != nullptr;1189return false;1190}11911192bool StackFrame::IsHistorical() const {1193return m_stack_frame_kind == StackFrame::Kind::History;1194}11951196bool StackFrame::IsArtificial() const {1197return m_stack_frame_kind == StackFrame::Kind::Artificial;1198}11991200SourceLanguage StackFrame::GetLanguage() {1201CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit;1202if (cu)1203return cu->GetLanguage();1204return {};1205}12061207SourceLanguage StackFrame::GuessLanguage() {1208SourceLanguage lang_type = GetLanguage();12091210if (lang_type == eLanguageTypeUnknown) {1211SymbolContext sc =1212GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol);1213if (sc.function)1214lang_type = LanguageType(sc.function->GetMangled().GuessLanguage());1215else if (sc.symbol)1216lang_type = SourceLanguage(sc.symbol->GetMangled().GuessLanguage());1217}12181219return lang_type;1220}12211222namespace {1223std::pair<const Instruction::Operand *, int64_t>1224GetBaseExplainingValue(const Instruction::Operand &operand,1225RegisterContext ®ister_context, lldb::addr_t value) {1226switch (operand.m_type) {1227case Instruction::Operand::Type::Dereference:1228case Instruction::Operand::Type::Immediate:1229case Instruction::Operand::Type::Invalid:1230case Instruction::Operand::Type::Product:1231// These are not currently interesting1232return std::make_pair(nullptr, 0);1233case Instruction::Operand::Type::Sum: {1234const Instruction::Operand *immediate_child = nullptr;1235const Instruction::Operand *variable_child = nullptr;1236if (operand.m_children[0].m_type == Instruction::Operand::Type::Immediate) {1237immediate_child = &operand.m_children[0];1238variable_child = &operand.m_children[1];1239} else if (operand.m_children[1].m_type ==1240Instruction::Operand::Type::Immediate) {1241immediate_child = &operand.m_children[1];1242variable_child = &operand.m_children[0];1243}1244if (!immediate_child) {1245return std::make_pair(nullptr, 0);1246}1247lldb::addr_t adjusted_value = value;1248if (immediate_child->m_negative) {1249adjusted_value += immediate_child->m_immediate;1250} else {1251adjusted_value -= immediate_child->m_immediate;1252}1253std::pair<const Instruction::Operand *, int64_t> base_and_offset =1254GetBaseExplainingValue(*variable_child, register_context,1255adjusted_value);1256if (!base_and_offset.first) {1257return std::make_pair(nullptr, 0);1258}1259if (immediate_child->m_negative) {1260base_and_offset.second -= immediate_child->m_immediate;1261} else {1262base_and_offset.second += immediate_child->m_immediate;1263}1264return base_and_offset;1265}1266case Instruction::Operand::Type::Register: {1267const RegisterInfo *info =1268register_context.GetRegisterInfoByName(operand.m_register.AsCString());1269if (!info) {1270return std::make_pair(nullptr, 0);1271}1272RegisterValue reg_value;1273if (!register_context.ReadRegister(info, reg_value)) {1274return std::make_pair(nullptr, 0);1275}1276if (reg_value.GetAsUInt64() == value) {1277return std::make_pair(&operand, 0);1278} else {1279return std::make_pair(nullptr, 0);1280}1281}1282}1283return std::make_pair(nullptr, 0);1284}12851286std::pair<const Instruction::Operand *, int64_t>1287GetBaseExplainingDereference(const Instruction::Operand &operand,1288RegisterContext ®ister_context,1289lldb::addr_t addr) {1290if (operand.m_type == Instruction::Operand::Type::Dereference) {1291return GetBaseExplainingValue(operand.m_children[0], register_context,1292addr);1293}1294return std::make_pair(nullptr, 0);1295}1296} // namespace12971298lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {1299TargetSP target_sp = CalculateTarget();13001301const ArchSpec &target_arch = target_sp->GetArchitecture();13021303AddressRange pc_range;1304pc_range.GetBaseAddress() = GetFrameCodeAddress();1305pc_range.SetByteSize(target_arch.GetMaximumOpcodeByteSize());13061307const char *plugin_name = nullptr;1308const char *flavor = nullptr;1309const bool force_live_memory = true;13101311DisassemblerSP disassembler_sp =1312Disassembler::DisassembleRange(target_arch, plugin_name, flavor,1313*target_sp, pc_range, force_live_memory);13141315if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {1316return ValueObjectSP();1317}13181319InstructionSP instruction_sp =1320disassembler_sp->GetInstructionList().GetInstructionAtIndex(0);13211322llvm::SmallVector<Instruction::Operand, 3> operands;13231324if (!instruction_sp->ParseOperands(operands)) {1325return ValueObjectSP();1326}13271328RegisterContextSP register_context_sp = GetRegisterContext();13291330if (!register_context_sp) {1331return ValueObjectSP();1332}13331334for (const Instruction::Operand &operand : operands) {1335std::pair<const Instruction::Operand *, int64_t> base_and_offset =1336GetBaseExplainingDereference(operand, *register_context_sp, addr);13371338if (!base_and_offset.first) {1339continue;1340}13411342switch (base_and_offset.first->m_type) {1343case Instruction::Operand::Type::Immediate: {1344lldb_private::Address addr;1345if (target_sp->ResolveLoadAddress(base_and_offset.first->m_immediate +1346base_and_offset.second,1347addr)) {1348auto c_type_system_or_err =1349target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC);1350if (auto err = c_type_system_or_err.takeError()) {1351LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(err),1352"Unable to guess value for given address: {0}");1353return ValueObjectSP();1354} else {1355auto ts = *c_type_system_or_err;1356if (!ts)1357return {};1358CompilerType void_ptr_type =1359ts->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar)1360.GetPointerType();1361return ValueObjectMemory::Create(this, "", addr, void_ptr_type);1362}1363} else {1364return ValueObjectSP();1365}1366break;1367}1368case Instruction::Operand::Type::Register: {1369return GuessValueForRegisterAndOffset(base_and_offset.first->m_register,1370base_and_offset.second);1371}1372default:1373return ValueObjectSP();1374}1375}13761377return ValueObjectSP();1378}13791380namespace {1381ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent,1382int64_t offset) {1383if (offset < 0 || uint64_t(offset) >= parent->GetByteSize()) {1384return ValueObjectSP();1385}13861387if (parent->IsPointerOrReferenceType()) {1388return parent;1389}13901391for (int ci = 0, ce = parent->GetNumChildrenIgnoringErrors(); ci != ce;1392++ci) {1393ValueObjectSP child_sp = parent->GetChildAtIndex(ci);13941395if (!child_sp) {1396return ValueObjectSP();1397}13981399int64_t child_offset = child_sp->GetByteOffset();1400int64_t child_size = child_sp->GetByteSize().value_or(0);14011402if (offset >= child_offset && offset < (child_offset + child_size)) {1403return GetValueForOffset(frame, child_sp, offset - child_offset);1404}1405}14061407if (offset == 0) {1408return parent;1409} else {1410return ValueObjectSP();1411}1412}14131414ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame,1415ValueObjectSP &base,1416int64_t offset) {1417// base is a pointer to something1418// offset is the thing to add to the pointer We return the most sensible1419// ValueObject for the result of *(base+offset)14201421if (!base->IsPointerOrReferenceType()) {1422return ValueObjectSP();1423}14241425Status error;1426ValueObjectSP pointee = base->Dereference(error);14271428if (!pointee) {1429return ValueObjectSP();1430}14311432if (offset >= 0 && uint64_t(offset) >= pointee->GetByteSize()) {1433int64_t index = offset / pointee->GetByteSize().value_or(1);1434offset = offset % pointee->GetByteSize().value_or(1);1435const bool can_create = true;1436pointee = base->GetSyntheticArrayMember(index, can_create);1437}14381439if (!pointee || error.Fail()) {1440return ValueObjectSP();1441}14421443return GetValueForOffset(frame, pointee, offset);1444}14451446/// Attempt to reconstruct the ValueObject for the address contained in a1447/// given register plus an offset.1448///1449/// \param [in] frame1450/// The current stack frame.1451///1452/// \param [in] reg1453/// The register.1454///1455/// \param [in] offset1456/// The offset from the register.1457///1458/// \param [in] disassembler1459/// A disassembler containing instructions valid up to the current PC.1460///1461/// \param [in] variables1462/// The variable list from the current frame,1463///1464/// \param [in] pc1465/// The program counter for the instruction considered the 'user'.1466///1467/// \return1468/// A string describing the base for the ExpressionPath. This could be a1469/// variable, a register value, an argument, or a function return value.1470/// The ValueObject if found. If valid, it has a valid ExpressionPath.1471lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,1472int64_t offset, Disassembler &disassembler,1473VariableList &variables, const Address &pc) {1474// Example of operation for Intel:1475//1476// +14: movq -0x8(%rbp), %rdi1477// +18: movq 0x8(%rdi), %rdi1478// +22: addl 0x4(%rdi), %eax1479//1480// f, a pointer to a struct, is known to be at -0x8(%rbp).1481//1482// DoGuessValueAt(frame, rdi, 4, dis, vars, 0x22) finds the instruction at1483// +18 that assigns to rdi, and calls itself recursively for that dereference1484// DoGuessValueAt(frame, rdi, 8, dis, vars, 0x18) finds the instruction at1485// +14 that assigns to rdi, and calls itself recursively for that1486// dereference1487// DoGuessValueAt(frame, rbp, -8, dis, vars, 0x14) finds "f" in the1488// variable list.1489// Returns a ValueObject for f. (That's what was stored at rbp-8 at +14)1490// Returns a ValueObject for *(f+8) or f->b (That's what was stored at rdi+81491// at +18)1492// Returns a ValueObject for *(f->b+4) or f->b->a (That's what was stored at1493// rdi+4 at +22)14941495// First, check the variable list to see if anything is at the specified1496// location.14971498using namespace OperandMatchers;14991500const RegisterInfo *reg_info =1501frame.GetRegisterContext()->GetRegisterInfoByName(reg.AsCString());1502if (!reg_info) {1503return ValueObjectSP();1504}15051506Instruction::Operand op =1507offset ? Instruction::Operand::BuildDereference(1508Instruction::Operand::BuildSum(1509Instruction::Operand::BuildRegister(reg),1510Instruction::Operand::BuildImmediate(offset)))1511: Instruction::Operand::BuildDereference(1512Instruction::Operand::BuildRegister(reg));15131514for (VariableSP var_sp : variables) {1515if (var_sp->LocationExpressionList().MatchesOperand(frame, op))1516return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);1517}15181519const uint32_t current_inst =1520disassembler.GetInstructionList().GetIndexOfInstructionAtAddress(pc);1521if (current_inst == UINT32_MAX) {1522return ValueObjectSP();1523}15241525for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) {1526// This is not an exact algorithm, and it sacrifices accuracy for1527// generality. Recognizing "mov" and "ld" instructions –– and which1528// are their source and destination operands -- is something the1529// disassembler should do for us.1530InstructionSP instruction_sp =1531disassembler.GetInstructionList().GetInstructionAtIndex(ii);15321533if (instruction_sp->IsCall()) {1534ABISP abi_sp = frame.CalculateProcess()->GetABI();1535if (!abi_sp) {1536continue;1537}15381539const char *return_register_name;1540if (!abi_sp->GetPointerReturnRegister(return_register_name)) {1541continue;1542}15431544const RegisterInfo *return_register_info =1545frame.GetRegisterContext()->GetRegisterInfoByName(1546return_register_name);1547if (!return_register_info) {1548continue;1549}15501551int64_t offset = 0;15521553if (!MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference),1554MatchRegOp(*return_register_info))(op) &&1555!MatchUnaryOp(1556MatchOpType(Instruction::Operand::Type::Dereference),1557MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum),1558MatchRegOp(*return_register_info),1559FetchImmOp(offset)))(op)) {1560continue;1561}15621563llvm::SmallVector<Instruction::Operand, 1> operands;1564if (!instruction_sp->ParseOperands(operands) || operands.size() != 1) {1565continue;1566}15671568switch (operands[0].m_type) {1569default:1570break;1571case Instruction::Operand::Type::Immediate: {1572SymbolContext sc;1573Address load_address;1574if (!frame.CalculateTarget()->ResolveLoadAddress(1575operands[0].m_immediate, load_address)) {1576break;1577}1578frame.CalculateTarget()->GetImages().ResolveSymbolContextForAddress(1579load_address, eSymbolContextFunction, sc);1580if (!sc.function) {1581break;1582}1583CompilerType function_type = sc.function->GetCompilerType();1584if (!function_type.IsFunctionType()) {1585break;1586}1587CompilerType return_type = function_type.GetFunctionReturnType();1588RegisterValue return_value;1589if (!frame.GetRegisterContext()->ReadRegister(return_register_info,1590return_value)) {1591break;1592}1593std::string name_str(1594sc.function->GetName().AsCString("<unknown function>"));1595name_str.append("()");1596Address return_value_address(return_value.GetAsUInt64());1597ValueObjectSP return_value_sp = ValueObjectMemory::Create(1598&frame, name_str, return_value_address, return_type);1599return GetValueForDereferincingOffset(frame, return_value_sp, offset);1600}1601}16021603continue;1604}16051606llvm::SmallVector<Instruction::Operand, 2> operands;1607if (!instruction_sp->ParseOperands(operands) || operands.size() != 2) {1608continue;1609}16101611Instruction::Operand *origin_operand = nullptr;1612auto clobbered_reg_matcher = [reg_info](const Instruction::Operand &op) {1613return MatchRegOp(*reg_info)(op) && op.m_clobbered;1614};16151616if (clobbered_reg_matcher(operands[0])) {1617origin_operand = &operands[1];1618}1619else if (clobbered_reg_matcher(operands[1])) {1620origin_operand = &operands[0];1621}1622else {1623continue;1624}16251626// We have an origin operand. Can we track its value down?1627ValueObjectSP source_path;1628ConstString origin_register;1629int64_t origin_offset = 0;16301631if (FetchRegOp(origin_register)(*origin_operand)) {1632source_path = DoGuessValueAt(frame, origin_register, 0, disassembler,1633variables, instruction_sp->GetAddress());1634} else if (MatchUnaryOp(1635MatchOpType(Instruction::Operand::Type::Dereference),1636FetchRegOp(origin_register))(*origin_operand) ||1637MatchUnaryOp(1638MatchOpType(Instruction::Operand::Type::Dereference),1639MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum),1640FetchRegOp(origin_register),1641FetchImmOp(origin_offset)))(*origin_operand)) {1642source_path =1643DoGuessValueAt(frame, origin_register, origin_offset, disassembler,1644variables, instruction_sp->GetAddress());1645if (!source_path) {1646continue;1647}1648source_path =1649GetValueForDereferincingOffset(frame, source_path, offset);1650}16511652if (source_path) {1653return source_path;1654}1655}16561657return ValueObjectSP();1658}1659}16601661lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,1662int64_t offset) {1663TargetSP target_sp = CalculateTarget();16641665const ArchSpec &target_arch = target_sp->GetArchitecture();16661667Block *frame_block = GetFrameBlock();16681669if (!frame_block) {1670return ValueObjectSP();1671}16721673Function *function = frame_block->CalculateSymbolContextFunction();1674if (!function) {1675return ValueObjectSP();1676}16771678AddressRange pc_range = function->GetAddressRange();16791680if (GetFrameCodeAddress().GetFileAddress() <1681pc_range.GetBaseAddress().GetFileAddress() ||1682GetFrameCodeAddress().GetFileAddress() -1683pc_range.GetBaseAddress().GetFileAddress() >=1684pc_range.GetByteSize()) {1685return ValueObjectSP();1686}16871688const char *plugin_name = nullptr;1689const char *flavor = nullptr;1690const bool force_live_memory = true;1691DisassemblerSP disassembler_sp =1692Disassembler::DisassembleRange(target_arch, plugin_name, flavor,1693*target_sp, pc_range, force_live_memory);16941695if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {1696return ValueObjectSP();1697}16981699const bool get_file_globals = false;1700VariableList *variables = GetVariableList(get_file_globals, nullptr);17011702if (!variables) {1703return ValueObjectSP();1704}17051706return DoGuessValueAt(*this, reg, offset, *disassembler_sp, *variables,1707GetFrameCodeAddress());1708}17091710lldb::ValueObjectSP StackFrame::FindVariable(ConstString name) {1711ValueObjectSP value_sp;17121713if (!name)1714return value_sp;17151716TargetSP target_sp = CalculateTarget();1717ProcessSP process_sp = CalculateProcess();17181719if (!target_sp && !process_sp)1720return value_sp;17211722VariableList variable_list;1723VariableSP var_sp;1724SymbolContext sc(GetSymbolContext(eSymbolContextBlock));17251726if (sc.block) {1727const bool can_create = true;1728const bool get_parent_variables = true;1729const bool stop_if_block_is_inlined_function = true;17301731if (sc.block->AppendVariables(1732can_create, get_parent_variables, stop_if_block_is_inlined_function,1733[this](Variable *v) { return v->IsInScope(this); },1734&variable_list)) {1735var_sp = variable_list.FindVariable(name);1736}17371738if (var_sp)1739value_sp = GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);1740}17411742return value_sp;1743}17441745TargetSP StackFrame::CalculateTarget() {1746TargetSP target_sp;1747ThreadSP thread_sp(GetThread());1748if (thread_sp) {1749ProcessSP process_sp(thread_sp->CalculateProcess());1750if (process_sp)1751target_sp = process_sp->CalculateTarget();1752}1753return target_sp;1754}17551756ProcessSP StackFrame::CalculateProcess() {1757ProcessSP process_sp;1758ThreadSP thread_sp(GetThread());1759if (thread_sp)1760process_sp = thread_sp->CalculateProcess();1761return process_sp;1762}17631764ThreadSP StackFrame::CalculateThread() { return GetThread(); }17651766StackFrameSP StackFrame::CalculateStackFrame() { return shared_from_this(); }17671768void StackFrame::CalculateExecutionContext(ExecutionContext &exe_ctx) {1769exe_ctx.SetContext(shared_from_this());1770}17711772bool StackFrame::DumpUsingFormat(Stream &strm,1773const FormatEntity::Entry *format,1774llvm::StringRef frame_marker) {1775GetSymbolContext(eSymbolContextEverything);1776ExecutionContext exe_ctx(shared_from_this());1777StreamString s;1778s.PutCString(frame_marker);17791780if (format && FormatEntity::Format(*format, s, &m_sc, &exe_ctx, nullptr,1781nullptr, false, false)) {1782strm.PutCString(s.GetString());1783return true;1784}1785return false;1786}17871788void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique,1789const char *frame_marker) {1790if (strm == nullptr)1791return;17921793ExecutionContext exe_ctx(shared_from_this());17941795const FormatEntity::Entry *frame_format = nullptr;1796Target *target = exe_ctx.GetTargetPtr();1797if (target) {1798if (show_unique) {1799frame_format = target->GetDebugger().GetFrameFormatUnique();1800} else {1801frame_format = target->GetDebugger().GetFrameFormat();1802}1803}1804if (!DumpUsingFormat(*strm, frame_format, frame_marker)) {1805Dump(strm, true, false);1806strm->EOL();1807}1808}18091810void StackFrame::Dump(Stream *strm, bool show_frame_index,1811bool show_fullpaths) {1812if (strm == nullptr)1813return;18141815if (show_frame_index)1816strm->Printf("frame #%u: ", m_frame_index);1817ExecutionContext exe_ctx(shared_from_this());1818Target *target = exe_ctx.GetTargetPtr();1819strm->Printf("0x%0*" PRIx64 " ",1820target ? (target->GetArchitecture().GetAddressByteSize() * 2)1821: 16,1822GetFrameCodeAddress().GetLoadAddress(target));1823GetSymbolContext(eSymbolContextEverything);1824const bool show_module = true;1825const bool show_inline = true;1826const bool show_function_arguments = true;1827const bool show_function_name = true;1828m_sc.DumpStopContext(strm, exe_ctx.GetBestExecutionContextScope(),1829GetFrameCodeAddress(), show_fullpaths, show_module,1830show_inline, show_function_arguments,1831show_function_name);1832}18331834void StackFrame::UpdateCurrentFrameFromPreviousFrame(StackFrame &prev_frame) {1835std::lock_guard<std::recursive_mutex> guard(m_mutex);1836assert(GetStackID() ==1837prev_frame.GetStackID()); // TODO: remove this after some testing1838m_variable_list_sp = prev_frame.m_variable_list_sp;1839m_variable_list_value_objects.Swap(prev_frame.m_variable_list_value_objects);1840if (!m_disassembly.GetString().empty()) {1841m_disassembly.Clear();1842m_disassembly.PutCString(prev_frame.m_disassembly.GetString());1843}1844}18451846void StackFrame::UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame) {1847std::lock_guard<std::recursive_mutex> guard(m_mutex);1848assert(GetStackID() ==1849curr_frame.GetStackID()); // TODO: remove this after some testing1850m_id.SetPC(curr_frame.m_id.GetPC()); // Update the Stack ID PC value1851assert(GetThread() == curr_frame.GetThread());1852m_frame_index = curr_frame.m_frame_index;1853m_concrete_frame_index = curr_frame.m_concrete_frame_index;1854m_reg_context_sp = curr_frame.m_reg_context_sp;1855m_frame_code_addr = curr_frame.m_frame_code_addr;1856m_behaves_like_zeroth_frame = curr_frame.m_behaves_like_zeroth_frame;1857assert(!m_sc.target_sp || !curr_frame.m_sc.target_sp ||1858m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get());1859assert(!m_sc.module_sp || !curr_frame.m_sc.module_sp ||1860m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get());1861assert(m_sc.comp_unit == nullptr || curr_frame.m_sc.comp_unit == nullptr ||1862m_sc.comp_unit == curr_frame.m_sc.comp_unit);1863assert(m_sc.function == nullptr || curr_frame.m_sc.function == nullptr ||1864m_sc.function == curr_frame.m_sc.function);1865m_sc = curr_frame.m_sc;1866m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything);1867m_flags.Set(m_sc.GetResolvedMask());1868m_frame_base.Clear();1869m_frame_base_error.Clear();1870}18711872bool StackFrame::HasCachedData() const {1873if (m_variable_list_sp)1874return true;1875if (m_variable_list_value_objects.GetSize() > 0)1876return true;1877if (!m_disassembly.GetString().empty())1878return true;1879return false;1880}18811882bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,1883bool show_unique, const char *frame_marker) {1884if (show_frame_info) {1885strm.Indent();1886DumpUsingSettingsFormat(&strm, show_unique, frame_marker);1887}18881889if (show_source) {1890ExecutionContext exe_ctx(shared_from_this());1891bool have_source = false, have_debuginfo = false;1892Debugger::StopDisassemblyType disasm_display =1893Debugger::eStopDisassemblyTypeNever;1894Target *target = exe_ctx.GetTargetPtr();1895if (target) {1896Debugger &debugger = target->GetDebugger();1897const uint32_t source_lines_before =1898debugger.GetStopSourceLineCount(true);1899const uint32_t source_lines_after =1900debugger.GetStopSourceLineCount(false);1901disasm_display = debugger.GetStopDisassemblyDisplay();19021903GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);1904if (m_sc.comp_unit && m_sc.line_entry.IsValid()) {1905have_debuginfo = true;1906if (source_lines_before > 0 || source_lines_after > 0) {1907uint32_t start_line = m_sc.line_entry.line;1908if (!start_line && m_sc.function) {1909FileSpec source_file;1910m_sc.function->GetStartLineSourceInfo(source_file, start_line);1911}19121913size_t num_lines =1914target->GetSourceManager().DisplaySourceLinesWithLineNumbers(1915m_sc.line_entry.GetFile(), start_line, m_sc.line_entry.column,1916source_lines_before, source_lines_after, "->", &strm);1917if (num_lines != 0)1918have_source = true;1919// TODO: Give here a one time warning if source file is missing.1920if (!m_sc.line_entry.line) {1921ConstString fn_name = m_sc.GetFunctionName();19221923if (!fn_name.IsEmpty())1924strm.Printf(1925"Note: this address is compiler-generated code in function "1926"%s that has no source code associated with it.",1927fn_name.AsCString());1928else1929strm.Printf("Note: this address is compiler-generated code that "1930"has no source code associated with it.");1931strm.EOL();1932}1933}1934}1935switch (disasm_display) {1936case Debugger::eStopDisassemblyTypeNever:1937break;19381939case Debugger::eStopDisassemblyTypeNoDebugInfo:1940if (have_debuginfo)1941break;1942[[fallthrough]];19431944case Debugger::eStopDisassemblyTypeNoSource:1945if (have_source)1946break;1947[[fallthrough]];19481949case Debugger::eStopDisassemblyTypeAlways:1950if (target) {1951const uint32_t disasm_lines = debugger.GetDisassemblyLineCount();1952if (disasm_lines > 0) {1953const ArchSpec &target_arch = target->GetArchitecture();1954const char *plugin_name = nullptr;1955const char *flavor = nullptr;1956const bool mixed_source_and_assembly = false;1957Disassembler::Disassemble(1958target->GetDebugger(), target_arch, plugin_name, flavor,1959exe_ctx, GetFrameCodeAddress(),1960{Disassembler::Limit::Instructions, disasm_lines},1961mixed_source_and_assembly, 0,1962Disassembler::eOptionMarkPCAddress, strm);1963}1964}1965break;1966}1967}1968}1969return true;1970}19711972RecognizedStackFrameSP StackFrame::GetRecognizedFrame() {1973if (!m_recognized_frame_sp) {1974m_recognized_frame_sp = GetThread()1975->GetProcess()1976->GetTarget()1977.GetFrameRecognizerManager()1978.RecognizeFrame(CalculateStackFrame());1979}1980return m_recognized_frame_sp;1981}198219831984