use internal linkedlist implementation instead of std::list,

std::vector. make stack trace a bit more complex
This commit is contained in:
2020-01-14 18:03:11 +04:00
parent b49318cd11
commit e2bdd31cef
3 changed files with 194 additions and 55 deletions
+148 -44
View File
@@ -113,27 +113,27 @@ void print_framereg(int regno)
bool __pst_parameter::print_dwarf() bool __pst_parameter::print_dwarf()
{ {
if(types.size()) { if(types.Size()) {
if(!is_return) { if(!is_return) {
if(has_value) { if(has_value) {
ctx->print("%s %s = 0x%lX", types[0].c_str(), name.c_str(), value); ctx->print("%s %s = 0x%lX", next_type(NULL)->name.c_str(), name.c_str(), value);
} else { } else {
ctx->print("%s %s = <undefined>", types[0].c_str(), name.c_str()); ctx->print("%s %s = <undefined>", next_type(NULL)->name.c_str(), name.c_str());
} }
} else { } else {
ctx->print("%s", types[0].c_str()); ctx->print("%s", next_type(NULL)->name.c_str());
} }
} else { } else {
if(has_value) { if(has_value) {
ctx->print("%s = 0x%lX", name.c_str(), value); ctx->print("%s = 0x%lX", name.c_str(), value);
} else { } else {
ctx->print("%s = <undefined>", name.c_str(), value); ctx->print("%s = <undefined>", name.c_str());
} }
} }
return true; return true;
} }
bool __pst_parameter::handle_type(Dwarf_Attribute* param, bool is_return) bool __pst_parameter::handle_type(Dwarf_Attribute* param)
{ {
Dwarf_Attribute attr_mem; Dwarf_Attribute attr_mem;
Dwarf_Attribute* attr; Dwarf_Attribute* attr;
@@ -155,43 +155,43 @@ bool __pst_parameter::handle_type(Dwarf_Attribute* param, bool is_return)
dwarf_formudata(attr, &size); dwarf_formudata(attr, &size);
} }
ctx->log(SEVERITY_DEBUG, "base type '%s'(%lu)", dwarf_diename(&ret_die), size); ctx->log(SEVERITY_DEBUG, "base type '%s'(%lu)", dwarf_diename(&ret_die), size);
types.push_back(dwarf_diename(&ret_die)); add_type(dwarf_diename(&ret_die), DW_TAG_base_type);
break; break;
} }
case DW_TAG_array_type: case DW_TAG_array_type:
ctx->log(SEVERITY_DEBUG, "array type"); ctx->log(SEVERITY_DEBUG, "array type");
types.push_back("[]"); add_type("[]", DW_TAG_array_type);
break; break;
case DW_TAG_structure_type: case DW_TAG_structure_type:
ctx->log(SEVERITY_DEBUG, "structure type"); ctx->log(SEVERITY_DEBUG, "structure type");
types.push_back("struct"); add_type("struct", DW_TAG_structure_type);
break; break;
case DW_TAG_union_type: case DW_TAG_union_type:
ctx->log(SEVERITY_DEBUG, "union type"); ctx->log(SEVERITY_DEBUG, "union type");
types.push_back("union"); add_type("union", DW_TAG_union_type);
break; break;
case DW_TAG_class_type: case DW_TAG_class_type:
ctx->log(SEVERITY_DEBUG, "class type"); ctx->log(SEVERITY_DEBUG, "class type");
types.push_back("class"); add_type("class", DW_TAG_class_type);
break; break;
case DW_TAG_pointer_type: case DW_TAG_pointer_type:
ctx->log(SEVERITY_DEBUG, "pointer type"); ctx->log(SEVERITY_DEBUG, "pointer type");
types.push_back("*"); add_type("*", DW_TAG_pointer_type);
break; break;
case DW_TAG_enumeration_type: case DW_TAG_enumeration_type:
ctx->log(SEVERITY_DEBUG, "enumeration type"); ctx->log(SEVERITY_DEBUG, "enumeration type");
types.push_back("enum"); add_type("enum", DW_TAG_enumeration_type);
break; break;
case DW_TAG_const_type: case DW_TAG_const_type:
ctx->log(SEVERITY_DEBUG, "constant type"); ctx->log(SEVERITY_DEBUG, "constant type");
types.push_back("const"); add_type("const", DW_TAG_const_type);
break; break;
case DW_TAG_subroutine_type: case DW_TAG_subroutine_type:
ctx->log(SEVERITY_DEBUG, "subroutine type"); ctx->log(SEVERITY_DEBUG, "Skipping subroutine type");
break; break;
case DW_TAG_typedef: case DW_TAG_typedef:
ctx->log(SEVERITY_DEBUG, "typedef '%s' type", dwarf_diename(&ret_die)); ctx->log(SEVERITY_DEBUG, "typedef '%s' type", dwarf_diename(&ret_die));
types.push_back(dwarf_diename(&ret_die)); add_type(dwarf_diename(&ret_die), DW_TAG_typedef);
break; break;
default: default:
ctx->log(SEVERITY_WARNING, "Unknown 0x%X tag type", dwarf_tag(&ret_die)); ctx->log(SEVERITY_WARNING, "Unknown 0x%X tag type", dwarf_tag(&ret_die));
@@ -206,6 +206,34 @@ bool __pst_parameter::handle_type(Dwarf_Attribute* param, bool is_return)
return true; return true;
} }
pst_type* __pst_parameter::add_type(const char* name, int type)
{
pst_type* t = new pst_type(name, type);
types.InsertLast(t);
return t;
}
void __pst_parameter::clear()
{
for(pst_type* t = (pst_type*)types.First(); t; t = (pst_type*)types.First()) {
types.Remove(t);
delete t;
}
}
pst_type* __pst_parameter::next_type(pst_type* t)
{
pst_type* next = NULL;
if(!t) {
next = (pst_type*)types.First();
} else {
next = (pst_type*)types.Next(t);
}
return next;
}
bool __pst_parameter::handle_dwarf(Dwarf_Die* result) bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
{ {
die = result; die = result;
@@ -313,6 +341,40 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
return true; return true;
} }
pst_parameter* __pst_function::add_param()
{
pst_parameter* p = new pst_parameter(ctx);
params.InsertLast(p);
return p;
}
void __pst_function::del_param(pst_parameter* p)
{
params.Remove(p);
delete p;
}
void __pst_function::clear()
{
for(pst_parameter* p = (pst_parameter*)params.First(); p; p = (pst_parameter*)params.First()) {
params.Remove(p);
delete p;
}
}
pst_parameter* __pst_function::next_param(pst_parameter* p)
{
pst_parameter* next = NULL;
if(!p) {
next = (pst_parameter*)params.First();
} else {
next = (pst_parameter*)params.Next(p);
}
return next;
}
bool __pst_function::print_dwarf() bool __pst_function::print_dwarf()
{ {
//std::vector<std::string>::const_iterator param; //std::vector<std::string>::const_iterator param;
@@ -320,26 +382,28 @@ bool __pst_function::print_dwarf()
ctx->print("%s:%u: ", file.c_str(), line); ctx->print("%s:%u: ", file.c_str(), line);
bool first = true; bool start_variable = false; bool first = true; bool start_variable = false;
for(auto param : params) { pst_parameter* ret = NULL;
if(param.is_return) { for(pst_parameter* param = next_param(NULL); param; param = next_param(param)) {
if(param->is_return) {
// print return value type, function name and start list of parameters // print return value type, function name and start list of parameters
param.print_dwarf(); ret = param;
param->print_dwarf();
ctx->print(" %s(", name.c_str()); ctx->print(" %s(", name.c_str());
continue; continue;
} }
if(param.is_variable) { if(param->is_variable) {
if(!start_variable) { if(!start_variable) {
ctx->print(")\n"); ctx->print(")\n");
ctx->print("{\n"); ctx->print("{\n");
start_variable = true; start_variable = true;
} }
if(param.line) { if(param->line) {
ctx->print("%04u: ", param.line); ctx->print("%04u: ", param->line);
} else { } else {
ctx->print(" "); ctx->print(" ");
} }
param.print_dwarf(); param->print_dwarf();
ctx->print(";\n"); ctx->print(";\n");
} else { } else {
if(first) { if(first) {
@@ -347,7 +411,7 @@ bool __pst_function::print_dwarf()
} else { } else {
ctx->print(", "); ctx->print(", ");
} }
param.print_dwarf(); param->print_dwarf();
} }
} }
@@ -412,19 +476,21 @@ bool __pst_function::handle_dwarf(Dwarf_Die* d)
// Get reference to return attribute type of the function // Get reference to return attribute type of the function
// may be to use dwfl_module_return_value_location() instead // may be to use dwfl_module_return_value_location() instead
pst_parameter ret_p(ctx); ret_p.is_return = true; pst_parameter* ret_p = add_param(); ret_p->is_return = true;
attr = dwarf_attr(die, DW_AT_type, &attr_mem); attr = dwarf_attr(die, DW_AT_type, &attr_mem);
if(attr) { if(attr) {
ctx->log(SEVERITY_DEBUG, "Handle return parameter"); ctx->log(SEVERITY_DEBUG, "Handle return parameter");
if(!unw_get_reg(&ctx->cursor, 16, &ret_p.value)) { if(!unw_get_reg(&ctx->cursor, 16, &ret_p->value)) {
ret_p.has_value = true; ret_p->has_value = true;
} else {
ctx->log(SEVERITY_ERROR, "Failed to get return parameter value from RIP");
} }
if(ret_p.handle_type(attr, true)) { if(!ret_p->handle_type(attr)) {
params.push_back(ret_p); ctx->log(SEVERITY_ERROR, "Failed to handle return parameter type");
del_param(ret_p);
} }
} else { } else {
ret_p.types.push_back("void"); ret_p->add_type("void", 0);
params.push_back(ret_p);
ctx->log(SEVERITY_DEBUG, "return attr name = 'void(0)'"); ctx->log(SEVERITY_DEBUG, "return attr name = 'void(0)'");
} }
@@ -434,15 +500,17 @@ bool __pst_function::handle_dwarf(Dwarf_Die* d)
// went through parameters and local variables of the function // went through parameters and local variables of the function
do { do {
pst_parameter param(ctx);
switch (dwarf_tag(&result)) { switch (dwarf_tag(&result)) {
case DW_TAG_formal_parameter: case DW_TAG_formal_parameter:
case DW_TAG_variable: case DW_TAG_variable: {
if(param.handle_dwarf(&result)) { pst_parameter* param = add_param();
params.push_back(param); if(!param->handle_dwarf(&result)) {
del_param(param);
} }
break; break;
}
// case DW_TAG_inlined_subroutine: // case DW_TAG_inlined_subroutine:
// /* Recurse further down */ // /* Recurse further down */
// HandleFunction(&result, dwarf_diename(&result)); // HandleFunction(&result, dwarf_diename(&result));
@@ -557,7 +625,7 @@ bool __pst_handler::get_frame()
return true; return true;
} }
bool __pst_handler::get_dwarf_function(pst_function& fun) bool __pst_handler::get_dwarf_function(pst_function* fun)
{ {
Dwarf_Addr mod_cu = 0; Dwarf_Addr mod_cu = 0;
// get CU(Compilation Unit) debug definition // get CU(Compilation Unit) debug definition
@@ -584,8 +652,8 @@ bool __pst_handler::get_dwarf_function(pst_function& fun)
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) {
if(!strcmp(fun.name.c_str(), dwarf_diename(&result))) { if(!strcmp(fun->name.c_str(), dwarf_diename(&result))) {
return fun.handle_dwarf(&result); return fun->handle_dwarf(&result);
} }
} }
} while(dwarf_siblingof(&result, &result) == 0); } while(dwarf_siblingof(&result, &result) == 0);
@@ -593,14 +661,48 @@ bool __pst_handler::get_dwarf_function(pst_function& fun)
return nret; return nret;
} }
pst_function* __pst_handler::add_function()
{
pst_function* f = new pst_function(&ctx);
functions.InsertLast(f);
return f;
}
void __pst_handler::del_function(pst_function* f)
{
functions.Remove(f);
delete f;
}
void __pst_handler::clear()
{
for(pst_function* f = (pst_function*)functions.First(); f; f = (pst_function*)functions.First()) {
functions.Remove(f);
delete f;
}
}
pst_function* __pst_handler::next_function(pst_function* f)
{
pst_function* next = NULL;
if(!f) {
next = (pst_function*)functions.First();
} else {
next = (pst_function*)functions.Next(f);
}
return next;
}
void __pst_handler::print_dwarf() void __pst_handler::print_dwarf()
{ {
ctx.offset = 0; ctx.offset = 0;
ctx.print("DWARF-based stack trace information:\n"); ctx.print("DWARF-based stack trace information:\n");
uint32_t idx = 0; uint32_t idx = 0;
for(auto function : functions) { for(pst_function* function = next_function(NULL); function; function = next_function(function)) {
ctx.print("[%-2u] ", idx); idx++; ctx.print("[%-2u] ", idx); idx++;
function.print_dwarf(); function->print_dwarf();
ctx.print("\n"); ctx.print("\n");
} }
} }
@@ -687,11 +789,13 @@ bool __pst_handler::unwind()
#endif #endif
module = dwfl_addrmodule(dwfl, addr); module = dwfl_addrmodule(dwfl, addr);
get_frame(); get_frame();
pst_function fun(&ctx); pst_function* fun = add_function();
if(fun.unwind(dwfl, module, pc)) { if(fun->unwind(dwfl, module, pc)) {
if(get_dwarf_function(fun)) { if(!get_dwarf_function(fun)) {
functions.push_back(fun); del_function(fun);
} }
} else {
del_function(fun);
} }
ctx.print("\n"); ctx.print("\n");
#ifdef USEI_LIBUNWIND #ifdef USEI_LIBUNWIND
+42 -9
View File
@@ -27,7 +27,17 @@ char* GetExecutableName(char* path, uint32_t size);
typedef struct __pst_function pst_function; typedef struct __pst_function pst_function;
typedef struct __pst_parameter { 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) __pst_parameter(pst_context* c) : ctx(c)
{ {
die = NULL; die = NULL;
@@ -41,8 +51,17 @@ typedef struct __pst_parameter {
line = 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_dwarf(Dwarf_Die* d);
bool handle_type(Dwarf_Attribute* param, bool is_return = false); bool handle_type(Dwarf_Attribute* param);
bool print_dwarf(); bool print_dwarf();
Dwarf_Die* die; // DWARF DIE containing parameter's definition Dwarf_Die* die; // DWARF DIE containing parameter's definition
@@ -50,7 +69,7 @@ typedef struct __pst_parameter {
uint32_t line; // line of parameter definition uint32_t line; // line of parameter definition
Dwarf_Word size; // size of parameter in bytes Dwarf_Word size; // size of parameter in bytes
int type; // base type of parameter in DW_TAG_XXX types enumeration int type; // base type of parameter in DW_TAG_XXX types enumeration
std::vector<std::string> types; // list of parameter's definitions i.e. 'typedef', 'uint32_t' SC_ListHead types; // list of parameter's definitions i.e. 'typedef', 'uint32_t'
void* loc; // pointer to location of parameter's value void* loc; // pointer to location of parameter's value
bool is_return; // whether this parameter is return value of the function 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 is_variable;// whether this parameter is function variable or argument of function
@@ -61,9 +80,8 @@ typedef struct __pst_parameter {
typedef struct __pst_handler pst_handler; typedef struct __pst_handler pst_handler;
typedef struct __pst_function { typedef struct __pst_function : public SC_ListNode {
__pst_function(pst_context* ctx) : ctx(ctx) __pst_function(pst_context* ctx) : ctx(ctx) {
{
pc = 0; pc = 0;
line = -1; line = -1;
die = NULL; die = NULL;
@@ -71,6 +89,15 @@ typedef struct __pst_function {
highpc = 0; highpc = 0;
} }
~__pst_function() {
clear();
}
void clear();
pst_parameter* add_param();
void del_param(pst_parameter* p);
pst_parameter* next_param(pst_parameter* p);
bool unwind(Dwfl* dwfl, Dwfl_Module* module, Dwarf_Addr addr); bool unwind(Dwfl* dwfl, Dwfl_Module* module, Dwarf_Addr addr);
bool handle_dwarf(Dwarf_Die* d); bool handle_dwarf(Dwarf_Die* d);
bool print_dwarf(); bool print_dwarf();
@@ -79,7 +106,7 @@ typedef struct __pst_function {
Dwarf_Addr highpc; Dwarf_Addr highpc;
Dwarf_Die* die; // DWARF DIE containing definition of the function Dwarf_Die* die; // DWARF DIE containing definition of the function
std::string name; // function's name std::string name; // function's name
std::vector<pst_parameter> params; // array of function's parameters SC_ListHead params; // array of function's parameters
unw_word_t pc; // pointer to the start of the function unw_word_t pc; // pointer to the start of the function
int line; // line in code where function is defined int line; // line in code where function is defined
std::string file; // file name (DWARF Compilation Unit) where is function defined std::string file; // file name (DWARF Compilation Unit) where is function defined
@@ -102,13 +129,19 @@ typedef struct __pst_handler {
if(handle) { if(handle) {
dlclose(handle); dlclose(handle);
} }
clear();
} }
void clear();
pst_function* add_function();
void del_function(pst_function* f);
pst_function* next_function(pst_function* f);
void print_dwarf(); void print_dwarf();
bool unwind(); bool unwind();
bool get_frame(); bool get_frame();
bool get_dwarf_function(pst_function& fun); bool get_dwarf_function(pst_function* fun);
pst_context ctx; // context of unwinding pst_context ctx; // context of unwinding
void* handle; // process handle void* handle; // process handle
@@ -117,7 +150,7 @@ typedef struct __pst_handler {
Dwfl_Module* module; // currently processed CU Dwfl_Module* module; // currently processed CU
Dwarf_Frame* frame; // currently processed stack frame Dwarf_Frame* frame; // currently processed stack frame
void* caller; // pointer to the function which requested to unwind stack void* caller; // pointer to the function which requested to unwind stack
std::vector<pst_function> functions; // array of functions in stack frame SC_ListHead functions; // list of functions in stack frame
} pst_handler; } pst_handler;
#endif /* SC_SYSUTILS_H_ */ #endif /* SC_SYSUTILS_H_ */
+4 -2
View File
@@ -20,12 +20,14 @@ void Fun2(int arg1, uint32_t arg2)
{ {
int* ptr = NULL; int* ptr = NULL;
*ptr = arg1; *ptr = arg1;
void* ptr2 = ptr+1;
printf("%p\n", ptr2);
} }
uint32_t Fun1(const int arg1, my_int arg2, uint32_t arg3) uint32_t Fun1(const int arg1, my_int arg2, uint32_t arg3)
{ {
int my_local = arg1 + 2; int my_local = arg1 + 2;
printf("%d", my_local); printf("%d\n", my_local);
Fun2(my_local, arg3); Fun2(my_local, arg3);
return arg2; return arg2;
} }
@@ -193,7 +195,7 @@ void ResetSignalHandler() {
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
logger->SetCurrentSeverity(SEVERITY_INFO); //logger->SetCurrentSeverity(SEVERITY_INFO);
SetSignalHandler(SigusrHandler); SetSignalHandler(SigusrHandler);
Fun1(1, DEF_2, 5); Fun1(1, DEF_2, 5);