2014-07-11 Edward Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / libgo / runtime / go-callers.c
blob213686933d9c5adb2ae3ede364c840c05183bf9b
1 /* go-callers.c -- get callers for Go.
3 Copyright 2012 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
7 #include "config.h"
9 #include "backtrace.h"
11 #include "runtime.h"
12 #include "array.h"
14 /* This is set to non-zero when calling backtrace_full. This is used
15 to avoid getting hanging on a recursive lock in dl_iterate_phdr on
16 older versions of glibc when a SIGPROF signal arrives while
17 collecting a backtrace. */
19 uint32 runtime_in_callers;
21 /* Argument passed to callback function. */
23 struct callers_data
25 Location *locbuf;
26 int skip;
27 int index;
28 int max;
31 /* Callback function for backtrace_full. Just collect the locations.
32 Return zero to continue, non-zero to stop. */
34 static int
35 callback (void *data, uintptr_t pc, const char *filename, int lineno,
36 const char *function)
38 struct callers_data *arg = (struct callers_data *) data;
39 Location *loc;
41 /* Skip split stack functions. */
42 if (function != NULL)
44 const char *p;
46 p = function;
47 if (__builtin_strncmp (p, "___", 3) == 0)
48 ++p;
49 if (__builtin_strncmp (p, "__morestack_", 12) == 0)
50 return 0;
52 else if (filename != NULL)
54 const char *p;
56 p = strrchr (filename, '/');
57 if (p == NULL)
58 p = filename;
59 if (__builtin_strncmp (p, "/morestack.S", 12) == 0)
60 return 0;
63 /* Skip thunks and recover functions. There is no equivalent to
64 these functions in the gc toolchain, so returning them here means
65 significantly different results for runtime.Caller(N). */
66 if (function != NULL)
68 const char *p;
70 p = __builtin_strchr (function, '.');
71 if (p != NULL && __builtin_strncmp (p + 1, "$thunk", 6) == 0)
72 return 0;
73 p = __builtin_strrchr (function, '$');
74 if (p != NULL && __builtin_strcmp(p, "$recover") == 0)
75 return 0;
78 if (arg->skip > 0)
80 --arg->skip;
81 return 0;
84 loc = &arg->locbuf[arg->index];
85 loc->pc = pc;
87 /* The libbacktrace library says that these strings might disappear,
88 but with the current implementation they won't. We can't easily
89 allocate memory here, so for now assume that we can save a
90 pointer to the strings. */
91 loc->filename = runtime_gostringnocopy ((const byte *) filename);
92 loc->function = runtime_gostringnocopy ((const byte *) function);
94 loc->lineno = lineno;
95 ++arg->index;
97 /* There is no point to tracing past certain runtime functions.
98 Stopping the backtrace here can avoid problems on systems that
99 don't provide proper unwind information for makecontext, such as
100 Solaris (http://gcc.gnu.org/PR52583 comment #21). */
101 if (function != NULL)
103 if (__builtin_strcmp (function, "makecontext") == 0)
104 return 1;
105 if (filename != NULL)
107 const char *p;
109 p = strrchr (filename, '/');
110 if (p == NULL)
111 p = filename;
112 if (__builtin_strcmp (p, "/proc.c") == 0)
114 if (__builtin_strcmp (function, "kickoff") == 0
115 || __builtin_strcmp (function, "runtime_mstart") == 0
116 || __builtin_strcmp (function, "runtime_main") == 0)
117 return 1;
122 return arg->index >= arg->max;
125 /* Error callback. */
127 static void
128 error_callback (void *data __attribute__ ((unused)),
129 const char *msg, int errnum)
131 if (errnum != 0)
132 runtime_printf ("%s errno %d\n", msg, errnum);
133 runtime_throw (msg);
136 /* Gather caller PC's. */
138 int32
139 runtime_callers (int32 skip, Location *locbuf, int32 m)
141 struct callers_data data;
143 data.locbuf = locbuf;
144 data.skip = skip + 1;
145 data.index = 0;
146 data.max = m;
147 runtime_xadd (&runtime_in_callers, 1);
148 backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback,
149 &data);
150 runtime_xadd (&runtime_in_callers, -1);
151 return data.index;
154 int Callers (int, struct __go_open_array)
155 __asm__ (GOSYM_PREFIX "runtime.Callers");
158 Callers (int skip, struct __go_open_array pc)
160 Location *locbuf;
161 int ret;
162 int i;
164 locbuf = (Location *) runtime_mal (pc.__count * sizeof (Location));
166 /* In the Go 1 release runtime.Callers has an off-by-one error,
167 which we can not correct because it would break backward
168 compatibility. Normally we would add 1 to SKIP here, but we
169 don't so that we are compatible. */
170 ret = runtime_callers (skip, locbuf, pc.__count);
172 for (i = 0; i < ret; i++)
173 ((uintptr *) pc.__values)[i] = locbuf[i].pc;
175 return ret;