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; 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) bool is_location_form(int form)
{ {
if (form == DW_FORM_block1 || form == DW_FORM_block2 || form == DW_FORM_block4 || form == DW_FORM_block || if (form == DW_FORM_block1 || form == DW_FORM_block2 || form == DW_FORM_block4 || form == DW_FORM_block ||
-98
View File
@@ -8,101 +8,6 @@
#include "logger/log.h" #include "logger/log.h"
#include "linkedlist.h" #include "linkedlist.h"
typedef enum {
DWARF_TYPE_INVALID = 0, // no type
DWARF_TYPE_SIGNED = 1, // signed type
DWARF_TYPE_UNSIGNED = 2, // unsigned type
DWARF_TYPE_CONST = 4, // constant signed/unsigned type
DWARF_TYPE_GENERIC = 8, // size of machine address type
DWARF_TYPE_CHAR = 16, // 1 byte size
DWARF_TYPE_FLOAT = 32, // machine-dependent floating point size
DWARF_TYPE_REGISTER_LOC = 64, // value located in register specified as 'value'
DWARF_TYPE_MEMORY_LOC = 128, // value located in memory address specified as 'value'
DWARF_TYPE_PIECE = 256, // piece of whole value located in current value
DWARF_TYPE_SHORT = 512, // 2 byte size
DWARF_TYPE_INT = 1024, // 4 byte size
DWARF_TYPE_LONG = 2048 // 8 byte size
} dwarf_value_type;
typedef struct __dwarf_value : public SC_ListNode {
__dwarf_value(char*v, uint32_t s, int t)
{
size = s;
value = (char*)malloc(s);
memcpy(value, v, s);
type = t;
}
~__dwarf_value()
{
if(value) {
free(value);
value = NULL;
size = 0;
}
}
void replace(void* v, uint32_t s, int t)
{
if(value) {
free(value);
size = 0;
type = DWARF_TYPE_INVALID;
}
value = (char*)malloc(s);
memcpy(value, v, s);
size = s;
type = t;
}
bool get_uint(uint64_t& v);
bool get_int(int64_t& v);
bool get_generic(uint64_t& v);
char* value;
uint32_t size; // size in bytes except of 'DWARF_TYPE_PIECE', in such case in bits
int type; // bitmask of DWARF_TYPE_XXX
} dwarf_value;
typedef struct __dwarf_stack : public SC_ListHead {
void clear() {
for(dwarf_value* v = (dwarf_value*)First(); v; v = (dwarf_value*)First()) {
Remove(v);
delete v;
}
}
void push(void* v, uint32_t s, int t) {
dwarf_value* value = new dwarf_value((char*)v, s, t);
InsertFirst(value);
}
void push(dwarf_value* value) {
InsertFirst(value);
}
dwarf_value* pop() {
dwarf_value* value = (dwarf_value*)First();
if(value) {
Remove(value);
}
return value;
}
dwarf_value* get(uint32_t idx = 0) {
dwarf_value* value = NULL;
for(value = (dwarf_value*)First(); value && idx; value = (dwarf_value*)Next(value)) {
idx--;
}
return value;
}
Dwarf_Attribute* attr; // attribute which expression currently processed
} dwarf_stack;
typedef struct __pst_context { typedef struct __pst_context {
__pst_context(ucontext_t* hctx) : hcontext(hctx) __pst_context(ucontext_t* hctx) : hcontext(hctx)
{ {
@@ -114,13 +19,10 @@ typedef struct __pst_context {
bool print(const char* fmt, ...); bool print(const char* fmt, ...);
void log(SC_LogSeverity severity, const char*fmt, ...); void log(SC_LogSeverity severity, const char*fmt, ...);
uint32_t print_expr_block(Dwarf_Op *exprs, int len, char* buff, uint32_t buff_size, Dwarf_Attribute* attr = 0); uint32_t print_expr_block(Dwarf_Op *exprs, int len, char* buff, uint32_t buff_size, Dwarf_Attribute* attr = 0);
bool calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr);
bool get_value(uint64_t& value);
ucontext_t* hcontext; // context of signal handler ucontext_t* hcontext; // context of signal handler
unw_context_t context; // context of stack trace unw_context_t context; // context of stack trace
unw_cursor_t cursor; // currently examined frame of context unw_cursor_t cursor; // currently examined frame of context
dwarf_stack stack;
Dwarf_Addr base_addr; // base address where process loaded Dwarf_Addr base_addr; // base address where process loaded
char buff[8192]; // stack trace buffer char buff[8192]; // stack trace buffer
+230 -153
View File
@@ -86,29 +86,29 @@ dwarf_reg_map reg_map[] = {
}; };
// not implemented operations // not implemented operations
bool dw_op_notimpl(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_notimpl(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
ctx->log(SEVERITY_ERROR, "%s(0x%lX, 0x%lX) operation is not implemented", map->op_name, op1, op2); stack->ctx->log(SEVERITY_ERROR, "%s(0x%lX, 0x%lX) operation is not implemented", map->op_name, op1, op2);
return false; return false;
} }
// The DW_OP_addr operation has a single operand that encodes a machine // The DW_OP_addr operation has a single operand that encodes a machine
// address and whose size is the size of an address on the target machine. // address and whose size is the size of an address on the target machine.
bool dw_op_addr(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_addr(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
ctx->stack.push(&op1, sizeof(op1), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC); stack->push(&op1, sizeof(op1), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC);
return true; return true;
} }
// The DW_ OP_deref operation pops the top stack entry and treats it as an address. // The DW_ OP_deref operation pops the top stack entry and treats it as an address.
// The popped value must have an integral type. The value retrieved from that address is pushed, and has the generic type. // The popped value must have an integral type. The value retrieved from that address is pushed, and has the generic type.
// The size of the data retrieved from the dereferenced address is the size of an address on the target machine. // The size of the data retrieved from the dereferenced address is the size of an address on the target machine.
bool dw_op_deref(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_deref(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value = ctx->stack.pop(); dwarf_value* value = stack->pop();
if(value) { if(value) {
uint64_t v = *((uint64_t*)value->value); uint64_t v = *((uint64_t*)value->value);
ctx->stack.push(&v, sizeof(v), DWARF_TYPE_GENERIC); stack->push(&v, sizeof(v), DWARF_TYPE_GENERIC);
return true; return true;
} }
@@ -118,7 +118,7 @@ bool dw_op_deref(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwar
// DW_OP_const1u, DW_OP_const2u, DW_OP_const4u, DW_OP_const8u. The single operand of a DW_OP_const<n>u operation provides a 1, 2, 4, or 8-byte unsigned integer constant, respectively. // DW_OP_const1u, DW_OP_const2u, DW_OP_const4u, DW_OP_const8u. The single operand of a DW_OP_const<n>u operation provides a 1, 2, 4, or 8-byte unsigned integer constant, respectively.
// These operations push a value with the generic type // These operations push a value with the generic type
bool dw_op_const_x_u(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_const_x_u(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
uint8_t size = 0; uint8_t size = 0;
dwarf_value_type type = DWARF_TYPE_UNSIGNED; dwarf_value_type type = DWARF_TYPE_UNSIGNED;
@@ -143,14 +143,14 @@ bool dw_op_const_x_u(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1,
return false; return false;
} }
ctx->stack.push(&op1, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC); stack->push(&op1, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
return true; return true;
} }
// DW_OP_const1s, DW_OP_const2s, DW_OP_const4s, DW_OP_const8s. The single operand of a DW_OP_const<n>s operation provides a 1, 2, 4, or 8-byte signed integer constant, respectively. // DW_OP_const1s, DW_OP_const2s, DW_OP_const4s, DW_OP_const8s. The single operand of a DW_OP_const<n>s operation provides a 1, 2, 4, or 8-byte signed integer constant, respectively.
// These operations push a value with the generic type // These operations push a value with the generic type
bool dw_op_const_x_s(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_const_x_s(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
uint8_t size; int64_t v; uint8_t size; int64_t v;
dwarf_value_type type = DWARF_TYPE_SIGNED; dwarf_value_type type = DWARF_TYPE_SIGNED;
@@ -179,40 +179,40 @@ bool dw_op_const_x_s(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1,
return false; return false;
} }
ctx->stack.push(&v, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC); stack->push(&v, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
return true; return true;
} }
// The single operand of the DW_OP_constu operation provides an unsigned LEB128 integer constant. // The single operand of the DW_OP_constu operation provides an unsigned LEB128 integer constant.
bool dw_op_constu(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_constu(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
uint64_t value = decode_uleb128((unsigned char*)&op1); uint64_t value = decode_uleb128((unsigned char*)&op1);
ctx->stack.push(&value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_UNSIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC); stack->push(&value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_UNSIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
return true; return true;
} }
bool dw_op_consts(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_consts(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
// The single operand of the DW_OP_consts operation provides a signed LEB128 integer constant. // The single operand of the DW_OP_consts operation provides a signed LEB128 integer constant.
int64_t value = decode_sleb128((unsigned char*)&op1); int64_t value = decode_sleb128((unsigned char*)&op1);
ctx->stack.push(&value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_SIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC); stack->push(&value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_SIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
return true; return true;
} }
// The DW_OP_dup operation duplicates the value (including its type identifier) at the top of the stack. // The DW_OP_dup operation duplicates the value (including its type identifier) at the top of the stack.
bool dw_op_dup(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_dup(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value = ctx->stack.get(); dwarf_value* value = stack->get();
ctx->stack.push(value->value, value->size, value->type); stack->push(value->value, value->size, value->type);
return true; return true;
} }
// The DW_OP_drop operation pops the value (including its type identifier) at the top of the stack. // The DW_OP_drop operation pops the value (including its type identifier) at the top of the stack.
bool dw_op_drop(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_drop(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value = ctx->stack.pop(); dwarf_value* value = stack->pop();
free(value); free(value);
return true; return true;
@@ -220,21 +220,21 @@ bool dw_op_drop(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf
// The DW_OP_over operation duplicates the entry currently second in the stack at the top of the stack. // The DW_OP_over operation duplicates the entry currently second in the stack at the top of the stack.
// This is equivalent to a DW_OP_pick operation, with index 1. // This is equivalent to a DW_OP_pick operation, with index 1.
bool dw_op_over(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_over(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value = ctx->stack.get(1); dwarf_value* value = stack->get(1);
ctx->stack.push(value->value, value->size, value->type); stack->push(value->value, value->size, value->type);
return true; return true;
} }
// The single operand of the DW_OP_pick operation provides a 1-byte index. // The single operand of the DW_OP_pick operation provides a 1-byte index.
// A copy of the stack entry (including its type identifier) with the specified index (0 through 255, inclusive) is pushed onto the stack. // A copy of the stack entry (including its type identifier) with the specified index (0 through 255, inclusive) is pushed onto the stack.
bool dw_op_pick(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_pick(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value = ctx->stack.get(op1); dwarf_value* value = stack->get(op1);
if(value) { if(value) {
ctx->stack.push(value->value, value->size, value->type); stack->push(value->value, value->size, value->type);
return true; return true;
} }
@@ -243,13 +243,13 @@ bool dw_op_pick(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf
// The DW_OP_swap operation swaps the top two stack entries. The entry at the top of the stack (including its type identifier) becomes the second stack // The DW_OP_swap operation swaps the top two stack entries. The entry at the top of the stack (including its type identifier) becomes the second stack
// entry, and the second entry (including its type identifier) becomes the top of the stack. // entry, and the second entry (including its type identifier) becomes the top of the stack.
bool dw_op_swap(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_swap(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value1 = ctx->stack.pop(); dwarf_value* value1 = stack->pop();
dwarf_value* value2 = ctx->stack.pop(); dwarf_value* value2 = stack->pop();
if(value1 && value2) { if(value1 && value2) {
ctx->stack.push(value1); stack->push(value1);
ctx->stack.push(value2); stack->push(value2);
return true; return true;
} }
@@ -267,15 +267,15 @@ bool dw_op_swap(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf
// The entry at the top of the stack (including its type identifier) becomes the third stack entry, // The entry at the top of the stack (including its type identifier) becomes the third stack entry,
// the second entry (including its type identifier) becomes the top of the stack, // the second entry (including its type identifier) becomes the top of the stack,
// and the third entry (including its type identifier) becomes the second entry // and the third entry (including its type identifier) becomes the second entry
bool dw_op_rot(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_rot(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value1 = ctx->stack.pop(); dwarf_value* value1 = stack->pop();
dwarf_value* value2 = ctx->stack.pop(); dwarf_value* value2 = stack->pop();
dwarf_value* value3 = ctx->stack.pop(); dwarf_value* value3 = stack->pop();
if(value1 && value2 && value3) { if(value1 && value2 && value3) {
ctx->stack.push(value1); stack->push(value1);
ctx->stack.push(value3); stack->push(value3);
ctx->stack.push(value2); stack->push(value2);
return true; return true;
} }
@@ -294,13 +294,13 @@ bool dw_op_rot(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_
// The DW_OP_abs operation pops the top stack entry, interprets it as a signed value and pushes its absolute value. // The DW_OP_abs operation pops the top stack entry, interprets it as a signed value and pushes its absolute value.
// If the absolute value cannot be represented, the result is undefined. // If the absolute value cannot be represented, the result is undefined.
bool dw_op_abs(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_abs(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value = ctx->stack.get(); dwarf_value* value = stack->get();
if(value) { if(value) {
int64_t v; int64_t v;
if(!value->get_int(v)) { if(!value->get_int(v)) {
ctx->log(SEVERITY_ERROR, "Wrong %d size of stack value", value->size); stack->ctx->log(SEVERITY_ERROR, "Wrong %d size of stack value", value->size);
return false; return false;
} }
uint64_t res = llabs(v); uint64_t res = llabs(v);
@@ -311,28 +311,28 @@ bool dw_op_abs(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_
} }
// The DW_OP_and operation pops the top two stack values, performs a bitwise and operation on the two, and pushes the result. // The DW_OP_and operation pops the top two stack values, performs a bitwise and operation on the two, and pushes the result.
bool dw_op_and(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_and(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value1 = ctx->stack.get(0); dwarf_value* value1 = stack->get(0);
dwarf_value* value2 = ctx->stack.get(1); dwarf_value* value2 = stack->get(1);
if(value1 && value2) { if(value1 && value2) {
if(!(value1->type & value2->type)) { if(!(value1->type & value2->type)) {
ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%0x%X, %0x%X)", map->op_name, value1->type, value2->type); stack->ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%0x%X, %0x%X)", map->op_name, value1->type, value2->type);
return false; return false;
} }
uint64_t v1 = 0, v2 = 0; uint64_t v1 = 0, v2 = 0;
if(!value1->get_generic(v1)) { if(!value1->get_generic(v1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(!value2->get_generic(v2)) { if(!value2->get_generic(v2)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
uint64_t res = v1 & v2; uint64_t res = v1 & v2;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, value1->size, DWARF_TYPE_GENERIC); stack->push(&res, value1->size, DWARF_TYPE_GENERIC);
return true; return true;
} }
@@ -340,84 +340,84 @@ bool dw_op_and(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_
} }
// The DW_OP_div operation pops the top two stack values, divides the former second entry by the former top of the stack using signed division, and pushes the result. // The DW_OP_div operation pops the top two stack values, divides the former second entry by the former top of the stack using signed division, and pushes the result.
bool dw_op_div(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_div(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value1 = ctx->stack.get(0); dwarf_value* value1 = stack->get(0);
dwarf_value* value2 = ctx->stack.get(1); dwarf_value* value2 = stack->get(1);
if(value1 && value2) { if(value1 && value2) {
if(!(value1->type & value2->type)) { if(!(value1->type & value2->type)) {
ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%0x%X, %0x%X)", map->op_name, value1->type, value2->type); stack->ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%0x%X, %0x%X)", map->op_name, value1->type, value2->type);
return false; return false;
} }
if(value2->type & DWARF_TYPE_SIGNED) { if(value2->type & DWARF_TYPE_SIGNED) {
int64_t sig2; int64_t sig2;
if(!value2->get_int(sig2)) { if(!value2->get_int(sig2)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(value1->type & DWARF_TYPE_SIGNED) { if(value1->type & DWARF_TYPE_SIGNED) {
int64_t sig1; int64_t sig1;
if(!value1->get_int(sig1)) { if(!value1->get_int(sig1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(sig1 == 0) { if(sig1 == 0) {
ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig2); stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig2);
return false; return false;
} }
uint64_t res = sig2 / sig1; uint64_t res = sig2 / sig1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC); stack->push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
return true; return true;
} else { } else {
uint64_t unsig1; uint64_t unsig1;
if(!value1->get_uint(unsig1)) { if(!value1->get_uint(unsig1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(unsig1 == 0) { if(unsig1 == 0) {
ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, sig2); stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, sig2);
return false; return false;
} }
int64_t res = sig2 / unsig1; int64_t res = sig2 / unsig1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC); stack->push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
return true; return true;
} }
} else { } else {
uint64_t unsig2; uint64_t unsig2;
if(!value2->get_uint(unsig2)) { if(!value2->get_uint(unsig2)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(value1->type & DWARF_TYPE_SIGNED) { if(value1->type & DWARF_TYPE_SIGNED) {
int64_t sig1; int64_t sig1;
if(!value1->get_int(sig1)) { if(!value1->get_int(sig1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(sig1 == 0) { if(sig1 == 0) {
ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig1); stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig1);
return false; return false;
} }
int64_t res = unsig2 / sig1; int64_t res = unsig2 / sig1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC); stack->push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
return true; return true;
} else { } else {
uint64_t unsig1; uint64_t unsig1;
if(!value1->get_uint(unsig1)) { if(!value1->get_uint(unsig1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(unsig1 == 0) { if(unsig1 == 0) {
ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, unsig2); stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, unsig2);
return false; return false;
} }
uint64_t res = unsig2 / unsig1; uint64_t res = unsig2 / unsig1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC); stack->push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
return true; return true;
} }
} }
@@ -427,23 +427,23 @@ bool dw_op_div(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_
} }
// The DW_OP_minus operation pops the top two stack values, subtracts the former top of the stack from the former second entry, and pushes the result. // The DW_OP_minus operation pops the top two stack values, subtracts the former top of the stack from the former second entry, and pushes the result.
bool dw_op_minus(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_minus(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value1 = ctx->stack.get(0); dwarf_value* value1 = stack->get(0);
dwarf_value* value2 = ctx->stack.get(1); dwarf_value* value2 = stack->get(1);
if(value1 && value2) { if(value1 && value2) {
if(!(value1->type & value2->type)) { if(!(value1->type & value2->type)) {
ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%d, %d)", map->op_name, value1->type, value2->type); stack->ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%d, %d)", map->op_name, value1->type, value2->type);
return false; return false;
} }
// use arithmetic by modulo 1 plus // use arithmetic by modulo 1 plus
uint64_t unsig1; uint64_t unsig2; uint64_t unsig1; uint64_t unsig2;
if(!value1->get_uint(unsig1)) { if(!value1->get_uint(unsig1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(!value2->get_uint(unsig2)) { if(!value2->get_uint(unsig2)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value2->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value2->size);
return false; return false;
} }
int res_type = DWARF_TYPE_GENERIC; int res_type = DWARF_TYPE_GENERIC;
@@ -451,8 +451,8 @@ bool dw_op_minus(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwar
res_type |= DWARF_TYPE_MEMORY_LOC; res_type |= DWARF_TYPE_MEMORY_LOC;
} }
uint64_t res = unsig2 - unsig1; uint64_t res = unsig2 - unsig1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, sizeof(res), res_type); stack->push(&res, sizeof(res), res_type);
return true; return true;
} }
@@ -461,34 +461,34 @@ bool dw_op_minus(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwar
} }
// The DW_OP_mod operation pops the top two stack values and pushes the result of the calculation: former second stack entry modulo the former top of the stack. // The DW_OP_mod operation pops the top two stack values and pushes the result of the calculation: former second stack entry modulo the former top of the stack.
bool dw_op_mod(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_mod(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value1 = ctx->stack.get(0); dwarf_value* value1 = stack->get(0);
dwarf_value* value2 = ctx->stack.get(1); dwarf_value* value2 = stack->get(1);
if(value1 && value2) { if(value1 && value2) {
if(!(value1->type & value2->type)) { if(!(value1->type & value2->type)) {
ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%d, %d)", map->op_name, value1->type, value2->type); stack->ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%d, %d)", map->op_name, value1->type, value2->type);
return false; return false;
} }
uint64_t v1 = 0, v2 = 0; uint64_t v1 = 0, v2 = 0;
if(!value1->get_uint(v1)) { if(!value1->get_uint(v1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(v1 == 0) { if(v1 == 0) {
ctx->log(SEVERITY_ERROR, "Division by zero requested, aborting."); stack->ctx->log(SEVERITY_ERROR, "Division by zero requested, aborting.");
return false; return false;
} }
if(!value2->get_uint(v2)) { if(!value2->get_uint(v2)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
uint64_t res = v2 % v1; uint64_t res = v2 % v1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, value1->size, DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC); stack->push(&res, value1->size, DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
return true; return true;
} }
@@ -496,84 +496,84 @@ bool dw_op_mod(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_
} }
// The DW_OP_mul operation pops the top two stack entries, multiplies them together, and pushes the result. // The DW_OP_mul operation pops the top two stack entries, multiplies them together, and pushes the result.
bool dw_op_mul(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_mul(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value1 = ctx->stack.get(0); dwarf_value* value1 = stack->get(0);
dwarf_value* value2 = ctx->stack.get(1); dwarf_value* value2 = stack->get(1);
if(value1 && value2) { if(value1 && value2) {
if(!(value1->type & value2->type)) { if(!(value1->type & value2->type)) {
ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%0x%X, %0x%X)", map->op_name, value1->type, value2->type); stack->ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%0x%X, %0x%X)", map->op_name, value1->type, value2->type);
return false; return false;
} }
if(value2->type & DWARF_TYPE_SIGNED) { if(value2->type & DWARF_TYPE_SIGNED) {
int64_t sig2; int64_t sig2;
if(!value2->get_int(sig2)) { if(!value2->get_int(sig2)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(value1->type & DWARF_TYPE_SIGNED) { if(value1->type & DWARF_TYPE_SIGNED) {
int64_t sig1; int64_t sig1;
if(!value1->get_int(sig1)) { if(!value1->get_int(sig1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(sig1 == 0) { if(sig1 == 0) {
ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig2); stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig2);
return false; return false;
} }
uint64_t res = sig2 * sig1; uint64_t res = sig2 * sig1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC); stack->push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
return true; return true;
} else { } else {
uint64_t unsig1; uint64_t unsig1;
if(!value1->get_uint(unsig1)) { if(!value1->get_uint(unsig1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(unsig1 == 0) { if(unsig1 == 0) {
ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, sig2); stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, sig2);
return false; return false;
} }
int64_t res = sig2 * unsig1; int64_t res = sig2 * unsig1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC); stack->push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
return true; return true;
} }
} else { } else {
uint64_t unsig2; uint64_t unsig2;
if(!value2->get_uint(unsig2)) { if(!value2->get_uint(unsig2)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(value1->type & DWARF_TYPE_SIGNED) { if(value1->type & DWARF_TYPE_SIGNED) {
int64_t sig1; int64_t sig1;
if(!value1->get_int(sig1)) { if(!value1->get_int(sig1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(sig1 == 0) { if(sig1 == 0) {
ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig1); stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig1);
return false; return false;
} }
int64_t res = unsig2 * sig1; int64_t res = unsig2 * sig1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC); stack->push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
return true; return true;
} else { } else {
uint64_t unsig1; uint64_t unsig1;
if(!value1->get_uint(unsig1)) { if(!value1->get_uint(unsig1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(unsig1 == 0) { if(unsig1 == 0) {
ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, unsig2); stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, unsig2);
return false; return false;
} }
uint64_t res = unsig2 * unsig1; uint64_t res = unsig2 * unsig1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC); stack->push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
return true; return true;
} }
} }
@@ -584,13 +584,13 @@ bool dw_op_mul(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_
// The DW_OP_neg operation pops the top stack entry, interprets it as a signed value and pushes its negation. // The DW_OP_neg operation pops the top stack entry, interprets it as a signed value and pushes its negation.
// If the negation cannot be represented, the result is undefined. // If the negation cannot be represented, the result is undefined.
bool dw_op_neg(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_neg(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value = ctx->stack.get(); dwarf_value* value = stack->get();
if(value) { if(value) {
int64_t v = 0; int64_t v = 0;
if(!value->get_int(v)) { if(!value->get_int(v)) {
ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size);
return false; return false;
} }
v *= -1; v *= -1;
@@ -616,7 +616,7 @@ bool dw_op_neg(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_
break; break;
} }
default: default:
ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size);
return false; return false;
break; break;
} }
@@ -628,13 +628,13 @@ bool dw_op_neg(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_
} }
// The DW_OP_not operation pops the top stack entry, and pushes its bitwise complement. // The DW_OP_not operation pops the top stack entry, and pushes its bitwise complement.
bool dw_op_not(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_not(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value = ctx->stack.get(); dwarf_value* value = stack->get();
if(value) { if(value) {
uint64_t v = 0; uint64_t v = 0;
if(!value->get_uint(v)) { if(!value->get_uint(v)) {
ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size);
return false; return false;
} }
v = ~v; v = ~v;
@@ -648,29 +648,29 @@ bool dw_op_not(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_
} }
// The DW_OP_or operation pops the top two stack entries, performs a bitwise or operation on the two, and pushes the result. // The DW_OP_or operation pops the top two stack entries, performs a bitwise or operation on the two, and pushes the result.
bool dw_op_or(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_or(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value1 = ctx->stack.get(0); dwarf_value* value1 = stack->get(0);
dwarf_value* value2 = ctx->stack.get(1); dwarf_value* value2 = stack->get(1);
if(value1 && value2) { if(value1 && value2) {
if(!(value1->type & value2->type)) { if(!(value1->type & value2->type)) {
ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%d, %d)", map->op_name, value1->type, value2->type); stack->ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%d, %d)", map->op_name, value1->type, value2->type);
return false; return false;
} }
uint64_t v1 = 0, v2 = 0; uint64_t v1 = 0, v2 = 0;
if(!value1->get_uint(v1)) { if(!value1->get_uint(v1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(!value2->get_uint(v2)) { if(!value2->get_uint(v2)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
uint64_t res = v2 | v1; uint64_t res = v2 | v1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, value1->size, value1->type); stack->push(&res, value1->size, value1->type);
return true; return true;
} }
@@ -678,29 +678,29 @@ bool dw_op_or(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_W
} }
// The DW_OP_plus operation pops the top two stack entries, adds them together, and pushes the result // The DW_OP_plus operation pops the top two stack entries, adds them together, and pushes the result
bool dw_op_plus(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_plus(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value1 = ctx->stack.get(0); dwarf_value* value1 = stack->get(0);
dwarf_value* value2 = ctx->stack.get(1); dwarf_value* value2 = stack->get(1);
if(value1 && value2) { if(value1 && value2) {
if(!(value1->type & value2->type)) { if(!(value1->type & value2->type)) {
ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%d, %d)", map->op_name, value1->type, value2->type); stack->ctx->log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%d, %d)", map->op_name, value1->type, value2->type);
return false; return false;
} }
int64_t v1 = 0, v2 = 0; int64_t v1 = 0, v2 = 0;
if(!value1->get_int(v1)) { if(!value1->get_int(v1)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
if(!value2->get_int(v2)) { if(!value2->get_int(v2)) {
ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
return false; return false;
} }
uint64_t res = v2 + v1; uint64_t res = v2 + v1;
ctx->stack.pop(); ctx->stack.pop(); stack->pop(); stack->pop();
ctx->stack.push(&res, value1->size, value1->type); stack->push(&res, value1->size, value1->type);
return true; return true;
} }
@@ -711,12 +711,12 @@ bool dw_op_plus(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf
// operand popped from the top of the stack and pushes the result. // operand popped from the top of the stack and pushes the result.
// This operation is supplied specifically to be able to encode more field offsets in two // This operation is supplied specifically to be able to encode more field offsets in two
// bytes than can be done with “DW_OP_lit<n> DW_OP_plus.” // bytes than can be done with “DW_OP_lit<n> DW_OP_plus.”
bool dw_op_plus_uconst(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_plus_uconst(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* value = ctx->stack.get(); dwarf_value* value = stack->get();
if(value) { if(value) {
if(value->type != DWARF_TYPE_SIGNED && value->type != DWARF_TYPE_UNSIGNED) { if(value->type != DWARF_TYPE_SIGNED && value->type != DWARF_TYPE_UNSIGNED) {
ctx->log(SEVERITY_ERROR, "Invalid type for operation %s(%d)", map->op_name, value->type); stack->ctx->log(SEVERITY_ERROR, "Invalid type for operation %s(%d)", map->op_name, value->type);
return false; return false;
} }
@@ -724,7 +724,7 @@ bool dw_op_plus_uconst(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1
if(value->type == DWARF_TYPE_SIGNED) { if(value->type == DWARF_TYPE_SIGNED) {
int64_t v = 0; int64_t v = 0;
if(!value->get_int(v)) { if(!value->get_int(v)) {
ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size);
return false; return false;
} }
v += op; v += op;
@@ -732,7 +732,7 @@ bool dw_op_plus_uconst(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1
} else { } else {
uint64_t v = 0; uint64_t v = 0;
if(!value->get_uint(v)) { if(!value->get_uint(v)) {
ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size); stack->ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size);
return false; return false;
} }
v += op; v += op;
@@ -748,7 +748,7 @@ bool dw_op_plus_uconst(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1
// Register location descriptions. Describe an object (or a piece of an object) that resides in a register. // Register location descriptions. Describe an object (or a piece of an object) that resides in a register.
// A register location description must stand alone as the entire description of an object or a piece of an object. // A register location description must stand alone as the entire description of an object or a piece of an object.
// The DW_OP_regx operation has a single unsigned LEB128 literal operand that encodes the name of a register // The DW_OP_regx operation has a single unsigned LEB128 literal operand that encodes the name of a register
bool dw_op_reg_x(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_reg_x(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
if(map->op_num != DW_OP_regx && (map->op_num < DW_OP_reg0 || map->op_num > DW_OP_reg31)) { if(map->op_num != DW_OP_regx && (map->op_num < DW_OP_reg0 || map->op_num > DW_OP_reg31)) {
return false; return false;
@@ -761,7 +761,7 @@ bool dw_op_reg_x(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwar
regno = map->op_num - DW_OP_reg0; regno = map->op_num - DW_OP_reg0;
} }
ctx->stack.push(&regno, sizeof(regno), DWARF_TYPE_REGISTER_LOC); stack->push(&regno, sizeof(regno), DWARF_TYPE_REGISTER_LOC);
return true; return true;
} }
@@ -769,7 +769,7 @@ bool dw_op_reg_x(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwar
// DWARF5, section 2.5.1.2 Register values are used to describe an object (or a piece of an object) that is located in memory at an address that is contained in a register (possibly offset by some constant) // DWARF5, section 2.5.1.2 Register values are used to describe an object (or a piece of an object) that is located in memory at an address that is contained in a register (possibly offset by some constant)
// The DW_OP_bregx operation provides the sum of two values specified by its two operands. // The DW_OP_bregx operation provides the sum of two values specified by its two operands.
// The first operand is a register number which is specified by an unsigned LEB128 number. The second operand is a signed LEB128 offset. // The first operand is a register number which is specified by an unsigned LEB128 number. The second operand is a signed LEB128 offset.
bool dw_op_breg_x(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_breg_x(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
if(map->op_num != DW_OP_bregx && (map->op_num < DW_OP_breg0 || map->op_num > DW_OP_breg31)) { if(map->op_num != DW_OP_bregx && (map->op_num < DW_OP_breg0 || map->op_num > DW_OP_breg31)) {
return false; return false;
@@ -785,26 +785,26 @@ bool dw_op_breg_x(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwa
} }
unw_word_t val = 0; unw_word_t val = 0;
if(unw_get_reg(&ctx->cursor, regno, &val)) { if(unw_get_reg(&stack->ctx->cursor, regno, &val)) {
return false; return false;
} }
val += off; val += off;
ctx->stack.push(&val, sizeof(val), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC); stack->push(&val, sizeof(val), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC);
return true; return true;
} }
// The DW_OP_lit<n> operations encode the unsigned literal values from 0 through 31, inclusive. // The DW_OP_lit<n> operations encode the unsigned literal values from 0 through 31, inclusive.
// Operations other than DW_OP_const_type push a value with the generic type. // Operations other than DW_OP_const_type push a value with the generic type.
bool dw_op_lit_x(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_lit_x(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
if(map->op_num < DW_OP_lit0 || map->op_num > DW_OP_lit31) { if(map->op_num < DW_OP_lit0 || map->op_num > DW_OP_lit31) {
return false; return false;
} }
uint64_t val = map->op_num - DW_OP_lit0; uint64_t val = map->op_num - DW_OP_lit0;
ctx->stack.push(&val, sizeof(val), DWARF_TYPE_GENERIC); stack->push(&val, sizeof(val), DWARF_TYPE_GENERIC);
return true; return true;
} }
@@ -812,10 +812,10 @@ bool dw_op_lit_x(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwar
// The DW_OP_stack_value operation specifies that the object does not exist in memory but its value is nonetheless known and is at the top of the DWARF // The DW_OP_stack_value operation specifies that the object does not exist in memory but its value is nonetheless known and is at the top of the DWARF
// expression stack. In this form of location description, the DWARF expression represents the actual value of the object, rather than its location. // expression stack. In this form of location description, the DWARF expression represents the actual value of the object, rather than its location.
// The DW_OP_stack_value operation terminates the expression. // The DW_OP_stack_value operation terminates the expression.
bool dw_op_stack_value(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_stack_value(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
dwarf_value* v = ctx->stack.get(); dwarf_value* v = stack->get();
if(v) { if(v) {
v->type = DWARF_TYPE_GENERIC; v->type = DWARF_TYPE_GENERIC;
return true; return true;
@@ -825,33 +825,33 @@ bool dw_op_stack_value(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1
} }
// The DW_OP_call_frame_cfa operation pushes the value of the CFA, obtained from the Call Frame Information (see Section 6.4 on page 171). // The DW_OP_call_frame_cfa operation pushes the value of the CFA, obtained from the Call Frame Information (see Section 6.4 on page 171).
bool dw_op_call_frame_cfa(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_call_frame_cfa(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
{ {
// since in signal handler we are know SP value, just push it to DWARF stack // since in signal handler we are know SP value, just push it to DWARF stack
unw_word_t sp; unw_word_t sp;
if(unw_get_reg(&ctx->cursor, UNW_REG_SP, &sp)) { if(unw_get_reg(&stack->ctx->cursor, UNW_REG_SP, &sp)) {
return false; return false;
} }
ctx->stack.push(&sp, sizeof(sp), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC); stack->push(&sp, sizeof(sp), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC);
return true; return true;
} }
// 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
bool dw_op_fbreg(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) bool dw_op_fbreg(dwarf_stack* stack, 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 // 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(&stack->ctx->cursor, UNW_REG_SP, &sp)) {
return false; return false;
} }
int64_t off = decode_sleb128((unsigned char*)&op1); int64_t off = decode_sleb128((unsigned char*)&op1);
sp += off; sp += off;
ctx->stack.push(&sp, sizeof(sp), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC); stack->push(&sp, sizeof(sp), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC);
return true; return true;
} }
@@ -1054,3 +1054,80 @@ const dwarf_op_map* find_op_map(int op)
return NULL; return NULL;
} }
bool __dwarf_stack::get_value(uint64_t& value)
{
if(!Size()) {
return false;
}
value = 0;
dwarf_value* v = get();
v->get_uint(value);
if(v->type & DWARF_TYPE_REGISTER_LOC) {
// dereference register location
uint64_t regno = value;
if(unw_get_reg(&ctx->cursor, regno, &value)) {
ctx->log(SEVERITY_ERROR, "Failed to get value of register 0x%lX", regno);
return false;
}
}
return true;
}
bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr)
{
clear();
for (int i = 0; i < expr_len; i++) {
const dwarf_op_map* map = find_op_map(exprs[i].atom);
if(!map) {
ctx->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 = 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(&ctx->cursor, regno, &value)) {
ctx->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)) {
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);
return false;
}
continue;
} else {
ctx->log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr location");
}
} else {
ctx->log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr expression");
}
}
if(!map->operation(this, map, exprs[i].number, exprs[i].number2)) {
ctx->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;
}
+105 -1
View File
@@ -4,9 +4,113 @@
#include "common.h" #include "common.h"
typedef enum {
DWARF_TYPE_INVALID = 0, // no type
DWARF_TYPE_SIGNED = 1, // signed type
DWARF_TYPE_UNSIGNED = 2, // unsigned type
DWARF_TYPE_CONST = 4, // constant signed/unsigned type
DWARF_TYPE_GENERIC = 8, // size of machine address type
DWARF_TYPE_CHAR = 16, // 1 byte size
DWARF_TYPE_FLOAT = 32, // machine-dependent floating point size
DWARF_TYPE_REGISTER_LOC = 64, // value located in register specified as 'value'
DWARF_TYPE_MEMORY_LOC = 128, // value located in memory address specified as 'value'
DWARF_TYPE_PIECE = 256, // piece of whole value located in current value
DWARF_TYPE_SHORT = 512, // 2 byte size
DWARF_TYPE_INT = 1024, // 4 byte size
DWARF_TYPE_LONG = 2048 // 8 byte size
} dwarf_value_type;
typedef struct __dwarf_value : public SC_ListNode {
__dwarf_value(char*v, uint32_t s, int t)
{
size = s;
value = (char*)malloc(s);
memcpy(value, v, s);
type = t;
}
~__dwarf_value()
{
if(value) {
free(value);
value = NULL;
size = 0;
}
}
void replace(void* v, uint32_t s, int t)
{
if(value) {
free(value);
size = 0;
type = DWARF_TYPE_INVALID;
}
value = (char*)malloc(s);
memcpy(value, v, s);
size = s;
type = t;
}
bool get_uint(uint64_t& v);
bool get_int(int64_t& v);
bool get_generic(uint64_t& v);
char* value;
uint32_t size; // size in bytes except of 'DWARF_TYPE_PIECE', in such case in bits
int type; // bitmask of DWARF_TYPE_XXX
} dwarf_value;
typedef struct __dwarf_stack : public SC_ListHead {
__dwarf_stack(pst_context* c) : ctx(c)
{
attr = NULL;
}
void clear() {
for(dwarf_value* v = (dwarf_value*)First(); v; v = (dwarf_value*)First()) {
Remove(v);
delete v;
}
}
void push(void* v, uint32_t s, int t) {
dwarf_value* value = new dwarf_value((char*)v, s, t);
InsertFirst(value);
}
void push(dwarf_value* value) {
InsertFirst(value);
}
dwarf_value* pop() {
dwarf_value* value = (dwarf_value*)First();
if(value) {
Remove(value);
}
return value;
}
dwarf_value* get(uint32_t idx = 0) {
dwarf_value* value = NULL;
for(value = (dwarf_value*)First(); value && idx; value = (dwarf_value*)Next(value)) {
idx--;
}
return value;
}
bool calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr);
bool get_value(uint64_t& value);
Dwarf_Attribute* attr; // attribute which expression currently processed
pst_context* ctx;
} dwarf_stack;
typedef struct __dwarf_op_map dwarf_op_map; typedef struct __dwarf_op_map dwarf_op_map;
typedef bool (*dwarf_operation)(pst_context* ctx, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2); typedef bool (*dwarf_operation)(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2);
typedef struct __dwarf_op_map { typedef struct __dwarf_op_map {
int op_num; // DWARF Operation DW_OP_XXX int op_num; // DWARF Operation DW_OP_XXX
+8 -6
View File
@@ -202,6 +202,7 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
unw_get_reg(&ctx->cursor, UNW_REG_IP, &pc); unw_get_reg(&ctx->cursor, UNW_REG_IP, &pc);
Dwarf_Addr offset = pc - ctx->base_addr; Dwarf_Addr offset = pc - ctx->base_addr;
dwarf_stack stack(ctx);
// determine location of parameter in stack/heap or CPU registers // determine location of parameter in stack/heap or CPU registers
attr = dwarf_attr(result, DW_AT_location, &attr_mem); attr = dwarf_attr(result, DW_AT_location, &attr_mem);
if(attr) { if(attr) {
@@ -211,9 +212,9 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
if(dwarf_getlocation(attr, &expr, &exprlen) == 0) { if(dwarf_getlocation(attr, &expr, &exprlen) == 0) {
char str[1024]; str[0] = 0; char str[1024]; str[0] = 0;
ctx->print_expr_block (expr, exprlen, str, sizeof(str), attr); ctx->print_expr_block (expr, exprlen, str, sizeof(str), attr);
if(ctx->calc_expression(expr, exprlen, attr)) { if(stack.calc_expression(expr, exprlen, attr)) {
uint64_t value; uint64_t value;
if(ctx->get_value(value)) { if(stack.get_value(value)) {
ctx->log(SEVERITY_DEBUG, "DW_AT_location expression: \"%s\" ==> 0x%lX", str, value); ctx->log(SEVERITY_DEBUG, "DW_AT_location expression: \"%s\" ==> 0x%lX", str, value);
} else { } else {
ctx->log(SEVERITY_ERROR, "Failed to get value of calculated DW_AT_location expression: %s", str); ctx->log(SEVERITY_ERROR, "Failed to get value of calculated DW_AT_location expression: %s", str);
@@ -234,9 +235,9 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
// actual location, try to calculate Location expression and retrieve value of parameter // actual location, try to calculate Location expression and retrieve value of parameter
char str[1024]; str[0] = 0; char str[1024]; str[0] = 0;
ctx->print_expr_block (expr, exprlen, str, sizeof(str), attr); ctx->print_expr_block (expr, exprlen, str, sizeof(str), attr);
if(ctx->calc_expression(expr, exprlen, attr)) { if(stack.calc_expression(expr, exprlen, attr)) {
uint64_t value; uint64_t value;
if(ctx->get_value(value)) { if(stack.get_value(value)) {
ctx->log(SEVERITY_DEBUG, "Location list expression: [%d] (low_offset: 0x%" PRIx64 ", high_offset: 0x%" PRIx64"), \"%s\" ==> 0x%lX", i, start, end, str, value); ctx->log(SEVERITY_DEBUG, "Location list expression: [%d] (low_offset: 0x%" PRIx64 ", high_offset: 0x%" PRIx64"), \"%s\" ==> 0x%lX", i, start, end, str, value);
} else { } else {
ctx->log(SEVERITY_DEBUG, "Failed to get value of calculated Location list expression: [%d] (low_offset: 0x%" PRIx64 ", high_offset: 0x%" PRIx64 "), \"%s\" ==> 0x%lX", ctx->log(SEVERITY_DEBUG, "Failed to get value of calculated Location list expression: [%d] (low_offset: 0x%" PRIx64 ", high_offset: 0x%" PRIx64 "), \"%s\" ==> 0x%lX",
@@ -293,9 +294,10 @@ bool __pst_function::handle_dwarf(Dwarf_Die* d)
if (dwarf_getlocation (attr, &expr, &exprlen) == 0) { if (dwarf_getlocation (attr, &expr, &exprlen) == 0) {
char str[1024]; str[0] = 0; char str[1024]; str[0] = 0;
ctx->print_expr_block (expr, exprlen, str, sizeof(str), attr); ctx->print_expr_block (expr, exprlen, str, sizeof(str), attr);
if(ctx->calc_expression(expr, exprlen, attr)) { dwarf_stack stack(ctx);
if(stack.calc_expression(expr, exprlen, attr)) {
uint64_t value; uint64_t value;
if(ctx->get_value(value)) { if(stack.get_value(value)) {
ctx->log(SEVERITY_DEBUG, "DW_AT_framebase expression: \"%s\"==> 0x%lX", str, value); ctx->log(SEVERITY_DEBUG, "DW_AT_framebase expression: \"%s\"==> 0x%lX", str, value);
} else { } else {
ctx->log(SEVERITY_ERROR, "Failed to get value of calculated DW_AT_framebase expression: %s", str); ctx->log(SEVERITY_ERROR, "Failed to get value of calculated DW_AT_framebase expression: %s", str);
-1
View File
@@ -98,7 +98,6 @@ typedef struct __pst_handler {
void dwarf_print(); void dwarf_print();
bool calc_expression(Dwarf_Op *exprs, int exp_len, dwarf_stack* stack, Dwarf_Attribute* attr = 0);
bool unwind(); bool unwind();
bool get_frame(); bool get_frame();
bool get_dwarf_function(pst_function& fun); bool get_dwarf_function(pst_function& fun);