1 /*
2 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
5 * This file is part of TUD:OS and distributed under the terms of the
6 * GNU Lesser General Public License 2.1.
7 * Please see the COPYING-LGPL-2.1 file for details.
8 */
9 #include <l4/util/backtrace.h>
10
11 #include <unwind.h>
12 #include <stdlib.h>
13 #include <stdint.h>
14
15 #if defined NOT_FOR_L4 && defined __PIC__
16
17 #include <dlfcn.h>
18
19 static _Unwind_Reason_Code (*uw_bt) (_Unwind_Trace_Fn, void *);
20 static _Unwind_Ptr (*uw_getpc) (struct _Unwind_Context *);
21
22 static void
init(void)23 init (void)
24 {
25 void *handle = dlopen ("libgcc_s.so.1", 0);
26
27 if (handle == NULL)
28 return;
29
30 uw_bt = dlsym (handle, "_Unwind_Backtrace");
31 uw_getpc = dlsym (handle, "_Unwind_GetIP");
32 if (uw_getpc == NULL)
33 uw_bt = NULL;
34 }
35 #else
36
37 #define uw_getgr _Unwind_GetGR
38 #define uw_getpc _Unwind_GetIP
39 #define uw_bt _Unwind_Backtrace
40 #define uw_getcfa _Unwind_GetCFA
41
42 #endif
43
44 struct Bt_arg
45 {
46 void **pc_array;
47 int cnt, max;
48 };
49
50 static _Unwind_Reason_Code
__bt_helper(struct _Unwind_Context * ctx,void * a)51 __bt_helper(struct _Unwind_Context *ctx, void *a)
52 {
53 struct Bt_arg *arg = a;
54
55 /* Skip first function, it is l4util_backtrace ... */
56 if (arg->cnt != -1)
57 arg->pc_array[arg->cnt] = (void *)(uintptr_t)uw_getpc (ctx);
58 if (++arg->cnt == arg->max)
59 return _URC_END_OF_STACK;
60
61 return _URC_NO_REASON;
62 }
63
64
65 int
l4util_backtrace(void ** pc_array,int max)66 l4util_backtrace(void **pc_array, int max)
67 {
68 struct Bt_arg arg = { .pc_array = pc_array, .max = max, .cnt = -1 };
69
70 #if defined NOT_FOR_L4 && defined __PIC__
71 static int initialized = 0;
72 if (!initialized)
73 {
74 initialized = 1;
75 init();
76 }
77
78 if (uw_bt == NULL)
79 return 0;
80 #endif
81
82 if (max >= 1)
83 uw_bt (__bt_helper, &arg);
84
85 if (arg.cnt > 1 && arg.pc_array[arg.cnt - 1] == (void*)0)
86 --arg.cnt;
87 return arg.cnt != -1 ? arg.cnt : 0;
88 }
89
90