move calc_expression() & get_value() from context to DWARF stack

This commit is contained in:
2020-01-14 12:21:00 +04:00
parent 5ee3935dc2
commit fc6a81b460
6 changed files with 344 additions and 337 deletions
-77
View File
@@ -180,83 +180,6 @@ uint32_t __pst_context::print_expr_block (Dwarf_Op *exprs, int len, char* buff,
return offset;
}
bool __pst_context::get_value(uint64_t& value)
{
if(!stack.Size()) {
return false;
}
value = 0;
dwarf_value* v = stack.get();
v->get_uint(value);
if(v->type & DWARF_TYPE_REGISTER_LOC) {
// dereference register location
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;
}
}
return true;
}
bool __pst_context::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr)
{
stack.clear();
for (int i = 0; i < expr_len; i++) {
const dwarf_op_map* map = find_op_map(exprs[i].atom);
if(!map) {
log(SEVERITY_ERROR, "Unknown operation type 0x%hhX(0x%lX, 0x%lX)", exprs[i].atom, exprs[i].number, exprs[i].number2);
return false;
}
dwarf_value* v = stack.get();
// dereference register location there if it is not last in stack
if(v && (v->type & DWARF_TYPE_REGISTER_LOC)) {
unw_word_t value = 0;
uint64_t regno = *((uint64_t*)v->value);
if(unw_get_reg(&cursor, regno, &value)) {
log(SEVERITY_ERROR, "Failed to ger value of register 0x%lX", regno);
return false;
}
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;
}
continue;
} 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;
}
}
return true;
}
bool is_location_form(int form)
{
if (form == DW_FORM_block1 || form == DW_FORM_block2 || form == DW_FORM_block4 || form == DW_FORM_block ||