right caculation of DW_OP_GNU_entry_value, use caller's information

This commit is contained in:
2020-01-26 15:36:33 +04:00
parent 898fa1e5e8
commit f9635841f6
4 changed files with 217 additions and 95 deletions
+22 -21
View File
@@ -1111,7 +1111,7 @@ bool __dwarf_stack::get_value(uint64_t& value)
uint64_t regno = value; uint64_t regno = value;
int ret = unw_get_reg(ctx->curr_frame, regno, &value); int ret = unw_get_reg(ctx->curr_frame, regno, &value);
if(ret) { if(ret) {
ctx->log(SEVERITY_ERROR, "Failed to get value of register 0x%X. Error: %d", __PRETTY_FUNCTION__, regno, ret); ctx->log(SEVERITY_ERROR, "Failed to get value of register 0x%X. Error: %d", regno, ret);
return false; return false;
} }
} else if(v->type & DWARF_TYPE_MEMORY_LOC) { } else if(v->type & DWARF_TYPE_MEMORY_LOC) {
@@ -1123,7 +1123,7 @@ bool __dwarf_stack::get_value(uint64_t& value)
return true; return true;
} }
bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr) bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr, pst_function* fun)
{ {
clear(); clear();
for (int i = 0; i < expr_len; i++) { for (int i = 0; i < expr_len; i++) {
@@ -1143,7 +1143,7 @@ bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
uint64_t regno = *((uint64_t*)v->value); uint64_t regno = *((uint64_t*)v->value);
int ret = unw_get_reg(ctx->curr_frame, regno, &value); int ret = unw_get_reg(ctx->curr_frame, regno, &value);
if(ret) { if(ret) {
ctx->log(SEVERITY_ERROR, "Failed to ger value of register 0x%X. Error: %d", __PRETTY_FUNCTION__, regno, ret); ctx->log(SEVERITY_ERROR, "Failed to ger value of register 0x%X. Error: %d", regno, ret);
return false; return false;
} }
v->replace(&value, sizeof(value), DWARF_TYPE_GENERIC); v->replace(&value, sizeof(value), DWARF_TYPE_GENERIC);
@@ -1151,6 +1151,14 @@ bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
// handle there because it contains sub-expression of a Location in caller's frame // handle there because it contains sub-expression of a Location in caller's frame
if(map->op_num == DW_OP_GNU_entry_value) { 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 // 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 // simple register or DWARF expression
Dwarf_Attribute attr_mem; Dwarf_Attribute attr_mem;
@@ -1158,26 +1166,19 @@ bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
Dwarf_Op *expr; Dwarf_Op *expr;
size_t exprlen; size_t exprlen;
if (dwarf_getlocation(&attr_mem, &expr, &exprlen) == 0) { if (dwarf_getlocation(&attr_mem, &expr, &exprlen) == 0) {
// save current frame cursor pst_call_site* cs = fun->parent->find_call_site(fun);
unw_cursor_t* cursor = ctx->curr_frame; ctx->curr_frame = ctx->next_frame; if(!cs) {
dwarf_stack st(ctx); ctx->log(SEVERITY_ERROR, "Failed to find call site while calculate DW_OP_GNU_entry_value expression");
char str[1024]; str[0]= 0;
ctx->print_expr_block (expr, exprlen, str, sizeof(str), &attr_mem);
ctx->log(SEVERITY_DEBUG, "Parent frame expression: %s", str);
bool eret = st.calc_expression(expr, exprlen, &attr_mem);
uint64_t val = 0;
bool gret = false;
if(eret) {
gret = st.get_value(val);
}
// restore current frame cursor
ctx->curr_frame = cursor;
if(!eret || !gret) {
ctx->log(SEVERITY_ERROR, "Failed to calculate sub-expression for operation %s(0x%lX, 0x%lX)", map->op_name, exprs[i].number, exprs[i].number2);
return false; return false;
} }
ctx->log(SEVERITY_DEBUG, "DW_OP_GNU_entry_value calculated from caller frame = 0x%lX", val); pst_dwarf_expr loc; loc.setup(expr, exprlen);
push(&val, sizeof(val), DWARF_TYPE_GENERIC); pst_call_site_param* param = cs->find_param(loc);
if(!param) {
ctx->log(SEVERITY_ERROR, "Failed to find call site parameter while calculate DW_OP_GNU_entry_value expression");
return false;
}
push(&param->value, sizeof(param->value), DWARF_TYPE_GENERIC);
continue; continue;
} else { } else {
+2 -11
View File
@@ -4,16 +4,7 @@
#include "common.h" #include "common.h"
#include "linkedlist.h" #include "linkedlist.h"
#include "sysutils.h"
// DWARF operation (represents our own DW_OP_XXX)
typedef struct __pst_dwarf_op : public SC_ListNode {
__pst_dwarf_op(uint8_t op, uint64_t a1, uint64_t a2) {
operation = op; arg1 = a1; arg2 = a2;
}
uint8_t operation;
uint64_t arg1;
uint64_t arg2;
} pst_dwarf_op;
typedef enum { typedef enum {
DWARF_TYPE_INVALID = 0, // no type DWARF_TYPE_INVALID = 0, // no type
@@ -120,7 +111,7 @@ typedef struct __dwarf_stack : public SC_ListHead {
return value; return value;
} }
bool calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr); bool calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr, pst_function* fun = NULL);
bool get_value(uint64_t& value); bool get_value(uint64_t& value);
Dwarf_Attribute* attr; // attribute which expression currently processed Dwarf_Attribute* attr; // attribute which expression currently processed
+144 -51
View File
@@ -51,35 +51,41 @@ int regname_callback (void *arg, int regno, const char *setname, const char *pre
return 0; return 0;
} }
bool handle_location(pst_context* ctx, Dwarf_Attribute* attr, dwarf_stack& stack, Dwarf_Addr pc, char* str, uint32_t strsize) bool handle_location(pst_context* ctx, Dwarf_Attribute* attr, pst_dwarf_expr& loc, Dwarf_Addr pc, char* str, uint32_t strsize, __pst_function* fun = NULL)
{ {
str[0] = 0; str[0] = 0;
Dwarf_Addr offset = pc - ctx->base_addr; Dwarf_Addr offset = pc - ctx->base_addr;
if(dwarf_hasform(attr, DW_FORM_exprloc)) { dwarf_stack stack(ctx);
// Location expression (exprloc class of location in DWARF terms)
Dwarf_Op *expr; Dwarf_Op *expr;
size_t exprlen; size_t exprlen;
if(dwarf_hasform(attr, DW_FORM_exprloc)) {
// Location expression (exprloc class of location in DWARF terms)
if(dwarf_getlocation(attr, &expr, &exprlen) == 0) { if(dwarf_getlocation(attr, &expr, &exprlen) == 0) {
loc.setup(expr, exprlen);
ctx->print_expr_block (expr, exprlen, str, strsize, attr); ctx->print_expr_block (expr, exprlen, str, strsize, attr);
if(stack.calc_expression(expr, exprlen, attr)) { if(stack.calc_expression(expr, exprlen, attr, fun) && stack.get_value(loc.value)) {
return true; return true;
} else {
return false;
} }
} }
} else if(dwarf_hasform(attr, DW_FORM_sec_offset)) { } else if(dwarf_hasform(attr, DW_FORM_sec_offset)) {
// Location list (loclist class of location in DWARF terms) // Location list (loclist class of location in DWARF terms)
Dwarf_Addr base, start, end; Dwarf_Addr base, start, end;
ptrdiff_t off = 0; ptrdiff_t off = 0;
Dwarf_Op *expr;
size_t exprlen;
// handle list of possible locations of parameter // handle list of possible locations of parameter
for(int i = 0; (off = dwarf_getlocations (attr, off, &base, &start, &end, &expr, &exprlen)) > 0; ++i) { for(int i = 0; (off = dwarf_getlocations (attr, off, &base, &start, &end, &expr, &exprlen)) > 0; ++i) {
ctx->print_expr_block (expr, exprlen, str, strsize, attr); ctx->print_expr_block (expr, exprlen, str, strsize, attr);
if(offset >= start && offset <= end) { if(offset >= start && offset <= end) {
loc.setup(expr, exprlen);
// actual location, try to calculate Location expression // actual location, try to calculate Location expression
if(stack.calc_expression(expr, exprlen, attr)) { if(stack.calc_expression(expr, exprlen, attr, fun) && stack.get_value(loc.value), fun) {
ctx->log(SEVERITY_DEBUG, "Location expression: (low_offset: 0x%" PRIx64 ", high_offset: 0x%" PRIx64 "), \"%s\" ==> 0x%lX", start, end, str, loc.value);
return true; return true;
} else {
return false;
} }
} else { } else {
// Location skipped due to don't match current PC offset // Location skipped due to don't match current PC offset
@@ -91,15 +97,88 @@ bool handle_location(pst_context* ctx, Dwarf_Attribute* attr, dwarf_stack& stack
ctx->log(SEVERITY_WARNING, "Unknown location attribute form = 0x%X, code = 0x%X, ", attr->form, attr->code); ctx->log(SEVERITY_WARNING, "Unknown location attribute form = 0x%X, code = 0x%X, ", attr->form, attr->code);
} }
return false; return false;
} }
bool __pst_dwarf_expr::operator== (__pst_dwarf_expr &rhs)
{
if(Size() != rhs.Size()) {
return false;
}
pst_dwarf_op* lop = next_op(NULL);
pst_dwarf_op* rop = rhs.next_op(NULL);
while(lop && rop) {
if(lop->operation == rop->operation && lop->arg1 == rop->arg1 && lop->arg2 == rop->arg2) {
return true;
}
lop = next_op(lop);
rop = rhs.next_op(rop);
}
return false;
}
pst_dwarf_op* __pst_dwarf_expr::add_op(uint8_t operation, uint64_t arg1, uint64_t arg2)
{
pst_dwarf_op* op = new pst_dwarf_op(operation, arg1, arg2);
InsertLast(op);
return op;
}
pst_dwarf_op* __pst_dwarf_expr::next_op(pst_dwarf_op* op)
{
pst_dwarf_op* ret = NULL;
if(!op) {
ret = (pst_dwarf_op*)First();
} else {
ret = (pst_dwarf_op*)Next(op);
}
return ret;
}
bool __pst_dwarf_expr::print_op(const char* fmt, ...)
{
bool nret = true;
va_list args;
va_start(args, fmt);
int size = sizeof(buff) - offset;
int ret = vsnprintf(buff + offset, size, fmt, args);
if(ret >= size || ret < 0) {
nret = false;
}
offset += ret;
va_end(args);
return nret;
}
void __pst_dwarf_expr::clean()
{
for(pst_dwarf_op* op = (pst_dwarf_op*)First(); op; op = (pst_dwarf_op*)First()) {
Remove(op);
delete op;
}
}
void __pst_dwarf_expr::setup(Dwarf_Op* expr, size_t exprlen)
{
clean();
for(size_t i = 0; i < exprlen; ++i) {
add_op(expr[i].atom, expr[i].number, expr[i].number2);
}
}
bool __pst_parameter::print_dwarf() bool __pst_parameter::print_dwarf()
{ {
if(types.Size()) { if(types.Size()) {
if(!is_return) { if(!is_return) {
if(has_value) { if(has_value) {
ctx->print("%s %s = 0x%lX", next_type(NULL)->name.c_str(), name.c_str(), value); ctx->print("%s %s = 0x%lX", next_type(NULL)->name.c_str(), name.c_str(), location.value);
} else { } else {
ctx->print("%s %s = <undefined>", next_type(NULL)->name.c_str(), name.c_str()); ctx->print("%s %s = <undefined>", next_type(NULL)->name.c_str(), name.c_str());
} }
@@ -108,7 +187,7 @@ bool __pst_parameter::print_dwarf()
} }
} else { } else {
if(has_value) { if(has_value) {
ctx->print("%s = 0x%lX", name.c_str(), value); ctx->print("%s = 0x%lX", name.c_str(), location.value);
} else { } else {
ctx->print("%s = <undefined>", name.c_str()); ctx->print("%s = <undefined>", name.c_str());
} }
@@ -224,7 +303,7 @@ pst_type* __pst_parameter::next_type(pst_type* t)
return next; return next;
} }
bool __pst_parameter::handle_dwarf(Dwarf_Die* result) bool __pst_parameter::handle_dwarf(Dwarf_Die* result, __pst_function* fun)
{ {
die = result; die = result;
@@ -250,13 +329,8 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
dwarf_stack stack(ctx); dwarf_stack stack(ctx);
char str[1024]; str[0] = 0; char str[1024]; str[0] = 0;
if(handle_location(ctx, attr, stack, pc, str, sizeof(str))) { if(handle_location(ctx, attr, location, pc, str, sizeof(str), fun)) {
if(stack.get_value(value)) {
ctx->log(SEVERITY_DEBUG, "Parameter Location: %s ==> 0x%lX", str, value);
has_value = true; has_value = true;
} else {
ctx->log(SEVERITY_ERROR, "Failed to get value of calculated DW_AT_location expression: %s", str);
}
} else { } else {
ctx->log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", str); ctx->log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", str);
} }
@@ -272,20 +346,20 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
case DW_FORM_data2: case DW_FORM_data2:
case DW_FORM_data4: case DW_FORM_data4:
case DW_FORM_data8: case DW_FORM_data8:
dwarf_formudata(attr, &value); dwarf_formudata(attr, &location.value);
has_value = true; has_value = true;
break; break;
case DW_FORM_sdata: case DW_FORM_sdata:
dwarf_formsdata(attr, (int64_t*)&value); dwarf_formsdata(attr, (int64_t*)&location.value);
has_value = true; has_value = true;
break; break;
case DW_FORM_udata: case DW_FORM_udata:
dwarf_formudata(attr, &value); dwarf_formudata(attr, &location.value);
has_value = true; has_value = true;
break; break;
} }
if(has_value) { if(has_value) {
ctx->log(SEVERITY_DEBUG, "Parameter constant value: 0x%lX", value); ctx->log(SEVERITY_DEBUG, "Parameter constant value: 0x%lX", location.value);
} }
} }
@@ -310,6 +384,11 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
return true; return true;
} }
void __pst_call_site_param::set_location(Dwarf_Op* expr, size_t exprlen)
{
location.setup(expr, exprlen);
}
pst_call_site_param* __pst_call_site::add_param() pst_call_site_param* __pst_call_site::add_param()
{ {
pst_call_site_param* p = new pst_call_site_param(ctx); pst_call_site_param* p = new pst_call_site_param(ctx);
@@ -321,6 +400,7 @@ pst_call_site_param* __pst_call_site::add_param()
void __pst_call_site::del_param(pst_call_site_param* p) void __pst_call_site::del_param(pst_call_site_param* p)
{ {
params.Remove(p); params.Remove(p);
delete p; delete p;
} }
@@ -336,6 +416,17 @@ pst_call_site_param* __pst_call_site::next_param(pst_call_site_param* p)
return param; return param;
} }
pst_call_site_param* __pst_call_site::find_param(pst_dwarf_expr& expr)
{
for(pst_call_site_param* param = next_param(NULL); param; param = next_param(param)) {
if(param->location == expr) {
return param;
}
}
return NULL;
}
bool __pst_call_site::handle_dwarf(Dwarf_Die* child) bool __pst_call_site::handle_dwarf(Dwarf_Die* child)
{ {
Dwarf_Attribute attr_mem; Dwarf_Attribute attr_mem;
@@ -350,19 +441,12 @@ bool __pst_call_site::handle_dwarf(Dwarf_Die* child)
char str[1024]; char str[1024];
// expression represent where callee parameter will be stored // expression represent where callee parameter will be stored
pst_call_site_param* param = new pst_call_site_param(ctx); pst_call_site_param* param = add_param();
if(dwarf_hasattr(child, DW_AT_location)) { if(dwarf_hasattr(child, DW_AT_location)) {
// handle location expression here // handle location expression here
// determine location of parameter in stack/heap or CPU registers // determine location of parameter in stack/heap or CPU registers
attr = dwarf_attr(child, DW_AT_location, &attr_mem); attr = dwarf_attr(child, DW_AT_location, &attr_mem);
if(handle_location(ctx, attr, param->location, pc, str, sizeof(str))) { if(!handle_location(ctx, attr, param->location, pc, str, sizeof(str))) {
uint64_t value = 0;
if(param->location.get_value(value)) {
ctx->log(SEVERITY_DEBUG, "\tDW_TAG_GNU_call_site_parameter: \"%s\" ==> 0x%lX", str, value);
} else {
ctx->log(SEVERITY_WARNING, "Failed to get value of calculated DW_AT_location expression: %s", str);
}
} else {
ctx->log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", str); ctx->log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", str);
del_param(param); del_param(param);
return false; return false;
@@ -374,14 +458,10 @@ bool __pst_call_site::handle_dwarf(Dwarf_Die* child)
// handle value expression here // handle value expression here
attr = dwarf_attr(child, DW_AT_GNU_call_site_value, &attr_mem); attr = dwarf_attr(child, DW_AT_GNU_call_site_value, &attr_mem);
dwarf_stack stack(ctx); dwarf_stack stack(ctx);
if(handle_location(ctx, attr, stack, pc, str, sizeof(str))) { pst_dwarf_expr loc;
if(stack.get_value(param->value)) { if(handle_location(ctx, attr, loc, pc, str, sizeof(str))) {
param->value = loc.value;
ctx->log(SEVERITY_DEBUG, "\tDW_AT_GNU_call_site_value:\"%s\" ==> 0x%lX", str, param->value); ctx->log(SEVERITY_DEBUG, "\tDW_AT_GNU_call_site_value:\"%s\" ==> 0x%lX", str, param->value);
} else {
ctx->log(SEVERITY_ERROR, "Failed to get value of calculated DW_AT_location expression: %s", str);
del_param(param);
return false;
}
} else { } else {
ctx->log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", str); ctx->log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", str);
del_param(param); del_param(param);
@@ -418,6 +498,14 @@ void __pst_function::clear()
params.Remove(p); params.Remove(p);
delete p; delete p;
} }
for(pst_call_site* p = (pst_call_site*)call_sites.First(); p; p = (pst_call_site*)call_sites.First()) {
call_sites.Remove(p);
delete p;
}
mCallStToTarget.Clean();
mCallStToTarget.Clean();
} }
pst_parameter* __pst_function::next_param(pst_parameter* p) pst_parameter* __pst_function::next_param(pst_parameter* p)
@@ -481,6 +569,17 @@ pst_call_site* __pst_function::call_site_by_target(uint64_t target)
return (pst_call_site*)mCallStToTarget.Lookup(&target, sizeof(target)); return (pst_call_site*)mCallStToTarget.Lookup(&target, sizeof(target));
} }
pst_call_site* __pst_function::find_call_site(pst_function* callee)
{
uint64_t start_pc = ctx->base_addr + callee->lowpc;
pst_call_site* cs = (pst_call_site*)mCallStToTarget.Lookup(&start_pc, sizeof(start_pc));
if(!cs) {
cs = (pst_call_site*)mCallStToOrigin.Lookup(callee->name.c_str(), strlen(callee->name.c_str()));
}
return cs;
}
bool __pst_function::print_dwarf() bool __pst_function::print_dwarf()
{ {
char* at = NULL; char* at = NULL;
@@ -588,7 +687,7 @@ bool __pst_function::handle_lexical_block(Dwarf_Die* result)
break; break;
case DW_TAG_variable: { case DW_TAG_variable: {
pst_parameter* param = add_param(); pst_parameter* param = add_param();
if(!param->handle_dwarf(&child)) { if(!param->handle_dwarf(&child, this)) {
del_param(param); del_param(param);
} }
break; break;
@@ -639,18 +738,11 @@ bool __pst_function::handle_call_site(Dwarf_Die* result)
if(dwarf_hasattr (result, DW_AT_GNU_call_site_target)) { if(dwarf_hasattr (result, DW_AT_GNU_call_site_target)) {
attr = dwarf_attr(result, DW_AT_GNU_call_site_target, &attr_mem); attr = dwarf_attr(result, DW_AT_GNU_call_site_target, &attr_mem);
if(attr) { if(attr) {
dwarf_stack stack(ctx);
char str[1024]; str[0] = 0; char str[1024]; str[0] = 0;
if(handle_location(ctx, &attr_mem, stack, pc, str, sizeof(str))) { pst_dwarf_expr expr;
if(stack.get_value(target)) { if(handle_location(ctx, &attr_mem, expr, pc, str, sizeof(str), this)) {
ctx->log(SEVERITY_DEBUG, "\tDW_AT_GNU_call_site_target: %s ==> %#lX", str, (void*)target); target = expr.value;
} else { ctx->log(SEVERITY_DEBUG, "\tDW_AT_GNU_call_site_target: %#lX", target);
ctx->log(SEVERITY_ERROR, "Failed to get value of calculated DW_AT_GNU_call_site_target expression: %s", str);
return false;
}
} else {
ctx->log(SEVERITY_ERROR, "Failed to calculate DW_AT_GNU_call_site_target expression: %s", str);
return false;
} }
} }
} }
@@ -707,7 +799,7 @@ bool __pst_function::handle_dwarf(Dwarf_Die* d)
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);
dwarf_stack stack(ctx); dwarf_stack stack(ctx);
if(stack.calc_expression(expr, exprlen, attr)) { if(stack.calc_expression(expr, exprlen, attr, this)) {
uint64_t value; uint64_t value;
if(stack.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);
@@ -762,7 +854,7 @@ bool __pst_function::handle_dwarf(Dwarf_Die* d)
case DW_TAG_formal_parameter: case DW_TAG_formal_parameter:
case DW_TAG_variable: { case DW_TAG_variable: {
pst_parameter* param = add_param(); pst_parameter* param = add_param();
if(!param->handle_dwarf(&result)) { if(!param->handle_dwarf(&result, this)) {
del_param(param); del_param(param);
} }
@@ -1012,7 +1104,8 @@ bool __pst_handler::handle_dwarf()
{ {
Dl_info info; Dl_info info;
for(pst_function* fun = next_function(NULL); fun; fun = next_function(fun)) { //for(pst_function* fun = next_function(NULL); fun; fun = next_function(fun)) {
for(pst_function* fun = (pst_function*)functions.Last(); fun; fun = (pst_function*)functions.Prev(fun)) {
dladdr((void*)(fun->pc), &info); dladdr((void*)(fun->pc), &info);
module = dwfl_addrmodule(dwfl, fun->pc); module = dwfl_addrmodule(dwfl, fun->pc);
ctx.base_addr = (uint64_t)info.dli_fbase; ctx.base_addr = (uint64_t)info.dli_fbase;
+47 -10
View File
@@ -24,9 +24,43 @@
#include "common.h" #include "common.h"
#include "dictionary.h" #include "dictionary.h"
#include "dwarf_operations.h" #include "data_entry.h"
typedef struct __pst_function pst_function;
// DWARF operation (represents our own DW_OP_XXX)
typedef struct __pst_dwarf_op : public SC_ListNode {
__pst_dwarf_op(uint8_t op, uint64_t a1, uint64_t a2) {
operation = op; arg1 = a1; arg2 = a2;
}
uint8_t operation;
uint64_t arg1;
uint64_t arg2;
} pst_dwarf_op;
typedef struct __pst_dwarf_expr : public SC_ListHead {
__pst_dwarf_expr() {
has_value = false; value = 0; offset = 0; buff[0] = 0;
}
~__pst_dwarf_expr() {
clean();
}
pst_dwarf_op* add_op(uint8_t op, uint64_t arg1, uint64_t arg2);
pst_dwarf_op* next_op(pst_dwarf_op* op);
void clean();
void setup(Dwarf_Op* expr, size_t exprlen);
void set_value(uint64_t v) {
has_value = true;
value = v;
}
bool print_op(const char* fmt, ...);
bool operator== (__pst_dwarf_expr &rhs);
bool has_value;
uint64_t value;
char buff[512];
uint16_t offset;
} pst_dwarf_expr;
typedef struct __pst_type : public SC_ListNode { typedef struct __pst_type : public SC_ListNode {
__pst_type(const char* n, uint32_t t) : type(t) { __pst_type(const char* n, uint32_t t) : type(t) {
@@ -38,6 +72,8 @@ typedef struct __pst_type : public SC_ListNode {
uint32_t type; // DW_AT_XXX type uint32_t type; // DW_AT_XXX type
} pst_type; } pst_type;
typedef struct __pst_function pst_function;
typedef struct __pst_parameter : public SC_ListNode { typedef struct __pst_parameter : public SC_ListNode {
__pst_parameter(pst_context* c) : ctx(c) __pst_parameter(pst_context* c) : ctx(c)
{ {
@@ -48,7 +84,6 @@ typedef struct __pst_parameter : public SC_ListNode {
is_return = false; is_return = false;
is_variable = false; is_variable = false;
has_value = false; has_value = false;
value = 0;
line = 0; line = 0;
} }
@@ -61,7 +96,7 @@ typedef struct __pst_parameter : public SC_ListNode {
pst_type* add_type(const char* name, int type); pst_type* add_type(const char* name, int type);
pst_type* next_type(pst_type* t); pst_type* next_type(pst_type* t);
bool handle_dwarf(Dwarf_Die* d); bool handle_dwarf(Dwarf_Die* d, __pst_function* fun);
bool handle_type(Dwarf_Attribute* param); bool handle_type(Dwarf_Attribute* param);
bool print_dwarf(); bool print_dwarf();
@@ -75,13 +110,13 @@ typedef struct __pst_parameter : public SC_ListNode {
bool is_return; // whether this parameter is return value of the function bool is_return; // whether this parameter is return value of the function
bool is_variable;// whether this parameter is function variable or argument of function bool is_variable;// whether this parameter is function variable or argument of function
bool has_value; // whether we got value of parameter or not bool has_value; // whether we got value of parameter or not
uint64_t value; // value of parameter pst_dwarf_expr location;
pst_context* ctx; pst_context* ctx;
} pst_parameter; } pst_parameter;
// DW_TAG_call_site_parameter // DW_TAG_call_site_parameter
typedef struct __pst_call_site_param : public SC_ListNode { typedef struct __pst_call_site_param : public SC_ListNode {
__pst_call_site_param(pst_context* ctx) : location(ctx) { __pst_call_site_param(pst_context* ctx) {
param = NULL; name = NULL; value = 0; param = NULL; name = NULL; value = 0;
} }
@@ -91,9 +126,11 @@ typedef struct __pst_call_site_param : public SC_ListNode {
} }
} }
void set_location(Dwarf_Op* expr, size_t exprlen);
Dwarf_Die* param; // reference to parameter DIE in callee (DW_AT_call_parameter) Dwarf_Die* param; // reference to parameter DIE in callee (DW_AT_call_parameter)
char* name; // name of parameter if present (DW_AT_name) char* name; // name of parameter if present (DW_AT_name)
dwarf_stack location; // DWARF stack containing location expression pst_dwarf_expr location; // DWARF stack containing location expression
uint64_t value; // parameter's value uint64_t value; // parameter's value
} pst_call_site_param; } pst_call_site_param;
@@ -120,6 +157,7 @@ typedef struct __pst_call_site : public SC_ListNode {
pst_call_site_param* add_param(); pst_call_site_param* add_param();
void del_param(pst_call_site_param* p); void del_param(pst_call_site_param* p);
pst_call_site_param* next_param(pst_call_site_param* p); pst_call_site_param* next_param(pst_call_site_param* p);
pst_call_site_param* find_param(pst_dwarf_expr& expr);
bool handle_dwarf(Dwarf_Die* die); bool handle_dwarf(Dwarf_Die* die);
@@ -130,8 +168,6 @@ typedef struct __pst_call_site : public SC_ListNode {
pst_context* ctx; pst_context* ctx;
} pst_call_site; } pst_call_site;
typedef struct __pst_handler pst_handler;
typedef struct __pst_function : public SC_ListNode { typedef struct __pst_function : public SC_ListNode {
__pst_function(pst_context* _ctx, __pst_function* _parent) : ctx(_ctx) { __pst_function(pst_context* _ctx, __pst_function* _parent) : ctx(_ctx) {
pc = 0; pc = 0;
@@ -165,6 +201,7 @@ typedef struct __pst_function : public SC_ListNode {
bool print_dwarf(); bool print_dwarf();
bool handle_lexical_block(Dwarf_Die* result); bool handle_lexical_block(Dwarf_Die* result);
bool handle_call_site(Dwarf_Die* result); bool handle_call_site(Dwarf_Die* result);
pst_call_site* find_call_site(__pst_function* callee);
Dwarf_Addr lowpc; // offset to start of the function against base address Dwarf_Addr lowpc; // offset to start of the function against base address
Dwarf_Addr highpc; // offset to the next address after the end of the function against base address Dwarf_Addr highpc; // offset to the next address after the end of the function against base address
@@ -183,7 +220,7 @@ typedef struct __pst_function : public SC_ListNode {
unw_cursor_t cursor; // copy of stack state of the function unw_cursor_t cursor; // copy of stack state of the function
int line; // line in code where function is defined int line; // line in code where function is defined
std::string file; // file name (DWARF Compilation Unit) where function is defined std::string file; // file name (DWARF Compilation Unit) where function is defined
pst_function* parent; // parent function in call trace (caller) __pst_function* parent; // parent function in call trace (caller)
pst_context* ctx; // context of unwinding pst_context* ctx; // context of unwinding
} pst_function; } pst_function;