From 5b4d7d034989b6ce537987fa45b293b1e065c626 Mon Sep 17 00:00:00 2001 From: Nikolai Nosov Date: Sat, 7 Mar 2020 10:15:56 +0400 Subject: [PATCH] refactor of function unwinding --- src/dwarf/dwarf_function.c | 39 +++++++++++------------ src/dwarf/dwarf_function.h | 2 +- src/dwarf/dwarf_handler.c | 65 ++++++++++++++++++-------------------- src/dwarf/dwarf_stack.h | 2 +- 4 files changed, 51 insertions(+), 57 deletions(-) diff --git a/src/dwarf/dwarf_function.c b/src/dwarf/dwarf_function.c index 043d474..d077b51 100644 --- a/src/dwarf/dwarf_function.c +++ b/src/dwarf/dwarf_function.c @@ -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; diff --git a/src/dwarf/dwarf_function.h b/src/dwarf/dwarf_function.h index 0b31ad2..98b60cd 100644 --- a/src/dwarf/dwarf_function.h +++ b/src/dwarf/dwarf_function.h @@ -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); diff --git a/src/dwarf/dwarf_handler.c b/src/dwarf/dwarf_handler.c index 12887d6..ed01dac 100644 --- a/src/dwarf/dwarf_handler.c +++ b/src/dwarf/dwarf_handler.c @@ -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"); } diff --git a/src/dwarf/dwarf_stack.h b/src/dwarf/dwarf_stack.h index 566b4b6..e0c996c 100644 --- a/src/dwarf/dwarf_stack.h +++ b/src/dwarf/dwarf_stack.h @@ -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