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.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@119885 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
index 0775b4f..f2d2bc9 100644
--- a/source/Expression/ClangExpressionDeclMap.cpp
+++ b/source/Expression/ClangExpressionDeclMap.cpp
@@ -1205,7 +1205,7 @@
}
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());
diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp
index 30381b0..df4170f 100644
--- a/source/Expression/DWARFExpression.cpp
+++ b/source/Expression/DWARFExpression.cpp
@@ -631,47 +631,37 @@
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 @@
) 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 @@
(
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
{
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 @@
// 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 @@
{
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 @@
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 @@
{
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 @@
{
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;