2013-02-11 Sebastian Huber <sebastian.huber@embedded-brains.de>
[official-gcc.git] / libgo / runtime / go-caller.c
blobd84580fa594b98eea23bee346c5ba9dd208cd55d
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 ();
104 back_state = backtrace_create_state (filename, 1, error_callback, NULL);
106 runtime_unlock (&back_state_lock);
107 return back_state;
110 /* Return function/file/line information for PC. */
112 _Bool
113 __go_file_line (uintptr pc, String *fn, String *file, intgo *line)
115 struct caller c;
117 runtime_memclr (&c, sizeof c);
118 backtrace_pcinfo (__go_get_backtrace_state (), pc, callback,
119 error_callback, &c);
120 *fn = c.fn;
121 *file = c.file;
122 *line = c.line;
123 return c.file.len > 0;
126 /* Collect symbol information. */
128 static void
129 syminfo_callback (void *data, uintptr_t pc __attribute__ ((unused)),
130 const char *symname __attribute__ ((unused)),
131 uintptr_t address)
133 uintptr_t *pval = (uintptr_t *) data;
135 *pval = address;
138 /* Set *VAL to the value of the symbol for PC. */
140 static _Bool
141 __go_symbol_value (uintptr_t pc, uintptr_t *val)
143 *val = 0;
144 backtrace_syminfo (__go_get_backtrace_state (), pc, syminfo_callback,
145 error_callback, val);
146 return *val != 0;
149 /* The values returned by runtime.Caller. */
151 struct caller_ret
153 uintptr_t pc;
154 String file;
155 intgo line;
156 _Bool ok;
159 struct caller_ret Caller (int n) __asm__ (GOSYM_PREFIX "runtime.Caller");
161 Func *FuncForPC (uintptr_t) __asm__ (GOSYM_PREFIX "runtime.FuncForPC");
163 /* Implement runtime.Caller. */
165 struct caller_ret
166 Caller (int skip)
168 struct caller_ret ret;
169 Location loc;
170 int32 n;
172 runtime_memclr (&ret, sizeof ret);
173 n = runtime_callers (skip + 1, &loc, 1);
174 if (n < 1)
175 return ret;
176 ret.pc = loc.pc;
177 ret.file = loc.filename;
178 ret.line = loc.lineno;
179 ret.ok = 1;
180 return ret;
183 /* Implement runtime.FuncForPC. */
185 Func *
186 FuncForPC (uintptr_t pc)
188 Func *ret;
189 String fn;
190 String file;
191 intgo line;
192 uintptr_t val;
194 if (!__go_file_line (pc, &fn, &file, &line))
195 return NULL;
197 ret = (Func *) runtime_malloc (sizeof (*ret));
198 ret->name = fn;
200 if (__go_symbol_value (pc, &val))
201 ret->entry = val;
202 else
203 ret->entry = 0;
205 return ret;
208 /* Look up the file and line information for a PC within a
209 function. */
211 struct funcline_go_return
213 String retfile;
214 intgo retline;
217 struct funcline_go_return
218 runtime_funcline_go (Func *f, uintptr targetpc)
219 __asm__ (GOSYM_PREFIX "runtime.funcline_go");
221 struct funcline_go_return
222 runtime_funcline_go (Func *f __attribute__((unused)), uintptr targetpc)
224 struct funcline_go_return ret;
225 String fn;
227 if (!__go_file_line (targetpc, &fn, &ret.retfile, &ret.retline))
228 runtime_memclr (&ret, sizeof ret);
229 return ret;