aboutsummaryrefslogtreecommitdiff
path: root/source/Target/StackFrame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Target/StackFrame.cpp')
-rw-r--r--source/Target/StackFrame.cpp1449
1 files changed, 1449 insertions, 0 deletions
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
new file mode 100644
index 000000000000..3c4c43d9f44c
--- /dev/null
+++ b/source/Target/StackFrame.cpp
@@ -0,0 +1,1449 @@
+//===-- StackFrame.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "lldb/Target/StackFrame.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/SymbolContextScope.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// The first bits in the flags are reserved for the SymbolContext::Scope bits
+// so we know if we have tried to look up information in our internal symbol
+// context (m_sc) already.
+#define RESOLVED_FRAME_CODE_ADDR (uint32_t(eSymbolContextEverything + 1))
+#define RESOLVED_FRAME_ID_SYMBOL_SCOPE (RESOLVED_FRAME_CODE_ADDR << 1)
+#define GOT_FRAME_BASE (RESOLVED_FRAME_ID_SYMBOL_SCOPE << 1)
+#define RESOLVED_VARIABLES (GOT_FRAME_BASE << 1)
+#define RESOLVED_GLOBAL_VARIABLES (RESOLVED_VARIABLES << 1)
+
+StackFrame::StackFrame (const ThreadSP &thread_sp,
+ user_id_t frame_idx,
+ user_id_t unwind_frame_index,
+ addr_t cfa,
+ addr_t pc,
+ const SymbolContext *sc_ptr) :
+ m_thread_wp (thread_sp),
+ m_frame_index (frame_idx),
+ m_concrete_frame_index (unwind_frame_index),
+ m_reg_context_sp (),
+ m_id (pc, cfa, NULL),
+ m_frame_code_addr (pc),
+ m_sc (),
+ m_flags (),
+ m_frame_base (),
+ m_frame_base_error (),
+ m_variable_list_sp (),
+ m_variable_list_value_objects (),
+ m_disassembly ()
+{
+ if (sc_ptr != NULL)
+ {
+ m_sc = *sc_ptr;
+ m_flags.Set(m_sc.GetResolvedMask ());
+ }
+}
+
+StackFrame::StackFrame (const ThreadSP &thread_sp,
+ user_id_t frame_idx,
+ user_id_t unwind_frame_index,
+ const RegisterContextSP &reg_context_sp,
+ addr_t cfa,
+ addr_t pc,
+ const SymbolContext *sc_ptr) :
+ m_thread_wp (thread_sp),
+ m_frame_index (frame_idx),
+ m_concrete_frame_index (unwind_frame_index),
+ m_reg_context_sp (reg_context_sp),
+ m_id (pc, cfa, NULL),
+ m_frame_code_addr (pc),
+ m_sc (),
+ m_flags (),
+ m_frame_base (),
+ m_frame_base_error (),
+ m_variable_list_sp (),
+ m_variable_list_value_objects (),
+ m_disassembly ()
+{
+ if (sc_ptr != NULL)
+ {
+ m_sc = *sc_ptr;
+ m_flags.Set(m_sc.GetResolvedMask ());
+ }
+
+ if (reg_context_sp && !m_sc.target_sp)
+ {
+ m_sc.target_sp = reg_context_sp->CalculateTarget();
+ if (m_sc.target_sp)
+ m_flags.Set (eSymbolContextTarget);
+ }
+}
+
+StackFrame::StackFrame (const ThreadSP &thread_sp,
+ user_id_t frame_idx,
+ user_id_t unwind_frame_index,
+ const RegisterContextSP &reg_context_sp,
+ addr_t cfa,
+ const Address& pc_addr,
+ const SymbolContext *sc_ptr) :
+ m_thread_wp (thread_sp),
+ m_frame_index (frame_idx),
+ m_concrete_frame_index (unwind_frame_index),
+ m_reg_context_sp (reg_context_sp),
+ m_id (pc_addr.GetLoadAddress (thread_sp->CalculateTarget().get()), cfa, NULL),
+ m_frame_code_addr (pc_addr),
+ m_sc (),
+ m_flags (),
+ m_frame_base (),
+ m_frame_base_error (),
+ m_variable_list_sp (),
+ m_variable_list_value_objects (),
+ m_disassembly ()
+{
+ if (sc_ptr != NULL)
+ {
+ m_sc = *sc_ptr;
+ m_flags.Set(m_sc.GetResolvedMask ());
+ }
+
+ if (m_sc.target_sp.get() == NULL && reg_context_sp)
+ {
+ m_sc.target_sp = reg_context_sp->CalculateTarget();
+ if (m_sc.target_sp)
+ m_flags.Set (eSymbolContextTarget);
+ }
+
+ ModuleSP pc_module_sp (pc_addr.GetModule());
+ if (!m_sc.module_sp || m_sc.module_sp != pc_module_sp)
+ {
+ if (pc_module_sp)
+ {
+ m_sc.module_sp = pc_module_sp;
+ m_flags.Set (eSymbolContextModule);
+ }
+ else
+ {
+ m_sc.module_sp.reset();
+ }
+ }
+}
+
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+StackFrame::~StackFrame()
+{
+}
+
+StackID&
+StackFrame::GetStackID()
+{
+ // Make sure we have resolved the StackID object's symbol context scope if
+ // we already haven't looked it up.
+
+ if (m_flags.IsClear (RESOLVED_FRAME_ID_SYMBOL_SCOPE))
+ {
+ if (m_id.GetSymbolContextScope ())
+ {
+ // We already have a symbol context scope, we just don't have our
+ // flag bit set.
+ m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE);
+ }
+ else
+ {
+ // Calculate the frame block and use this for the stack ID symbol
+ // context scope if we have one.
+ SymbolContextScope *scope = GetFrameBlock ();
+ if (scope == NULL)
+ {
+ // We don't have a block, so use the symbol
+ if (m_flags.IsClear (eSymbolContextSymbol))
+ GetSymbolContext (eSymbolContextSymbol);
+
+ // It is ok if m_sc.symbol is NULL here
+ scope = m_sc.symbol;
+ }
+ // Set the symbol context scope (the accessor will set the
+ // RESOLVED_FRAME_ID_SYMBOL_SCOPE bit in m_flags).
+ SetSymbolContextScope (scope);
+ }
+ }
+ return m_id;
+}
+
+uint32_t
+StackFrame::GetFrameIndex () const
+{
+ ThreadSP thread_sp = GetThread();
+ if (thread_sp)
+ return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex(m_frame_index);
+ else
+ return m_frame_index;
+}
+
+void
+StackFrame::SetSymbolContextScope (SymbolContextScope *symbol_scope)
+{
+ m_flags.Set (RESOLVED_FRAME_ID_SYMBOL_SCOPE);
+ m_id.SetSymbolContextScope (symbol_scope);
+}
+
+const Address&
+StackFrame::GetFrameCodeAddress()
+{
+ if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && !m_frame_code_addr.IsSectionOffset())
+ {
+ m_flags.Set (RESOLVED_FRAME_CODE_ADDR);
+
+ // Resolve the PC into a temporary address because if ResolveLoadAddress
+ // fails to resolve the address, it will clear the address object...
+ ThreadSP thread_sp (GetThread());
+ if (thread_sp)
+ {
+ TargetSP target_sp (thread_sp->CalculateTarget());
+ if (target_sp)
+ {
+ if (m_frame_code_addr.SetOpcodeLoadAddress (m_frame_code_addr.GetOffset(), target_sp.get()))
+ {
+ ModuleSP module_sp (m_frame_code_addr.GetModule());
+ if (module_sp)
+ {
+ m_sc.module_sp = module_sp;
+ m_flags.Set(eSymbolContextModule);
+ }
+ }
+ }
+ }
+ }
+ return m_frame_code_addr;
+}
+
+void
+StackFrame::ChangePC (addr_t pc)
+{
+ m_frame_code_addr.SetRawAddress(pc);
+ m_sc.Clear(false);
+ m_flags.Reset(0);
+ ThreadSP thread_sp (GetThread());
+ if (thread_sp)
+ thread_sp->ClearStackFrames ();
+}
+
+const char *
+StackFrame::Disassemble ()
+{
+ if (m_disassembly.GetSize() == 0)
+ {
+ ExecutionContext exe_ctx (shared_from_this());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ {
+ const char *plugin_name = NULL;
+ const char *flavor = NULL;
+ Disassembler::Disassemble (target->GetDebugger(),
+ target->GetArchitecture(),
+ plugin_name,
+ flavor,
+ exe_ctx,
+ 0,
+ 0,
+ 0,
+ m_disassembly);
+ }
+ if (m_disassembly.GetSize() == 0)
+ return NULL;
+ }
+ return m_disassembly.GetData();
+}
+
+Block *
+StackFrame::GetFrameBlock ()
+{
+ if (m_sc.block == NULL && m_flags.IsClear (eSymbolContextBlock))
+ GetSymbolContext (eSymbolContextBlock);
+
+ if (m_sc.block)
+ {
+ Block *inline_block = m_sc.block->GetContainingInlinedBlock();
+ if (inline_block)
+ {
+ // Use the block with the inlined function info
+ // as the frame block we want this frame to have only the variables
+ // for the inlined function and its non-inlined block child blocks.
+ return inline_block;
+ }
+ else
+ {
+ // This block is not contained withing any inlined function blocks
+ // with so we want to use the top most function block.
+ return &m_sc.function->GetBlock (false);
+ }
+ }
+ return NULL;
+}
+
+//----------------------------------------------------------------------
+// Get the symbol context if we already haven't done so by resolving the
+// PC address as much as possible. This way when we pass around a
+// StackFrame object, everyone will have as much information as
+// possible and no one will ever have to look things up manually.
+//----------------------------------------------------------------------
+const SymbolContext&
+StackFrame::GetSymbolContext (uint32_t resolve_scope)
+{
+ // Copy our internal symbol context into "sc".
+ if ((m_flags.Get() & resolve_scope) != resolve_scope)
+ {
+ uint32_t resolved = 0;
+
+ // If the target was requested add that:
+ if (!m_sc.target_sp)
+ {
+ m_sc.target_sp = CalculateTarget();
+ if (m_sc.target_sp)
+ resolved |= eSymbolContextTarget;
+ }
+
+
+ // Resolve our PC to section offset if we haven't alreday done so
+ // and if we don't have a module. The resolved address section will
+ // contain the module to which it belongs
+ if (!m_sc.module_sp && m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR))
+ GetFrameCodeAddress();
+
+ // If this is not frame zero, then we need to subtract 1 from the PC
+ // value when doing address lookups since the PC will be on the
+ // instruction following the function call instruction...
+
+ Address lookup_addr(GetFrameCodeAddress());
+ if (m_frame_index > 0 && lookup_addr.IsValid())
+ {
+ addr_t offset = lookup_addr.GetOffset();
+ if (offset > 0)
+ lookup_addr.SetOffset(offset - 1);
+ }
+
+
+ if (m_sc.module_sp)
+ {
+ // We have something in our stack frame symbol context, lets check
+ // if we haven't already tried to lookup one of those things. If we
+ // haven't then we will do the query.
+
+ uint32_t actual_resolve_scope = 0;
+
+ if (resolve_scope & eSymbolContextCompUnit)
+ {
+ if (m_flags.IsClear (eSymbolContextCompUnit))
+ {
+ if (m_sc.comp_unit)
+ resolved |= eSymbolContextCompUnit;
+ else
+ actual_resolve_scope |= eSymbolContextCompUnit;
+ }
+ }
+
+ if (resolve_scope & eSymbolContextFunction)
+ {
+ if (m_flags.IsClear (eSymbolContextFunction))
+ {
+ if (m_sc.function)
+ resolved |= eSymbolContextFunction;
+ else
+ actual_resolve_scope |= eSymbolContextFunction;
+ }
+ }
+
+ if (resolve_scope & eSymbolContextBlock)
+ {
+ if (m_flags.IsClear (eSymbolContextBlock))
+ {
+ if (m_sc.block)
+ resolved |= eSymbolContextBlock;
+ else
+ actual_resolve_scope |= eSymbolContextBlock;
+ }
+ }
+
+ if (resolve_scope & eSymbolContextSymbol)
+ {
+ if (m_flags.IsClear (eSymbolContextSymbol))
+ {
+ if (m_sc.symbol)
+ resolved |= eSymbolContextSymbol;
+ else
+ actual_resolve_scope |= eSymbolContextSymbol;
+ }
+ }
+
+ if (resolve_scope & eSymbolContextLineEntry)
+ {
+ if (m_flags.IsClear (eSymbolContextLineEntry))
+ {
+ if (m_sc.line_entry.IsValid())
+ resolved |= eSymbolContextLineEntry;
+ else
+ actual_resolve_scope |= eSymbolContextLineEntry;
+ }
+ }
+
+ if (actual_resolve_scope)
+ {
+ // We might be resolving less information than what is already
+ // in our current symbol context so resolve into a temporary
+ // symbol context "sc" so we don't clear out data we have
+ // already found in "m_sc"
+ SymbolContext sc;
+ // Set flags that indicate what we have tried to resolve
+ resolved |= m_sc.module_sp->ResolveSymbolContextForAddress (lookup_addr, actual_resolve_scope, sc);
+ // Only replace what we didn't already have as we may have
+ // information for an inlined function scope that won't match
+ // what a standard lookup by address would match
+ if ((resolved & eSymbolContextCompUnit) && m_sc.comp_unit == NULL)
+ m_sc.comp_unit = sc.comp_unit;
+ if ((resolved & eSymbolContextFunction) && m_sc.function == NULL)
+ m_sc.function = sc.function;
+ if ((resolved & eSymbolContextBlock) && m_sc.block == NULL)
+ m_sc.block = sc.block;
+ if ((resolved & eSymbolContextSymbol) && m_sc.symbol == NULL)
+ m_sc.symbol = sc.symbol;
+ if ((resolved & eSymbolContextLineEntry) && !m_sc.line_entry.IsValid())
+ {
+ m_sc.line_entry = sc.line_entry;
+ if (m_sc.target_sp)
+ {
+ // Be sure to apply and file remappings to our file and line
+ // entries when handing out a line entry
+ FileSpec new_file_spec;
+ if (m_sc.target_sp->GetSourcePathMap().FindFile (m_sc.line_entry.file, new_file_spec))
+ m_sc.line_entry.file = new_file_spec;
+ }
+ }
+ }
+ }
+ else
+ {
+ // If we don't have a module, then we can't have the compile unit,
+ // function, block, line entry or symbol, so we can safely call
+ // ResolveSymbolContextForAddress with our symbol context member m_sc.
+ if (m_sc.target_sp)
+ {
+ resolved |= m_sc.target_sp->GetImages().ResolveSymbolContextForAddress (lookup_addr, resolve_scope, m_sc);
+ }
+ }
+
+ // Update our internal flags so we remember what we have tried to locate so
+ // we don't have to keep trying when more calls to this function are made.
+ // We might have dug up more information that was requested (for example
+ // if we were asked to only get the block, we will have gotten the
+ // compile unit, and function) so set any additional bits that we resolved
+ m_flags.Set (resolve_scope | resolved);
+ }
+
+ // Return the symbol context with everything that was possible to resolve
+ // resolved.
+ return m_sc;
+}
+
+
+VariableList *
+StackFrame::GetVariableList (bool get_file_globals)
+{
+ if (m_flags.IsClear(RESOLVED_VARIABLES))
+ {
+ m_flags.Set(RESOLVED_VARIABLES);
+
+ Block *frame_block = GetFrameBlock();
+
+ if (frame_block)
+ {
+ const bool get_child_variables = true;
+ const bool can_create = true;
+ const bool stop_if_child_block_is_inlined_function = true;
+ m_variable_list_sp.reset(new VariableList());
+ frame_block->AppendBlockVariables(can_create, get_child_variables, stop_if_child_block_is_inlined_function, m_variable_list_sp.get());
+ }
+ }
+
+ if (m_flags.IsClear(RESOLVED_GLOBAL_VARIABLES) &&
+ get_file_globals)
+ {
+ m_flags.Set(RESOLVED_GLOBAL_VARIABLES);
+
+ if (m_flags.IsClear (eSymbolContextCompUnit))
+ GetSymbolContext (eSymbolContextCompUnit);
+
+ if (m_sc.comp_unit)
+ {
+ VariableListSP global_variable_list_sp (m_sc.comp_unit->GetVariableList(true));
+ if (m_variable_list_sp)
+ m_variable_list_sp->AddVariables (global_variable_list_sp.get());
+ else
+ m_variable_list_sp = global_variable_list_sp;
+ }
+ }
+
+ return m_variable_list_sp.get();
+}
+
+VariableListSP
+StackFrame::GetInScopeVariableList (bool get_file_globals)
+{
+ VariableListSP var_list_sp(new VariableList);
+ GetSymbolContext (eSymbolContextCompUnit | eSymbolContextBlock);
+
+ if (m_sc.block)
+ {
+ const bool can_create = true;
+ const bool get_parent_variables = true;
+ const bool stop_if_block_is_inlined_function = true;
+ m_sc.block->AppendVariables (can_create,
+ get_parent_variables,
+ stop_if_block_is_inlined_function,
+ var_list_sp.get());
+ }
+
+ if (m_sc.comp_unit)
+ {
+ VariableListSP global_variable_list_sp (m_sc.comp_unit->GetVariableList(true));
+ if (global_variable_list_sp)
+ var_list_sp->AddVariables (global_variable_list_sp.get());
+ }
+
+ return var_list_sp;
+}
+
+
+ValueObjectSP
+StackFrame::GetValueForVariableExpressionPath (const char *var_expr_cstr,
+ DynamicValueType use_dynamic,
+ uint32_t options,
+ VariableSP &var_sp,
+ Error &error)
+{
+
+ if (var_expr_cstr && var_expr_cstr[0])
+ {
+ const bool check_ptr_vs_member = (options & eExpressionPathOptionCheckPtrVsMember) != 0;
+ const bool no_fragile_ivar = (options & eExpressionPathOptionsNoFragileObjcIvar) != 0;
+ const bool no_synth_child = (options & eExpressionPathOptionsNoSyntheticChildren) != 0;
+ //const bool no_synth_array = (options & eExpressionPathOptionsNoSyntheticArrayRange) != 0;
+ error.Clear();
+ bool deref = false;
+ bool address_of = false;
+ ValueObjectSP valobj_sp;
+ const bool get_file_globals = true;
+ // When looking up a variable for an expression, we need only consider the
+ // variables that are in scope.
+ VariableListSP var_list_sp (GetInScopeVariableList (get_file_globals));
+ VariableList *variable_list = var_list_sp.get();
+
+ if (variable_list)
+ {
+ // If first character is a '*', then show pointer contents
+ const char *var_expr = var_expr_cstr;
+ if (var_expr[0] == '*')
+ {
+ deref = true;
+ var_expr++; // Skip the '*'
+ }
+ else if (var_expr[0] == '&')
+ {
+ address_of = true;
+ var_expr++; // Skip the '&'
+ }
+
+ std::string var_path (var_expr);
+ size_t separator_idx = var_path.find_first_of(".-[=+~|&^%#@!/?,<>{}");
+ StreamString var_expr_path_strm;
+
+ ConstString name_const_string;
+ if (separator_idx == std::string::npos)
+ name_const_string.SetCString (var_path.c_str());
+ else
+ name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx);
+
+ var_sp = variable_list->FindVariable(name_const_string);
+
+ bool synthetically_added_instance_object = false;
+
+ if (var_sp)
+ {
+ var_path.erase (0, name_const_string.GetLength ());
+ }
+ else if (options & eExpressionPathOptionsAllowDirectIVarAccess)
+ {
+ // Check for direct ivars access which helps us with implicit
+ // access to ivars with the "this->" or "self->"
+ GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock);
+ lldb::LanguageType method_language = eLanguageTypeUnknown;
+ bool is_instance_method = false;
+ ConstString method_object_name;
+ if (m_sc.GetFunctionMethodInfo (method_language, is_instance_method, method_object_name))
+ {
+ if (is_instance_method && method_object_name)
+ {
+ var_sp = variable_list->FindVariable(method_object_name);
+ if (var_sp)
+ {
+ separator_idx = 0;
+ var_path.insert(0, "->");
+ synthetically_added_instance_object = true;
+ }
+ }
+ }
+ }
+
+ if (var_sp)
+ {
+ valobj_sp = GetValueObjectForFrameVariable (var_sp, use_dynamic);
+ if (!valobj_sp)
+ return valobj_sp;
+
+ // We are dumping at least one child
+ while (separator_idx != std::string::npos)
+ {
+ // Calculate the next separator index ahead of time
+ ValueObjectSP child_valobj_sp;
+ const char separator_type = var_path[0];
+ switch (separator_type)
+ {
+
+ case '-':
+ if (var_path.size() >= 2 && var_path[1] != '>')
+ return ValueObjectSP();
+
+ if (no_fragile_ivar)
+ {
+ // Make sure we aren't trying to deref an objective
+ // C ivar if this is not allowed
+ const uint32_t pointer_type_flags = valobj_sp->GetClangType().GetTypeInfo (NULL);
+ if ((pointer_type_flags & ClangASTType::eTypeIsObjC) &&
+ (pointer_type_flags & ClangASTType::eTypeIsPointer))
+ {
+ // This was an objective C object pointer and
+ // it was requested we skip any fragile ivars
+ // so return nothing here
+ return ValueObjectSP();
+ }
+ }
+ var_path.erase (0, 1); // Remove the '-'
+ // Fall through
+ case '.':
+ {
+ const bool expr_is_ptr = var_path[0] == '>';
+
+ var_path.erase (0, 1); // Remove the '.' or '>'
+ separator_idx = var_path.find_first_of(".-[");
+ ConstString child_name;
+ if (separator_idx == std::string::npos)
+ child_name.SetCString (var_path.c_str());
+ else
+ child_name.SetCStringWithLength(var_path.c_str(), separator_idx);
+
+ if (check_ptr_vs_member)
+ {
+ // We either have a pointer type and need to verify
+ // valobj_sp is a pointer, or we have a member of a
+ // class/union/struct being accessed with the . syntax
+ // and need to verify we don't have a pointer.
+ const bool actual_is_ptr = valobj_sp->IsPointerType ();
+
+ if (actual_is_ptr != expr_is_ptr)
+ {
+ // Incorrect use of "." with a pointer, or "->" with
+ // a class/union/struct instance or reference.
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ if (actual_is_ptr)
+ error.SetErrorStringWithFormat ("\"%s\" is a pointer and . was used to attempt to access \"%s\". Did you mean \"%s->%s\"?",
+ var_expr_path_strm.GetString().c_str(),
+ child_name.GetCString(),
+ var_expr_path_strm.GetString().c_str(),
+ var_path.c_str());
+ else
+ error.SetErrorStringWithFormat ("\"%s\" is not a pointer and -> was used to attempt to access \"%s\". Did you mean \"%s.%s\"?",
+ var_expr_path_strm.GetString().c_str(),
+ child_name.GetCString(),
+ var_expr_path_strm.GetString().c_str(),
+ var_path.c_str());
+ return ValueObjectSP();
+ }
+ }
+ child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
+ if (!child_valobj_sp)
+ {
+ if (no_synth_child == false)
+ {
+ child_valobj_sp = valobj_sp->GetSyntheticValue();
+ if (child_valobj_sp)
+ child_valobj_sp = child_valobj_sp->GetChildMemberWithName (child_name, true);
+ }
+
+ if (no_synth_child || !child_valobj_sp)
+ {
+ // No child member with name "child_name"
+ if (synthetically_added_instance_object)
+ {
+ // We added a "this->" or "self->" to the beginning of the expression
+ // and this is the first pointer ivar access, so just return the normal
+ // error
+ error.SetErrorStringWithFormat("no variable or instance variable named '%s' found in this frame",
+ name_const_string.GetCString());
+ }
+ else
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ if (child_name)
+ {
+ error.SetErrorStringWithFormat ("\"%s\" is not a member of \"(%s) %s\"",
+ child_name.GetCString(),
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("incomplete expression path after \"%s\" in \"%s\"",
+ var_expr_path_strm.GetString().c_str(),
+ var_expr_cstr);
+ }
+ }
+ return ValueObjectSP();
+ }
+ }
+ synthetically_added_instance_object = false;
+ // Remove the child name from the path
+ var_path.erase(0, child_name.GetLength());
+ if (use_dynamic != eNoDynamicValues)
+ {
+ ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic));
+ if (dynamic_value_sp)
+ child_valobj_sp = dynamic_value_sp;
+ }
+ }
+ break;
+
+ case '[':
+ // Array member access, or treating pointer as an array
+ if (var_path.size() > 2) // Need at least two brackets and a number
+ {
+ char *end = NULL;
+ long child_index = ::strtol (&var_path[1], &end, 0);
+ if (end && *end == ']'
+ && *(end-1) != '[') // this code forces an error in the case of arr[]. as bitfield[] is not a good syntax we're good to go
+ {
+ if (valobj_sp->GetClangType().IsPointerToScalarType() && deref)
+ {
+ // what we have is *ptr[low]. the most similar C++ syntax is to deref ptr
+ // and extract bit low out of it. reading array item low
+ // would be done by saying ptr[low], without a deref * sign
+ Error error;
+ ValueObjectSP temp(valobj_sp->Dereference(error));
+ if (error.Fail())
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ return ValueObjectSP();
+ }
+ valobj_sp = temp;
+ deref = false;
+ }
+ else if (valobj_sp->GetClangType().IsArrayOfScalarType() && deref)
+ {
+ // what we have is *arr[low]. the most similar C++ syntax is to get arr[0]
+ // (an operation that is equivalent to deref-ing arr)
+ // and extract bit low out of it. reading array item low
+ // would be done by saying arr[low], without a deref * sign
+ Error error;
+ ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true));
+ if (error.Fail())
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ return ValueObjectSP();
+ }
+ valobj_sp = temp;
+ deref = false;
+ }
+
+ bool is_incomplete_array = false;
+ if (valobj_sp->IsPointerType ())
+ {
+ bool is_objc_pointer = true;
+
+ if (valobj_sp->GetClangType().GetMinimumLanguage() != eLanguageTypeObjC)
+ is_objc_pointer = false;
+ else if (!valobj_sp->GetClangType().IsPointerType())
+ is_objc_pointer = false;
+
+ if (no_synth_child && is_objc_pointer)
+ {
+ error.SetErrorStringWithFormat("\"(%s) %s\" is an Objective-C pointer, and cannot be subscripted",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+
+ return ValueObjectSP();
+ }
+ else if (is_objc_pointer)
+ {
+ // dereferencing ObjC variables is not valid.. so let's try and recur to synthetic children
+ ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
+ if (synthetic.get() == NULL /* no synthetic */
+ || synthetic == valobj_sp) /* synthetic is the same as the original object */
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ else
+ {
+ child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
+ }
+ else
+ {
+ child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("failed to use pointer as array for index %ld for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
+ }
+ else if (valobj_sp->GetClangType().IsArrayType (NULL, NULL, &is_incomplete_array))
+ {
+ // Pass false to dynamic_value here so we can tell the difference between
+ // no dynamic value and no member of this type...
+ child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
+ if (!child_valobj_sp && (is_incomplete_array || no_synth_child == false))
+ child_valobj_sp = valobj_sp->GetSyntheticArrayMember (child_index, true);
+
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
+ else if (valobj_sp->GetClangType().IsScalarType())
+ {
+ // this is a bitfield asking to display just one bit
+ child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("bitfield range %ld-%ld is not valid for \"(%s) %s\"",
+ child_index, child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
+ else
+ {
+ ValueObjectSP synthetic = valobj_sp->GetSyntheticValue();
+ if (no_synth_child /* synthetic is forbidden */ ||
+ synthetic.get() == NULL /* no synthetic */
+ || synthetic == valobj_sp) /* synthetic is the same as the original object */
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("\"(%s) %s\" is not an array type",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ else if (child_index >= synthetic->GetNumChildren() /* synthetic does not have that many values */)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ else
+ {
+ child_valobj_sp = synthetic->GetChildAtIndex(child_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("array index %ld is not valid for \"(%s) %s\"",
+ child_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
+ }
+
+ if (!child_valobj_sp)
+ {
+ // Invalid array index...
+ return ValueObjectSP();
+ }
+
+ // Erase the array member specification '[%i]' where
+ // %i is the array index
+ var_path.erase(0, (end - var_path.c_str()) + 1);
+ separator_idx = var_path.find_first_of(".-[");
+ if (use_dynamic != eNoDynamicValues)
+ {
+ ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic));
+ if (dynamic_value_sp)
+ child_valobj_sp = dynamic_value_sp;
+ }
+ // Break out early from the switch since we were
+ // able to find the child member
+ break;
+ }
+ else if (end && *end == '-')
+ {
+ // this is most probably a BitField, let's take a look
+ char *real_end = NULL;
+ long final_index = ::strtol (end+1, &real_end, 0);
+ bool expand_bitfield = true;
+ if (real_end && *real_end == ']')
+ {
+ // if the format given is [high-low], swap range
+ if (child_index > final_index)
+ {
+ long temp = child_index;
+ child_index = final_index;
+ final_index = temp;
+ }
+
+ if (valobj_sp->GetClangType().IsPointerToScalarType() && deref)
+ {
+ // what we have is *ptr[low-high]. the most similar C++ syntax is to deref ptr
+ // and extract bits low thru high out of it. reading array items low thru high
+ // would be done by saying ptr[low-high], without a deref * sign
+ Error error;
+ ValueObjectSP temp(valobj_sp->Dereference(error));
+ if (error.Fail())
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ return ValueObjectSP();
+ }
+ valobj_sp = temp;
+ deref = false;
+ }
+ else if (valobj_sp->GetClangType().IsArrayOfScalarType() && deref)
+ {
+ // what we have is *arr[low-high]. the most similar C++ syntax is to get arr[0]
+ // (an operation that is equivalent to deref-ing arr)
+ // and extract bits low thru high out of it. reading array items low thru high
+ // would be done by saying arr[low-high], without a deref * sign
+ Error error;
+ ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true));
+ if (error.Fail())
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"",
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ return ValueObjectSP();
+ }
+ valobj_sp = temp;
+ deref = false;
+ }
+ /*else if (valobj_sp->IsArrayType() || valobj_sp->IsPointerType())
+ {
+ child_valobj_sp = valobj_sp->GetSyntheticArrayRangeChild(child_index, final_index, true);
+ expand_bitfield = false;
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("array range %i-%i is not valid for \"(%s) %s\"",
+ child_index, final_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }*/
+
+ if (expand_bitfield)
+ {
+ child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true);
+ if (!child_valobj_sp)
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("bitfield range %ld-%ld is not valid for \"(%s) %s\"",
+ child_index, final_index,
+ valobj_sp->GetTypeName().AsCString("<invalid type>"),
+ var_expr_path_strm.GetString().c_str());
+ }
+ }
+ }
+
+ if (!child_valobj_sp)
+ {
+ // Invalid bitfield range...
+ return ValueObjectSP();
+ }
+
+ // Erase the bitfield member specification '[%i-%i]' where
+ // %i is the index
+ var_path.erase(0, (real_end - var_path.c_str()) + 1);
+ separator_idx = var_path.find_first_of(".-[");
+ if (use_dynamic != eNoDynamicValues)
+ {
+ ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic));
+ if (dynamic_value_sp)
+ child_valobj_sp = dynamic_value_sp;
+ }
+ // Break out early from the switch since we were
+ // able to find the child member
+ break;
+
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("invalid square bracket encountered after \"%s\" in \"%s\"",
+ var_expr_path_strm.GetString().c_str(),
+ var_path.c_str());
+ }
+ return ValueObjectSP();
+
+ default:
+ // Failure...
+ {
+ valobj_sp->GetExpressionPath (var_expr_path_strm, false);
+ error.SetErrorStringWithFormat ("unexpected char '%c' encountered after \"%s\" in \"%s\"",
+ separator_type,
+ var_expr_path_strm.GetString().c_str(),
+ var_path.c_str());
+
+ return ValueObjectSP();
+ }
+ }
+
+ if (child_valobj_sp)
+ valobj_sp = child_valobj_sp;
+
+ if (var_path.empty())
+ break;
+
+ }
+ if (valobj_sp)
+ {
+ if (deref)
+ {
+ ValueObjectSP deref_valobj_sp (valobj_sp->Dereference(error));
+ valobj_sp = deref_valobj_sp;
+ }
+ else if (address_of)
+ {
+ ValueObjectSP address_of_valobj_sp (valobj_sp->AddressOf(error));
+ valobj_sp = address_of_valobj_sp;
+ }
+ }
+ return valobj_sp;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("no variable named '%s' found in this frame",
+ name_const_string.GetCString());
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("invalid variable path '%s'", var_expr_cstr);
+ }
+ return ValueObjectSP();
+}
+
+bool
+StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
+{
+ if (m_flags.IsClear(GOT_FRAME_BASE))
+ {
+ if (m_sc.function)
+ {
+ m_frame_base.Clear();
+ m_frame_base_error.Clear();
+
+ m_flags.Set(GOT_FRAME_BASE);
+ ExecutionContext exe_ctx (shared_from_this());
+ Value expr_value;
+ addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
+ if (m_sc.function->GetFrameBaseExpression().IsLocationList())
+ loclist_base_addr = m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (exe_ctx.GetTargetPtr());
+
+ if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, NULL, NULL, loclist_base_addr, NULL, expr_value, &m_frame_base_error) == false)
+ {
+ // We should really have an error if evaluate returns, but in case
+ // we don't, lets set the error to something at least.
+ if (m_frame_base_error.Success())
+ m_frame_base_error.SetErrorString("Evaluation of the frame base expression failed.");
+ }
+ else
+ {
+ m_frame_base = expr_value.ResolveValue(&exe_ctx);
+ }
+ }
+ else
+ {
+ m_frame_base_error.SetErrorString ("No function in symbol context.");
+ }
+ }
+
+ if (m_frame_base_error.Success())
+ frame_base = m_frame_base;
+
+ if (error_ptr)
+ *error_ptr = m_frame_base_error;
+ return m_frame_base_error.Success();
+}
+
+RegisterContextSP
+StackFrame::GetRegisterContext ()
+{
+ if (!m_reg_context_sp)
+ {
+ ThreadSP thread_sp (GetThread());
+ if (thread_sp)
+ m_reg_context_sp = thread_sp->CreateRegisterContextForFrame (this);
+ }
+ return m_reg_context_sp;
+}
+
+bool
+StackFrame::HasDebugInformation ()
+{
+ GetSymbolContext (eSymbolContextLineEntry);
+ return m_sc.line_entry.IsValid();
+}
+
+
+ValueObjectSP
+StackFrame::GetValueObjectForFrameVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic)
+{
+ ValueObjectSP valobj_sp;
+ VariableList *var_list = GetVariableList (true);
+ if (var_list)
+ {
+ // Make sure the variable is a frame variable
+ const uint32_t var_idx = var_list->FindIndexForVariable (variable_sp.get());
+ const uint32_t num_variables = var_list->GetSize();
+ if (var_idx < num_variables)
+ {
+ valobj_sp = m_variable_list_value_objects.GetValueObjectAtIndex (var_idx);
+ if (valobj_sp.get() == NULL)
+ {
+ if (m_variable_list_value_objects.GetSize() < num_variables)
+ m_variable_list_value_objects.Resize(num_variables);
+ valobj_sp = ValueObjectVariable::Create (this, variable_sp);
+ m_variable_list_value_objects.SetValueObjectAtIndex (var_idx, valobj_sp);
+ }
+ }
+ }
+ if (use_dynamic != eNoDynamicValues && valobj_sp)
+ {
+ ValueObjectSP dynamic_sp = valobj_sp->GetDynamicValue (use_dynamic);
+ if (dynamic_sp)
+ return dynamic_sp;
+ }
+ return valobj_sp;
+}
+
+ValueObjectSP
+StackFrame::TrackGlobalVariable (const VariableSP &variable_sp, DynamicValueType use_dynamic)
+{
+ // Check to make sure we aren't already tracking this variable?
+ ValueObjectSP valobj_sp (GetValueObjectForFrameVariable (variable_sp, use_dynamic));
+ if (!valobj_sp)
+ {
+ // We aren't already tracking this global
+ VariableList *var_list = GetVariableList (true);
+ // If this frame has no variables, create a new list
+ if (var_list == NULL)
+ m_variable_list_sp.reset (new VariableList());
+
+ // Add the global/static variable to this frame
+ m_variable_list_sp->AddVariable (variable_sp);
+
+ // Now make a value object for it so we can track its changes
+ valobj_sp = GetValueObjectForFrameVariable (variable_sp, use_dynamic);
+ }
+ return valobj_sp;
+}
+
+bool
+StackFrame::IsInlined ()
+{
+ if (m_sc.block == NULL)
+ GetSymbolContext (eSymbolContextBlock);
+ if (m_sc.block)
+ return m_sc.block->GetContainingInlinedBlock() != NULL;
+ return false;
+}
+
+TargetSP
+StackFrame::CalculateTarget ()
+{
+ TargetSP target_sp;
+ ThreadSP thread_sp(GetThread());
+ if (thread_sp)
+ {
+ ProcessSP process_sp (thread_sp->CalculateProcess());
+ if (process_sp)
+ target_sp = process_sp->CalculateTarget();
+ }
+ return target_sp;
+}
+
+ProcessSP
+StackFrame::CalculateProcess ()
+{
+ ProcessSP process_sp;
+ ThreadSP thread_sp(GetThread());
+ if (thread_sp)
+ process_sp = thread_sp->CalculateProcess();
+ return process_sp;
+}
+
+ThreadSP
+StackFrame::CalculateThread ()
+{
+ return GetThread();
+}
+
+StackFrameSP
+StackFrame::CalculateStackFrame ()
+{
+ return shared_from_this();
+}
+
+
+void
+StackFrame::CalculateExecutionContext (ExecutionContext &exe_ctx)
+{
+ exe_ctx.SetContext (shared_from_this());
+}
+
+void
+StackFrame::DumpUsingSettingsFormat (Stream *strm)
+{
+ if (strm == NULL)
+ return;
+
+ GetSymbolContext(eSymbolContextEverything);
+ ExecutionContext exe_ctx (shared_from_this());
+ StreamString s;
+ const char *frame_format = NULL;
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ frame_format = target->GetDebugger().GetFrameFormat();
+ if (frame_format && Debugger::FormatPrompt (frame_format, &m_sc, &exe_ctx, NULL, s))
+ {
+ strm->Write(s.GetData(), s.GetSize());
+ }
+ else
+ {
+ Dump (strm, true, false);
+ strm->EOL();
+ }
+}
+
+void
+StackFrame::Dump (Stream *strm, bool show_frame_index, bool show_fullpaths)
+{
+ if (strm == NULL)
+ return;
+
+ if (show_frame_index)
+ strm->Printf("frame #%u: ", m_frame_index);
+ ExecutionContext exe_ctx (shared_from_this());
+ Target *target = exe_ctx.GetTargetPtr();
+ strm->Printf("0x%0*" PRIx64 " ",
+ target ? (target->GetArchitecture().GetAddressByteSize() * 2) : 16,
+ GetFrameCodeAddress().GetLoadAddress(target));
+ GetSymbolContext(eSymbolContextEverything);
+ const bool show_module = true;
+ const bool show_inline = true;
+ m_sc.DumpStopContext (strm,
+ exe_ctx.GetBestExecutionContextScope(),
+ GetFrameCodeAddress(),
+ show_fullpaths,
+ show_module,
+ show_inline);
+}
+
+void
+StackFrame::UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame)
+{
+ assert (GetStackID() == prev_frame.GetStackID()); // TODO: remove this after some testing
+ m_variable_list_sp = prev_frame.m_variable_list_sp;
+ m_variable_list_value_objects.Swap (prev_frame.m_variable_list_value_objects);
+ if (!m_disassembly.GetString().empty())
+ m_disassembly.GetString().swap (m_disassembly.GetString());
+}
+
+
+void
+StackFrame::UpdatePreviousFrameFromCurrentFrame (StackFrame &curr_frame)
+{
+ assert (GetStackID() == curr_frame.GetStackID()); // TODO: remove this after some testing
+ m_id.SetPC (curr_frame.m_id.GetPC()); // Update the Stack ID PC value
+ assert (GetThread() == curr_frame.GetThread());
+ m_frame_index = curr_frame.m_frame_index;
+ m_concrete_frame_index = curr_frame.m_concrete_frame_index;
+ m_reg_context_sp = curr_frame.m_reg_context_sp;
+ m_frame_code_addr = curr_frame.m_frame_code_addr;
+ assert (m_sc.target_sp.get() == NULL || curr_frame.m_sc.target_sp.get() == NULL || m_sc.target_sp.get() == curr_frame.m_sc.target_sp.get());
+ assert (m_sc.module_sp.get() == NULL || curr_frame.m_sc.module_sp.get() == NULL || m_sc.module_sp.get() == curr_frame.m_sc.module_sp.get());
+ assert (m_sc.comp_unit == NULL || curr_frame.m_sc.comp_unit == NULL || m_sc.comp_unit == curr_frame.m_sc.comp_unit);
+ assert (m_sc.function == NULL || curr_frame.m_sc.function == NULL || m_sc.function == curr_frame.m_sc.function);
+ m_sc = curr_frame.m_sc;
+ m_flags.Clear(GOT_FRAME_BASE | eSymbolContextEverything);
+ m_flags.Set (m_sc.GetResolvedMask());
+ m_frame_base.Clear();
+ m_frame_base_error.Clear();
+}
+
+
+bool
+StackFrame::HasCachedData () const
+{
+ if (m_variable_list_sp.get())
+ return true;
+ if (m_variable_list_value_objects.GetSize() > 0)
+ return true;
+ if (!m_disassembly.GetString().empty())
+ return true;
+ return false;
+}
+
+bool
+StackFrame::GetStatus (Stream& strm,
+ bool show_frame_info,
+ bool show_source)
+{
+
+ if (show_frame_info)
+ {
+ strm.Indent();
+ DumpUsingSettingsFormat (&strm);
+ }
+
+ if (show_source)
+ {
+ ExecutionContext exe_ctx (shared_from_this());
+ bool have_source = false;
+ Debugger::StopDisassemblyType disasm_display = Debugger::eStopDisassemblyTypeNever;
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ {
+ Debugger &debugger = target->GetDebugger();
+ const uint32_t source_lines_before = debugger.GetStopSourceLineCount(true);
+ const uint32_t source_lines_after = debugger.GetStopSourceLineCount(false);
+ disasm_display = debugger.GetStopDisassemblyDisplay ();
+
+ if (source_lines_before > 0 || source_lines_after > 0)
+ {
+ GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry);
+
+ if (m_sc.comp_unit && m_sc.line_entry.IsValid())
+ {
+ have_source = true;
+ target->GetSourceManager().DisplaySourceLinesWithLineNumbers (m_sc.line_entry.file,
+ m_sc.line_entry.line,
+ source_lines_before,
+ source_lines_after,
+ "->",
+ &strm);
+ }
+ }
+ switch (disasm_display)
+ {
+ case Debugger::eStopDisassemblyTypeNever:
+ break;
+
+ case Debugger::eStopDisassemblyTypeNoSource:
+ if (have_source)
+ break;
+ // Fall through to next case
+ case Debugger::eStopDisassemblyTypeAlways:
+ if (target)
+ {
+ const uint32_t disasm_lines = debugger.GetDisassemblyLineCount();
+ if (disasm_lines > 0)
+ {
+ const ArchSpec &target_arch = target->GetArchitecture();
+ AddressRange pc_range;
+ pc_range.GetBaseAddress() = GetFrameCodeAddress();
+ pc_range.SetByteSize(disasm_lines * target_arch.GetMaximumOpcodeByteSize());
+ const char *plugin_name = NULL;
+ const char *flavor = NULL;
+ Disassembler::Disassemble (target->GetDebugger(),
+ target_arch,
+ plugin_name,
+ flavor,
+ exe_ctx,
+ pc_range,
+ disasm_lines,
+ 0,
+ Disassembler::eOptionMarkPCAddress,
+ strm);
+ }
+ }
+ break;
+ }
+ }
+ }
+ return true;
+}
+