Change the DWARFExpression::Evaluate methods to take an optional

RegisterContext* - normally this is retrieved from the ExecutionContext's
StackFrame but when we need to evaluate an expression while creating
the stack frame list this can be a little tricky.

Add DW_OP_deref_size, needed for the _sigtramp FDE expression.

Add support for processing DWARF expressions in RegisterContextLLDB.

Update callers to DWARFExpression::Evaluate.

llvm-svn: 119885
This commit is contained in:
Jason Molenda 2010-11-20 01:28:30 +00:00
parent 40e78b4da0
commit 2d107dd02b
8 changed files with 180 additions and 46 deletions

View File

@ -201,6 +201,7 @@ public:
bool
Evaluate (ExecutionContext *exe_ctx,
clang::ASTContext *ast_context,
RegisterContext *reg_ctx,
lldb::addr_t loclist_base_load_addr,
const Value* initial_value_ptr,
Value& result,
@ -234,6 +235,13 @@ public:
/// expression. Can be NULL if the location expression uses no
/// external variables.
///
/// @param[in] reg_ctx
/// An optional parameter which provides a RegisterContext for use
/// when evaluating the expression (i.e. for fetching register values).
/// Normally this will come from the ExecutionContext's StackFrame but
/// in the case where an expression needs to be evaluated while building
/// the stack frame list, this short-cut is available.
///
/// @param[in] offset
/// The offset of the location expression in the data extractor.
///
@ -264,6 +272,7 @@ public:
const DataExtractor& opcodes,
ClangExpressionVariableList *expr_locals,
ClangExpressionDeclMap *decl_map,
RegisterContext *reg_ctx,
const uint32_t offset,
const uint32_t length,
const uint32_t reg_set,

View File

@ -104,6 +104,12 @@ public:
void
SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len);
const uint8_t *
GetDWARFExpressionBytes () { return m_location.expr.opcodes; }
int
GetDWARFExpressionLength () { return m_location.expr.length; }
void
Dump (Stream &s) const;

View File

