system/stacktrace.cpp: add backtrace function for debugging, define HAVE_BACKTRACE to enable code

This commit is contained in:
[CST] Focus
2015-03-06 13:20:59 +03:00
parent 476b6d0850
commit 09e1399a11
4 changed files with 189 additions and 1 deletions

View File

@@ -77,7 +77,6 @@ neutrino_LDADD = \
gui/widget/libneutrino_gui_widget.a \
gui/widget/libneutrino_gui_widget2.a \
driver/pictureviewer/libneutrino_pictureviewer.a \
system/libneutrino_system.a \
$(MTDUTILSLIBS) \
gui/movieinfo.o \
gui/libneutrino_gui2.a \
@@ -93,6 +92,7 @@ neutrino_LDADD = \
nhttpd/tuxboxapi/coolstream/libnhttpd_tuxboxapi.a \
nhttpd/yhttpd_mods/libyhttpdmods.a \
nhttpd/yhttpd_core/libyhttpd.a \
system/libneutrino_system.a \
$(top_builddir)/lib/sectionsdclient/libsectionsdclient.a \
$(top_builddir)/lib/timerdclient/libtimerdclient.a \
$(top_builddir)/src/zapit/lib/libzapitclient.a \

View File

@@ -45,6 +45,7 @@ libneutrino_system_a_SOURCES = \
helpers.cpp \
ping.cpp \
settings.cpp \
stacktrace.cpp \
sysload.cpp \
ytcache.cpp \
ytparser.cpp \

180
src/system/stacktrace.cpp Normal file
View File

@@ -0,0 +1,180 @@
/*
Neutrino-GUI - DBoxII-Project
Copyright (C) 2015 CoolStream International Ltd
print_stacktrace function taken from:
stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/
published under the WTFPL v2.0
License: GPLv2
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation;
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define __USE_GNU
#include <stdio.h>
#include <stdlib.h>
#include <cxxabi.h>
#include <signal.h>
#include <ucontext.h>
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
/** Print a demangled stack backtrace of the caller function to FILE* out. */
void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63)
{
fprintf(out, "stack trace:\n");
// storage array for stack trace address data
void* addrlist[max_frames+1];
// retrieve current stack addresses
int addrlen = backtrace(addrlist, sizeof(addrlist) / sizeof(void*));
if (addrlen == 0) {
fprintf(out, " <empty, possibly corrupt>\n");
return;
}
// resolve addresses into strings containing "filename(function+address)",
// this array must be free()-ed
char** symbollist = backtrace_symbols(addrlist, addrlen);
// allocate string which will be filled with the demangled function name
size_t funcnamesize = 256;
char* funcname = (char*)malloc(funcnamesize);
// iterate over the returned symbol lines. skip the first, it is the
// address of this function.
for (int i = 1; i < addrlen; i++)
{
char *begin_name = 0, *begin_offset = 0, *end_offset = 0;
// find parentheses and +address offset surrounding the mangled name:
// ./module(function+0x15c) [0x8048a6d]
for (char *p = symbollist[i]; *p; ++p)
{
if (*p == '(')
begin_name = p;
else if (*p == '+')
begin_offset = p;
else if (*p == ')' && begin_offset) {
end_offset = p;
break;
}
}
if (begin_name && begin_offset && end_offset
&& begin_name < begin_offset)
{
*begin_name++ = '\0';
*begin_offset++ = '\0';
*end_offset = '\0';
// mangled name is now in [begin_name, begin_offset) and caller
// offset in [begin_offset, end_offset). now apply
// __cxa_demangle():
int status;
char* ret = abi::__cxa_demangle(begin_name,
funcname, &funcnamesize, &status);
if (status == 0) {
funcname = ret; // use possibly realloc()-ed string
fprintf(out, " %s : %s+%s [%p]\n",
symbollist[i], funcname, begin_offset, addrlist[i]);
}
else {
// demangling failed. Output function name as a C function with
// no arguments.
fprintf(out, " %s : %s()+%s [%p]\n",
symbollist[i], begin_name, begin_offset, addrlist[i]);
}
}
else
{
// couldn't parse the line? print the whole line.
fprintf(out, " %s\n", symbollist[i]);
}
}
free(funcname);
free(symbollist);
}
static void crash_handler(int signum, siginfo_t * si, void *ctx)
{
void *trace[16];
int trace_size = 0;
ucontext_t *ct = (ucontext_t *) ctx;
if (si) {}
#if 0
printf("signal %d, siginfo->si_addr is %p\n", signum, si->si_addr);
printf("reg[%02d] = 0x%lx\n",0 , ct->uc_mcontext.arm_r0);
printf("reg[%02d] = 0x%lx\n",1 , ct->uc_mcontext.arm_r1);
printf("reg[%02d] = 0x%lx\n",2 , ct->uc_mcontext.arm_r2);
printf("reg[%02d] = 0x%lx\n",3 , ct->uc_mcontext.arm_r3);
printf("reg[%02d] = 0x%lx\n",4 , ct->uc_mcontext.arm_r4);
printf("reg[%02d] = 0x%lx\n",5 , ct->uc_mcontext.arm_r5);
printf("reg[%02d] = 0x%lx\n",6 , ct->uc_mcontext.arm_r6);
printf("reg[%02d] = 0x%lx\n",7 , ct->uc_mcontext.arm_r7);
printf("reg[%02d] = 0x%lx\n",8 , ct->uc_mcontext.arm_r8);
printf("reg[%02d] = 0x%lx\n",9 , ct->uc_mcontext.arm_r9);
printf("reg[%02d] = 0x%lx\n",10 , ct->uc_mcontext.arm_r10);
printf("FP = 0x%lx\n", ct->uc_mcontext.arm_fp);
printf("IP = 0x%lx\n", ct->uc_mcontext.arm_ip);
printf("SP = 0x%lx\n", ct->uc_mcontext.arm_sp);
printf("LR = 0x%lx\n", ct->uc_mcontext.arm_lr);
printf("PC = 0x%lx\n", ct->uc_mcontext.arm_pc);
printf("CPSR = 0x%lx\n", ct->uc_mcontext.arm_cpsr);
printf("Fault Address = 0x%lx\n", ct->uc_mcontext.fault_address);
printf("Trap no = 0x%lx\n", ct->uc_mcontext.trap_no);
printf("Err Code = 0x%lx\n", ct->uc_mcontext.error_code);
printf("Old Mask = 0x%lx\n", ct->uc_mcontext.oldmask);
#endif
trace_size = backtrace(trace, 16);
trace[1] = (void *) ct->uc_mcontext.arm_pc;
#if 0
char **messages = backtrace_symbols(trace, trace_size);
/* skip first stack frame (points here) */
printf("Execution path: (%d)\n", trace_size);
for (int i = 0; i < trace_size; ++i)
printf("[#%d] %s\n", i, messages[i]);
#endif
backtrace_symbols_fd(trace, trace_size, fileno(stdout));
if (signum != SIGUSR1)
abort();
}
void install_crash_handler()
{
struct sigaction sa;
sa.sa_sigaction = crash_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
sigaction(SIGBUS, &sa, NULL);
/* for testing */
sigaction(SIGUSR1, &sa, NULL);
void *trace[16];
backtrace(trace, 16);
}
#endif

7
src/system/stacktrace.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef _STACKTRACE_H_
#define _STACKTRACE_H_
void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63);
void install_crash_handler();
#endif