From 810ce7519d0ed2a8c11af21e582a9cb99b0cc46f Mon Sep 17 00:00:00 2001 From: Nikolai Nosov Date: Mon, 3 Feb 2020 15:04:09 +0400 Subject: [PATCH] do not use struct function pointers elsewhere, use them only in case when polymorphysm needed --- framework/dwarf_call_site.cpp | 69 +--- framework/dwarf_call_site.h | 45 +-- framework/dwarf_expression.cpp | 76 ++-- framework/dwarf_expression.h | 14 +- framework/dwarf_function.cpp | 695 ++++++++++++++++----------------- framework/dwarf_function.h | 17 +- framework/dwarf_operations.cpp | 152 +++---- framework/dwarf_parameter.cpp | 103 +++-- framework/dwarf_parameter.h | 12 +- framework/dwarf_stack.cpp | 49 ++- framework/dwarf_stack.h | 41 +- framework/dwarf_utils.cpp | 12 +- framework/sysutils.cpp | 51 +-- framework/sysutils.h | 16 +- main.cpp | 6 +- 15 files changed, 609 insertions(+), 749 deletions(-) diff --git a/framework/dwarf_call_site.cpp b/framework/dwarf_call_site.cpp index 99f9283..b8fb10f 100644 --- a/framework/dwarf_call_site.cpp +++ b/framework/dwarf_call_site.cpp @@ -17,16 +17,8 @@ // ----------------------------------------------------------------------------------- // pst_call_site_param // ----------------------------------------------------------------------------------- -void param_set_location(pst_call_site_param* param, Dwarf_Op* expr, size_t exprlen) -{ - param->location.setup(¶m->location, expr, exprlen); -} - void pst_call_site_param_init(pst_call_site_param* param) { - // methods - param->set_location = param_set_location; - // fields param->param = NULL; param->name = NULL; @@ -61,7 +53,7 @@ void pst_call_site_param_fini(pst_call_site_param* param) // ----------------------------------------------------------------------------------- // pst_call_site // ----------------------------------------------------------------------------------- -pst_call_site_param* site_add_param(pst_call_site* site) +pst_call_site_param* add_param(pst_call_site* site) { pst_call_site_param* p = pst_call_site_param_new(); pst_call_site_param_init(p); @@ -70,13 +62,13 @@ pst_call_site_param* site_add_param(pst_call_site* site) return p; } -void site_del_param(pst_call_site*, pst_call_site_param* p) +void del_param(pst_call_site*, pst_call_site_param* p) { list_del(&p->node); pst_call_site_param_fini(p); } -pst_call_site_param* site_next_param(pst_call_site* site, pst_call_site_param* p) +pst_call_site_param* next_param(pst_call_site* site, pst_call_site_param* p) { list_node* n = (p == NULL) ? list_first(&site->params) : list_next(&p->node); pst_call_site_param* ret = NULL; @@ -87,10 +79,10 @@ pst_call_site_param* site_next_param(pst_call_site* site, pst_call_site_param* p return ret; } -pst_call_site_param* site_find_param(pst_call_site* site, pst_dwarf_expr* expr) +pst_call_site_param* pst_call_site_find(pst_call_site* site, pst_dwarf_expr* expr) { - for(pst_call_site_param* param = site_next_param(site, NULL); param; param = site_next_param(site, param)) { - if(param->location.is_equal(¶m->location, expr)) { + for(pst_call_site_param* param = next_param(site, NULL); param; param = next_param(site, param)) { + if(pst_dwarf_expr_equal(¶m->location, expr)) { return param; } } @@ -98,7 +90,7 @@ pst_call_site_param* site_find_param(pst_call_site* site, pst_dwarf_expr* expr) return NULL; } -bool site_handle_dwarf(pst_call_site* site, Dwarf_Die* child) +bool handle_dwarf(pst_call_site* site, Dwarf_Die* child) { Dwarf_Attribute attr_mem; Dwarf_Attribute* attr; @@ -110,14 +102,14 @@ bool site_handle_dwarf(pst_call_site* site, Dwarf_Die* child) unw_get_reg(site->ctx->curr_frame, UNW_REG_IP, &pc); // expression represent where callee parameter will be stored - pst_call_site_param* param = site->add_param(site); + pst_call_site_param* param = add_param(site); 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(site->ctx, attr, ¶m->location, pc, NULL)) { pst_log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", site->ctx->buff); - site->del_param(site, param); + del_param(site, param); return false; } } @@ -133,7 +125,7 @@ bool site_handle_dwarf(pst_call_site* site, Dwarf_Die* child) pst_log(SEVERITY_DEBUG, "\tDW_AT_GNU_call_site_value:\"%s\" ==> 0x%lX", site->ctx->buff, param->value); } else { pst_log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", site->ctx->buff); - site->del_param(site, param); + del_param(site, param); return false; } } @@ -149,14 +141,6 @@ bool site_handle_dwarf(pst_call_site* site, Dwarf_Die* child) void pst_call_site_init(pst_call_site* site, pst_context* c, uint64_t tgt, const char* orn) { - // methods - site->add_param = site_add_param; - site->del_param = site_del_param; - site->next_param = site_next_param; - site->find_param = site_find_param; - site->handle_dwarf = site_handle_dwarf; - - // fields list_node_init(&site->node); site->target = tgt; @@ -209,7 +193,7 @@ void pst_call_site_fini(pst_call_site* site) // DW_TAG_GNU_call_site_parameter is defined under child DIE of DW_TAG_GNU_call_site and defines value of subroutine before calling it // relates to DW_OP_GNU_entry_value() handling in callee function to determine the value of an argument/variable of the callee // get DIE of return type -bool storage_handle_dwarf(pst_call_site_storage* storage, Dwarf_Die* result, pst_function* info) +bool pst_call_site_storage_handle_dwarf(pst_call_site_storage* storage, Dwarf_Die* result, pst_function* info) { Dwarf_Die origin; Dwarf_Attribute attr_mem; @@ -246,9 +230,9 @@ bool storage_handle_dwarf(pst_call_site_storage* storage, Dwarf_Die* result, pst Dwarf_Die child; if(dwarf_child (result, &child) == 0) { - pst_call_site* st = storage->add_call_site(storage, target, oname); - if(!st->handle_dwarf(st, &child)) { - storage->del_call_site(storage, st); + pst_call_site* st = pst_call_site_storage_add(storage, target, oname); + if(!handle_dwarf(st, &child)) { + pst_call_site_storage_del(storage, st); return false; } } @@ -278,7 +262,7 @@ pst_call_site* storage_call_site_by_target(pst_call_site_storage* storage, uint6 return ret; } -pst_call_site* storage_add_call_site(pst_call_site_storage* storage, uint64_t target, const char* origin) +pst_call_site* pst_call_site_storage_add(pst_call_site_storage* storage, uint64_t target, const char* origin) { pst_new(pst_call_site, st, storage->ctx, target, origin); list_add_bottom(&storage->call_sites, &st->node); @@ -292,7 +276,7 @@ pst_call_site* storage_add_call_site(pst_call_site_storage* storage, uint64_t ta return st; } -void storage_del_call_site(pst_call_site_storage* storage, pst_call_site* st) +void pst_call_site_storage_del(pst_call_site_storage* storage, pst_call_site* st) { hash_node* node = NULL; list_del(&st->node); @@ -309,19 +293,8 @@ void storage_del_call_site(pst_call_site_storage* storage, pst_call_site* st) pst_free(st); } -pst_call_site* storage_next_call_site(pst_call_site_storage* storage, pst_call_site* st) -{ - struct list_node* n = (st == NULL) ? list_first(&storage->call_sites) : list_next(&st->node); - pst_call_site* ret = NULL; - if(n) { - ret = list_entry(n, pst_call_site, node); - } - - return ret; -} - -pst_call_site* storage_find_call_site(pst_call_site_storage* storage, pst_function* callee) +pst_call_site* pst_call_site_storage_find(pst_call_site_storage* storage, pst_function* callee) { uint64_t start_pc = storage->ctx->base_addr + callee->lowpc; pst_call_site* cs = storage_call_site_by_target(storage, start_pc); @@ -334,14 +307,6 @@ pst_call_site* storage_find_call_site(pst_call_site_storage* storage, pst_functi void pst_call_site_storage_init(pst_call_site_storage* storage, pst_context* ctx) { - // methods - storage->handle_dwarf = storage_handle_dwarf; - storage->add_call_site = storage_add_call_site; - storage->del_call_site = storage_del_call_site; - storage->find_call_site = storage_find_call_site; - storage->next_call_site = storage_next_call_site; - - // fields storage->ctx = ctx; list_head_init(&storage->call_sites); hash_head_init(&storage->cs_to_target); diff --git a/framework/dwarf_call_site.h b/framework/dwarf_call_site.h index bfea109..d0f85e9 100644 --- a/framework/dwarf_call_site.h +++ b/framework/dwarf_call_site.h @@ -29,15 +29,11 @@ typedef struct pst_callee_info { typedef struct pst_call_site_param { list_node node; // uplink. !!! must be first !!! - // methods - void (*set_location) (pst_call_site_param* param, Dwarf_Op* expr, size_t exprlen); - - // fields - Dwarf_Die* param; // reference to parameter DIE in callee (DW_AT_call_parameter) - char* name; // name of parameter if present (DW_AT_name) - pst_dwarf_expr location; // DWARF stack containing location expression - uint64_t value; // parameter's value - bool allocated; // whether this object was allocated or not + Dwarf_Die* param; // reference to parameter DIE in callee (DW_AT_call_parameter) + char* name; // name of parameter if present (DW_AT_name) + pst_dwarf_expr location; // DWARF stack containing location expression + uint64_t value; // parameter's value + bool allocated; // whether this object was allocated or not } pst_call_site_param; void pst_call_site_param_init(pst_call_site_param* param); @@ -49,18 +45,10 @@ void pst_call_site_param_fini(pst_call_site_param* param); // DW_TAG_call_site // ----------------------------------------------------------------------------------- typedef struct pst_call_site { - list_node node; // uplink. !!! must be first !!! - hash_node tgt_node; - hash_node org_node; + list_node node; // uplink to list of call-sites + hash_node tgt_node; // uplink to call-site by node dictionary + hash_node org_node; // uplink to call-site by origin dictionary - // methods - pst_call_site_param* (*add_param) (pst_call_site* site); - void (*del_param) (pst_call_site* site, pst_call_site_param* p); - pst_call_site_param* (*next_param) (pst_call_site* site, pst_call_site_param* p); - pst_call_site_param* (*find_param) (pst_call_site* site, pst_dwarf_expr* expr); - bool (*handle_dwarf) (pst_call_site* site, Dwarf_Die* die); - - // fields uint64_t target; // pointer to callee function's (it's Low PC + base address) char* origin; // name of callee function Dwarf_Die* die; // DIE of function for which this call site has parameters @@ -72,19 +60,14 @@ void pst_call_site_init(pst_call_site* site, pst_context* context, uint64_t targ pst_call_site* pst_call_site_new(pst_context* context, uint64_t target, const char* origin); void pst_call_site_fini(pst_call_site* site); +pst_call_site_param* pst_call_site_find(pst_call_site* site, pst_dwarf_expr* expr); +bool pst_call_site_handle_dwarf(pst_call_site* site, Dwarf_Die* child); + typedef struct __pst_function pst_function; // ----------------------------------------------------------------------------------- // storage for all of function's call sites // ----------------------------------------------------------------------------------- typedef struct pst_call_site_storage { - // methods - bool (*handle_dwarf) (pst_call_site_storage* storage, Dwarf_Die* result, pst_function* info); - pst_call_site* (*add_call_site) (pst_call_site_storage* storage, uint64_t target, const char* origin); - void (*del_call_site) (pst_call_site_storage* storage, pst_call_site* site); - pst_call_site* (*find_call_site) (pst_call_site_storage* storage, pst_function* callee); - pst_call_site* (*next_call_site) (pst_call_site_storage* storage, pst_call_site* st); - - // fields pst_context* ctx; list_head call_sites; // Call-Site definitions hash_head cs_to_target; // map pointer to caller to call-site @@ -96,5 +79,11 @@ void pst_call_site_storage_init(pst_call_site_storage* storage, pst_context* ctx pst_call_site_storage* pst_call_site_storage_new(pst_context* ctx); void pst_call_site_storage_fini(pst_call_site_storage* storage); +bool pst_call_site_storage_handle_dwarf(pst_call_site_storage* storage, Dwarf_Die* result, pst_function* info); +pst_call_site* pst_call_site_storage_find(pst_call_site_storage* storage, pst_function* callee); +pst_call_site* pst_call_site_storage_add(pst_call_site_storage* storage, uint64_t target, const char* origin); +void pst_call_site_storage_del(pst_call_site_storage* storage, pst_call_site* st); +void pst_call_site_storage_del(pst_call_site_storage* storage, pst_call_site* st); + #endif /* FRAMEWORK_DWARF_CALL_SITE_H_ */ diff --git a/framework/dwarf_expression.cpp b/framework/dwarf_expression.cpp index 7bac984..85f531b 100644 --- a/framework/dwarf_expression.cpp +++ b/framework/dwarf_expression.cpp @@ -53,26 +53,7 @@ void pst_dwarf_op_fini(pst_dwarf_op* dwop) // // pst_dwarf_expr // -bool expr_is_equal(pst_dwarf_expr* lhs, pst_dwarf_expr* rhs) -{ - if(list_count(&lhs->operations) != list_count(&rhs->operations)) { - return false; - } - - pst_dwarf_op* lop = lhs->next_op(lhs, NULL); - pst_dwarf_op* rop = rhs->next_op(rhs, NULL); - while(lop && rop) { - if(lop->operation == rop->operation && lop->arg1 == rop->arg1 && lop->arg2 == rop->arg2) { - return true; - } - lop = lhs->next_op(lhs, lop); - rop = rhs->next_op(rhs, rop); - } - - return false; -} - -pst_dwarf_op* expr_add_op(pst_dwarf_expr* expr, uint8_t operation, uint64_t arg1, uint64_t arg2) +pst_dwarf_op* add_op(pst_dwarf_expr* expr, uint8_t operation, uint64_t arg1, uint64_t arg2) { pst_new(pst_dwarf_op, op, operation, arg1, arg2); list_add_bottom(&expr->operations, &op->node); @@ -80,7 +61,7 @@ pst_dwarf_op* expr_add_op(pst_dwarf_expr* expr, uint8_t operation, uint64_t arg1 return op; } -pst_dwarf_op* expr_next_op(pst_dwarf_expr* expr, pst_dwarf_op* op) +pst_dwarf_op* next_op(pst_dwarf_expr* expr, pst_dwarf_op* op) { struct list_node* n = (op == NULL) ? list_first(&expr->operations) : list_next(&op->node); @@ -92,7 +73,17 @@ pst_dwarf_op* expr_next_op(pst_dwarf_expr* expr, pst_dwarf_op* op) return ret; } -bool expr_print_op(pst_dwarf_expr* expr, const char* fmt, ...) +void clean(pst_dwarf_expr* expr) +{ + pst_dwarf_op* op = NULL; + struct list_node *pos, *tn; + list_for_each_entry_safe(op, pos, tn, &expr->operations, node) { + list_del(&op->node); + pst_dwarf_op_fini(op); + } +} + +bool pst_dwarf_expr_print_op(pst_dwarf_expr* expr, const char* fmt, ...) { bool nret = true; @@ -109,42 +100,41 @@ bool expr_print_op(pst_dwarf_expr* expr, const char* fmt, ...) return nret; } -void expr_set_value(pst_dwarf_expr* expr, uint64_t v) +void pst_dwarf_expr_set_value(pst_dwarf_expr* expr, uint64_t v) { expr->has_value = true; expr->value = v; } -void expr_clean(pst_dwarf_expr* expr) +bool pst_dwarf_expr_equal(pst_dwarf_expr* lhs, pst_dwarf_expr* rhs) { - pst_dwarf_op* op = NULL; - struct list_node *pos, *tn; - list_for_each_entry_safe(op, pos, tn, &expr->operations, node) { - list_del(&op->node); - pst_dwarf_op_fini(op); + if(list_count(&lhs->operations) != list_count(&rhs->operations)) { + return false; } + + pst_dwarf_op* lop = next_op(lhs, NULL); + pst_dwarf_op* rop = next_op(rhs, NULL); + while(lop && rop) { + if(lop->operation == rop->operation && lop->arg1 == rop->arg1 && lop->arg2 == rop->arg2) { + return true; + } + lop = next_op(lhs, lop); + rop = next_op(rhs, rop); + } + + return false; } -void expr_setup(pst_dwarf_expr* expr, Dwarf_Op* exprs, size_t exprlen) +void pst_dwarf_expr_setup(pst_dwarf_expr* expr, Dwarf_Op* exprs, size_t exprlen) { - expr->clean(expr); + clean(expr); for(size_t i = 0; i < exprlen; ++i) { - expr->add_op(expr, exprs[i].atom, exprs[i].number, exprs[i].number2); + add_op(expr, exprs[i].atom, exprs[i].number, exprs[i].number2); } } void pst_dwarf_expr_init(pst_dwarf_expr* expr) { - // methods - expr->is_equal = expr_is_equal; - expr->add_op = expr_add_op; - expr->next_op = expr_next_op; - expr->clean = expr_clean; - expr->setup = expr_setup; - expr->set_value = expr_set_value; - expr->print_op = expr_print_op; - - // fields list_head_init(&expr->operations); expr->has_value = false; expr->value = 0; @@ -167,7 +157,7 @@ pst_dwarf_expr* pst_dwarf_expr_new() void pst_dwarf_expr_fini(pst_dwarf_expr* expr) { - expr->clean(expr); + clean(expr); if(expr->allocated) { pst_free(expr); } diff --git a/framework/dwarf_expression.h b/framework/dwarf_expression.h index 9f438a4..3ec85a1 100644 --- a/framework/dwarf_expression.h +++ b/framework/dwarf_expression.h @@ -30,16 +30,6 @@ void pst_dwarf_op_fini(pst_dwarf_op* dwop); // DWARF expression typedef struct pst_dwarf_expr { - // methods - bool (*is_equal)(pst_dwarf_expr* lhs, pst_dwarf_expr* rhs); - pst_dwarf_op* (*add_op) (pst_dwarf_expr* expr, uint8_t op, uint64_t arg1, uint64_t arg2); - pst_dwarf_op* (*next_op) (pst_dwarf_expr* expr, pst_dwarf_op* op); - void (*clean) (pst_dwarf_expr* expr); - void (*setup) (pst_dwarf_expr* expr, Dwarf_Op* exprs, size_t exprlen); - void (*set_value) (pst_dwarf_expr* expr, uint64_t v); - bool (*print_op) (pst_dwarf_expr* expr, const char* fmt, ...); - - // fields list_head operations; bool has_value; uint64_t value; @@ -51,5 +41,9 @@ void pst_dwarf_expr_init(pst_dwarf_expr* expr); pst_dwarf_expr* pst_dwarf_expr_new(); void pst_dwarf_expr_fini(pst_dwarf_expr* expr); +void pst_dwarf_expr_setup(pst_dwarf_expr* expr, Dwarf_Op* exprs, size_t exprlen); +bool pst_dwarf_expr_equal(pst_dwarf_expr* lhs, pst_dwarf_expr* rhs); +bool pst_dwarf_expr_print_op(pst_dwarf_expr* expr, const char* fmt, ...); +void pst_dwarf_expr_set_value(pst_dwarf_expr* expr, uint64_t v); #endif /* FRAMEWORK_DWARF_EXPRESSION_H_ */ diff --git a/framework/dwarf_function.cpp b/framework/dwarf_function.cpp index 03beb8a..ed1a7e1 100644 --- a/framework/dwarf_function.cpp +++ b/framework/dwarf_function.cpp @@ -16,346 +16,7 @@ // ----------------------------------------------------------------------------------- // pst_function // ----------------------------------------------------------------------------------- -pst_parameter* fn_add_param(pst_function* fn) -{ - pst_new(pst_parameter, p, fn->ctx); - list_add_bottom(&fn->params, &p->node); - - return p; -} - -void fn_del_param(pst_parameter* p) -{ - list_del(&p->node); - pst_free(p); -} - -void fn_clear(pst_function* fn) -{ - pst_parameter* param = NULL; - struct list_node *pos, *tn; - list_for_each_entry_safe(param, pos, tn, &fn->params, node) { - list_del(¶m->node); - pst_parameter_fini(param); - } - - pst_call_site_storage_fini(&fn->call_sites); -} - -pst_parameter* fn_next_param(pst_function* fn, pst_parameter* p) -{ - struct list_node* n = (p == NULL) ? list_first(&fn->params) : list_next(&p->node); - - pst_parameter* ret = NULL; - if(n) { - ret = list_entry(n, pst_parameter, node); - } - - return ret; -} - -bool fn_print_dwarf(pst_function* fn) -{ - char* at = NULL; - if(!asprintf(&at, " at %s:%d, %p", fn->file, fn->line, (void*)fn->pc)) { - return false; - } - if(at[4] == ':' && at[5] == '-') { - free(at); - if(!asprintf(&at, " at %p", (void*)fn->pc)) { - return false; - } - } - //ctx->print(ctx, "%s:%d: ", file.c_str(), line); - - // handle return parameter and be safe if function haven't parameters (for example, dwar info for function is absent) - pst_parameter* param = fn->next_param(fn, NULL); - if(param && param->is_return) { - // print return value type, function name and start list of parameters - param->print_dwarf(param); - fn->ctx->print(fn->ctx, " %s(", fn->name); - param = fn->next_param(fn, param); - } else { - fn->ctx->print(fn->ctx, "%s(", fn->name); - } - - bool first = true; bool start_variable = false; - for(; param; param = fn->next_param(fn, param)) { - if(param->is_return) { - // print return value type, function name and start list of parameters - param->print_dwarf(param); - fn->ctx->print(fn->ctx, " %s(", fn->name); - continue; - } - - if(param->is_variable) { - if(!start_variable) { - fn->ctx->print(fn->ctx, ")%s\n", at); - fn->ctx->print(fn->ctx, "{\n"); - start_variable = true; - } - if(param->line) { - fn->ctx->print(fn->ctx, "%04u: ", param->line); - } else { - fn->ctx->print(fn->ctx, " "); - } - param->print_dwarf(param); - fn->ctx->print(fn->ctx, ";\n"); - } else { - if(first) { - first = false; - } else { - fn->ctx->print(fn->ctx, ", "); - } - param->print_dwarf(param); - } - } - - if(!start_variable) { - fn->ctx->print(fn->ctx, ");%s\n", at); - } else { - fn->ctx->print(fn->ctx, "}\n"); - } - - free(at); - return true; -} - -bool fn_handle_lexical_block(pst_function* fn, Dwarf_Die* result) -{ - uint64_t lowpc = 0, highpc = 0; const char* origin_name = ""; - dwarf_lowpc(result, &lowpc); - dwarf_highpc(result, &lowpc); - - Dwarf_Attribute attr_mem; - Dwarf_Die origin; - if(dwarf_hasattr (result, DW_AT_abstract_origin) && dwarf_formref_die (dwarf_attr (result, DW_AT_abstract_origin, &attr_mem), &origin) != NULL) { - origin_name = dwarf_diename(&origin); - Dwarf_Die child; - if(dwarf_child (&origin, &child) == 0) { - do { - switch (dwarf_tag (&child)) - { - case DW_TAG_variable: - case DW_TAG_formal_parameter: - pst_log(SEVERITY_DEBUG, "Abstract origin: %s('%s')", dwarf_diename(&origin), dwarf_diename (&child)); - break; - // Also handle DW_TAG_unspecified_parameters (unknown number of arguments i.e. fun(arg1, ...); - default: - break; - } - } while (dwarf_siblingof (&child, &child) == 0); - } - } - const char* die_name = ""; - if(dwarf_diename(result)) { - die_name = dwarf_diename(result); - } - pst_log(SEVERITY_DEBUG, "Lexical block with name '%s', tag 0x%X and origin '%s' found. lowpc = 0x%lX, highpc = 0x%lX", die_name, dwarf_tag (result), origin_name, lowpc, highpc); - Dwarf_Die child; - if(dwarf_child (result, &child) == 0) { - do { - switch (dwarf_tag (&child)) { - case DW_TAG_lexical_block: - fn->handle_lexical_block(fn, &child); - break; - case DW_TAG_variable: { - pst_parameter* param = fn->add_param(fn); - if(!param->handle_dwarf(param, &child, fn)) { - fn->del_param(param); - } - break; - } - case DW_TAG_GNU_call_site: - fn->call_sites.handle_dwarf(&fn->call_sites, &child, fn); - break; - case DW_TAG_inlined_subroutine: - pst_log(SEVERITY_DEBUG, "Skipping Lexical block tag 'DW_TAG_inlined_subroutine'"); - break; - default: - pst_log(SEVERITY_DEBUG, "Unknown Lexical block tag 0x%X", dwarf_tag(&child)); - break; - } - }while (dwarf_siblingof (&child, &child) == 0); - } - - return true; -} - -bool fn_handle_dwarf(pst_function * fn, Dwarf_Die* d) -{ - fn->die = d; - fn->get_frame(fn); - - Dwarf_Attribute attr_mem; - Dwarf_Attribute* attr; - - // get list of offsets from process base address of continuous memory ranges where function's code resides -// if(dwarf_haspc(d, pc)) { - dwarf_lowpc(d, &fn->lowpc); - dwarf_highpc(d, &fn->highpc); -// } else { -// pst_log(SEVERITY_ERROR, "Function's '%s' DIE hasn't definitions of memory offsets of function's code", dwarf_diename(d)); -// return false; -// } - - unw_proc_info_t info; - unw_get_proc_info(&fn->cursor, &info); - fn->ctx->clean_print(fn->ctx); - - pst_log(SEVERITY_INFO, "Function %s(...): LOW_PC = %#lX, HIGH_PC = %#lX, offset from base address: 0x%lX, START_PC = 0x%lX, offset from start of function: 0x%lX", - dwarf_diename(d), fn->lowpc, fn->highpc, fn->pc - fn->ctx->base_addr, info.start_ip, info.start_ip - fn->ctx->base_addr); - fn->ctx->print_registers(fn->ctx, 0x0, 0x10); - pst_log(SEVERITY_INFO, "Function %s(...): CFA: %#lX %s", dwarf_diename(d), fn->parent ? fn->parent->sp : 0, fn->ctx->buff); - pst_log(SEVERITY_INFO, "Function %s(...): %s", dwarf_diename(d), fn->ctx->buff); - - // determine function's stack frame base - attr = dwarf_attr(fn->die, DW_AT_frame_base, &attr_mem); - if(attr) { - if(dwarf_hasform(attr, DW_FORM_exprloc)) { - Dwarf_Op *expr; - size_t exprlen; - if (dwarf_getlocation (attr, &expr, &exprlen) == 0) { - fn->ctx->print_expr(fn->ctx, expr, exprlen, attr); - pst_decl(pst_dwarf_stack, stack, fn->ctx); - if(stack.calc(&stack, expr, exprlen, attr, fn)) { - uint64_t value; - if(stack.get_value(&stack, &value)) { - pst_log(SEVERITY_DEBUG, "DW_AT_framebase expression: \"%s\" ==> 0x%lX", fn->ctx->buff, value); - } else { - pst_log(SEVERITY_ERROR, "Failed to get value of calculated DW_AT_framebase expression: %s", fn->ctx->buff); - } - } else { - pst_log(SEVERITY_ERROR, "Failed to calculate DW_AT_framebase expression: %s", fn->ctx->buff); - } - pst_dwarf_stack_fini(&stack); - } else { - pst_log(SEVERITY_WARNING, "Unknown attribute form = 0x%X, code = 0x%X", attr->form, attr->code); - } - } - } - - // Get reference to return attribute type of the function - // may be to use dwfl_module_return_value_location() instead - pst_parameter* ret_p = fn->add_param(fn); ret_p->is_return = true; - attr = dwarf_attr(fn->die, DW_AT_type, &attr_mem); - if(attr) { - if(!ret_p->handle_type(ret_p, attr)) { - pst_log(SEVERITY_ERROR, "Failed to handle return parameter type for function %s(...)", fn->name); - fn->del_param(ret_p); - } - } else { - ret_p->add_type(ret_p, "void", 0); - } - - // handle and save additionally these attributes: - // 1. string of DW_AT_linkage_name (mangled name of program if any) - // A debugging information entry may have a DW_AT_linkage_name attribute - // whose value is a null-terminated string containing the object file linkage name - // associated with the corresponding entity. - - // 2. flag DW_AT_external attribute - // A DW_AT_external attribute, which is a flag, if the name of a variable is - // visible outside of its enclosing compilation unit. - - // 3. A subroutine entry may contain a DW_AT_main_subprogram attribute which is - // a flag whose presence indicates that the subroutine has been identified as the - // starting function of the program. If more than one subprogram contains this flag, - // any one of them may be the starting subroutine of the program. - - - Dwarf_Die result; - if(dwarf_child(fn->die, &result) != 0) - return false; - - // went through parameters and local variables of the function - do { - switch (dwarf_tag(&result)) { - case DW_TAG_formal_parameter: - case DW_TAG_variable: { - pst_parameter* param = fn->add_param(fn); - if(!param->handle_dwarf(param, &result, fn)) { - fn->del_param(param); - } - - break; - } - case DW_TAG_GNU_call_site: - fn->call_sites.handle_dwarf(&fn->call_sites, &result, fn); - break; - - // case DW_TAG_inlined_subroutine: - // /* Recurse further down */ - // HandleFunction(&result); - // break; - case DW_TAG_lexical_block: { - fn->handle_lexical_block(fn, &result); - break; - } - // Also handle: - // DW_TAG_unspecified_parameters (unknown number of arguments i.e. fun(arg1, ...); - // DW_AT_inline - default: - pst_log(SEVERITY_DEBUG, "Unknown TAG of function: 0x%X", dwarf_tag(&result)); - break; - } - } while(dwarf_siblingof(&result, &result) == 0); - - return true; -} - -bool fn_unwind(pst_function* fn, Dwarf_Addr addr) -{ - fn->pc = addr; - - Dwfl_Line *dwline = dwfl_getsrc(fn->ctx->dwfl, addr); - if(dwline != NULL) { - Dwarf_Addr addr; - const char* filename = dwfl_lineinfo (dwline, &addr, &fn->line, NULL, NULL, NULL); - if(filename) { - const char* str = strrchr(filename, '/'); - if(str && *str != 0) { - str++; - } else { - str = filename; - } - fn->file = pst_strdup(str); - fn->ctx->print(fn->ctx, "%s:%d", str, fn->line); - } else { - fn->ctx->print(fn->ctx, "%p", (void*)addr); - } - } else { - fn->ctx->print(fn->ctx, "%p", (void*)addr); - } - - const char* addrname = dwfl_module_addrname(fn->ctx->module, addr); - char* demangle_name = NULL; - if(addrname) { - int status; - demangle_name = abi::__cxa_demangle(addrname, NULL, NULL, &status); - char* function_name = NULL; - if(asprintf(&function_name, "%s%s", demangle_name ? demangle_name : addrname, demangle_name ? "" : "()") == -1) { - pst_log(SEVERITY_ERROR, "Failed to allocate memory"); - return false; - } - fn->ctx->print(fn->ctx, " --> %s", function_name); - - char* str = strchr(function_name, '('); - if(str) { - *str = 0; - } - fn->name = pst_strdup(function_name); - free(function_name); - } - - if(demangle_name) { - free(demangle_name); - } - - return true; -} - -bool fn_get_frame(pst_function* fn) +bool get_frame(pst_function* fn) { // get CFI (Call Frame Information) for current module // from handle_cfi() @@ -409,7 +70,7 @@ bool fn_get_frame(pst_function* fn) fn->ctx->print_expr(fn->ctx, cfa_ops, cfa_nops, NULL); pst_decl(pst_dwarf_stack, stack, fn->ctx); - if(stack.calc(&stack, cfa_ops, cfa_nops, NULL, NULL) && stack.get_value(&stack, &fn->cfa)) { + if(pst_dwarf_stack_calc(&stack, cfa_ops, cfa_nops, NULL, NULL) && pst_dwarf_stack_get_value(&stack, &fn->cfa)) { pst_log(SEVERITY_INFO, "Function %s(...): CFA expression: %s ==> %#lX", fn->name, fn->ctx->buff, fn->cfa); // setup context to match CFA for frame @@ -423,19 +84,347 @@ bool fn_get_frame(pst_function* fn) return true; } +pst_parameter* add_param(pst_function* fn) +{ + pst_new(pst_parameter, p, fn->ctx); + list_add_bottom(&fn->params, &p->node); + + return p; +} + +void del_param(pst_parameter* p) +{ + list_del(&p->node); + pst_free(p); +} + +void clear(pst_function* fn) +{ + pst_parameter* param = NULL; + struct list_node *pos, *tn; + list_for_each_entry_safe(param, pos, tn, &fn->params, node) { + list_del(¶m->node); + pst_parameter_fini(param); + } + + pst_call_site_storage_fini(&fn->call_sites); +} + +pst_parameter* next_param(pst_function* fn, pst_parameter* p) +{ + struct list_node* n = (p == NULL) ? list_first(&fn->params) : list_next(&p->node); + + pst_parameter* ret = NULL; + if(n) { + ret = list_entry(n, pst_parameter, node); + } + + return ret; +} + +bool handle_lexical_block(pst_function* fn, Dwarf_Die* result) +{ + uint64_t lowpc = 0, highpc = 0; const char* origin_name = ""; + dwarf_lowpc(result, &lowpc); + dwarf_highpc(result, &lowpc); + + Dwarf_Attribute attr_mem; + Dwarf_Die origin; + if(dwarf_hasattr (result, DW_AT_abstract_origin) && dwarf_formref_die (dwarf_attr (result, DW_AT_abstract_origin, &attr_mem), &origin) != NULL) { + origin_name = dwarf_diename(&origin); + Dwarf_Die child; + if(dwarf_child (&origin, &child) == 0) { + do { + switch (dwarf_tag (&child)) + { + case DW_TAG_variable: + case DW_TAG_formal_parameter: + pst_log(SEVERITY_DEBUG, "Abstract origin: %s('%s')", dwarf_diename(&origin), dwarf_diename (&child)); + break; + // Also handle DW_TAG_unspecified_parameters (unknown number of arguments i.e. fun(arg1, ...); + default: + break; + } + } while (dwarf_siblingof (&child, &child) == 0); + } + } + const char* die_name = ""; + if(dwarf_diename(result)) { + die_name = dwarf_diename(result); + } + pst_log(SEVERITY_DEBUG, "Lexical block with name '%s', tag 0x%X and origin '%s' found. lowpc = 0x%lX, highpc = 0x%lX", die_name, dwarf_tag (result), origin_name, lowpc, highpc); + Dwarf_Die child; + if(dwarf_child (result, &child) == 0) { + do { + switch (dwarf_tag (&child)) { + case DW_TAG_lexical_block: + handle_lexical_block(fn, &child); + break; + case DW_TAG_variable: { + pst_parameter* param = add_param(fn); + if(!pst_parameter_handle_dwarf(param, &child, fn)) { + del_param(param); + } + break; + } + case DW_TAG_GNU_call_site: + pst_call_site_storage_handle_dwarf(&fn->call_sites, &child, fn); + break; + case DW_TAG_inlined_subroutine: + pst_log(SEVERITY_DEBUG, "Skipping Lexical block tag 'DW_TAG_inlined_subroutine'"); + break; + default: + pst_log(SEVERITY_DEBUG, "Unknown Lexical block tag 0x%X", dwarf_tag(&child)); + break; + } + }while (dwarf_siblingof (&child, &child) == 0); + } + + return true; +} + +bool pst_function_print_dwarf(pst_function* fn) +{ + char* at = NULL; + if(!asprintf(&at, " at %s:%d, %p", fn->file, fn->line, (void*)fn->pc)) { + return false; + } + if(at[4] == ':' && at[5] == '-') { + free(at); + if(!asprintf(&at, " at %p", (void*)fn->pc)) { + return false; + } + } + //ctx->print(ctx, "%s:%d: ", file.c_str(), line); + + // handle return parameter and be safe if function haven't parameters (for example, dwar info for function is absent) + pst_parameter* param = next_param(fn, NULL); + if(param && param->is_return) { + // print return value type, function name and start list of parameters + pst_parameter_print_dwarf(param); + fn->ctx->print(fn->ctx, " %s(", fn->name); + param = next_param(fn, param); + } else { + fn->ctx->print(fn->ctx, "%s(", fn->name); + } + + bool first = true; bool start_variable = false; + for(; param; param = next_param(fn, param)) { + if(param->is_return) { + // print return value type, function name and start list of parameters + pst_parameter_print_dwarf(param); + fn->ctx->print(fn->ctx, " %s(", fn->name); + continue; + } + + if(param->is_variable) { + if(!start_variable) { + fn->ctx->print(fn->ctx, ")%s\n", at); + fn->ctx->print(fn->ctx, "{\n"); + start_variable = true; + } + if(param->line) { + fn->ctx->print(fn->ctx, "%04u: ", param->line); + } else { + fn->ctx->print(fn->ctx, " "); + } + pst_parameter_print_dwarf(param); + fn->ctx->print(fn->ctx, ";\n"); + } else { + if(first) { + first = false; + } else { + fn->ctx->print(fn->ctx, ", "); + } + pst_parameter_print_dwarf(param); + } + } + + if(!start_variable) { + fn->ctx->print(fn->ctx, ");%s\n", at); + } else { + fn->ctx->print(fn->ctx, "}\n"); + } + + free(at); + return true; +} + +bool pst_function_handle_dwarf(pst_function * fn, Dwarf_Die* d) +{ + fn->die = d; + get_frame(fn); + + Dwarf_Attribute attr_mem; + Dwarf_Attribute* attr; + + // get list of offsets from process base address of continuous memory ranges where function's code resides +// if(dwarf_haspc(d, pc)) { + dwarf_lowpc(d, &fn->lowpc); + dwarf_highpc(d, &fn->highpc); +// } else { +// pst_log(SEVERITY_ERROR, "Function's '%s' DIE hasn't definitions of memory offsets of function's code", dwarf_diename(d)); +// return false; +// } + + unw_proc_info_t info; + unw_get_proc_info(&fn->cursor, &info); + fn->ctx->clean_print(fn->ctx); + + pst_log(SEVERITY_INFO, "Function %s(...): LOW_PC = %#lX, HIGH_PC = %#lX, offset from base address: 0x%lX, START_PC = 0x%lX, offset from start of function: 0x%lX", + dwarf_diename(d), fn->lowpc, fn->highpc, fn->pc - fn->ctx->base_addr, info.start_ip, info.start_ip - fn->ctx->base_addr); + fn->ctx->print_registers(fn->ctx, 0x0, 0x10); + pst_log(SEVERITY_INFO, "Function %s(...): CFA: %#lX %s", dwarf_diename(d), fn->parent ? fn->parent->sp : 0, fn->ctx->buff); + pst_log(SEVERITY_INFO, "Function %s(...): %s", dwarf_diename(d), fn->ctx->buff); + + // determine function's stack frame base + attr = dwarf_attr(fn->die, DW_AT_frame_base, &attr_mem); + if(attr) { + if(dwarf_hasform(attr, DW_FORM_exprloc)) { + Dwarf_Op *expr; + size_t exprlen; + if (dwarf_getlocation (attr, &expr, &exprlen) == 0) { + fn->ctx->print_expr(fn->ctx, expr, exprlen, attr); + pst_decl(pst_dwarf_stack, stack, fn->ctx); + if(pst_dwarf_stack_calc(&stack, expr, exprlen, attr, fn)) { + uint64_t value; + if(pst_dwarf_stack_get_value(&stack, &value)) { + pst_log(SEVERITY_DEBUG, "DW_AT_framebase expression: \"%s\" ==> 0x%lX", fn->ctx->buff, value); + } else { + pst_log(SEVERITY_ERROR, "Failed to get value of calculated DW_AT_framebase expression: %s", fn->ctx->buff); + } + } else { + pst_log(SEVERITY_ERROR, "Failed to calculate DW_AT_framebase expression: %s", fn->ctx->buff); + } + pst_dwarf_stack_fini(&stack); + } else { + pst_log(SEVERITY_WARNING, "Unknown attribute form = 0x%X, code = 0x%X", attr->form, attr->code); + } + } + } + + // Get reference to return attribute type of the function + // may be to use dwfl_module_return_value_location() instead + pst_parameter* ret_p = add_param(fn); ret_p->is_return = true; + attr = dwarf_attr(fn->die, DW_AT_type, &attr_mem); + if(attr) { + if(!pst_parameter_handle_type(ret_p, attr)) { + pst_log(SEVERITY_ERROR, "Failed to handle return parameter type for function %s(...)", fn->name); + del_param(ret_p); + } + } else { + pst_parameter_add_type(ret_p, "void", 0); + } + + // handle and save additionally these attributes: + // 1. string of DW_AT_linkage_name (mangled name of program if any) + // A debugging information entry may have a DW_AT_linkage_name attribute + // whose value is a null-terminated string containing the object file linkage name + // associated with the corresponding entity. + + // 2. flag DW_AT_external attribute + // A DW_AT_external attribute, which is a flag, if the name of a variable is + // visible outside of its enclosing compilation unit. + + // 3. A subroutine entry may contain a DW_AT_main_subprogram attribute which is + // a flag whose presence indicates that the subroutine has been identified as the + // starting function of the program. If more than one subprogram contains this flag, + // any one of them may be the starting subroutine of the program. + + + Dwarf_Die result; + if(dwarf_child(fn->die, &result) != 0) + return false; + + // went through parameters and local variables of the function + do { + switch (dwarf_tag(&result)) { + case DW_TAG_formal_parameter: + case DW_TAG_variable: { + pst_parameter* param = add_param(fn); + if(!pst_parameter_handle_dwarf(param, &result, fn)) { + del_param(param); + } + + break; + } + case DW_TAG_GNU_call_site: + pst_call_site_storage_handle_dwarf(&fn->call_sites, &result, fn); + break; + + // case DW_TAG_inlined_subroutine: + // /* Recurse further down */ + // HandleFunction(&result); + // break; + case DW_TAG_lexical_block: { + handle_lexical_block(fn, &result); + break; + } + // Also handle: + // DW_TAG_unspecified_parameters (unknown number of arguments i.e. fun(arg1, ...); + // DW_AT_inline + default: + pst_log(SEVERITY_DEBUG, "Unknown TAG of function: 0x%X", dwarf_tag(&result)); + break; + } + } while(dwarf_siblingof(&result, &result) == 0); + + return true; +} + +bool pst_function_unwind(pst_function* fn, Dwarf_Addr addr) +{ + fn->pc = addr; + + Dwfl_Line *dwline = dwfl_getsrc(fn->ctx->dwfl, addr); + if(dwline != NULL) { + Dwarf_Addr addr; + const char* filename = dwfl_lineinfo (dwline, &addr, &fn->line, NULL, NULL, NULL); + if(filename) { + const char* str = strrchr(filename, '/'); + if(str && *str != 0) { + str++; + } else { + str = filename; + } + fn->file = pst_strdup(str); + fn->ctx->print(fn->ctx, "%s:%d", str, fn->line); + } else { + fn->ctx->print(fn->ctx, "%p", (void*)addr); + } + } else { + fn->ctx->print(fn->ctx, "%p", (void*)addr); + } + + const char* addrname = dwfl_module_addrname(fn->ctx->module, addr); + char* demangle_name = NULL; + if(addrname) { + int status; + demangle_name = abi::__cxa_demangle(addrname, NULL, NULL, &status); + char* function_name = NULL; + if(asprintf(&function_name, "%s%s", demangle_name ? demangle_name : addrname, demangle_name ? "" : "()") == -1) { + pst_log(SEVERITY_ERROR, "Failed to allocate memory"); + return false; + } + fn->ctx->print(fn->ctx, " --> %s", function_name); + + char* str = strchr(function_name, '('); + if(str) { + *str = 0; + } + fn->name = pst_strdup(function_name); + free(function_name); + } + + if(demangle_name) { + free(demangle_name); + } + + return true; +} + void pst_function_init(pst_function* fn, pst_context* _ctx, __pst_function* _parent) { - // methods - fn->clear = fn_clear; - fn->add_param = fn_add_param; - fn->del_param = fn_del_param; - fn->next_param = fn_next_param; - fn->unwind = fn_unwind; - fn->handle_dwarf = fn_handle_dwarf; - fn->print_dwarf = fn_print_dwarf; - fn->handle_lexical_block = fn_handle_lexical_block; - fn->get_frame = fn_get_frame; - list_node_init(&fn->node); // fields @@ -471,7 +460,7 @@ pst_function* pst_function_new(pst_context* _ctx, __pst_function* _parent) void pst_function_fini(pst_function* fn) { - fn->clear(fn); + clear(fn); if(fn->frame) { // use free here because it was allocate out of our control by libdw diff --git a/framework/dwarf_function.h b/framework/dwarf_function.h index def3066..9af6e85 100644 --- a/framework/dwarf_function.h +++ b/framework/dwarf_function.h @@ -18,18 +18,7 @@ // pst_function // ----------------------------------------------------------------------------------- typedef struct __pst_function { - list_node node; // uplink. !!! must be first !!! - - void (*clear) (pst_function* fn); - pst_parameter* (*add_param) (pst_function* fn); - void (*del_param) (pst_parameter* p); - pst_parameter* (*next_param) (pst_function* fn, pst_parameter* p); - - bool (*unwind) (pst_function* fn, Dwarf_Addr addr); - bool (*handle_dwarf) (pst_function* fn, Dwarf_Die* d); - bool (*print_dwarf) (pst_function* fn); - bool (*handle_lexical_block) (pst_function* fn, Dwarf_Die* result); - bool (*get_frame) (pst_function* fn); + list_node node; 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 @@ -53,4 +42,8 @@ void pst_function_init(pst_function* fn, pst_context* _ctx, __pst_function* _par void pst_function_fini(pst_function* fn); pst_function* pst_function_new(pst_context* _ctx, __pst_function* _parent); +bool pst_function_unwind(pst_function* fn, Dwarf_Addr addr); +bool pst_function_handle_dwarf(pst_function * fn, Dwarf_Die* d); +bool pst_function_print_dwarf(pst_function* fn); + #endif /* FRAMEWORK_DWARF_FUNCTION_H_ */ diff --git a/framework/dwarf_operations.cpp b/framework/dwarf_operations.cpp index 271a080..9b8200f 100644 --- a/framework/dwarf_operations.cpp +++ b/framework/dwarf_operations.cpp @@ -22,7 +22,7 @@ bool dw_op_notimpl(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word o // address and whose size is the size of an address on the target machine. bool dw_op_addr(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - stack->push(stack, &op1, sizeof(op1), DWARF_TYPE_GENERIC); + pst_dwarf_stack_push(stack, &op1, sizeof(op1), DWARF_TYPE_GENERIC); return true; } @@ -34,7 +34,7 @@ bool dw_op_addr(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, bool dw_op_deref_size(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value = stack->pop(stack); + pst_dwarf_value* value = pst_dwarf_stack_pop(stack); if(value) { uint64_t addr = value->value.uint64; uint64_t res = 0; @@ -55,7 +55,7 @@ bool dw_op_deref_size(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Wor return false; break; } - stack->push(stack, &res, sizeof(res), DWARF_TYPE_GENERIC); + pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_GENERIC); return true; } @@ -97,7 +97,7 @@ bool dw_op_const_x_u(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word return false; } - stack->push(stack, &op1, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC); + pst_dwarf_stack_push(stack, &op1, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC); return true; } @@ -133,7 +133,7 @@ bool dw_op_const_x_s(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word return false; } - stack->push(stack, &v, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC); + pst_dwarf_stack_push(stack, &v, size, type | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC); return true; } @@ -142,7 +142,7 @@ bool dw_op_const_x_s(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word 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(stack, &value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_UNSIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC); + pst_dwarf_stack_push(stack, &value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_UNSIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC); return true; } @@ -150,15 +150,15 @@ bool dw_op_consts(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op { // 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(stack, &value, sizeof(value), DWARF_TYPE_LONG | DWARF_TYPE_SIGNED | DWARF_TYPE_CONST | DWARF_TYPE_GENERIC); + pst_dwarf_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(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value = stack->get(stack, 0); - stack->push(stack, &value->value, sizeof(value->value), value->type); + pst_dwarf_value* value = pst_dwarf_stack_get(stack, 0); + pst_dwarf_stack_push(stack, &value->value, sizeof(value->value), value->type); return true; } @@ -166,7 +166,7 @@ bool dw_op_dup(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // The DW_OP_drop operation pops the value (including its type identifier) at the top of the stack. bool dw_op_drop(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value = stack->pop(stack); + pst_dwarf_value* value = pst_dwarf_stack_pop(stack); pst_dwarf_value_fini(value); return true; @@ -176,8 +176,8 @@ bool dw_op_drop(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // This is equivalent to a DW_OP_pick operation, with index 1. bool dw_op_over(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value = stack->get(stack, 1); - stack->push(stack, &value->value, sizeof(value->value), value->type); + pst_dwarf_value* value = pst_dwarf_stack_get(stack, 1); + pst_dwarf_stack_push(stack, &value->value, sizeof(value->value), value->type); return true; } @@ -186,9 +186,9 @@ bool dw_op_over(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // A copy of the stack entry (including its type identifier) with the specified index (0 through 255, inclusive) is pushed onto the stack. bool dw_op_pick(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value = stack->get(stack, op1); + pst_dwarf_value* value = pst_dwarf_stack_get(stack, op1); if(value) { - stack->push(stack, &value->value, sizeof(value->value), value->type); + pst_dwarf_stack_push(stack, &value->value, sizeof(value->value), value->type); return true; } @@ -199,11 +199,11 @@ bool dw_op_pick(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // entry, and the second entry (including its type identifier) becomes the top of the stack. bool dw_op_swap(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value1 = stack->pop(stack); - pst_dwarf_value* value2 = stack->pop(stack); + pst_dwarf_value* value1 = pst_dwarf_stack_pop(stack); + pst_dwarf_value* value2 = pst_dwarf_stack_pop(stack); if(value1 && value2) { - stack->push_value(stack, value1); - stack->push_value(stack, value2); + pst_dwarf_stack_push_value(stack, value1); + pst_dwarf_stack_push_value(stack, value2); return true; } @@ -223,13 +223,13 @@ bool dw_op_swap(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // and the third entry (including its type identifier) becomes the second entry bool dw_op_rot(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value1 = stack->pop(stack); - pst_dwarf_value* value2 = stack->pop(stack); - pst_dwarf_value* value3 = stack->pop(stack); + pst_dwarf_value* value1 = pst_dwarf_stack_pop(stack); + pst_dwarf_value* value2 = pst_dwarf_stack_pop(stack); + pst_dwarf_value* value3 = pst_dwarf_stack_pop(stack); if(value1 && value2 && value3) { - stack->push_value(stack, value1); - stack->push_value(stack, value3); - stack->push_value(stack, value2); + pst_dwarf_stack_push_value(stack, value1); + pst_dwarf_stack_push_value(stack, value3); + pst_dwarf_stack_push_value(stack, value2); return true; } @@ -250,10 +250,10 @@ bool dw_op_rot(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // If the absolute value cannot be represented, the result is undefined. bool dw_op_abs(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value = stack->get(stack, 0); + pst_dwarf_value* value = pst_dwarf_stack_get(stack, 0); if(value) { uint64_t res = llabs(value->value.int64); - value->set(value, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC | DWARF_TYPE_LONG); + pst_dwarf_value_set(value, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC | DWARF_TYPE_LONG); } return false; @@ -262,16 +262,16 @@ bool dw_op_abs(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // The DW_OP_and operation pops the top two stack values, performs a bitwise and operation on the two, and pushes the result. bool dw_op_and(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value1 = stack->get(stack, 0); - pst_dwarf_value* value2 = stack->get(stack, 1); + pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0); + pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1); if(value1 && value2) { if(!(value1->type & value2->type)) { return false; } 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_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_GENERIC); pst_dwarf_value_fini(value1); pst_dwarf_value_fini(value2); @@ -284,8 +284,8 @@ bool dw_op_and(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // The DW_OP_div operation pops the top two stack values, divides the former second entry by the former top of the stack using signed division, and pushes the result. bool dw_op_div(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value1 = stack->get(stack, 0); - pst_dwarf_value* value2 = stack->get(stack, 1); + pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0); + pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1); if(value1 && value2) { if(!(value1->type & value2->type)) { return false; @@ -297,16 +297,16 @@ bool dw_op_div(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, return false; } 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); + pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC); return true; } else { if(value1->value.uint64 == 0) { return false; } 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); + pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC); return true; } } else { @@ -315,16 +315,16 @@ bool dw_op_div(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, return false; } 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); + pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC); return true; } else { if(value1->value.uint64 == 0) { 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); + pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC); return true; } } @@ -336,8 +336,8 @@ bool dw_op_div(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // The DW_OP_minus operation pops the top two stack values, subtracts the former top of the stack from the former second entry, and pushes the result. bool dw_op_minus(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value1 = stack->get(stack, 0); - pst_dwarf_value* value2 = stack->get(stack, 1); + pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0); + pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1); if(value1 && value2) { if(!(value1->type & value2->type)) { return false; @@ -349,8 +349,8 @@ bool dw_op_minus(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1 } // 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); + pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), res_type); return true; } @@ -361,8 +361,8 @@ bool dw_op_minus(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1 // The DW_OP_mod operation pops the top two stack values and pushes the result of the calculation: former second stack entry modulo the former top of the stack. bool dw_op_mod(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value1 = stack->get(stack, 0); - pst_dwarf_value* value2 = stack->get(stack, 1); + pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0); + pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1); if(value1 && value2) { if(!(value1->type & value2->type)) { return false; @@ -373,8 +373,8 @@ bool dw_op_mod(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, } 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); + pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC); return true; } @@ -385,8 +385,8 @@ bool dw_op_mod(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // The DW_OP_mul operation pops the top two stack entries, multiplies them together, and pushes the result. bool dw_op_mul(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value1 = stack->get(stack, 0); - pst_dwarf_value* value2 = stack->get(stack, 1); + pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0); + pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1); if(value1 && value2) { if(!(value1->type & value2->type)) { pst_log(SEVERITY_ERROR, "Different types of two stack values for operation: %s(%0x%X, %0x%X)", map->op_name, value1->type, value2->type); @@ -396,28 +396,28 @@ bool dw_op_mul(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, if(value2->type & DWARF_TYPE_SIGNED) { if(value1->type & DWARF_TYPE_SIGNED) { 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); + pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC); return true; } else { 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); + pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC); return true; } } else { if(value1->type & DWARF_TYPE_SIGNED) { 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); + pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_SIGNED | DWARF_TYPE_GENERIC); return true; } else { 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); + pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), DWARF_TYPE_UNSIGNED | DWARF_TYPE_GENERIC); return true; } @@ -431,7 +431,7 @@ bool dw_op_mul(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // If the negation cannot be represented, the result is undefined. bool dw_op_neg(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value = stack->get(stack, 0); + pst_dwarf_value* value = pst_dwarf_stack_get(stack, 0); if(value) { if(value->type & DWARF_TYPE_CHAR) { value->value.int8 *= -1; @@ -451,7 +451,7 @@ bool dw_op_neg(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // The DW_OP_not operation pops the top stack entry, and pushes its bitwise complement. bool dw_op_not(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value = stack->get(stack, 0); + pst_dwarf_value* value = pst_dwarf_stack_get(stack, 0); if(value) { value->value.uint64 = ~value->value.uint64; @@ -464,16 +464,16 @@ bool dw_op_not(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // The DW_OP_or operation pops the top two stack entries, performs a bitwise or operation on the two, and pushes the result. bool dw_op_or(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value1 = stack->get(stack, 0); - pst_dwarf_value* value2 = stack->get(stack, 1); + pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0); + pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1); if(value1 && value2) { if(!(value1->type & value2->type)) { 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_stack_pop(stack); pst_dwarf_stack_pop(stack); + pst_dwarf_stack_push(stack, &res, sizeof(res), value1->type); pst_dwarf_value_fini(value1); pst_dwarf_value_fini(value2); @@ -487,8 +487,8 @@ bool dw_op_or(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, D // The DW_OP_plus operation pops the top two stack entries, adds them together, and pushes the result bool dw_op_plus(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value1 = stack->get(stack, 0); - pst_dwarf_value* value2 = stack->get(stack, 1); + pst_dwarf_value* value1 = pst_dwarf_stack_get(stack, 0); + pst_dwarf_value* value2 = pst_dwarf_stack_get(stack, 1); if(value1 && value2) { if(!(value1->type & value2->type)) { return false; @@ -496,15 +496,15 @@ bool dw_op_plus(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, 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); + pst_dwarf_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); + pst_dwarf_stack_push(stack, &res, sizeof(res), type); } - stack->pop(stack); stack->pop(stack); + pst_dwarf_stack_pop(stack); pst_dwarf_stack_pop(stack); pst_dwarf_value_fini(value1); pst_dwarf_value_fini(value2); @@ -520,7 +520,7 @@ bool dw_op_plus(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, // bytes than can be done with “DW_OP_lit DW_OP_plus.” bool dw_op_plus_uconst(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* value = stack->get(stack, 0); + pst_dwarf_value* value = pst_dwarf_stack_get(stack, 0); if(value) { uint64_t op = decode_uleb128((unsigned char*)&op1); value->value.uint64 += op; @@ -547,7 +547,7 @@ bool dw_op_reg_x(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1 regno = map->op_num - DW_OP_reg0; } - stack->push(stack, ®no, sizeof(regno), DWARF_TYPE_REGISTER_LOC); + pst_dwarf_stack_push(stack, ®no, sizeof(regno), DWARF_TYPE_REGISTER_LOC); return true; } @@ -577,7 +577,7 @@ bool dw_op_breg_x(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op } val += off; - stack->push(stack, &val, sizeof(val), DWARF_TYPE_GENERIC); + pst_dwarf_stack_push(stack, &val, sizeof(val), DWARF_TYPE_GENERIC); return true; } @@ -591,7 +591,7 @@ bool dw_op_lit_x(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1 } uint64_t val = map->op_num - DW_OP_lit0; - stack->push(stack, &val, sizeof(val), DWARF_TYPE_GENERIC); + pst_dwarf_stack_push(stack, &val, sizeof(val), DWARF_TYPE_GENERIC); return true; } @@ -602,7 +602,7 @@ bool dw_op_lit_x(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1 bool dw_op_stack_value(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dwarf_Word op2) { - pst_dwarf_value* v = stack->get(stack, 0); + pst_dwarf_value* v = pst_dwarf_stack_get(stack, 0); if(v) { v->type = DWARF_TYPE_GENERIC; return true; @@ -622,7 +622,7 @@ bool dw_op_call_frame_cfa(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf // return false; // } - stack->push(stack, &stack->ctx->cfa, sizeof(stack->ctx->cfa), /*DWARF_TYPE_MEMORY_LOC | */DWARF_TYPE_GENERIC); + pst_dwarf_stack_push(stack, &stack->ctx->cfa, sizeof(stack->ctx->cfa), /*DWARF_TYPE_MEMORY_LOC | */DWARF_TYPE_GENERIC); return true; } @@ -643,7 +643,7 @@ bool dw_op_fbreg(pst_dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1 int64_t off = decode_sleb128((unsigned char*)&op1); sp += off; - stack->push(stack, &sp, sizeof(sp), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC); + pst_dwarf_stack_push(stack, &sp, sizeof(sp), DWARF_TYPE_MEMORY_LOC | DWARF_TYPE_GENERIC); return true; } diff --git a/framework/dwarf_parameter.cpp b/framework/dwarf_parameter.cpp index 7b822f5..83f95f9 100644 --- a/framework/dwarf_parameter.cpp +++ b/framework/dwarf_parameter.cpp @@ -45,17 +45,38 @@ void pst_type_fini(pst_type* t) // // pst_parameter // -bool param_print_dwarf(pst_parameter* param) +void clear(pst_parameter* param) +{ + pst_type* t = NULL; + struct list_node *pos, *tn; + list_for_each_entry_safe(t, pos, tn, ¶m->types, node) { + list_del(&t->node); + pst_type_fini(t); + } +} + +pst_type* next_type(pst_parameter* param, pst_type* t) +{ + list_node* n = (t == NULL) ? list_first(¶m->types) : list_next(&t->node); + pst_type* ret = NULL; + if(n) { + ret = list_entry(n, pst_type, node); + } + + return ret; +} + +bool pst_parameter_print_dwarf(pst_parameter* param) { if(list_count(¶m->types)) { if(!param->is_return) { if(param->has_value) { - param->ctx->print(param->ctx, "%s %s = 0x%lX", param->next_type(param, NULL)->name, param->name, param->location.value); + param->ctx->print(param->ctx, "%s %s = 0x%lX", next_type(param, NULL)->name, param->name, param->location.value); } else { - param->ctx->print(param->ctx, "%s %s = ", param->next_type(param, NULL)->name, param->name); + param->ctx->print(param->ctx, "%s %s = ", next_type(param, NULL)->name, param->name); } } else { - param->ctx->print(param->ctx, "%s", param->next_type(param, NULL)->name); + param->ctx->print(param->ctx, "%s", next_type(param, NULL)->name); } } else { if(param->has_value) { @@ -67,7 +88,15 @@ bool param_print_dwarf(pst_parameter* param) return true; } -bool param_handle_type(pst_parameter* param, Dwarf_Attribute* base) +pst_type* pst_parameter_add_type(pst_parameter* param, const char* name, int type) +{ + pst_new(pst_type, t, name, type); + list_add_bottom(¶m->types, &t->node); + + return t; +} + +bool pst_parameter_handle_type(pst_parameter* param, Dwarf_Attribute* base) { Dwarf_Attribute attr_mem; Dwarf_Attribute* attr; @@ -89,7 +118,7 @@ bool param_handle_type(pst_parameter* param, Dwarf_Attribute* base) dwarf_formudata(attr, ¶m->size); } pst_log(SEVERITY_DEBUG, "base type '%s'(%lu)", dwarf_diename(&ret_die), param->size); - param->add_type(param, dwarf_diename(&ret_die), DW_TAG_base_type); + pst_parameter_add_type(param, dwarf_diename(&ret_die), DW_TAG_base_type); param->type = DW_TAG_base_type; attr = dwarf_attr(&ret_die, DW_AT_encoding, &attr_mem); @@ -101,38 +130,38 @@ bool param_handle_type(pst_parameter* param, Dwarf_Attribute* base) } case DW_TAG_array_type: pst_log(SEVERITY_DEBUG, "array type"); - param->add_type(param, "[]", DW_TAG_array_type); + pst_parameter_add_type(param, "[]", DW_TAG_array_type); break; case DW_TAG_structure_type: pst_log(SEVERITY_DEBUG, "structure type"); - param->add_type(param, "struct", DW_TAG_structure_type); + pst_parameter_add_type(param, "struct", DW_TAG_structure_type); break; case DW_TAG_union_type: pst_log(SEVERITY_DEBUG, "union type"); - param->add_type(param, "union", DW_TAG_union_type); + pst_parameter_add_type(param, "union", DW_TAG_union_type); break; case DW_TAG_class_type: pst_log(SEVERITY_DEBUG, "class type"); - param->add_type(param, "class", DW_TAG_class_type); + pst_parameter_add_type(param, "class", DW_TAG_class_type); break; case DW_TAG_pointer_type: pst_log(SEVERITY_DEBUG, "pointer type"); - param->add_type(param, "*", DW_TAG_pointer_type); + pst_parameter_add_type(param, "*", DW_TAG_pointer_type); break; case DW_TAG_enumeration_type: pst_log(SEVERITY_DEBUG, "enumeration type"); - param->add_type(param, "enum", DW_TAG_enumeration_type); + pst_parameter_add_type(param, "enum", DW_TAG_enumeration_type); break; case DW_TAG_const_type: pst_log(SEVERITY_DEBUG, "constant type"); - param->add_type(param, "const", DW_TAG_const_type); + pst_parameter_add_type(param, "const", DW_TAG_const_type); break; case DW_TAG_subroutine_type: pst_log(SEVERITY_DEBUG, "Skipping subroutine type"); break; case DW_TAG_typedef: pst_log(SEVERITY_DEBUG, "typedef '%s' type", dwarf_diename(&ret_die)); - param->add_type(param, dwarf_diename(&ret_die), DW_TAG_typedef); + pst_parameter_add_type(param, dwarf_diename(&ret_die), DW_TAG_typedef); break; default: pst_log(SEVERITY_WARNING, "Unknown 0x%X tag type", dwarf_tag(&ret_die)); @@ -141,42 +170,13 @@ bool param_handle_type(pst_parameter* param, Dwarf_Attribute* base) attr = dwarf_attr(&ret_die, DW_AT_type, &attr_mem); if(attr) { - return param->handle_type(param, attr); + return pst_parameter_handle_type(param, attr); } return true; } -pst_type* param_add_type(pst_parameter* param, const char* name, int type) -{ - pst_new(pst_type, t, name, type); - list_add_bottom(¶m->types, &t->node); - - return t; -} - -void param_clear(pst_parameter* param) -{ - pst_type* t = NULL; - struct list_node *pos, *tn; - list_for_each_entry_safe(t, pos, tn, ¶m->types, node) { - list_del(&t->node); - pst_type_fini(t); - } -} - -pst_type* param_next_type(pst_parameter* param, pst_type* t) -{ - list_node* n = (t == NULL) ? list_first(¶m->types) : list_next(&t->node); - pst_type* ret = NULL; - if(n) { - ret = list_entry(n, pst_type, node); - } - - return ret; -} - -bool param_handle_dwarf(pst_parameter* param, Dwarf_Die* result, pst_function* fun) +bool pst_parameter_handle_dwarf(pst_parameter* param, Dwarf_Die* result, pst_function* fun) { param->die = result; @@ -191,7 +191,7 @@ bool param_handle_dwarf(pst_parameter* param, Dwarf_Die* result, pst_function* f attr = dwarf_attr(result, DW_AT_type, &attr_mem); pst_log(SEVERITY_DEBUG, "---> Handle '%s' %s", param->name, dwarf_tag(result) == DW_TAG_formal_parameter ? "parameter" : "variable"); if(attr) { - param->handle_type(param, attr); + pst_parameter_handle_type(param, attr); } if(dwarf_hasattr(result, DW_AT_location)) { @@ -257,15 +257,6 @@ bool param_handle_dwarf(pst_parameter* param, Dwarf_Die* result, pst_function* f void pst_parameter_init(pst_parameter* param, pst_context* ctx) { - // methods - param->clear = param_clear; - param->add_type = param_add_type; - param->next_type = param_next_type; - param->handle_dwarf = param_handle_dwarf; - param->handle_type = param_handle_type; - param->print_dwarf = param_print_dwarf; - - // fields list_node_init(¶m->node); param->die = NULL; param->name = NULL; @@ -294,7 +285,7 @@ pst_parameter* pst_parameter_new(pst_context* ctx) } void pst_parameter_fini(pst_parameter* param) { - param->clear(param); + clear(param); if(param->name) { pst_free(param->name); } diff --git a/framework/dwarf_parameter.h b/framework/dwarf_parameter.h index 2bff055..31abf0f 100644 --- a/framework/dwarf_parameter.h +++ b/framework/dwarf_parameter.h @@ -31,14 +31,6 @@ typedef struct __pst_function pst_function; typedef struct pst_parameter{ list_node node; // uplink. !!! must be first !!! - // methods - void (*clear) (pst_parameter* param); - pst_type* (*add_type) (pst_parameter* param, const char* name, int type); - pst_type* (*next_type) (pst_parameter* param, pst_type* t); - bool (*handle_dwarf) (pst_parameter* param, Dwarf_Die* d, pst_function* fun); - bool (*handle_type) (pst_parameter* param, Dwarf_Attribute* attr); - bool (*print_dwarf) (pst_parameter* param); - // fields Dwarf_Die* die; // DWARF DIE containing parameter's definition char* name; // parameter's name @@ -59,5 +51,9 @@ void pst_parameter_init(pst_parameter* param, pst_context* ctx); pst_parameter* pst_parameter_new(pst_context* ctx); void pst_parameter_fini(pst_parameter* param); +bool pst_parameter_handle_dwarf(pst_parameter* param, Dwarf_Die* result, pst_function* fun); +bool pst_parameter_print_dwarf(pst_parameter* param); +bool pst_parameter_handle_type(pst_parameter* param, Dwarf_Attribute* base); +pst_type* pst_parameter_add_type(pst_parameter* param, const char* name, int type); #endif /* FRAMEWORK_DWARF_PARAMETER_H_ */ diff --git a/framework/dwarf_stack.cpp b/framework/dwarf_stack.cpp index b431812..ffb715e 100644 --- a/framework/dwarf_stack.cpp +++ b/framework/dwarf_stack.cpp @@ -19,7 +19,7 @@ // ----------------------------------------------------------------------------------- // DWARF Stack value // ----------------------------------------------------------------------------------- -void value_set(pst_dwarf_value* value, void* v, uint32_t s, int t) +void pst_dwarf_value_set(pst_dwarf_value* value, void* v, uint32_t s, int t) { pst_assert(value && v && s > 0 && s <= sizeof(value->value)); @@ -70,8 +70,7 @@ void pst_dwarf_value_init(pst_dwarf_value* dv, char* v, uint32_t s, int t) list_node_init(&dv->node); dv->type = t; dv->allocated = false; - dv->set = value_set; - value_set(dv, v, s, t); + pst_dwarf_value_set(dv, v, s, t); } pst_dwarf_value* pst_dwarf_value_new(char* v, uint32_t s, int t) @@ -104,16 +103,19 @@ void pst_dwarf_value_fini(pst_dwarf_value* value) // ----------------------------------------------------------------------------------- // DWARF stack // ----------------------------------------------------------------------------------- -void stack_push(pst_dwarf_stack* st, void* v, uint32_t s, int t) { +void pst_dwarf_stack_push(pst_dwarf_stack* st, void* v, uint32_t s, int t) +{ pst_new(pst_dwarf_value, value, (char*)v, s, t); list_add_head(&st->values, &value->node); } -void stack_push_value(pst_dwarf_stack* st, pst_dwarf_value* value) { +void pst_dwarf_stack_push_value(pst_dwarf_stack* st, pst_dwarf_value* value) +{ list_add_head(&st->values, &value->node); } -pst_dwarf_value* stack_pop(pst_dwarf_stack* st) { +pst_dwarf_value* pst_dwarf_stack_pop(pst_dwarf_stack* st) +{ pst_dwarf_value* value = (pst_dwarf_value*)list_first(&st->values); if(value) { list_del(&value->node); @@ -122,7 +124,8 @@ pst_dwarf_value* stack_pop(pst_dwarf_stack* st) { return value; } -pst_dwarf_value* stack_get(pst_dwarf_stack* st, uint32_t idx = 0) { +pst_dwarf_value* pst_dwarf_stack_get(pst_dwarf_stack* st, uint32_t idx) +{ pst_dwarf_value* value = NULL; struct list_node *pos; list_for_each_entry(value, pos, &st->values, node) { @@ -135,7 +138,7 @@ pst_dwarf_value* stack_get(pst_dwarf_stack* st, uint32_t idx = 0) { return value; } -bool stack_get_value(pst_dwarf_stack* st, uint64_t* value) +bool pst_dwarf_stack_get_value(pst_dwarf_stack* st, uint64_t* value) { assert(st && value); @@ -143,7 +146,7 @@ bool stack_get_value(pst_dwarf_stack* st, uint64_t* value) return false; } - pst_dwarf_value* v = st->get(st, 0); + pst_dwarf_value* v = pst_dwarf_stack_get(st, 0); if(v->type & DWARF_TYPE_REGISTER_LOC) { // dereference register location int ret = unw_get_reg(st->ctx->curr_frame, v->value.uint64, value); @@ -161,7 +164,7 @@ bool stack_get_value(pst_dwarf_stack* st, uint64_t* value) return true; } -void stack_clear(pst_dwarf_stack* st) +void pst_dwarf_stack_clear(pst_dwarf_stack* st) { pst_dwarf_value* value = NULL; struct list_node *pos, *tn; @@ -177,9 +180,9 @@ void stack_clear(pst_dwarf_stack* st) } } -bool stack_calc(pst_dwarf_stack* st, Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr, pst_function* fun = NULL) +bool pst_dwarf_stack_calc(pst_dwarf_stack* st, Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr, pst_function* fun) { - st->clear(st); + pst_dwarf_stack_clear(st); for (int i = 0; i < expr_len; i++) { const dwarf_op_map* map = find_op_map(exprs[i].atom); @@ -191,7 +194,7 @@ bool stack_calc(pst_dwarf_stack* st, Dwarf_Op *exprs, int expr_len, Dwarf_Attrib pst_new(pst_dwarf_op, op, exprs[i].atom, exprs[i].number, exprs[i].number2); list_add_bottom(&st->expr, &op->node); - pst_dwarf_value* v = st->get(st, 0); + pst_dwarf_value* v = pst_dwarf_stack_get(st, 0); // dereference register location there if it is not last in stack if(v && (v->type & DWARF_TYPE_REGISTER_LOC)) { unw_word_t value = 0; @@ -201,7 +204,7 @@ bool stack_calc(pst_dwarf_stack* st, Dwarf_Op *exprs, int expr_len, Dwarf_Attrib pst_log(SEVERITY_ERROR, "Failed to ger value of register 0x%X. Error: %d", regno, ret); return false; } - v->set(v, &value, sizeof(value), DWARF_TYPE_GENERIC); + pst_dwarf_value_set(v, &value, sizeof(value), DWARF_TYPE_GENERIC); } // handle there because it contains sub-expression of a Location in caller's frame @@ -221,22 +224,22 @@ bool stack_calc(pst_dwarf_stack* st, Dwarf_Op *exprs, int expr_len, Dwarf_Attrib Dwarf_Op *expr; size_t exprlen; if (dwarf_getlocation(&attr_mem, &expr, &exprlen) == 0) { - pst_call_site* cs = fun->parent->call_sites.find_call_site(&fun->parent->call_sites, fun); + pst_call_site* cs = pst_call_site_storage_find(&fun->parent->call_sites, fun); if(!cs) { pst_log(SEVERITY_ERROR, "Failed to find call site while calculate DW_OP_GNU_entry_value expression"); return false; } pst_dwarf_expr loc; pst_dwarf_expr_init(&loc); - loc.setup(&loc, expr, exprlen); - pst_call_site_param* param = cs->find_param(cs, &loc); + pst_dwarf_expr_setup(&loc, expr, exprlen); + pst_call_site_param* param = pst_call_site_find(cs, &loc); pst_dwarf_expr_fini(&loc); if(!param) { pst_log(SEVERITY_ERROR, "Failed to find call site parameter while calculate DW_OP_GNU_entry_value expression"); return false; } - st->push(st, ¶m->value, sizeof(param->value), DWARF_TYPE_GENERIC); + pst_dwarf_stack_push(st, ¶m->value, sizeof(param->value), DWARF_TYPE_GENERIC); continue; } else { @@ -265,14 +268,6 @@ void pst_dwarf_stack_init(pst_dwarf_stack* st, pst_context* ctx) list_head_init(&st->expr); list_head_init(&st->values); - st->push = stack_push; - st->push_value = stack_push_value; - st->pop = stack_pop; - st->get = stack_get; - st->get_value = stack_get_value; - st->calc = stack_calc; - st->clear = stack_clear; - st->ctx = ctx; st->allocated = false; } @@ -294,7 +289,7 @@ void pst_dwarf_stack_fini(pst_dwarf_stack* st) { pst_assert(st); - st->clear(st); + pst_dwarf_stack_clear(st); if(st->allocated) { pst_free(st); } else { diff --git a/framework/dwarf_stack.h b/framework/dwarf_stack.h index 9971983..6c34b51 100644 --- a/framework/dwarf_stack.h +++ b/framework/dwarf_stack.h @@ -57,18 +57,9 @@ typedef union { void* ptr; } pst_sized_value; -// forward declaration -typedef struct __pst_dwarf_value pst_dwarf_value; - -// typedefs for member function pointers -typedef void (*pst_dwarf_value_set) (pst_dwarf_value* value, void* v, uint32_t s, int t); - typedef struct __pst_dwarf_value { list_node node; // uplink, !!! must be 1st field in structure !!! - // methods - pst_dwarf_value_set set; // replace value data - // fields pst_sized_value value; // value itself int type; // value type. bitmask of DWARF_TYPE_XXX @@ -78,35 +69,13 @@ typedef struct __pst_dwarf_value { void pst_dwarf_value_init(pst_dwarf_value* value, char* v, uint32_t s, int t); pst_dwarf_value* pst_dwarf_value_new(char* v, uint32_t s, int t); void pst_dwarf_value_fini(pst_dwarf_value* value); - +void pst_dwarf_value_set(pst_dwarf_value* value, void* v, uint32_t s, int t); // ----------------------------------------------------------------------------------- // DWARF stack // ----------------------------------------------------------------------------------- -// forward declaration -typedef struct __pst_dwarf_stack pst_dwarf_stack; - -// typedefs for member function pointers -typedef void (*pst_dwarf_stack_push) (pst_dwarf_stack* st, void* v, uint32_t s, int t); -typedef void (*pst_dwarf_stack_push_val) (pst_dwarf_stack* st, pst_dwarf_value* value); -typedef pst_dwarf_value* (*pst_dwarf_stack_pop) (pst_dwarf_stack* st); -typedef pst_dwarf_value* (*pst_dwarf_stack_get) (pst_dwarf_stack* st, uint32_t idx); -typedef bool (*pst_dwarf_stack_calc) (pst_dwarf_stack* st, Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr, pst_function* fun); -typedef bool (*pst_dwarf_stack_get_value) (pst_dwarf_stack* st, uint64_t* value); -typedef void (*pst_dwarf_stack_clear) (pst_dwarf_stack* st); - typedef struct __pst_dwarf_stack { - // methods - pst_dwarf_stack_push push; // push new value on the top of the stack - pst_dwarf_stack_push_val push_value; // push an existing value on the top of the stack - pst_dwarf_stack_pop pop; // pop value from the top of the stack - pst_dwarf_stack_get get; // get value from top of the stack without popping - pst_dwarf_stack_calc calc; // calculate DWARF expression - pst_dwarf_stack_get_value get_value; // get result of calculation - pst_dwarf_stack_clear clear; // clean-up the stack - - // fields list_head expr; // DWARF expression list_head values; // list of values on the stack pst_context* ctx; // context of execution @@ -117,4 +86,12 @@ void pst_dwarf_stack_init(pst_dwarf_stack* st, pst_context* ctx); pst_dwarf_stack* pst_dwarf_stack_new(pst_context* ctx); void pst_dwarf_stack_fini(pst_dwarf_stack* st); +bool pst_dwarf_stack_calc(pst_dwarf_stack* st, Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr, pst_function* fun = NULL); +void pst_dwarf_stack_clear(pst_dwarf_stack* st); +bool pst_dwarf_stack_get_value(pst_dwarf_stack* st, uint64_t* value); +pst_dwarf_value* pst_dwarf_stack_get(pst_dwarf_stack* st, uint32_t idx = 0); +pst_dwarf_value* pst_dwarf_stack_pop(pst_dwarf_stack* st); +void pst_dwarf_stack_push_value(pst_dwarf_stack* st, pst_dwarf_value* value); +void pst_dwarf_stack_push(pst_dwarf_stack* st, void* v, uint32_t s, int t); + #endif /* FRAMEWORK_DWARF_STACK_H_ */ diff --git a/framework/dwarf_utils.cpp b/framework/dwarf_utils.cpp index bc7901c..fed3937 100644 --- a/framework/dwarf_utils.cpp +++ b/framework/dwarf_utils.cpp @@ -32,10 +32,10 @@ bool handle_location(pst_context* ctx, Dwarf_Attribute* attr, pst_dwarf_expr* lo 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(loc, expr, exprlen); + pst_dwarf_expr_setup(loc, expr, exprlen); ctx->print_expr(ctx, expr, exprlen, attr); - ret = stack.calc(&stack, expr, exprlen, attr, fun); - stack.get_value(&stack, &loc->value); + ret = pst_dwarf_stack_calc(&stack, expr, exprlen, attr, fun); + pst_dwarf_stack_get_value(&stack, &loc->value); } } else if(dwarf_hasform(attr, DW_FORM_sec_offset)) { // Location list (loclist class of location in DWARF terms) @@ -46,10 +46,10 @@ bool handle_location(pst_context* ctx, Dwarf_Attribute* attr, pst_dwarf_expr* lo for(int i = 0; (off = dwarf_getlocations (attr, off, &base, &start, &end, &expr, &exprlen)) > 0; ++i) { ctx->print_expr(ctx, expr, exprlen, attr); if(offset >= start && offset <= end) { - loc->setup(loc, expr, exprlen); + pst_dwarf_expr_setup(loc, expr, exprlen); // actual location, try to calculate Location expression - ret = stack.calc(&stack, expr, exprlen, attr, fun); - stack.get_value(&stack, &loc->value); + ret = pst_dwarf_stack_calc(&stack, expr, exprlen, attr, fun); + pst_dwarf_stack_get_value(&stack, &loc->value); } else { // Location skipped due to don't match current PC offset pst_log(SEVERITY_DEBUG, "Skip Location list expression: [%d] (low_offset: 0x%" PRIx64 ", high_offset: 0x%" PRIx64 "), \"%s\"", i, start, end, ctx->buff); diff --git a/framework/sysutils.cpp b/framework/sysutils.cpp index fb9bfd4..ebb20a1 100644 --- a/framework/sysutils.cpp +++ b/framework/sysutils.cpp @@ -34,7 +34,7 @@ // dwarf_getattrs() allows to enumerate all DIE attributes // dwarf_getfuncs() allows to enumerate functions within CU -bool handler_get_dwarf_function(pst_handler* h, pst_function* fun) +bool get_dwarf_function(pst_handler* h, pst_function* fun) { Dwarf_Addr mod_cu = 0; // get CU(Compilation Unit) debug definition @@ -64,7 +64,7 @@ bool handler_get_dwarf_function(pst_handler* h, pst_function* fun) if(tag == DW_TAG_subprogram || tag == DW_TAG_entry_point || tag == DW_TAG_inlined_subroutine) { //ctx.log(SEVERITY_DEBUG, "function die name %s", dwarf_diename(&result)); if(!strcmp(fun->name, dwarf_diename(&result))) { - return fun->handle_dwarf(fun, &result); + return pst_function_handle_dwarf(fun, &result); } } } while(dwarf_siblingof(&result, &result) == 0); @@ -72,7 +72,7 @@ bool handler_get_dwarf_function(pst_handler* h, pst_function* fun) return nret; } -pst_function* handler_add_function(pst_handler* h, pst_function* parent) +pst_function* add_function(pst_handler* h, pst_function* parent) { pst_new(pst_function, fn, &h->ctx, parent); list_add_bottom(&h->functions, &fn->node); @@ -80,13 +80,13 @@ pst_function* handler_add_function(pst_handler* h, pst_function* parent) return fn; } -void handler_del_function(pst_function* fn) +void del_function(pst_function* fn) { list_del(&fn->node); pst_function_fini(fn); } -void handler_clear(pst_handler* h) +void clear(pst_handler* h) { pst_function* fn = NULL; struct list_node *pos, *tn; @@ -96,7 +96,7 @@ void handler_clear(pst_handler* h) } } -pst_function* handler_next_function(pst_handler* h, pst_function* fn) +pst_function* next_function(pst_handler* h, pst_function* fn) { list_node* n = (fn == NULL) ? list_first(&h->functions) : list_next(&fn->node); pst_function* ret = NULL; @@ -107,7 +107,7 @@ pst_function* handler_next_function(pst_handler* h, pst_function* fn) return ret; } -pst_function* handler_prev_function(pst_handler* h, pst_function* fn) +pst_function* prev_function(pst_handler* h, pst_function* fn) { list_node* n = (fn == NULL) ? list_last(&h->functions) : list_prev(&fn->node); pst_function* ret = NULL; @@ -118,7 +118,7 @@ pst_function* handler_prev_function(pst_handler* h, pst_function* fn) return ret; } -pst_function* handler_last_function(pst_handler* h) +pst_function* last_function(pst_handler* h) { list_node* n = list_last(&h->functions); if(n) { @@ -128,13 +128,13 @@ pst_function* handler_last_function(pst_handler* h) return NULL; } -bool handler_handle_dwarf(pst_handler* h) +bool pst_handler_handle_dwarf(pst_handler* h) { h->ctx.clean_print(&h->ctx); Dl_info info; //for(pst_function* fun = next_function(NULL); fun; fun = next_function(fun)) { - for(pst_function* fun = handler_last_function(h); fun; fun = h->prev_function(h, fun)) { + for(pst_function* fun = last_function(h); fun; fun = prev_function(h, fun)) { dladdr((void*)(fun->pc), &info); pst_log(SEVERITY_INFO, "Function %s(...): module name: %s, base address: %p, CFA: %#lX", fun->name, info.dli_fname, info.dli_fbase, fun->parent ? fun->parent->sp : 0); @@ -146,20 +146,20 @@ bool handler_handle_dwarf(pst_handler* h) h->ctx.cfa = fun->cfa; h->ctx.curr_frame = &fun->cursor; - handler_get_dwarf_function(h, fun); + get_dwarf_function(h, fun); } return true; } -void handler_print_dwarf(pst_handler* h) +void pst_handler_print_dwarf(pst_handler* h) { h->ctx.clean_print(&h->ctx); h->ctx.print(&h->ctx, "DWARF-based stack trace information:\n"); uint32_t idx = 0; - for(pst_function* fn = h->next_function(h, NULL); fn; fn = h->next_function(h, fn)) { + for(pst_function* fn = next_function(h, NULL); fn; fn = next_function(h, fn)) { h->ctx.print(&h->ctx, "[%-2u] ", idx); idx++; - fn->print_dwarf(fn); + pst_function_print_dwarf(fn); h->ctx.print(&h->ctx, "\n"); } } @@ -174,7 +174,7 @@ Dwfl_Callbacks callbacks = { #include -bool handler_unwind(pst_handler* h) +bool pst_handler_unwind(pst_handler* h) { h->ctx.clean_print(&h->ctx); #ifdef REG_RIP // x86_64 @@ -239,12 +239,12 @@ bool handler_unwind(pst_handler* h) h->ctx.print(&h->ctx, "[%-2d] ", i); h->ctx.module = dwfl_addrmodule(h->ctx.dwfl, h->addr); - pst_function* last = handler_last_function(h); - pst_function* fn = h->add_function(h, NULL); + pst_function* last = last_function(h); + pst_function* fn = add_function(h, NULL); fn->sp = sp; pst_log(SEVERITY_DEBUG, "Analyze frame #%d: PC = %#lX, SP = %#lX", i, h->addr, sp); - if(!fn->unwind(fn, h->addr)) { - h->del_function(fn); + if(!pst_function_unwind(fn, h->addr)) { + del_function(fn); } else { if(last) { last->parent = fn; @@ -259,17 +259,6 @@ bool handler_unwind(pst_handler* h) void pst_handler_init(pst_handler* h, ucontext_t* hctx) { - // methods - h->clear = handler_clear; - h->add_function = handler_add_function; - h->del_function = handler_del_function; - h->next_function = handler_next_function; - h->prev_function = handler_prev_function; - h->handle_dwarf = handler_handle_dwarf; - h->print_dwarf = handler_print_dwarf; - h->unwind = handler_unwind; - - // fields pst_context_init(&h->ctx, hctx); h->handle = NULL; h->addr = 0; @@ -284,7 +273,7 @@ void pst_handler_fini(pst_handler* h) dlclose(h->handle); } - h->clear(h); + clear(h); pst_context_fini(&h->ctx); } diff --git a/framework/sysutils.h b/framework/sysutils.h index e37143c..7b6ed23 100644 --- a/framework/sysutils.h +++ b/framework/sysutils.h @@ -32,18 +32,6 @@ #include "dwarf_function.h" typedef struct pst_handler { - // methods - void (*clear) (pst_handler* h); - pst_function* (*add_function) (pst_handler* h, pst_function* fun); - void (*del_function) (pst_function* f); - pst_function* (*next_function) (pst_handler* h, pst_function* f); - pst_function* (*prev_function) (pst_handler* h, pst_function* fn); - - bool (*handle_dwarf) (pst_handler* h); - void (*print_dwarf) (pst_handler* h); - bool (*unwind) (pst_handler* h); - - // fields pst_context ctx; // context of unwinding void* handle; // process handle Dwarf_Addr addr; // address of currently processed function @@ -54,4 +42,8 @@ typedef struct pst_handler { void pst_handler_init(pst_handler* h, ucontext_t* hctx); void pst_handler_fini(pst_handler* h); +bool pst_handler_handle_dwarf(pst_handler* h); +void pst_handler_print_dwarf(pst_handler* h); +bool pst_handler_unwind(pst_handler* h); + #endif /* SC_SYSUTILS_H_ */ diff --git a/main.cpp b/main.cpp index e4a11f0..3a8e733 100644 --- a/main.cpp +++ b/main.cpp @@ -65,13 +65,13 @@ void FatalSignalHandler(int sig, siginfo_t* info, void* context) if((context != 0) && (sig == SIGSEGV || sig == SIGABRT || sig == SIGBUS || sig == SIGFPE)) { - ret = handler.unwind(&handler); + ret = pst_handler_unwind(&handler); } if(ret) { pst_log(SEVERITY_INFO, "%s", handler.ctx.buff); - handler.handle_dwarf(&handler); - handler.print_dwarf(&handler); + pst_handler_handle_dwarf(&handler); + pst_handler_print_dwarf(&handler); pst_log(SEVERITY_INFO, "%s", handler.ctx.buff); } else { pst_log(SEVERITY_ERROR, "No stack trace obtained");