LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // +build amd64 386 | 5 // +build amd64 386 |
6 | 6 |
7 #include "runtime.h" | 7 #include "runtime.h" |
8 #include "arch_GOARCH.h" | 8 #include "arch_GOARCH.h" |
9 #include "malloc.h" | 9 #include "malloc.h" |
10 | 10 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 // Start in the caller's frame. | 46 // Start in the caller's frame. |
47 if(frame.pc == 0) { | 47 if(frame.pc == 0) { |
48 frame.pc = *(uintptr*)frame.sp; | 48 frame.pc = *(uintptr*)frame.sp; |
49 frame.sp += sizeof(uintptr); | 49 frame.sp += sizeof(uintptr); |
50 } | 50 } |
51 ········ | 51 ········ |
52 f = runtime·findfunc(frame.pc); | 52 f = runtime·findfunc(frame.pc); |
53 if(f == nil) { | 53 if(f == nil) { |
54 if(callback != nil) { | 54 if(callback != nil) { |
55 runtime·printf("runtime: unknown pc %p\n", frame.pc); | 55 runtime·printf("runtime: unknown pc %p\n", frame.pc); |
56 » » » if(!printing) | 56 » » » runtime·throw("unknown pc"); |
57 » » » » runtime·throw("unknown pc"); | |
58 } | 57 } |
59 return 0; | 58 return 0; |
60 } | 59 } |
61 frame.fn = f; | 60 frame.fn = f; |
62 | 61 |
63 n = 0; | 62 n = 0; |
64 stk = (Stktop*)gp->stackbase; | 63 stk = (Stktop*)gp->stackbase; |
65 while(n < max) { | 64 while(n < max) { |
66 // Typically: | 65 // Typically: |
67 // pc is the PC of the running function. | 66 // pc is the PC of the running function. |
68 // sp is the stack pointer at that program counter. | 67 // sp is the stack pointer at that program counter. |
69 // fp is the frame pointer (caller's stack pointer) at that
program counter, or nil if unknown. | 68 // fp is the frame pointer (caller's stack pointer) at that
program counter, or nil if unknown. |
70 // stk is the stack containing sp. | 69 // stk is the stack containing sp. |
71 // The caller's program counter is lr, unless lr is zero, i
n which case it is *(uintptr*)sp. | 70 // The caller's program counter is lr, unless lr is zero, i
n which case it is *(uintptr*)sp. |
72 ········ | 71 ········ |
73 if(frame.pc == (uintptr)runtime·lessstack) { | 72 if(frame.pc == (uintptr)runtime·lessstack) { |
74 // Hit top of stack segment. Unwind to next segment. | 73 // Hit top of stack segment. Unwind to next segment. |
75 frame.pc = stk->gobuf.pc; | 74 frame.pc = stk->gobuf.pc; |
76 frame.sp = stk->gobuf.sp; | 75 frame.sp = stk->gobuf.sp; |
77 frame.lr = 0; | 76 frame.lr = 0; |
78 frame.fp = 0; | 77 frame.fp = 0; |
79 frame.fn = nil; | 78 frame.fn = nil; |
80 if(printing && runtime·showframe(nil, gp)) | 79 if(printing && runtime·showframe(nil, gp)) |
81 runtime·printf("----- stack segment boundary ---
--\n"); | 80 runtime·printf("----- stack segment boundary ---
--\n"); |
82 stk = (Stktop*)stk->stackbase; | 81 stk = (Stktop*)stk->stackbase; |
83 | 82 |
84 f = runtime·findfunc(frame.pc); | 83 f = runtime·findfunc(frame.pc); |
85 if(f == nil) { | 84 if(f == nil) { |
86 runtime·printf("runtime: unknown pc %p after sta
ck split\n", frame.pc); | 85 runtime·printf("runtime: unknown pc %p after sta
ck split\n", frame.pc); |
87 » » » » if(!printing) | 86 » » » » if(callback != nil) |
88 runtime·throw("unknown pc"); | 87 runtime·throw("unknown pc"); |
89 } | 88 } |
90 frame.fn = f; | 89 frame.fn = f; |
91 continue; | 90 continue; |
92 } | 91 } |
93 f = frame.fn; | 92 f = frame.fn; |
94 | 93 |
95 // Found an actual function. | 94 // Found an actual function. |
96 // Derive frame pointer and link register. | 95 // Derive frame pointer and link register. |
97 if(frame.fp == 0) { | 96 if(frame.fp == 0) { |
98 frame.fp = frame.sp + runtime·funcspdelta(f, frame.pc); | 97 frame.fp = frame.sp + runtime·funcspdelta(f, frame.pc); |
99 frame.fp += sizeof(uintptr); // caller PC | 98 frame.fp += sizeof(uintptr); // caller PC |
100 } | 99 } |
101 if(runtime·topofstack(f)) { | 100 if(runtime·topofstack(f)) { |
102 frame.lr = 0; | 101 frame.lr = 0; |
103 flr = nil; | 102 flr = nil; |
104 } else { | 103 } else { |
105 if(frame.lr == 0) | 104 if(frame.lr == 0) |
106 frame.lr = ((uintptr*)frame.fp)[-1]; | 105 frame.lr = ((uintptr*)frame.fp)[-1]; |
107 flr = runtime·findfunc(frame.lr); | 106 flr = runtime·findfunc(frame.lr); |
108 if(flr == nil) { | 107 if(flr == nil) { |
109 runtime·printf("runtime: unexpected return pc fo
r %s called from %p\n", runtime·funcname(f), frame.lr); | 108 runtime·printf("runtime: unexpected return pc fo
r %s called from %p\n", runtime·funcname(f), frame.lr); |
110 » » » » if(!printing) | 109 » » » » if(callback != nil) |
111 runtime·throw("unknown caller pc"); | 110 runtime·throw("unknown caller pc"); |
112 } | 111 } |
113 } | 112 } |
114 | 113 |
115 // Derive size of arguments. | 114 // Derive size of arguments. |
116 // Most functions have a fixed-size argument block, | 115 // Most functions have a fixed-size argument block, |
117 // so we can use metadata about the function f. | 116 // so we can use metadata about the function f. |
118 // Not all, though: there are some variadic functions | 117 // Not all, though: there are some variadic functions |
119 // in package runtime, and for those we use call-specific | 118 // in package runtime, and for those we use call-specific |
120 // metadata recorded by f's caller. | 119 // metadata recorded by f's caller. |
121 if(callback != nil || printing) { | 120 if(callback != nil || printing) { |
122 frame.argp = (byte*)frame.fp; | 121 frame.argp = (byte*)frame.fp; |
123 if(f->args != ArgsSizeUnknown) | 122 if(f->args != ArgsSizeUnknown) |
124 frame.arglen = f->args; | 123 frame.arglen = f->args; |
125 else if(flr == nil) | 124 else if(flr == nil) |
126 frame.arglen = 0; | 125 frame.arglen = 0; |
127 else if(frame.lr == (uintptr)runtime·lessstack) | 126 else if(frame.lr == (uintptr)runtime·lessstack) |
128 frame.arglen = stk->argsize; | 127 frame.arglen = stk->argsize; |
129 else if((i = runtime·funcarglen(flr, frame.lr)) >= 0) | 128 else if((i = runtime·funcarglen(flr, frame.lr)) >= 0) |
130 frame.arglen = i; | 129 frame.arglen = i; |
131 else { | 130 else { |
132 runtime·printf("runtime: unknown argument frame
size for %s called from %p [%s]\n", | 131 runtime·printf("runtime: unknown argument frame
size for %s called from %p [%s]\n", |
133 runtime·funcname(f), frame.lr, flr ? run
time·funcname(flr) : "?"); | 132 runtime·funcname(f), frame.lr, flr ? run
time·funcname(flr) : "?"); |
134 » » » » if(!printing) | 133 » » » » if(callback != nil) |
135 runtime·throw("invalid stack"); | 134 runtime·throw("invalid stack"); |
136 frame.arglen = 0; | 135 frame.arglen = 0; |
137 } | 136 } |
138 } | 137 } |
139 | 138 |
140 // Derive location and size of local variables. | 139 // Derive location and size of local variables. |
141 if(frame.fp == frame.sp + sizeof(uintptr)) { | 140 if(frame.fp == frame.sp + sizeof(uintptr)) { |
142 // Function has not created a frame for itself yet. | 141 // Function has not created a frame for itself yet. |
143 frame.varp = nil; | 142 frame.varp = nil; |
144 frame.varlen = 0; | 143 frame.varlen = 0; |
145 } else if(f->locals == 0) { | 144 } else if(f->locals == 0) { |
146 // Assume no information, so use whole frame. | 145 // Assume no information, so use whole frame. |
147 // TODO: Distinguish local==0 from local==unknown. | 146 // TODO: Distinguish local==0 from local==unknown. |
148 frame.varp = (byte*)frame.sp; | 147 frame.varp = (byte*)frame.sp; |
149 frame.varlen = frame.fp - sizeof(uintptr) - frame.sp; | 148 frame.varlen = frame.fp - sizeof(uintptr) - frame.sp; |
150 } else { | 149 } else { |
151 if(f->locals > frame.fp - sizeof(uintptr) - frame.sp) { | 150 if(f->locals > frame.fp - sizeof(uintptr) - frame.sp) { |
152 runtime·printf("runtime: inconsistent locals=%p
frame=%p fp=%p sp=%p for %s\n", (uintptr)f->locals, (uintptr)f->frame, frame.fp,
frame.sp, runtime·funcname(f)); | 151 runtime·printf("runtime: inconsistent locals=%p
frame=%p fp=%p sp=%p for %s\n", (uintptr)f->locals, (uintptr)f->frame, frame.fp,
frame.sp, runtime·funcname(f)); |
153 » » » » if(!printing) | 152 » » » » if(callback != nil) |
154 runtime·throw("invalid stack"); | 153 runtime·throw("invalid stack"); |
155 } | 154 } |
156 frame.varp = (byte*)frame.fp - sizeof(uintptr) - f->loca
ls; | 155 frame.varp = (byte*)frame.fp - sizeof(uintptr) - f->loca
ls; |
157 frame.varlen = f->locals; | 156 frame.varlen = f->locals; |
158 } | 157 } |
159 | 158 |
160 if(skip > 0) { | 159 if(skip > 0) { |
161 skip--; | 160 skip--; |
162 goto skipped; | 161 goto skipped; |
163 } | 162 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 int32 | 261 int32 |
263 runtime·callers(int32 skip, uintptr *pcbuf, int32 m) | 262 runtime·callers(int32 skip, uintptr *pcbuf, int32 m) |
264 { | 263 { |
265 uintptr pc, sp; | 264 uintptr pc, sp; |
266 | 265 |
267 sp = runtime·getcallersp(&skip); | 266 sp = runtime·getcallersp(&skip); |
268 pc = (uintptr)runtime·getcallerpc(&skip); | 267 pc = (uintptr)runtime·getcallerpc(&skip); |
269 | 268 |
270 return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m, nil, nil, fals
e); | 269 return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m, nil, nil, fals
e); |
271 } | 270 } |
LEFT | RIGHT |