mirror of
https://github.com/golang/go
synced 2024-11-25 14:17:57 -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;
|
Node *fn, *tmp;
|
||||||
NodeList *body, *init;
|
NodeList *body, *init;
|
||||||
Type *th, *t;
|
Type *th, *t;
|
||||||
|
int lno;
|
||||||
|
|
||||||
t = n->type;
|
t = n->type;
|
||||||
init = nil;
|
init = nil;
|
||||||
|
|
||||||
a = n->right;
|
a = n->right;
|
||||||
|
lno = setlineno(a);
|
||||||
if(t->etype == TSTRING && !eqtype(t, types[TSTRING])) {
|
if(t->etype == TSTRING && !eqtype(t, types[TSTRING])) {
|
||||||
a = nod(OCONV, n->right, N);
|
a = nod(OCONV, n->right, N);
|
||||||
a->type = types[TSTRING];
|
a->type = types[TSTRING];
|
||||||
@ -248,5 +250,7 @@ walkrange(Node *n)
|
|||||||
typechecklist(body, Etop);
|
typechecklist(body, Etop);
|
||||||
n->nbody = concat(body, n->nbody);
|
n->nbody = concat(body, n->nbody);
|
||||||
walkstmt(&n);
|
walkstmt(&n);
|
||||||
|
|
||||||
|
lineno = lno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ void runtime·deferproc(void);
|
|||||||
void runtime·newproc(void);
|
void runtime·newproc(void);
|
||||||
void runtime·newstack(void);
|
void runtime·newstack(void);
|
||||||
void runtime·morestack(void);
|
void runtime·morestack(void);
|
||||||
|
void runtime·sigpanic(void);
|
||||||
|
|
||||||
// This code is also used for the 386 tracebacks.
|
// This code is also used for the 386 tracebacks.
|
||||||
// Use uintptr for an appropriate word-sized integer.
|
// 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;
|
byte *fp;
|
||||||
Stktop *stk;
|
Stktop *stk;
|
||||||
Func *f;
|
Func *f;
|
||||||
|
bool waspanic;
|
||||||
|
|
||||||
USED(lr0);
|
USED(lr0);
|
||||||
pc = (uintptr)pc0;
|
pc = (uintptr)pc0;
|
||||||
lr = 0;
|
lr = 0;
|
||||||
fp = nil;
|
fp = nil;
|
||||||
|
waspanic = false;
|
||||||
|
|
||||||
// If the PC is goexit, the goroutine hasn't started yet.
|
// If the PC is goexit, the goroutine hasn't started yet.
|
||||||
if(pc0 == g->sched.pc && sp == g->sched.sp && pc0 == (byte*)runtime·goexit) {
|
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)
|
if(pc > f->entry)
|
||||||
runtime·printf("+%p", (uintptr)(pc - f->entry));
|
runtime·printf("+%p", (uintptr)(pc - f->entry));
|
||||||
tracepc = pc; // back up to CALL instruction for funcline.
|
tracepc = pc; // back up to CALL instruction for funcline.
|
||||||
if(n > 0 && pc > f->entry)
|
if(n > 0 && pc > f->entry && !waspanic)
|
||||||
tracepc--;
|
tracepc--;
|
||||||
runtime·printf(" %S:%d\n", f->src, runtime·funcline(f, tracepc));
|
runtime·printf(" %S:%d\n", f->src, runtime·funcline(f, tracepc));
|
||||||
runtime·printf("\t%S(", f->name);
|
runtime·printf("\t%S(", f->name);
|
||||||
@ -144,6 +147,8 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
waspanic = f->entry == (uintptr)runtime·sigpanic;
|
||||||
|
|
||||||
if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
|
if(f->entry == (uintptr)runtime·deferproc || f->entry == (uintptr)runtime·newproc)
|
||||||
fp += 2*sizeof(uintptr);
|
fp += 2*sizeof(uintptr);
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ void runtime·deferproc(void);
|
|||||||
void runtime·newproc(void);
|
void runtime·newproc(void);
|
||||||
void runtime·newstack(void);
|
void runtime·newstack(void);
|
||||||
void runtime·morestack(void);
|
void runtime·morestack(void);
|
||||||
|
void runtime·sigpanic(void);
|
||||||
void _div(void);
|
void _div(void);
|
||||||
void _mod(void);
|
void _mod(void);
|
||||||
void _divu(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;
|
int32 i, n, iter;
|
||||||
uintptr pc, lr, tracepc, x;
|
uintptr pc, lr, tracepc, x;
|
||||||
byte *fp, *p;
|
byte *fp, *p;
|
||||||
|
bool waspanic;
|
||||||
Stktop *stk;
|
Stktop *stk;
|
||||||
Func *f;
|
Func *f;
|
||||||
|
|
||||||
pc = (uintptr)pc0;
|
pc = (uintptr)pc0;
|
||||||
lr = (uintptr)lr0;
|
lr = (uintptr)lr0;
|
||||||
fp = nil;
|
fp = nil;
|
||||||
|
waspanic = false;
|
||||||
|
|
||||||
// If the PC is goexit, the goroutine hasn't started yet.
|
// If the PC is goexit, the goroutine hasn't started yet.
|
||||||
if(pc == (uintptr)runtime·goexit) {
|
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)
|
if(pc > f->entry)
|
||||||
runtime·printf("+%p", (uintptr)(pc - f->entry));
|
runtime·printf("+%p", (uintptr)(pc - f->entry));
|
||||||
tracepc = pc; // back up to CALL instruction for funcline.
|
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);
|
tracepc -= sizeof(uintptr);
|
||||||
runtime·printf(" %S:%d\n", f->src, runtime·funcline(f, tracepc));
|
runtime·printf(" %S:%d\n", f->src, runtime·funcline(f, tracepc));
|
||||||
runtime·printf("\t%S(", f->name);
|
runtime·printf("\t%S(", f->name);
|
||||||
@ -138,6 +141,8 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *g, int32 skip, uintptr
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
waspanic = f->entry == (uintptr)runtime·sigpanic;
|
||||||
|
|
||||||
if(pcbuf == nil && f->entry == (uintptr)runtime·newstack && g == m->g0) {
|
if(pcbuf == nil && f->entry == (uintptr)runtime·newstack && g == m->g0) {
|
||||||
runtime·printf("----- newstack called from goroutine %d -----\n", m->curg->goid);
|
runtime·printf("----- newstack called from goroutine %d -----\n", m->curg->goid);
|
||||||
pc = (uintptr)m->morepc;
|
pc = (uintptr)m->morepc;
|
||||||
|
@ -167,3 +167,14 @@ os·sigpipe(void)
|
|||||||
{
|
{
|
||||||
runtime·throw("too many writes on closed pipe");
|
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;
|
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
|
int32
|
||||||
runtime·gotraceback(void)
|
runtime·gotraceback(void)
|
||||||
{
|
{
|
||||||
@ -519,25 +527,35 @@ runtime·nanotime(void)
|
|||||||
void
|
void
|
||||||
runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool)
|
runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool)
|
||||||
{
|
{
|
||||||
Func *f;
|
Func *f, *g;
|
||||||
uintptr pc;
|
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;
|
retfile = runtime·emptystring;
|
||||||
retline = 0;
|
retline = 0;
|
||||||
retbool = false;
|
retbool = false;
|
||||||
} else if((f = runtime·findfunc(retpc)) == nil) {
|
} else if((f = runtime·findfunc(rpc[1])) == nil) {
|
||||||
retfile = runtime·emptystring;
|
retfile = runtime·emptystring;
|
||||||
retline = 0;
|
retline = 0;
|
||||||
retbool = true; // have retpc at least
|
retbool = true; // have retpc at least
|
||||||
} else {
|
} else {
|
||||||
|
retpc = rpc[1];
|
||||||
retfile = f->src;
|
retfile = f->src;
|
||||||
pc = retpc;
|
pc = retpc;
|
||||||
if(pc > f->entry)
|
g = runtime·findfunc(rpc[0]);
|
||||||
|
if(pc > f->entry && (g == nil || g->entry != (uintptr)runtime·sigpanic))
|
||||||
pc--;
|
pc--;
|
||||||
retline = runtime·funcline(f, pc);
|
retline = runtime·funcline(f, pc);
|
||||||
retbool = true;
|
retbool = true;
|
||||||
}
|
}
|
||||||
|
FLUSH(&retpc);
|
||||||
FLUSH(&retfile);
|
FLUSH(&retfile);
|
||||||
FLUSH(&retline);
|
FLUSH(&retline);
|
||||||
FLUSH(&retbool);
|
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