right caculation of DW_OP_GNU_entry_value, use caller's information

This commit is contained in:
2020-01-26 15:36:33 +04:00
parent 898fa1e5e8
commit f9635841f6
4 changed files with 217 additions and 95 deletions
+22 -21
View File
@@ -1111,7 +1111,7 @@ bool __dwarf_stack::get_value(uint64_t& value)
uint64_t regno = value;
int ret = unw_get_reg(ctx->curr_frame, regno, &value);
if(ret) {
ctx->log(SEVERITY_ERROR, "Failed to get value of register 0x%X. Error: %d", __PRETTY_FUNCTION__, regno, ret);
ctx->log(SEVERITY_ERROR, "Failed to get value of register 0x%X. Error: %d", regno, ret);
return false;
}
} else if(v->type & DWARF_TYPE_MEMORY_LOC) {
@@ -1123,7 +1123,7 @@ bool __dwarf_stack::get_value(uint64_t& value)
return true;
}
bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr)
bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr, pst_function* fun)
{
clear();
for (int i = 0; i < expr_len; i++) {
@@ -1143,7 +1143,7 @@ bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
uint64_t regno = *((uint64_t*)v->value);
int ret = unw_get_reg(ctx->curr_frame, regno, &value);
if(ret) {
ctx->log(SEVERITY_ERROR, "Failed to ger value of register 0x%X. Error: %d", __PRETTY_FUNCTION__, regno, ret);
ctx->log(SEVERITY_ERROR, "Failed to ger value of register 0x%X. Error: %d", regno, ret);
return false;
}
v->replace(&value, sizeof(value), DWARF_TYPE_GENERIC);
@@ -1151,6 +1151,14 @@ bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
// handle there because it contains sub-expression of a Location in caller's frame
if(map->op_num == DW_OP_GNU_entry_value) {
if(!fun) {
ctx->log(SEVERITY_ERROR, "Cannot calculate DW_OP_GNU_entry_value expression while function is undefined");
return false;
}
if(!fun->parent) {
ctx->log(SEVERITY_ERROR, "Function has not parent while calculate DW_OP_GNU_entry_value expression");
return false;
}
// 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;
@@ -1158,26 +1166,19 @@ bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
Dwarf_Op *expr;
size_t exprlen;
if (dwarf_getlocation(&attr_mem, &expr, &exprlen) == 0) {
// save current frame cursor
unw_cursor_t* cursor = ctx->curr_frame; ctx->curr_frame = ctx->next_frame;
dwarf_stack st(ctx);
char str[1024]; str[0]= 0;
ctx->print_expr_block (expr, exprlen, str, sizeof(str), &attr_mem);
ctx->log(SEVERITY_DEBUG, "Parent frame expression: %s", str);
bool eret = st.calc_expression(expr, exprlen, &attr_mem);
uint64_t val = 0;
bool gret = false;
if(eret) {
gret = st.get_value(val);
}
// restore current frame cursor
ctx->curr_frame = cursor;
if(!eret || !gret) {
ctx->log(SEVERITY_ERROR, "Failed to calculate sub-expression for operation %s(0x%lX, 0x%lX)", map->op_name, exprs[i].number, exprs[i].number2);
pst_call_site* cs = fun->parent->find_call_site(fun);
if(!cs) {
ctx->log(SEVERITY_ERROR, "Failed to find call site while calculate DW_OP_GNU_entry_value expression");
return false;
}
ctx->log(SEVERITY_DEBUG, "DW_OP_GNU_entry_value calculated from caller frame = 0x%lX", val);
push(&val, sizeof(val), DWARF_TYPE_GENERIC);
pst_dwarf_expr loc; loc.setup(expr, exprlen);
pst_call_site_param* param = cs->find_param(loc);
if(!param) {
ctx->log(SEVERITY_ERROR, "Failed to find call site parameter while calculate DW_OP_GNU_entry_value expression");
return false;
}
push(&param->value, sizeof(param->value), DWARF_TYPE_GENERIC);
continue;
} else {