#define REG_PC 15
#define REG_SPSR 16
+#define MAXPROCNAMELEN 512
+
/**
* @brief Important registers for unwinding stack on ARM
*/
void _create_crash_stack(Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, Callstack *callstack)
{
// reimplemented based on libunwind tests/test-ptrace.c file
- callstack->elems = 0;
- unw_addr_space_t as = unw_create_addr_space(&_UPT_accessors, 0);
- if (as) {
- void *uptInfo = _UPT_create(pid);
- if (uptInfo) {
- unw_cursor_t cursor;
- if (unw_init_remote(&cursor, as, uptInfo) >= 0) {
- // MaxDeep as proposed in libunwind tests/test-ptrace.c file
- // guard against bad unwind info in old libraries
- static const int MaxDeep = 64;
- int n;
- for (n = 0; n < MaxDeep; ++n) {
- unw_word_t ip;
- if (unw_get_reg(&cursor, UNW_REG_IP, &ip) >= 0) {
- callstack->tab[callstack->elems++] = ip;
- }
- int step = unw_step(&cursor);
- if (step <= 0)
- break;
- }
- }
- _UPT_destroy(uptInfo);
+ unw_addr_space_t as = 0;
+ void *ui = 0;
+ do {
+ callstack->elems = 0;
+
+ as = unw_create_addr_space(&_UPT_accessors, 0);
+ if (!as)
+ break;
+
+ ui = _UPT_create(pid);
+ if (!ui)
+ break;
+
+ unw_cursor_t cursor;
+ if (unw_init_remote(&cursor, as, ui) < 0)
+ break;
+
+ char proc_name[MAXPROCNAMELEN];
+ int n;
+ // MaxDeep as proposed in libunwind tests/test-ptrace.c file
+ // guard against bad unwind info in old libraries
+ static const int MaxDeep = 64;
+ for (n = 0; n < MaxDeep; ++n) {
+
+ unw_word_t ip;
+ if (unw_get_reg(&cursor, UNW_REG_IP, &ip) < 0)
+ break;
+ callstack->tab[callstack->elems] = ip;
+
+ proc_name[0] = '\0';
+ unw_word_t off;
+ unw_get_proc_name(&cursor, proc_name, sizeof(proc_name), &off);
+ if (strlen(proc_name) > 0)
+ callstack->proc_name[callstack->elems] = strdup(proc_name);
+
+ ++callstack->elems;
+ if (unw_step(&cursor) <= 0)
+ break;
}
+ } while (0);
+
+ if (ui)
+ _UPT_destroy(ui);
+ if (as)
unw_destroy_addr_space(as);
- }
}
void _crash_stack_print_regs(FILE* outputfile)
fprintf(outputfile, "0x%016llx: ", (long long)callstack->tab[it]);
else
fprintf(outputfile, "0x%08x: ", (int32_t)callstack->tab[it]);
+ const char *symbol = callstack->proc_name[it];
+
Dwfl_Module *module = dwfl_addrmodule(dwfl, callstack->tab[it]);
if (module) {
char *demangled_symbol = 0;
- const char *symbol = dwfl_module_addrname(module, callstack->tab[it]);
const char *fname = 0;
const char *module_name = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
char *symbol_from_elf = 0;
+ if (symbol == NULL)
+ symbol = dwfl_module_addrname(module, callstack->tab[it]);
if (symbol == NULL)
symbol = symbol_from_elf = __try_symbol_from_elfs(core, notes, callstack->tab[it], &fname);
if (symbol != 0 && symbol[0] == '_' && symbol[1] == 'Z') {
free(symbol_from_elf);
fprintf(outputfile, " from %s\n", fname != NULL ? fname : module_name);
+ } else if (symbol) {
+ fprintf(outputfile, "%s()", symbol);
} else {
fprintf(outputfile, "unknown function\n");
}
*/
int main(int argc, char **argv)
{
- int c;
+ int c, i;
pid_t pid = 0;
const char *core_file_name;
/* Unwind call stack */
Callstack callstack;
+ callstack.elems = 0;
+ memset(callstack.proc_name, 0, sizeof(callstack.proc_name));
_create_crash_stack(dwfl, core, pid, &mappings, &callstack);
/* Print the results */
__print_callstack(&callstack, dwfl, core, pid, notes);
+ for (i = 0; i < callstack.elems; ++i)
+ if (callstack.proc_name[i])
+ free(callstack.proc_name[i]);
+
/* Clean up */
dwfl_report_end(dwfl, NULL, NULL);
dwfl_end(dwfl);
*/
struct Callstack {
uintptr_t tab[MAX_CALLSTACK_LEN]; ///< storage for elements
+ char *proc_name[MAX_CALLSTACK_LEN]; ///< procedure name related to tab element with the same index
size_t elems; ///< number of elements in the database
};
typedef struct Callstack Callstack;