mirror of
https://github.com/golang/go
synced 2024-11-25 06:47:56 -07:00
gc, runtime: fix range+panic line number bugs
Fixes #1856. R=ken2 CC=golang-dev https://golang.org/cl/4810054
This commit is contained in:
parent
cce10dacc6
commit
12a5774cde
@ -98,11 +98,13 @@ walkrange(Node *n)
|
||||
Node *fn, *tmp;
|
||||
NodeList *body, *init;
|
||||
Type *th, *t;
|
||||
int lno;
|
||||
|
||||
t = n->type;
|
||||
init = nil;
|
||||
|
||||
a = n->right;
|
||||
lno = setlineno(a);
|
||||
if(t->etype == TSTRING && !eqtype(t, types[TSTRING])) {
|
||||
a = nod(OCONV, n->right, N);
|
||||
a->type = types[TSTRING];
|
||||
@ -248,5 +250,7 @@ walkrange(Node *n)
|
||||
typechecklist(body, Etop);
|
||||
n->nbody = concat(body, n->nbody);
|
||||
walkstmt(&n);
|
||||
|
||||
lineno = lno;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ void runtime·deferproc(void);
|
||||
void runtime·newproc(void);
|
||||
void runtime·newstack(void);
|
||||
void runtime·morestack(void);
|
||||
void runtime·sigpanic(void);
|
||||
|
||||
// This code is also used for the 386 tracebacks.
|
||||
// Use uintptr for an appropriate word-sized integer.
|
||||
@ -27,11 +28,13 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
|
||||
byte *fp;
|
||||
Stktop *stk;
|
||||
Func *f;
|
||||
bool waspanic;
|
||||
|
||||
USED(lr0);
|
||||
pc = (uintptr)pc0;
|
||||
lr = 0;
|
||||
fp = nil;
|
||||
waspanic = false;
|
||||
|
||||
// If the PC is goexit, the goroutine hasn't started yet.
|
||||
if(pc0 == g->sched.pc && sp == g->sched.sp && pc0 == (byte*)runtime·goexit) {
|
||||
@ -127,7 +130,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
|
||||
if(pc > f->entry)
|
||||
runtime·printf("+%p", (uintptr)(pc - f->entry));
|
||||
tracepc = pc; // back up to CALL instruction for funcline.
|
||||
if(n > 0 && pc > f->entry)
|
||||
if(n > 0 && pc > f->entry && !waspanic)
|
||||
tracepc--;
|
||||
runtime·printf(" %S:%d\n", f->src, runtime·funcline(f, tracepc));
|
||||
runtime·printf("\t%S(", f->name);
|
||||
@ -144,6 +147,8 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
|
||||
n++;
|
||||
}
|
||||
|
||||
waspanic = f->entry == (uintptr)runtime·sigpanic;
|
||||
|
||||
if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
|
||||
fp += 2*sizeof(uintptr);
|
||||
|
||||
|
@ -9,6 +9,7 @@ void runtime·deferproc(void);
|
||||
void runtime·newproc(void);
|
||||
void runtime·newstack(void);
|
||||
void runtime·morestack(void);
|
||||
void runtime·sigpanic(void);
|
||||
void _div(void);
|
||||
void _mod(void);
|
||||
void _divu(void);
|
||||
@ -20,12 +21,14 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
|
||||
int32 i, n, iter;
|
||||
uintptr pc, lr, tracepc, x;
|
||||
byte *fp, *p;
|
||||
bool waspanic;
|
||||
Stktop *stk;
|
||||
Func *f;
|
||||
|
||||
pc = (uintptr)pc0;
|
||||
lr = (uintptr)lr0;
|
||||
fp = nil;
|
||||
waspanic = false;
|
||||
|
||||
// If the PC is goexit, the goroutine hasn't started yet.
|
||||
if(pc == (uintptr)runtime·goexit) {
|
||||
@ -121,7 +124,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
|
||||
if(pc > f->entry)
|
||||
runtime·printf("+%p", (uintptr)(pc - f->entry));
|
||||
tracepc = pc; // back up to CALL instruction for funcline.
|
||||
if(n > 0 && pc > f->entry)
|
||||
if(n > 0 && pc > f->entry && !waspanic)
|
||||
tracepc -= sizeof(uintptr);
|
||||
runtime·printf(" %S:%d\n", f->src, runtime·funcline(f, tracepc));
|
||||
runtime·printf("\t%S(", f->name);
|
||||
@ -138,6 +141,8 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
|
||||
n++;
|
||||
}
|
||||
|
||||
waspanic = f->entry == (uintptr)runtime·sigpanic;
|
||||
|
||||
if(pcbuf == nil && f->entry == (uintptr)runtime·newstack && g == m->g0) {
|
||||
runtime·printf("----- newstack called from goroutine %d -----\n", m->curg->goid);
|
||||
pc = (uintptr)m->morepc;
|
||||
|
@ -167,3 +167,14 @@ os·sigpipe(void)
|
||||
{
|
||||
runtime·throw("too many writes on closed pipe");
|
||||
}
|
||||
|
||||
/*
|
||||
* placeholder - once notes are implemented,
|
||||
* a signal generating a panic must appear as
|
||||
* a call to this function for correct handling by
|
||||
* traceback.
|
||||
*/
|
||||
void
|
||||
runtime·sigpanic(void)
|
||||
{
|
||||
}
|
||||
|
@ -11,6 +11,14 @@ enum {
|
||||
|
||||
uint32 runtime·panicking;
|
||||
|
||||
/*
|
||||
* We assume that all architectures turn faults and the like
|
||||
* into apparent calls to runtime.sigpanic. If we see a "call"
|
||||
* to runtime.sigpanic, we do not back up the PC to find the
|
||||
* line number of the CALL instruction, because there is no CALL.
|
||||
*/
|
||||
void runtime·sigpanic(void);
|
||||
|
||||
int32
|
||||
runtime·gotraceback(void)
|
||||
{
|
||||
@ -519,25 +527,35 @@ runtime·nanotime(void)
|
||||
void
|
||||
runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool)
|
||||
{
|
||||
Func *f;
|
||||
Func *f, *g;
|
||||
uintptr pc;
|
||||
uintptr rpc[2];
|
||||
|
||||
if(runtime·callers(1+skip, &retpc, 1) == 0) {
|
||||
/*
|
||||
* Ask for two PCs: the one we were asked for
|
||||
* and what it called, so that we can see if it
|
||||
* "called" sigpanic.
|
||||
*/
|
||||
retpc = 0;
|
||||
if(runtime·callers(1+skip-1, rpc, 2) < 2) {
|
||||
retfile = runtime·emptystring;
|
||||
retline = 0;
|
||||
retbool = false;
|
||||
} else if((f = runtime·findfunc(retpc)) == nil) {
|
||||
} else if((f = runtime·findfunc(rpc[1])) == nil) {
|
||||
retfile = runtime·emptystring;
|
||||
retline = 0;
|
||||
retbool = true; // have retpc at least
|
||||
} else {
|
||||
retpc = rpc[1];
|
||||
retfile = f->src;
|
||||
pc = retpc;
|
||||
if(pc > f->entry)
|
||||
g = runtime·findfunc(rpc[0]);
|
||||
if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic))
|
||||
pc--;
|
||||
retline = runtime·funcline(f, pc);
|
||||
retbool = true;
|
||||
}
|
||||
FLUSH(&retpc);
|
||||
FLUSH(&retfile);
|
||||
FLUSH(&retline);
|
||||
FLUSH(&retbool);
|
||||
|
46
test/fixedbugs/bug348.go
Normal file
46
test/fixedbugs/bug348.go
Normal file
@ -0,0 +1,46 @@
|
||||
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func f() {
|
||||
var x *string
|
||||
|
||||
for _, i := range *x { // THIS IS LINE 17
|
||||
println(i)
|
||||
}
|
||||
}
|
||||
|
||||
func g() {
|
||||
}
|
||||
|
||||
func main() {
|
||||
defer func() {
|
||||
for i := 0;; i++ {
|
||||
pc, file, line, ok := runtime.Caller(i)
|
||||
if !ok {
|
||||
print("BUG: bug348: cannot find caller\n")
|
||||
return
|
||||
}
|
||||
if !strings.Contains(file, "bug348.go") || runtime.FuncForPC(pc).Name() != "main.f" {
|
||||
// walk past runtime frames
|
||||
continue
|
||||
}
|
||||
if line != 17 {
|
||||
print("BUG: bug348: panic at ", file, ":", line, " in ", runtime.FuncForPC(pc).Name(), "\n")
|
||||
return
|
||||
}
|
||||
recover()
|
||||
return
|
||||
}
|
||||
}()
|
||||
f()
|
||||
}
|
Loading…
Reference in New Issue
Block a user