PR c++/63283
[official-gcc.git] / libgo / runtime / go-caller.c
blob7fcdf2021d399f7c4abeaa1d2bd43b906ed32ac3
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. */
9 #include <stdint.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <unistd.h>
14 #include "backtrace.h"
16 #include "runtime.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. */
23 struct caller
25 String fn;
26 String file;
27 intgo line;
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. */
34 static int
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;
40 if (function == NULL)
42 c->fn.str = NULL;
43 c->fn.len = 0;
45 else
47 byte *s;
49 c->fn.len = __builtin_strlen (function);
50 s = runtime_malloc (c->fn.len);
51 __builtin_memcpy (s, function, c->fn.len);
52 c->fn.str = s;
55 if (filename == NULL)
57 c->file.str = NULL;
58 c->file.len = 0;
60 else
62 byte *s;
64 c->file.len = __builtin_strlen (filename);
65 s = runtime_malloc (c->file.len);
66 __builtin_memcpy (s, filename, c->file.len);
67 c->file.str = s;
70 c->line = lineno;
72 return 0;
75 /* The error callback for backtrace_pcinfo and backtrace_syminfo. */
77 static void
78 error_callback (void *data __attribute__ ((unused)),
79 const char *msg, int errnum)
81 if (errnum == -1)
82 return;
83 if (errnum > 0)
84 runtime_printf ("%s errno %d\n", msg, errnum);
85 runtime_throw (msg);
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;
105 struct stat s;
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)
113 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
119 executable. */
120 if (stat (filename, &s) < 0 || s.st_size < 1024)
121 filename = NULL;
123 back_state = backtrace_create_state (filename, 1, error_callback, NULL);
125 runtime_unlock (&back_state_lock);
126 return back_state;
129 /* Return function/file/line information for PC. */
131 _Bool
132 __go_file_line (uintptr pc, String *fn, String *file, intgo *line)
134 struct caller c;
136 runtime_memclr (&c, sizeof c);
137 backtrace_pcinfo (__go_get_backtrace_state (), pc, callback,
138 error_callback, &c);
139 *fn = c.fn;
140 *file = c.file;
141 *line = c.line;
142 return c.file.len > 0;
145 /* Collect symbol information. */
147 static void
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;
154 *pval = address;
157 /* Set *VAL to the value of the symbol for PC. */
159 static _Bool
160 __go_symbol_value (uintptr_t pc, uintptr_t *val)
162 *val = 0;
163 backtrace_syminfo (__go_get_backtrace_state (), pc, syminfo_callback,
164 error_callback, val);
165 return *val != 0;
168 /* The values returned by runtime.Caller. */
170 struct caller_ret
172 uintptr_t pc;
173 String file;
174 intgo line;
175 _Bool ok;
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. */
184 struct caller_ret
185 Caller (int skip)
187 struct caller_ret ret;
188 Location loc;
189 int32 n;
191 runtime_memclr (&ret, sizeof ret);
192 n = runtime_callers (skip + 1, &loc, 1, false);
193 if (n < 1)
194 return ret;
195 ret.pc = loc.pc;
196 ret.file = loc.filename;
197 ret.line = loc.lineno;
198 ret.ok = 1;
199 return ret;
202 /* Implement runtime.FuncForPC. */
204 Func *
205 FuncForPC (uintptr_t pc)
207 Func *ret;
208 String fn;
209 String file;
210 intgo line;
211 uintptr_t val;
213 if (!__go_file_line (pc, &fn, &file, &line))
214 return NULL;
216 ret = (Func *) runtime_malloc (sizeof (*ret));
217 ret->name = fn;
219 if (__go_symbol_value (pc, &val))
220 ret->entry = val;
221 else
222 ret->entry = 0;
224 return ret;
227 /* Look up the file and line information for a PC within a
228 function. */
230 struct funcline_go_return
232 String retfile;
233 intgo retline;
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;
244 String fn;
246 if (!__go_file_line (targetpc, &fn, &ret.retfile, &ret.retline))
247 runtime_memclr (&ret, sizeof ret);
248 return ret;
251 /* Return the name of a function. */
252 String runtime_funcname_go (Func *f)
253 __asm__ (GOSYM_PREFIX "runtime.funcname_go");
255 String
256 runtime_funcname_go (Func *f)
258 return f->name;
261 /* Return the entry point of a function. */
262 uintptr runtime_funcentry_go(Func *f)
263 __asm__ (GOSYM_PREFIX "runtime.funcentry_go");
265 uintptr
266 runtime_funcentry_go (Func *f)
268 return f->entry;