Commit 12a5774c authored by Russ Cox's avatar Russ Cox

gc, runtime: fix range+panic line number bugs

Fixes #1856.

R=ken2
CC=golang-dev
https://golang.org/cl/4810054
parent cce10dac
......@@ -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);
......@@ -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);
......
......@@ -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;
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);
......
// $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()
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment