/* * sysutils.h * * Created on: Dec 28, 2019 * Author: nnosov */ #ifndef SC_SYSUTILS_H_ #define SC_SYSUTILS_H_ //system #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "dictionary.h" #include "dwarf_operations.h" typedef struct __pst_function pst_function; typedef struct __pst_type : public SC_ListNode { __pst_type(const char* n, uint32_t t) : type(t) { if(n) { name = n; } } std::string name; // type name uint32_t type; // DW_AT_XXX type } pst_type; typedef struct __pst_parameter : public SC_ListNode { __pst_parameter(pst_context* c) : ctx(c) { die = NULL; size = 0; type = 0; enc_type = 0; is_return = false; is_variable = false; has_value = false; value = 0; line = 0; } ~__pst_parameter() { clear(); } void clear(); pst_type* add_type(const char* name, int type); pst_type* next_type(pst_type* t); bool handle_dwarf(Dwarf_Die* d); bool handle_type(Dwarf_Attribute* param); bool print_dwarf(); Dwarf_Die* die; // DWARF DIE containing parameter's definition std::string name; // parameter's name uint32_t line; // line of parameter definition Dwarf_Word size; // size of parameter in bytes int type; // type of parameter in DW_TAG_XXX types enumeration Dwarf_Word enc_type; // if 'type' is DW_TAG_Base_type, then 'base_type' holds DW_AT_ATE_XXX base type encoding type SC_ListHead types; // list of parameter's definitions i.e. 'typedef', 'uint32_t' bool is_return; // whether this parameter is return value of the function bool is_variable;// whether this parameter is function variable or argument of function bool has_value; // whether we got value of parameter or not uint64_t value; // value of parameter pst_context* ctx; } pst_parameter; // DW_TAG_call_site_parameter typedef struct __pst_call_site_param : public SC_ListNode { __pst_call_site_param(pst_context* ctx) : location(ctx) { param = NULL; name = NULL; value = 0; } ~__pst_call_site_param() { if(name) { free(name); name = NULL; } } Dwarf_Die* param; // reference to parameter DIE in callee (DW_AT_call_parameter) char* name; // name of parameter if present (DW_AT_name) dwarf_stack location; // DWARF stack containing location expression uint64_t value; // parameter's value } pst_call_site_param; // DW_TAG_call_site typedef struct __pst_call_site : public SC_ListNode { __pst_call_site(pst_context* c, uint64_t tgt, const char* orn) { target = tgt; if(orn) { origin = strdup(orn); } else { origin = NULL; } die = NULL; ctx = c; } ~__pst_call_site() { if(origin) { free(origin); origin = NULL; } } pst_call_site_param* add_param(); void del_param(pst_call_site_param* p); pst_call_site_param* next_param(pst_call_site_param* p); bool handle_dwarf(Dwarf_Die* die); uint64_t target; // pointer to callee function's (it's Low PC + base address) char* origin; // name of callee function Dwarf_Die* die; // DIE of function for which this call site has parameters SC_ListHead params; // list of parameters and their values pst_context* ctx; } pst_call_site; typedef struct __pst_handler pst_handler; typedef struct __pst_function : public SC_ListNode { __pst_function(pst_context* _ctx, __pst_function* _parent) : ctx(_ctx) { pc = 0; line = -1; die = NULL; lowpc = 0; highpc = 0; memcpy(&cursor, _ctx->curr_frame, sizeof(cursor)); parent = _parent; sp = 0; cfa = 0; } ~__pst_function() { clear(); } void clear(); pst_parameter* add_param(); void del_param(pst_parameter* p); pst_parameter* next_param(pst_parameter* p); pst_call_site* add_call_site(uint64_t target, const char* origin); void del_call_site(pst_call_site* st); pst_call_site* next_call_site(pst_call_site* st); pst_call_site* call_site_by_origin(const char* origin); pst_call_site* call_site_by_target(uint64_t target); bool unwind(Dwfl* dwfl, Dwfl_Module* module, Dwarf_Addr addr); bool handle_dwarf(Dwarf_Die* d); bool print_dwarf(); bool handle_lexical_block(Dwarf_Die* result); bool handle_call_site(Dwarf_Die* result); Dwarf_Addr lowpc; // offset to start of the function against base address Dwarf_Addr highpc; // offset to the next address after the end of the function against base address Dwarf_Die* die; // DWARF DIE containing definition of the function std::string name; // function's name SC_ListHead params; // function's parameters // call-site SC_ListHead call_sites; // Call-Site definitions SC_Dict mCallStToTarget; // map pointer to caller to call-site SC_Dict mCallStToOrigin; // map caller name to call-site unw_word_t pc; // address between lowpc & highpc (plus base address offset). actually, currently executed command unw_word_t sp; // SP register in function's frame unw_word_t cfa; // CFA (Canonical Frame Adress) of the function unw_cursor_t cursor; // copy of stack state of the function int line; // line in code where function is defined std::string file; // file name (DWARF Compilation Unit) where function is defined pst_function* parent; // parent function in call trace (caller) pst_context* ctx; // context of unwinding } pst_function; typedef struct __pst_handler { __pst_handler(ucontext_t* hctx) : ctx(hctx) { caller = NULL; module = NULL; dwfl = NULL; frame = NULL; addr = 0; handle = 0; } ~__pst_handler() { if(handle) { dlclose(handle); } clear(); } void clear(); pst_function* add_function(__pst_function* fun); void del_function(pst_function* f); pst_function* next_function(pst_function* f); pst_function* last_function(); bool handle_dwarf(); void print_dwarf(); bool unwind(); bool get_frame(pst_function* fun); bool get_dwarf_function(pst_function* fun); pst_context ctx; // context of unwinding void* handle; // process handle Dwarf_Addr addr; // address of currently processed function Dwfl* dwfl; // DWARF context Dwfl_Module* module; // currently processed CU Dwarf_Frame* frame; // currently processed stack frame void* caller; // pointer to the function which requested to unwind stack SC_ListHead functions; // list of functions in stack frame } pst_handler; #endif /* SC_SYSUTILS_H_ */