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. */
10 #include <sys/types.h>
14 #include "backtrace.h"
18 /* Get the function name, file name, and line number for a PC value.
19 We use the backtrace library to get this. */
21 /* Data structure to gather file/line information. */
30 /* Collect file/line information for a PC value. If this is called
31 more than once, due to inlined functions, we use the last call, as
32 that is usually the most useful one. */
35 callback (void *data
, uintptr_t pc
__attribute__ ((unused
)),
36 const char *filename
, int lineno
, const char *function
)
38 struct caller
*c
= (struct caller
*) data
;
49 c
->fn
.len
= __builtin_strlen (function
);
50 s
= runtime_malloc (c
->fn
.len
);
51 __builtin_memcpy (s
, function
, c
->fn
.len
);
64 c
->file
.len
= __builtin_strlen (filename
);
65 s
= runtime_malloc (c
->file
.len
);
66 __builtin_memcpy (s
, filename
, c
->file
.len
);
75 /* The error callback for backtrace_pcinfo and backtrace_syminfo. */
78 error_callback (void *data
__attribute__ ((unused
)),
79 const char *msg
, int errnum
)
84 runtime_printf ("%s errno %d\n", msg
, errnum
);
88 /* The backtrace library state. */
90 static void *back_state
;
92 /* A lock to control creating back_state. */
94 static Lock back_state_lock
;
96 /* Fetch back_state, creating it if necessary. */
98 struct backtrace_state
*
99 __go_get_backtrace_state ()
101 runtime_lock (&back_state_lock
);
102 if (back_state
== NULL
)
104 const char *filename
;
107 filename
= (const char *) runtime_progname ();
109 /* If there is no '/' in FILENAME, it was found on PATH, and
110 might not be the same as the file with the same name in the
111 current directory. */
112 if (__builtin_strchr (filename
, '/') == NULL
)
115 /* If the file is small, then it's not the real executable.
116 This is specifically to deal with Docker, which uses a bogus
117 argv[0] (http://gcc.gnu.org/PR61895). It would be nice to
118 have a better check for whether this file is the real
120 if (stat (filename
, &s
) < 0 || s
.st_size
< 1024)
123 back_state
= backtrace_create_state (filename
, 1, error_callback
, NULL
);
125 runtime_unlock (&back_state_lock
);
129 /* Return function/file/line information for PC. */
132 __go_file_line (uintptr pc
, String
*fn
, String
*file
, intgo
*line
)
136 runtime_memclr (&c
, sizeof c
);
137 backtrace_pcinfo (__go_get_backtrace_state (), pc
, callback
,
142 return c
.file
.len
> 0;
145 /* Collect symbol information. */
148 syminfo_callback (void *data
, uintptr_t pc
__attribute__ ((unused
)),
149 const char *symname
__attribute__ ((unused
)),
150 uintptr_t address
, uintptr_t size
__attribute__ ((unused
)))
152 uintptr_t *pval
= (uintptr_t *) data
;
157 /* Set *VAL to the value of the symbol for PC. */
160 __go_symbol_value (uintptr_t pc
, uintptr_t *val
)
163 backtrace_syminfo (__go_get_backtrace_state (), pc
, syminfo_callback
,
164 error_callback
, val
);
168 /* The values returned by runtime.Caller. */
178 struct caller_ret
Caller (int n
) __asm__ (GOSYM_PREFIX
"runtime.Caller");
180 Func
*FuncForPC (uintptr_t) __asm__ (GOSYM_PREFIX
"runtime.FuncForPC");
182 /* Implement runtime.Caller. */
187 struct caller_ret ret
;
191 runtime_memclr (&ret
, sizeof ret
);
192 n
= runtime_callers (skip
+ 1, &loc
, 1);
196 ret
.file
= loc
.filename
;
197 ret
.line
= loc
.lineno
;
202 /* Implement runtime.FuncForPC. */
205 FuncForPC (uintptr_t pc
)
213 if (!__go_file_line (pc
, &fn
, &file
, &line
))
216 ret
= (Func
*) runtime_malloc (sizeof (*ret
));
219 if (__go_symbol_value (pc
, &val
))
227 /* Look up the file and line information for a PC within a
230 struct funcline_go_return
236 struct funcline_go_return
237 runtime_funcline_go (Func
*f
, uintptr targetpc
)
238 __asm__ (GOSYM_PREFIX
"runtime.funcline_go");
240 struct funcline_go_return
241 runtime_funcline_go (Func
*f
__attribute__((unused
)), uintptr targetpc
)
243 struct funcline_go_return ret
;
246 if (!__go_file_line (targetpc
, &fn
, &ret
.retfile
, &ret
.retline
))
247 runtime_memclr (&ret
, sizeof ret
);
251 /* Return the name of a function. */
252 String
runtime_funcname_go (Func
*f
)
253 __asm__ (GOSYM_PREFIX
"runtime.funcname_go");
256 runtime_funcname_go (Func
*f
)
259 return runtime_gostringnocopy ((const byte
*) "");
263 /* Return the entry point of a function. */
264 uintptr
runtime_funcentry_go(Func
*f
)
265 __asm__ (GOSYM_PREFIX
"runtime.funcentry_go");
268 runtime_funcentry_go (Func
*f
)