introduce printing functions and their parameters on base of dwarf info

This commit is contained in:
2020-01-14 13:47:08 +04:00
parent fc6a81b460
commit eb9dc1341d
3 changed files with 87 additions and 21 deletions
+78 -18
View File
@@ -111,6 +111,20 @@ void print_framereg(int regno)
} }
*/ */
bool __pst_parameter::print_dwarf()
{
if(types.size()) {
if(!is_return) {
ctx->print("%s %s = 0x%lX", types[0].c_str(), name.c_str(), value);
} else {
ctx->print("%s", types[0].c_str());
}
} else {
ctx->print("%s = 0x%lX", name.c_str(), value);
}
return true;
}
bool __pst_parameter::handle_type(Dwarf_Attribute* param, bool is_return) bool __pst_parameter::handle_type(Dwarf_Attribute* param, bool is_return)
{ {
Dwarf_Attribute attr_mem; Dwarf_Attribute attr_mem;
@@ -132,47 +146,47 @@ bool __pst_parameter::handle_type(Dwarf_Attribute* param, bool is_return)
if(attr) { if(attr) {
dwarf_formudata(attr, &size); dwarf_formudata(attr, &size);
} }
ctx->log(SEVERITY_INFO, "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)); types.push_back(dwarf_diename(&ret_die));
break; break;
} }
case DW_TAG_array_type: case DW_TAG_array_type:
ctx->log(SEVERITY_INFO, "array type"); ctx->log(SEVERITY_DEBUG, "array type");
types.push_back("[]"); types.push_back("[]");
break; break;
case DW_TAG_structure_type: case DW_TAG_structure_type:
ctx->log(SEVERITY_INFO, "structure type"); ctx->log(SEVERITY_DEBUG, "structure type");
types.push_back("struct"); types.push_back("struct");
break; break;
case DW_TAG_union_type: case DW_TAG_union_type:
ctx->log(SEVERITY_INFO, "union type"); ctx->log(SEVERITY_DEBUG, "union type");
types.push_back("union"); types.push_back("union");
break; break;
case DW_TAG_class_type: case DW_TAG_class_type:
ctx->log(SEVERITY_INFO, "class type"); ctx->log(SEVERITY_DEBUG, "class type");
types.push_back("class"); types.push_back("class");
break; break;
case DW_TAG_pointer_type: case DW_TAG_pointer_type:
ctx->log(SEVERITY_INFO, "pointer type"); ctx->log(SEVERITY_DEBUG, "pointer type");
types.push_back("*"); types.push_back("*");
break; break;
case DW_TAG_enumeration_type: case DW_TAG_enumeration_type:
ctx->log(SEVERITY_INFO, "enumeration type"); ctx->log(SEVERITY_DEBUG, "enumeration type");
types.push_back("enum"); types.push_back("enum");
break; break;
case DW_TAG_const_type: case DW_TAG_const_type:
ctx->log(SEVERITY_INFO, "constant type"); ctx->log(SEVERITY_DEBUG, "constant type");
types.push_back("const"); types.push_back("const");
break; break;
case DW_TAG_subroutine_type: case DW_TAG_subroutine_type:
ctx->log(SEVERITY_INFO, "subroutine type"); ctx->log(SEVERITY_DEBUG, "subroutine type");
break; break;
case DW_TAG_typedef: case DW_TAG_typedef:
ctx->log(SEVERITY_INFO, "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)); types.push_back(dwarf_diename(&ret_die));
break; break;
default: default:
ctx->log(SEVERITY_INFO, "Unknown 0x%X tag type", dwarf_tag(&ret_die)); ctx->log(SEVERITY_WARNING, "Unknown 0x%X tag type", dwarf_tag(&ret_die));
break; break;
} }
@@ -191,9 +205,11 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
Dwarf_Attribute attr_mem; Dwarf_Attribute attr_mem;
Dwarf_Attribute* attr; Dwarf_Attribute* attr;
name = dwarf_diename(result);
is_variable = (dwarf_tag(result) == DW_TAG_variable);
// Get reference to attribute type of the parameter/variable // Get reference to attribute type of the parameter/variable
attr = dwarf_attr(result, DW_AT_type, &attr_mem); attr = dwarf_attr(result, DW_AT_type, &attr_mem);
ctx->log(SEVERITY_INFO, "Handle '%s' %s", dwarf_diename(result), dwarf_tag(result) == DW_TAG_formal_parameter ? "parameter" : "variable"); ctx->log(SEVERITY_DEBUG, "Handle '%s' %s", name.c_str(), dwarf_tag(result) == DW_TAG_formal_parameter ? "parameter" : "variable");
if(attr) { if(attr) {
handle_type(attr); handle_type(attr);
} }
@@ -213,7 +229,6 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
char str[1024]; str[0] = 0; char str[1024]; str[0] = 0;
ctx->print_expr_block (expr, exprlen, str, sizeof(str), attr); ctx->print_expr_block (expr, exprlen, str, sizeof(str), attr);
if(stack.calc_expression(expr, exprlen, attr)) { if(stack.calc_expression(expr, exprlen, attr)) {
uint64_t value;
if(stack.get_value(value)) { if(stack.get_value(value)) {
ctx->log(SEVERITY_DEBUG, "DW_AT_location expression: \"%s\" ==> 0x%lX", str, value); ctx->log(SEVERITY_DEBUG, "DW_AT_location expression: \"%s\" ==> 0x%lX", str, value);
} else { } else {
@@ -236,7 +251,6 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
char str[1024]; str[0] = 0; char str[1024]; str[0] = 0;
ctx->print_expr_block (expr, exprlen, str, sizeof(str), attr); ctx->print_expr_block (expr, exprlen, str, sizeof(str), attr);
if(stack.calc_expression(expr, exprlen, attr)) { if(stack.calc_expression(expr, exprlen, attr)) {
uint64_t value;
if(stack.get_value(value)) { if(stack.get_value(value)) {
ctx->log(SEVERITY_DEBUG, "Location list expression: [%d] (low_offset: 0x%" PRIx64 ", high_offset: 0x%" PRIx64"), \"%s\" ==> 0x%lX", i, start, end, str, value); ctx->log(SEVERITY_DEBUG, "Location list expression: [%d] (low_offset: 0x%" PRIx64 ", high_offset: 0x%" PRIx64"), \"%s\" ==> 0x%lX", i, start, end, str, value);
} else { } else {
@@ -261,6 +275,47 @@ bool __pst_parameter::handle_dwarf(Dwarf_Die* result)
return true; return true;
} }
bool __pst_function::print_dwarf()
{
//std::vector<std::string>::const_iterator param;
//for (param = params.begin(); param != params.end(); ++param) {
bool first = true; bool start_variable = false;
for(auto param : params) {
if(param.is_return) {
// print return value, function name and start list of parameters
param.print_dwarf();
ctx->print(" %s(", name.c_str());
continue;
}
if(param.is_variable) {
if(!start_variable) {
ctx->print(")\n");
ctx->print("{\n");
start_variable = true;
}
ctx->print("\t");
param.print_dwarf();
ctx->print(";\n");
} else {
if(first) {
first = false;
} else {
ctx->print(", ");
}
param.print_dwarf();
}
}
if(!start_variable) {
ctx->print(");\n");
} else {
ctx->print("}\n");
}
return true;
}
bool __pst_function::handle_dwarf(Dwarf_Die* d) bool __pst_function::handle_dwarf(Dwarf_Die* d)
{ {
die = d; die = d;
@@ -282,7 +337,7 @@ bool __pst_function::handle_dwarf(Dwarf_Die* d)
unw_word_t sp; unw_word_t sp;
unw_get_reg(&ctx->cursor, UNW_REG_SP, &sp); unw_get_reg(&ctx->cursor, UNW_REG_SP, &sp);
ctx->log(SEVERITY_INFO, "Found function in debug info. name = %s(...), PC = 0x%lX, LOW_PC = 0x%lX, HIGH_PC = 0x%lX, offset from base address: 0x%lX, BASE_PC = 0x%lX, offset from start of function: 0x%lX, stack address: 0x%lX", ctx->log(SEVERITY_DEBUG, "Found function in debug info. name = %s(...), PC = 0x%lX, LOW_PC = 0x%lX, HIGH_PC = 0x%lX, offset from base address: 0x%lX, BASE_PC = 0x%lX, offset from start of function: 0x%lX, stack address: 0x%lX",
dwarf_diename(d), pc, lowpc, highpc, pc - ctx->base_addr, info.start_ip, info.start_ip - ctx->base_addr, sp); dwarf_diename(d), pc, lowpc, highpc, pc - ctx->base_addr, info.start_ip, info.start_ip - ctx->base_addr, sp);
// determine function's stack frame base // determine function's stack frame base
@@ -316,7 +371,7 @@ bool __pst_function::handle_dwarf(Dwarf_Die* d)
pst_parameter ret_p(ctx); ret_p.is_return = true; pst_parameter ret_p(ctx); 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_INFO, "Handle return parameter"); ctx->log(SEVERITY_DEBUG, "Handle return parameter");
if(ret_p.handle_type(attr, true)) { if(ret_p.handle_type(attr, true)) {
params.push_back(ret_p); params.push_back(ret_p);
} }
@@ -491,9 +546,14 @@ bool __pst_handler::get_dwarf_function(pst_function& fun)
return nret; return nret;
} }
void __pst_handler::dwarf_print() void __pst_handler::print_dwarf()
{ {
ctx.offset = 0;
ctx.print("DWARF-based stack trace information:\n");
for(auto function : functions) {
function.print_dwarf();
ctx.print("\n");
}
} }
char *debuginfo_path = NULL; char *debuginfo_path = NULL;
+5 -1
View File
@@ -35,11 +35,13 @@ typedef struct __pst_parameter {
type = 0; type = 0;
loc = NULL; loc = NULL;
is_return = false; is_return = false;
is_variable = false;
value = 0; value = 0;
} }
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 is_return = false);
bool print_dwarf();
Dwarf_Die* die; // DWARF DIE containing parameter's definition Dwarf_Die* die; // DWARF DIE containing parameter's definition
std::string name; // parameter's name std::string name; // parameter's name
@@ -48,6 +50,7 @@ typedef struct __pst_parameter {
std::vector<std::string> types; // list of parameter's definitions i.e. 'typedef', 'uint32_t' std::vector<std::string> 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
uint64_t value; // value of parameter uint64_t value; // value of parameter
pst_context* ctx; pst_context* ctx;
} pst_parameter; } pst_parameter;
@@ -66,6 +69,7 @@ typedef struct __pst_function {
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();
Dwarf_Addr lowpc; Dwarf_Addr lowpc;
Dwarf_Addr highpc; Dwarf_Addr highpc;
@@ -97,7 +101,7 @@ typedef struct __pst_handler {
} }
void dwarf_print(); 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);
+4 -2
View File
@@ -71,7 +71,9 @@ void FatalSignalHandler(int sig, siginfo_t* info, void* context)
} }
if(trace) { if(trace) {
logger->Log(SEVERITY_DEBUG, "%s", handler.ctx.buff); logger->Log(SEVERITY_INFO, "%s", handler.ctx.buff);
handler.print_dwarf();
logger->Log(SEVERITY_INFO, "%s", handler.ctx.buff);
} else { } else {
logger->Log(SEVERITY_ERROR, "No stack trace obtained"); logger->Log(SEVERITY_ERROR, "No stack trace obtained");
} }
@@ -191,7 +193,7 @@ void ResetSignalHandler() {
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
logger->SetCurrentSeverity(SEVERITY_INFO);
SetSignalHandler(SigusrHandler); SetSignalHandler(SigusrHandler);
Fun1(1, DEF_2, 5); Fun1(1, DEF_2, 5);