1 /* go-caller.c -- runtime.Caller and runtime.FuncForPC for Go.
3 Copyright 2009 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 /* Implement runtime.Caller. */
11 #include "backtrace.h"
15 /* Get the function name, file name, and line number for a PC value.
16 We use the backtrace library to get this. */
18 /* Data structure to gather file/line information. */
27 /* Collect file/line information for a PC value. If this is called
28 more than once, due to inlined functions, we use the last call, as
29 that is usually the most useful one. */
32 callback (void *data
, uintptr_t pc
__attribute__ ((unused
)),
33 const char *filename
, int lineno
, const char *function
)
35 struct caller
*c
= (struct caller
*) data
;
46 c
->fn
.len
= __builtin_strlen (function
);
47 s
= runtime_malloc (c
->fn
.len
);
48 __builtin_memcpy (s
, function
, c
->fn
.len
);
61 c
->file
.len
= __builtin_strlen (filename
);
62 s
= runtime_malloc (c
->file
.len
);
63 __builtin_memcpy (s
, filename
, c
->file
.len
);
72 /* The error callback for backtrace_pcinfo and backtrace_syminfo. */
75 error_callback (void *data
__attribute__ ((unused
)),
76 const char *msg
, int errnum
)
81 runtime_printf ("%s errno %d\n", msg
, errnum
);
85 /* The backtrace library state. */
87 static void *back_state
;
89 /* A lock to control creating back_state. */
91 static Lock back_state_lock
;
93 /* Fetch back_state, creating it if necessary. */
95 struct backtrace_state
*
96 __go_get_backtrace_state ()
98 runtime_lock (&back_state_lock
);
99 if (back_state
== NULL
)
101 const char *filename
;
103 filename
= (const char *) runtime_progname ();
105 /* If there is no '/' in FILENAME, it was found on PATH, and
106 might not be the same as the file with the same name in the
107 current directory. */
108 if (__builtin_strchr (filename
, '/') == NULL
)
111 back_state
= backtrace_create_state (filename
, 1, error_callback
, NULL
);
113 runtime_unlock (&back_state_lock
);
117 /* Return function/file/line information for PC. */
120 __go_file_line (uintptr pc
, String
*fn
, String
*file
, intgo
*line
)
124 runtime_memclr (&c
, sizeof c
);
125 backtrace_pcinfo (__go_get_backtrace_state (), pc
, callback
,
130 return c
.file
.len
> 0;
133 /* Collect symbol information. */
136 syminfo_callback (void *data
, uintptr_t pc
__attribute__ ((unused
)),
137 const char *symname
__attribute__ ((unused
)),
138 uintptr_t address
, uintptr_t size
__attribute__ ((unused
)))
140 uintptr_t *pval
= (uintptr_t *) data
;
145 /* Set *VAL to the value of the symbol for PC. */
148 __go_symbol_value (uintptr_t pc
, uintptr_t *val
)
151 backtrace_syminfo (__go_get_backtrace_state (), pc
, syminfo_callback
,
152 error_callback
, val
);
156 /* The values returned by runtime.Caller. */
166 struct caller_ret
Caller (int n
) __asm__ (GOSYM_PREFIX
"runtime.Caller");
168 Func
*FuncForPC (uintptr_t) __asm__ (GOSYM_PREFIX
"runtime.FuncForPC");
170 /* Implement runtime.Caller. */
175 struct caller_ret ret
;
179 runtime_memclr (&ret
, sizeof ret
);
180 n
= runtime_callers (skip
+ 1, &loc
, 1);
184 ret
.file
= loc
.filename
;
185 ret
.line
= loc
.lineno
;
190 /* Implement runtime.FuncForPC. */
193 FuncForPC (uintptr_t pc
)
201 if (!__go_file_line (pc
, &fn
, &file
, &line
))
204 ret
= (Func
*) runtime_malloc (sizeof (*ret
));
207 if (__go_symbol_value (pc
, &val
))
215 /* Look up the file and line information for a PC within a
218 struct funcline_go_return
224 struct funcline_go_return
225 runtime_funcline_go (Func
*f
, uintptr targetpc
)
226 __asm__ (GOSYM_PREFIX
"runtime.funcline_go");
228 struct funcline_go_return
229 runtime_funcline_go (Func
*f
__attribute__((unused
)), uintptr targetpc
)
231 struct funcline_go_return ret
;
234 if (!__go_file_line (targetpc
, &fn
, &ret
.retfile
, &ret
.retline
))
235 runtime_memclr (&ret
, sizeof ret
);
239 /* Return the name of a function. */
240 String
runtime_funcname_go (Func
*f
)
241 __asm__ (GOSYM_PREFIX
"runtime.funcname_go");
244 runtime_funcname_go (Func
*f
)
249 /* Return the entry point of a function. */
250 uintptr
runtime_funcentry_go(Func
*f
)
251 __asm__ (GOSYM_PREFIX
"runtime.funcentry_go");
254 runtime_funcentry_go (Func
*f
)