Make backtrace resemble gdb bt

This commit is contained in:
Alexander Mai 2014-03-30 21:29:17 +02:00
parent 0242a3c188
commit a12e59dbee
1 changed files with 42 additions and 20 deletions

View File

@ -205,11 +205,13 @@ static const Signaltype listofsignals[] = {
* \return size of array * \return size of array
* */ * */
template<typename T, int size> template<typename T, int size>
int GetArrayLength(T(&)[size]) int GetArrayLength(const T(&)[size])
{ {
return size; return size;
} }
// 32 vs. 64bit
#define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8)
/* /*
* Try to print the callstack. * Try to print the callstack.
@ -218,34 +220,53 @@ int GetArrayLength(T(&)[size])
static void print_stacktrace(FILE* f, bool demangling) static void print_stacktrace(FILE* f, bool demangling)
{ {
#if defined(__GNUC__) #if defined(__GNUC__)
void *array[50]= {0}; void *array[32]= {0}; // the less resources the better...
const int depth = backtrace(array, (int)GetArrayLength(array)); const int depth = backtrace(array, (int)GetArrayLength(array));
char **symbolstrings = backtrace_symbols(array, depth); char **symbolstrings = backtrace_symbols(array, depth);
if (symbolstrings) { if (symbolstrings) {
fprintf(f, "Callstack:\n"); fputs("Callstack:\n", f);
const int offset=3; // the first two entries are simply within our own exception handling code, third is within libc const int offset=3; // the first two entries are simply within our own exception handling code, third is within libc
for (int i = offset; i < depth; ++i) { for (int i = offset; i < depth; ++i) {
const char * const symbol = symbolstrings[i]; const char * const symbol = symbolstrings[i];
//fprintf(f, "\"%s\"\n", symbol);
char * realname = nullptr; char * realname = nullptr;
const char * const firstBracket = strchr(symbol, '('); const char * const firstBracketName = strchr(symbol, '(');
if (demangling && firstBracket) { const char * const firstBracketAddress = strchr(symbol, '[');
const char * const plus = strchr(firstBracket, '+'); const char * const secondBracketAddress = strchr(firstBracketAddress, ']');
if (plus) { const char * const beginAddress = firstBracketAddress+3;
const int addressLen = int(secondBracketAddress-beginAddress);
const int padLen = int(ADDRESSDISPLAYLENGTH-addressLen);
//fprintf(f, "AddressDisplayLength=%d addressLen=%d padLen=%d\n", ADDRESSDISPLAYLENGTH, addressLen, padLen);
if (demangling && firstBracketName) {
const char * const plus = strchr(firstBracketName, '+');
if (plus && (plus>(firstBracketName+1))) {
char input_buffer[512]= {0}; char input_buffer[512]= {0};
strncpy(input_buffer, firstBracket+1, plus-firstBracket-1); strncpy(input_buffer, firstBracketName+1, plus-firstBracketName-1);
char output_buffer[1024]= {0}; char output_buffer[1024]= {0};
size_t length = GetArrayLength(output_buffer); size_t length = GetArrayLength(output_buffer);
int status=0; int status=0;
realname = abi::__cxa_demangle(input_buffer, output_buffer, &length, &status); // non-NULL on success realname = abi::__cxa_demangle(input_buffer, output_buffer, &length, &status); // non-NULL on success
} }
} }
fprintf(f, "#%d 0x",
fprintf(f, "%d. %s\n", i-offset);
i-offset, (realname) ? realname : symbolstrings[i]); if (padLen>0)
fprintf(f, "%0*d",
padLen, 0);
if (realname) {
fprintf(f, "%.*s in %s\n",
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
realname);
}
else {
fprintf(f, "%.*s in %.*s\n",
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
(int)(firstBracketAddress-symbol), symbol);
}
} }
free(symbolstrings); free(symbolstrings);
} else { } else {
fprintf(f, "Callstack could not be obtained\n"); fputs("Callstack could not be obtained\n", f);
} }
#endif #endif
} }
@ -269,26 +290,27 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * /*context*
{ {
const char * const signame=signal_name(signo); const char * const signame=signal_name(signo);
bool bPrintCallstack=true; bool bPrintCallstack=true;
FILE* f=stderr;
switch (signo) { switch (signo) {
case SIGILL: case SIGILL:
fprintf(stderr, "Internal error (caught signal %d=%s at 0x%p)\n", fprintf(f, "Internal error (caught signal %d=%s at 0x%p)\n",
signo, signame, info->si_addr); signo, signame, info->si_addr);
break; break;
case SIGFPE: case SIGFPE:
fprintf(stderr, "Internal error (caught signal %d=%s at 0x%p)\n", fprintf(f, "Internal error (caught signal %d=%s at 0x%p)\n",
signo, signame, info->si_addr); signo, signame, info->si_addr);
break; break;
case SIGSEGV: case SIGSEGV:
fprintf(stderr, "Internal error (caught signal %d=%s at 0x%p)\n", fprintf(f, "Internal error (caught signal %d=%s at 0x%p)\n",
signo, signame, info->si_addr); signo, signame, info->si_addr);
break; break;
/* /*
case SIGBUS: case SIGBUS:
fprintf(stderr, "Internal error (caught signal %d=%s at 0x%p)\n", fprintf(f, "Internal error (caught signal %d=%s at 0x%p)\n",
signo, signame, info->si_addr); signo, signame, info->si_addr);
break; break;
case SIGTRAP: case SIGTRAP:
fprintf(stderr, "Internal error (caught signal %d=%s at 0x%p)\n", fprintf(f, "Internal error (caught signal %d=%s at 0x%p)\n",
signo, signame, info->si_addr); signo, signame, info->si_addr);
break; break;
*/ */
@ -296,13 +318,13 @@ static void CppcheckSignalHandler(int signo, siginfo_t * info, void * /*context*
bPrintCallstack=false; bPrintCallstack=false;
break; break;
default: default:
fprintf(stderr, "Internal error (caught signal %d)\n", fprintf(f, "Internal error (caught signal %d)\n",
signo); signo);
break; break;
} }
if (bPrintCallstack) { if (bPrintCallstack) {
print_stacktrace(stderr, false); print_stacktrace(f, true);
fprintf(stderr, "Please report this to the cppcheck developers!\n"); fputs("\nPlease report this to the cppcheck developers!\n", f);
} }
abort(); abort();
} }