From d1441b3b6fbba41e8f22c48e45449620f40a8bd9 Mon Sep 17 00:00:00 2001 From: Nikolai Nosov Date: Sat, 2 May 2020 13:51:31 +0400 Subject: [PATCH] haide frame storage from user and introduce separate method pst_get_register() to obtain register value within function's stack frame --- include/libpst-types.h | 14 +++++++++++++- include/libpst.h | 9 +++++++++ src/dwarf/dwarf_function.c | 6 +++--- src/dwarf/dwarf_function.h | 1 + src/dwarf/dwarf_handler.c | 7 ++----- src/libpst.c | 5 +++++ 6 files changed, 33 insertions(+), 9 deletions(-) diff --git a/include/libpst-types.h b/include/libpst-types.h index fac5f82..4914847 100644 --- a/include/libpst-types.h +++ b/include/libpst-types.h @@ -11,6 +11,18 @@ #include #include +/// @brief bitmask of function's options +typedef enum { + FUNC_GLOBAL = 0x00000001, ///< function has global visibility + FUNC_LOCAL = 0x00000002, ///< function has local visibility + IS_MEMBER_OF = 0x00000004, ///< function is member of class + IS_INLINED = 0x00000008, ///< function was inlined + IS_PRIVATE = 0x00000010, ///< private member of class + IS_PROTECTED = 0x00000020, ///< protected member of class + IS_PUBLIC = 0x00000040, ///< public member of class +} pst_fun_flags; + + typedef struct { char* name; ///< demangled name of the function. NULL if function name resolution failed char* file; ///< file name where the function is defined. NULL if library failed to get file name @@ -20,7 +32,7 @@ typedef struct { unw_word_t highpc; ///< offset to the next address after the end of the function against base address unw_word_t sp; ///< SP register in function's frame unw_word_t cfa; ///< CFA (Canonical Frame Address) of the function. !!! Don't use CFA provided by libunwind, it's not valid !!! - unw_cursor_t context;///< Function's frame including register's values + pst_fun_flags flags; ///< flags of various function options } pst_function_info; /// @brief bitmask of parameter's options diff --git a/include/libpst.h b/include/libpst.h index 0f6b499..0518502 100644 --- a/include/libpst.h +++ b/include/libpst.h @@ -74,6 +74,15 @@ const pst_function* pst_function_next(pst_handler* handler, pst_function* curren */ const pst_function_info* pst_get_function_info(pst_function* function); +/** + * @brief Get value of CPU register in function's frame + * @param function function's handler obtained by pst_get_next_function() + * @param regno index of register + * @param val pointer to store register's value + * @return zero on success, UNW_EUNSPEC in case of unspecified error, UNW_EBADREG - register that is either invalid or not accessible in the current frame + */ +int pst_get_register(pst_function* function, int regno, unw_word_t* val); + /** * @brief Get next parameter's handle in function * @param function Function's handler obtained by pst_get_next_function() diff --git a/src/dwarf/dwarf_function.c b/src/dwarf/dwarf_function.c index dff65fe..0412404 100644 --- a/src/dwarf/dwarf_function.c +++ b/src/dwarf/dwarf_function.c @@ -271,7 +271,7 @@ bool function_handle_dwarf(pst_function * fn, Dwarf_Die* d) // } unw_proc_info_t info; - unw_get_proc_info(&fn->info.context, &info); + unw_get_proc_info(&fn->context, &info); fn->ctx->clean_print(fn->ctx); pst_log(SEVERITY_INFO, "Function %s(...): LOW_PC = %#lX, HIGH_PC = %#lX, offset from base address: 0x%lX, START_PC = 0x%lX, offset from start of function: 0x%lX", @@ -429,7 +429,7 @@ void pst_function_init(pst_function* fn, pst_context* _ctx, pst_function* _paren fn->info.pc = 0; fn->info.lowpc = 0; fn->info.highpc = 0; - bzero(&fn->info.context, sizeof(fn->info.context)); + bzero(&fn->context, sizeof(fn->context)); fn->info.name = NULL; fn->info.line = -1; fn->info.file = NULL; @@ -440,7 +440,7 @@ void pst_function_init(pst_function* fn, pst_context* _ctx, pst_function* _paren list_head_init(&fn->params); pst_call_site_storage_init(&fn->call_sites, _ctx); - memcpy(&fn->info.context, &_ctx->cursor, sizeof(fn->info.context)); + memcpy(&fn->context, &_ctx->cursor, sizeof(fn->context)); fn->parent = _parent; fn->frame = NULL; fn->ctx = _ctx; diff --git a/src/dwarf/dwarf_function.h b/src/dwarf/dwarf_function.h index a9d504c..473817c 100644 --- a/src/dwarf/dwarf_function.h +++ b/src/dwarf/dwarf_function.h @@ -30,6 +30,7 @@ typedef struct pst_function { pst_function* parent; // parent function in call trace (caller) Dwarf_Frame* frame; // function's stack frame pst_context* ctx; // context of unwinding + unw_cursor_t context; ///< Function's frame including register's values bool allocated; // whether this object was allocated or not } pst_function; void pst_function_init(pst_function* fn, pst_context* _ctx, pst_function* _parent); diff --git a/src/dwarf/dwarf_handler.c b/src/dwarf/dwarf_handler.c index 54b3308..5facd55 100644 --- a/src/dwarf/dwarf_handler.c +++ b/src/dwarf/dwarf_handler.c @@ -61,19 +61,16 @@ bool get_dwarf_function(pst_handler* h, pst_function* fun) return false; } - bool nret = false; - do { int tag = dwarf_tag(&result); if(tag == DW_TAG_subprogram || tag == DW_TAG_entry_point || tag == DW_TAG_inlined_subroutine) { - //ctx.log(SEVERITY_DEBUG, "function die name %s", dwarf_diename(&result)); if(!strcmp(fun->info.name, dwarf_diename(&result))) { return function_handle_dwarf(fun, &result); } } } while(dwarf_siblingof(&result, &result) == 0); - return nret; + return false; } static pst_function* add_function(pst_handler* h, pst_function* parent) @@ -152,7 +149,7 @@ bool pst_handler_handle_dwarf(pst_handler* h) // setup context h->ctx.module = dwfl_addrmodule(h->ctx.dwfl, fun->info.pc); h->ctx.base_addr = (uint64_t)info.dli_fbase; - h->ctx.curr_frame = &fun->info.context; + h->ctx.curr_frame = &fun->context; h->ctx.sp = fun->info.sp; h->ctx.cfa = fun->info.cfa; diff --git a/src/libpst.c b/src/libpst.c index 7747c40..ef4e392 100644 --- a/src/libpst.c +++ b/src/libpst.c @@ -68,6 +68,11 @@ pst_function* pst_function_next(pst_handler* handler, pst_function* current) return pst_handler_next_function(handler, current); } +int pst_get_register(pst_function* fn, int regno, unw_word_t* val) +{ + return unw_get_reg(&fn->context, regno, val); +} + pst_parameter* pst_parameter_next(pst_function* function, pst_parameter* current) { return function_next_parameter(function, current);