added DW_OP_GNU_entry_value operation handling
This commit is contained in:
+25
-3
@@ -191,8 +191,8 @@ bool __pst_context::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
|
|||||||
}
|
}
|
||||||
|
|
||||||
dwarf_value* v = stack.get();
|
dwarf_value* v = stack.get();
|
||||||
|
// dereference register location there if it is not last in stack
|
||||||
if(v && (v->type & DWARF_TYPE_REGISTER_LOC)) {
|
if(v && (v->type & DWARF_TYPE_REGISTER_LOC)) {
|
||||||
// dereference register location
|
|
||||||
unw_word_t value = 0;
|
unw_word_t value = 0;
|
||||||
uint64_t regno = *((uint64_t*)v->value);
|
uint64_t regno = *((uint64_t*)v->value);
|
||||||
if(unw_get_reg(&cursor, regno, &value)) {
|
if(unw_get_reg(&cursor, regno, &value)) {
|
||||||
@@ -202,6 +202,29 @@ bool __pst_context::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
|
|||||||
v->replace(&value, sizeof(value), DWARF_TYPE_GENERIC);
|
v->replace(&value, sizeof(value), DWARF_TYPE_GENERIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle there because it contains sub-expression of Location
|
||||||
|
if(map->op_num == DW_OP_GNU_entry_value) {
|
||||||
|
// This opcode has two operands, the first one is uleb128 length and the second is block of that length, containing either a
|
||||||
|
// simple register or DWARF expression
|
||||||
|
Dwarf_Attribute attr_mem;
|
||||||
|
if(!dwarf_getlocation_attr(attr, exprs, &attr_mem)) {
|
||||||
|
Dwarf_Op *expr;
|
||||||
|
size_t exprlen;
|
||||||
|
if (dwarf_getlocation(&attr_mem, &expr, &exprlen) == 0) {
|
||||||
|
//offset += print_expr_block (expr, exprlen, buff + offset, buff_size - offset, &attr_mem);
|
||||||
|
//offset += snprintf(buff + offset, buff_size - offset, ") ");
|
||||||
|
if(!calc_expression(expr, exprlen, &attr_mem)) {
|
||||||
|
log(SEVERITY_ERROR, "Failed to calculate sub-expression for operation %s(0x%lX, 0x%lX)", map->op_name, exprs[i].number, exprs[i].number2);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr location");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr expression");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!map->operation(this, map, exprs[i].number, exprs[i].number2)) {
|
if(!map->operation(this, map, exprs[i].number, exprs[i].number2)) {
|
||||||
log(SEVERITY_ERROR, "Failed to calculate %s(0x%lX, 0x%lX) operation", map->op_name, exprs[i].number, exprs[i].number2);
|
log(SEVERITY_ERROR, "Failed to calculate %s(0x%lX, 0x%lX) operation", map->op_name, exprs[i].number, exprs[i].number2);
|
||||||
return false;
|
return false;
|
||||||
@@ -215,8 +238,7 @@ bool __pst_context::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
|
|||||||
v->get_uint(value);
|
v->get_uint(value);
|
||||||
if(v->type & DWARF_TYPE_REGISTER_LOC) {
|
if(v->type & DWARF_TYPE_REGISTER_LOC) {
|
||||||
// dereference register location
|
// dereference register location
|
||||||
uint64_t regno;
|
uint64_t regno = value;
|
||||||
v->get_uint(regno);
|
|
||||||
if(unw_get_reg(&cursor, regno, &value)) {
|
if(unw_get_reg(&cursor, regno, &value)) {
|
||||||
log(SEVERITY_ERROR, "Failed to get value of register 0x%lX", regno);
|
log(SEVERITY_ERROR, "Failed to get value of register 0x%lX", regno);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ typedef struct __dwarf_stack : public SC_ListHead {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dwarf_Attribute* attr; // attribute which expression currently processed
|
||||||
} dwarf_stack;
|
} dwarf_stack;
|
||||||
|
|
||||||
typedef struct __pst_context {
|
typedef struct __pst_context {
|
||||||
|
|||||||
@@ -804,9 +804,9 @@ bool dw_op_call_frame_cfa(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word
|
|||||||
|
|
||||||
// The DW_OP_fbreg operation provides a signed LEB128 offset from the address specified by the location description in the DW_AT_frame_base
|
// The DW_OP_fbreg operation provides a signed LEB128 offset from the address specified by the location description in the DW_AT_frame_base
|
||||||
// attribute of the current function. This is typically a stack pointer register plus or minus some offset
|
// attribute of the current function. This is typically a stack pointer register plus or minus some offset
|
||||||
// since in signal handler we are know SP value, just use it as DW_AT_frame_base
|
|
||||||
bool dw_op_fbreg(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
bool dw_op_fbreg(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||||
{
|
{
|
||||||
|
// since in signal handler we are know SP value, just use it as DW_AT_frame_base
|
||||||
unw_word_t sp;
|
unw_word_t sp;
|
||||||
if(unw_get_reg(&ctx->cursor, UNW_REG_SP, &sp)) {
|
if(unw_get_reg(&ctx->cursor, UNW_REG_SP, &sp)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -992,9 +992,7 @@ dwarf_op_map dw_op[] = {
|
|||||||
{DW_OP_bit_piece, "DW_OP_bit_piece", dw_op_notimpl},
|
{DW_OP_bit_piece, "DW_OP_bit_piece", dw_op_notimpl},
|
||||||
{DW_OP_implicit_value, "DW_OP_implicit_value", dw_op_notimpl},
|
{DW_OP_implicit_value, "DW_OP_implicit_value", dw_op_notimpl},
|
||||||
{DW_OP_stack_value, "DW_OP_stack_value", dw_op_stack_value},
|
{DW_OP_stack_value, "DW_OP_stack_value", dw_op_stack_value},
|
||||||
|
// in fact, implementation is at upper layer since this operation contains sub-expression
|
||||||
// This opcode has two operands, the first one is uleb128 length and the second is block of that length, containing either a
|
|
||||||
// simple register or DWARF expression
|
|
||||||
{DW_OP_GNU_entry_value, "DW_OP_GNU_entry_value", dw_op_notimpl},
|
{DW_OP_GNU_entry_value, "DW_OP_GNU_entry_value", dw_op_notimpl},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user