| 29 | #include <execinfo.h> |
| 30 | |
| 31 | void print_stacktrace(FILE* output, int start_idx, bool demangling, int maxdepth, bool omit_above_own) |
| 32 | { |
| 33 | // 32 vs. 64bit |
| 34 | static constexpr auto ADDRESSDISPLAYLENGTH = (sizeof(long) == 8) ? 12 : 8; |
| 35 | |
| 36 | void *callstackArray[32]= {nullptr}; // the less resources the better... |
| 37 | const int currentdepth = backtrace(callstackArray, static_cast<int>(getArrayLength(callstackArray))); |
| 38 | if (currentdepth == 0) { |
| 39 | fputs("Callstack could not be obtained (backtrace)\n", output); |
| 40 | return; |
| 41 | } |
| 42 | if (currentdepth == getArrayLength(callstackArray)) { |
| 43 | fputs("Callstack might be truncated\n", output); |
| 44 | } |
| 45 | // set offset to 1 to omit the printing function itself |
| 46 | int offset=start_idx+1; // some entries on top are within our own exception handling code or libc |
| 47 | if (maxdepth<0) |
| 48 | maxdepth=currentdepth-offset; |
| 49 | else |
| 50 | maxdepth = std::min(maxdepth, currentdepth); |
| 51 | |
| 52 | char **symbolStringList = backtrace_symbols(callstackArray, currentdepth); |
| 53 | if (!symbolStringList) { |
| 54 | fputs("Callstack could not be obtained (backtrace_symbols)\n", output); |
| 55 | return; |
| 56 | } |
| 57 | |
| 58 | fputs("Callstack:\n", output); |
| 59 | bool own_code = false; |
| 60 | char demangle_buffer[2048]= {0}; |
| 61 | bool no_address = false; |
| 62 | for (int i = offset; i < maxdepth; ++i) { |
| 63 | const char * const symbolString = symbolStringList[i]; |
| 64 | // TODO: implement parsing for __APPLE__ |
| 65 | // 0 test-signalhandler 0x0000000100dbf42c _Z16print_stacktraceP7__sFILEibib + 124 |
| 66 | |
| 67 | /* |
| 68 | * examples: |
| 69 | * ./test-signalhandler(_Z16print_stacktraceP8_IO_FILEibib+0xa1) [0x55cb65e41464] |
| 70 | * ./test-signalhandler(+0xf9d9) [0x55cb65e3c9d9] |
| 71 | */ |
| 72 | |
| 73 | // skip all leading libc symbols so the first symbol is our code |
| 74 | if (omit_above_own && !own_code) { |
| 75 | if (strstr(symbolString, "/libc.so.6") != nullptr) |
| 76 | continue; |
| 77 | own_code = true; |
| 78 | offset = i; // make sure the numbering is continuous if we omit frames |
| 79 | } |
| 80 | const char * realnameString = nullptr; |
| 81 | if (demangling) { |
| 82 | const char * const firstBracketName = strchr(symbolString, '('); |
| 83 | if (firstBracketName) { |
| 84 | const char * const plus = strchr(firstBracketName, '+'); |
| 85 | if (plus && (plus>(firstBracketName+1))) { |
| 86 | char input_buffer[1024]= {0}; |
| 87 | strncpy(input_buffer, firstBracketName+1, plus-firstBracketName-1); |
| 88 | size_t length = getArrayLength(demangle_buffer); |