aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 2df17727ef858b06e7fcda5ae1a8702d11c001b6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# preload-libbt

`preload-libbt` is a utility library for some very special occasions.

It aims to extract a backtrace when a program *segfaults*, on machines where
[`ptrace(2)`][ptrace] syscalls are restricted, and hence launching the program
under *gdb* or attaching wth *gdb* is not possible.

The library must be `LD_PRELOAD`ed, which then installs a signal handler that
dumps a stacktrace. For it to work the program must adhere to the following
rules:

- The program must not override the installed signal handler.
- If the program overrides the signal handler, it needs to implement chaining
  signal handlers properly.

The preload library `libbt.so` is build with the default make target.
```
> make
cc -o libbt.so bt.c -shared -fPIC -static-libgcc -ldl -Wall -Wextra -g
```

## Concept

The library is based on the following features.

- Global signal disposition for `SIGSEGV`.
- *Alternate* signal stacks.

The signal handler for `SIGSEGV` is directly executed in the thread generating
the *segfault*. This is fine as long as the segfault is generated from anything
other than a *stackoverflow*. To also support this case, the library installs
an *alternate* signal stack with [`sigaltstack(2)`][sigaltstack] for each
thread by wrapping the [`pthread_create(3)`][pthread_create] call.

Support for threads created with raw [`clone(2)`][clone] calls is not
supported.

The examples `recurse1.c` and `recurse2.c` demonstrate the handling for
stackoverflows.

## Examples

The following gives an example and shows how a stacktrace dump looks like.
```
cc -o libbt.so bt.c -shared -fPIC -ldl
cc -o raise1 example/raise1.c -rdynamic
LD_PRELOAD=./libbt.so ./raise1

[BT:INFO]: installed signal handler
[BT:INFO]: caught signal 11
# 0 [  0x7f53b9e203f4] /usr/lib/libc.so.6+0x963f4
# 1 [  0x7f53b9dc7120] gsignal+0x20 /usr/lib/libc.so.6+0x3d100
# 2 [  0x55748166c147] foo+0xe raise1+0x1139
# 3 [  0x55748166c158] bar+0xe raise1+0x114a
# 4 [  0x55748166c169] qux+0xe raise1+0x115b
# 5 [  0x55748166c17a] main+0xe raise1+0x116c
# 6 [  0x7f53b9dafe08] /usr/lib/libc.so.6+0x25e08
# 7 [  0x7f53b9dafecc] __libc_start_main+0x8c /usr/lib/libc.so.6+0x25e40
# 8 [  0x55748166c065] _start+0x25 raise1+0x1040
```

Alternatively one can run `make run`, to run all examples under `example/`.

## License
This project is licensed under the MIT license.

[clone]: https://www.man7.org/linux/man-pages/man2/clone.2.html
[ptrace]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
[sigaltstack]: https://www.man7.org/linux/man-pages/man2/sigaltstack.2.html
[pthread_create]: https://www.man7.org/linux/man-pages/man3/pthread_create.3.html