right caculation of DW_OP_GNU_entry_value, use caller's information
This commit is contained in:
@@ -1111,7 +1111,7 @@ bool __dwarf_stack::get_value(uint64_t& value)
|
||||
uint64_t regno = value;
|
||||
int ret = unw_get_reg(ctx->curr_frame, regno, &value);
|
||||
if(ret) {
|
||||
ctx->log(SEVERITY_ERROR, "Failed to get value of register 0x%X. Error: %d", __PRETTY_FUNCTION__, regno, ret);
|
||||
ctx->log(SEVERITY_ERROR, "Failed to get value of register 0x%X. Error: %d", regno, ret);
|
||||
return false;
|
||||
}
|
||||
} else if(v->type & DWARF_TYPE_MEMORY_LOC) {
|
||||
@@ -1123,7 +1123,7 @@ bool __dwarf_stack::get_value(uint64_t& value)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr)
|
||||
bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr, pst_function* fun)
|
||||
{
|
||||
clear();
|
||||
for (int i = 0; i < expr_len; i++) {
|
||||
@@ -1143,7 +1143,7 @@ bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
|
||||
uint64_t regno = *((uint64_t*)v->value);
|
||||
int ret = unw_get_reg(ctx->curr_frame, regno, &value);
|
||||
if(ret) {
|
||||
ctx->log(SEVERITY_ERROR, "Failed to ger value of register 0x%X. Error: %d", __PRETTY_FUNCTION__, regno, ret);
|
||||
ctx->log(SEVERITY_ERROR, "Failed to ger value of register 0x%X. Error: %d", regno, ret);
|
||||
return false;
|
||||
}
|
||||
v->replace(&value, sizeof(value), DWARF_TYPE_GENERIC);
|
||||
@@ -1151,6 +1151,14 @@ bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
|
||||
|
||||
// handle there because it contains sub-expression of a Location in caller's frame
|
||||
if(map->op_num == DW_OP_GNU_entry_value) {
|
||||
if(!fun) {
|
||||
ctx->log(SEVERITY_ERROR, "Cannot calculate DW_OP_GNU_entry_value expression while function is undefined");
|
||||
return false;
|
||||
}
|
||||
if(!fun->parent) {
|
||||
ctx->log(SEVERITY_ERROR, "Function has not parent while calculate DW_OP_GNU_entry_value expression");
|
||||
return false;
|
||||
}
|
||||
// This opcode has two operands, the first one is uleb128 length and the second is block of that length, containing either a
|
||||
// simple register or DWARF expression
|
||||
Dwarf_Attribute attr_mem;
|
||||
@@ -1158,26 +1166,19 @@ bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu
|
||||
Dwarf_Op *expr;
|
||||
size_t exprlen;
|
||||
if (dwarf_getlocation(&attr_mem, &expr, &exprlen) == 0) {
|
||||
// save current frame cursor
|
||||
unw_cursor_t* cursor = ctx->curr_frame; ctx->curr_frame = ctx->next_frame;
|
||||
dwarf_stack st(ctx);
|
||||
char str[1024]; str[0]= 0;
|
||||
ctx->print_expr_block (expr, exprlen, str, sizeof(str), &attr_mem);
|
||||
ctx->log(SEVERITY_DEBUG, "Parent frame expression: %s", str);
|
||||
bool eret = st.calc_expression(expr, exprlen, &attr_mem);
|
||||
uint64_t val = 0;
|
||||
bool gret = false;
|
||||
if(eret) {
|
||||
gret = st.get_value(val);
|
||||
}
|
||||
// restore current frame cursor
|
||||
ctx->curr_frame = cursor;
|
||||
if(!eret || !gret) {
|
||||
ctx->log(SEVERITY_ERROR, "Failed to calculate sub-expression for operation %s(0x%lX, 0x%lX)", map->op_name, exprs[i].number, exprs[i].number2);
|
||||
pst_call_site* cs = fun->parent->find_call_site(fun);
|
||||
if(!cs) {
|
||||
ctx->log(SEVERITY_ERROR, "Failed to find call site while calculate DW_OP_GNU_entry_value expression");
|
||||
return false;
|
||||
}
|
||||
ctx->log(SEVERITY_DEBUG, "DW_OP_GNU_entry_value calculated from caller frame = 0x%lX", val);
|
||||
push(&val, sizeof(val), DWARF_TYPE_GENERIC);
|
||||
pst_dwarf_expr loc; loc.setup(expr, exprlen);
|
||||
pst_call_site_param* param = cs->find_param(loc);
|
||||
if(!param) {
|
||||
ctx->log(SEVERITY_ERROR, "Failed to find call site parameter while calculate DW_OP_GNU_entry_value expression");
|
||||
return false;
|
||||
}
|
||||
|
||||
push(¶m->value, sizeof(param->value), DWARF_TYPE_GENERIC);
|
||||
|
||||
continue;
|
||||
} else {
|
||||
|
||||
@@ -4,16 +4,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "linkedlist.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;
|
||||
#include "sysutils.h"
|
||||
|
||||
typedef enum {
|
||||
DWARF_TYPE_INVALID = 0, // no type
|
||||
@@ -120,7 +111,7 @@ typedef struct __dwarf_stack : public SC_ListHead {
|
||||
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);
|
||||
|
||||
Dwarf_Attribute* attr; // attribute which expression currently processed
|
||||
|
||||
+144
-51
@@ -51,35 +51,41 @@ int regname_callback (void *arg, int regno, const char *setname, const char *pre
|
||||
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;
|
||||
Dwarf_Addr offset = pc - ctx->base_addr;
|
||||
|
||||
if(dwarf_hasform(attr, DW_FORM_exprloc)) {
|
||||
// Location expression (exprloc class of location in DWARF terms)
|
||||
dwarf_stack stack(ctx);
|
||||
Dwarf_Op *expr;
|
||||
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) {
|
||||
loc.setup(expr, exprlen);
|
||||
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;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if(dwarf_hasform(attr, DW_FORM_sec_offset)) {
|
||||
// Location list (loclist class of location in DWARF terms)
|
||||
Dwarf_Addr base, start, end;
|
||||
ptrdiff_t off = 0;
|
||||
Dwarf_Op *expr;
|
||||
size_t exprlen;
|
||||
|
||||
// handle list of possible locations of parameter
|
||||
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);
|
||||
if(offset >= start && offset <= end) {
|
||||
loc.setup(expr, exprlen);
|
||||
// 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;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
if(types.Size()) {
|
||||
if(!is_return) {
|
||||
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 {
|
||||
ctx->print("%s %s = <undefined>", next_type(NULL)->name.c_str(), name.c_str());
|
||||
}
|
||||
@@ -108,7 +187,7 @@ bool __pst_parameter::print_dwarf()
|
||||
}
|
||||
} else {
|
||||
if(has_value) {
|
||||
ctx->print("%s = 0x%lX", name.c_str(), value);
|
||||
ctx->print("%s = 0x%lX", name.c_str(), location.value);
|
||||
} else {
|
||||
ctx->print("%s = <undefined>", name.c_str());
|
||||
}
|
||||
@@ -224,7 +303,7 @@ pst_type* __pst_parameter::next_type(pst_type* t)
|
||||
return next;
|
||||
}
|
||||
|
||||
bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
|
||||
bool __pst_parameter::handle_dwarf(Dwarf_Die* result, __pst_function* fun)
|
||||
{
|
||||
die = result;
|
||||
|
||||
@@ -250,13 +329,8 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
|
||||
|
||||
dwarf_stack stack(ctx);
|
||||
char str[1024]; str[0] = 0;
|
||||
if(handle_location(ctx, attr, stack, pc, str, sizeof(str))) {
|
||||
if(stack.get_value(value)) {
|
||||
ctx->log(SEVERITY_DEBUG, "Parameter Location: %s ==> 0x%lX", str, value);
|
||||
if(handle_location(ctx, attr, location, pc, str, sizeof(str), fun)) {
|
||||
has_value = true;
|
||||
} else {
|
||||
ctx->log(SEVERITY_ERROR, "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);
|
||||
}
|
||||
@@ -272,20 +346,20 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
|
||||
case DW_FORM_data2:
|
||||
case DW_FORM_data4:
|
||||
case DW_FORM_data8:
|
||||
dwarf_formudata(attr, &value);
|
||||
dwarf_formudata(attr, &location.value);
|
||||
has_value = true;
|
||||
break;
|
||||
case DW_FORM_sdata:
|
||||
dwarf_formsdata(attr, (int64_t*)&value);
|
||||
dwarf_formsdata(attr, (int64_t*)&location.value);
|
||||
has_value = true;
|
||||
break;
|
||||
case DW_FORM_udata:
|
||||
dwarf_formudata(attr, &value);
|
||||
dwarf_formudata(attr, &location.value);
|
||||
has_value = true;
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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* 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)
|
||||
{
|
||||
params.Remove(p);
|
||||
|
||||
delete p;
|
||||
}
|
||||
|
||||
@@ -336,6 +416,17 @@ pst_call_site_param* __pst_call_site::next_param(pst_call_site_param* p)
|
||||
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)
|
||||
{
|
||||
Dwarf_Attribute attr_mem;
|
||||
@@ -350,19 +441,12 @@ bool __pst_call_site::handle_dwarf(Dwarf_Die* child)
|
||||
|
||||
char str[1024];
|
||||
// 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)) {
|
||||
// handle location expression here
|
||||
// determine location of parameter in stack/heap or CPU registers
|
||||
attr = dwarf_attr(child, DW_AT_location, &attr_mem);
|
||||
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 {
|
||||
if(!handle_location(ctx, attr, param->location, pc, str, sizeof(str))) {
|
||||
ctx->log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", str);
|
||||
del_param(param);
|
||||
return false;
|
||||
@@ -374,14 +458,10 @@ bool __pst_call_site::handle_dwarf(Dwarf_Die* child)
|
||||
// handle value expression here
|
||||
attr = dwarf_attr(child, DW_AT_GNU_call_site_value, &attr_mem);
|
||||
dwarf_stack stack(ctx);
|
||||
if(handle_location(ctx, attr, stack, pc, str, sizeof(str))) {
|
||||
if(stack.get_value(param->value)) {
|
||||
pst_dwarf_expr loc;
|
||||
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);
|
||||
} else {
|
||||
ctx->log(SEVERITY_ERROR, "Failed to get value of calculated DW_AT_location expression: %s", str);
|
||||
del_param(param);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
ctx->log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", str);
|
||||
del_param(param);
|
||||
@@ -418,6 +498,14 @@ void __pst_function::clear()
|
||||
params.Remove(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)
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
char* at = NULL;
|
||||
@@ -588,7 +687,7 @@ bool __pst_function::handle_lexical_block(Dwarf_Die* result)
|
||||
break;
|
||||
case DW_TAG_variable: {
|
||||
pst_parameter* param = add_param();
|
||||
if(!param->handle_dwarf(&child)) {
|
||||
if(!param->handle_dwarf(&child, this)) {
|
||||
del_param(param);
|
||||
}
|
||||
break;
|
||||
@@ -639,18 +738,11 @@ bool __pst_function::handle_call_site(Dwarf_Die* result)
|
||||
if(dwarf_hasattr (result, DW_AT_GNU_call_site_target)) {
|
||||
attr = dwarf_attr(result, DW_AT_GNU_call_site_target, &attr_mem);
|
||||
if(attr) {
|
||||
dwarf_stack stack(ctx);
|
||||
char str[1024]; str[0] = 0;
|
||||
if(handle_location(ctx, &attr_mem, stack, pc, str, sizeof(str))) {
|
||||
if(stack.get_value(target)) {
|
||||
ctx->log(SEVERITY_DEBUG, "\tDW_AT_GNU_call_site_target: %s ==> %#lX", str, (void*)target);
|
||||
} else {
|
||||
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;
|
||||
pst_dwarf_expr expr;
|
||||
if(handle_location(ctx, &attr_mem, expr, pc, str, sizeof(str), this)) {
|
||||
target = expr.value;
|
||||
ctx->log(SEVERITY_DEBUG, "\tDW_AT_GNU_call_site_target: %#lX", target);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -707,7 +799,7 @@ bool __pst_function::handle_dwarf(Dwarf_Die* d)
|
||||
char str[1024]; str[0] = 0;
|
||||
ctx->print_expr_block (expr, exprlen, str, sizeof(str), attr);
|
||||
dwarf_stack stack(ctx);
|
||||
if(stack.calc_expression(expr, exprlen, attr)) {
|
||||
if(stack.calc_expression(expr, exprlen, attr, this)) {
|
||||
uint64_t value;
|
||||
if(stack.get_value(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_variable: {
|
||||
pst_parameter* param = add_param();
|
||||
if(!param->handle_dwarf(&result)) {
|
||||
if(!param->handle_dwarf(&result, this)) {
|
||||
del_param(param);
|
||||
}
|
||||
|
||||
@@ -1012,7 +1104,8 @@ bool __pst_handler::handle_dwarf()
|
||||
{
|
||||
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);
|
||||
module = dwfl_addrmodule(dwfl, fun->pc);
|
||||
ctx.base_addr = (uint64_t)info.dli_fbase;
|
||||
|
||||
+47
-10
@@ -24,9 +24,43 @@
|
||||
|
||||
#include "common.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 {
|
||||
__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
|
||||
} pst_type;
|
||||
|
||||
typedef struct __pst_function pst_function;
|
||||
|
||||
typedef struct __pst_parameter : public SC_ListNode {
|
||||
__pst_parameter(pst_context* c) : ctx(c)
|
||||
{
|
||||
@@ -48,7 +84,6 @@ typedef struct __pst_parameter : public SC_ListNode {
|
||||
is_return = false;
|
||||
is_variable = false;
|
||||
has_value = false;
|
||||
value = 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* 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 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_variable;// whether this parameter is function variable or argument of function
|
||||
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_parameter;
|
||||
|
||||
// DW_TAG_call_site_parameter
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
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
|
||||
} pst_call_site_param;
|
||||
|
||||
@@ -120,6 +157,7 @@ typedef struct __pst_call_site : public SC_ListNode {
|
||||
pst_call_site_param* add_param();
|
||||
void del_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);
|
||||
|
||||
@@ -130,8 +168,6 @@ typedef struct __pst_call_site : public SC_ListNode {
|
||||
pst_context* ctx;
|
||||
} pst_call_site;
|
||||
|
||||
typedef struct __pst_handler pst_handler;
|
||||
|
||||
typedef struct __pst_function : public SC_ListNode {
|
||||
__pst_function(pst_context* _ctx, __pst_function* _parent) : ctx(_ctx) {
|
||||
pc = 0;
|
||||
@@ -165,6 +201,7 @@ typedef struct __pst_function : public SC_ListNode {
|
||||
bool print_dwarf();
|
||||
bool handle_lexical_block(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 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
|
||||
int line; // line in code 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_function;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user