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