fix most of compilation warnings

This commit is contained in:
2020-02-02 12:28:43 +04:00
parent abba9f735b
commit dbaffdf689
17 changed files with 371 additions and 331 deletions
+1
View File
@@ -68,6 +68,7 @@ $(ATR_LIBS):
clean: clean:
${RM} $(BUILD_DIR)/*.o $(BUILD_DIR)/*.dep $(BIN) $(BUILD_DIR)/prepare.bld $(RESULT_DIR)/prepare.res $(BUILD_DIR)/version.h ${RM} $(BUILD_DIR)/*.o $(BUILD_DIR)/*.dep $(BIN) $(BUILD_DIR)/prepare.bld $(RESULT_DIR)/prepare.res $(BUILD_DIR)/version.h
@make clean -C ./framework
@if [ -z "$$(ls -A $(BUILD_DIR) 2>&1)" ]; then ${RM} -r $(BUILD_DIR); fi @if [ -z "$$(ls -A $(BUILD_DIR) 2>&1)" ]; then ${RM} -r $(BUILD_DIR); fi
@if [ -z "$$(ls -A $(RESULT_DIR) 2>&1)" ]; then ${RM} -r $(RESULT_DIR); fi @if [ -z "$$(ls -A $(RESULT_DIR) 2>&1)" ]; then ${RM} -r $(RESULT_DIR); fi
+1 -1
View File
@@ -202,7 +202,7 @@ char* pst_strdup(const char* str)
pst_assert(str); pst_assert(str);
uint32_t len = strlen(str); uint32_t len = strlen(str);
char* dst = (char*)allocator.alloc(len + 1); char* dst = (char*)allocator.alloc(&allocator, len + 1);
memcpy(dst, str, len); memcpy(dst, str, len);
dst[len] = 0; dst[len] = 0;
+5 -3
View File
@@ -6,11 +6,13 @@
*/ */
#include <dwarf.h> #include <dwarf.h>
#include <elfutils/libdw.h>
#include "dwarf_call_site.h" #include "dwarf_call_site.h"
#include "dwarf_utils.h" #include "dwarf_utils.h"
#include "hash_multimap.h" #include "hash_multimap.h"
#include "dwarf_utils.h" #include "dwarf_utils.h"
#include "dwarf_function.h"
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// pst_call_site_param // pst_call_site_param
@@ -203,7 +205,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 // 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 // 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 // get DIE of return type
bool storage_handle_dwarf(pst_call_site_storage* storage, Dwarf_Die* result) bool storage_handle_dwarf(pst_call_site_storage* storage, Dwarf_Die* result, pst_function* info)
{ {
Dwarf_Die origin; Dwarf_Die origin;
Dwarf_Attribute attr_mem; Dwarf_Attribute attr_mem;
@@ -225,7 +227,7 @@ bool storage_handle_dwarf(pst_call_site_storage* storage, Dwarf_Die* result)
if(attr) { if(attr) {
pst_dwarf_expr expr; pst_dwarf_expr expr;
pst_dwarf_expr_init(&expr); pst_dwarf_expr_init(&expr);
if(handle_location(storage->ctx, &attr_mem, expr, pc, this)) { if(handle_location(storage->ctx, &attr_mem, &expr, info->pc, info)) {
target = expr.value; target = expr.value;
pst_log(SEVERITY_DEBUG, "\tDW_AT_GNU_call_site_target: %#lX", target); pst_log(SEVERITY_DEBUG, "\tDW_AT_GNU_call_site_target: %#lX", target);
} }
@@ -280,7 +282,7 @@ pst_call_site* storage_add_call_site(pst_call_site_storage* storage, uint64_t ta
if(target) { if(target) {
hash_add(&storage->cs_to_target, &st->tgt_node, &target, sizeof(target)); hash_add(&storage->cs_to_target, &st->tgt_node, &target, sizeof(target));
} else if(origin) { } else if(origin) {
hash_add(&storage->cs_to_origin, &st->org_node, (char*)origin, strlen(origin)); hash_add(&storage->cs_to_origin, &st->org_node, origin, strlen(origin));
} }
return st; return st;
+7 -1
View File
@@ -16,6 +16,12 @@
#include "dwarf_expression.h" #include "dwarf_expression.h"
#include "hash_multimap.h" #include "hash_multimap.h"
typedef struct pst_callee_info {
Dwarf_Addr target;
char* origin;
Dwarf_Addr pc;
} pst_callee_info;
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// DW_TAG_call_site_parameter // DW_TAG_call_site_parameter
@@ -66,7 +72,7 @@ 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); 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); void pst_call_site_fini(pst_call_site* site);
typedef struct __pst_function pst_function;
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// storage for all of function's call sites // storage for all of function's call sites
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
+6 -6
View File
@@ -59,14 +59,14 @@ bool expr_is_equal(pst_dwarf_expr* lhs, pst_dwarf_expr* rhs)
return false; return false;
} }
pst_dwarf_op* lop = lhs->next_op(NULL); pst_dwarf_op* lop = lhs->next_op(lhs, NULL);
pst_dwarf_op* rop = rhs->next_op(NULL); pst_dwarf_op* rop = rhs->next_op(rhs, NULL);
while(lop && rop) { while(lop && rop) {
if(lop->operation == rop->operation && lop->arg1 == rop->arg1 && lop->arg2 == rop->arg2) { if(lop->operation == rop->operation && lop->arg1 == rop->arg1 && lop->arg2 == rop->arg2) {
return true; return true;
} }
lop = lhs->next_op(lop); lop = lhs->next_op(lhs, lop);
rop = rhs->next_op(rop); rop = rhs->next_op(rhs, rop);
} }
return false; return false;
@@ -127,7 +127,7 @@ void expr_clean(pst_dwarf_expr* expr)
void expr_setup(pst_dwarf_expr* expr, Dwarf_Op* exprs, size_t exprlen) void 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) { for(size_t i = 0; i < exprlen; ++i) {
expr->add_op(expr, exprs[i].atom, exprs[i].number, exprs[i].number2); expr->add_op(expr, exprs[i].atom, exprs[i].number, exprs[i].number2);
} }
@@ -167,7 +167,7 @@ pst_dwarf_expr* pst_dwarf_expr_new()
void pst_dwarf_expr_fini(pst_dwarf_expr* expr) void pst_dwarf_expr_fini(pst_dwarf_expr* expr)
{ {
expr->clean(); expr->clean(expr);
if(expr->allocated) { if(expr->allocated) {
pst_free(expr); pst_free(expr);
} }
+28 -13
View File
@@ -71,7 +71,7 @@ bool fn_print_dwarf(pst_function* fn)
pst_parameter* param = fn->next_param(fn, NULL); pst_parameter* param = fn->next_param(fn, NULL);
if(param && param->is_return) { if(param && param->is_return) {
// print return value type, function name and start list of parameters // print return value type, function name and start list of parameters
param->print_dwarf(); param->print_dwarf(param);
fn->ctx->print(fn->ctx, " %s(", fn->name); fn->ctx->print(fn->ctx, " %s(", fn->name);
param = fn->next_param(fn, param); param = fn->next_param(fn, param);
} else { } else {
@@ -82,7 +82,7 @@ bool fn_print_dwarf(pst_function* fn)
for(; param; param = fn->next_param(fn, param)) { for(; param; param = fn->next_param(fn, param)) {
if(param->is_return) { if(param->is_return) {
// print return value type, function name and start list of parameters // print return value type, function name and start list of parameters
param->print_dwarf(); param->print_dwarf(param);
fn->ctx->print(fn->ctx, " %s(", fn->name); fn->ctx->print(fn->ctx, " %s(", fn->name);
continue; continue;
} }
@@ -98,7 +98,7 @@ bool fn_print_dwarf(pst_function* fn)
} else { } else {
fn->ctx->print(fn->ctx, " "); fn->ctx->print(fn->ctx, " ");
} }
param->print_dwarf(); param->print_dwarf(param);
fn->ctx->print(fn->ctx, ";\n"); fn->ctx->print(fn->ctx, ";\n");
} else { } else {
if(first) { if(first) {
@@ -106,7 +106,7 @@ bool fn_print_dwarf(pst_function* fn)
} else { } else {
fn->ctx->print(fn->ctx, ", "); fn->ctx->print(fn->ctx, ", ");
} }
param->print_dwarf(); param->print_dwarf(param);
} }
} }
@@ -160,8 +160,8 @@ bool fn_handle_lexical_block(pst_function* fn, Dwarf_Die* result)
break; break;
case DW_TAG_variable: { case DW_TAG_variable: {
pst_parameter* param = fn->add_param(fn); pst_parameter* param = fn->add_param(fn);
if(!param->handle_dwarf(&child, fn)) { if(!param->handle_dwarf(param, &child, fn)) {
fn->del_param(fn, param); fn->del_param(param);
} }
break; break;
} }
@@ -217,7 +217,7 @@ bool fn_handle_dwarf(pst_function * fn, Dwarf_Die* d)
if (dwarf_getlocation (attr, &expr, &exprlen) == 0) { if (dwarf_getlocation (attr, &expr, &exprlen) == 0) {
fn->ctx->print_expr(fn->ctx, expr, exprlen, attr); fn->ctx->print_expr(fn->ctx, expr, exprlen, attr);
pst_decl(pst_dwarf_stack, stack, fn->ctx); pst_decl(pst_dwarf_stack, stack, fn->ctx);
if(stack.calc(&stack, expr, exprlen, attr, this)) { if(stack.calc(&stack, expr, exprlen, attr, fn)) {
uint64_t value; uint64_t value;
if(stack.get_value(&stack, &value)) { if(stack.get_value(&stack, &value)) {
pst_log(SEVERITY_DEBUG, "DW_AT_framebase expression: \"%s\" ==> 0x%lX", fn->ctx->buff, value); pst_log(SEVERITY_DEBUG, "DW_AT_framebase expression: \"%s\" ==> 0x%lX", fn->ctx->buff, value);
@@ -239,12 +239,12 @@ bool fn_handle_dwarf(pst_function * fn, Dwarf_Die* d)
pst_parameter* ret_p = fn->add_param(fn); ret_p->is_return = true; pst_parameter* ret_p = fn->add_param(fn); ret_p->is_return = true;
attr = dwarf_attr(fn->die, DW_AT_type, &attr_mem); attr = dwarf_attr(fn->die, DW_AT_type, &attr_mem);
if(attr) { if(attr) {
if(!ret_p->handle_type(attr)) { if(!ret_p->handle_type(ret_p, attr)) {
pst_log(SEVERITY_ERROR, "Failed to handle return parameter type for function %s(...)", fn->name); pst_log(SEVERITY_ERROR, "Failed to handle return parameter type for function %s(...)", fn->name);
fn->del_param(fn, ret_p); fn->del_param(ret_p);
} }
} else { } else {
ret_p->add_type("void", 0); ret_p->add_type(ret_p, "void", 0);
} }
// handle and save additionally these attributes: // handle and save additionally these attributes:
@@ -274,7 +274,7 @@ bool fn_handle_dwarf(pst_function * fn, Dwarf_Die* d)
case DW_TAG_variable: { case DW_TAG_variable: {
pst_parameter* param = fn->add_param(fn); pst_parameter* param = fn->add_param(fn);
if(!param->handle_dwarf(param, &result, fn)) { if(!param->handle_dwarf(param, &result, fn)) {
fn->del_param(fn, param); fn->del_param(param);
} }
break; break;
@@ -318,7 +318,7 @@ bool fn_unwind(pst_function* fn, Dwarf_Addr addr)
} else { } else {
str = filename; str = filename;
} }
fn->file = str; fn->file = pst_strdup(str);
fn->ctx->print(fn->ctx, "%s:%d", str, fn->line); fn->ctx->print(fn->ctx, "%s:%d", str, fn->line);
} else { } else {
fn->ctx->print(fn->ctx, "%p", (void*)addr); fn->ctx->print(fn->ctx, "%p", (void*)addr);
@@ -407,7 +407,7 @@ bool fn_get_frame(pst_function* fn)
fn->ctx->print_expr(fn->ctx, cfa_ops, cfa_nops, NULL); fn->ctx->print_expr(fn->ctx, cfa_ops, cfa_nops, NULL);
pst_decl(pst_dwarf_stack, stack, fn->ctx); pst_decl(pst_dwarf_stack, stack, fn->ctx);
if(stack.calc(&stack, cfa_ops, cfa_nops, NULL, this) && stack.get_value(&stack, &fn->cfa)) { if(stack.calc(&stack, cfa_ops, cfa_nops, NULL, fn) && stack.get_value(&stack, &fn->cfa)) {
pst_log(SEVERITY_INFO, "Function %s(...): CFA expression: %s ==> %#lX", fn->name, fn->ctx->buff, 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 // setup context to match CFA for frame
@@ -456,6 +456,17 @@ void pst_function_init(pst_function* fn, pst_context* _ctx, __pst_function* _par
fn->allocated = false; fn->allocated = false;
} }
pst_function* pst_function_new(pst_context* _ctx, __pst_function* _parent)
{
pst_function* fn = pst_alloc(pst_function);
if(fn) {
pst_function_init(fn, _ctx, _parent);
fn->allocated = true;
}
return fn;
}
void pst_function_fini(pst_function* fn) void pst_function_fini(pst_function* fn)
{ {
fn->clear(fn); fn->clear(fn);
@@ -472,4 +483,8 @@ void pst_function_fini(pst_function* fn)
if(fn->file) { if(fn->file) {
pst_free(fn->file); pst_free(fn->file);
} }
if(fn->allocated) {
pst_free(fn);
}
} }
+12 -11
View File
@@ -20,17 +20,16 @@
typedef struct __pst_function { typedef struct __pst_function {
list_node node; // uplink. !!! must be first !!! list_node node; // uplink. !!! must be first !!!
void clear(pst_function* fn); void (*clear) (pst_function* fn);
pst_parameter* add_param(pst_function* fn); pst_parameter* (*add_param) (pst_function* fn);
void del_param(pst_function* fn, pst_parameter* p); void (*del_param) (pst_parameter* p);
pst_parameter* next_param(pst_function* fn, pst_parameter* p); pst_parameter* (*next_param) (pst_function* fn, pst_parameter* p);
bool unwind(pst_function* fn, Dwarf_Addr addr); bool (*unwind) (pst_function* fn, Dwarf_Addr addr);
bool handle_dwarf(pst_function* fn, Dwarf_Die* d); bool (*handle_dwarf) (pst_function* fn, Dwarf_Die* d);
bool print_dwarf(pst_function* fn); bool (*print_dwarf) (pst_function* fn);
bool handle_lexical_block(pst_function* fn, Dwarf_Die* result); bool (*handle_lexical_block) (pst_function* fn, Dwarf_Die* result);
bool (*get_frame) (pst_function* fn);
bool get_frame(pst_function* fn);
Dwarf_Addr lowpc; // offset to start of the function against base address Dwarf_Addr lowpc; // offset to start of the function against base address
Dwarf_Addr highpc; // offset to the next address after the end of the function against base address Dwarf_Addr highpc; // offset to the next address after the end of the function against base address
@@ -50,6 +49,8 @@ typedef struct __pst_function {
pst_context* ctx; // context of unwinding pst_context* ctx; // context of unwinding
bool allocated; // whether this object was allocated or not bool allocated; // whether this object was allocated or not
} pst_function; } pst_function;
void pst_function_init(pst_function* fn, pst_context* _ctx, __pst_function* _parent);
void pst_function_fini(pst_function* fn);
pst_function* pst_function_new(pst_context* _ctx, __pst_function* _parent);
#endif /* FRAMEWORK_DWARF_FUNCTION_H_ */ #endif /* FRAMEWORK_DWARF_FUNCTION_H_ */
+14 -14
View File
@@ -50,12 +50,12 @@ bool param_print_dwarf(pst_parameter* param)
if(list_count(&param->types)) { if(list_count(&param->types)) {
if(!param->is_return) { if(!param->is_return) {
if(param->has_value) { if(param->has_value) {
param->ctx->print(param->ctx, "%s %s = 0x%lX", param->next_type(NULL)->name, param->name, param->location.value); param->ctx->print(param->ctx, "%s %s = 0x%lX", param->next_type(param, NULL)->name, param->name, param->location.value);
} else { } else {
param->ctx->print(param->ctx, "%s %s = <undefined>", param->next_type(NULL)->name, param->name); param->ctx->print(param->ctx, "%s %s = <undefined>", param->next_type(param, NULL)->name, param->name);
} }
} else { } else {
param->ctx->print(param->ctx, "%s", param->next_type(NULL)->name); param->ctx->print(param->ctx, "%s", param->next_type(param, NULL)->name);
} }
} else { } else {
if(param->has_value) { if(param->has_value) {
@@ -89,7 +89,7 @@ bool param_handle_type(pst_parameter* param, Dwarf_Attribute* base)
dwarf_formudata(attr, &param->size); dwarf_formudata(attr, &param->size);
} }
pst_log(SEVERITY_DEBUG, "base type '%s'(%lu)", dwarf_diename(&ret_die), param->size); pst_log(SEVERITY_DEBUG, "base type '%s'(%lu)", dwarf_diename(&ret_die), param->size);
param->add_type(dwarf_diename(&ret_die), DW_TAG_base_type); param->add_type(param, dwarf_diename(&ret_die), DW_TAG_base_type);
param->type = DW_TAG_base_type; param->type = DW_TAG_base_type;
attr = dwarf_attr(&ret_die, DW_AT_encoding, &attr_mem); attr = dwarf_attr(&ret_die, DW_AT_encoding, &attr_mem);
@@ -101,38 +101,38 @@ bool param_handle_type(pst_parameter* param, Dwarf_Attribute* base)
} }
case DW_TAG_array_type: case DW_TAG_array_type:
pst_log(SEVERITY_DEBUG, "array type"); pst_log(SEVERITY_DEBUG, "array type");
param->add_type("[]", DW_TAG_array_type); param->add_type(param, "[]", DW_TAG_array_type);
break; break;
case DW_TAG_structure_type: case DW_TAG_structure_type:
pst_log(SEVERITY_DEBUG, "structure type"); pst_log(SEVERITY_DEBUG, "structure type");
param->add_type("struct", DW_TAG_structure_type); param->add_type(param, "struct", DW_TAG_structure_type);
break; break;
case DW_TAG_union_type: case DW_TAG_union_type:
pst_log(SEVERITY_DEBUG, "union type"); pst_log(SEVERITY_DEBUG, "union type");
param->add_type("union", DW_TAG_union_type); param->add_type(param, "union", DW_TAG_union_type);
break; break;
case DW_TAG_class_type: case DW_TAG_class_type:
pst_log(SEVERITY_DEBUG, "class type"); pst_log(SEVERITY_DEBUG, "class type");
param->add_type("class", DW_TAG_class_type); param->add_type(param, "class", DW_TAG_class_type);
break; break;
case DW_TAG_pointer_type: case DW_TAG_pointer_type:
pst_log(SEVERITY_DEBUG, "pointer type"); pst_log(SEVERITY_DEBUG, "pointer type");
param->add_type("*", DW_TAG_pointer_type); param->add_type(param, "*", DW_TAG_pointer_type);
break; break;
case DW_TAG_enumeration_type: case DW_TAG_enumeration_type:
pst_log(SEVERITY_DEBUG, "enumeration type"); pst_log(SEVERITY_DEBUG, "enumeration type");
param->add_type("enum", DW_TAG_enumeration_type); param->add_type(param, "enum", DW_TAG_enumeration_type);
break; break;
case DW_TAG_const_type: case DW_TAG_const_type:
pst_log(SEVERITY_DEBUG, "constant type"); pst_log(SEVERITY_DEBUG, "constant type");
param->add_type("const", DW_TAG_const_type); param->add_type(param, "const", DW_TAG_const_type);
break; break;
case DW_TAG_subroutine_type: case DW_TAG_subroutine_type:
pst_log(SEVERITY_DEBUG, "Skipping subroutine type"); pst_log(SEVERITY_DEBUG, "Skipping subroutine type");
break; break;
case DW_TAG_typedef: case DW_TAG_typedef:
pst_log(SEVERITY_DEBUG, "typedef '%s' type", dwarf_diename(&ret_die)); pst_log(SEVERITY_DEBUG, "typedef '%s' type", dwarf_diename(&ret_die));
param->add_type(dwarf_diename(&ret_die), DW_TAG_typedef); param->add_type(param, dwarf_diename(&ret_die), DW_TAG_typedef);
break; break;
default: default:
pst_log(SEVERITY_WARNING, "Unknown 0x%X tag type", dwarf_tag(&ret_die)); pst_log(SEVERITY_WARNING, "Unknown 0x%X tag type", dwarf_tag(&ret_die));
@@ -141,7 +141,7 @@ bool param_handle_type(pst_parameter* param, Dwarf_Attribute* base)
attr = dwarf_attr(&ret_die, DW_AT_type, &attr_mem); attr = dwarf_attr(&ret_die, DW_AT_type, &attr_mem);
if(attr) { if(attr) {
return param->handle_type(attr); return param->handle_type(param, attr);
} }
return true; return true;
@@ -295,7 +295,7 @@ pst_parameter* pst_parameter_new(pst_context* ctx)
} }
void pst_parameter_fini(pst_parameter* param) void pst_parameter_fini(pst_parameter* param)
{ {
param->clear(); param->clear(param);
if(param->name) { if(param->name) {
pst_free(param->name); pst_free(param->name);
} }
+3 -5
View File
@@ -178,7 +178,6 @@ 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 stack_calc(pst_dwarf_stack* st, Dwarf_Op *exprs, int expr_len, Dwarf_Attribute* attr, pst_function* fun = NULL)
{ {
st->clear(st); st->clear(st);
bool nret = true;
for (int i = 0; i < expr_len; i++) { for (int i = 0; i < expr_len; i++) {
const dwarf_op_map* map = find_op_map(exprs[i].atom); const dwarf_op_map* map = find_op_map(exprs[i].atom);
@@ -220,7 +219,7 @@ bool stack_calc(pst_dwarf_stack* st, Dwarf_Op *exprs, int expr_len, Dwarf_Attrib
Dwarf_Op *expr; Dwarf_Op *expr;
size_t exprlen; size_t exprlen;
if (dwarf_getlocation(&attr_mem, &expr, &exprlen) == 0) { if (dwarf_getlocation(&attr_mem, &expr, &exprlen) == 0) {
pst_call_site* cs = fun->parent->find_call_site(fun); pst_call_site* cs = fun->parent->call_sites.find_call_site(&fun->parent->call_sites, fun);
if(!cs) { if(!cs) {
pst_log(SEVERITY_ERROR, "Failed to find call site while calculate DW_OP_GNU_entry_value expression"); pst_log(SEVERITY_ERROR, "Failed to find call site while calculate DW_OP_GNU_entry_value expression");
return false; return false;
@@ -228,7 +227,7 @@ bool stack_calc(pst_dwarf_stack* st, Dwarf_Op *exprs, int expr_len, Dwarf_Attrib
pst_dwarf_expr loc; pst_dwarf_expr loc;
pst_dwarf_expr_init(&loc); pst_dwarf_expr_init(&loc);
loc.setup(&loc, expr, exprlen); loc.setup(&loc, expr, exprlen);
pst_call_site_param* param = cs->find_param(loc); pst_call_site_param* param = cs->find_param(cs, loc);
pst_dwarf_expr_fini(&loc); pst_dwarf_expr_fini(&loc);
if(!param) { if(!param) {
pst_log(SEVERITY_ERROR, "Failed to find call site parameter while calculate DW_OP_GNU_entry_value expression"); pst_log(SEVERITY_ERROR, "Failed to find call site parameter while calculate DW_OP_GNU_entry_value expression");
@@ -240,8 +239,7 @@ bool stack_calc(pst_dwarf_stack* st, Dwarf_Op *exprs, int expr_len, Dwarf_Attrib
continue; continue;
} else { } else {
pst_log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr location"); pst_log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr location");
nret = false; return false;
break;
} }
} else { } else {
pst_log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr expression"); pst_log(SEVERITY_ERROR, "Failed to get DW_OP_GNU_entry_value attr expression");
+2 -2
View File
@@ -32,7 +32,7 @@ bool handle_location(pst_context* ctx, Dwarf_Attribute* attr, pst_dwarf_expr* lo
if(dwarf_hasform(attr, DW_FORM_exprloc)) { if(dwarf_hasform(attr, DW_FORM_exprloc)) {
// Location expression (exprloc class of location in DWARF terms) // Location expression (exprloc class of location in DWARF terms)
if(dwarf_getlocation(attr, &expr, &exprlen) == 0) { if(dwarf_getlocation(attr, &expr, &exprlen) == 0) {
loc->setup(expr, exprlen); loc->setup(loc, expr, exprlen);
ctx->print_expr(ctx, expr, exprlen, attr); ctx->print_expr(ctx, expr, exprlen, attr);
ret = stack.calc(&stack, expr, exprlen, attr, fun); ret = stack.calc(&stack, expr, exprlen, attr, fun);
} }
@@ -45,7 +45,7 @@ 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) { for(int i = 0; (off = dwarf_getlocations (attr, off, &base, &start, &end, &expr, &exprlen)) > 0; ++i) {
ctx->print_expr(ctx, expr, exprlen, attr); ctx->print_expr(ctx, expr, exprlen, attr);
if(offset >= start && offset <= end) { if(offset >= start && offset <= end) {
loc->setup(expr, exprlen); loc->setup(loc, expr, exprlen);
// actual location, try to calculate Location expression // actual location, try to calculate Location expression
ret = stack.calc(&stack, expr, exprlen, attr, fun); ret = stack.calc(&stack, expr, exprlen, attr, fun);
} else { } else {
+50 -39
View File
@@ -1,20 +1,19 @@
/* ============================================================================= /* =============================================================================
* CDL (Configuration Definition Language) validator $Revision: 1.4 $ * CDL (Configuration Definition Language) validator $Revision: 1.4 $
* (C)2004-2007 Nikolai Nosov. All rights reserved. * (C)2004-2007 Nikolay Nosov. All rights reserved.
* *
* File: $RCSfile: hash_multimap.c,v $ * File: $RCSfile: hash_multimap.c,v $
* Purpose: Hash Multimap implementation * Purpose: Hash Multimap implementation
* Written by: Nikolai Nosov nnosov@gmail.com * Written by: Nikolay Nosov
* Last modified: $Date: 2008/06/21 12:15:53 $ by $Author: nnosov $. * Last modified: $Date: 2008/06/21 12:15:53 $ by $Author: nnosov $.
* *
* For more information please visit * For more information please visit
* http://nsoft.volgocity.ru/cdl or
* http://cdl.sourceforge.net * http://cdl.sourceforge.net
* ===========================================================================*/ * ===========================================================================*/
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include "hash_multimap.h" #include "hash_multimap.h"
/* Default hash function /* Default hash function
@@ -22,16 +21,19 @@
@param size hash key size in bytes @param size hash key size in bytes
@return hash value, depends of the hash key @return hash value, depends of the hash key
*/ */
static unsigned int default_hash_fn(const char *key, int size) static unsigned int default_hash_fn(const void *key, int size)
{ {
register int i, j; register int i, j;
unsigned int cs = 0; unsigned int cs = 0;
unsigned int ps = 0; unsigned int ps = 0;
if(key) { if(key)
for(i = 0, j = 0; i < size; i++, j++) { {
ps |= ((unsigned int)key[i]) << (j * 8); for(i = 0, j = 0; i < size; i++, j++)
if(j == 3 || j == (size - 1)) { {
ps |= ((unsigned int)((const char*)key)[i]) << (j * 8);
if(j == 3 || j == (size - 1))
{
cs ^= ps; cs ^= ps;
ps = 0; ps = 0;
j = 0; j = 0;
@@ -42,12 +44,13 @@ static unsigned int default_hash_fn(const char *key, int size)
return cs; return cs;
} }
static int default_compare_fn(const char *key1, const char *key2, const int size) static int default_compare_fn(const void *key1, const void *key2, const int size)
{ {
return !memcmp(key1, key2, size); return !memcmp(key1, key2, size);
} }
/** Initialize hash node. Must be called before first usage of the node. /** Initialize hash node. Must be called before first usage of the node.
@param node pointer to the hash node descriptor @param node pointer to the hash node descriptor
*/ */
void hash_node_init(struct hash_node *node) void hash_node_init(struct hash_node *node)
@@ -58,6 +61,7 @@ void hash_node_init(struct hash_node *node)
} }
/** Cleanup hash node /** Cleanup hash node
@param node pointer to the hash node descriptor @param node pointer to the hash node descriptor
*/ */
void hash_node_cleanup(struct hash_node *node) void hash_node_cleanup(struct hash_node *node)
@@ -69,6 +73,7 @@ void hash_node_cleanup(struct hash_node *node)
} }
/** Initialize hash table /** Initialize hash table
@param map pointer to the hash table descriptor @param map pointer to the hash table descriptor
@param hash_shift size of the hash table in bits. Should be greater than @param hash_shift size of the hash table in bits. Should be greater than
HASH_MIN_SHIFT and less than HASH_MAX_SHIFT. In case of less than HASH_MIN_SHIFT, HASH_MIN_SHIFT and less than HASH_MAX_SHIFT. In case of less than HASH_MIN_SHIFT,
@@ -83,7 +88,8 @@ int hash_head_init(struct hash_head *map, unsigned int hash_shift, _hash_fn hf,
{ {
int i; int i;
if(map) { if(map)
{
if(hash_shift <= HASH_MIN_SHIFT) { if(hash_shift <= HASH_MIN_SHIFT) {
map->hash_shift = HASH_MIN_SHIFT; map->hash_shift = HASH_MIN_SHIFT;
} else if(hash_shift >= HASH_MAX_SHIFT) { } else if(hash_shift >= HASH_MAX_SHIFT) {
@@ -95,9 +101,11 @@ int hash_head_init(struct hash_head *map, unsigned int hash_shift, _hash_fn hf,
map->hash_size = 1UL << map->hash_shift; map->hash_size = 1UL << map->hash_shift;
map->hash_mask = (map->hash_size - 1); map->hash_mask = (map->hash_size - 1);
map->bucket = (list_head*)malloc(sizeof(list_head) * map->hash_size); map->bucket = (struct list_head *)malloc(sizeof(struct list_head) * map->hash_size);
if(map->bucket) { if(map->bucket)
for(uint16_t i = 0; i < map->hash_size; i++) { {
for(i = 0; i < map->hash_size; i++)
{
list_head_init(map->bucket + i); list_head_init(map->bucket + i);
} }
@@ -112,12 +120,12 @@ int hash_head_init(struct hash_head *map, unsigned int hash_shift, _hash_fn hf,
} else { } else {
map->compare_fn = default_compare_fn; map->compare_fn = default_compare_fn;
} }
} else {
return ENOMEM;
} }
} else { else
return ENODEV; return ENOMEM;
} }
else
return ENODEV;
return 0; return 0;
} }
@@ -132,10 +140,14 @@ void hash_head_cleanup(struct hash_head *map)
struct hash_node *node; struct hash_node *node;
int i; int i;
if(map) { if(map)
if(map->bucket) { {
for(i = 0; i < map->hash_size; i++) { if(map->bucket)
list_for_each_safe(p, n, map->bucket + i) { {
for(i = 0; i < map->hash_size; i++)
{
list_for_each_safe(p, n, map->bucket + i)
{
node = list_entry(p, struct hash_node, node); node = list_entry(p, struct hash_node, node);
hash_node_cleanup(node); hash_node_cleanup(node);
} }
@@ -160,12 +172,12 @@ struct hash_node* hash_find(struct hash_head *map, const void *key, int key_size
struct hash_node *node; struct hash_node *node;
list = map->bucket + (map->hash_fn(key, key_size) & map->hash_mask); list = map->bucket + (map->hash_fn(key, key_size) & map->hash_mask);
list_for_each(n, list) { list_for_each(n, list)
{
node = list_entry(n, struct hash_node, node); node = list_entry(n, struct hash_node, node);
if(key_size == node->key_size) { if(key_size == node->key_size)
if(map->compare_fn(key, node->key, key_size)) { {
return node; if(map->compare_fn(key, node->key, key_size)) return node;
}
} }
} }
@@ -184,9 +196,11 @@ struct hash_node* hash_find_next(struct hash_head *map, struct hash_node *hn1)
struct hash_node *hn2; struct hash_node *hn2;
while((n = list_next(n)) != NULL) { while((n = list_next(n)) != NULL)
{
hn2 = list_entry(n, struct hash_node, node); hn2 = list_entry(n, struct hash_node, node);
if(hn1->key_size == hn2->key_size) { if(hn1->key_size == hn2->key_size)
{
if(map->compare_fn(hn1->key, hn2->key, hn2->key_size)) return hn2; if(map->compare_fn(hn1->key, hn2->key, hn2->key_size)) return hn2;
} }
} }
@@ -203,10 +217,11 @@ struct hash_node* hash_find_next(struct hash_head *map, struct hash_node *hn1)
@return zero in case of success, ENOMEM in case of error @return zero in case of success, ENOMEM in case of error
*/ */
int hash_add(struct hash_head *map, struct hash_node *node, void *key, int key_size) int hash_add(struct hash_head *map, struct hash_node *node, const void *key, int key_size)
{ {
node->key = (char*)malloc(key_size); node->key = (char*)malloc(key_size);
if(node->key) { if(node->key)
{
memcpy(node->key, key, key_size); memcpy(node->key, key, key_size);
node->key_size = key_size; node->key_size = key_size;
list_add_bottom(map->bucket + (map->hash_fn(key, key_size) & map->hash_mask), &node->node); list_add_bottom(map->bucket + (map->hash_fn(key, key_size) & map->hash_mask), &node->node);
@@ -249,7 +264,8 @@ struct hash_node * hash_node_first(struct hash_iterator *iter)
iter->current = list_first(iter->map->bucket); iter->current = list_first(iter->map->bucket);
iter->map_idx = 0; iter->map_idx = 0;
if (iter->current) { if (iter->current)
{
return list_entry(iter->current, struct hash_node, node); return list_entry(iter->current, struct hash_node, node);
} }
@@ -263,14 +279,11 @@ struct hash_node * hash_node_first(struct hash_iterator *iter)
*/ */
struct hash_node * hash_node_next(struct hash_iterator *iter) struct hash_node * hash_node_next(struct hash_iterator *iter)
{ {
if(iter->map_idx >= iter->map->hash_size) { if(iter->map_idx >= iter->map->hash_size) return NULL;
return NULL;
}
if(iter->current) { if(iter->current) {
iter->current = list_next(iter->current); iter->current = list_next(iter->current);
} }
if(iter->current) { if(iter->current) {
return list_entry(iter->current, struct hash_node, node); return list_entry(iter->current, struct hash_node, node);
} }
@@ -308,9 +321,7 @@ int hash_count(struct hash_head *head)
int i; int i;
int count = 0; int count = 0;
for(i = 0; i < head->hash_size; i++) { for(i = 0; i < head->hash_size; i++) count += list_count(head->bucket + i);
count += list_count(head->bucket + i);
}
return count; return count;
} }
+24 -39
View File
@@ -1,21 +1,6 @@
#ifndef HASH_MULTIMAP_H #ifndef HASH_MULTIMAP_H
#define HASH_MULTIMAP_H #define HASH_MULTIMAP_H
/* =============================================================================
* CDL (Configuration Definition Language) validator $Revision: 1.4 $
* (C)2004-2007 Nikolai Nosov. All rights reserved.
*
* File: $RCSfile: hash_multimap.c,v $
* Purpose: Hash Multimap implementation
* Written by: Nikolai Nosov nnosov@gmail.com
* Last modified: $Date: 2008/06/21 12:15:53 $ by $Author: nnosov $.
*
* For more information please visit
* http://cdl.sourceforge.net
* ===========================================================================*/
#include <stdint.h>
#include "list_head.h" #include "list_head.h"
#define HASH_MIN_SHIFT (8) #define HASH_MIN_SHIFT (8)
@@ -29,12 +14,12 @@
@param key_size hash key size in bytes @param key_size hash key size in bytes
@param node uplink to hash multimap table @param node uplink to hash multimap table
*/ */
typedef struct hash_node struct hash_node
{ {
list_node node; char *key;
char* key; int key_size;
int key_size; struct list_node node;
} hash_node; };
/** Hash function prototype /** Hash function prototype
@@ -42,7 +27,7 @@ typedef struct hash_node
@param key_size hash key size in bytes @param key_size hash key size in bytes
@return hash value @return hash value
*/ */
typedef unsigned int (* _hash_fn)(const char *key, int key_size); typedef unsigned int (* _hash_fn)(const void *key, int key_size);
/** Compare function prototype /** Compare function prototype
* *
@@ -52,7 +37,7 @@ typedef unsigned int (* _hash_fn)(const char *key, int key_size);
* *
* @return zero if keys equals each other, othervize 1 * @return zero if keys equals each other, othervize 1
*/ */
typedef int (*_compare_fn)(const char *key1, const char *key2, int size); typedef int (*_compare_fn)(const void *key1, const void *key2, int size);
/** Hash multimap table descriptor /** Hash multimap table descriptor
@@ -63,15 +48,17 @@ typedef int (*_compare_fn)(const char *key1, const char *key2, int size);
hash multimap table hash multimap table
@param count count of the nodes in the hash table @param count count of the nodes in the hash table
*/ */
typedef struct hash_head { struct hash_head
uint8_t hash_shift; {
uint16_t hash_size; unsigned char hash_shift;
uint32_t hash_mask; unsigned short hash_size;
list_head* bucket; unsigned int hash_mask;
struct list_head *bucket;
//int count;
_hash_fn hash_fn; _hash_fn hash_fn;
_compare_fn compare_fn; _compare_fn compare_fn;
} hash_head; };
/** Hash table iterator /** Hash table iterator
@@ -79,25 +66,23 @@ typedef struct hash_head {
@param current pointer to the current list node (bucket[map_idx]) @param current pointer to the current list node (bucket[map_idx])
@param map_idx current bucket index @param map_idx current bucket index
*/ */
struct hash_iterator { struct hash_iterator
hash_head* map; // pointer to the hash map header {
list_node* current; // pointer to current list node in the bucket[map_idx] list struct hash_head *map; // pointer to the hash map header
int map_idx; // index of current list in the hash map bucket struct list_node *current; // pointer to current list node in the bucket[map_idx] list
unsigned int map_idx; // index of current list in the hash map bucket
}; };
void hash_node_init(struct hash_node *node); void hash_node_init(struct hash_node *node);
void hash_node_cleanup(struct hash_node *node); void hash_node_cleanup(struct hash_node *node);
unsigned int default_hash_fn(const char *key, int size); int hash_head_init(struct hash_head *map, unsigned int hash_shift = HASH_MIN_SHIFT, _hash_fn hf = 0, _compare_fn cf = 0);
int default_compare_fn(const char *key1, const char *key2, const int size);
int hash_head_init(struct hash_head *map, unsigned int hash_shift = 8, _hash_fn hf = default_hash_fn, _compare_fn cf = default_compare_fn);
void hash_head_cleanup(struct hash_head *map); void hash_head_cleanup(struct hash_head *map);
struct hash_node* hash_find(struct hash_head *map, const void *key, int key_size); struct hash_node* hash_find(struct hash_head *map, const void *key, int key_size);
struct hash_node* hash_find_next(struct hash_head *map, struct hash_node *node); struct hash_node* hash_find_next(struct hash_head *map, struct hash_node *node);
int hash_add(struct hash_head *map, struct hash_node *node, void *key, int key_size); int hash_add(struct hash_head *map, struct hash_node *node, const void *key, int key_size);
void hash_del(struct hash_node *node); void hash_del(struct hash_node *node);
void hash_iterator_init(struct hash_head *map, struct hash_iterator *iter); void hash_iterator_init(struct hash_head *map, struct hash_iterator *iter);
+2 -2
View File
@@ -77,7 +77,7 @@ void log_init_base(pst_log* plog, const char* source)
plog->child = 0; plog->child = 0;
} }
void log_fini(pst_log* log) void pst_log_fini(pst_log* log)
{ {
pthread_mutex_destroy(&log->mLock); pthread_mutex_destroy(&log->mLock);
log->close(log); log->close(log);
@@ -133,7 +133,7 @@ bool is_opened_console(pst_log* log) {
return true; return true;
} }
void pst_init_console(pst_log* log) void pst_log_init_console(pst_log* log)
{ {
log_init_base(log, NULL); log_init_base(log, NULL);
log->close = close_console; log->close = close_console;
-11
View File
@@ -21,15 +21,4 @@ typedef enum {
REG_EXPR_ERROR REG_EXPR_ERROR
} pst_reg_error; } pst_reg_error;
typedef struct __pst_frame : public SC_ListNode {
__pst_frame() {
memset(reg_state, REG_UNDEFINED, sizeof(reg_state));
memset(regs, 0, sizeof(regs));
cfa = 0;
}
int32_t reg_state[128];
uint64_t regs[128];
uint64_t cfa;
} pst_frame;
pst_reg_error pst_get_reg(pst_context* ctx, int regno, uint64_t& regval); pst_reg_error pst_get_reg(pst_context* ctx, int regno, uint64_t& regval);
+128 -80
View File
@@ -34,26 +34,26 @@
// dwarf_getattrs() allows to enumerate all DIE attributes // dwarf_getattrs() allows to enumerate all DIE attributes
// dwarf_getfuncs() allows to enumerate functions within CU // dwarf_getfuncs() allows to enumerate functions within CU
bool __pst_handler::get_dwarf_function(pst_function* fun) bool handler_get_dwarf_function(pst_handler* h, pst_function* fun)
{ {
Dwarf_Addr mod_cu = 0; Dwarf_Addr mod_cu = 0;
// get CU(Compilation Unit) debug definition // get CU(Compilation Unit) debug definition
ctx.module = dwfl_addrmodule(ctx.dwfl, fun->pc); h->ctx.module = dwfl_addrmodule(h->ctx.dwfl, fun->pc);
Dwarf_Die* cdie = dwfl_module_addrdie(ctx.module, fun->pc, &mod_cu); Dwarf_Die* cdie = dwfl_module_addrdie(h->ctx.module, fun->pc, &mod_cu);
//Dwarf_Die* cdie = dwfl_addrdie(dwfl, addr, &mod_bias); //Dwarf_Die* cdie = dwfl_addrdie(dwfl, addr, &mod_bias);
if(!cdie) { if(!cdie) {
ctx.log(SEVERITY_INFO, "Failed to find DWARF DIE for address %X", fun->pc); h->ctx.log(SEVERITY_INFO, "Failed to find DWARF DIE for address %X", fun->pc);
return false; return false;
} }
if(dwarf_tag(cdie) != DW_TAG_compile_unit) { if(dwarf_tag(cdie) != DW_TAG_compile_unit) {
ctx.log(SEVERITY_DEBUG, "Skipping non-cu die. DWARF tag: 0x%X, name = %s", dwarf_tag(cdie), dwarf_diename(cdie)); h->ctx.log(SEVERITY_DEBUG, "Skipping non-cu die. DWARF tag: 0x%X, name = %s", dwarf_tag(cdie), dwarf_diename(cdie));
return false; return false;
} }
Dwarf_Die result; Dwarf_Die result;
if(dwarf_child(cdie, &result)) { if(dwarf_child(cdie, &result)) {
ctx.log(SEVERITY_ERROR, "No child DIE found for CU %s", dwarf_diename(cdie)); h->ctx.log(SEVERITY_ERROR, "No child DIE found for CU %s", dwarf_diename(cdie));
return false; return false;
} }
@@ -63,8 +63,8 @@ bool __pst_handler::get_dwarf_function(pst_function* fun)
int tag = dwarf_tag(&result); int tag = dwarf_tag(&result);
if(tag == DW_TAG_subprogram || tag == DW_TAG_entry_point || tag == DW_TAG_inlined_subroutine) { 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)); //ctx.log(SEVERITY_DEBUG, "function die name %s", dwarf_diename(&result));
if(!strcmp(fun->name.c_str(), dwarf_diename(&result))) { if(!strcmp(fun->name, dwarf_diename(&result))) {
return fun->handle_dwarf(&result); return fun->handle_dwarf(fun, &result);
} }
} }
} while(dwarf_siblingof(&result, &result) == 0); } while(dwarf_siblingof(&result, &result) == 0);
@@ -72,76 +72,95 @@ bool __pst_handler::get_dwarf_function(pst_function* fun)
return nret; return nret;
} }
pst_function* __pst_handler::add_function(__pst_function* parent) pst_function* handler_add_function(pst_handler* h, pst_function* parent)
{ {
pst_function* f = new pst_function(&ctx, parent); pst_new(pst_function, fn, &h->ctx, parent);
functions.InsertLast(f); list_add_bottom(&h->functions, &fn->node);
return f; return fn;
} }
void __pst_handler::del_function(pst_function* f) void handler_del_function(pst_function* fn)
{ {
functions.Remove(f); list_del(&fn->node);
delete f; pst_function_fini(fn);
} }
void __pst_handler::clear() void handler_clear(pst_handler* h)
{ {
for(pst_function* f = (pst_function*)functions.First(); f; f = (pst_function*)functions.First()) { pst_function* fn = NULL;
functions.Remove(f); struct list_node *pos, *tn;
delete f; list_for_each_entry_safe(fn, pos, tn, &h->functions, node) {
list_del(&fn->node);
pst_function_fini(fn);
} }
} }
pst_function* __pst_handler::next_function(pst_function* f) pst_function* handler_next_function(pst_handler* h, pst_function* fn)
{ {
pst_function* next = NULL; list_node* n = (fn == NULL) ? list_first(&h->functions) : list_next(&fn->node);
if(!f) { pst_function* ret = NULL;
next = (pst_function*)functions.First(); if(n) {
} else { ret = list_entry(n, pst_function, node);
next = (pst_function*)functions.Next(f);
} }
return next; return ret;
} }
pst_function* __pst_handler::last_function() pst_function* handler_prev_function(pst_handler* h, pst_function* fn)
{ {
return (pst_function*)functions.Last(); list_node* n = (fn == NULL) ? list_last(&h->functions) : list_prev(&fn->node);
pst_function* ret = NULL;
if(n) {
ret = list_entry(n, pst_function, node);
}
return ret;
} }
bool __pst_handler::handle_dwarf() pst_function* handler_last_function(pst_handler* h)
{ {
ctx.clean_print(&ctx); list_node* n = list_last(&h->functions);
if(n) {
return list_entry(n, pst_function, node);
}
return NULL;
}
bool handler_handle_dwarf(pst_handler* h)
{
h->ctx.clean_print(&h->ctx);
Dl_info info; Dl_info info;
//for(pst_function* fun = next_function(NULL); fun; fun = next_function(fun)) { //for(pst_function* fun = next_function(NULL); fun; fun = next_function(fun)) {
for(pst_function* fun = (pst_function*)functions.Last(); fun; fun = (pst_function*)functions.Prev(fun)) { for(pst_function* fun = (pst_function*)handler_last_function(h); fun; fun = h->prev_function(h, fun)) {
dladdr((void*)(fun->pc), &info); dladdr((void*)(fun->pc), &info);
ctx.module = dwfl_addrmodule(ctx.dwfl, fun->pc); h->ctx.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);
ctx.base_addr = (uint64_t)info.dli_fbase;
ctx.log(SEVERITY_INFO, "Function %s(...): module name: %s, base address: %p, CFA: %#lX", fun->name.c_str(), info.dli_fname, info.dli_fbase, fun->parent ? fun->parent->sp : 0);
ctx.curr_frame = &fun->cursor;
ctx.sp = fun->sp;
ctx.cfa = fun->cfa;
ctx.curr_frame = &fun->cursor; // setup context
get_dwarf_function(fun); h->ctx.module = dwfl_addrmodule(h->ctx.dwfl, fun->pc);
h->ctx.base_addr = (uint64_t)info.dli_fbase;
h->ctx.curr_frame = &fun->cursor;
h->ctx.sp = fun->sp;
h->ctx.cfa = fun->cfa;
h->ctx.curr_frame = &fun->cursor;
handler_get_dwarf_function(h, fun);
} }
return true; return true;
} }
void __pst_handler::print_dwarf() void handler_print_dwarf(pst_handler* h)
{ {
ctx.clean_print(&ctx); h->ctx.clean_print(&h->ctx);
ctx.print(&ctx, "DWARF-based stack trace information:\n"); h->ctx.print(&h->ctx, "DWARF-based stack trace information:\n");
uint32_t idx = 0; uint32_t idx = 0;
for(pst_function* function = next_function(NULL); function; function = next_function(function)) { for(pst_function* fn = h->next_function(h, NULL); fn; fn = h->next_function(h, fn)) {
ctx.print(&ctx, "[%-2u] ", idx); idx++; h->ctx.print(&h->ctx, "[%-2u] ", idx); idx++;
function->print_dwarf(); fn->print_dwarf(fn);
ctx.print(&ctx, "\n"); h->ctx.print(&h->ctx, "\n");
} }
} }
@@ -155,13 +174,13 @@ Dwfl_Callbacks callbacks = {
#include <dlfcn.h> #include <dlfcn.h>
bool __pst_handler::unwind() bool handler_unwind(pst_handler* h)
{ {
ctx.clean_print(&ctx); h->ctx.clean_print(&h->ctx);
#ifdef REG_RIP // x86_64 #ifdef REG_RIP // x86_64
caller = (void *) ctx.hcontext->uc_mcontext.gregs[REG_RIP]; h->caller = (void *) h->ctx.hcontext->uc_mcontext.gregs[REG_RIP];
ctx.sp = ctx.hcontext->uc_mcontext.gregs[REG_RSP]; h->ctx.sp = h->ctx.hcontext->uc_mcontext.gregs[REG_RSP];
ctx.log(SEVERITY_DEBUG, "Original caller's SP: %#lX", ctx.sp); h->ctx.log(SEVERITY_DEBUG, "Original caller's SP: %#lX", h->ctx.sp);
#elif defined(REG_EIP) // x86_32 #elif defined(REG_EIP) // x86_32
caller_address = (void *) uctx->uc_mcontext.gregs[REG_EIP]); caller_address = (void *) uctx->uc_mcontext.gregs[REG_EIP]);
#elif defined(__arm__) #elif defined(__arm__)
@@ -180,60 +199,89 @@ bool __pst_handler::unwind()
//handle = dlopen(NULL, RTLD_NOW); //handle = dlopen(NULL, RTLD_NOW);
Dl_info info; Dl_info info;
dladdr(caller, &info); dladdr(h->caller, &info);
ctx.base_addr = (uint64_t)info.dli_fbase; h->ctx.base_addr = (uint64_t)info.dli_fbase;
ctx.log(SEVERITY_INFO, "Process address information: PC address: %p, base address: %p, object name: %s", caller, info.dli_fbase, info.dli_fname); h->ctx.log(SEVERITY_INFO, "Process address information: PC address: %p, base address: %p, object name: %s", h->caller, info.dli_fbase, info.dli_fname);
ctx.dwfl = dwfl_begin(&callbacks); h->ctx.dwfl = dwfl_begin(&callbacks);
if(ctx.dwfl == NULL) { if(h->ctx.dwfl == NULL) {
ctx.print(&ctx, "Failed to initialize libdw session for parse stack frames"); h->ctx.print(&h->ctx, "Failed to initialize libdw session for parse stack frames");
return false; return false;
} }
if(dwfl_linux_proc_report(ctx.dwfl, getpid()) != 0 || dwfl_report_end(ctx.dwfl, NULL, NULL) !=0) { if(dwfl_linux_proc_report(h->ctx.dwfl, getpid()) != 0 || dwfl_report_end(h->ctx.dwfl, NULL, NULL) !=0) {
ctx.print(&ctx, "Failed to parse debug section of executable"); h->ctx.print(&h->ctx, "Failed to parse debug section of executable");
return false; return false;
} }
ctx.print(&ctx, "Stack trace: caller = %p\n", caller); h->ctx.print(&h->ctx, "Stack trace: caller = %p\n", h->caller);
unw_getcontext(&ctx.context); unw_getcontext(&h->ctx.context);
unw_init_local(&ctx.cursor, &ctx.context); unw_init_local(&h->ctx.cursor, &h->ctx.context);
ctx.curr_frame = &ctx.cursor; h->ctx.curr_frame = &h->ctx.cursor;
for(int i = 0, skip = 1; unw_step(ctx.curr_frame) > 0; ++i) { for(int i = 0, skip = 1; unw_step(h->ctx.curr_frame) > 0; ++i) {
if(unw_get_reg(ctx.curr_frame, UNW_REG_IP, &addr)) { if(unw_get_reg(h->ctx.curr_frame, UNW_REG_IP, &h->addr)) {
ctx.log(SEVERITY_DEBUG, "Failed to get IP value"); h->ctx.log(SEVERITY_DEBUG, "Failed to get IP value");
continue; continue;
} }
unw_word_t sp; unw_word_t sp;
if(unw_get_reg(ctx.curr_frame, UNW_REG_SP, &sp)) { if(unw_get_reg(h->ctx.curr_frame, UNW_REG_SP, &sp)) {
ctx.log(SEVERITY_DEBUG, "Failed to get SP value"); h->ctx.log(SEVERITY_DEBUG, "Failed to get SP value");
continue; continue;
} }
if(addr == (uint64_t)caller) { if(h->addr == (uint64_t)h->caller) {
skip = 0; skip = 0;
} else if(skip) { } else if(skip) {
ctx.log(SEVERITY_DEBUG, "Skipping frame #%d: PC = %#lX, SP = %#lX", i, addr, sp); h->ctx.log(SEVERITY_DEBUG, "Skipping frame #%d: PC = %#lX, SP = %#lX", i, h->addr, sp);
continue; continue;
} }
ctx.print(&ctx, "[%-2d] ", i); h->ctx.print(&h->ctx, "[%-2d] ", i);
ctx.module = dwfl_addrmodule(ctx.dwfl, addr); h->ctx.module = dwfl_addrmodule(h->ctx.dwfl, h->addr);
pst_function* last = last_function(); pst_function* last = handler_last_function(h);
pst_function* fun = add_function(NULL); pst_function* fn = h->add_function(h, NULL);
fun->sp = sp; fn->sp = sp;
ctx.log(SEVERITY_DEBUG, "Analyze frame #%d: PC = %#lX, SP = %#lX", i, addr, sp); h->ctx.log(SEVERITY_DEBUG, "Analyze frame #%d: PC = %#lX, SP = %#lX", i, h->addr, sp);
if(!fun->unwind(addr)) { if(!fn->unwind(fn, h->addr)) {
del_function(fun); h->del_function(fn);
} else { } else {
if(last) { if(last) {
last->parent = fun; last->parent = fn;
} }
//get_frame(fun); //get_frame(fun);
} }
ctx.print(&ctx, "\n"); h->ctx.print(&h->ctx, "\n");
} }
return true; return true;
} }
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;
// fields
pst_context_init(&h->ctx, hctx);
h->handle = NULL;
h->addr = 0;
h->frame = NULL;
h->caller = NULL;
list_head_init(&h->functions);
}
void pst_handler_fini(pst_handler* h)
{
if(h->handle) {
dlclose(h->handle);
}
h->clear(h);
pst_context_fini(&h->ctx);
}
+14 -30
View File
@@ -32,43 +32,27 @@
#include "dwarf_utils.h" #include "dwarf_utils.h"
#include "dwarf_function.h" #include "dwarf_function.h"
typedef struct __pst_handler { typedef struct pst_handler {
__pst_handler(ucontext_t* hctx) // methods
{ void (*clear) (pst_handler* h);
pst_context_init(&ctx, hctx); pst_function* (*add_function) (pst_handler* h, pst_function* fun);
caller = NULL; void (*del_function) (pst_function* f);
frame = NULL; pst_function* (*next_function) (pst_handler* h, pst_function* f);
addr = 0; pst_function* (*prev_function) (pst_handler* h, pst_function* fn);
handle = 0;
}
~__pst_handler() bool (*handle_dwarf) (pst_handler* h);
{ void (*print_dwarf) (pst_handler* h);
if(handle) { bool (*unwind) (pst_handler* h);
dlclose(handle);
}
clear();
pst_context_fini(&ctx);
}
void clear();
pst_function* add_function(pst_function* fun);
void del_function(pst_function* f);
pst_function* next_function(pst_function* f);
pst_function* last_function();
bool handle_dwarf();
void print_dwarf();
bool unwind();
bool get_dwarf_function(pst_function* fun);
// fields
pst_context ctx; // context of unwinding pst_context ctx; // context of unwinding
void* handle; // process handle void* handle; // process handle
Dwarf_Addr addr; // address of currently processed function Dwarf_Addr addr; // address of currently processed function
Dwarf_Frame* frame; // currently processed stack frame Dwarf_Frame* frame; // currently processed stack frame
void* caller; // pointer to the function which requested to unwind stack void* caller; // pointer to the function which requested to unwind stack
SC_ListHead functions; // list of functions in stack frame list_head functions; // list of functions in stack frame
} pst_handler; } pst_handler;
void pst_handler_init(pst_handler* h, ucontext_t* hctx);
void pst_handler_fini(pst_handler* h);
#endif /* SC_SYSUTILS_H_ */ #endif /* SC_SYSUTILS_H_ */
+4 -4
View File
@@ -62,17 +62,17 @@ void FatalSignalHandler(int sig, siginfo_t* info, void* context)
pst_log(SEVERITY_ERROR, "%s signal handled", strsignal(sig)); pst_log(SEVERITY_ERROR, "%s signal handled", strsignal(sig));
bool ret = false; bool ret = false;
pst_handler handler((ucontext_t*)context); pst_decl(pst_handler, handler, (ucontext_t*)context);
if((context != 0) && (sig == SIGSEGV || sig == SIGABRT || sig == SIGBUS || sig == SIGFPE)) if((context != 0) && (sig == SIGSEGV || sig == SIGABRT || sig == SIGBUS || sig == SIGFPE))
{ {
ret = handler.unwind(); ret = handler.unwind(&handler);
} }
if(ret) { if(ret) {
pst_log(SEVERITY_INFO, "%s", handler.ctx.buff); pst_log(SEVERITY_INFO, "%s", handler.ctx.buff);
handler.handle_dwarf(); handler.handle_dwarf(&handler);
handler.print_dwarf(); handler.print_dwarf(&handler);
pst_log(SEVERITY_INFO, "%s", handler.ctx.buff); pst_log(SEVERITY_INFO, "%s", handler.ctx.buff);
} else { } else {
pst_log(SEVERITY_ERROR, "No stack trace obtained"); pst_log(SEVERITY_ERROR, "No stack trace obtained");