@ -118,7 +118,7 @@ ValueObjectVariable::UpdateValue (ExecutionContextScope *exe_scope)
loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (exe_ctx.target);
}
Value old_value(m_value);
if (expr.Evaluate (&exe_ctx, GetClangAST(), loclist_base_load_addr, NULL, m_value, &m_error))
if (expr.Evaluate (&exe_ctx, GetClangAST(), NULL, loclist_base_load_addr, NULL, m_value, &m_error))
{
m_value.SetContext(Value::eContextTypeVariable, variable);

View File

@ -1205,7 +1205,7 @@ ClangExpressionDeclMap::GetVariableValue
}
Error err;
if (!var_location_expr.Evaluate(&exe_ctx, exe_ast_ctx, loclist_base_load_addr, NULL, *var_location.get(), &err))
if (!var_location_expr.Evaluate(&exe_ctx, exe_ast_ctx, NULL, loclist_base_load_addr, NULL, *var_location.get(), &err))
{
if (log)
log->Printf("Error evaluating location: %s", err.AsCString());

View File

@ -631,47 +631,37 @@ DWARFExpression::GetDescription (Stream *s, lldb::DescriptionLevel level, addr_t
static bool
ReadRegisterValueAsScalar
(
ExecutionContext *exe_ctx,
RegisterContext *reg_context,
uint32_t reg_kind,
uint32_t reg_num,
Error *error_ptr,
Value &value
)
{
if (exe_ctx && exe_ctx->frame)
if (reg_context == NULL)
{
RegisterContext *reg_context = exe_ctx->frame->GetRegisterContext();
if (reg_context == NULL)
{
if (error_ptr)
error_ptr->SetErrorStringWithFormat("No register context in frame.\n");
}
else
{
uint32_t native_reg = reg_context->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
if (native_reg == LLDB_INVALID_REGNUM)
{
if (error_ptr)
error_ptr->SetErrorStringWithFormat("Unable to convert register kind=%u reg_num=%u to a native register number.\n", reg_kind, reg_num);
}
else
{
value.SetValueType (Value::eValueTypeScalar);
value.SetContext (Value::eContextTypeRegisterInfo, const_cast<RegisterInfo *>(reg_context->GetRegisterInfoAtIndex(native_reg)));
if (reg_context->ReadRegisterValue (native_reg, value.GetScalar()))
return true;
if (error_ptr)
error_ptr->SetErrorStringWithFormat("Failed to read register %u.\n", native_reg);
}
}
if (error_ptr)
error_ptr->SetErrorStringWithFormat("No register context in frame.\n");
}
else
{
if (error_ptr)
error_ptr->SetErrorStringWithFormat("Invalid frame in execution context.\n");
uint32_t native_reg = reg_context->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num);
if (native_reg == LLDB_INVALID_REGNUM)
{
if (error_ptr)
error_ptr->SetErrorStringWithFormat("Unable to convert register kind=%u reg_num=%u to a native register number.\n", reg_kind, reg_num);
}
else
{
value.SetValueType (Value::eValueTypeScalar);
value.SetContext (Value::eContextTypeRegisterInfo, const_cast<RegisterInfo *>(reg_context->GetRegisterInfoAtIndex(native_reg)));
if (reg_context->ReadRegisterValue (native_reg, value.GetScalar()))
return true;
if (error_ptr)
error_ptr->SetErrorStringWithFormat("Failed to read register %u.\n", native_reg);
}
}
return false;
}
@ -766,7 +756,7 @@ DWARFExpression::Evaluate
) const
{
ExecutionContext exe_ctx (exe_scope);
return Evaluate(&exe_ctx, ast_context, loclist_base_load_addr, initial_value_ptr, result, error_ptr);
return Evaluate(&exe_ctx, ast_context, NULL, loclist_base_load_addr, initial_value_ptr, result, error_ptr);
}
bool
@ -774,6 +764,7 @@ DWARFExpression::Evaluate
(
ExecutionContext *exe_ctx,
clang::ASTContext *ast_context,
RegisterContext *reg_ctx,
lldb::addr_t loclist_base_load_addr,
const Value* initial_value_ptr,
Value& result,
@ -783,7 +774,11 @@ DWARFExpression::Evaluate
if (IsLocationList())
{
uint32_t offset = 0;
addr_t pc = exe_ctx->frame->GetRegisterContext()->GetPC();
addr_t pc;
if (reg_ctx)
pc = reg_ctx->GetPC();
else
pc = exe_ctx->frame->GetRegisterContext()->GetPC();
if (loclist_base_load_addr != LLDB_INVALID_ADDRESS)
{
@ -814,7 +809,7 @@ DWARFExpression::Evaluate
if (length > 0 && lo_pc <= pc && pc < hi_pc)
{
return DWARFExpression::Evaluate (exe_ctx, ast_context, m_data, m_expr_locals, m_decl_map, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr);
return DWARFExpression::Evaluate (exe_ctx, ast_context, m_data, m_expr_locals, m_decl_map, reg_ctx, offset, length, m_reg_kind, initial_value_ptr, result, error_ptr);
}
offset += length;
}
@ -826,7 +821,7 @@ DWARFExpression::Evaluate
}
// Not a location list, just a single expression.
return DWARFExpression::Evaluate (exe_ctx, ast_context, m_data, m_expr_locals, m_decl_map, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr);
return DWARFExpression::Evaluate (exe_ctx, ast_context, m_data, m_expr_locals, m_decl_map, reg_ctx, 0, m_data.GetByteSize(), m_reg_kind, initial_value_ptr, result, error_ptr);
}
@ -839,6 +834,7 @@ DWARFExpression::Evaluate
const DataExtractor& opcodes,
ClangExpressionVariableList *expr_locals,
ClangExpressionDeclMap *decl_map,
RegisterContext *reg_ctx,
const uint32_t opcodes_offset,
const uint32_t opcodes_length,
const uint32_t reg_kind,
@ -849,6 +845,9 @@ DWARFExpression::Evaluate
{
std::vector<Value> stack;
if (reg_ctx == NULL && exe_ctx && exe_ctx->frame)
reg_ctx = exe_ctx->frame->GetRegisterContext();
if (initial_value_ptr)
stack.push_back(*initial_value_ptr);
@ -1015,9 +1014,86 @@ DWARFExpression::Evaluate
// on the expression stack.
//----------------------------------------------------------------------
case DW_OP_deref_size:
if (error_ptr)
error_ptr->SetErrorString("Unimplemented opcode: DW_OP_deref_size.");
return false;
{
uint8_t size = opcodes.GetU8(&offset);
Value::ValueType value_type = stack.back().GetValueType();
switch (value_type)
{
case Value::eValueTypeHostAddress:
{
void *src = (void *)stack.back().GetScalar().ULongLong();
intptr_t ptr;
::memcpy (&ptr, src, sizeof(void *));
// I can't decide whether the size operand should apply to the bytes in their
// lldb-host endianness or the target endianness.. I doubt this'll ever come up
// but I'll opt for assuming big endian regardless.
switch (size)
{
case 1: ptr = ptr & 0xff; break;
case 2: ptr = ptr & 0xffff; break;
case 3: ptr = ptr & 0xffffff; break;
case 4: ptr = ptr & 0xffffffff; break;
case 5: ptr = ptr & 0xffffffffff; break;
case 6: ptr = ptr & 0xffffffffffff; break;
case 7: ptr = ptr & 0xffffffffffffff; break;
default: break;
}
stack.back().GetScalar() = ptr;
stack.back().ClearContext();
}
break;
case Value::eValueTypeLoadAddress:
if (exe_ctx)
{
if (exe_ctx->process)
{
lldb::addr_t pointer_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
uint8_t addr_bytes[sizeof(lldb::addr_t)];
Error error;
if (exe_ctx->process->ReadMemory(pointer_addr, &addr_bytes, size, error) == size)
{
DataExtractor addr_data(addr_bytes, sizeof(addr_bytes), exe_ctx->process->GetByteOrder(), size);
uint32_t addr_data_offset = 0;
switch (size)
{
case 1: stack.back().GetScalar() = addr_data.GetU8(&addr_data_offset); break;
case 2: stack.back().GetScalar() = addr_data.GetU16(&addr_data_offset); break;
case 4: stack.back().GetScalar() = addr_data.GetU32(&addr_data_offset); break;
case 8: stack.back().GetScalar() = addr_data.GetU64(&addr_data_offset); break;
default: stack.back().GetScalar() = addr_data.GetPointer(&addr_data_offset);
}
stack.back().ClearContext();
}
else
{
if (error_ptr)
error_ptr->SetErrorStringWithFormat ("Failed to dereference pointer from 0x%llx for DW_OP_deref: %s\n",
pointer_addr,
error.AsCString());
return false;
}
}
else
{
if (error_ptr)
error_ptr->SetErrorStringWithFormat ("NULL process for DW_OP_deref.\n");
return false;
}
}
else
{
if (error_ptr)
error_ptr->SetErrorStringWithFormat ("NULL execution context for DW_OP_deref.\n");
return false;
}
break;
default:
break;
}
}
break;
//----------------------------------------------------------------------
// OPCODE: DW_OP_xderef_size
@ -1837,7 +1913,7 @@ DWARFExpression::Evaluate
{
reg_num = op - DW_OP_reg0;
if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
stack.push_back(tmp);
else
return false;
@ -1852,7 +1928,7 @@ DWARFExpression::Evaluate
case DW_OP_regx:
{
reg_num = opcodes.GetULEB128(&offset);
if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
stack.push_back(tmp);
else
return false;
@ -1901,7 +1977,7 @@ DWARFExpression::Evaluate
{
reg_num = op - DW_OP_breg0;
if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
{
int64_t breg_offset = opcodes.GetSLEB128(&offset);
tmp.ResolveValue(exe_ctx, ast_context) += (uint64_t)breg_offset;
@ -1924,7 +2000,7 @@ DWARFExpression::Evaluate
{
reg_num = opcodes.GetULEB128(&offset);
if (ReadRegisterValueAsScalar (exe_ctx, reg_kind, reg_num, error_ptr, tmp))
if (ReadRegisterValueAsScalar (reg_ctx, reg_kind, reg_num, error_ptr, tmp))
{
int64_t breg_offset = opcodes.GetSLEB128(&offset);
tmp.ResolveValue(exe_ctx, ast_context) += (uint64_t)breg_offset;

View File

@ -22,6 +22,10 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Utility/ArchVolatileRegs.h"
#include "lldb/Core/Log.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Core/Value.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/StackFrame.h"
using namespace lldb;
using namespace lldb_private;
@ -814,7 +818,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
UnwindPlan::Row::RegisterLocation unwindplan_regloc;
bool have_unwindplan_regloc = false;
int unwindplan_registerkind;
int unwindplan_registerkind = -1;
if (m_fast_unwind_plan)
{
@ -995,6 +999,44 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
return true;
}
if (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression())
{
DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
unwindplan_regloc.GetDWARFExpressionLength(),
m_thread.GetProcess().GetByteOrder(), m_thread.GetProcess().GetAddressByteSize());
DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind (unwindplan_registerkind);
ExecutionContext exe_ctx (&m_thread.GetProcess(), &m_thread, NULL);
Value result;
Error error;
if (dwarfexpr.Evaluate (&exe_ctx, NULL, this, 0, NULL, result, &error))
{
addr_t val;
val = result.GetScalar().ULongLong();
if (unwindplan_regloc.IsDWARFExpression())
{
regloc.type = eRegisterValueInferred;
regloc.location.register_value = val;
m_registers[lldb_regnum] = regloc;
return true;
}
else
{
regloc.type = eRegisterSavedAtMemoryLocation;
regloc.location.target_memory_location = val;
m_registers[lldb_regnum] = regloc;
return true;
}
}
if (log)
{
log->Printf("%*sFrame %d tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
lldb_regnum);
}
return false;
}
if (log)
{
log->Printf("%*sFrame %d could not supply caller's reg %d location",

View File

@ -1225,6 +1225,7 @@ SymbolFileDWARF::ParseChildMembers
debug_info_data,
NULL,
NULL,
NULL,
block_offset,
block_length,
eRegisterKindDWARF,

View File

@ -496,7 +496,7 @@ StackFrame::GetFrameBaseValue (Scalar &frame_base, Error *error_ptr)
if (m_sc.function->GetFrameBaseExpression().IsLocationList())
loclist_base_addr = m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (&m_thread.GetProcess().GetTarget());
if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, NULL, loclist_base_addr, NULL, expr_value, &m_frame_base_error) == false)
if (m_sc.function->GetFrameBaseExpression().Evaluate(&exe_ctx, 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.