/******************************************************************************* * libretroshare/src/util: smallobject.h * * * * libretroshare: retroshare core library * * * * Copyright (C) 2016 Gioacchino Mazzurco * * Copyright (C) 2008 Timo Bingmann http://idlebox.net/ * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * 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 Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see . * * * *******************************************************************************/ #ifndef _STACKTRACE_H_ #define _STACKTRACE_H_ #include #if defined(__linux__) && defined(__GLIBC__) #include #include #include /** Print a demangled stack backtrace of the caller function to FILE* out. */ static inline 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, " \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\n", symbollist[i], funcname, begin_offset); } else { // demangling failed. Output function name as a C function with // no arguments. fprintf(out, " %s : %s()+%s\n", symbollist[i], begin_name, begin_offset); } } else { // couldn't parse the line? print the whole line. fprintf(out, " %s\n", symbollist[i]); } } free(funcname); free(symbollist); } #else // defined(__linux__) && defined(__GLIBC__) static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63) { (void) max_frames; fprintf(out, "TODO: 2016/01/01 print_stacktrace not implemented yet for WINDOWS_SYS and ANDROID\n"); } #endif // defined(__linux__) && defined(__GLIBC__) #endif // _STACKTRACE_H_