llvm-project/lldb/source/API/SBFrame.cpp

603 lines
17 KiB
C++
Raw Normal View History

//===-- SBFrame.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/API/SBFrame.h"
#include <string>
#include <algorithm>
#include "lldb/lldb-types.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/ClangUserExpression.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBValue.h"
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBSymbolContext.h"
#include "lldb/API/SBThread.h"
using namespace lldb;
using namespace lldb_private;
SBFrame::SBFrame () :
m_opaque_sp ()
{
}
SBFrame::SBFrame (const lldb::StackFrameSP &lldb_object_sp) :
m_opaque_sp (lldb_object_sp)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
{
SBStream sstr;
GetDescription (sstr);
2010-10-30 12:51:46 +08:00
log->Printf ("SBFrame::SBFrame (sp=%p) => SBFrame(%p): %s",
lldb_object_sp.get(), m_opaque_sp.get(), sstr.GetData());
}
}
SBFrame::SBFrame(const SBFrame &rhs) :
m_opaque_sp (rhs.m_opaque_sp)
{
}
const SBFrame &
SBFrame::operator = (const SBFrame &rhs)
{
if (this != &rhs)
m_opaque_sp = rhs.m_opaque_sp;
return *this;
}
SBFrame::~SBFrame()
{
}
void
SBFrame::SetFrame (const lldb::StackFrameSP &lldb_object_sp)
{
2010-10-30 12:51:46 +08:00
void *old_ptr = m_opaque_sp.get();
m_opaque_sp = lldb_object_sp;
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
{
log->Printf ("SBFrame(%p)::SetFrame(sp=%p) := SBFrame(%p)",
old_ptr, lldb_object_sp.get(), m_opaque_sp.get());
}
}
bool
SBFrame::IsValid() const
{
return (m_opaque_sp.get() != NULL);
}
SBSymbolContext
SBFrame::GetSymbolContext (uint32_t resolve_scope) const
{
SBSymbolContext sb_sym_ctx;
if (m_opaque_sp)
sb_sym_ctx.SetSymbolContext(&m_opaque_sp->GetSymbolContext (resolve_scope));
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
2010-10-30 12:51:46 +08:00
log->Printf ("SBFrame(%p)::GetSymbolContext (resolve_scope=0x%8.8x) => SBSymbolContext(%p)",
m_opaque_sp.get(), resolve_scope, sb_sym_ctx.get());
return sb_sym_ctx;
}
SBModule
SBFrame::GetModule () const
{
SBModule sb_module;
if (m_opaque_sp)
*sb_module = m_opaque_sp->GetSymbolContext (eSymbolContextModule).module_sp;
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::GetModule () => SBModule(%p)",
m_opaque_sp.get(), sb_module.get());
return sb_module;
}
SBCompileUnit
SBFrame::GetCompileUnit () const
{
SBCompileUnit sb_comp_unit;
if (m_opaque_sp)
sb_comp_unit.reset (m_opaque_sp->GetSymbolContext (eSymbolContextCompUnit).comp_unit);
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
2010-10-30 12:51:46 +08:00
log->Printf ("SBFrame(%p)::GetModule () => SBCompileUnit(%p)",
m_opaque_sp.get(), sb_comp_unit.get());
return sb_comp_unit;
}
SBFunction
SBFrame::GetFunction () const
{
SBFunction sb_function;
if (m_opaque_sp)
sb_function.reset(m_opaque_sp->GetSymbolContext (eSymbolContextFunction).function);
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::GetFunction () => SBFunction(%p)",
m_opaque_sp.get(), sb_function.get());
return sb_function;
}
SBSymbol
SBFrame::GetSymbol () const
{
SBSymbol sb_symbol;
if (m_opaque_sp)
sb_symbol.reset(m_opaque_sp->GetSymbolContext (eSymbolContextSymbol).symbol);
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::GetSymbol () => SBSymbol(%p)",
m_opaque_sp.get(), sb_symbol.get());
return sb_symbol;
}
SBBlock
SBFrame::GetBlock () const
{
SBBlock sb_block;
if (m_opaque_sp)
sb_block.reset (m_opaque_sp->GetSymbolContext (eSymbolContextBlock).block);
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::GetBlock () => SBBlock(%p)",
m_opaque_sp.get(), sb_block.get());
return sb_block;
}
SBBlock
SBFrame::GetFrameBlock () const
{
SBBlock sb_block;
if (m_opaque_sp)
sb_block.reset(m_opaque_sp->GetFrameBlock ());
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::GetFrameBlock () => SBBlock(%p)",
m_opaque_sp.get(), sb_block.get());
return sb_block;
}
SBLineEntry
SBFrame::GetLineEntry () const
{
SBLineEntry sb_line_entry;
if (m_opaque_sp)
sb_line_entry.SetLineEntry (m_opaque_sp->GetSymbolContext (eSymbolContextLineEntry).line_entry);
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::GetLineEntry () => SBLineEntry(%p)",
m_opaque_sp.get(), sb_line_entry.get());
return sb_line_entry;
}
uint32_t
SBFrame::GetFrameID () const
{
2010-10-30 12:51:46 +08:00
uint32_t frame_idx = m_opaque_sp ? m_opaque_sp->GetFrameIndex () : UINT32_MAX;
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::GetFrameID () => %u",
m_opaque_sp.get(), frame_idx);
return frame_idx;
}
lldb::addr_t
SBFrame::GetPC () const
{
lldb::addr_t addr = LLDB_INVALID_ADDRESS;
if (m_opaque_sp)
addr = m_opaque_sp->GetFrameCodeAddress().GetLoadAddress (&m_opaque_sp->GetThread().GetProcess().GetTarget());
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBFrame(%p)::GetPC () => 0x%llx", m_opaque_sp.get(), addr);
return addr;
}
bool
SBFrame::SetPC (lldb::addr_t new_pc)
{
bool ret_val = false;
if (m_opaque_sp)
ret_val = m_opaque_sp->GetRegisterContext()->SetPC (new_pc);
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
2010-10-30 12:51:46 +08:00
log->Printf ("SBFrame(%p)::SetPC (new_pc=0x%llx) => %i",
m_opaque_sp.get(), new_pc, ret_val);
return ret_val;
}
lldb::addr_t
SBFrame::GetSP () const
{
2010-10-30 12:51:46 +08:00
addr_t addr = LLDB_INVALID_ADDRESS;
if (m_opaque_sp)
2010-10-30 12:51:46 +08:00
addr = m_opaque_sp->GetRegisterContext()->GetSP();
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::GetSP () => 0x%llx", m_opaque_sp.get(), addr);
2010-10-30 12:51:46 +08:00
return addr;
}
lldb::addr_t
SBFrame::GetFP () const
{
lldb::addr_t addr = LLDB_INVALID_ADDRESS;
if (m_opaque_sp)
addr = m_opaque_sp->GetRegisterContext()->GetFP();
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBFrame(%p)::GetFP () => 0x%llx", m_opaque_sp.get(), addr);
return addr;
}
SBAddress
SBFrame::GetPCAddress () const
{
SBAddress sb_addr;
if (m_opaque_sp)
sb_addr.SetAddress (&m_opaque_sp->GetFrameCodeAddress());
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::GetPCAddress () => SBAddress(%p)", m_opaque_sp.get(), sb_addr.get());
return sb_addr;
}
void
SBFrame::Clear()
{
m_opaque_sp.reset();
}
SBValue
SBFrame::LookupVar (const char *var_name)
{
lldb::VariableSP var_sp;
if (m_opaque_sp && var_name && var_name[0])
{
lldb_private::VariableList variable_list;
SymbolContext sc (m_opaque_sp->GetSymbolContext (eSymbolContextBlock));
if (sc.block)
{
const bool can_create = true;
const bool get_parent_variables = true;
const bool stop_if_block_is_inlined_function = true;
if (sc.block->AppendVariables (can_create,
get_parent_variables,
stop_if_block_is_inlined_function,
&variable_list))
{
var_sp = variable_list.FindVariable (lldb_private::ConstString(var_name));
}
}
}
SBValue sb_value;
2010-10-30 12:51:46 +08:00
if (var_sp)
*sb_value = ValueObjectSP (new ValueObjectVariable (var_sp));
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::LookupVar (name=\"%s\") => SBValue(%p)",
m_opaque_sp.get(), var_name, sb_value.get());
return sb_value;
}
SBValue
SBFrame::LookupVarInScope (const char *var_name, const char *scope)
{
lldb::VariableSP var_sp;
if (m_opaque_sp && var_name && var_name[0] && scope && scope[0])
{
std::string scope_str = scope;
lldb::ValueType var_scope = eValueTypeInvalid;
// Convert scope_str to be all lowercase;
std::transform (scope_str.begin(), scope_str.end(), scope_str.begin(), ::tolower);
if (scope_str.compare ("global") == 0)
var_scope = eValueTypeVariableGlobal;
else if (scope_str.compare ("local") == 0)
var_scope = eValueTypeVariableLocal;
else if (scope_str.compare ("parameter") == 0)
var_scope = eValueTypeVariableArgument;
if (var_scope != eValueTypeInvalid)
{
lldb_private::VariableList *variable_list = m_opaque_sp->GetVariableList(true);
SymbolContext sc (m_opaque_sp->GetSymbolContext (eSymbolContextBlock));
const bool can_create = true;
const bool get_parent_variables = true;
const bool stop_if_block_is_inlined_function = true;
if (sc.block && sc.block->AppendVariables (can_create,
get_parent_variables,
stop_if_block_is_inlined_function,
variable_list))
{
lldb_private::ConstString const_var_name(var_name);
const uint32_t num_variables = variable_list->GetSize();
for (uint32_t i = 0; i < num_variables; ++i)
{
lldb::VariableSP curr_var_sp (variable_list->GetVariableAtIndex(i));
if (curr_var_sp && curr_var_sp->GetScope() == var_scope &&
curr_var_sp->GetName() == const_var_name)
{
var_sp = curr_var_sp;
break;
}
}
}
}
}
2010-10-30 12:51:46 +08:00
SBValue sb_value;
if (var_sp)
2010-10-30 12:51:46 +08:00
*sb_value = ValueObjectSP (new ValueObjectVariable (var_sp));
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::LookupVarInScope (name=\"%s\", scope=%s) => SBValue(%p)",
m_opaque_sp.get(), var_name, scope, sb_value.get());
return sb_value;
}
bool
SBFrame::operator == (const SBFrame &rhs) const
{
return m_opaque_sp.get() == rhs.m_opaque_sp.get();
}
bool
SBFrame::operator != (const SBFrame &rhs) const
{
return m_opaque_sp.get() != rhs.m_opaque_sp.get();
}
lldb_private::StackFrame *
SBFrame::operator->() const
{
return m_opaque_sp.get();
}
lldb_private::StackFrame *
SBFrame::get() const
{
return m_opaque_sp.get();
}
SBThread
SBFrame::GetThread () const
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBThread sb_thread;
if (m_opaque_sp)
sb_thread.SetThread (m_opaque_sp->GetThread().GetSP());
if (log)
{
SBStream sstr;
sb_thread.GetDescription (sstr);
2010-10-30 12:51:46 +08:00
log->Printf ("SBFrame(%p)::GetThread () => SBThread(%p): %s", m_opaque_sp.get(),
sb_thread.get(), sstr.GetData());
}
return sb_thread;
}
const char *
SBFrame::Disassemble () const
{
2010-10-30 12:51:46 +08:00
const char *disassembly = NULL;
if (m_opaque_sp)
disassembly = m_opaque_sp->Disassemble();
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::Disassemble () => %s", m_opaque_sp.get(), disassembly);
2010-10-30 12:51:46 +08:00
return disassembly;
}
SBValueList
SBFrame::GetVariables (bool arguments,
bool locals,
bool statics,
bool in_scope_only)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
2010-10-30 12:51:46 +08:00
log->Printf ("SBFrame(%p)::GetVariables (arguments=%i, locals=%i, statics=%i, in_scope_only=%i)",
m_opaque_sp.get(),
2010-10-30 12:51:46 +08:00
arguments,
locals,
statics,
in_scope_only);
SBValueList value_list;
if (m_opaque_sp)
{
size_t i;
VariableList *variable_list = m_opaque_sp->GetVariableList(true);
if (variable_list)
{
const size_t num_variables = variable_list->GetSize();
if (num_variables)
{
for (i = 0; i < num_variables; ++i)
{
VariableSP variable_sp (variable_list->GetVariableAtIndex(i));
if (variable_sp)
{
bool add_variable = false;
switch (variable_sp->GetScope())
{
case eValueTypeVariableGlobal:
case eValueTypeVariableStatic:
add_variable = statics;
break;
case eValueTypeVariableArgument:
add_variable = arguments;
break;
case eValueTypeVariableLocal:
add_variable = locals;
break;
default:
break;
}
if (add_variable)
{
if (in_scope_only && !variable_sp->IsInScope(m_opaque_sp.get()))
continue;
value_list.Append(m_opaque_sp->GetValueObjectForFrameVariable (variable_sp));
}
}
}
}
}
}
if (log)
{
2010-10-30 12:51:46 +08:00
log->Printf ("SBFrame(%p)::GetVariables (...) => SBValueList(%p)", m_opaque_sp.get(),
value_list.get());
}
return value_list;
}
lldb::SBValueList
SBFrame::GetRegisters ()
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
SBValueList value_list;
if (m_opaque_sp)
{
RegisterContext *reg_ctx = m_opaque_sp->GetRegisterContext();
if (reg_ctx)
{
const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx)
{
Fixed an expression parsing issue where if you were stopped somewhere without debug information and you evaluated an expression, a crash would occur as a result of an unchecked pointer. Added the ability to get the expression path for a ValueObject. For a rectangle point child "x" the expression path would be something like: "rect.top_left.x". This will allow GUI and command lines to get ahold of the expression path for a value object without having to explicitly know about the hierarchy. This means the ValueObject base class now has a "ValueObject *m_parent;" member. All ValueObject subclasses now correctly track their lineage and are able to provide value expression paths as well. Added a new "--flat" option to the "frame variable" to allow for flat variable output. An example of the current and new outputs: (lldb) frame variable argc = 1 argv = 0x00007fff5fbffe80 pt = { x = 2 y = 3 } rect = { bottom_left = { x = 1 y = 2 } top_right = { x = 3 y = 4 } } (lldb) frame variable --flat argc = 1 argv = 0x00007fff5fbffe80 pt.x = 2 pt.y = 3 rect.bottom_left.x = 1 rect.bottom_left.y = 2 rect.top_right.x = 3 rect.top_right.y = 4 As you can see when there is a lot of hierarchy it can help flatten things out. Also if you want to use a member in an expression, you can copy the text from the "--flat" output and not have to piece it together manually. This can help when you want to use parts of the STL in expressions: (lldb) frame variable --flat argc = 1 argv = 0x00007fff5fbffea8 hello_world._M_dataplus._M_p = 0x0000000000000000 (lldb) expr hello_world._M_dataplus._M_p[0] == '\0' llvm-svn: 116532
2010-10-15 06:52:14 +08:00
value_list.Append(ValueObjectSP (new ValueObjectRegisterSet (NULL, reg_ctx, set_idx)));
}
}
}
if (log)
2010-10-30 12:51:46 +08:00
log->Printf ("SBFrame(%p)::Registers () => SBValueList(%p)", m_opaque_sp.get(), value_list.get());
return value_list;
}
bool
SBFrame::GetDescription (SBStream &description)
{
if (m_opaque_sp)
{
Stream &s = description.ref();
m_opaque_sp->DumpUsingSettingsFormat (&s);
}
else
description.Printf ("No value");
return true;
}
lldb::SBValue
SBFrame::EvaluateExpression (const char *expr)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
LogSP expr_log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
2010-10-30 12:51:46 +08:00
lldb::SBValue expr_result;
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::EvaluateExpression (expr=\"%s\")...", m_opaque_sp.get(), expr);
if (m_opaque_sp)
{
Modified LLDB expressions to not have to JIT and run code just to see variable values or persistent expression variables. Now if an expression consists of a value that is a child of a variable, or of a persistent variable only, we will create a value object for it and make a ValueObjectConstResult from it to freeze the value (for program variables only, not persistent variables) and avoid running JITed code. For everything else we still parse up and JIT code and run it in the inferior. There was also a lot of clean up in the expression code. I made the ClangExpressionVariables be stored in collections of shared pointers instead of in collections of objects. This will help stop a lot of copy constructors on these large objects and also cleans up the code considerably. The persistent clang expression variables were moved over to the Target to ensure they persist across process executions. Added the ability for lldb_private::Target objects to evaluate expressions. We want to evaluate expressions at the target level in case we aren't running yet, or we have just completed running. We still want to be able to access the persistent expression variables between runs, and also evaluate constant expressions. Added extra logging to the dynamic loader plug-in for MacOSX. ModuleList objects can now dump their contents with the UUID, arch and full paths being logged with appropriate prefix values. Thread hardened the Communication class a bit by making the connection auto_ptr member into a shared pointer member and then making a local copy of the shared pointer in each method that uses it to make sure another thread can't nuke the connection object while it is being used by another thread. Added a new file to the lldb/test/load_unload test that causes the test a.out file to link to the libd.dylib file all the time. This will allow us to test using the DYLD_LIBRARY_PATH environment variable after moving libd.dylib somewhere else. llvm-svn: 121745
2010-12-14 10:59:59 +08:00
lldb::ExecutionResults exe_results;
const bool unwind_on_error = true;
exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr, m_opaque_sp.get(), unwind_on_error, *expr_result);
}
2010-10-30 12:51:46 +08:00
if (expr_log)
expr_log->Printf("** [SBFrame::EvaluateExpression] Expression result is %s, summary %s **", expr_result.GetValue(*this), expr_result.GetSummary(*this));
2010-10-30 12:51:46 +08:00
if (log)
log->Printf ("SBFrame(%p)::EvaluateExpression (expr=\"%s\") => SBValue(%p)", m_opaque_sp.get(), expr, expr_result.get());
2010-10-30 12:51:46 +08:00
return expr_result;
}