Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(5)

Side by Side Diff: src/pkg/runtime/traceback_arm.c

Issue 134200044: code review 134200044: runtime: convert traceback*.c to Go (Closed)
Patch Set: diff -r df0572446e37549332e1d1154955409e2cff6008 https://code.google.com/p/go/ Created 10 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/runtime/traceback.go ('k') | src/pkg/runtime/traceback_windows.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 #include "runtime.h"
6 #include "arch_GOARCH.h"
7 #include "malloc.h"
8 #include "funcdata.h"
9
10 void runtime·sigpanic(void);
11 void runtime·newproc(void);
12 void runtime·deferproc(void);
13
14 int32
15 runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip, u intptr *pcbuf, int32 max, bool (*callback)(Stkframe*, void*), void *v, bool prin tall)
16 {
17 int32 i, n, nprint, line, gotraceback;
18 uintptr x, tracepc, sparg;
19 bool waspanic, wasnewproc, printing;
20 Func *f, *flr;
21 Stkframe frame;
22 Stktop *stk;
23 String file;
24 Panic *panic;
25 Defer *defer;
26
27 gotraceback = runtime·gotraceback(nil);
28
29 if(pc0 == ~(uintptr)0 && sp0 == ~(uintptr)0) { // Signal to fetch saved values from gp.
30 if(gp->syscallstack != (uintptr)nil) {
31 pc0 = gp->syscallpc;
32 sp0 = gp->syscallsp;
33 lr0 = 0;
34 } else {
35 pc0 = gp->sched.pc;
36 sp0 = gp->sched.sp;
37 lr0 = gp->sched.lr;
38 }
39 }
40
41 nprint = 0;
42 runtime·memclr((byte*)&frame, sizeof frame);
43 frame.pc = pc0;
44 frame.lr = lr0;
45 frame.sp = sp0;
46 waspanic = false;
47 wasnewproc = false;
48 printing = pcbuf==nil && callback==nil;
49
50 panic = gp->panic;
51 defer = gp->defer;
52
53 while(defer != nil && defer->argp == NoArgs)
54 defer = defer->link;····
55 while(panic != nil && panic->defer == nil)
56 panic = panic->link;
57
58 // If the PC is zero, it's likely a nil function call.
59 // Start in the caller's frame.
60 if(frame.pc == 0) {
61 frame.pc = frame.lr;
62 frame.lr = 0;
63 }
64 ········
65 f = runtime·findfunc(frame.pc);
66 if(f == nil) {
67 if(callback != nil) {
68 runtime·printf("runtime: unknown pc %p\n", frame.pc);
69 runtime·throw("unknown pc");
70 }
71 return 0;
72 }
73 frame.fn = f;
74
75 n = 0;
76 stk = (Stktop*)gp->stackbase;
77 while(n < max) {
78 // Typically:
79 // pc is the PC of the running function.
80 // sp is the stack pointer at that program counter.
81 // fp is the frame pointer (caller's stack pointer) at that program counter, or nil if unknown.
82 // stk is the stack containing sp.
83 // The caller's program counter is lr, unless lr is zero, i n which case it is *(uintptr*)sp.
84 ················
85 if(frame.pc == (uintptr)runtime·lessstack) {
86 // Hit top of stack segment. Unwind to next segment.
87 frame.pc = stk->gobuf.pc;
88 frame.sp = stk->gobuf.sp;
89 frame.lr = 0;
90 frame.fp = 0;
91 if(printing && runtime·showframe(nil, gp))
92 runtime·printf("----- stack segment boundary --- --\n");
93 stk = (Stktop*)stk->stackbase;
94 ························
95 f = runtime·findfunc(frame.pc);
96 if(f == nil) {
97 runtime·printf("runtime: unknown pc %p after sta ck split\n", frame.pc);
98 if(callback != nil)
99 runtime·throw("unknown pc");
100 }
101 frame.fn = f;
102 continue;
103 }
104 f = frame.fn;
105 ················
106 // Found an actual function.
107 // Derive frame pointer and link register.
108 if(frame.fp == 0)
109 frame.fp = frame.sp + runtime·funcspdelta(f, frame.pc);
110 if(runtime·topofstack(f)) {
111 frame.lr = 0;
112 flr = nil;
113 } else if(f->entry == (uintptr)runtime·jmpdefer) {
114 // jmpdefer modifies SP/LR/PC non-atomically.
115 // If a profiling interrupt arrives during jmpdefer,
116 // the stack unwind may see a mismatched register set
117 // and get confused. Stop if we see PC within jmpdefer
118 // to avoid that confusion.
119 // See golang.org/issue/8153.
120 // This check can be deleted if jmpdefer is changed
121 // to restore all three atomically using pop.
122 if(callback != nil)
123 runtime·throw("traceback_arm: found jmpdefer whe n tracing with callback");
124 frame.lr = 0;
125 flr = nil;
126 } else {
127 if((n == 0 && frame.sp < frame.fp) || frame.lr == 0)
128 frame.lr = *(uintptr*)frame.sp;
129 flr = runtime·findfunc(frame.lr);
130 if(flr == nil) {
131 // This happens if you get a profiling interrupt at just the wrong time.
132 // In that context it is okay to stop early.
133 // But if callback is set, we're doing a garbage collection and must
134 // get everything, so crash loudly.
135 if(callback != nil) {
136 runtime·printf("runtime: unexpected retu rn pc for %s called from %p\n", runtime·funcname(f), frame.lr);
137 runtime·throw("unknown caller pc");
138 }
139 }
140 }
141
142 frame.varp = frame.fp;
143
144 // Derive size of arguments.
145 // Most functions have a fixed-size argument block,
146 // so we can use metadata about the function f.
147 // Not all, though: there are some variadic functions
148 // in package runtime and reflect, and for those we use call-spe cific
149 // metadata recorded by f's caller.
150 if(callback != nil || printing) {
151 frame.argp = frame.fp + sizeof(uintptr);
152 if(f->args != ArgsSizeUnknown)
153 frame.arglen = f->args;
154 else if(flr == nil)
155 frame.arglen = 0;
156 else if(frame.lr == (uintptr)runtime·lessstack)
157 frame.arglen = stk->argsize;
158 else if((i = runtime·funcarglen(flr, frame.lr)) >= 0)
159 frame.arglen = i;
160 else {
161 runtime·printf("runtime: unknown argument frame size for %s called from %p [%s]\n",
162 runtime·funcname(f), frame.lr, flr ? run time·funcname(flr) : "?");
163 if(callback != nil)
164 runtime·throw("invalid stack");
165 frame.arglen = 0;
166 }
167 }
168
169 // Determine function SP where deferproc would find its argument s.
170 // On ARM that's just the standard bottom-of-stack plus 1 word f or
171 // the saved LR. If the previous frame was a direct call to newp roc/deferproc,
172 // however, the SP is three words lower than normal.
173 // If the function has no frame at all - perhaps it just started , or perhaps
174 // it is a leaf with no local variables - then we cannot possibl y find its
175 // SP in a defer, and we might confuse its SP for its caller's S P, so
176 // set sparg=0 in that case.
177 sparg = 0;
178 if(frame.fp != frame.sp) {
179 sparg = frame.sp + sizeof(uintreg);
180 if(wasnewproc)
181 sparg += 3*sizeof(uintreg);
182 }
183
184 // Determine frame's 'continuation PC', where it can continue.
185 // Normally this is the return address on the stack, but if sigp anic
186 // is immediately below this function on the stack, then the fra me
187 // stopped executing due to a trap, and frame.pc is probably not
188 // a safe point for looking up liveness information. In this pan icking case,
189 // the function either doesn't return at all (if it has no defer s or if the
190 // defers do not recover) or it returns from one of the calls to·······
191 // deferproc a second time (if the corresponding deferred func r ecovers).
192 // It suffices to assume that the most recent deferproc is the o ne that
193 // returns; everything live at earlier deferprocs is still live at that one.
194 frame.continpc = frame.pc;
195 if(waspanic) {
196 if(panic != nil && panic->defer->argp == sparg)
197 frame.continpc = (uintptr)panic->defer->pc;
198 else if(defer != nil && defer->argp == sparg)
199 frame.continpc = (uintptr)defer->pc;
200 else
201 frame.continpc = 0;
202 }
203
204 // Unwind our local panic & defer stacks past this frame.
205 while(panic != nil && (panic->defer == nil || panic->defer->argp == sparg || panic->defer->argp == NoArgs))
206 panic = panic->link;
207 while(defer != nil && (defer->argp == sparg || defer->argp == No Args))
208 defer = defer->link;····
209
210 if(skip > 0) {
211 skip--;
212 goto skipped;
213 }
214
215 if(pcbuf != nil)
216 pcbuf[n] = frame.pc;
217 if(callback != nil) {
218 if(!callback(&frame, v))
219 return n;
220 }
221 if(printing) {
222 if(printall || runtime·showframe(f, gp)) {
223 // Print during crash.
224 // main(0x1, 0x2, 0x3)
225 // /home/rsc/go/src/runtime/x.go:23 +0xf
226 tracepc = frame.pc; // back up to CALL instr uction for funcline.
227 if(n > 0 && frame.pc > f->entry && !waspanic)
228 tracepc -= sizeof(uintptr);
229 runtime·printf("%s(", runtime·funcname(f));
230 for(i = 0; i < frame.arglen/sizeof(uintptr); i++ ) {
231 if(i >= 10) {
232 runtime·prints(", ...");
233 break;
234 }
235 if(i != 0)
236 runtime·prints(", ");
237 runtime·printhex(((uintptr*)frame.argp)[ i]);
238 }
239 runtime·prints(")\n");
240 line = runtime·funcline(f, tracepc, &file);
241 runtime·printf("\t%S:%d", file, line);
242 if(frame.pc > f->entry)
243 runtime·printf(" +%p", (uintptr)(frame.p c - f->entry));
244 if(g->m->throwing > 0 && gp == g->m->curg || got raceback >= 2)
245 runtime·printf(" fp=%p sp=%p", frame.fp, frame.sp);
246 runtime·printf("\n");
247 nprint++;
248 }
249 }
250 n++;
251 ················
252 skipped:
253 waspanic = f->entry == (uintptr)runtime·sigpanic;
254 wasnewproc = f->entry == (uintptr)runtime·newproc || f->entry == (uintptr)runtime·deferproc;
255
256 // Do not unwind past the bottom of the stack.
257 if(flr == nil)
258 break;
259
260 // Unwind to next frame.
261 frame.pc = frame.lr;
262 frame.fn = flr;
263 frame.lr = 0;
264 frame.sp = frame.fp;
265 frame.fp = 0;
266 ········
267 // sighandler saves the lr on stack before faking a call to sigp anic
268 if(waspanic) {
269 x = *(uintptr*)frame.sp;
270 frame.sp += 4;
271 frame.fn = f = runtime·findfunc(frame.pc);
272 if(f == nil)
273 frame.pc = x;
274 else if(f->frame == 0)
275 frame.lr = x;
276 }
277 }
278 ········
279 if(pcbuf == nil && callback == nil)
280 n = nprint;
281
282 // For rationale, see long comment in traceback_x86.c.
283 if(callback != nil && n < max && defer != nil) {
284 if(defer != nil)
285 runtime·printf("runtime: g%D: leftover defer argp=%p pc= %p\n", gp->goid, defer->argp, defer->pc);
286 if(panic != nil)
287 runtime·printf("runtime: g%D: leftover panic argp=%p pc= %p\n", gp->goid, panic->defer->argp, panic->defer->pc);
288 for(defer = gp->defer; defer != nil; defer = defer->link)
289 runtime·printf("\tdefer %p argp=%p pc=%p\n", defer, defe r->argp, defer->pc);
290 for(panic = gp->panic; panic != nil; panic = panic->link) {
291 runtime·printf("\tpanic %p defer %p", panic, panic->defe r);
292 if(panic->defer != nil)
293 runtime·printf(" argp=%p pc=%p", panic->defer->a rgp, panic->defer->pc);
294 runtime·printf("\n");
295 }
296 runtime·throw("traceback has leftover defers or panics");
297 }
298
299 return n;···············
300 }
301
302 void
303 runtime·printcreatedby(G *gp)
304 {
305 int32 line;
306 uintptr pc, tracepc;
307 Func *f;
308 String file;
309
310 // Show what created goroutine, except main goroutine (goid 1).
311 if((pc = gp->gopc) != 0 && (f = runtime·findfunc(pc)) != nil &&
312 runtime·showframe(f, gp) && gp->goid != 1) {
313 runtime·printf("created by %s\n", runtime·funcname(f));
314 tracepc = pc; // back up to CALL instruction for funcline.
315 if(pc > f->entry)
316 tracepc -= PCQuantum;
317 line = runtime·funcline(f, tracepc, &file);
318 runtime·printf("\t%S:%d", file, line);
319 if(pc > f->entry)
320 runtime·printf(" +%p", (uintptr)(pc - f->entry));
321 runtime·printf("\n");
322 }
323 }
324
325 void
326 runtime·traceback(uintptr pc, uintptr sp, uintptr lr, G *gp)
327 {
328 int32 n;
329
330 if((runtime·readgstatus(gp)&~Gscan) == Gsyscall){
331 // Override signal registers if blocked in system call.
332 pc = gp->syscallpc;
333 sp = gp->syscallsp;
334 lr = 0;
335 }
336
337 // Print traceback. By default, omits runtime frames.
338 // If that means we print nothing at all, repeat forcing all frames prin ted.
339 n = runtime·gentraceback(pc, sp, lr, gp, 0, nil, TracebackMaxFrames, nil , nil, false);
340 if(n == 0)
341 runtime·gentraceback(pc, sp, lr, gp, 0, nil, TracebackMaxFrames, nil, nil, true);
342 if(n == TracebackMaxFrames)
343 runtime·printf("...additional frames elided...\n");
344 runtime·printcreatedby(gp);
345 }
346
347 // func caller(n int) (pc uintptr, file string, line int, ok bool)
348 int32
349 runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
350 {
351 uintptr pc, sp;
352 ········
353 sp = runtime·getcallersp(&skip);
354 pc = (uintptr)runtime·getcallerpc(&skip);
355
356 return runtime·gentraceback(pc, sp, 0, g, skip, pcbuf, m, nil, nil, fals e);
357 }
358
359 int32
360 runtime·gcallers(G *gp, int32 skip, uintptr *pcbuf, int32 m)
361 {
362 return runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, skip, pcbuf , m, nil, nil, false);
363 }
OLDNEW
« no previous file with comments | « src/pkg/runtime/traceback.go ('k') | src/pkg/runtime/traceback_windows.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b