Last active
December 18, 2015 00:59
-
-
Save awreece/5700700 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ 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