haide frame storage from user and introduce separate method
pst_get_register() to obtain register value within function's stack frame
This commit is contained in:
+13
-1
@@ -11,6 +11,18 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <libunwind.h>
|
#include <libunwind.h>
|
||||||
|
|
||||||
|
/// @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 {
|
typedef struct {
|
||||||
char* name; ///< demangled name of the function. NULL if function name resolution failed
|
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
|
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 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 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_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;
|
} pst_function_info;
|
||||||
|
|
||||||
/// @brief bitmask of parameter's options
|
/// @brief bitmask of parameter's options
|
||||||
|
|||||||
@@ -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);
|
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
|
* @brief Get next parameter's handle in function
|
||||||
* @param function Function's handler obtained by pst_get_next_function()
|
* @param function Function's handler obtained by pst_get_next_function()
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ bool function_handle_dwarf(pst_function * fn, Dwarf_Die* d)
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
unw_proc_info_t info;
|
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);
|
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",
|
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.pc = 0;
|
||||||
fn->info.lowpc = 0;
|
fn->info.lowpc = 0;
|
||||||
fn->info.highpc = 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.name = NULL;
|
||||||
fn->info.line = -1;
|
fn->info.line = -1;
|
||||||
fn->info.file = NULL;
|
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);
|
list_head_init(&fn->params);
|
||||||
pst_call_site_storage_init(&fn->call_sites, _ctx);
|
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->parent = _parent;
|
||||||
fn->frame = NULL;
|
fn->frame = NULL;
|
||||||
fn->ctx = _ctx;
|
fn->ctx = _ctx;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ typedef struct pst_function {
|
|||||||
pst_function* parent; // parent function in call trace (caller)
|
pst_function* parent; // parent function in call trace (caller)
|
||||||
Dwarf_Frame* frame; // function's stack frame
|
Dwarf_Frame* frame; // function's stack frame
|
||||||
pst_context* ctx; // context of unwinding
|
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
|
bool allocated; // whether this object was allocated or not
|
||||||
} pst_function;
|
} pst_function;
|
||||||
void pst_function_init(pst_function* fn, pst_context* _ctx, pst_function* _parent);
|
void pst_function_init(pst_function* fn, pst_context* _ctx, pst_function* _parent);
|
||||||
|
|||||||
@@ -61,19 +61,16 @@ bool get_dwarf_function(pst_handler* h, pst_function* fun)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nret = false;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
int tag = dwarf_tag(&result);
|
int tag = dwarf_tag(&result);
|
||||||
if(tag == DW_TAG_subprogram || tag == DW_TAG_entry_point || tag == DW_TAG_inlined_subroutine) {
|
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))) {
|
if(!strcmp(fun->info.name, dwarf_diename(&result))) {
|
||||||
return function_handle_dwarf(fun, &result);
|
return function_handle_dwarf(fun, &result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while(dwarf_siblingof(&result, &result) == 0);
|
} while(dwarf_siblingof(&result, &result) == 0);
|
||||||
|
|
||||||
return nret;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static pst_function* add_function(pst_handler* h, pst_function* parent)
|
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
|
// setup context
|
||||||
h->ctx.module = dwfl_addrmodule(h->ctx.dwfl, fun->info.pc);
|
h->ctx.module = dwfl_addrmodule(h->ctx.dwfl, fun->info.pc);
|
||||||
h->ctx.base_addr = (uint64_t)info.dli_fbase;
|
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.sp = fun->info.sp;
|
||||||
h->ctx.cfa = fun->info.cfa;
|
h->ctx.cfa = fun->info.cfa;
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,11 @@ pst_function* pst_function_next(pst_handler* handler, pst_function* current)
|
|||||||
return pst_handler_next_function(handler, 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)
|
pst_parameter* pst_parameter_next(pst_function* function, pst_parameter* current)
|
||||||
{
|
{
|
||||||
return function_next_parameter(function, current);
|
return function_next_parameter(function, current);
|
||||||
|
|||||||
Reference in New Issue
Block a user