all code except of pst_function & pst_handler rewritten on C language.
Logger nad Allocator decided to be a global for all library
This commit is contained in:
+187
-444
@@ -10,19 +10,19 @@
|
||||
|
||||
#include "dwarf_operations.h"
|
||||
#include "common.h"
|
||||
#include "registers.h"
|
||||
|
||||
// not implemented operations
|
||||
bool dw_op_notimpl(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_notimpl(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
stack->ctx->log(SEVERITY_ERROR, "%s(0x%lX, 0x%lX) operation is not implemented", map->op_name, op1, op2);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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.
|
||||
bool dw_op_addr(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_addr(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
stack->push(&op1, sizeof(op1), DWARF_TYPE_GENERIC);
|
||||
stack->push(stack, &op1, sizeof(op1), DWARF_TYPE_GENERIC);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -32,30 +32,31 @@ bool dw_op_addr(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwa
|
||||
// retrieved is zero extended to the size of an address on the target machine
|
||||
// before being pushed onto the expression stack.
|
||||
|
||||
bool dw_op_deref_size(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_deref_size(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value = stack->pop();
|
||||
pst_dwarf_value* value = stack->pop(stack);
|
||||
if(value) {
|
||||
uint64_t addr;
|
||||
if(value->get_uint(addr)) {
|
||||
uint64_t res = 0;
|
||||
switch(op1) {
|
||||
case 1:
|
||||
res = *((uint8_t*)addr);
|
||||
break;
|
||||
case 2:
|
||||
res = *((uint16_t*)addr);
|
||||
break;
|
||||
case 4:
|
||||
res = *((uint32_t*)addr);
|
||||
break;
|
||||
case 8:
|
||||
res = *((uint64_t*)addr);
|
||||
break;
|
||||
}
|
||||
stack->push(&res, sizeof(res), DWARF_TYPE_GENERIC);
|
||||
return true;
|
||||
uint64_t addr = value->value.uint64;
|
||||
uint64_t res = 0;
|
||||
switch(op1) {
|
||||
case 1:
|
||||
res = *((uint8_t*)addr);
|
||||
break;
|
||||
case 2:
|
||||
res = *((uint16_t*)addr);
|
||||
break;
|
||||
case 4:
|
||||
res = *((uint32_t*)addr);
|
||||
break;
|
||||
case 8:
|
||||
res = *((uint64_t*)addr);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
stack->push(stack, &res, sizeof(res), DWARF_TYPE_GENERIC);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -64,17 +65,17 @@ bool dw_op_deref_size(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op
|
||||
// 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 size of the data retrieved from the dereferenced address is the size of an address on the target machine.
|
||||
bool dw_op_deref(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_deref(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
return dw_op_deref_size(stack, map, 8, op2);
|
||||
}
|
||||
|
||||
// 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
|
||||
bool dw_op_const_x_u(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_const_x_u(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
uint8_t size = 0;
|
||||
dwarf_value_type type = DWARF_TYPE_UNSIGNED;
|
||||
pst_dwarf_value_type type = DWARF_TYPE_UNSIGNED;
|
||||
switch (map->op_num) {
|
||||
case DW_OP_const1u:
|
||||
size = 1;
|
||||
@@ -96,17 +97,17 @@ bool dw_op_const_x_u(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1
|
||||
return false;
|
||||
}
|
||||
|
||||
stack->push(&op1, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
|
||||
stack->push(stack, &op1, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
|
||||
|
||||
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.
|
||||
// These operations push a value with the generic type
|
||||
bool dw_op_const_x_s(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_const_x_s(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
uint8_t size; int64_t v;
|
||||
dwarf_value_type type = DWARF_TYPE_SIGNED;
|
||||
pst_dwarf_value_type type = DWARF_TYPE_SIGNED;
|
||||
switch (map->op_num) {
|
||||
case DW_OP_const1s:
|
||||
v = (int8_t)op1;
|
||||
@@ -132,62 +133,62 @@ bool dw_op_const_x_s(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1
|
||||
return false;
|
||||
}
|
||||
|
||||
stack->push(&v, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
|
||||
stack->push(stack, &v, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// The single operand of the DW_OP_constu operation provides an unsigned LEB128 integer constant.
|
||||
bool dw_op_constu(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_constu(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
uint64_t value = decode_uleb128((unsigned char*)&op1);
|
||||
stack->push(&value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_UNSIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
|
||||
stack->push(stack, &value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_UNSIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dw_op_consts(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_consts(pst_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.
|
||||
int64_t value = decode_sleb128((unsigned char*)&op1);
|
||||
stack->push(&value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_SIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
|
||||
stack->push(stack, &value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_SIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The DW_OP_dup operation duplicates the value (including its type identifier) at the top of the stack.
|
||||
bool dw_op_dup(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_dup(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value = stack->get();
|
||||
stack->push(value->value, value->size, value->type);
|
||||
pst_dwarf_value* value = stack->get(stack, 0);
|
||||
stack->push(stack, &value->value, sizeof(value->value), value->type);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// The DW_OP_drop operation pops the value (including its type identifier) at the top of the stack.
|
||||
bool dw_op_drop(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_drop(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value = stack->pop();
|
||||
free(value);
|
||||
pst_dwarf_value* value = stack->pop(stack);
|
||||
pst_dwarf_value_fini(value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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.
|
||||
bool dw_op_over(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_over(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value = stack->get(1);
|
||||
stack->push(value->value, value->size, value->type);
|
||||
pst_dwarf_value* value = stack->get(stack, 1);
|
||||
stack->push(stack, &value->value, sizeof(value->value), value->type);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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.
|
||||
bool dw_op_pick(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_pick(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value = stack->get(op1);
|
||||
pst_dwarf_value* value = stack->get(stack, op1);
|
||||
if(value) {
|
||||
stack->push(value->value, value->size, value->type);
|
||||
stack->push(stack, &value->value, sizeof(value->value), value->type);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -196,21 +197,21 @@ bool dw_op_pick(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwa
|
||||
|
||||
// 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.
|
||||
bool dw_op_swap(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_swap(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value1 = stack->pop();
|
||||
dwarf_value* value2 = stack->pop();
|
||||
pst_dwarf_value* value1 = stack->pop(stack);
|
||||
pst_dwarf_value* value2 = stack->pop(stack);
|
||||
if(value1 && value2) {
|
||||
stack->push(value1);
|
||||
stack->push(value2);
|
||||
stack->push_value(stack, value1);
|
||||
stack->push_value(stack, value2);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(value1) {
|
||||
delete(value1);
|
||||
pst_dwarf_value_fini(value1);
|
||||
}
|
||||
if(value2) {
|
||||
delete(value2);
|
||||
pst_dwarf_value_fini(value2);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -220,26 +221,26 @@ bool dw_op_swap(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwa
|
||||
// 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,
|
||||
// and the third entry (including its type identifier) becomes the second entry
|
||||
bool dw_op_rot(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_rot(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value1 = stack->pop();
|
||||
dwarf_value* value2 = stack->pop();
|
||||
dwarf_value* value3 = stack->pop();
|
||||
pst_dwarf_value* value1 = stack->pop(stack);
|
||||
pst_dwarf_value* value2 = stack->pop(stack);
|
||||
pst_dwarf_value* value3 = stack->pop(stack);
|
||||
if(value1 && value2 && value3) {
|
||||
stack->push(value1);
|
||||
stack->push(value3);
|
||||
stack->push(value2);
|
||||
stack->push_value(stack, value1);
|
||||
stack->push_value(stack, value3);
|
||||
stack->push_value(stack, value2);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(value1) {
|
||||
free(value1);
|
||||
pst_dwarf_value_fini(value1);
|
||||
}
|
||||
if(value2) {
|
||||
free(value2);
|
||||
pst_dwarf_value_fini(value2);
|
||||
}
|
||||
if(value3) {
|
||||
free(value3);
|
||||
pst_dwarf_value_fini(value3);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -247,45 +248,33 @@ bool dw_op_rot(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwar
|
||||
|
||||
// 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.
|
||||
bool dw_op_abs(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_abs(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value = stack->get();
|
||||
pst_dwarf_value* value = stack->get(stack, 0);
|
||||
if(value) {
|
||||
int64_t v;
|
||||
if(!value->get_int(v)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong %d size of stack value", value->size);
|
||||
return false;
|
||||
}
|
||||
uint64_t res = llabs(v);
|
||||
value->replace(&res, value->size, DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC | DWARF_TYPE_LONG);
|
||||
uint64_t res = llabs(value->value.int64);
|
||||
value->set(value, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC | DWARF_TYPE_LONG);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_and(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value1 = stack->get(0);
|
||||
dwarf_value* value2 = stack->get(1);
|
||||
pst_dwarf_value* value1 = stack->get(stack, 0);
|
||||
pst_dwarf_value* value2 = stack->get(stack, 1);
|
||||
if(value1 && value2) {
|
||||
if(!(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;
|
||||
}
|
||||
uint64_t v1 = 0, v2 = 0;
|
||||
if(!value1->get_generic(v1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!value2->get_generic(v2)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
uint64_t res = v1 & v2;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, value1->size, DWARF_TYPE_GENERIC);
|
||||
uint64_t res = value1->value.uint64 & value2->value.uint64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), DWARF_TYPE_GENERIC);
|
||||
|
||||
pst_dwarf_value_fini(value1);
|
||||
pst_dwarf_value_fini(value2);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -293,84 +282,49 @@ bool dw_op_and(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwar
|
||||
}
|
||||
|
||||
// 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(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_div(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value1 = stack->get(0);
|
||||
dwarf_value* value2 = stack->get(1);
|
||||
pst_dwarf_value* value1 = stack->get(stack, 0);
|
||||
pst_dwarf_value* value2 = stack->get(stack, 1);
|
||||
if(value1 && value2) {
|
||||
if(!(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;
|
||||
}
|
||||
|
||||
if(value2->type & DWARF_TYPE_SIGNED) {
|
||||
int64_t sig2;
|
||||
if(!value2->get_int(sig2)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
if(value1->type & DWARF_TYPE_SIGNED) {
|
||||
int64_t sig1;
|
||||
if(!value1->get_int(sig1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
if(value1->value.int64 == 0) {
|
||||
return false;
|
||||
}
|
||||
if(sig1 == 0) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig2);
|
||||
return false;
|
||||
}
|
||||
uint64_t res = sig2 / sig1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
|
||||
uint64_t res = value2->value.int64 / value1->value.int64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
|
||||
return true;
|
||||
} else {
|
||||
uint64_t unsig1;
|
||||
if(!value1->get_uint(unsig1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
if(value1->value.uint64 == 0) {
|
||||
return false;
|
||||
}
|
||||
if(unsig1 == 0) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, sig2);
|
||||
return false;
|
||||
}
|
||||
int64_t res = sig2 / unsig1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
|
||||
int64_t res = value2->value.int64 / value1->value.uint64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
uint64_t unsig2;
|
||||
if(!value2->get_uint(unsig2)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
if(value1->type & DWARF_TYPE_SIGNED) {
|
||||
int64_t sig1;
|
||||
if(!value1->get_int(sig1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
if(value1->value.int64 == 0) {
|
||||
return false;
|
||||
}
|
||||
if(sig1 == 0) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig1);
|
||||
return false;
|
||||
}
|
||||
int64_t res = unsig2 / sig1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
|
||||
int64_t res = value2->value.uint64 / value1->value.int64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
|
||||
return true;
|
||||
} else {
|
||||
uint64_t unsig1;
|
||||
if(!value1->get_uint(unsig1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
if(value1->value.uint64 == 0) {
|
||||
return false;
|
||||
}
|
||||
if(unsig1 == 0) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, unsig2);
|
||||
return false;
|
||||
}
|
||||
uint64_t res = unsig2 / unsig1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
|
||||
uint64_t res = value2->value.uint64 / value1->value.uint64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -380,32 +334,23 @@ bool dw_op_div(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwar
|
||||
}
|
||||
|
||||
// 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(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_minus(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value1 = stack->get(0);
|
||||
dwarf_value* value2 = stack->get(1);
|
||||
pst_dwarf_value* value1 = stack->get(stack, 0);
|
||||
pst_dwarf_value* value2 = stack->get(stack, 1);
|
||||
if(value1 && value2) {
|
||||
if(!(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;
|
||||
}
|
||||
// use arithmetic by modulo 1 plus
|
||||
uint64_t unsig1; uint64_t unsig2;
|
||||
if(!value1->get_uint(unsig1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
if(!value2->get_uint(unsig2)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value2->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
int res_type = DWARF_TYPE_GENERIC;
|
||||
if(value2->type & DWARF_TYPE_MEMORY_LOC) {
|
||||
res_type |= DWARF_TYPE_MEMORY_LOC;
|
||||
}
|
||||
uint64_t res = unsig2 - unsig1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, sizeof(res), res_type);
|
||||
// use arithmetic by modulo 1 plus
|
||||
uint64_t res = value2->value.uint64 - value1->value.uint64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), res_type);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -414,34 +359,23 @@ bool dw_op_minus(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dw
|
||||
}
|
||||
|
||||
// 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(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_mod(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value1 = stack->get(0);
|
||||
dwarf_value* value2 = stack->get(1);
|
||||
pst_dwarf_value* value1 = stack->get(stack, 0);
|
||||
pst_dwarf_value* value2 = stack->get(stack, 1);
|
||||
if(value1 && value2) {
|
||||
if(!(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;
|
||||
}
|
||||
uint64_t v1 = 0, v2 = 0;
|
||||
if(!value1->get_uint(v1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(v1 == 0) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Division by zero requested, aborting.");
|
||||
if(value1->value.uint64 == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!value2->get_uint(v2)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
uint64_t res = value2->value.uint64 % value1->value.uint64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
|
||||
|
||||
uint64_t res = v2 % v1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, value1->size, DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -449,10 +383,10 @@ bool dw_op_mod(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwar
|
||||
}
|
||||
|
||||
// The DW_OP_mul operation pops the top two stack entries, multiplies them together, and pushes the result.
|
||||
bool dw_op_mul(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_mul(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value1 = stack->get(0);
|
||||
dwarf_value* value2 = stack->get(1);
|
||||
pst_dwarf_value* value1 = stack->get(stack, 0);
|
||||
pst_dwarf_value* value2 = stack->get(stack, 1);
|
||||
if(value1 && value2) {
|
||||
if(!(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);
|
||||
@@ -460,73 +394,31 @@ bool dw_op_mul(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwar
|
||||
}
|
||||
|
||||
if(value2->type & DWARF_TYPE_SIGNED) {
|
||||
int64_t sig2;
|
||||
if(!value2->get_int(sig2)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
if(value1->type & DWARF_TYPE_SIGNED) {
|
||||
int64_t sig1;
|
||||
if(!value1->get_int(sig1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
if(sig1 == 0) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig2);
|
||||
return false;
|
||||
}
|
||||
uint64_t res = sig2 * sig1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
|
||||
uint64_t res = value2->value.int64 * value1->value.int64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
uint64_t unsig1;
|
||||
if(!value1->get_uint(unsig1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
if(unsig1 == 0) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, sig2);
|
||||
return false;
|
||||
}
|
||||
int64_t res = sig2 * unsig1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
|
||||
int64_t res = value2->value.int64 * value1->value.uint64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
|
||||
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
uint64_t unsig2;
|
||||
if(!value2->get_uint(unsig2)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
if(value1->type & DWARF_TYPE_SIGNED) {
|
||||
int64_t sig1;
|
||||
if(!value1->get_int(sig1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
if(sig1 == 0) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, sig1, sig1);
|
||||
return false;
|
||||
}
|
||||
int64_t res = unsig2 * sig1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
|
||||
int64_t res = value2->value.uint64 * value1->value.int64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
uint64_t unsig1;
|
||||
if(!value1->get_uint(unsig1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
if(unsig1 == 0) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Division by zero for operation %s(0x%lX, 0x%lX)", map->op_name, unsig1, unsig2);
|
||||
return false;
|
||||
}
|
||||
uint64_t res = unsig2 * unsig1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
|
||||
uint64_t res = value2->value.uint64 * value1->value.uint64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -537,62 +429,31 @@ bool dw_op_mul(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwar
|
||||
|
||||
// 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.
|
||||
bool dw_op_neg(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_neg(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value = stack->get();
|
||||
pst_dwarf_value* value = stack->get(stack, 0);
|
||||
if(value) {
|
||||
int64_t v = 0;
|
||||
if(!value->get_int(v)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size);
|
||||
return false;
|
||||
}
|
||||
v *= -1;
|
||||
|
||||
switch (value->size) {
|
||||
case 1: {
|
||||
int8_t vv = (int8_t)v;
|
||||
value->replace(&vv, sizeof(vv), value->type);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
int16_t vv = (int16_t)v;
|
||||
value->replace(&vv, sizeof(vv), value->type);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
int32_t vv = (int32_t)v;
|
||||
value->replace(&vv, sizeof(vv), value->type);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
value->replace(&v, sizeof(v), value->type);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
if(value->type & DWARF_TYPE_CHAR) {
|
||||
value->value.int8 *= -1;
|
||||
} else if(value->type & DWARF_TYPE_SHORT) {
|
||||
value->value.int16 *= -1;
|
||||
} else if(value->type & DWARF_TYPE_INT) {
|
||||
value->value.int32 *= -1;
|
||||
} else {
|
||||
value->value.int64 *= -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// The DW_OP_not operation pops the top stack entry, and pushes its bitwise complement.
|
||||
bool dw_op_not(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_not(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value = stack->get();
|
||||
pst_dwarf_value* value = stack->get(stack, 0);
|
||||
if(value) {
|
||||
uint64_t v = 0;
|
||||
if(!value->get_uint(v)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size);
|
||||
return false;
|
||||
}
|
||||
v = ~v;
|
||||
|
||||
value->replace(&v, value->size, value->type);
|
||||
value->value.uint64 = ~value->value.uint64;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -601,29 +462,22 @@ bool dw_op_not(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwar
|
||||
}
|
||||
|
||||
// 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(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_or(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value1 = stack->get(0);
|
||||
dwarf_value* value2 = stack->get(1);
|
||||
pst_dwarf_value* value1 = stack->get(stack, 0);
|
||||
pst_dwarf_value* value2 = stack->get(stack, 1);
|
||||
if(value1 && value2) {
|
||||
if(!(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;
|
||||
}
|
||||
uint64_t v1 = 0, v2 = 0;
|
||||
if(!value1->get_uint(v1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!value2->get_uint(v2)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
uint64_t res = value2->value.uint64 | value1->value.uint64;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
stack->push(stack, &res, sizeof(res), value1->type);
|
||||
|
||||
pst_dwarf_value_fini(value1);
|
||||
pst_dwarf_value_fini(value2);
|
||||
|
||||
uint64_t res = v2 | v1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, value1->size, value1->type);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -631,30 +485,30 @@ bool dw_op_or(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf
|
||||
}
|
||||
|
||||
// The DW_OP_plus operation pops the top two stack entries, adds them together, and pushes the result
|
||||
bool dw_op_plus(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_plus(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value1 = stack->get(0);
|
||||
dwarf_value* value2 = stack->get(1);
|
||||
pst_dwarf_value* value1 = stack->get(stack, 0);
|
||||
pst_dwarf_value* value2 = stack->get(stack, 1);
|
||||
if(value1 && value2) {
|
||||
if(!(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;
|
||||
}
|
||||
int64_t v1 = 0, v2 = 0;
|
||||
if(!value1->get_int(v1)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 1st stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!value2->get_int(v2)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of 2nd stack value for operation %s(%d)", map->op_name, value1->size);
|
||||
return false;
|
||||
if((value1->type & DWARF_TYPE_SIGNED) && (value2->type & DWARF_TYPE_SIGNED)) {
|
||||
int64_t res = value2->value.int64 + value1->value.int64;
|
||||
stack->push(stack, &res, sizeof(res), value1->type);
|
||||
} else {
|
||||
// if in arithmetic expression even one operand is unsigned then result is unsigned as well
|
||||
int type = (value1->type & (~DWARF_TYPE_SIGNED)) | DWARF_TYPE_UNSIGNED;
|
||||
uint64_t res = value2->value.uint64 + value1->value.uint64;
|
||||
stack->push(stack, &res, sizeof(res), type);
|
||||
}
|
||||
|
||||
uint64_t res = v2 + v1;
|
||||
stack->pop(); stack->pop();
|
||||
stack->push(&res, value1->size, value1->type);
|
||||
return true;
|
||||
stack->pop(stack); stack->pop(stack);
|
||||
pst_dwarf_value_fini(value1);
|
||||
pst_dwarf_value_fini(value2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -664,18 +518,12 @@ bool dw_op_plus(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwa
|
||||
// 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
|
||||
// bytes than can be done with “DW_OP_lit<n> DW_OP_plus.”
|
||||
bool dw_op_plus_uconst(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_plus_uconst(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
dwarf_value* value = stack->get();
|
||||
pst_dwarf_value* value = stack->get(stack, 0);
|
||||
if(value) {
|
||||
uint64_t op = decode_uleb128((unsigned char*)&op1);
|
||||
uint64_t v = 0;
|
||||
if(!value->get_generic(v)) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "Wrong size of stack value for operation %s(%d)", map->op_name, value->size);
|
||||
return false;
|
||||
}
|
||||
v += op;
|
||||
value->replace(&v, sizeof(v), value->type);
|
||||
value->value.uint64 += op;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -686,7 +534,7 @@ bool dw_op_plus_uconst(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word o
|
||||
// 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.
|
||||
// The DW_OP_regx operation has a single unsigned LEB128 literal operand that encodes the name of a register
|
||||
bool dw_op_reg_x(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_reg_x(pst_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)) {
|
||||
return false;
|
||||
@@ -699,7 +547,7 @@ bool dw_op_reg_x(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dw
|
||||
regno = map->op_num - DW_OP_reg0;
|
||||
}
|
||||
|
||||
stack->push(®no, sizeof(regno), DWARF_TYPE_REGISTER_LOC);
|
||||
stack->push(stack, ®no, sizeof(regno), DWARF_TYPE_REGISTER_LOC);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -707,7 +555,7 @@ bool dw_op_reg_x(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dw
|
||||
// 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 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(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_breg_x(pst_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)) {
|
||||
return false;
|
||||
@@ -725,26 +573,25 @@ bool dw_op_breg_x(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, D
|
||||
unw_word_t val = 0;
|
||||
int ret = unw_get_reg(stack->ctx->curr_frame, regno, &val);
|
||||
if(ret) {
|
||||
stack->ctx->log(SEVERITY_ERROR, "%s: Failed to get register 0x%X value. Error: %d", __PRETTY_FUNCTION__, regno, ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
val += off;
|
||||
stack->push(&val, sizeof(val), DWARF_TYPE_GENERIC);
|
||||
stack->push(stack, &val, sizeof(val), DWARF_TYPE_GENERIC);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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.
|
||||
bool dw_op_lit_x(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_lit_x(pst_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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t val = map->op_num - DW_OP_lit0;
|
||||
stack->push(&val, sizeof(val), DWARF_TYPE_GENERIC);
|
||||
stack->push(stack, &val, sizeof(val), DWARF_TYPE_GENERIC);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -752,10 +599,10 @@ bool dw_op_lit_x(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dw
|
||||
// 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.
|
||||
// The DW_OP_stack_value operation terminates the expression.
|
||||
bool dw_op_stack_value(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_stack_value(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
|
||||
dwarf_value* v = stack->get();
|
||||
pst_dwarf_value* v = stack->get(stack, 0);
|
||||
if(v) {
|
||||
v->type = DWARF_TYPE_GENERIC;
|
||||
return true;
|
||||
@@ -765,7 +612,7 @@ bool dw_op_stack_value(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word o
|
||||
}
|
||||
|
||||
// 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(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_call_frame_cfa(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
{
|
||||
// since we are already know SP value, just push it to DWARF stack
|
||||
// unw_word_t sp;
|
||||
@@ -775,14 +622,14 @@ bool dw_op_call_frame_cfa(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Wor
|
||||
// return false;
|
||||
// }
|
||||
|
||||
stack->push(&stack->ctx->cfa, sizeof(stack->ctx->cfa), /*DWARF_TYPE_MEMORY_LOC | */DWARF_TYPE_GENERIC);
|
||||
stack->push(stack, &stack->ctx->cfa, sizeof(stack->ctx->cfa), /*DWARF_TYPE_MEMORY_LOC | */DWARF_TYPE_GENERIC);
|
||||
|
||||
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
|
||||
// attribute of the current function. This is typically a stack pointer register plus or minus some offset
|
||||
bool dw_op_fbreg(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2)
|
||||
bool dw_op_fbreg(pst_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
|
||||
unw_word_t sp;
|
||||
@@ -796,7 +643,7 @@ bool dw_op_fbreg(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dw
|
||||
int64_t off = decode_sleb128((unsigned char*)&op1);
|
||||
sp += off;
|
||||
|
||||
stack->push(&sp, sizeof(sp), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC);
|
||||
stack->push(stack, &sp, sizeof(sp), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -989,107 +836,3 @@ const dwarf_op_map* find_op_map(int op)
|
||||
|
||||
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;
|
||||
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", regno, ret);
|
||||
return false;
|
||||
}
|
||||
} else if(v->type & DWARF_TYPE_MEMORY_LOC) {
|
||||
// dereference memory location
|
||||
uint64_t addr = *(uint64_t*)v->value;
|
||||
value = *((uint64_t*)addr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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++) {
|
||||
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;
|
||||
}
|
||||
|
||||
pst_dwarf_op* op = new pst_dwarf_op(exprs[i].atom, exprs[i].number, exprs[i].number2);
|
||||
expr.InsertLast(op);
|
||||
|
||||
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);
|
||||
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", regno, ret);
|
||||
return false;
|
||||
}
|
||||
v->replace(&value, sizeof(value), DWARF_TYPE_GENERIC);
|
||||
}
|
||||
|
||||
// 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;
|
||||
if(!dwarf_getlocation_attr(attr, exprs, &attr_mem)) {
|
||||
Dwarf_Op *expr;
|
||||
size_t exprlen;
|
||||
if (dwarf_getlocation(&attr_mem, &expr, &exprlen) == 0) {
|
||||
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;
|
||||
}
|
||||
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(¶m->value, sizeof(param->value), DWARF_TYPE_GENERIC);
|
||||
|
||||
continue;
|
||||
} else {
|
||||
ctx->log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr location");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
ctx->log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr expression");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user