refactor of function unwinding

This commit is contained in:
2020-03-07 10:15:56 +04:00
parent 09f6432061
commit 5b4d7d0349
4 changed files with 51 additions and 57 deletions
+18 -21
View File
@@ -375,34 +375,31 @@ bool pst_function_handle_dwarf(pst_function * fn, Dwarf_Die* d)
return true; 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, fn->pc);
Dwfl_Line *dwline = dwfl_getsrc(fn->ctx->dwfl, addr);
if(dwline != NULL) { if(dwline != NULL) {
Dwarf_Addr addr; const char* filename = dwfl_lineinfo (dwline, &fn->pc, &fn->line, NULL, NULL, NULL);
const char* filename = dwfl_lineinfo (dwline, &addr, &fn->line, NULL, NULL, NULL);
if(filename) { if(filename) {
const char* str = strrchr(filename, '/'); const char* file = strrchr(filename, '/');
if(str && *str != 0) { if(file && *file != 0) {
str++; file++;
} else { } else {
str = filename; file = filename;
} }
fn->file = pst_strdup(str); fn->file = pst_strdup(file);
fn->ctx->print(fn->ctx, "%s:%d", str, fn->line); fn->ctx->print(fn->ctx, "%s:%d", fn->file, fn->line);
} else { } else {
fn->ctx->print(fn->ctx, "%p", (void*)addr); fn->ctx->print(fn->ctx, "%p", (void*)fn->pc);
} }
} else { } 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); Dwfl_Module* module = dwfl_addrmodule(fn->ctx->dwfl, fn->pc);
char* demangle_name = NULL; const char* addrname = dwfl_module_addrname(module, fn->pc);
if(addrname) { if(addrname) {
demangle_name = cplus_demangle(addrname, 0); char* demangle_name = cplus_demangle(addrname, 0);
char* function_name = NULL; char* function_name = NULL;
if(asprintf(&function_name, "%s%s", demangle_name ? demangle_name : addrname, demangle_name ? "" : "()") == -1) { if(asprintf(&function_name, "%s%s", demangle_name ? demangle_name : addrname, demangle_name ? "" : "()") == -1) {
pst_log(SEVERITY_ERROR, "Failed to allocate memory"); 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); fn->name = pst_strdup(function_name);
free(function_name); free(function_name);
}
if(demangle_name) { if(demangle_name) {
free(demangle_name); free(demangle_name);
}
} }
return true; return true;
@@ -440,7 +437,7 @@ void pst_function_init(pst_function* fn, pst_context* _ctx, pst_function* _paren
fn->sp = 0; fn->sp = 0;
fn->cfa = 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->line = -1;
fn->file = NULL; fn->file = NULL;
fn->parent = _parent; fn->parent = _parent;
+1 -1
View File
@@ -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); pst_function* pst_function_new(pst_context* _ctx, pst_function* _parent);
void pst_function_fini(pst_function* fn); 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_handle_dwarf(pst_function * fn, Dwarf_Die* d);
bool pst_function_print_dwarf(pst_function* fn); bool pst_function_print_dwarf(pst_function* fn);
+31 -34
View File
@@ -188,17 +188,17 @@ bool pst_handler_unwind(pst_handler* h)
h->ctx.sp = h->ctx.hcontext->uc_mcontext.gregs[REG_RSP]; h->ctx.sp = h->ctx.hcontext->uc_mcontext.gregs[REG_RSP];
pst_log(SEVERITY_DEBUG, "Original caller's SP: %#lX", h->ctx.sp); pst_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 = (void *) uctx->uc_mcontext.gregs[REG_EIP]);
#elif defined(__arm__) #elif defined(__arm__)
caller_address = (void *) uctx->uc_mcontext.arm_pc); caller = (void *) uctx->uc_mcontext.arm_pc);
#elif defined(__aarch64__) #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__) #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__) #elif defined(__s390x__)
caller_address = (void *) uctx->uc_mcontext.psw.addr); caller = (void *) uctx->uc_mcontext.psw.addr);
#elif defined(__APPLE__) && defined(__x86_64__) #elif defined(__APPLE__) && defined(__x86_64__)
caller_address = (void *) uctx->uc_mcontext->__ss.__rip); caller = (void *) uctx->uc_mcontext->__ss.__rip);
#else #else
# error "unknown architecture!" # error "unknown architecture!"
#endif #endif
@@ -209,55 +209,52 @@ bool pst_handler_unwind(pst_handler* h)
h->ctx.base_addr = (uint64_t)info.dli_fbase; 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); 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) {
if(h->ctx.dwfl == NULL) { h->ctx.dwfl = dwfl_begin(&callbacks);
h->ctx.print(&h->ctx, "Failed to initialize libdw session for parse stack frames"); if(h->ctx.dwfl == NULL) {
return false; 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(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); h->ctx.print(&h->ctx, "Stack trace: caller = %p\n", caller);
unw_getcontext(&h->ctx.context); unw_getcontext(&h->ctx.context);
unw_init_local(&h->ctx.cursor, &h->ctx.context); unw_init_local(&h->ctx.cursor, &h->ctx.context);
h->ctx.curr_frame = &h->ctx.cursor; for(int i = 0, skip = 1; unw_step(&h->ctx.cursor) > 0; ++i) {
Dwarf_Addr pc, sp;
Dwarf_Addr addr; // address of currently processed function if(unw_get_reg(&h->ctx.cursor, UNW_REG_IP, &pc)) {
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)) {
pst_log(SEVERITY_DEBUG, "Failed to get IP value"); pst_log(SEVERITY_DEBUG, "Failed to get IP value");
continue; 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"); pst_log(SEVERITY_DEBUG, "Failed to get SP value");
continue; continue;
} }
if(addr == (uint64_t)caller) { if(pc == (uint64_t)caller) {
skip = 0; skip = 0;
} else if(skip) { } 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; continue;
} }
h->ctx.print(&h->ctx, "[%-2d] ", i); 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* last = last_function(h);
pst_function* fn = add_function(h, NULL); pst_function* fn = add_function(h, NULL);
fn->sp = sp; fn->pc = pc; fn->sp = sp;
pst_log(SEVERITY_DEBUG, "Analyze frame #%d: PC = %#lX, SP = %#lX", i, addr, sp); if(!pst_function_unwind(fn)) {
if(!pst_function_unwind(fn, addr)) {
del_function(fn); del_function(fn);
} else { } else if(last) {
if(last) { last->parent = fn;
last->parent = fn;
}
//get_frame(fun);
} }
h->ctx.print(&h->ctx, "\n"); h->ctx.print(&h->ctx, "\n");
} }
+1 -1
View File
@@ -59,7 +59,7 @@ typedef union {
} pst_sized_value; } pst_sized_value;
typedef struct __pst_dwarf_value { typedef struct __pst_dwarf_value {
list_node node; // uplink, !!! must be 1st field in structure !!! list_node node; // uplink
// fields // fields
pst_sized_value value; // value itself pst_sized_value value; // value itself