Skip to content

Instantly share code, notes, and snippets.

@awreece
Last active December 18, 2015 00:59
Show Gist options
  • Save awreece/5700700 to your computer and use it in GitHub Desktop.
Save awreece/5700700 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#ifdef WITH_UNWIND
#define UNW_LOCAL_ONLY
#include <libunwind.h>
void show_backtrace (void) {
unw_cursor_t cursor; unw_context_t uc;
unw_word_t ip, sp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
while (unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
printf ("ip = %lx, sp = %lx\n", (long) ip, (long) sp);
}
}
#endif // WITH_UNWIND
int bar(int x) {
#ifdef WITH_UNWIND
show_backtrace();
#endif // WITH_UNWIND
__asm__("int $3");
return 1;
}
// Define a function named name which calls next.
//
// i.e: `make_func(foo, bar)` would define the function:
//
// int foo(int x) {
// return x * bar(x-1);
// }
//
// This allows us to briefly define several nested functions so we have a
// non-trivial stacktrace.
#define make_func(name, next) int name(int x) { return x * next(x-1); }
make_func(foo1, bar);
make_func(foo2, foo1);
make_func(foo3, foo2);
make_func(foo4, foo3);
make_func(foo5, foo4);
make_func(foo6, foo5);
int main() {
foo6(20);
return 0;
}
$ gcc -g -fomit-frame-pointer -DWITH_UNWIND get_stacktrace.c
$ ./a.out
ip = 10e12ed19, sp = 7fff51ad1970
ip = 10e12ed3a, sp = 7fff51ad1990
ip = 10e12ed5a, sp = 7fff51ad19b0
ip = 10e12ed7a, sp = 7fff51ad19d0
ip = 10e12ed9a, sp = 7fff51ad19f0
ip = 10e12edba, sp = 7fff51ad1a10
ip = 10e12edda, sp = 7fff51ad1a30
ip = 10e12edf2, sp = 7fff51ad1a50
$ gdb a.out
... <snip> ...
(gdb) r
... <snip> ...
(gdb) bt
#0 bar (x=14) at temp.c:24
#1 0x0000000100000d3a in foo1 (x=15) at temp.c:27
$ lldb a.out
(lldb) r
... <snip> ...
(lldb) bt
* thread #1: tid = 0x1c03, 0x0000000100000d1a a.out`bar(x=14) + 14 at temp.c:24, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
frame #0: 0x0000000100000d1a a.out`bar(x=14) + 14 at temp.c:24
frame #1: 0x0000000100000d3a a.out`foo1(x=15) + 22 at temp.c:27
frame #2: 0x0000000100000d5a a.out`foo2(x=16) + 22 at temp.c:28
frame #3: 0x0000000100000d7a a.out`foo3(x=17) + 22 at temp.c:29
frame #4: 0x0000000100000d9a a.out`foo4(x=18) + 22 at temp.c:30
frame #5: 0x0000000100000dba a.out`foo5(x=19) + 22 at temp.c:31
frame #6: 0x0000000100000dda a.out`foo6(x=20) + 22 at temp.c:32
frame #7: 0x0000000100000df2 a.out`main + 14 at temp.c:35
frame #8: 0x00007fff89f197e1 libdyld.dylib`start + 1
# dtrace -n 'pid$target::bar:entry { @[ustack()] = count(); }' -c ./a.out
... <snip> ...
a.out`bar
a.out`foo1+0x16
a.out`0x1
1
# Modify the binary slightly to while (1); instead of __asm__("int $3");
# ./a.out &
# spindump 92595
... <snip> ...
Process: a.out [92595]
Path: ./a.out
Architecture: x86_64
Parent: bash [92528]
UID: 0
Task size: 136 pages
CPU Time: 10.248s
Thread 0x413ad priority 31 cpu time 10.248s
1026 bar + 13 (a.out) [0x106810d29]
1026 <executing in user space>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment