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. */
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 __go_runtime_in_callers
;
21 /* Argument passed to callback function. */
32 /* Callback function for backtrace_full. Just collect the locations.
33 Return zero to continue, non-zero to stop. */
36 callback (void *data
, uintptr_t pc
, const char *filename
, int lineno
,
39 struct callers_data
*arg
= (struct callers_data
*) data
;
42 /* Skip split stack functions. */
48 if (__builtin_strncmp (p
, "___", 3) == 0)
50 if (__builtin_strncmp (p
, "__morestack_", 12) == 0)
53 else if (filename
!= NULL
)
57 p
= strrchr (filename
, '/');
60 if (__builtin_strncmp (p
, "/morestack.S", 12) == 0)
64 /* Skip thunks and recover functions. There is no equivalent to
65 these functions in the gc toolchain, so returning them here means
66 significantly different results for runtime.Caller(N). See also
67 similar code in runtime/mprof.go that strips out such functions
68 for block/mutex/memory profiles. */
69 if (function
!= NULL
&& !arg
->keep_thunks
)
73 p
= function
+ __builtin_strlen (function
);
74 while (p
> function
&& p
[-1] >= '0' && p
[-1] <= '9')
76 if (p
- function
> 7 && __builtin_strncmp (p
- 7, "..thunk", 7) == 0)
78 if (p
- function
> 3 && __builtin_strcmp (p
- 3, "..r") == 0)
80 if (p
- function
> 6 && __builtin_strncmp (p
- 6, "..stub", 6) == 0)
90 loc
= &arg
->locbuf
[arg
->index
];
92 /* On the call to backtrace_full the pc value was most likely
93 decremented if there was a normal call, since the pc referred to
94 the instruction where the call returned and not the call itself.
95 This was done so that the line number referred to the call
96 instruction. To make sure the actual pc from the call stack is
97 used, it is incremented here.
99 In the case of a signal, the pc was not decremented by
100 backtrace_full but still incremented here. That doesn't really
101 hurt anything since the line number is right and the pc refers to
102 the same instruction. */
106 /* The libbacktrace library says that these strings might disappear,
107 but with the current implementation they won't. We can't easily
108 allocate memory here, so for now assume that we can save a
109 pointer to the strings. */
110 loc
->filename
= runtime_gostringnocopy ((const byte
*) filename
);
111 loc
->function
= runtime_gostringnocopy ((const byte
*) function
);
113 loc
->lineno
= lineno
;
116 /* There is no point to tracing past certain runtime functions.
117 Stopping the backtrace here can avoid problems on systems that
118 don't provide proper unwind information for makecontext, such as
119 Solaris (http://gcc.gnu.org/PR52583 comment #21). */
120 if (function
!= NULL
)
122 if (__builtin_strcmp (function
, "makecontext") == 0)
124 if (filename
!= NULL
)
128 p
= strrchr (filename
, '/');
131 if (__builtin_strcmp (p
, "/proc.c") == 0)
133 if (__builtin_strcmp (function
, "runtime_mstart") == 0)
136 else if (__builtin_strcmp (p
, "/proc.go") == 0)
138 if (__builtin_strcmp (function
, "runtime.kickoff") == 0
139 || __builtin_strcmp (function
, "runtime.main") == 0)
145 return arg
->index
>= arg
->max
;
148 /* Syminfo callback. */
151 __go_syminfo_fnname_callback (void *data
,
152 uintptr_t pc
__attribute__ ((unused
)),
154 uintptr_t address
__attribute__ ((unused
)),
155 uintptr_t size
__attribute__ ((unused
)))
157 String
* strptr
= (String
*) data
;
160 *strptr
= runtime_gostringnocopy ((const byte
*) symname
);
163 /* Error callback. */
166 error_callback (void *data
__attribute__ ((unused
)),
167 const char *msg
, int errnum
)
171 /* No debug info available. Carry on as best we can. */
175 runtime_printf ("%s errno %d\n", msg
, errnum
);
179 /* Return whether we are already collecting a stack trace. This is
180 called from the signal handler. */
182 bool alreadyInCallers(void)
183 __attribute__ ((no_split_stack
));
184 bool alreadyInCallers(void)
185 __asm__ (GOSYM_PREFIX
"runtime.alreadyInCallers");
190 return runtime_atomicload(&__go_runtime_in_callers
) > 0;
193 /* Gather caller PC's. */
196 runtime_callers (int32 skip
, Location
*locbuf
, int32 m
, bool keep_thunks
)
198 struct callers_data data
;
199 struct backtrace_state
* state
;
202 data
.locbuf
= locbuf
;
203 data
.skip
= skip
+ 1;
206 data
.keep_thunks
= keep_thunks
;
207 runtime_xadd (&__go_runtime_in_callers
, 1);
208 state
= __go_get_backtrace_state ();
209 backtrace_full (state
, 0, callback
, error_callback
, &data
);
210 runtime_xadd (&__go_runtime_in_callers
, -1);
212 /* For some reason GCC sometimes loses the name of a thunk function
213 at the top of the stack. If we are skipping thunks, skip that
217 && locbuf
[data
.index
- 2].function
.len
== 0
218 && locbuf
[data
.index
- 1].function
.str
!= NULL
219 && __builtin_strcmp ((const char *) locbuf
[data
.index
- 1].function
.str
,
220 "runtime.kickoff") == 0)
222 locbuf
[data
.index
- 2] = locbuf
[data
.index
- 1];
226 /* Try to use backtrace_syminfo to fill in any missing function
227 names. This can happen when tracing through an object which has
228 no debug info; backtrace_syminfo will look at the symbol table to
229 get the name. This should only happen when tracing through code
230 that is not written in Go and is not part of libgo. */
231 for (i
= 0; i
< data
.index
; ++i
)
233 if (locbuf
[i
].function
.len
== 0 && locbuf
[i
].pc
!= 0)
234 backtrace_syminfo (state
, locbuf
[i
].pc
, __go_syminfo_fnname_callback
,
235 error_callback
, &locbuf
[i
].function
);
241 intgo
Callers (intgo
, struct __go_open_array
)
242 __asm__ (GOSYM_PREFIX
"runtime.Callers");
245 Callers (intgo skip
, struct __go_open_array pc
)
251 /* Note that calling mallocgc here assumes that we are not going to
252 store any allocated Go pointers in the slice. */
253 locbuf
= (Location
*) runtime_mallocgc (pc
.__count
* sizeof (Location
),
256 /* In the Go 1 release runtime.Callers has an off-by-one error,
257 which we can not correct because it would break backward
258 compatibility. Normally we would add 1 to SKIP here, but we
259 don't so that we are compatible. */
260 ret
= runtime_callers (skip
, locbuf
, pc
.__count
, false);
262 for (i
= 0; i
< ret
; i
++)
263 ((uintptr
*) pc
.__values
)[i
] = locbuf
[i
].pc
;
268 struct callersRaw_data
275 // Callback function for backtrace_simple. Just collect pc's.
276 // Return zero to continue, non-zero to stop.
278 static int callback_raw (void *data
, uintptr_t pc
)
280 struct callersRaw_data
*arg
= (struct callersRaw_data
*) data
;
282 /* On the call to backtrace_simple the pc value was most likely
283 decremented if there was a normal call, since the pc referred to
284 the instruction where the call returned and not the call itself.
285 This was done so that the line number referred to the call
286 instruction. To make sure the actual pc from the call stack is
287 used, it is incremented here.
289 In the case of a signal, the pc was not decremented by
290 backtrace_full but still incremented here. That doesn't really
291 hurt anything since the line number is right and the pc refers to
292 the same instruction. */
294 arg
->pcbuf
[arg
->index
] = pc
+ 1;
296 return arg
->index
>= arg
->max
;
299 /* runtime_callersRaw is similar to runtime_callers() above, but
300 it returns raw PC values as opposed to file/func/line locations. */
302 runtime_callersRaw (uintptr
*pcbuf
, int32 m
)
304 struct callersRaw_data data
;
305 struct backtrace_state
* state
;
310 runtime_xadd (&__go_runtime_in_callers
, 1);
311 state
= __go_get_backtrace_state ();
312 backtrace_simple (state
, 0, callback_raw
, error_callback
, &data
);
313 runtime_xadd (&__go_runtime_in_callers
, -1);