introduce separate print functions for 'simple' and 'pretty' variands of
unwinding
This commit is contained in:
@@ -72,6 +72,7 @@ static bool get_frame(pst_function* fn)
|
||||
|
||||
fn->ctx->print_expr(fn->ctx, cfa_ops, cfa_nops, NULL);
|
||||
|
||||
bool nret = true;
|
||||
pst_decl(pst_dwarf_stack, stack, fn->ctx);
|
||||
if(pst_dwarf_stack_calc(&stack, cfa_ops, cfa_nops, NULL, NULL) && pst_dwarf_stack_get_value(&stack, &fn->cfa)) {
|
||||
pst_log(SEVERITY_INFO, "Function %s(...): CFA expression: %s ==> %#lX", fn->name, fn->ctx->buff, fn->cfa);
|
||||
@@ -79,12 +80,13 @@ static bool get_frame(pst_function* fn)
|
||||
// setup context to match CFA for frame
|
||||
fn->ctx->cfa = fn->cfa;
|
||||
} else {
|
||||
nret = false;
|
||||
pst_log(SEVERITY_ERROR, "Failed to calculate CFA expression");
|
||||
}
|
||||
|
||||
pst_dwarf_stack_fini(&stack);
|
||||
|
||||
return true;
|
||||
return nret;
|
||||
}
|
||||
|
||||
static pst_parameter* add_param(pst_function* fn)
|
||||
@@ -189,16 +191,12 @@ bool handle_lexical_block(pst_function* fn, Dwarf_Die* result)
|
||||
bool pst_function_print_dwarf(pst_function* fn)
|
||||
{
|
||||
char* at = NULL;
|
||||
if(!asprintf(&at, " at %s:%d, %p", fn->file, fn->line, (void*)fn->pc)) {
|
||||
if(fn->file) {
|
||||
if(!asprintf(&at, " at %s:%d, %p", fn->file, fn->line, (void*)fn->pc))
|
||||
return false;
|
||||
} else if(!asprintf(&at, " at %p", (void*)fn->pc)){
|
||||
return false;
|
||||
}
|
||||
if(at[4] == ':' && at[5] == '-') {
|
||||
free(at);
|
||||
if(!asprintf(&at, " at %p", (void*)fn->pc)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//ctx->print(ctx, "%s:%d: ", file.c_str(), line);
|
||||
|
||||
// handle return parameter and be safe if function haven't parameters (for example, dwar info for function is absent)
|
||||
pst_parameter* param = next_param(fn, NULL);
|
||||
@@ -244,7 +242,7 @@ bool pst_function_print_dwarf(pst_function* fn)
|
||||
}
|
||||
|
||||
if(!start_variable) {
|
||||
fn->ctx->print(fn->ctx, ");%s\n", at);
|
||||
fn->ctx->print(fn->ctx, ")%s\n", at);
|
||||
} else {
|
||||
fn->ctx->print(fn->ctx, "}\n");
|
||||
}
|
||||
@@ -388,12 +386,7 @@ bool pst_function_unwind(pst_function* fn)
|
||||
file = filename;
|
||||
}
|
||||
fn->file = pst_strdup(file);
|
||||
fn->ctx->print(fn->ctx, "%s:%d", fn->file, fn->line);
|
||||
} else {
|
||||
fn->ctx->print(fn->ctx, "%p", (void*)fn->pc);
|
||||
}
|
||||
} else {
|
||||
fn->ctx->print(fn->ctx, "%p", (void*)fn->pc);
|
||||
}
|
||||
|
||||
Dwfl_Module* module = dwfl_addrmodule(fn->ctx->dwfl, fn->pc);
|
||||
@@ -405,7 +398,6 @@ bool pst_function_unwind(pst_function* fn)
|
||||
pst_log(SEVERITY_ERROR, "Failed to allocate memory");
|
||||
return false;
|
||||
}
|
||||
fn->ctx->print(fn->ctx, " --> %s", function_name);
|
||||
|
||||
char* str = strchr(function_name, '(');
|
||||
if(str) {
|
||||
|
||||
+61
-36
@@ -156,7 +156,7 @@ bool pst_handler_handle_dwarf(pst_handler* h)
|
||||
return true;
|
||||
}
|
||||
|
||||
void pst_handler_print_dwarf(pst_handler* h)
|
||||
const char* pst_print_pretty(pst_handler* h)
|
||||
{
|
||||
h->ctx.clean_print(&h->ctx);
|
||||
h->ctx.print(&h->ctx, "DWARF-based stack trace information:\n");
|
||||
@@ -166,6 +166,8 @@ void pst_handler_print_dwarf(pst_handler* h)
|
||||
pst_function_print_dwarf(fn);
|
||||
h->ctx.print(&h->ctx, "\n");
|
||||
}
|
||||
|
||||
return h->ctx.buff;
|
||||
}
|
||||
|
||||
char *debuginfo_path = NULL;
|
||||
@@ -177,53 +179,76 @@ Dwfl_Callbacks callbacks = {
|
||||
};
|
||||
|
||||
#include <dlfcn.h>
|
||||
const char* pst_print_simple(pst_handler* h)
|
||||
{
|
||||
h->ctx.clean_print(&h->ctx);
|
||||
h->ctx.print(&h->ctx, "Simple unwind-based stack trace:\n");
|
||||
uint32_t idx = 0;
|
||||
for(pst_function* fn = next_function(h, NULL); fn; fn = next_function(h, fn)) {
|
||||
h->ctx.print(&h->ctx, "[%-2d] ", idx);
|
||||
h->ctx.print(fn->ctx, "%s() ", fn->name);
|
||||
if(fn->file) {
|
||||
h->ctx.print(fn->ctx, "at %s:%d, %p", fn->file, fn->line, (void*)fn->pc);
|
||||
} else {
|
||||
h->ctx.print(fn->ctx, "at %p", (void*)fn->pc);
|
||||
}
|
||||
h->ctx.print(&h->ctx, "\n");
|
||||
idx++;
|
||||
}
|
||||
|
||||
return h->ctx.buff;
|
||||
}
|
||||
|
||||
|
||||
bool pst_handler_unwind(pst_handler* h)
|
||||
{
|
||||
h->ctx.clean_print(&h->ctx);
|
||||
void* caller; // pointer to the function which requested to unwind stack
|
||||
void* caller = NULL; // pointer to the function which requested to unwind stack
|
||||
|
||||
#ifdef REG_RIP // x86_64
|
||||
caller = (void *) h->ctx.hcontext->uc_mcontext.gregs[REG_RIP];
|
||||
h->ctx.sp = h->ctx.hcontext->uc_mcontext.gregs[REG_RSP];
|
||||
pst_log(SEVERITY_DEBUG, "Original caller's SP: %#lX", h->ctx.sp);
|
||||
#elif defined(REG_EIP) // x86_32
|
||||
caller = (void *) uctx->uc_mcontext.gregs[REG_EIP]);
|
||||
#elif defined(__arm__)
|
||||
caller = (void *) uctx->uc_mcontext.arm_pc);
|
||||
#elif defined(__aarch64__)
|
||||
caller = (void *) uctx->uc_mcontext.pc);
|
||||
#elif defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__)
|
||||
caller = (void *) uctx->uc_mcontext.regs->nip);
|
||||
#elif defined(__s390x__)
|
||||
caller = (void *) uctx->uc_mcontext.psw.addr);
|
||||
#elif defined(__APPLE__) && defined(__x86_64__)
|
||||
caller = (void *) uctx->uc_mcontext->__ss.__rip);
|
||||
#else
|
||||
# error "unknown architecture!"
|
||||
#endif
|
||||
if(h->ctx.hcontext) {
|
||||
#ifdef REG_RIP // x86_64
|
||||
caller = (void *) h->ctx.hcontext->uc_mcontext.gregs[REG_RIP];
|
||||
h->ctx.sp = h->ctx.hcontext->uc_mcontext.gregs[REG_RSP];
|
||||
pst_log(SEVERITY_DEBUG, "Original caller's SP: %#lX", h->ctx.sp);
|
||||
#elif defined(REG_EIP) // x86_32
|
||||
caller = (void *) h->uc_mcontext.gregs[REG_EIP]);
|
||||
#elif defined(__arm__)
|
||||
caller = (void *) h->uc_mcontext.arm_pc);
|
||||
#elif defined(__aarch64__)
|
||||
caller = (void *) h->uc_mcontext.pc);
|
||||
#elif defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__)
|
||||
caller = (void *) h->uc_mcontext.regs->nip);
|
||||
#elif defined(__s390x__)
|
||||
caller = (void *) h->uc_mcontext.psw.addr);
|
||||
#elif defined(__APPLE__) && defined(__x86_64__)
|
||||
caller = (void *) h->uc_mcontext->__ss.__rip);
|
||||
#else
|
||||
# error "unknown architecture!"
|
||||
#endif
|
||||
}
|
||||
|
||||
//handle = dlopen(NULL, RTLD_NOW);
|
||||
Dl_info info;
|
||||
dladdr(caller, &info);
|
||||
h->ctx.base_addr = (uint64_t)info.dli_fbase;
|
||||
pst_log(SEVERITY_INFO, "Process address information: PC address: %p, base address: %p, object name: %s", caller, info.dli_fbase, info.dli_fname);
|
||||
if(caller) {
|
||||
Dl_info info;
|
||||
dladdr(caller, &info);
|
||||
h->ctx.base_addr = (uint64_t)info.dli_fbase;
|
||||
pst_log(SEVERITY_INFO, "Process address information: PC address: %p, base address: %p, object name: %s", caller, info.dli_fbase, info.dli_fname);
|
||||
}
|
||||
|
||||
if(!h->ctx.dwfl) {
|
||||
h->ctx.dwfl = dwfl_begin(&callbacks);
|
||||
if(h->ctx.dwfl == NULL) {
|
||||
h->ctx.print(&h->ctx, "Failed to initialize libdw session for parse stack frames");
|
||||
pst_log(SEVERITY_ERROR, "Failed to initialize libdw session to parse stack frames");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(dwfl_linux_proc_report(h->ctx.dwfl, getpid()) != 0 || dwfl_report_end(h->ctx.dwfl, NULL, NULL) !=0) {
|
||||
h->ctx.print(&h->ctx, "Failed to parse debug section of executable");
|
||||
pst_log(SEVERITY_ERROR, "Failed to parse debug section of executable");
|
||||
dwfl_end(h->ctx.dwfl);
|
||||
h->ctx.dwfl = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
h->ctx.print(&h->ctx, "Stack trace: caller = %p\n", caller);
|
||||
pst_log(SEVERITY_INFO, "Stack trace: caller = %p\n", caller);
|
||||
|
||||
unw_getcontext(&h->ctx.context);
|
||||
unw_init_local(&h->ctx.cursor, &h->ctx.context);
|
||||
@@ -239,14 +264,15 @@ bool pst_handler_unwind(pst_handler* h)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(pc == (uint64_t)caller) {
|
||||
skip = 0;
|
||||
} else if(skip) {
|
||||
pst_log(SEVERITY_DEBUG, "Skipping frame #%d: PC = %#lX, SP = %#lX", i, pc, sp);
|
||||
continue;
|
||||
if(caller) {
|
||||
if(pc == (uint64_t)caller) {
|
||||
skip = 0;
|
||||
} else if(skip) {
|
||||
pst_log(SEVERITY_DEBUG, "Skipping frame #%d: PC = %#lX, SP = %#lX", i, pc, sp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
h->ctx.print(&h->ctx, "[%-2d] ", i);
|
||||
pst_log(SEVERITY_DEBUG, "Analyze frame #%d: PC = %#lX, SP = %#lX", i, pc, sp);
|
||||
pst_function* last = last_function(h);
|
||||
pst_function* fn = add_function(h, NULL);
|
||||
@@ -256,7 +282,6 @@ bool pst_handler_unwind(pst_handler* h)
|
||||
} else if(last) {
|
||||
last->parent = fn;
|
||||
}
|
||||
h->ctx.print(&h->ctx, "\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "utils/list_head.h"
|
||||
#include "common.h"
|
||||
#include "context.h"
|
||||
#include "dwarf_function.h"
|
||||
|
||||
typedef struct pst_handler {
|
||||
pst_context ctx; // context of unwinding
|
||||
@@ -26,7 +27,6 @@ pst_handler* pst_handler_new(ucontext_t* hctx);
|
||||
void pst_handler_fini(pst_handler* h);
|
||||
|
||||
bool pst_handler_handle_dwarf(pst_handler* h);
|
||||
void pst_handler_print_dwarf(pst_handler* h);
|
||||
bool pst_handler_unwind(pst_handler* h);
|
||||
|
||||
#endif /* __PST_DWARF_HANDLER_H__ */
|
||||
|
||||
Reference in New Issue
Block a user