]> Cypherpunks repositories - gostls13.git/commitdiff
gc, runtime: fix range+panic line number bugs
authorRuss Cox <rsc@golang.org>
Tue, 26 Jul 2011 04:52:46 +0000 (00:52 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 26 Jul 2011 04:52:46 +0000 (00:52 -0400)
Fixes #1856.

R=ken2
CC=golang-dev
https://golang.org/cl/4810054

src/cmd/gc/range.c
src/pkg/runtime/amd64/traceback.c
src/pkg/runtime/arm/traceback.c
src/pkg/runtime/plan9/thread.c
src/pkg/runtime/runtime.c
test/fixedbugs/bug348.go [new file with mode: 0644]

index dfb2b8efd68430748bbda182565d21c4ad150e5e..fb33e4e4855f7555e8743a086fa8eb919adf237b 100644 (file)
@@ -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;
 }
 
index d422cb69229a03b2b90de66c12a50d3f5357a4ca..3e85d36bd7a3299c26a0095f57c9659a578cd8d5 100644 (file)
@@ -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);
 
index c3934c37cb4796bdb06b4dd7a2b306c2f7c079c7..5628b8349e04065da251ed1c2722ff33053163cd 100644 (file)
@@ -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);
@@ -137,6 +140,8 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
                        runtime·prints(")\n");
                        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);
index d428e7fcde9142c8ba133e7b7b17c9033d8295c6..b091c59788f9e8ee555111de759ecc77701f1d7e 100644 (file)
@@ -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)
+{
+}
index 00116c001a0e646eddf8cbf5e7d4ed7e66187fef..c572897d2c3f9dd63233b2d99a2cc6152cf78e9d 100644 (file)
@@ -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;
-
-       if(runtime·callers(1+skip, &retpc, 1) == 0) {
+       uintptr rpc[2];
+
+       /*
+        * 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);
diff --git a/test/fixedbugs/bug348.go b/test/fixedbugs/bug348.go
new file mode 100644 (file)
index 0000000..1a539aa
--- /dev/null
@@ -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()
+}