extend to user types of parameter and initialize them. introduce
'typename' to parameter_info, it's C/C++ name of parameter type. rewrite parameter printing using new capabilities.
This commit is contained in:
+35
-10
@@ -11,24 +11,49 @@
|
||||
#include <stdint.h>
|
||||
#include <libunwind.h>
|
||||
|
||||
typedef struct pst_function_info {
|
||||
char* name; ///< demangled name of the function
|
||||
char* file; ///< file name where the function is defined
|
||||
int line; ///< line of definition of the function
|
||||
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
|
||||
int line; ///< line of definition of the function. -1 if library failed to get file line
|
||||
unw_word_t pc; ///< address between LowPC & HighPC (plus base address offset). actually, address of currently executed command in function
|
||||
} pst_function_info;
|
||||
|
||||
/// @brief bitmask of parameter options
|
||||
typedef enum {
|
||||
PARAM_RETURN = 1, ///< parameter is return value of a function
|
||||
PARAM_VARIABLE = 2, ///< parameter is variable inside of a function
|
||||
PARAM_HAS_VALUE = 4 ///< parameter has a valid value (if not set, then value is undefined)
|
||||
// scope & access
|
||||
PARAM_CONST = 0x00000001, ///< constant access
|
||||
PARAM_GLOBAL = 0x00000002, ///< global scope
|
||||
PARAM_STATIC = 0x00000004, ///< parameter defined as static
|
||||
PARAM_RETURN = 0x00000008, ///< parameter is return value of a function
|
||||
PARAM_VARIABLE = 0x00000010, ///< parameter is variable inside of a function
|
||||
// validity
|
||||
PARAM_HAS_VALUE = 0x00000020, ///< parameter has a valid value (if not set, then value is undefined)
|
||||
PARAM_INVALID = 0x00000040, ///< library failed to dereference pointer
|
||||
// base types
|
||||
PARAM_TYPE_POINTER = 0x00000080, ///< pointer
|
||||
PARAM_TYPE_INT = 0x00000100, ///< integer. to determine size of value, use 'size' field of parameter
|
||||
PARAM_TYPE_UINT = 0x00000200, ///< unsigned integer. to determine size of value, use 'size' field of parameter
|
||||
PARAM_TYPE_FLOAT = 0x00000400, ///< float
|
||||
PARAM_TYPE_BOOL = 0x00000800, ///< boolean
|
||||
PARAM_TYPE_VOID = 0x00001000, ///< void
|
||||
PARAM_TYPE_CHAR = 0x00002000, ///< character
|
||||
PARAM_TYPE_UCHAR = 0x00004000, ///< unsigned character
|
||||
PARAM_TYPE_REF = 0x00008000, ///< reference
|
||||
// complex types
|
||||
PARAM_TYPE_ARRAY = 0x00010000, ///< array
|
||||
PARAM_TYPE_STRUCT = 0x00020000, ///< structure
|
||||
PARAM_TYPE_UNION = 0x00040000, ///< union
|
||||
PARAM_TYPE_ENUM = 0x00080000, ///< enumeration
|
||||
PARAM_TYPE_CLASS = 0x00100000, ///< class
|
||||
PARAM_TYPE_TYPEDEF = 0x00200000, ///< type definition
|
||||
} pst_param_flags;
|
||||
|
||||
typedef struct pst_parameter_info {
|
||||
typedef struct {
|
||||
char* name; ///< parameter's name
|
||||
char* type_name; ///< name of parameter's type in case of 'PARAM_TYPE_TYPEDEF'
|
||||
uint32_t line; ///< line of parameter definition
|
||||
unw_word_t size; ///< size of parameter in bytes
|
||||
unw_word_t value; ///< value of parameter. currently only base types supported. use 'size' to determine number of actual bytes of value
|
||||
unw_word_t size; ///< size of parameter in bits
|
||||
unw_word_t value; ///< value of parameter. use 'size' to determine number of actual bits of 'value'
|
||||
pst_param_flags flags; ///< flags of various parameter's options
|
||||
} pst_parameter_info;
|
||||
|
||||
|
||||
+87
-41
@@ -16,15 +16,19 @@
|
||||
//
|
||||
// pst_type
|
||||
//
|
||||
void pst_type_init(pst_type* t, const char* name, uint32_t type)
|
||||
void pst_type_init(pst_type* t, const char* name, pst_param_flags type)
|
||||
{
|
||||
list_node_init(&t->node);
|
||||
t->name = pst_strdup(name);
|
||||
if(name) {
|
||||
t->name = pst_strdup(name);
|
||||
} else {
|
||||
t->name = NULL;
|
||||
}
|
||||
t->type = type;
|
||||
t->allocated = false;
|
||||
}
|
||||
|
||||
pst_type* pst_type_new(const char* name, uint32_t type)
|
||||
pst_type* pst_type_new(const char* name, pst_param_flags type)
|
||||
{
|
||||
pst_type* nt = pst_alloc(pst_type);
|
||||
if(nt) {
|
||||
@@ -37,7 +41,9 @@ pst_type* pst_type_new(const char* name, uint32_t type)
|
||||
|
||||
void pst_type_fini(pst_type* t)
|
||||
{
|
||||
pst_free(t->name);
|
||||
if(t->name) {
|
||||
pst_free(t->name);
|
||||
}
|
||||
if(t->allocated) {
|
||||
pst_free(t);
|
||||
}
|
||||
@@ -54,6 +60,14 @@ static void clear(pst_parameter* param)
|
||||
list_del(&t->node);
|
||||
pst_type_fini(t);
|
||||
}
|
||||
|
||||
if(param->info.name) {
|
||||
pst_free(param->info.name);
|
||||
}
|
||||
|
||||
if(param->info.type_name) {
|
||||
pst_free(param->info.type_name);
|
||||
}
|
||||
}
|
||||
|
||||
static pst_type* next_type(pst_parameter* param, pst_type* t)
|
||||
@@ -69,30 +83,30 @@ static pst_type* next_type(pst_parameter* param, pst_type* t)
|
||||
|
||||
bool pst_parameter_print_dwarf(pst_parameter* param)
|
||||
{
|
||||
if(list_count(¶m->types)) {
|
||||
if(param->info.flags & PARAM_RETURN) {
|
||||
param->ctx->print(param->ctx, "%s", next_type(param, NULL)->name);
|
||||
} else {
|
||||
if(param->info.flags & PARAM_HAS_VALUE) {
|
||||
param->ctx->print(param->ctx, "%s %s = 0x%lX", next_type(param, NULL)->name, param->info.name, param->info.value);
|
||||
} else {
|
||||
param->ctx->print(param->ctx, "%s %s = <undefined>", next_type(param, NULL)->name, param->info.name);
|
||||
}
|
||||
}
|
||||
if(param->info.flags & PARAM_RETURN) {
|
||||
param->ctx->print(param->ctx, "%s", param->info.type_name);
|
||||
} else {
|
||||
if(param->info.flags & PARAM_HAS_VALUE) {
|
||||
param->ctx->print(param->ctx, "%s = 0x%lX", param->info.name, param->info.value);
|
||||
param->ctx->print(param->ctx, "%s%s %s = 0x%lX",
|
||||
param->info.type_name ? param->info.type_name : "void"/*hack to represent void since DWARF has no ability to determine it another way*/,
|
||||
param->info.flags & PARAM_TYPE_POINTER ? "*" : "", param->info.name, param->info.value);
|
||||
} else {
|
||||
param->ctx->print(param->ctx, "%s = <undefined>", param->info.name);
|
||||
param->ctx->print(param->ctx, "%s%s %s = <undefined>",
|
||||
param->info.type_name ? param->info.type_name : "void"/*hack to represent void since DWARF has no ability to determine it another way*/,
|
||||
param->info.flags & PARAM_TYPE_POINTER ? "*" : "", param->info.name);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
pst_type* pst_parameter_add_type(pst_parameter* param, const char* name, int type)
|
||||
pst_type* pst_parameter_add_type(pst_parameter* param, const char* name, pst_param_flags type)
|
||||
{
|
||||
pst_new(pst_type, t, name, type);
|
||||
list_add_bottom(¶m->types, &t->node);
|
||||
param->info.flags |= type;
|
||||
if(name && !param->info.type_name) {
|
||||
param->info.type_name = pst_strdup(name);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
@@ -110,10 +124,10 @@ bool pst_parameter_handle_type(pst_parameter* param, Dwarf_Attribute* base)
|
||||
return false;
|
||||
}
|
||||
|
||||
param->info.size = 64;
|
||||
switch (dwarf_tag(&ret_die)) {
|
||||
case DW_TAG_base_type: {
|
||||
// get Size attribute and it's value
|
||||
param->info.size = 0;
|
||||
attr = dwarf_attr(&ret_die, DW_AT_byte_size, &attr_mem);
|
||||
if(attr) {
|
||||
dwarf_formudata(attr, ¶m->info.size);
|
||||
@@ -126,44 +140,75 @@ bool pst_parameter_handle_type(pst_parameter* param, Dwarf_Attribute* base)
|
||||
if(attr) {
|
||||
param->enc_type = 0;
|
||||
dwarf_formudata(attr, ¶m->enc_type);
|
||||
static const char* sizemod[] = {"", "char", "short", "", "int", "", "", "", "long long"};
|
||||
char name[32]; name[0] = 0;
|
||||
switch (param->enc_type) {
|
||||
case DW_ATE_boolean:
|
||||
pst_parameter_add_type(param, "bool", PARAM_TYPE_BOOL);
|
||||
break;
|
||||
case DW_ATE_address:
|
||||
pst_parameter_add_type(param, NULL, PARAM_TYPE_POINTER);
|
||||
break;
|
||||
case DW_ATE_signed:
|
||||
snprintf(name, sizeof(name), "signed %s", sizemod[param->info.size & 0x0F]);
|
||||
pst_parameter_add_type(param, name, PARAM_TYPE_INT);
|
||||
break;
|
||||
case DW_ATE_unsigned:
|
||||
snprintf(name, sizeof(name), "unsigned %s", sizemod[param->info.size & 0x0F]);
|
||||
pst_parameter_add_type(param, name, PARAM_TYPE_UINT);
|
||||
break;
|
||||
case DW_ATE_signed_char:
|
||||
pst_parameter_add_type(param, "char", PARAM_TYPE_CHAR);
|
||||
break;
|
||||
case DW_ATE_unsigned_char:
|
||||
pst_parameter_add_type(param, "unsigned char", PARAM_TYPE_UCHAR);
|
||||
break;
|
||||
case DW_ATE_float:
|
||||
case DW_ATE_complex_float:
|
||||
case DW_ATE_imaginary_float:
|
||||
case DW_ATE_decimal_float:
|
||||
pst_parameter_add_type(param, "float", PARAM_TYPE_FLOAT);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DW_TAG_array_type:
|
||||
pst_log(SEVERITY_DEBUG, "array type");
|
||||
pst_parameter_add_type(param, "[]", DW_TAG_array_type);
|
||||
pst_parameter_add_type(param, NULL, PARAM_TYPE_ARRAY);
|
||||
break;
|
||||
case DW_TAG_structure_type:
|
||||
pst_log(SEVERITY_DEBUG, "structure type");
|
||||
pst_parameter_add_type(param, "struct", DW_TAG_structure_type);
|
||||
pst_parameter_add_type(param, NULL, PARAM_TYPE_STRUCT);
|
||||
break;
|
||||
case DW_TAG_union_type:
|
||||
pst_log(SEVERITY_DEBUG, "union type");
|
||||
pst_parameter_add_type(param, "union", DW_TAG_union_type);
|
||||
pst_parameter_add_type(param, NULL, PARAM_TYPE_UNION);
|
||||
break;
|
||||
case DW_TAG_class_type:
|
||||
pst_log(SEVERITY_DEBUG, "class type");
|
||||
pst_parameter_add_type(param, "class", DW_TAG_class_type);
|
||||
pst_parameter_add_type(param, NULL, PARAM_TYPE_CLASS);
|
||||
break;
|
||||
case DW_TAG_pointer_type:
|
||||
pst_log(SEVERITY_DEBUG, "pointer type");
|
||||
pst_parameter_add_type(param, "*", DW_TAG_pointer_type);
|
||||
pst_parameter_add_type(param, NULL, PARAM_TYPE_POINTER);
|
||||
break;
|
||||
case DW_TAG_enumeration_type:
|
||||
pst_log(SEVERITY_DEBUG, "enumeration type");
|
||||
pst_parameter_add_type(param, "enum", DW_TAG_enumeration_type);
|
||||
pst_parameter_add_type(param, NULL, PARAM_TYPE_ENUM);
|
||||
break;
|
||||
case DW_TAG_const_type:
|
||||
pst_log(SEVERITY_DEBUG, "constant type");
|
||||
pst_parameter_add_type(param, "const", DW_TAG_const_type);
|
||||
pst_parameter_add_type(param, NULL, PARAM_CONST);
|
||||
break;
|
||||
case DW_TAG_subroutine_type:
|
||||
pst_log(SEVERITY_DEBUG, "Skipping subroutine type");
|
||||
pst_log(SEVERITY_DEBUG, "%s: Skipping subroutine type", __FUNCTION__);
|
||||
break;
|
||||
case DW_TAG_typedef:
|
||||
pst_log(SEVERITY_DEBUG, "typedef '%s' type", dwarf_diename(&ret_die));
|
||||
pst_parameter_add_type(param, dwarf_diename(&ret_die), DW_TAG_typedef);
|
||||
case DW_TAG_typedef: {
|
||||
pst_parameter_add_type(param, dwarf_diename(&ret_die), PARAM_TYPE_TYPEDEF);
|
||||
break;
|
||||
}
|
||||
case DW_TAG_unspecified_type:
|
||||
pst_parameter_add_type(param, "void", PARAM_TYPE_VOID);
|
||||
break;
|
||||
case DW_TAG_reference_type:
|
||||
pst_parameter_add_type(param, NULL, PARAM_TYPE_REF);
|
||||
break;
|
||||
|
||||
default:
|
||||
pst_log(SEVERITY_WARNING, "Unknown 0x%X tag type", dwarf_tag(&ret_die));
|
||||
break;
|
||||
@@ -208,12 +253,13 @@ bool pst_parameter_handle_dwarf(pst_parameter* param, Dwarf_Die* result, pst_fun
|
||||
pst_log(SEVERITY_ERROR, "Failed to calculate DW_AT_location expression: %s", param->ctx->buff);
|
||||
}
|
||||
} else if(dwarf_hasattr(result, DW_AT_const_value)) {
|
||||
param->info.flags |= PARAM_CONST;
|
||||
// no locations definitions, value is constant, known by DWARF directly
|
||||
attr = dwarf_attr(result, DW_AT_const_value, &attr_mem);
|
||||
switch (dwarf_whatform(attr)) {
|
||||
case DW_FORM_string:
|
||||
// do nothing for now
|
||||
pst_log(SEVERITY_WARNING, "Const value form DW_FORM_string value = %s.", dwarf_formstring(attr));
|
||||
param->info.value = (unw_word_t)dwarf_formstring(attr);
|
||||
param->info.flags |= PARAM_HAS_VALUE;
|
||||
break;
|
||||
case DW_FORM_data1:
|
||||
case DW_FORM_data2:
|
||||
@@ -236,6 +282,8 @@ bool pst_parameter_handle_dwarf(pst_parameter* param, Dwarf_Die* result, pst_fun
|
||||
}
|
||||
}
|
||||
|
||||
//param->info.value &=0xFFFFFFFFFFFFFFFF >> (64 - ((param->info.size * 8) & 0x0F));
|
||||
|
||||
// Additionally handle these attributes:
|
||||
// 1. DW_AT_default_value to get information about default value for DW_TAG_formal_parameter type of function
|
||||
// A DW_AT_default_value attribute for a formal parameter entry. The value of
|
||||
@@ -263,6 +311,7 @@ void pst_parameter_init(pst_parameter* param, pst_context* ctx)
|
||||
param->die = NULL;
|
||||
// info field
|
||||
param->info.name = NULL;
|
||||
param->info.type_name = NULL;
|
||||
param->info.line = 0;
|
||||
param->info.size = 0;
|
||||
param->info.flags = 0;
|
||||
@@ -288,9 +337,6 @@ pst_parameter* pst_parameter_new(pst_context* ctx)
|
||||
void pst_parameter_fini(pst_parameter* param)
|
||||
{
|
||||
clear(param);
|
||||
if(param->info.name) {
|
||||
pst_free(param->info.name);
|
||||
}
|
||||
if(param->allocated) {
|
||||
pst_free(param);
|
||||
}
|
||||
|
||||
@@ -19,11 +19,11 @@ typedef struct __pst_type {
|
||||
list_node node; // uplink
|
||||
|
||||
char* name; // type name
|
||||
uint32_t type; // DW_AT_XXX type
|
||||
pst_param_flags type; // type bit
|
||||
bool allocated; // whether this struct was allocated or not
|
||||
} pst_type;
|
||||
void pst_type_init(pst_type* t, const char* name, uint32_t type);
|
||||
pst_type* pst_type_new(const char* name, uint32_t type);
|
||||
void pst_type_init(pst_type* t, const char* name, pst_param_flags type);
|
||||
pst_type* pst_type_new(const char* name, pst_param_flags type);
|
||||
void pst_type_fini(pst_type* t);
|
||||
|
||||
typedef struct pst_function pst_function;
|
||||
@@ -49,6 +49,6 @@ void pst_parameter_fini(pst_parameter* param);
|
||||
bool pst_parameter_handle_dwarf(pst_parameter* param, Dwarf_Die* result, pst_function* fun);
|
||||
bool pst_parameter_print_dwarf(pst_parameter* param);
|
||||
bool pst_parameter_handle_type(pst_parameter* param, Dwarf_Attribute* base);
|
||||
pst_type* pst_parameter_add_type(pst_parameter* param, const char* name, int type);
|
||||
pst_type* pst_parameter_add_type(pst_parameter* param, const char* name, pst_param_flags type);
|
||||
|
||||
#endif /* __PST_DWARF_PARAMETER_H__ */
|
||||
|
||||
Reference in New Issue
Block a user