refactor of function unwinding
This commit is contained in:
+18
-21
@@ -375,34 +375,31 @@ bool pst_function_handle_dwarf(pst_function * fn, Dwarf_Die* d)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pst_function_unwind(pst_function* fn, Dwarf_Addr addr)
|
||||
bool pst_function_unwind(pst_function* fn)
|
||||
{
|
||||
fn->pc = addr;
|
||||
|
||||
Dwfl_Line *dwline = dwfl_getsrc(fn->ctx->dwfl, addr);
|
||||
Dwfl_Line *dwline = dwfl_getsrc(fn->ctx->dwfl, fn->pc);
|
||||
if(dwline != NULL) {
|
||||
Dwarf_Addr addr;
|
||||
const char* filename = dwfl_lineinfo (dwline, &addr, &fn->line, NULL, NULL, NULL);
|
||||
const char* filename = dwfl_lineinfo (dwline, &fn->pc, &fn->line, NULL, NULL, NULL);
|
||||
if(filename) {
|
||||
const char* str = strrchr(filename, '/');
|
||||
if(str && *str != 0) {
|
||||
str++;
|
||||
const char* file = strrchr(filename, '/');
|
||||
if(file && *file != 0) {
|
||||
file++;
|
||||
} else {
|
||||
str = filename;
|
||||
file = filename;
|
||||
}
|
||||
fn->file = pst_strdup(str);
|
||||
fn->ctx->print(fn->ctx, "%s:%d", str, fn->line);
|
||||
fn->file = pst_strdup(file);
|
||||
fn->ctx->print(fn->ctx, "%s:%d", fn->file, fn->line);
|
||||
} else {
|
||||
fn->ctx->print(fn->ctx, "%p", (void*)addr);
|
||||
fn->ctx->print(fn->ctx, "%p", (void*)fn->pc);
|
||||
}
|
||||
} else {
|
||||
fn->ctx->print(fn->ctx, "%p", (void*)addr);
|
||||
fn->ctx->print(fn->ctx, "%p", (void*)fn->pc);
|
||||
}
|
||||
|
||||
const char* addrname = dwfl_module_addrname(fn->ctx->module, addr);
|
||||
char* demangle_name = NULL;
|
||||
Dwfl_Module* module = dwfl_addrmodule(fn->ctx->dwfl, fn->pc);
|
||||
const char* addrname = dwfl_module_addrname(module, fn->pc);
|
||||
if(addrname) {
|
||||
demangle_name = cplus_demangle(addrname, 0);
|
||||
char* demangle_name = cplus_demangle(addrname, 0);
|
||||
char* function_name = NULL;
|
||||
if(asprintf(&function_name, "%s%s", demangle_name ? demangle_name : addrname, demangle_name ? "" : "()") == -1) {
|
||||
pst_log(SEVERITY_ERROR, "Failed to allocate memory");
|
||||
@@ -416,10 +413,10 @@ bool pst_function_unwind(pst_function* fn, Dwarf_Addr addr)
|
||||
}
|
||||
fn->name = pst_strdup(function_name);
|
||||
free(function_name);
|
||||
}
|
||||
|
||||
if(demangle_name) {
|
||||
free(demangle_name);
|
||||
if(demangle_name) {
|
||||
free(demangle_name);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -440,7 +437,7 @@ void pst_function_init(pst_function* fn, pst_context* _ctx, pst_function* _paren
|
||||
|
||||
fn->sp = 0;
|
||||
fn->cfa = 0;
|
||||
memcpy(&fn->cursor, _ctx->curr_frame, sizeof(fn->cursor));
|
||||
memcpy(&fn->cursor, &_ctx->cursor, sizeof(fn->cursor));
|
||||
fn->line = -1;
|
||||
fn->file = NULL;
|
||||
fn->parent = _parent;
|
||||
|
||||
@@ -45,7 +45,7 @@ void pst_function_init(pst_function* fn, pst_context* _ctx, pst_function* _paren
|
||||
pst_function* pst_function_new(pst_context* _ctx, pst_function* _parent);
|
||||
void pst_function_fini(pst_function* fn);
|
||||
|
||||
bool pst_function_unwind(pst_function* fn, Dwarf_Addr addr);
|
||||
bool pst_function_unwind(pst_function* fn);
|
||||
bool pst_function_handle_dwarf(pst_function * fn, Dwarf_Die* d);
|
||||
bool pst_function_print_dwarf(pst_function* fn);
|
||||
|
||||
|
||||
+31
-34
@@ -188,17 +188,17 @@ bool pst_handler_unwind(pst_handler* h)
|
||||
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_address = (void *) uctx->uc_mcontext.gregs[REG_EIP]);
|
||||
caller = (void *) uctx->uc_mcontext.gregs[REG_EIP]);
|
||||
#elif defined(__arm__)
|
||||
caller_address = (void *) uctx->uc_mcontext.arm_pc);
|
||||
caller = (void *) uctx->uc_mcontext.arm_pc);
|
||||
#elif defined(__aarch64__)
|
||||
caller_address = (void *) uctx->uc_mcontext.pc);
|
||||
caller = (void *) uctx->uc_mcontext.pc);
|
||||
#elif defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__)
|
||||
caller_address = (void *) uctx->uc_mcontext.regs->nip);
|
||||
caller = (void *) uctx->uc_mcontext.regs->nip);
|
||||
#elif defined(__s390x__)
|
||||
caller_address = (void *) uctx->uc_mcontext.psw.addr);
|
||||
caller = (void *) uctx->uc_mcontext.psw.addr);
|
||||
#elif defined(__APPLE__) && defined(__x86_64__)
|
||||
caller_address = (void *) uctx->uc_mcontext->__ss.__rip);
|
||||
caller = (void *) uctx->uc_mcontext->__ss.__rip);
|
||||
#else
|
||||
# error "unknown architecture!"
|
||||
#endif
|
||||
@@ -209,55 +209,52 @@ bool pst_handler_unwind(pst_handler* h)
|
||||
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);
|
||||
|
||||
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");
|
||||
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");
|
||||
return false;
|
||||
}
|
||||
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");
|
||||
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");
|
||||
dwfl_end(h->ctx.dwfl);
|
||||
h->ctx.dwfl = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
h->ctx.print(&h->ctx, "Stack trace: caller = %p\n", caller);
|
||||
|
||||
unw_getcontext(&h->ctx.context);
|
||||
unw_init_local(&h->ctx.cursor, &h->ctx.context);
|
||||
h->ctx.curr_frame = &h->ctx.cursor;
|
||||
|
||||
Dwarf_Addr addr; // address of currently processed function
|
||||
for(int i = 0, skip = 1; unw_step(h->ctx.curr_frame) > 0; ++i) {
|
||||
if(unw_get_reg(h->ctx.curr_frame, UNW_REG_IP, &addr)) {
|
||||
for(int i = 0, skip = 1; unw_step(&h->ctx.cursor) > 0; ++i) {
|
||||
Dwarf_Addr pc, sp;
|
||||
if(unw_get_reg(&h->ctx.cursor, UNW_REG_IP, &pc)) {
|
||||
pst_log(SEVERITY_DEBUG, "Failed to get IP value");
|
||||
continue;
|
||||
}
|
||||
unw_word_t sp;
|
||||
if(unw_get_reg(h->ctx.curr_frame, UNW_REG_SP, &sp)) {
|
||||
|
||||
if(unw_get_reg(&h->ctx.cursor, UNW_REG_SP, &sp)) {
|
||||
pst_log(SEVERITY_DEBUG, "Failed to get SP value");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(addr == (uint64_t)caller) {
|
||||
if(pc == (uint64_t)caller) {
|
||||
skip = 0;
|
||||
} else if(skip) {
|
||||
pst_log(SEVERITY_DEBUG, "Skipping frame #%d: PC = %#lX, SP = %#lX", i, addr, sp);
|
||||
pst_log(SEVERITY_DEBUG, "Skipping frame #%d: PC = %#lX, SP = %#lX", i, pc, sp);
|
||||
continue;
|
||||
}
|
||||
|
||||
h->ctx.print(&h->ctx, "[%-2d] ", i);
|
||||
h->ctx.module = dwfl_addrmodule(h->ctx.dwfl, addr);
|
||||
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);
|
||||
fn->sp = sp;
|
||||
pst_log(SEVERITY_DEBUG, "Analyze frame #%d: PC = %#lX, SP = %#lX", i, addr, sp);
|
||||
if(!pst_function_unwind(fn, addr)) {
|
||||
fn->pc = pc; fn->sp = sp;
|
||||
if(!pst_function_unwind(fn)) {
|
||||
del_function(fn);
|
||||
} else {
|
||||
if(last) {
|
||||
last->parent = fn;
|
||||
}
|
||||
//get_frame(fun);
|
||||
} else if(last) {
|
||||
last->parent = fn;
|
||||
}
|
||||
h->ctx.print(&h->ctx, "\n");
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ typedef union {
|
||||
} pst_sized_value;
|
||||
|
||||
typedef struct __pst_dwarf_value {
|
||||
list_node node; // uplink, !!! must be 1st field in structure !!!
|
||||
list_node node; // uplink
|
||||
|
||||
// fields
|
||||
pst_sized_value value; // value itself
|
||||
|
||||
Reference in New Issue
Block a user