| 507 | static bool gdbExtendedBacktrace(int const dumpFile, const ucontext_t *sigcontext) |
| 508 | #else |
| 509 | static bool gdbExtendedBacktrace(int const dumpFile) |
| 510 | #endif |
| 511 | { |
| 512 | /* |
| 513 | * Pointer to the stackframe of the function containing faulting |
| 514 | * instruction (assuming |
| 515 | * -fomit-frame-pointer has *not* been used). |
| 516 | * |
| 517 | * The frame pointer register (x86: %ebp, x64: %rbp) point's to the |
| 518 | * local variables of the current function (which are preceded by the |
| 519 | * previous frame pointer and the return address). Hence the |
| 520 | * additions to the frame-pointer register's content. |
| 521 | */ |
| 522 | void const *const frame = |
| 523 | #if defined(SA_SIGINFO) && defined(REG_RBP) |
| 524 | sigcontext ? (void *)(sigcontext->uc_mcontext.gregs[REG_RBP] + sizeof(greg_t) + sizeof(void (*)(void))) : nullptr; |
| 525 | #elif defined(SA_SIGINFO) && defined(REG_EBP) |
| 526 | sigcontext ? (void *)(sigcontext->uc_mcontext.gregs[REG_EBP] + sizeof(greg_t) + sizeof(void (*)(void))) : NULL; |
| 527 | #else |
| 528 | NULL; |
| 529 | #endif |
| 530 | |
| 531 | /* |
| 532 | * Faulting instruction. |
| 533 | */ |
| 534 | void (*instruction)(void) = |
| 535 | #if defined(SA_SIGINFO) && defined(REG_RIP) |
| 536 | sigcontext ? (void (*)(void))sigcontext->uc_mcontext.gregs[REG_RIP] : nullptr; |
| 537 | #elif defined(SA_SIGINFO) && defined(REG_EIP) |
| 538 | sigcontext ? (void (*)(void))sigcontext->uc_mcontext.gregs[REG_EIP] : NULL; |
| 539 | #else |
| 540 | NULL; |
| 541 | #endif |
| 542 | |
| 543 | // Spawn a GDB instance and retrieve a pipe to its stdin |
| 544 | int gdbPipe; |
| 545 | int status; |
| 546 | pid_t wpid; |
| 547 | // Retrieve a full stack backtrace |
| 548 | static const char gdbCommands[] = "thread apply all backtrace full\n" |
| 549 | |
| 550 | // Move to the stack frame where we triggered the crash |
| 551 | "frame 4\n" |
| 552 | |
| 553 | // Show the assembly code associated with that stack frame |
| 554 | "disassemble /m\n" |
| 555 | |
| 556 | // Show the content of all registers |
| 557 | "info registers\n" |
| 558 | "quit\n"; |
| 559 | const pid_t pid = execGdb(dumpFile, &gdbPipe); |
| 560 | if (pid == 0) |
| 561 | { |
| 562 | return false; |
| 563 | } |
| 564 | |
| 565 | // Disassemble the faulting instruction (if we know it) |
| 566 | if (instruction) |
no test coverage detected