brintos

brintos / llvm-project-archived public Read only

0
0
Text · 77.2 KiB · 78f67d2 Raw
2130 lines · cpp
1//===-- StackFrame.cpp ----------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Target/StackFrame.h"10#include "lldb/Core/Debugger.h"11#include "lldb/Core/Disassembler.h"12#include "lldb/Core/FormatEntity.h"13#include "lldb/Core/Mangled.h"14#include "lldb/Core/Module.h"15#include "lldb/Core/Value.h"16#include "lldb/Symbol/CompileUnit.h"17#include "lldb/Symbol/Function.h"18#include "lldb/Symbol/Symbol.h"19#include "lldb/Symbol/SymbolContextScope.h"20#include "lldb/Symbol/SymbolFile.h"21#include "lldb/Symbol/Type.h"22#include "lldb/Symbol/VariableList.h"23#include "lldb/Target/ABI.h"24#include "lldb/Target/ExecutionContext.h"25#include "lldb/Target/LanguageRuntime.h"26#include "lldb/Target/Process.h"27#include "lldb/Target/RegisterContext.h"28#include "lldb/Target/StackFrameRecognizer.h"29#include "lldb/Target/Target.h"30#include "lldb/Target/Thread.h"31#include "lldb/Utility/LLDBLog.h"32#include "lldb/Utility/Log.h"33#include "lldb/Utility/RegisterValue.h"34#include "lldb/ValueObject/DILEval.h"35#include "lldb/ValueObject/DILLexer.h"36#include "lldb/ValueObject/DILParser.h"37#include "lldb/ValueObject/ValueObjectConstResult.h"38#include "lldb/ValueObject/ValueObjectMemory.h"39#include "lldb/ValueObject/ValueObjectVariable.h"40 41#include "lldb/lldb-enumerations.h"42 43#include <memory>44 45using namespace lldb;46using namespace lldb_private;47 48// The first bits in the flags are reserved for the SymbolContext::Scope bits49// so we know if we have tried to look up information in our internal symbol50// context (m_sc) already.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)56 57StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,58                       user_id_t unwind_frame_index, addr_t cfa,59                       bool cfa_is_valid, addr_t pc, StackFrame::Kind kind,60                       bool artificial, bool behaves_like_zeroth_frame,61                       const SymbolContext *sc_ptr)62    : m_thread_wp(thread_sp), m_frame_index(frame_idx),63      m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(),64      m_id(pc, cfa, nullptr, thread_sp->GetProcess().get()),65      m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(),66      m_frame_base_error(), m_cfa_is_valid(cfa_is_valid),67      m_stack_frame_kind(kind), m_artificial(artificial),68      m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),69      m_variable_list_sp(), m_variable_list_value_objects(),70      m_recognized_frame_sp(), m_disassembly(), m_mutex() {71  // If we don't have a CFA value, use the frame index for our StackID so that72  // recursive functions properly aren't confused with one another on a history73  // stack.74  if (IsHistorical() && !m_cfa_is_valid) {75    m_id.SetCFA(m_frame_index, thread_sp->GetProcess().get());76  }77 78  if (sc_ptr != nullptr) {79    m_sc = *sc_ptr;80    m_flags.Set(m_sc.GetResolvedMask());81  }82}83 84StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,85                       user_id_t unwind_frame_index,86                       const RegisterContextSP &reg_context_sp, addr_t cfa,87                       addr_t pc, bool behaves_like_zeroth_frame,88                       const SymbolContext *sc_ptr)89    : m_thread_wp(thread_sp), m_frame_index(frame_idx),90      m_concrete_frame_index(unwind_frame_index),91      m_reg_context_sp(reg_context_sp),92      m_id(pc, cfa, nullptr, thread_sp->GetProcess().get()),93      m_frame_code_addr(pc), m_sc(), m_flags(), m_frame_base(),94      m_frame_base_error(), m_cfa_is_valid(true),95      m_stack_frame_kind(StackFrame::Kind::Regular), m_artificial(false),96      m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),97      m_variable_list_sp(), m_variable_list_value_objects(),98      m_recognized_frame_sp(), m_disassembly(), m_mutex() {99  if (sc_ptr != nullptr) {100    m_sc = *sc_ptr;101    m_flags.Set(m_sc.GetResolvedMask());102  }103 104  if (reg_context_sp && !m_sc.target_sp) {105    m_sc.target_sp = reg_context_sp->CalculateTarget();106    if (m_sc.target_sp)107      m_flags.Set(eSymbolContextTarget);108  }109}110 111StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,112                       user_id_t unwind_frame_index,113                       const RegisterContextSP &reg_context_sp, addr_t cfa,114                       const Address &pc_addr, bool behaves_like_zeroth_frame,115                       const SymbolContext *sc_ptr)116    : m_thread_wp(thread_sp), m_frame_index(frame_idx),117      m_concrete_frame_index(unwind_frame_index),118      m_reg_context_sp(reg_context_sp),119      m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa,120           nullptr, thread_sp->GetProcess().get()),121      m_frame_code_addr(pc_addr), m_sc(), m_flags(), m_frame_base(),122      m_frame_base_error(), m_cfa_is_valid(true),123      m_stack_frame_kind(StackFrame::Kind::Regular), m_artificial(false),124      m_behaves_like_zeroth_frame(behaves_like_zeroth_frame),125      m_variable_list_sp(), m_variable_list_value_objects(),126      m_recognized_frame_sp(), m_disassembly(), m_mutex() {127  if (sc_ptr != nullptr) {128    m_sc = *sc_ptr;129    m_flags.Set(m_sc.GetResolvedMask());130  }131 132  if (!m_sc.target_sp && reg_context_sp) {133    m_sc.target_sp = reg_context_sp->CalculateTarget();134    if (m_sc.target_sp)135      m_flags.Set(eSymbolContextTarget);136  }137 138  ModuleSP pc_module_sp(pc_addr.GetModule());139  if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp) {140    if (pc_module_sp) {141      m_sc.module_sp = pc_module_sp;142      m_flags.Set(eSymbolContextModule);143    } else {144      m_sc.module_sp.reset();145    }146  }147}148 149StackFrame::~StackFrame() = default;150 151StackID &StackFrame::GetStackID() {152  std::lock_guard<std::recursive_mutex> guard(m_mutex);153  // Make sure we have resolved the StackID object's symbol context scope if we154  // already haven't looked it up.155 156  if (m_flags.IsClear(RESOLVED_FRAME_ID_SYMBOL_SCOPE)) {157    if (m_id.GetSymbolContextScope()) {158      // We already have a symbol context scope, we just don't have our flag159      // bit set.160      m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE);161    } else {162      // Calculate the frame block and use this for the stack ID symbol context163      // scope if we have one.164      SymbolContextScope *scope = GetFrameBlock();165      if (scope == nullptr) {166        // We don't have a block, so use the symbol167        if (m_flags.IsClear(eSymbolContextSymbol))168          GetSymbolContext(eSymbolContextSymbol);169 170        // It is ok if m_sc.symbol is nullptr here171        scope = m_sc.symbol;172      }173      // Set the symbol context scope (the accessor will set the174      // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags).175      SetSymbolContextScope(scope);176    }177  }178  return m_id;179}180 181uint32_t StackFrame::GetFrameIndex() const {182  ThreadSP thread_sp = GetThread();183  if (thread_sp)184    return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex(185        m_frame_index);186  else187    return m_frame_index;188}189 190void StackFrame::SetSymbolContextScope(SymbolContextScope *symbol_scope) {191  std::lock_guard<std::recursive_mutex> guard(m_mutex);192  m_flags.Set(RESOLVED_FRAME_ID_SYMBOL_SCOPE);193  m_id.SetSymbolContextScope(symbol_scope);194}195 196const Address &StackFrame::GetFrameCodeAddress() {197  std::lock_guard<std::recursive_mutex> guard(m_mutex);198  if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) &&199      !m_frame_code_addr.IsSectionOffset()) {200    m_flags.Set(RESOLVED_FRAME_CODE_ADDR);201 202    // Resolve the PC into a temporary address because if ResolveLoadAddress203    // fails to resolve the address, it will clear the address object...204    ThreadSP thread_sp(GetThread());205    if (thread_sp) {206      TargetSP target_sp(thread_sp->CalculateTarget());207      if (target_sp) {208        const bool allow_section_end = true;209        if (m_frame_code_addr.SetOpcodeLoadAddress(210                m_frame_code_addr.GetOffset(), target_sp.get(),211                AddressClass::eCode, allow_section_end)) {212          ModuleSP module_sp(m_frame_code_addr.GetModule());213          if (module_sp) {214            m_sc.module_sp = module_sp;215            m_flags.Set(eSymbolContextModule);216          }217        }218      }219    }220  }221  return m_frame_code_addr;222}223 224// This can't be rewritten into a call to225// RegisterContext::GetPCForSymbolication because this226// StackFrame may have been constructed with a special pc,227// e.g. tail-call artificial frames.228Address StackFrame::GetFrameCodeAddressForSymbolication() {229  Address lookup_addr(GetFrameCodeAddress());230  if (!lookup_addr.IsValid())231    return lookup_addr;232  if (m_behaves_like_zeroth_frame)233    return lookup_addr;234 235  addr_t offset = lookup_addr.GetOffset();236  if (offset > 0) {237    lookup_addr.SetOffset(offset - 1);238  } else {239    // lookup_addr is the start of a section.  We need do the math on the240    // actual load address and re-compute the section.  We're working with241    // a 'noreturn' function at the end of a section.242    TargetSP target_sp = CalculateTarget();243    if (target_sp) {244      addr_t addr_minus_one = lookup_addr.GetOpcodeLoadAddress(245                                  target_sp.get(), AddressClass::eCode) -246                              1;247      lookup_addr.SetOpcodeLoadAddress(addr_minus_one, target_sp.get());248    }249  }250  return lookup_addr;251}252 253bool StackFrame::ChangePC(addr_t pc) {254  std::lock_guard<std::recursive_mutex> guard(m_mutex);255  // We can't change the pc value of a history stack frame - it is immutable.256  if (IsHistorical())257    return false;258  m_frame_code_addr.SetRawAddress(pc);259  m_sc.Clear(false);260  m_flags.Reset(0);261  ThreadSP thread_sp(GetThread());262  if (thread_sp)263    thread_sp->ClearStackFrames();264  return true;265}266 267const char *StackFrame::Disassemble() {268  std::lock_guard<std::recursive_mutex> guard(m_mutex);269 270  if (!m_disassembly.Empty())271    return m_disassembly.GetData();272 273  ExecutionContext exe_ctx(shared_from_this());274  if (Target *target = exe_ctx.GetTargetPtr()) {275    Disassembler::Disassemble(target->GetDebugger(), target->GetArchitecture(),276                              *this, m_disassembly);277  }278 279  return m_disassembly.Empty() ? nullptr : m_disassembly.GetData();280}281 282Block *StackFrame::GetFrameBlock() {283  if (m_sc.block == nullptr && m_flags.IsClear(eSymbolContextBlock))284    GetSymbolContext(eSymbolContextBlock);285 286  if (m_sc.block) {287    Block *inline_block = m_sc.block->GetContainingInlinedBlock();288    if (inline_block) {289      // Use the block with the inlined function info as the frame block we290      // want this frame to have only the variables for the inlined function291      // and its non-inlined block child blocks.292      return inline_block;293    } else {294      // This block is not contained within any inlined function blocks with so295      // we want to use the top most function block.296      return &m_sc.function->GetBlock(false);297    }298  }299  return nullptr;300}301 302// Get the symbol context if we already haven't done so by resolving the303// PC address as much as possible. This way when we pass around a304// StackFrame object, everyone will have as much information as possible and no305// one will ever have to look things up manually.306const SymbolContext &307StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) {308  std::lock_guard<std::recursive_mutex> guard(m_mutex);309  // Copy our internal symbol context into "sc".310  if ((m_flags.Get() & resolve_scope) != resolve_scope) {311    uint32_t resolved = 0;312 313    // If the target was requested add that:314    if (!m_sc.target_sp) {315      m_sc.target_sp = CalculateTarget();316      if (m_sc.target_sp)317        resolved |= eSymbolContextTarget;318    }319 320    // Resolve our PC to section offset if we haven't already done so and if we321    // don't have a module. The resolved address section will contain the322    // module to which it belongs323    if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR))324      GetFrameCodeAddress();325 326    // If this is not frame zero, then we need to subtract 1 from the PC value327    // when doing address lookups since the PC will be on the instruction328    // following the function call instruction...329    Address lookup_addr(GetFrameCodeAddressForSymbolication());330 331    if (m_sc.module_sp) {332      // We have something in our stack frame symbol context, lets check if we333      // haven't already tried to lookup one of those things. If we haven't334      // then we will do the query.335 336      SymbolContextItem actual_resolve_scope = SymbolContextItem(0);337 338      if (resolve_scope & eSymbolContextCompUnit) {339        if (m_flags.IsClear(eSymbolContextCompUnit)) {340          if (m_sc.comp_unit)341            resolved |= eSymbolContextCompUnit;342          else343            actual_resolve_scope |= eSymbolContextCompUnit;344        }345      }346 347      if (resolve_scope & eSymbolContextFunction) {348        if (m_flags.IsClear(eSymbolContextFunction)) {349          if (m_sc.function)350            resolved |= eSymbolContextFunction;351          else352            actual_resolve_scope |= eSymbolContextFunction;353        }354      }355 356      if (resolve_scope & eSymbolContextBlock) {357        if (m_flags.IsClear(eSymbolContextBlock)) {358          if (m_sc.block)359            resolved |= eSymbolContextBlock;360          else361            actual_resolve_scope |= eSymbolContextBlock;362        }363      }364 365      if (resolve_scope & eSymbolContextSymbol) {366        if (m_flags.IsClear(eSymbolContextSymbol)) {367          if (m_sc.symbol)368            resolved |= eSymbolContextSymbol;369          else370            actual_resolve_scope |= eSymbolContextSymbol;371        }372      }373 374      if (resolve_scope & eSymbolContextLineEntry) {375        if (m_flags.IsClear(eSymbolContextLineEntry)) {376          if (m_sc.line_entry.IsValid())377            resolved |= eSymbolContextLineEntry;378          else379            actual_resolve_scope |= eSymbolContextLineEntry;380        }381      }382 383      if (actual_resolve_scope) {384        // We might be resolving less information than what is already in our385        // current symbol context so resolve into a temporary symbol context386        // "sc" so we don't clear out data we have already found in "m_sc"387        SymbolContext sc;388        // Set flags that indicate what we have tried to resolve389        resolved |= m_sc.module_sp->ResolveSymbolContextForAddress(390            lookup_addr, actual_resolve_scope, sc);391        // Only replace what we didn't already have as we may have information392        // for an inlined function scope that won't match what a standard393        // lookup by address would match394        if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == nullptr)395          m_sc.comp_unit = sc.comp_unit;396        if ((resolved & eSymbolContextFunction) && m_sc.function == nullptr)397          m_sc.function = sc.function;398        if ((resolved & eSymbolContextBlock) && m_sc.block == nullptr)399          m_sc.block = sc.block;400        if ((resolved & eSymbolContextSymbol) && m_sc.symbol == nullptr)401          m_sc.symbol = sc.symbol;402        if ((resolved & eSymbolContextLineEntry) &&403            !m_sc.line_entry.IsValid()) {404          m_sc.line_entry = sc.line_entry;405          m_sc.line_entry.ApplyFileMappings(m_sc.target_sp);406        }407      }408    } else {409      // If we don't have a module, then we can't have the compile unit,410      // function, block, line entry or symbol, so we can safely call411      // ResolveSymbolContextForAddress with our symbol context member m_sc.412      if (m_sc.target_sp) {413        resolved |= m_sc.target_sp->GetImages().ResolveSymbolContextForAddress(414            lookup_addr, resolve_scope, m_sc);415      }416    }417 418    // Update our internal flags so we remember what we have tried to locate so419    // we don't have to keep trying when more calls to this function are made.420    // We might have dug up more information that was requested (for example if421    // we were asked to only get the block, we will have gotten the compile422    // unit, and function) so set any additional bits that we resolved423    m_flags.Set(resolve_scope | resolved);424  }425 426  // Return the symbol context with everything that was possible to resolve427  // resolved.428  return m_sc;429}430 431VariableList *StackFrame::GetVariableList(bool get_file_globals,432                                          Status *error_ptr) {433  std::lock_guard<std::recursive_mutex> guard(m_mutex);434  if (m_flags.IsClear(RESOLVED_VARIABLES)) {435    m_flags.Set(RESOLVED_VARIABLES);436    m_variable_list_sp = std::make_shared<VariableList>();437 438    Block *frame_block = GetFrameBlock();439 440    if (frame_block) {441      const bool get_child_variables = true;442      const bool can_create = true;443      const bool stop_if_child_block_is_inlined_function = true;444      frame_block->AppendBlockVariables(445          can_create, get_child_variables,446          stop_if_child_block_is_inlined_function,447          [](Variable *v) { return true; }, m_variable_list_sp.get());448    }449  }450 451  if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) && get_file_globals) {452    m_flags.Set(RESOLVED_GLOBAL_VARIABLES);453 454    if (m_flags.IsClear(eSymbolContextCompUnit))455      GetSymbolContext(eSymbolContextCompUnit);456 457    if (m_sc.comp_unit) {458      VariableListSP global_variable_list_sp(459          m_sc.comp_unit->GetVariableList(true));460      if (m_variable_list_sp)461        m_variable_list_sp->AddVariables(global_variable_list_sp.get());462      else463        m_variable_list_sp = global_variable_list_sp;464    }465  }466 467  if (error_ptr && m_variable_list_sp->GetSize() == 0) {468    // Check with the symbol file to check if there is an error for why we469    // don't have variables that the user might need to know about.470    GetSymbolContext(eSymbolContextEverything);471    if (m_sc.module_sp) {472      SymbolFile *sym_file = m_sc.module_sp->GetSymbolFile();473      if (sym_file)474        *error_ptr = sym_file->GetFrameVariableError(*this);475    }476  }477 478  return m_variable_list_sp.get();479}480 481VariableListSP482StackFrame::GetInScopeVariableList(bool get_file_globals,483                                   bool must_have_valid_location) {484  std::lock_guard<std::recursive_mutex> guard(m_mutex);485  // We can't fetch variable information for a history stack frame.486  if (IsHistorical())487    return VariableListSP();488 489  VariableListSP var_list_sp(new VariableList);490  GetSymbolContext(eSymbolContextCompUnit | eSymbolContextBlock);491 492  if (m_sc.block) {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 ||500                                        v->LocationIsValidForFrame(this));501        },502        var_list_sp.get());503  }504 505  if (m_sc.comp_unit && get_file_globals) {506    VariableListSP global_variable_list_sp(507        m_sc.comp_unit->GetVariableList(true));508    if (global_variable_list_sp)509      var_list_sp->AddVariables(global_variable_list_sp.get());510  }511 512  return var_list_sp;513}514 515ValueObjectSP StackFrame::GetValueForVariableExpressionPath(516    llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,517    VariableSP &var_sp, Status &error) {518  ExecutionContext exe_ctx;519  CalculateExecutionContext(exe_ctx);520  bool use_DIL = exe_ctx.GetTargetRef().GetUseDIL(&exe_ctx);521  if (use_DIL)522    return DILGetValueForVariableExpressionPath(var_expr, use_dynamic, options,523                                                var_sp, error);524 525  return LegacyGetValueForVariableExpressionPath(var_expr, use_dynamic, options,526                                                 var_sp, error);527}528 529ValueObjectSP StackFrame::DILGetValueForVariableExpressionPath(530    llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,531    uint32_t options, lldb::VariableSP &var_sp, Status &error) {532 533  const bool check_ptr_vs_member =534      (options & eExpressionPathOptionCheckPtrVsMember) != 0;535  const bool no_fragile_ivar =536      (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;537  const bool no_synth_child =538      (options & eExpressionPathOptionsNoSyntheticChildren) != 0;539 540  // Lex the expression.541  auto lex_or_err = dil::DILLexer::Create(var_expr);542  if (!lex_or_err) {543    error = Status::FromError(lex_or_err.takeError());544    return ValueObjectConstResult::Create(nullptr, std::move(error));545  }546 547  // Parse the expression.548  auto tree_or_error = dil::DILParser::Parse(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) {552    error = Status::FromError(tree_or_error.takeError());553    return ValueObjectConstResult::Create(nullptr, std::move(error));554  }555 556  // Evaluate the parsed expression.557  lldb::TargetSP target = this->CalculateTarget();558  dil::Interpreter interpreter(target, var_expr, shared_from_this(),559                               use_dynamic, !no_synth_child, !no_fragile_ivar,560                               check_ptr_vs_member);561 562  auto valobj_or_error = interpreter.Evaluate((*tree_or_error).get());563  if (!valobj_or_error) {564    error = Status::FromError(valobj_or_error.takeError());565    return ValueObjectConstResult::Create(nullptr, std::move(error));566  }567 568  var_sp = (*valobj_or_error)->GetVariable();569  return *valobj_or_error;570}571 572ValueObjectSP StackFrame::LegacyGetValueForVariableExpressionPath(573    llvm::StringRef var_expr, DynamicValueType use_dynamic, uint32_t options,574    VariableSP &var_sp, Status &error) {575  llvm::StringRef original_var_expr = var_expr;576  // We can't fetch variable information for a history stack frame.577  if (IsHistorical())578    return ValueObjectSP();579 580  if (var_expr.empty()) {581    error = Status::FromErrorStringWithFormatv("invalid variable path '{0}'",582                                               var_expr);583    return ValueObjectSP();584  }585 586  const bool check_ptr_vs_member =587      (options & eExpressionPathOptionCheckPtrVsMember) != 0;588  const bool no_fragile_ivar =589      (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;590  const bool no_synth_child =591      (options & eExpressionPathOptionsNoSyntheticChildren) != 0;592  // const bool no_synth_array = (options &593  // eExpressionPathOptionsNoSyntheticArrayRange) != 0;594  error.Clear();595  bool deref = false;596  bool address_of = false;597  ValueObjectSP valobj_sp;598  const bool get_file_globals = true;599  // When looking up a variable for an expression, we need only consider the600  // variables that are in scope.601  VariableListSP var_list_sp(GetInScopeVariableList(get_file_globals));602  VariableList *variable_list = var_list_sp.get();603 604  if (!variable_list)605    return ValueObjectSP();606 607  // If first character is a '*', then show pointer contents608  std::string var_expr_storage;609  if (var_expr[0] == '*') {610    deref = true;611    var_expr = var_expr.drop_front(); // Skip the '*'612  } else if (var_expr[0] == '&') {613    address_of = true;614    var_expr = var_expr.drop_front(); // Skip the '&'615  }616 617  size_t separator_idx = var_expr.find_first_of(".-[=+~|&^%#@!/?,<>{}");618  StreamString var_expr_path_strm;619 620  ConstString name_const_string(var_expr.substr(0, separator_idx));621 622  var_sp = variable_list->FindVariable(name_const_string, false);623 624  bool synthetically_added_instance_object = false;625 626  if (var_sp) {627    var_expr = var_expr.drop_front(name_const_string.GetLength());628  }629 630  if (!var_sp && (options & eExpressionPathOptionsAllowDirectIVarAccess)) {631    // Check for direct ivars access which helps us with implicit access to632    // ivars using "this" or "self".633    GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock);634    llvm::StringRef instance_var_name = m_sc.GetInstanceVariableName();635    if (!instance_var_name.empty()) {636      var_sp = variable_list->FindVariable(ConstString(instance_var_name));637      if (var_sp) {638        separator_idx = 0;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 = ".";643 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;649      }650    }651  }652 653  if (!var_sp && (options & eExpressionPathOptionsInspectAnonymousUnions)) {654    // Check if any anonymous unions are there which contain a variable with655    // the name we need656    for (const VariableSP &variable_sp : *variable_list) {657      if (!variable_sp)658        continue;659      if (!variable_sp->GetName().IsEmpty())660        continue;661 662      Type *var_type = variable_sp->GetType();663      if (!var_type)664        continue;665 666      if (!var_type->GetForwardCompilerType().IsAnonymousType())667        continue;668      valobj_sp = GetValueObjectForFrameVariable(variable_sp, use_dynamic);669      if (!valobj_sp)670        return valobj_sp;671      valobj_sp = valobj_sp->GetChildMemberWithName(name_const_string);672      if (valobj_sp)673        break;674    }675  }676 677  if (var_sp && !valobj_sp) {678    valobj_sp = GetValueObjectForFrameVariable(var_sp, use_dynamic);679    if (!valobj_sp)680      return valobj_sp;681  }682  if (!valobj_sp) {683    error = Status::FromErrorStringWithFormatv(684        "no variable named '{0}' found in this frame", name_const_string);685    return ValueObjectSP();686  }687 688  // We are dumping at least one child689  while (!var_expr.empty()) {690    // Calculate the next separator index ahead of time691    ValueObjectSP child_valobj_sp;692    const char separator_type = var_expr[0];693    bool expr_is_ptr = false;694    switch (separator_type) {695    case '-':696      expr_is_ptr = true;697      if (var_expr.size() >= 2 && var_expr[1] != '>')698        return ValueObjectSP();699 700      if (no_fragile_ivar) {701        // Make sure we aren't trying to deref an objective702        // C ivar if this is not allowed703        const uint32_t pointer_type_flags =704            valobj_sp->GetCompilerType().GetTypeInfo(nullptr);705        if ((pointer_type_flags & eTypeIsObjC) &&706            (pointer_type_flags & eTypeIsPointer)) {707          // This was an objective C object pointer and it was requested we708          // skip any fragile ivars so return nothing here709          return ValueObjectSP();710        }711      }712 713      // If we have a non-pointer type with a synthetic value then lets check if714      // we have a synthetic dereference specified.715      if (!valobj_sp->IsPointerType() && valobj_sp->HasSyntheticValue()) {716        Status deref_error;717        if (ValueObjectSP synth_deref_sp =718                valobj_sp->GetSyntheticValue()->Dereference(deref_error);719            synth_deref_sp && deref_error.Success()) {720          valobj_sp = std::move(synth_deref_sp);721        }722        if (!valobj_sp || deref_error.Fail()) {723          error = Status::FromErrorStringWithFormatv(724              "Failed to dereference synthetic value: {0}", deref_error);725          return ValueObjectSP();726        }727 728        // Some synthetic plug-ins fail to set the error in Dereference729        if (!valobj_sp) {730          error =731              Status::FromErrorString("Failed to dereference synthetic value");732          return ValueObjectSP();733        }734        expr_is_ptr = false;735      }736 737      var_expr = var_expr.drop_front(); // Remove the '-'738      [[fallthrough]];739    case '.': {740      var_expr = var_expr.drop_front(); // Remove the '.' or '>'741      separator_idx = var_expr.find_first_of(".-[");742      ConstString child_name(var_expr.substr(0, var_expr.find_first_of(".-[")));743 744      if (check_ptr_vs_member) {745        // We either have a pointer type and need to verify valobj_sp is a746        // pointer, or we have a member of a class/union/struct being accessed747        // with the . syntax and need to verify we don't have a pointer.748        const bool actual_is_ptr = valobj_sp->IsPointerType();749 750        if (actual_is_ptr != expr_is_ptr) {751          // Incorrect use of "." with a pointer, or "->" with a752          // class/union/struct instance or reference.753          valobj_sp->GetExpressionPath(var_expr_path_strm);754          if (actual_is_ptr)755            error = Status::FromErrorStringWithFormat(756                "\"%s\" is a pointer and . was used to attempt to access "757                "\"%s\". Did you mean \"%s->%s\"?",758                var_expr_path_strm.GetData(), child_name.GetCString(),759                var_expr_path_strm.GetData(), var_expr.str().c_str());760          else761            error = Status::FromErrorStringWithFormat(762                "\"%s\" is not a pointer and -> was used to attempt to "763                "access \"%s\". Did you mean \"%s.%s\"?",764                var_expr_path_strm.GetData(), child_name.GetCString(),765                var_expr_path_strm.GetData(), var_expr.str().c_str());766          return ValueObjectSP();767        }768      }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();773          if (child_valobj_sp)774            child_valobj_sp =775                child_valobj_sp->GetChildMemberWithName(child_name);776        }777 778        if (no_synth_child || !child_valobj_sp) {779          // No child member with name "child_name"780          if (synthetically_added_instance_object) {781            // We added a "this->" or "self->" to the beginning of the782            // expression and this is the first pointer ivar access, so just783            // return the normal error784            error = Status::FromErrorStringWithFormat(785                "no variable or instance variable named '%s' found in "786                "this frame",787                name_const_string.GetCString());788          } else {789            valobj_sp->GetExpressionPath(var_expr_path_strm);790            if (child_name) {791              error = Status::FromErrorStringWithFormat(792                  "\"%s\" is not a member of \"(%s) %s\"",793                  child_name.GetCString(),794                  valobj_sp->GetTypeName().AsCString("<invalid type>"),795                  var_expr_path_strm.GetData());796            } else {797              error = Status::FromErrorStringWithFormat(798                  "incomplete expression path after \"%s\" in \"%s\"",799                  var_expr_path_strm.GetData(),800                  original_var_expr.str().c_str());801            }802          }803          return ValueObjectSP();804        }805      }806      synthetically_added_instance_object = false;807      // Remove the child name from the path808      var_expr = var_expr.drop_front(child_name.GetLength());809      if (use_dynamic != eNoDynamicValues) {810        ValueObjectSP dynamic_value_sp(811            child_valobj_sp->GetDynamicValue(use_dynamic));812        if (dynamic_value_sp)813          child_valobj_sp = dynamic_value_sp;814      }815    } break;816 817    case '[': {818      // Array member access, or treating pointer as an array Need at least two819      // brackets and a number820      if (var_expr.size() <= 2) {821        error = Status::FromErrorStringWithFormat(822            "invalid square bracket encountered after \"%s\" in \"%s\"",823            var_expr_path_strm.GetData(), var_expr.str().c_str());824        return ValueObjectSP();825      }826 827      // Drop the open brace.828      var_expr = var_expr.drop_front();829      long child_index = 0;830 831      // If there's no closing brace, this is an invalid expression.832      size_t end_pos = var_expr.find_first_of(']');833      if (end_pos == llvm::StringRef::npos) {834        error = Status::FromErrorStringWithFormat(835            "missing closing square bracket in expression \"%s\"",836            var_expr_path_strm.GetData());837        return ValueObjectSP();838      }839      llvm::StringRef index_expr = var_expr.take_front(end_pos);840      llvm::StringRef original_index_expr = index_expr;841      // Drop all of "[index_expr]"842      var_expr = var_expr.drop_front(end_pos + 1);843 844      if (index_expr.consumeInteger(0, child_index)) {845        // If there was no integer anywhere in the index expression, this is846        // erroneous expression.847        error = Status::FromErrorStringWithFormat(848            "invalid index expression \"%s\"", index_expr.str().c_str());849        return ValueObjectSP();850      }851 852      if (index_expr.empty()) {853        // The entire index expression was a single integer.854 855        if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {856          // what we have is *ptr[low]. the most similar C++ syntax is to deref857          // ptr and extract bit low out of it. reading array item low would be858          // done by saying ptr[low], without a deref * sign859          Status deref_error;860          ValueObjectSP temp(valobj_sp->Dereference(deref_error));861          if (!temp || deref_error.Fail()) {862            valobj_sp->GetExpressionPath(var_expr_path_strm);863            error = Status::FromErrorStringWithFormat(864                "could not dereference \"(%s) %s\"",865                valobj_sp->GetTypeName().AsCString("<invalid type>"),866                var_expr_path_strm.GetData());867            return ValueObjectSP();868          }869          valobj_sp = temp;870          deref = false;871        } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() &&872                   deref) {873          // what we have is *arr[low]. the most similar C++ syntax is to get874          // arr[0] (an operation that is equivalent to deref-ing arr) and875          // extract bit low out of it. reading array item low would be done by876          // saying arr[low], without a deref * sign877          ValueObjectSP temp(valobj_sp->GetChildAtIndex(0));878          if (!temp) {879            valobj_sp->GetExpressionPath(var_expr_path_strm);880            error = Status::FromErrorStringWithFormat(881                "could not get item 0 for \"(%s) %s\"",882                valobj_sp->GetTypeName().AsCString("<invalid type>"),883                var_expr_path_strm.GetData());884            return ValueObjectSP();885          }886          valobj_sp = temp;887          deref = false;888        }889 890        bool is_incomplete_array = false;891        if (valobj_sp->IsPointerType()) {892          bool is_objc_pointer = true;893 894          if (valobj_sp->GetCompilerType().GetMinimumLanguage() !=895              eLanguageTypeObjC)896            is_objc_pointer = false;897          else if (!valobj_sp->GetCompilerType().IsPointerType())898            is_objc_pointer = false;899 900          if (no_synth_child && is_objc_pointer) {901            error = Status::FromErrorStringWithFormat(902                "\"(%s) %s\" is an Objective-C pointer, and cannot be "903                "subscripted",904                valobj_sp->GetTypeName().AsCString("<invalid type>"),905                var_expr_path_strm.GetData());906 907            return ValueObjectSP();908          } else if (is_objc_pointer) {909            // dereferencing ObjC variables is not valid.. so let's try and910            // recur to synthetic children911            ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();912            if (!synthetic                 /* no synthetic */913                || synthetic == valobj_sp) /* synthetic is the same as914                                              the original object */915            {916              valobj_sp->GetExpressionPath(var_expr_path_strm);917              error = Status::FromErrorStringWithFormat(918                  "\"(%s) %s\" is not an array type",919                  valobj_sp->GetTypeName().AsCString("<invalid type>"),920                  var_expr_path_strm.GetData());921            } else if (static_cast<uint32_t>(child_index) >=922                       synthetic923                           ->GetNumChildrenIgnoringErrors() /* synthetic does924                                                                not have that925                                                                many values */) {926              valobj_sp->GetExpressionPath(var_expr_path_strm);927              error = Status::FromErrorStringWithFormat(928                  "array index %ld is not valid for \"(%s) %s\"", child_index,929                  valobj_sp->GetTypeName().AsCString("<invalid type>"),930                  var_expr_path_strm.GetData());931            } else {932              child_valobj_sp = synthetic->GetChildAtIndex(child_index);933              if (!child_valobj_sp) {934                valobj_sp->GetExpressionPath(var_expr_path_strm);935                error = Status::FromErrorStringWithFormat(936                    "array index %ld is not valid for \"(%s) %s\"", child_index,937                    valobj_sp->GetTypeName().AsCString("<invalid type>"),938                    var_expr_path_strm.GetData());939              }940            }941          } else {942            child_valobj_sp =943                valobj_sp->GetSyntheticArrayMember(child_index, true);944            if (!child_valobj_sp) {945              valobj_sp->GetExpressionPath(var_expr_path_strm);946              error = Status::FromErrorStringWithFormat(947                  "failed to use pointer as array for index %ld for "948                  "\"(%s) %s\"",949                  child_index,950                  valobj_sp->GetTypeName().AsCString("<invalid type>"),951                  var_expr_path_strm.GetData());952            }953          }954        } else if (valobj_sp->GetCompilerType().IsArrayType(955                       nullptr, nullptr, &is_incomplete_array)) {956          // Pass false to dynamic_value here so we can tell the difference957          // between no dynamic value and no member of this type...958          child_valobj_sp = valobj_sp->GetChildAtIndex(child_index);959          if (!child_valobj_sp && (is_incomplete_array || !no_synth_child))960            child_valobj_sp =961                valobj_sp->GetSyntheticArrayMember(child_index, true);962 963          if (!child_valobj_sp) {964            valobj_sp->GetExpressionPath(var_expr_path_strm);965            error = Status::FromErrorStringWithFormat(966                "array index %ld is not valid for \"(%s) %s\"", child_index,967                valobj_sp->GetTypeName().AsCString("<invalid type>"),968                var_expr_path_strm.GetData());969          }970        } else if (valobj_sp->GetCompilerType().IsScalarType()) {971          // this is a bitfield asking to display just one bit972          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);976            error = Status::FromErrorStringWithFormat(977                "bitfield range %ld-%ld is not valid for \"(%s) %s\"",978                child_index, child_index,979                valobj_sp->GetTypeName().AsCString("<invalid type>"),980                var_expr_path_strm.GetData());981          }982        } else {983          ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();984          if (no_synth_child /* synthetic is forbidden */ ||985              !synthetic                 /* no synthetic */986              || synthetic == valobj_sp) /* synthetic is the same as the987                                            original object */988          {989            valobj_sp->GetExpressionPath(var_expr_path_strm);990            error = Status::FromErrorStringWithFormat(991                "\"(%s) %s\" is not an array type",992                valobj_sp->GetTypeName().AsCString("<invalid type>"),993                var_expr_path_strm.GetData());994          } else if (static_cast<uint32_t>(child_index) >=995                     synthetic->GetNumChildrenIgnoringErrors() /* synthetic996                                     does not have that many values */) {997            valobj_sp->GetExpressionPath(var_expr_path_strm);998            error = Status::FromErrorStringWithFormat(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());1002          } else {1003            child_valobj_sp = synthetic->GetChildAtIndex(child_index);1004            if (!child_valobj_sp) {1005              valobj_sp->GetExpressionPath(var_expr_path_strm);1006              error = Status::FromErrorStringWithFormat(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());1010            }1011          }1012        }1013 1014        if (!child_valobj_sp) {1015          // Invalid array index...1016          return ValueObjectSP();1017        }1018 1019        if (use_dynamic != eNoDynamicValues) {1020          ValueObjectSP dynamic_value_sp(1021              child_valobj_sp->GetDynamicValue(use_dynamic));1022          if (dynamic_value_sp)1023            child_valobj_sp = dynamic_value_sp;1024        }1025        // Break out early from the switch since we were able to find the child1026        // member1027        break;1028      }1029 1030      // this is most probably a BitField, let's take a look1031      if (index_expr.front() != '-') {1032        error = Status::FromErrorStringWithFormat(1033            "invalid range expression \"'%s'\"",1034            original_index_expr.str().c_str());1035        return ValueObjectSP();1036      }1037 1038      index_expr = index_expr.drop_front();1039      long final_index = 0;1040      if (index_expr.getAsInteger(0, final_index)) {1041        error = Status::FromErrorStringWithFormat(1042            "invalid range expression \"'%s'\"",1043            original_index_expr.str().c_str());1044        return ValueObjectSP();1045      }1046 1047      // if the format given is [high-low], swap range1048      if (child_index > final_index) {1049        long temp = child_index;1050        child_index = final_index;1051        final_index = temp;1052      }1053 1054      if (valobj_sp->GetCompilerType().IsPointerToScalarType() && deref) {1055        // what we have is *ptr[low-high]. the most similar C++ syntax is to1056        // deref ptr and extract bits low thru high out of it. reading array1057        // items low thru high would be done by saying ptr[low-high], without a1058        // deref * sign1059        Status deref_error;1060        ValueObjectSP temp(valobj_sp->Dereference(deref_error));1061        if (!temp || deref_error.Fail()) {1062          valobj_sp->GetExpressionPath(var_expr_path_strm);1063          error = Status::FromErrorStringWithFormat(1064              "could not dereference \"(%s) %s\"",1065              valobj_sp->GetTypeName().AsCString("<invalid type>"),1066              var_expr_path_strm.GetData());1067          return ValueObjectSP();1068        }1069        valobj_sp = temp;1070        deref = false;1071      } else if (valobj_sp->GetCompilerType().IsArrayOfScalarType() && deref) {1072        // what we have is *arr[low-high]. the most similar C++ syntax is to1073        // get arr[0] (an operation that is equivalent to deref-ing arr) and1074        // extract bits low thru high out of it. reading array items low thru1075        // high would be done by saying arr[low-high], without a deref * sign1076        ValueObjectSP temp(valobj_sp->GetChildAtIndex(0));1077        if (!temp) {1078          valobj_sp->GetExpressionPath(var_expr_path_strm);1079          error = Status::FromErrorStringWithFormat(1080              "could not get item 0 for \"(%s) %s\"",1081              valobj_sp->GetTypeName().AsCString("<invalid type>"),1082              var_expr_path_strm.GetData());1083          return ValueObjectSP();1084        }1085        valobj_sp = temp;1086        deref = false;1087      }1088 1089      child_valobj_sp =1090          valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true);1091      if (!child_valobj_sp) {1092        valobj_sp->GetExpressionPath(var_expr_path_strm);1093        error = Status::FromErrorStringWithFormat(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());1097      }1098 1099      if (!child_valobj_sp) {1100        // Invalid bitfield range...1101        return ValueObjectSP();1102      }1103 1104      if (use_dynamic != eNoDynamicValues) {1105        ValueObjectSP dynamic_value_sp(1106            child_valobj_sp->GetDynamicValue(use_dynamic));1107        if (dynamic_value_sp)1108          child_valobj_sp = dynamic_value_sp;1109      }1110      // Break out early from the switch since we were able to find the child1111      // member1112      break;1113    }1114    default:1115      // Failure...1116      {1117        valobj_sp->GetExpressionPath(var_expr_path_strm);1118        error = Status::FromErrorStringWithFormat(1119            "unexpected char '%c' encountered after \"%s\" in \"%s\"",1120            separator_type, var_expr_path_strm.GetData(),1121            var_expr.str().c_str());1122 1123        return ValueObjectSP();1124      }1125    }1126 1127    if (child_valobj_sp)1128      valobj_sp = child_valobj_sp;1129  }1130  if (valobj_sp) {1131    if (deref) {1132      ValueObjectSP deref_valobj_sp(valobj_sp->Dereference(error));1133      if (!deref_valobj_sp && !no_synth_child) {1134        if (ValueObjectSP synth_obj_sp = valobj_sp->GetSyntheticValue()) {1135          error.Clear();1136          deref_valobj_sp = synth_obj_sp->Dereference(error);1137        }1138      }1139      valobj_sp = deref_valobj_sp;1140    } else if (address_of) {1141      ValueObjectSP address_of_valobj_sp(valobj_sp->AddressOf(error));1142      valobj_sp = address_of_valobj_sp;1143    }1144  }1145  return valobj_sp;1146}1147 1148llvm::Error StackFrame::GetFrameBaseValue(Scalar &frame_base) {1149  std::lock_guard<std::recursive_mutex> guard(m_mutex);1150  if (!m_cfa_is_valid) {1151    m_frame_base_error = Status::FromErrorString(1152        "No frame base available for this historical stack frame.");1153    return m_frame_base_error.ToError();1154  }1155 1156  if (m_flags.IsClear(GOT_FRAME_BASE)) {1157    if (m_sc.function) {1158      m_frame_base.Clear();1159      m_frame_base_error.Clear();1160 1161      m_flags.Set(GOT_FRAME_BASE);1162      ExecutionContext exe_ctx(shared_from_this());1163      addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;1164      if (!m_sc.function->GetFrameBaseExpression().IsAlwaysValidSingleExpr())1165        loclist_base_addr =1166            m_sc.function->GetAddress().GetLoadAddress(exe_ctx.GetTargetPtr());1167 1168      llvm::Expected<Value> expr_value =1169          m_sc.function->GetFrameBaseExpression().Evaluate(1170              &exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr);1171      if (!expr_value)1172        m_frame_base_error = Status::FromError(expr_value.takeError());1173      else1174        m_frame_base = expr_value->ResolveValue(&exe_ctx);1175    } else {1176      m_frame_base_error =1177          Status::FromErrorString("No function in symbol context.");1178    }1179  }1180 1181  if (m_frame_base_error.Fail())1182    return m_frame_base_error.ToError();1183 1184  frame_base = m_frame_base;1185  return llvm::Error::success();1186}1187 1188DWARFExpressionList *StackFrame::GetFrameBaseExpression(Status *error_ptr) {1189  if (!m_sc.function) {1190    if (error_ptr) {1191      *error_ptr = Status::FromErrorString("No function in symbol context.");1192    }1193    return nullptr;1194  }1195 1196  return &m_sc.function->GetFrameBaseExpression();1197}1198 1199RegisterContextSP StackFrame::GetRegisterContext() {1200  std::lock_guard<std::recursive_mutex> guard(m_mutex);1201  if (!m_reg_context_sp) {1202    ThreadSP thread_sp(GetThread());1203    if (thread_sp)1204      m_reg_context_sp = thread_sp->CreateRegisterContextForFrame(this);1205  }1206  return m_reg_context_sp;1207}1208 1209bool StackFrame::HasDebugInformation() {1210  GetSymbolContext(eSymbolContextLineEntry);1211  return m_sc.line_entry.IsValid();1212}1213 1214ValueObjectSP1215StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,1216                                           DynamicValueType use_dynamic) {1217  ValueObjectSP valobj_sp;1218  { // Scope for stack frame mutex.  We need to drop this mutex before we figure1219    // out the dynamic value.  That will require converting the StackID in the1220    // VO back to a StackFrame, which will in turn require locking the1221    // StackFrameList.  If we still hold the StackFrame mutex, we could suffer1222    // lock inversion against the pattern of getting the StackFrameList and1223    // then the stack frame, which is fairly common.1224    std::lock_guard<std::recursive_mutex> guard(m_mutex);1225    if (IsHistorical()) {1226      return valobj_sp;1227    }1228    VariableList *var_list = GetVariableList(true, nullptr);1229    if (var_list) {1230      // Make sure the variable is a frame variable1231      const uint32_t var_idx =1232          var_list->FindIndexForVariable(variable_sp.get());1233      const uint32_t num_variables = var_list->GetSize();1234      if (var_idx < num_variables) {1235        valobj_sp =1236            m_variable_list_value_objects.GetValueObjectAtIndex(var_idx);1237        if (!valobj_sp) {1238          if (m_variable_list_value_objects.GetSize() < num_variables)1239            m_variable_list_value_objects.Resize(num_variables);1240          valobj_sp = ValueObjectVariable::Create(this, variable_sp);1241          m_variable_list_value_objects.SetValueObjectAtIndex(var_idx,1242                                                              valobj_sp);1243        }1244      }1245    }1246  } // End of StackFrame mutex scope.1247  if (use_dynamic != eNoDynamicValues && valobj_sp) {1248    ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue(use_dynamic);1249    if (dynamic_sp)1250      return dynamic_sp;1251  }1252  return valobj_sp;1253}1254 1255bool StackFrame::IsInlined() {1256  if (m_sc.block == nullptr)1257    GetSymbolContext(eSymbolContextBlock);1258  if (m_sc.block)1259    return m_sc.block->GetContainingInlinedBlock() != nullptr;1260  return false;1261}1262 1263bool StackFrame::IsHistorical() const {1264  return m_stack_frame_kind == StackFrame::Kind::History;1265}1266 1267bool StackFrame::IsSynthetic() const {1268  return m_stack_frame_kind == StackFrame::Kind::Synthetic;1269}1270 1271bool StackFrame::IsArtificial() const { return m_artificial; }1272 1273bool StackFrame::IsHidden() {1274  if (auto recognized_frame_sp = GetRecognizedFrame())1275    return recognized_frame_sp->ShouldHide();1276  return false;1277}1278 1279StructuredData::ObjectSP StackFrame::GetLanguageSpecificData() {1280  auto process_sp = CalculateProcess();1281  SourceLanguage language = GetLanguage();1282  if (!language)1283    return {};1284  if (auto runtime_sp =1285          process_sp->GetLanguageRuntime(language.AsLanguageType()))1286    return runtime_sp->GetLanguageSpecificData(1287        GetSymbolContext(eSymbolContextFunction));1288  return {};1289}1290 1291const char *StackFrame::GetFunctionName() {1292  const char *name = nullptr;1293  SymbolContext sc = GetSymbolContext(1294      eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol);1295  if (sc.block) {1296    Block *inlined_block = sc.block->GetContainingInlinedBlock();1297    if (inlined_block) {1298      const InlineFunctionInfo *inlined_info =1299          inlined_block->GetInlinedFunctionInfo();1300      if (inlined_info)1301        name = inlined_info->GetName().AsCString();1302    }1303  }1304 1305  if (name == nullptr) {1306    if (sc.function)1307      name = sc.function->GetName().GetCString();1308  }1309 1310  if (name == nullptr) {1311    if (sc.symbol)1312      name = sc.symbol->GetName().GetCString();1313  }1314 1315  return name;1316}1317 1318const char *StackFrame::GetDisplayFunctionName() {1319  const char *name = nullptr;1320  SymbolContext sc = GetSymbolContext(1321      eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol);1322  if (sc.block) {1323    Block *inlined_block = sc.block->GetContainingInlinedBlock();1324    if (inlined_block) {1325      const InlineFunctionInfo *inlined_info =1326          inlined_block->GetInlinedFunctionInfo();1327      if (inlined_info)1328        name = inlined_info->GetDisplayName().AsCString();1329    }1330  }1331 1332  if (name == nullptr) {1333    if (sc.function)1334      name = sc.function->GetDisplayName().GetCString();1335  }1336 1337  if (name == nullptr) {1338    if (sc.symbol)1339      name = sc.symbol->GetDisplayName().GetCString();1340  }1341  return name;1342}1343 1344SourceLanguage StackFrame::GetLanguage() {1345  CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit;1346  if (cu)1347    return SourceLanguage{cu->GetLanguage()};1348  return {};1349}1350 1351SourceLanguage StackFrame::GuessLanguage() {1352  SourceLanguage lang_type = GetLanguage();1353 1354  if (!lang_type) {1355    SymbolContext sc =1356        GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol);1357    if (sc.function)1358      lang_type = SourceLanguage(sc.function->GetMangled().GuessLanguage());1359    else if (sc.symbol)1360      lang_type = SourceLanguage(sc.symbol->GetMangled().GuessLanguage());1361  }1362 1363  return lang_type;1364}1365 1366namespace {1367std::pair<const Instruction::Operand *, int64_t>1368GetBaseExplainingValue(const Instruction::Operand &operand,1369                       RegisterContext &register_context, lldb::addr_t value) {1370  switch (operand.m_type) {1371  case Instruction::Operand::Type::Dereference:1372  case Instruction::Operand::Type::Immediate:1373  case Instruction::Operand::Type::Invalid:1374  case Instruction::Operand::Type::Product:1375    // These are not currently interesting1376    return std::make_pair(nullptr, 0);1377  case Instruction::Operand::Type::Sum: {1378    const Instruction::Operand *immediate_child = nullptr;1379    const Instruction::Operand *variable_child = nullptr;1380    if (operand.m_children[0].m_type == Instruction::Operand::Type::Immediate) {1381      immediate_child = &operand.m_children[0];1382      variable_child = &operand.m_children[1];1383    } else if (operand.m_children[1].m_type ==1384               Instruction::Operand::Type::Immediate) {1385      immediate_child = &operand.m_children[1];1386      variable_child = &operand.m_children[0];1387    }1388    if (!immediate_child) {1389      return std::make_pair(nullptr, 0);1390    }1391    lldb::addr_t adjusted_value = value;1392    if (immediate_child->m_negative) {1393      adjusted_value += immediate_child->m_immediate;1394    } else {1395      adjusted_value -= immediate_child->m_immediate;1396    }1397    std::pair<const Instruction::Operand *, int64_t> base_and_offset =1398        GetBaseExplainingValue(*variable_child, register_context,1399                               adjusted_value);1400    if (!base_and_offset.first) {1401      return std::make_pair(nullptr, 0);1402    }1403    if (immediate_child->m_negative) {1404      base_and_offset.second -= immediate_child->m_immediate;1405    } else {1406      base_and_offset.second += immediate_child->m_immediate;1407    }1408    return base_and_offset;1409  }1410  case Instruction::Operand::Type::Register: {1411    const RegisterInfo *info =1412        register_context.GetRegisterInfoByName(operand.m_register.AsCString());1413    if (!info) {1414      return std::make_pair(nullptr, 0);1415    }1416    RegisterValue reg_value;1417    if (!register_context.ReadRegister(info, reg_value)) {1418      return std::make_pair(nullptr, 0);1419    }1420    if (reg_value.GetAsUInt64() == value) {1421      return std::make_pair(&operand, 0);1422    } else {1423      return std::make_pair(nullptr, 0);1424    }1425  }1426  }1427  return std::make_pair(nullptr, 0);1428}1429 1430std::pair<const Instruction::Operand *, int64_t>1431GetBaseExplainingDereference(const Instruction::Operand &operand,1432                             RegisterContext &register_context,1433                             lldb::addr_t addr) {1434  if (operand.m_type == Instruction::Operand::Type::Dereference) {1435    return GetBaseExplainingValue(operand.m_children[0], register_context,1436                                  addr);1437  }1438  return std::make_pair(nullptr, 0);1439}1440} // namespace1441 1442lldb::ValueObjectSP StackFrame::GuessValueForAddress(lldb::addr_t addr) {1443  TargetSP target_sp = CalculateTarget();1444 1445  const ArchSpec &target_arch = target_sp->GetArchitecture();1446 1447  AddressRange pc_range;1448  pc_range.GetBaseAddress() = GetFrameCodeAddress();1449  pc_range.SetByteSize(target_arch.GetMaximumOpcodeByteSize());1450 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;1456 1457  DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(1458      target_arch, plugin_name, flavor, cpu, features, *target_sp, pc_range,1459      force_live_memory);1460 1461  if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {1462    return ValueObjectSP();1463  }1464 1465  InstructionSP instruction_sp =1466      disassembler_sp->GetInstructionList().GetInstructionAtIndex(0);1467 1468  llvm::SmallVector<Instruction::Operand, 3> operands;1469 1470  if (!instruction_sp->ParseOperands(operands)) {1471    return ValueObjectSP();1472  }1473 1474  RegisterContextSP register_context_sp = GetRegisterContext();1475 1476  if (!register_context_sp) {1477    return ValueObjectSP();1478  }1479 1480  for (const Instruction::Operand &operand : operands) {1481    std::pair<const Instruction::Operand *, int64_t> base_and_offset =1482        GetBaseExplainingDereference(operand, *register_context_sp, addr);1483 1484    if (!base_and_offset.first) {1485      continue;1486    }1487 1488    switch (base_and_offset.first->m_type) {1489    case Instruction::Operand::Type::Immediate: {1490      lldb_private::Address addr;1491      if (target_sp->ResolveLoadAddress(base_and_offset.first->m_immediate +1492                                            base_and_offset.second,1493                                        addr)) {1494        auto c_type_system_or_err =1495            target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC);1496        if (auto err = c_type_system_or_err.takeError()) {1497          LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(err),1498                         "Unable to guess value for given address: {0}");1499          return ValueObjectSP();1500        } else {1501          auto ts = *c_type_system_or_err;1502          if (!ts)1503            return {};1504          CompilerType void_ptr_type =1505              ts->GetBasicTypeFromAST(lldb::BasicType::eBasicTypeChar)1506                  .GetPointerType();1507          return ValueObjectMemory::Create(this, "", addr, void_ptr_type);1508        }1509      } else {1510        return ValueObjectSP();1511      }1512      break;1513    }1514    case Instruction::Operand::Type::Register: {1515      return GuessValueForRegisterAndOffset(base_and_offset.first->m_register,1516                                            base_and_offset.second);1517    }1518    default:1519      return ValueObjectSP();1520    }1521  }1522 1523  return ValueObjectSP();1524}1525 1526namespace {1527ValueObjectSP GetValueForOffset(StackFrame &frame, ValueObjectSP &parent,1528                                int64_t offset) {1529  if (offset < 0 ||1530      uint64_t(offset) >=1531          llvm::expectedToOptional(parent->GetByteSize()).value_or(0)) {1532    return ValueObjectSP();1533  }1534 1535  if (parent->IsPointerOrReferenceType()) {1536    return parent;1537  }1538 1539  for (int ci = 0, ce = parent->GetNumChildrenIgnoringErrors(); ci != ce;1540       ++ci) {1541    ValueObjectSP child_sp = parent->GetChildAtIndex(ci);1542 1543    if (!child_sp) {1544      return ValueObjectSP();1545    }1546 1547    int64_t child_offset = child_sp->GetByteOffset();1548    int64_t child_size =1549        llvm::expectedToOptional(child_sp->GetByteSize()).value_or(0);1550 1551    if (offset >= child_offset && offset < (child_offset + child_size)) {1552      return GetValueForOffset(frame, child_sp, offset - child_offset);1553    }1554  }1555 1556  if (offset == 0) {1557    return parent;1558  } else {1559    return ValueObjectSP();1560  }1561}1562 1563ValueObjectSP GetValueForDereferincingOffset(StackFrame &frame,1564                                             ValueObjectSP &base,1565                                             int64_t offset) {1566  // base is a pointer to something1567  // offset is the thing to add to the pointer We return the most sensible1568  // ValueObject for the result of *(base+offset)1569 1570  if (!base->IsPointerOrReferenceType()) {1571    return ValueObjectSP();1572  }1573 1574  Status error;1575  ValueObjectSP pointee = base->Dereference(error);1576 1577  if (!pointee) {1578    return ValueObjectSP();1579  }1580 1581  if (offset >= 0 &&1582      uint64_t(offset) >=1583          llvm::expectedToOptional(pointee->GetByteSize()).value_or(0)) {1584    uint64_t size =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);1590  }1591 1592  if (!pointee || error.Fail()) {1593    return ValueObjectSP();1594  }1595 1596  return GetValueForOffset(frame, pointee, offset);1597}1598 1599/// Attempt to reconstruct the ValueObject for the address contained in a1600/// given register plus an offset.1601///1602/// \param [in] frame1603///   The current stack frame.1604///1605/// \param [in] reg1606///   The register.1607///1608/// \param [in] offset1609///   The offset from the register.1610///1611/// \param [in] disassembler1612///   A disassembler containing instructions valid up to the current PC.1613///1614/// \param [in] variables1615///   The variable list from the current frame,1616///1617/// \param [in] pc1618///   The program counter for the instruction considered the 'user'.1619///1620/// \return1621///   A string describing the base for the ExpressionPath.  This could be a1622///     variable, a register value, an argument, or a function return value.1623///   The ValueObject if found.  If valid, it has a valid ExpressionPath.1624lldb::ValueObjectSP DoGuessValueAt(StackFrame &frame, ConstString reg,1625                                   int64_t offset, Disassembler &disassembler,1626                                   VariableList &variables, const Address &pc) {1627  // Example of operation for Intel:1628  //1629  // +14: movq   -0x8(%rbp), %rdi1630  // +18: movq   0x8(%rdi), %rdi1631  // +22: addl   0x4(%rdi), %eax1632  //1633  // f, a pointer to a struct, is known to be at -0x8(%rbp).1634  //1635  // DoGuessValueAt(frame, rdi, 4, dis, vars, 0x22) finds the instruction at1636  // +18 that assigns to rdi, and calls itself recursively for that dereference1637  //   DoGuessValueAt(frame, rdi, 8, dis, vars, 0x18) finds the instruction at1638  //   +14 that assigns to rdi, and calls itself recursively for that1639  //   dereference1640  //     DoGuessValueAt(frame, rbp, -8, dis, vars, 0x14) finds "f" in the1641  //     variable list.1642  //     Returns a ValueObject for f.  (That's what was stored at rbp-8 at +14)1643  //   Returns a ValueObject for *(f+8) or f->b (That's what was stored at rdi+81644  //   at +18)1645  // Returns a ValueObject for *(f->b+4) or f->b->a (That's what was stored at1646  // rdi+4 at +22)1647 1648  // First, check the variable list to see if anything is at the specified1649  // location.1650 1651  using namespace OperandMatchers;1652 1653  const RegisterInfo *reg_info =1654      frame.GetRegisterContext()->GetRegisterInfoByName(reg.AsCString());1655  if (!reg_info) {1656    return ValueObjectSP();1657  }1658 1659  Instruction::Operand op =1660      offset ? Instruction::Operand::BuildDereference(1661                   Instruction::Operand::BuildSum(1662                       Instruction::Operand::BuildRegister(reg),1663                       Instruction::Operand::BuildImmediate(offset)))1664             : Instruction::Operand::BuildDereference(1665                   Instruction::Operand::BuildRegister(reg));1666 1667  for (VariableSP var_sp : variables) {1668    if (var_sp->LocationExpressionList().MatchesOperand(frame, op))1669      return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);1670  }1671 1672  const uint32_t current_inst =1673      disassembler.GetInstructionList().GetIndexOfInstructionAtAddress(pc);1674  if (current_inst == UINT32_MAX) {1675    return ValueObjectSP();1676  }1677 1678  for (uint32_t ii = current_inst - 1; ii != (uint32_t)-1; --ii) {1679    // This is not an exact algorithm, and it sacrifices accuracy for1680    // generality.  Recognizing "mov" and "ld" instructions –– and which1681    // are their source and destination operands -- is something the1682    // disassembler should do for us.1683    InstructionSP instruction_sp =1684        disassembler.GetInstructionList().GetInstructionAtIndex(ii);1685 1686    if (instruction_sp->IsCall()) {1687      ABISP abi_sp = frame.CalculateProcess()->GetABI();1688      if (!abi_sp) {1689        continue;1690      }1691 1692      const char *return_register_name;1693      if (!abi_sp->GetPointerReturnRegister(return_register_name)) {1694        continue;1695      }1696 1697      const RegisterInfo *return_register_info =1698          frame.GetRegisterContext()->GetRegisterInfoByName(1699              return_register_name);1700      if (!return_register_info) {1701        continue;1702      }1703 1704      int64_t offset = 0;1705 1706      if (!MatchUnaryOp(MatchOpType(Instruction::Operand::Type::Dereference),1707                        MatchRegOp(*return_register_info))(op) &&1708          !MatchUnaryOp(1709              MatchOpType(Instruction::Operand::Type::Dereference),1710              MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum),1711                            MatchRegOp(*return_register_info),1712                            FetchImmOp(offset)))(op)) {1713        continue;1714      }1715 1716      llvm::SmallVector<Instruction::Operand, 1> operands;1717      if (!instruction_sp->ParseOperands(operands) || operands.size() != 1) {1718        continue;1719      }1720 1721      switch (operands[0].m_type) {1722      default:1723        break;1724      case Instruction::Operand::Type::Immediate: {1725        SymbolContext sc;1726        if (!pc.GetModule())1727          break;1728        Address address(operands[0].m_immediate,1729                        pc.GetModule()->GetSectionList());1730        if (!address.IsValid())1731          break;1732        frame.CalculateTarget()->GetImages().ResolveSymbolContextForAddress(1733            address, eSymbolContextFunction, sc);1734        if (!sc.function) {1735          break;1736        }1737        CompilerType function_type = sc.function->GetCompilerType();1738        if (!function_type.IsFunctionType()) {1739          break;1740        }1741        CompilerType return_type = function_type.GetFunctionReturnType();1742        RegisterValue return_value;1743        if (!frame.GetRegisterContext()->ReadRegister(return_register_info,1744                                                      return_value)) {1745          break;1746        }1747        std::string name_str(1748            sc.function->GetName().AsCString("<unknown function>"));1749        name_str.append("()");1750        Address return_value_address(return_value.GetAsUInt64());1751        ValueObjectSP return_value_sp = ValueObjectMemory::Create(1752            &frame, name_str, return_value_address, return_type);1753        return GetValueForDereferincingOffset(frame, return_value_sp, offset);1754      }1755      }1756 1757      continue;1758    }1759 1760    llvm::SmallVector<Instruction::Operand, 2> operands;1761    if (!instruction_sp->ParseOperands(operands) || operands.size() != 2) {1762      continue;1763    }1764 1765    Instruction::Operand *origin_operand = nullptr;1766    auto clobbered_reg_matcher = [reg_info](const Instruction::Operand &op) {1767      return MatchRegOp(*reg_info)(op) && op.m_clobbered;1768    };1769 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];1774    } else {1775      continue;1776    }1777 1778    // We have an origin operand.  Can we track its value down?1779    ValueObjectSP source_path;1780    ConstString origin_register;1781    int64_t origin_offset = 0;1782 1783    if (FetchRegOp(origin_register)(*origin_operand)) {1784      source_path = DoGuessValueAt(frame, origin_register, 0, disassembler,1785                                   variables, instruction_sp->GetAddress());1786    } else if (MatchUnaryOp(1787                   MatchOpType(Instruction::Operand::Type::Dereference),1788                   FetchRegOp(origin_register))(*origin_operand) ||1789               MatchUnaryOp(1790                   MatchOpType(Instruction::Operand::Type::Dereference),1791                   MatchBinaryOp(MatchOpType(Instruction::Operand::Type::Sum),1792                                 FetchRegOp(origin_register),1793                                 FetchImmOp(origin_offset)))(*origin_operand)) {1794      source_path =1795          DoGuessValueAt(frame, origin_register, origin_offset, disassembler,1796                         variables, instruction_sp->GetAddress());1797      if (!source_path) {1798        continue;1799      }1800      source_path = GetValueForDereferincingOffset(frame, source_path, offset);1801    }1802 1803    if (source_path) {1804      return source_path;1805    }1806  }1807 1808  return ValueObjectSP();1809}1810} // namespace1811 1812lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,1813                                                               int64_t offset) {1814  TargetSP target_sp = CalculateTarget();1815 1816  const ArchSpec &target_arch = target_sp->GetArchitecture();1817 1818  Block *frame_block = GetFrameBlock();1819 1820  if (!frame_block) {1821    return ValueObjectSP();1822  }1823 1824  Function *function = frame_block->CalculateSymbolContextFunction();1825  if (!function) {1826    return ValueObjectSP();1827  }1828 1829  AddressRange unused_range;1830  if (!function->GetRangeContainingLoadAddress(1831          GetFrameCodeAddress().GetLoadAddress(target_sp.get()), *target_sp,1832          unused_range))1833    return ValueObjectSP();1834 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;1840  DisassemblerSP disassembler_sp = Disassembler::DisassembleRange(1841      target_arch, plugin_name, flavor, cpu, features, *target_sp,1842      function->GetAddressRanges(), force_live_memory);1843 1844  if (!disassembler_sp || !disassembler_sp->GetInstructionList().GetSize()) {1845    return ValueObjectSP();1846  }1847 1848  const bool get_file_globals = false;1849  VariableList *variables = GetVariableList(get_file_globals, nullptr);1850 1851  if (!variables) {1852    return ValueObjectSP();1853  }1854 1855  return DoGuessValueAt(*this, reg, offset, *disassembler_sp, *variables,1856                        GetFrameCodeAddress());1857}1858 1859lldb::ValueObjectSP StackFrame::FindVariable(ConstString name) {1860  ValueObjectSP value_sp;1861 1862  if (!name)1863    return value_sp;1864 1865  TargetSP target_sp = CalculateTarget();1866  ProcessSP process_sp = CalculateProcess();1867 1868  if (!target_sp && !process_sp)1869    return value_sp;1870 1871  VariableList variable_list;1872  VariableSP var_sp;1873  SymbolContext sc(GetSymbolContext(eSymbolContextBlock));1874 1875  if (sc.block) {1876    const bool can_create = true;1877    const bool get_parent_variables = true;1878    const bool stop_if_block_is_inlined_function = true;1879 1880    if (sc.block->AppendVariables(1881            can_create, get_parent_variables, stop_if_block_is_inlined_function,1882            [this](Variable *v) { return v->IsInScope(this); },1883            &variable_list)) {1884      var_sp = variable_list.FindVariable(name);1885    }1886 1887    if (var_sp)1888      value_sp = GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);1889  }1890 1891  return value_sp;1892}1893 1894TargetSP StackFrame::CalculateTarget() {1895  TargetSP target_sp;1896  ThreadSP thread_sp(GetThread());1897  if (thread_sp) {1898    ProcessSP process_sp(thread_sp->CalculateProcess());1899    if (process_sp)1900      target_sp = process_sp->CalculateTarget();1901  }1902  return target_sp;1903}1904 1905ProcessSP StackFrame::CalculateProcess() {1906  ProcessSP process_sp;1907  ThreadSP thread_sp(GetThread());1908  if (thread_sp)1909    process_sp = thread_sp->CalculateProcess();1910  return process_sp;1911}1912 1913ThreadSP StackFrame::CalculateThread() { return GetThread(); }1914 1915StackFrameSP StackFrame::CalculateStackFrame() { return shared_from_this(); }1916 1917void StackFrame::CalculateExecutionContext(ExecutionContext &exe_ctx) {1918  exe_ctx.SetContext(shared_from_this());1919}1920 1921bool StackFrame::DumpUsingFormat(Stream &strm,1922                                 const FormatEntity::Entry *format,1923                                 llvm::StringRef frame_marker) {1924  GetSymbolContext(eSymbolContextEverything);1925  ExecutionContext exe_ctx(shared_from_this());1926  StreamString s;1927  s.PutCString(frame_marker);1928 1929  if (format && FormatEntity::Format(*format, s, &m_sc, &exe_ctx, nullptr,1930                                     nullptr, false, false)) {1931    strm.PutCString(s.GetString());1932    return true;1933  }1934  return false;1935}1936 1937void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique,1938                                         const char *frame_marker) {1939  if (strm == nullptr)1940    return;1941 1942  ExecutionContext exe_ctx(shared_from_this());1943 1944  const FormatEntity::Entry *frame_format = nullptr;1945  FormatEntity::Entry format_entry;1946  Target *target = exe_ctx.GetTargetPtr();1947  if (target) {1948    if (show_unique) {1949      format_entry = target->GetDebugger().GetFrameFormatUnique();1950      frame_format = &format_entry;1951    } else {1952      format_entry = target->GetDebugger().GetFrameFormat();1953      frame_format = &format_entry;1954    }1955  }1956  if (!DumpUsingFormat(*strm, frame_format, frame_marker)) {1957    Dump(strm, true, false);1958    strm->EOL();1959  }1960}1961 1962void StackFrame::Dump(Stream *strm, bool show_frame_index,1963                      bool show_fullpaths) {1964  if (strm == nullptr)1965    return;1966 1967  if (show_frame_index)1968    strm->Printf("frame #%u: ", m_frame_index);1969  ExecutionContext exe_ctx(shared_from_this());1970  Target *target = exe_ctx.GetTargetPtr();1971  strm->Printf("0x%0*" PRIx64 " ",1972               target ? (target->GetArchitecture().GetAddressByteSize() * 2)1973                      : 16,1974               GetFrameCodeAddress().GetLoadAddress(target));1975  GetSymbolContext(eSymbolContextEverything);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;1980  m_sc.DumpStopContext(strm, exe_ctx.GetBestExecutionContextScope(),1981                       GetFrameCodeAddress(), show_fullpaths, show_module,1982                       show_inline, show_function_arguments,1983                       show_function_name);1984}1985 1986void StackFrame::UpdateCurrentFrameFromPreviousFrame(StackFrame &prev_frame) {1987  std::lock_guard<std::recursive_mutex> guard(m_mutex);1988  assert(GetStackID() ==1989         prev_frame.GetStackID()); // TODO: remove this after some testing1990  m_variable_list_sp = prev_frame.m_variable_list_sp;1991  m_variable_list_value_objects.Swap(prev_frame.m_variable_list_value_objects);1992  if (!m_disassembly.GetString().empty()) {1993    m_disassembly.Clear();1994    m_disassembly.PutCString(prev_frame.m_disassembly.GetString());1995  }1996}1997 1998void StackFrame::UpdatePreviousFrameFromCurrentFrame(StackFrame &curr_frame) {1999  std::lock_guard<std::recursive_mutex> guard(m_mutex);2000  assert(GetStackID() ==2001         curr_frame.GetStackID());     // TODO: remove this after some testing2002  m_id.SetPC(2003      curr_frame.m_id.GetPC(),2004      curr_frame.CalculateProcess().get()); // Update the Stack ID PC value2005  assert(GetThread() == curr_frame.GetThread());2006  m_frame_index = curr_frame.m_frame_index;2007  m_concrete_frame_index = curr_frame.m_concrete_frame_index;2008  m_reg_context_sp = curr_frame.m_reg_context_sp;2009  m_frame_code_addr = curr_frame.m_frame_code_addr;2010  m_behaves_like_zeroth_frame = curr_frame.m_behaves_like_zeroth_frame;2011  assert(!m_sc.target_sp || !curr_frame.m_sc.target_sp ||2012         m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get());2013  assert(!m_sc.module_sp || !curr_frame.m_sc.module_sp ||2014         m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get());2015  assert(m_sc.comp_unit == nullptr || curr_frame.m_sc.comp_unit == nullptr ||2016         m_sc.comp_unit == curr_frame.m_sc.comp_unit);2017  assert(m_sc.function == nullptr || curr_frame.m_sc.function == nullptr ||2018         m_sc.function == curr_frame.m_sc.function);2019  m_sc = curr_frame.m_sc;2020  m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything);2021  m_flags.Set(m_sc.GetResolvedMask());2022  m_frame_base.Clear();2023  m_frame_base_error.Clear();2024}2025 2026bool StackFrame::HasCachedData() const {2027  if (m_variable_list_sp)2028    return true;2029  if (m_variable_list_value_objects.GetSize() > 0)2030    return true;2031  if (!m_disassembly.GetString().empty())2032    return true;2033  return false;2034}2035 2036bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,2037                           bool show_unique, const char *frame_marker) {2038  if (show_frame_info) {2039    strm.Indent();2040    DumpUsingSettingsFormat(&strm, show_unique, frame_marker);2041  }2042 2043  if (show_source) {2044    ExecutionContext exe_ctx(shared_from_this());2045    bool have_source = false, have_debuginfo = false;2046    lldb::StopDisassemblyType disasm_display = lldb::eStopDisassemblyTypeNever;2047    Target *target = exe_ctx.GetTargetPtr();2048    if (target) {2049      Debugger &debugger = target->GetDebugger();2050      const uint32_t source_lines_before =2051          debugger.GetStopSourceLineCount(true);2052      const uint32_t source_lines_after =2053          debugger.GetStopSourceLineCount(false);2054      disasm_display = debugger.GetStopDisassemblyDisplay();2055 2056      GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);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) {2060          SupportFileNSP source_file_sp = m_sc.line_entry.file_sp;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);2064          }2065 2066          size_t num_lines =2067              target->GetSourceManager().DisplaySourceLinesWithLineNumbers(2068                  source_file_sp, start_line, m_sc.line_entry.column,2069                  source_lines_before, source_lines_after, "->", &strm);2070          if (num_lines != 0)2071            have_source = true;2072          // TODO: Give here a one time warning if source file is missing.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";2076        }2077      }2078      switch (disasm_display) {2079      case lldb::eStopDisassemblyTypeNever:2080        break;2081 2082      case lldb::eStopDisassemblyTypeNoDebugInfo:2083        if (have_debuginfo)2084          break;2085        [[fallthrough]];2086 2087      case lldb::eStopDisassemblyTypeNoSource:2088        if (have_source)2089          break;2090        [[fallthrough]];2091 2092      case lldb::eStopDisassemblyTypeAlways:2093        if (target) {2094          const uint32_t disasm_lines = debugger.GetDisassemblyLineCount();2095          if (disasm_lines > 0) {2096            const ArchSpec &target_arch = target->GetArchitecture();2097            const char *plugin_name = nullptr;2098            const char *flavor = nullptr;2099            const bool mixed_source_and_assembly = false;2100            Disassembler::Disassemble(2101                target->GetDebugger(), target_arch, plugin_name, flavor,2102                target->GetDisassemblyCPU(), target->GetDisassemblyFeatures(),2103                exe_ctx, GetFrameCodeAddress(),2104                {Disassembler::Limit::Instructions, disasm_lines},2105                mixed_source_and_assembly, 0,2106                Disassembler::eOptionMarkPCAddress, strm);2107          }2108        }2109        break;2110      }2111    }2112  }2113  return true;2114}2115 2116RecognizedStackFrameSP StackFrame::GetRecognizedFrame() {2117  auto process = GetThread()->GetProcess();2118  if (!process)2119    return {};2120  // If recognizer list has been modified, discard cache.2121  auto &manager = process->GetTarget().GetFrameRecognizerManager();2122  auto new_generation = manager.GetGeneration();2123  if (m_frame_recognizer_generation != new_generation)2124    m_recognized_frame_sp.reset();2125  m_frame_recognizer_generation = new_generation;2126  if (!m_recognized_frame_sp.has_value())2127    m_recognized_frame_sp = manager.RecognizeFrame(CalculateStackFrame());2128  return m_recognized_frame_sp.value();2129}2130