| 302 | } |
| 303 | |
| 304 | [[gnu::noinline]] std::string DumpStack() { |
| 305 | const size_t max_stack_depth = 64; |
| 306 | void *addrs[max_stack_depth] = {}; |
| 307 | |
| 308 | std::ostringstream stack; |
| 309 | |
| 310 | char **symbols; |
| 311 | int skips = 0; |
| 312 | |
| 313 | // the linker requires -rdynamic for non-exported symbols |
| 314 | int cnt = backtrace(addrs, max_stack_depth); |
| 315 | |
| 316 | // in some cases the bottom of the stack is NULL - not useful at all, remove. |
| 317 | while (cnt > 0 && !addrs[cnt - 1]) { |
| 318 | cnt--; |
| 319 | } |
| 320 | |
| 321 | // The return addresses point to the next instruction after its call, |
| 322 | // so adjust them by -1 |
| 323 | for (int i = 0; i < cnt; i++) { |
| 324 | if (addrs[i] != trap_ip) { |
| 325 | addrs[i] = |
| 326 | reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(addrs[i]) - 1); |
| 327 | } |
| 328 | } |
| 329 | |
| 330 | symbols = backtrace_symbols(addrs, cnt); |
| 331 | if (!symbols) { |
| 332 | return "ERROR: backtrace_symbols() failed\n"; |
| 333 | } |
| 334 | |
| 335 | // Triggered by a signal? (trap_ip is set) |
| 336 | if (trap_ip) { |
| 337 | // addrs[0]: DumpStack() <- this function calling backtrace() |
| 338 | // addrs[1]: TrapHandler() |
| 339 | // addrs[2]: sigaction in glibc, or pthread signal handler |
| 340 | // addrs[3]: the trigerring instruction pointer *or* its caller |
| 341 | // (depending on the kernel behavior?) |
| 342 | if (addrs[3] == trap_ip) { |
| 343 | skips = 3; |
| 344 | } else { |
| 345 | skips = 2; |
| 346 | addrs[2] = trap_ip; |
| 347 | } |
| 348 | } else { |
| 349 | // LOG(FATAL) or CHECK() failed |
| 350 | // addrs[0]: DumpStack() <- this function calling backtrace() |
| 351 | // addrs[1]: GoPanic() |
| 352 | // addrs[2]: caller of GoPanic() |
| 353 | skips = 2; |
| 354 | while (skips < cnt && SkipSymbol(symbols[skips])) { |
| 355 | skips++; |
| 356 | } |
| 357 | } |
| 358 | |
| 359 | stack << "Backtrace (recent calls first) ---" << std::endl; |
| 360 | |
| 361 | for (int i = skips; i < cnt; i++) { |
no test coverage detected