Test.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/
  2. // published under the WTFPL v2.0
  3. #ifndef _STACKTRACE_H_
  4. #define _STACKTRACE_H_
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <execinfo.h>
  8. #include <cxxabi.h>
  9. /** Print a demangled stack backtrace of the caller function to FILE* out. */
  10. static inline void print_stacktrace( FILE *out = stdout, unsigned int max_frames = 3 )
  11. {
  12. fprintf( out, "stack trace:\n" );
  13. // storage array for stack trace address data
  14. void* addrlist[ max_frames + 1 ];
  15. // retrieve current stack addresses
  16. int addrlen = backtrace( addrlist, sizeof( addrlist ) / sizeof( void* ) );
  17. if( addrlen == 0 )
  18. {
  19. fprintf( out, " <empty, possibly corrupt>\n" );
  20. return;
  21. }
  22. // resolve addresses into strings containing "filename(function+address)",
  23. // this array must be free()-ed
  24. char** symbollist = backtrace_symbols( addrlist, addrlen );
  25. // allocate string which will be filled with the demangled function name
  26. size_t funcnamesize = 256;
  27. char* funcname = (char*)malloc( funcnamesize );
  28. // iterate over the returned symbol lines. skip the first, it is the
  29. // address of this function.
  30. for( int i = 1; i < addrlen; i++ )
  31. {
  32. char *begin_name = 0, *begin_offset = 0, *end_offset = 0;
  33. // find parentheses and +address offset surrounding the mangled name:
  34. // ./module(function+0x15c) [0x8048a6d]
  35. for( char *p = symbollist[ i ]; *p; ++p )
  36. {
  37. if( *p == '(' )
  38. begin_name = p;
  39. else if( *p == '+' )
  40. begin_offset = p;
  41. else if( *p == ')' && begin_offset )
  42. {
  43. end_offset = p;
  44. break;
  45. }
  46. }
  47. if( begin_name && begin_offset && end_offset
  48. && begin_name < begin_offset )
  49. {
  50. *begin_name++ = '\0';
  51. *begin_offset++ = '\0';
  52. *end_offset = '\0';
  53. // mangled name is now in [begin_name, begin_offset) and caller
  54. // offset in [begin_offset, end_offset). now apply
  55. // __cxa_demangle():
  56. int status;
  57. char* ret = abi::__cxa_demangle( begin_name,
  58. funcname, &funcnamesize, &status );
  59. if( status == 0 )
  60. {
  61. funcname = ret; // use possibly realloc()-ed string
  62. char line[ 256 ];
  63. sprintf( line, " %s : %s+%s\n",
  64. symbollist[ i ], funcname, begin_offset );
  65. int y = 0;
  66. }
  67. else
  68. {
  69. // demangling failed. Output function name as a C function with
  70. // no arguments.
  71. char line[ 256 ];
  72. sprintf( line, " %s : %s()+%s\n",
  73. symbollist[ i ], begin_name, begin_offset );
  74. int x = 0;
  75. }
  76. }
  77. else
  78. {
  79. // couldn't parse the line? print the whole line.
  80. char line[ 256 ];
  81. sprintf( line, " %s\n", symbollist[ i ] );
  82. int x = 0;
  83. }
  84. }
  85. free( funcname );
  86. free( symbollist );
  87. }
  88. #endif // _STACKTRACE_H_