Merge from branches/gcc-4_8-branch up to rev 203510.
[official-gcc.git] / gcc-4_8-branch / libgo / runtime / go-callers.c
blob291dfd0d666764296c13e8b9af6baa50486788d6
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 /* Argument passed to callback function. */
16 struct callers_data
18 Location *locbuf;
19 int skip;
20 int index;
21 int max;
24 /* Callback function for backtrace_full. Just collect the locations.
25 Return zero to continue, non-zero to stop. */
27 static int
28 callback (void *data, uintptr_t pc, const char *filename, int lineno,
29 const char *function)
31 struct callers_data *arg = (struct callers_data *) data;
32 Location *loc;
34 /* Skip split stack functions. */
35 if (function != NULL)
37 const char *p;
39 p = function;
40 if (__builtin_strncmp (p, "___", 3) == 0)
41 ++p;
42 if (__builtin_strncmp (p, "__morestack_", 12) == 0)
43 return 0;
45 else if (filename != NULL)
47 const char *p;
49 p = strrchr (filename, '/');
50 if (p == NULL)
51 p = filename;
52 if (__builtin_strncmp (p, "/morestack.S", 12) == 0)
53 return 0;
56 /* Skip thunks and recover functions. There is no equivalent to
57 these functions in the gc toolchain, so returning them here means
58 significantly different results for runtime.Caller(N). */
59 if (function != NULL)
61 const char *p;
63 p = __builtin_strchr (function, '.');
64 if (p != NULL && __builtin_strncmp (p + 1, "$thunk", 6) == 0)
65 return 0;
66 p = __builtin_strrchr (function, '$');
67 if (p != NULL && __builtin_strcmp(p, "$recover") == 0)
68 return 0;
71 if (arg->skip > 0)
73 --arg->skip;
74 return 0;
77 loc = &arg->locbuf[arg->index];
78 loc->pc = pc;
80 /* The libbacktrace library says that these strings might disappear,
81 but with the current implementation they won't. We can't easily
82 allocate memory here, so for now assume that we can save a
83 pointer to the strings. */
84 loc->filename = runtime_gostringnocopy ((const byte *) filename);
85 loc->function = runtime_gostringnocopy ((const byte *) function);
87 loc->lineno = lineno;
88 ++arg->index;
89 return arg->index >= arg->max;
92 /* Error callback. */
94 static void
95 error_callback (void *data __attribute__ ((unused)),
96 const char *msg, int errnum)
98 if (errnum != 0)
99 runtime_printf ("%s errno %d\n", msg, errnum);
100 runtime_throw (msg);
103 /* Gather caller PC's. */
105 int32
106 runtime_callers (int32 skip, Location *locbuf, int32 m)
108 struct callers_data data;
110 data.locbuf = locbuf;
111 data.skip = skip + 1;
112 data.index = 0;
113 data.max = m;
114 backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback,
115 &data);
116 return data.index;
119 int Callers (int, struct __go_open_array)
120 __asm__ (GOSYM_PREFIX "runtime.Callers");
123 Callers (int skip, struct __go_open_array pc)
125 Location *locbuf;
126 int ret;
127 int i;
129 locbuf = (Location *) runtime_mal (pc.__count * sizeof (Location));
131 /* In the Go 1 release runtime.Callers has an off-by-one error,
132 which we can not correct because it would break backward
133 compatibility. Normally we would add 1 to SKIP here, but we
134 don't so that we are compatible. */
135 ret = runtime_callers (skip, locbuf, pc.__count);
137 for (i = 0; i < ret; i++)
138 ((uintptr *) pc.__values)[i] = locbuf[i].pc;
140 return ret;