2013-02-11 Sebastian Huber <sebastian.huber@embedded-brains.de>
[official-gcc.git] / libgo / runtime / go-callers.c
blobdd1cf7909b6cd71f2c8e921f4fc7a6d57bfa4d40
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 if (arg->skip > 0)
58 --arg->skip;
59 return 0;
62 loc = &arg->locbuf[arg->index];
63 loc->pc = pc;
65 /* The libbacktrace library says that these strings might disappear,
66 but with the current implementation they won't. We can't easily
67 allocate memory here, so for now assume that we can save a
68 pointer to the strings. */
69 loc->filename = runtime_gostringnocopy ((const byte *) filename);
70 loc->function = runtime_gostringnocopy ((const byte *) function);
72 loc->lineno = lineno;
73 ++arg->index;
74 return arg->index >= arg->max;
77 /* Error callback. */
79 static void
80 error_callback (void *data __attribute__ ((unused)),
81 const char *msg, int errnum)
83 if (errnum != 0)
84 runtime_printf ("%s errno %d\n", msg, errnum);
85 runtime_throw (msg);
88 /* Gather caller PC's. */
90 int32
91 runtime_callers (int32 skip, Location *locbuf, int32 m)
93 struct callers_data data;
95 data.locbuf = locbuf;
96 data.skip = skip + 1;
97 data.index = 0;
98 data.max = m;
99 backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback,
100 &data);
101 return data.index;
104 int Callers (int, struct __go_open_array)
105 __asm__ (GOSYM_PREFIX "runtime.Callers");
108 Callers (int skip, struct __go_open_array pc)
110 Location *locbuf;
111 int ret;
112 int i;
114 locbuf = (Location *) runtime_mal (pc.__count * sizeof (Location));
116 /* In the Go 1 release runtime.Callers has an off-by-one error,
117 which we can not correct because it would break backward
118 compatibility. Normally we would add 1 to SKIP here, but we
119 don't so that we are compatible. */
120 ret = runtime_callers (skip, locbuf, pc.__count);
122 for (i = 0; i < ret; i++)
123 ((uintptr *) pc.__values)[i] = locbuf[i].pc;
125 return ret;