From ba9db80f07be80dd9ee2de870d4aa62f5a7bfe72 Mon Sep 17 00:00:00 2001 From: Nikolai Nosov Date: Thu, 16 Jan 2020 16:22:17 +0400 Subject: [PATCH] introduce parent frame --- framework/common.cpp | 8 ++++---- framework/common.h | 5 ++++- framework/dwarf_operations.cpp | 12 +++++------- framework/sysutils.cpp | 22 +++++++++++++++------- framework/sysutils.h | 2 +- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/framework/common.cpp b/framework/common.cpp index 4672d80..549bd32 100644 --- a/framework/common.cpp +++ b/framework/common.cpp @@ -121,14 +121,14 @@ uint32_t __pst_context::print_expr_block (Dwarf_Op *exprs, int len, char* buff, int32_t off = decode_sleb128((unsigned char*)&exprs[i].number); int regno = map->op_num - DW_OP_breg0; unw_word_t ptr = 0; - unw_get_reg(&cursor, regno, &ptr); + unw_get_reg(&curr_frame, regno, &ptr); //ptr += off; offset += snprintf(buff + offset, buff_size - offset, "%s(*%s%s%d) reg_value: 0x%lX", map->op_name, unw_regname(regno), off >=0 ? "+" : "", off, ptr); } else if(map->op_num >= DW_OP_reg0 && map->op_num <= DW_OP_reg16) { unw_word_t value = 0; int regno = map->op_num - DW_OP_reg0; - unw_get_reg(&cursor, regno, &value); + unw_get_reg(&curr_frame, regno, &value); offset += snprintf(buff + offset, buff_size - offset, "%s(*%s) value: 0x%lX", map->op_name, unw_regname(regno), value); } else if(map->op_num == DW_OP_GNU_entry_value) { uint32_t value = decode_uleb128((unsigned char*)&exprs[i].number); @@ -155,14 +155,14 @@ uint32_t __pst_context::print_expr_block (Dwarf_Op *exprs, int len, char* buff, uint32_t regno = decode_uleb128((unsigned char*)&exprs[i].number); int32_t off = decode_sleb128((unsigned char*)&exprs[i].number2); unw_word_t ptr = 0; - unw_get_reg(&cursor, regno, &ptr); + unw_get_reg(&curr_frame, regno, &ptr); //ptr += off; offset += snprintf(buff + offset, buff_size - offset, "%s(%s%s%d) reg_value = 0x%lX", map->op_name, unw_regname(regno), off >= 0 ? "+" : "", off, ptr); } else if(map->op_num == DW_OP_regx) { int32_t reg = decode_sleb128((unsigned char*)&exprs[i].number); unw_word_t value = 0; - unw_get_reg(&cursor, reg, &value); + unw_get_reg(&curr_frame, reg, &value); offset += snprintf(buff + offset, buff_size - offset, "%s(%s) value = 0x%lX", map->op_name, unw_regname(reg), value); } else if(map->op_num == DW_OP_addr) { diff --git a/framework/common.h b/framework/common.h index 2ae48a5..808d0d4 100644 --- a/framework/common.h +++ b/framework/common.h @@ -14,6 +14,7 @@ typedef struct __pst_context { offset = 0; buff[0] = 0; base_addr = 0; + has_nframe = false; } bool print(const char* fmt, ...); @@ -22,7 +23,9 @@ typedef struct __pst_context { ucontext_t* hcontext; // context of signal handler unw_context_t context; // context of stack trace - unw_cursor_t cursor; // currently examined frame of context + unw_cursor_t curr_frame; // currently examined frame of context + unw_cursor_t next_frame; // caller frame + bool has_nframe; // has next frame or not Dwarf_Addr base_addr; // base address where process loaded char buff[8192]; // stack trace buffer diff --git a/framework/dwarf_operations.cpp b/framework/dwarf_operations.cpp index 7d0d54d..1099807 100644 --- a/framework/dwarf_operations.cpp +++ b/framework/dwarf_operations.cpp @@ -785,7 +785,7 @@ bool dw_op_breg_x(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, D } unw_word_t val = 0; - if(unw_get_reg(&stack->ctx->cursor, regno, &val)) { + if(unw_get_reg(&stack->ctx->curr_frame, regno, &val)) { return false; } @@ -829,7 +829,7 @@ bool dw_op_call_frame_cfa(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Wor { // since in signal handler we are know SP value, just push it to DWARF stack unw_word_t sp; - if(unw_get_reg(&stack->ctx->cursor, UNW_REG_SP, &sp)) { + if(unw_get_reg(&stack->ctx->curr_frame, UNW_REG_SP, &sp)) { return false; } @@ -844,7 +844,7 @@ bool dw_op_fbreg(dwarf_stack* stack, const dwarf_op_map* map, Dwarf_Word op1, Dw { // since in signal handler we are know SP value, just use it as DW_AT_frame_base unw_word_t sp; - if(unw_get_reg(&stack->ctx->cursor, UNW_REG_SP, &sp)) { + if(unw_get_reg(&stack->ctx->curr_frame, UNW_REG_SP, &sp)) { return false; } @@ -1067,7 +1067,7 @@ bool __dwarf_stack::get_value(uint64_t& value) if(v->type & DWARF_TYPE_REGISTER_LOC) { // dereference register location uint64_t regno = value; - if(unw_get_reg(&ctx->cursor, regno, &value)) { + if(unw_get_reg(&ctx->curr_frame, regno, &value)) { ctx->log(SEVERITY_ERROR, "Failed to get value of register 0x%lX", regno); return false; } @@ -1091,7 +1091,7 @@ bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu if(v && (v->type & DWARF_TYPE_REGISTER_LOC)) { unw_word_t value = 0; uint64_t regno = *((uint64_t*)v->value); - if(unw_get_reg(&ctx->cursor, regno, &value)) { + if(unw_get_reg(&ctx->curr_frame, regno, &value)) { ctx->log(SEVERITY_ERROR, "Failed to ger value of register 0x%lX", regno); return false; } @@ -1107,8 +1107,6 @@ bool __dwarf_stack::calc_expression(Dwarf_Op *exprs, int expr_len, Dwarf_Attribu Dwarf_Op *expr; size_t exprlen; if (dwarf_getlocation(&attr_mem, &expr, &exprlen) == 0) { - //offset += print_expr_block (expr, exprlen, buff + offset, buff_size - offset, &attr_mem); - //offset += snprintf(buff + offset, buff_size - offset, ") "); if(!calc_expression(expr, exprlen, &attr_mem)) { ctx->log(SEVERITY_ERROR, "Failed to calculate sub-expression for operation %s(0x%lX, 0x%lX)", map->op_name, exprs[i].number, exprs[i].number2); return false; diff --git a/framework/sysutils.cpp b/framework/sysutils.cpp index 9d39bec..9604806 100644 --- a/framework/sysutils.cpp +++ b/framework/sysutils.cpp @@ -301,7 +301,7 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result) // determine location of parameter in stack/heap or CPU registers attr = dwarf_attr(result, DW_AT_location, &attr_mem); Dwarf_Addr pc; - unw_get_reg(&ctx->cursor, UNW_REG_IP, &pc); + unw_get_reg(&ctx->curr_frame, UNW_REG_IP, &pc); dwarf_stack stack(ctx); char str[1024]; @@ -453,7 +453,7 @@ bool __pst_function::print_dwarf() bool __pst_function::handle_dwarf(Dwarf_Die* d) { die = d; - ctx->cursor = cursor; + ctx->curr_frame = cursor; Dwarf_Attribute attr_mem; Dwarf_Attribute* attr; @@ -792,6 +792,13 @@ pst_function* __pst_handler::next_function(pst_function* f) bool __pst_handler::handle_dwarf() { for(pst_function* fun = next_function(NULL); fun; fun = next_function(fun)) { + ctx.curr_frame = fun->cursor; + if(fun->parent) { + ctx.next_frame = fun->parent->cursor; + ctx.has_nframe = true; + } else { + ctx.has_nframe = false; + } get_dwarf_function(fun); } @@ -858,9 +865,9 @@ bool __pst_handler::unwind() unw_word_t pc; unw_getcontext(&ctx.context); - unw_init_local(&ctx.cursor, &ctx.context); - while (unw_step(&ctx.cursor) > 0) { - unw_get_reg(&ctx.cursor, UNW_REG_IP, &pc); + unw_init_local(&ctx.curr_frame, &ctx.context); + while (unw_step(&ctx.curr_frame) > 0) { + unw_get_reg(&ctx.curr_frame, UNW_REG_IP, &pc); if(pc == (uint64_t)caller) { break; } else { @@ -887,8 +894,9 @@ bool __pst_handler::unwind() ctx.print("[%-2d] ", idx); Dwarf_Addr addr = (uintptr_t)array[i]; #else + ctx.has_nframe = false; for (int i = skipped, idx = 0; true ; ++i, ++idx) { - unw_get_reg(&ctx.cursor, UNW_REG_IP, &pc); + unw_get_reg(&ctx.curr_frame, UNW_REG_IP, &pc); addr = pc; ctx.print("[%-2d] ", idx); #endif @@ -900,7 +908,7 @@ bool __pst_handler::unwind() } ctx.print("\n"); #ifdef USE_LIBUNWIND - if(unw_step(&ctx.cursor) <= 0) { + if(unw_step(&ctx.curr_frame) <= 0) { break; } #endif diff --git a/framework/sysutils.h b/framework/sysutils.h index 4167664..d95b267 100644 --- a/framework/sysutils.h +++ b/framework/sysutils.h @@ -88,7 +88,7 @@ typedef struct __pst_function : public SC_ListNode { lowpc = 0; highpc = 0; parent = NULL; - cursor = _ctx->cursor; + cursor = _ctx->curr_frame; parent = _parent; }