- C 97.9%
- Makefile 2.1%
| .gitignore | Add .gitignore | |
| GNUmakefile | Optional stack dump | |
| hexdump.c | Tweaks, warning fixes | |
| hexdump.h | Optional stack dump | |
| LICENCE | README and LICENCE | |
| README.md | README tweaks | |
| tracecrash.c | Tweaks | |
| unwind.c | Optional stack dump | |
| unwind.h | Unwinding using libunwind-ptrace now works | |
tracecrash
What is it?
tracecrash is a just-in-time debugger. For most of the process
lifetime, it does as little as possible, only attaching to child threads
and processes as they are created. If one of them receives a "crashing"
signal (currently chosen as SIGSEGV, SIGBUS, SIGILL, or
SIGTRAP), tracecrash produces a backtrace on the standard output.
What does it look like?
$ cat crash.c
void crash(void) { *(double*)42 = 42; }
$ R CMD SHLIB crash.c
<compiler output omitted>
$ ./tracecrash R -q -s -e 'dyn.load("crash.so"); .C("crash")'
-----------------------------------8<-----------------------------------
PID 8864 received crashing signal 11
rax=4045000000000000 rbx=000056166e1a12a8 rcx=00005616701178b0 rdx=00007f39740acc1c
rsi=000056166e169440 rdi=0000000000000000 rbp=00005616701179c8 rsp=00007ffee4c9b218
r8=わ0000000000000007 r9=わ0000000000000001 r10=わ0000000000000000 r11=わ0000000000000000
r12=00007ffee4c9b3e0 r13=000056166e169440 r14=わ0000561670117958 r15=000056166e169440
ip = 7f396f01c107, sp = 7ffee4c9b218 [crash+7]
ip = 7f3973f023e9, sp = 7ffee4c9b220 [Rf_NewFrameConfirm+26969]
ip = 7f3973f5809d, sp = 7ffee4c9b830 [Rf_eval+2013]
ip = 7f3973f8c161, sp = 7ffee4c9ba80 [Rf_ReplIteration+513]
ip = 7f3973f8c4d0, sp = 7ffee4c9bac0 [Rf_ReplIteration+1392]
ip = 7f3973f8c588, sp = 7ffee4c9cb10 [run_Rmainloop+72]
ip = 56166dca907b, sp = 7ffee4c9cb20 [main+27]
ip = 7f3973c4624a, sp = 7ffee4c9cb30 [__libc_init_first+138]
ip = 7f3973c46305, sp = 7ffee4c9cbd0 [__libc_start_main+133]
ip = 56166dca90b1, sp = 7ffee4c9cc20 [_start+33]
-----------------------------------8<-----------------------------------
*** caught segfault ***
address 0x2a, cause 'memory not mapped'
Traceback:
1: .C("crash")
An irrecoverable exception occurred. R is aborting now ...
<R raises the signal again, so the output is duplicated>
There is an optional stack dump feature. If the program is compiled with
a positive -DHEXDUMP_LIMIT, up to this many bytes from the stack are
dumped together with the call frames:
ip = 7f1b6bb8c4d0, sp = 7ffe45118da0 [Rf_ReplIteration+1392]
7ffe45118da0 01 00 00 00 01 00 00 00 00 00 00 00 64 79 6e 2e dyn.
7ffe45118db0 6c 6f 61 64 28 22 63 72 61 73 68 2e 73 6f 22 29 load("crash.so")
7ffe45118dc0 3b 20 2e 43 28 22 63 72 61 73 68 22 29 0a 00 00 ; .C("crash")
7ffe45118dd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Any problems with this approach?
- For now,
tracecrashonly supportsamd64Linux. Support for other architectures is easy to add as long as it exists in libunwind. Support for other Unix-like operating systems will require separating theptrace()interface due to it being not portable. On Windows, better usecatchsegvfrom Dr. Mingw, which served as the inspiration for this program. - Since
tracecrashusesptrace(), it will prevent other processes from attaching to the target process or any of its children. If another tracer attaches to a child first, it will preventtracecrashfrom handling its crashes or its children. tracecrashwill wait for all tracees to terminate, not only the target program. This includes any background processes created during the lifetime of the process tree: the tracer may terminate much later than the traced child.tracecrashwill forward the exit code of the target program. If the target program is terminated by a signal,tracecrashwill exit with code0x80 | signal. If the parent cares aboutWIFEXITEDvs.WIFSIGNALED, it will notice the difference.
How do I build the program?
Make sure that libunwind is installed, including the development
headers and pkg-config files, and type make.
Patches?
Welcome.
Licence
Copyright 2024 Ivan Krylov
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.