diff --git a/framework/common.cpp b/framework/common.cpp index 7166b25..440f6a8 100644 --- a/framework/common.cpp +++ b/framework/common.cpp @@ -191,8 +191,8 @@ bool __pst_context::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu } dwarf_value* v = stack.get(); + // dereference register location there if it is not last in stack if(v && (v->type & DWARF_TYPE_REGISTER_LOC)) { - // dereference register location unw_word_t value = 0; uint64_t regno = *((uint64_t*)v->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); } + // 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)) { log(SEVERITY_ERROR, "Failed to calculate %s(0x%lX, 0x%lX) operation", map->op_name, exprs[i].number, exprs[i].number2); return false; @@ -215,8 +238,7 @@ bool __pst_context::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu v->get_uint(value); if(v->type & DWARF_TYPE_REGISTER_LOC) { // dereference register location - uint64_t regno; - v->get_uint(regno); + uint64_t regno = value; if(unw_get_reg(&cursor, regno, &value)) { log(SEVERITY_ERROR, "Failed to get value of register 0x%lX", regno); return false; diff --git a/framework/common.h b/framework/common.h index ace8637..a6e32bb 100644 --- a/framework/common.h +++ b/framework/common.h @@ -100,6 +100,7 @@ typedef struct __dwarf_stack : public SC_ListHead { return value; } + Dwarf_Attribute* attr; // attribute which expression currently processed } dwarf_stack; typedef struct __pst_context { diff --git a/framework/dwarf_operations.cpp b/framework/dwarf_operations.cpp index 129181a..da1593e 100644 --- a/framework/dwarf_operations.cpp +++ b/framework/dwarf_operations.cpp @@ -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 // 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) { + // since in signal handler we are know SP value, just use it as DW_AT_frame_base unw_word_t sp; if(unw_get_reg(&ctx->cursor, UNW_REG_SP, &sp)) { return false; @@ -992,9 +992,7 @@ dwarf_op_map dw_op[] = { {DW_OP_bit_piece, "DW_OP_bit_piece", 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}, - - // 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 + // in fact, implementation is at upper layer since this operation contains sub-expression {DW_OP_GNU_entry_value, "DW_OP_GNU_entry_value", dw_op_notimpl}, };