fix most of compilation warnings
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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_ */
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ bool param_print_dwarf(pst_parameter* param)
|
|||||||
if(list_count(¶m->types)) {
|
if(list_count(¶m->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, ¶m->size);
|
dwarf_formudata(attr, ¶m->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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
+49
-38
@@ -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 {
|
}
|
||||||
|
else
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
} else {
|
else
|
||||||
return ENODEV;
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-35
@@ -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;
|
||||||
} hash_node;
|
struct list_node 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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool __pst_handler::handle_dwarf()
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
@@ -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_ */
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user