Back to index

texmacs  1.0.7.15
stack_trace.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : stack_trace.cpp
00004 * DESCRIPTION: Debugging facilities
00005 * COPYRIGHT  : (C) 2008  Timo Bingmann from http://idlebox.net
00006 *              (C) 2011  Joris van der Hoeven
00007 *******************************************************************************
00008 * This software falls under the GNU general public license version 3 or later.
00009 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00010 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00011 ******************************************************************************/
00012 
00013 #include "sys_utils.hpp"
00014 
00015 #ifdef USE_STACK_TRACE
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <execinfo.h>
00019 #include <cxxabi.h>
00020 
00021 string
00022 get_stacktrace (unsigned int max_frames) {
00023   string r;
00024   r << "Backtrace of C++ stack:\n";
00025   
00026   // storage array for stack trace address data
00027   void* addrlist[max_frames+1];
00028 
00029   // retrieve current stack addresses
00030   int addrlen = backtrace (addrlist, sizeof (addrlist) / sizeof (void*));
00031 
00032   if (addrlen == 0) {
00033     r << "  <empty, possibly corrupt>\n";
00034     return r;
00035   }
00036 
00037   // resolve addresses into strings containing "filename(function+address)",
00038   // this array must be free()-ed
00039   char** symbollist = backtrace_symbols (addrlist, addrlen);
00040 
00041   // allocate string which will be filled with the demangled function name
00042   size_t funcnamesize = 1024;
00043   char* funcname = (char*) malloc (funcnamesize);
00044 
00045   // iterate over the returned symbol lines. skip the first, it is the
00046   // address of this function.
00047   for (int i = 1; i < addrlen; i++) {
00048     char *begin_name = 0, *end_name = 0, *begin_offset = 0, *end_offset = 0;
00049 
00050     // find parentheses and +address offset surrounding the mangled name:
00051     // ./module(function+0x15c) [0x8048a6d]
00052     for (char *p = symbollist[i]; *p; ++p) {
00053       if (*p == '(')
00054         begin_name = p;
00055       else if (*p == '+') {
00056         end_name = p;
00057         begin_offset = p;
00058       }
00059       else if (*p == ')' && begin_offset) {
00060         end_offset = p;
00061         break;
00062       }
00063     }
00064     
00065     bool ok= begin_name && end_offset && begin_name < end_name;
00066     if (ok) {
00067       begin_name++;
00068       begin_offset++;
00069     }
00070     else if (begin_offset) {
00071       begin_offset++;
00072       while (begin_offset[0] == ' ') begin_offset++;
00073       for (char* p= begin_offset; true; ++p)
00074         if (*p == '\0') {
00075           end_offset = p;
00076           break;
00077         }
00078       while (end_name[-1] == ' ') end_name--;
00079       for (char* p= end_name; *p; --p)
00080         if (p == symbollist[i] || p[-1] == ' ') {
00081           begin_name = p;
00082           break;
00083         }
00084       ok= begin_offset < end_offset && begin_name < end_name;
00085     }
00086 
00087     if (ok) {
00088       while (end_name[-1] == ' ') end_name--;
00089       while (begin_offset[0] == ' ') begin_offset++;
00090       begin_name[-1] = '\0';
00091       end_name[0] = '\0';
00092       begin_offset[-1] = '\0';
00093       end_offset[0] = '\0';
00094 
00095       // mangled name is now in [begin_name, end_name) and caller
00096       // offset in [begin_offset, end_offset). now apply
00097       // __cxa_demangle():
00098 
00099       int status;
00100       char* ret =
00101         abi::__cxa_demangle (begin_name, funcname, &funcnamesize, &status);
00102       if (status == 0) {
00103         funcname = ret; // use possibly realloc()-ed string
00104         r << "  " << symbollist[i]
00105           << " : " << funcname
00106           << " + " << begin_offset << "\n";
00107       }
00108       else {
00109         // demangling failed. Output function name as a C function with
00110         // no arguments.
00111         r << "  " << symbollist[i]
00112           << " : " << begin_name << "()"
00113           << " + " << begin_offset << "\n";
00114       }
00115     }
00116     else {
00117       // couldn't parse the line? print the whole line.
00118       r << "  " << symbollist[i] << "\n";
00119     }
00120   }
00121 
00122   free (funcname);
00123   free (symbollist);
00124   return r;
00125 }
00126 
00127 #else
00128 
00129 string
00130 get_stacktrace (unsigned int max_frames) {
00131   (void) max_frames;
00132   return "Backtrace of C++ stack not supported\n";
00133 }
00134 
00135 #endif