runtime: Copy runtime_printf from other Go library.
[gcc.git] / libgo / runtime / go-callers.c
1 /* go-callers.c -- get callers for Go.
2
3 Copyright 2012 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. */
6
7 #include "config.h"
8
9 #include "unwind.h"
10
11 #include "runtime.h"
12
13 /* Argument passed to backtrace function. */
14
15 struct callers_data
16 {
17 int skip;
18 uintptr *pcbuf;
19 int index;
20 int max;
21 };
22
23 static _Unwind_Reason_Code
24 backtrace (struct _Unwind_Context *context, void *varg)
25 {
26 struct callers_data *arg = (struct callers_data *) varg;
27 uintptr pc;
28 int ip_before_insn = 0;
29
30 #ifdef HAVE_GETIPINFO
31 pc = _Unwind_GetIPInfo (context, &ip_before_insn);
32 #else
33 pc = _Unwind_GetIP (context);
34 #endif
35
36 /* FIXME: If PC is in the __morestack routine, we should ignore
37 it. */
38
39 if (arg->skip > 0)
40 --arg->skip;
41 else if (arg->index >= arg->max)
42 return _URC_END_OF_STACK;
43 else
44 {
45 /* Here PC will be the return address. We actually want the
46 address of the call instruction, so back up one byte and
47 count on the lookup routines handling that correctly. */
48 if (!ip_before_insn)
49 --pc;
50 arg->pcbuf[arg->index] = pc;
51 ++arg->index;
52 }
53 return _URC_NO_REASON;
54 }
55
56 int32
57 runtime_callers (int32 skip, uintptr *pcbuf, int32 m)
58 {
59 struct callers_data arg;
60
61 arg.skip = skip + 1;
62 arg.pcbuf = pcbuf;
63 arg.index = 0;
64 arg.max = m;
65 _Unwind_Backtrace (backtrace, &arg);
66 return arg.index;
67 }
68
69 int Callers (int, struct __go_open_array)
70 __asm__ ("runtime.Callers");
71
72 int
73 Callers (int skip, struct __go_open_array pc)
74 {
75 /* In the Go 1 release runtime.Callers has an off-by-one error,
76 which we can not correct because it would break backward
77 compatibility. Adjust SKIP here to be compatible. */
78 return runtime_callers (skip - 1, (uintptr *) pc.__values, pc.__count);
79 }