2014-07-29 Ed Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / libgo / runtime / go-caller.c
bloba5c687d00f49f816f7e37a0edefb68b87eeb06ec
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>
11 #include "backtrace.h"
13 #include "runtime.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. */
20 struct caller
22 String fn;
23 String file;
24 intgo line;
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. */
31 static int
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;
37 if (function == NULL)
39 c->fn.str = NULL;
40 c->fn.len = 0;
42 else
44 byte *s;
46 c->fn.len = __builtin_strlen (function);
47 s = runtime_malloc (c->fn.len);
48 __builtin_memcpy (s, function, c->fn.len);
49 c->fn.str = s;
52 if (filename == NULL)
54 c->file.str = NULL;
55 c->file.len = 0;
57 else
59 byte *s;
61 c->file.len = __builtin_strlen (filename);
62 s = runtime_malloc (c->file.len);
63 __builtin_memcpy (s, filename, c->file.len);
64 c->file.str = s;
67 c->line = lineno;
69 return 0;
72 /* The error callback for backtrace_pcinfo and backtrace_syminfo. */
74 static void
75 error_callback (void *data __attribute__ ((unused)),
76 const char *msg, int errnum)
78 if (errnum == -1)
79 return;
80 if (errnum > 0)
81 runtime_printf ("%s errno %d\n", msg, errnum);
82 runtime_throw (msg);
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)
109 filename = NULL;
111 back_state = backtrace_create_state (filename, 1, error_callback, NULL);
113 runtime_unlock (&back_state_lock);
114 return back_state;
117 /* Return function/file/line information for PC. */
119 _Bool
120 __go_file_line (uintptr pc, String *fn, String *file, intgo *line)
122 struct caller c;
124 runtime_memclr (&c, sizeof c);
125 backtrace_pcinfo (__go_get_backtrace_state (), pc, callback,
126 error_callback, &c);
127 *fn = c.fn;
128 *file = c.file;
129 *line = c.line;
130 return c.file.len > 0;
133 /* Collect symbol information. */
135 static void
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;
142 *pval = address;
145 /* Set *VAL to the value of the symbol for PC. */
147 static _Bool
148 __go_symbol_value (uintptr_t pc, uintptr_t *val)
150 *val = 0;
151 backtrace_syminfo (__go_get_backtrace_state (), pc, syminfo_callback,
152 error_callback, val);
153 return *val != 0;
156 /* The values returned by runtime.Caller. */
158 struct caller_ret
160 uintptr_t pc;
161 String file;
162 intgo line;
163 _Bool ok;
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. */
172 struct caller_ret
173 Caller (int skip)
175 struct caller_ret ret;
176 Location loc;
177 int32 n;
179 runtime_memclr (&ret, sizeof ret);
180 n = runtime_callers (skip + 1, &loc, 1, false);
181 if (n < 1)
182 return ret;
183 ret.pc = loc.pc;
184 ret.file = loc.filename;
185 ret.line = loc.lineno;
186 ret.ok = 1;
187 return ret;
190 /* Implement runtime.FuncForPC. */
192 Func *
193 FuncForPC (uintptr_t pc)
195 Func *ret;
196 String fn;
197 String file;
198 intgo line;
199 uintptr_t val;
201 if (!__go_file_line (pc, &fn, &file, &line))
202 return NULL;
204 ret = (Func *) runtime_malloc (sizeof (*ret));
205 ret->name = fn;
207 if (__go_symbol_value (pc, &val))
208 ret->entry = val;
209 else
210 ret->entry = 0;
212 return ret;
215 /* Look up the file and line information for a PC within a
216 function. */
218 struct funcline_go_return
220 String retfile;
221 intgo retline;
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;
232 String fn;
234 if (!__go_file_line (targetpc, &fn, &ret.retfile, &ret.retline))
235 runtime_memclr (&ret, sizeof ret);
236 return ret;
239 /* Return the name of a function. */
240 String runtime_funcname_go (Func *f)
241 __asm__ (GOSYM_PREFIX "runtime.funcname_go");
243 String
244 runtime_funcname_go (Func *f)
246 return f->name;
249 /* Return the entry point of a function. */
250 uintptr runtime_funcentry_go(Func *f)
251 __asm__ (GOSYM_PREFIX "runtime.funcentry_go");
253 uintptr
254 runtime_funcentry_go (Func *f)
256 return f->entry;