Print a demangled stack backtrace of the caller function to FILE* out. */
| 56 | |
| 57 | /** Print a demangled stack backtrace of the caller function to FILE* out. */ |
| 58 | static inline void printStackTrace(std::ostream &eout = std::cerr) |
| 59 | { |
| 60 | #ifdef _WIN32 |
| 61 | // TODO add code for windows stack trace |
| 62 | #else |
| 63 | std::stringstream out; |
| 64 | // storage array for stack trace address data |
| 65 | std::array<void *, MAX_FRAMES + 1> addrlist; |
| 66 | // retrieve current stack addresses |
| 67 | int addrlen = |
| 68 | backtrace(reinterpret_cast<void **>(&addrlist), static_cast<int>(addrlist.size())); |
| 69 | |
| 70 | if (addrlen == 0) { |
| 71 | out << " <empty, possibly corrupt>\n"; |
| 72 | return; |
| 73 | } |
| 74 | |
| 75 | // resolve addresses into strings containing "filename(function+address)", |
| 76 | // this array must be free()-ed |
| 77 | char **symbollist = backtrace_symbols(reinterpret_cast<void *const *>(&addrlist), addrlen); |
| 78 | // allocate string which will be filled with the demangled function name |
| 79 | size_t funcnamesize = 256; |
| 80 | char *funcname = (char *)malloc(funcnamesize); |
| 81 | |
| 82 | // iterate over the returned symbol lines. skip the first, it is the |
| 83 | // address of this function. |
| 84 | for (int i = 1; i < addrlen; i++) { |
| 85 | char *begin_name = 0, *begin_offset = 0, *end_offset = 0; |
| 86 | |
| 87 | // find parentheses and +address offset surrounding the mangled name: |
| 88 | // ./module(function+0x15c) [0x8048a6d] |
| 89 | for (char *p = symbollist[i]; *p; ++p) { |
| 90 | if (*p == '(') { |
| 91 | begin_name = p; |
| 92 | } |
| 93 | else if (*p == '+') { |
| 94 | begin_offset = p; |
| 95 | } |
| 96 | else if (*p == ')' && begin_offset) { |
| 97 | end_offset = p; |
| 98 | break; |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | if (begin_name && begin_offset && end_offset && begin_name < begin_offset) { |
| 103 | *begin_name++ = '\0'; |
| 104 | *begin_offset++ = '\0'; |
| 105 | *end_offset = '\0'; |
| 106 | // mangled name is now in [begin_name, begin_offset) and caller |
| 107 | // offset in [begin_offset, end_offset). now apply |
| 108 | // __cxa_demangle(): |
| 109 | int status; |
| 110 | char *ret = |
| 111 | abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status); |
| 112 | |
| 113 | if (status == 0) { |
| 114 | funcname = ret; // use possibly realloc()-ed string |
| 115 | out << " " << symbollist[i] << " : " << funcname << "+" << begin_offset |
no test coverage detected