Commit 141a4a17 authored by Russ Cox's avatar Russ Cox

runtime: fix arm reflect.call boundary case

The fault was lucky: when it wasn't faulting it was silently
copying a word from some other block and later putting
that same word back.  If some other goroutine had changed
that word of memory in the interim, too bad.

The ARM code was inconsistent about whether the
"argument frame" included the saved LR.  Including it made
some things more regular but mostly just caused confusion
in the places where the regularity broke.  Now the rule
reflects reality: argp is always a pointer to arguments,
never a saved link register.

Renamed struct fields to make meaning clearer.

Running ARM in QEMU, package time's gotest:
  * before: 27/58 failed
  * after: 0/50

R=r, r2
CC=golang-dev
https://golang.org/cl/3993041
parent 5adfe937
...@@ -172,7 +172,7 @@ ginscall(Node *f, int proc) ...@@ -172,7 +172,7 @@ ginscall(Node *f, int proc)
p->to.reg = REGSP; p->to.reg = REGSP;
p->to.offset = 8; p->to.offset = 8;
nodconst(&con, types[TINT32], argsize(f->type) + 4); nodconst(&con, types[TINT32], argsize(f->type));
gins(AMOVW, &con, &r); gins(AMOVW, &con, &r);
p = gins(AMOVW, &r, N); p = gins(AMOVW, &r, N);
p->to.type = D_OREG; p->to.type = D_OREG;
......
...@@ -340,13 +340,12 @@ noops(void) ...@@ -340,13 +340,12 @@ noops(void)
p->to.type = D_REG; p->to.type = D_REG;
p->to.reg = 1; p->to.reg = 1;
// MOVW.LO $args +4, R2 // MOVW.LO $args, R2
// also need to store the extra 4 bytes.
p = appendp(p); p = appendp(p);
p->as = AMOVW; p->as = AMOVW;
p->scond = C_SCOND_LO; p->scond = C_SCOND_LO;
p->from.type = D_CONST; p->from.type = D_CONST;
p->from.offset = ((cursym->text->to.offset2 + 3) & ~3) + 4; p->from.offset = (cursym->text->to.offset2 + 3) & ~3;
p->to.type = D_REG; p->to.type = D_REG;
p->to.reg = 2; p->to.reg = 2;
...@@ -391,12 +390,12 @@ noops(void) ...@@ -391,12 +390,12 @@ noops(void)
p->to.type = D_REG; p->to.type = D_REG;
p->to.reg = 1; p->to.reg = 1;
// MOVW $args +4, R2 // MOVW $args, R2
// also need to store the extra 4 bytes. // also need to store the extra 4 bytes.
p = appendp(p); p = appendp(p);
p->as = AMOVW; p->as = AMOVW;
p->from.type = D_CONST; p->from.type = D_CONST;
p->from.offset = ((cursym->text->to.offset2 + 3) & ~3) + 4; p->from.offset = (cursym->text->to.offset2 + 3) & ~3;
p->to.type = D_REG; p->to.type = D_REG;
p->to.reg = 2; p->to.reg = 2;
......
...@@ -156,8 +156,8 @@ TEXT runtime·morestack(SB),7,$0 ...@@ -156,8 +156,8 @@ TEXT runtime·morestack(SB),7,$0
// frame size in DX // frame size in DX
// arg size in AX // arg size in AX
// Save in m. // Save in m.
MOVL DX, m_moreframe(BX) MOVL DX, m_moreframesize(BX)
MOVL AX, m_moreargs(BX) MOVL AX, m_moreargsize(BX)
// Called from f. // Called from f.
// Set m->morebuf to f's caller. // Set m->morebuf to f's caller.
...@@ -165,7 +165,7 @@ TEXT runtime·morestack(SB),7,$0 ...@@ -165,7 +165,7 @@ TEXT runtime·morestack(SB),7,$0
MOVL DI, (m_morebuf+gobuf_pc)(BX) MOVL DI, (m_morebuf+gobuf_pc)(BX)
LEAL 8(SP), CX // f's caller's SP LEAL 8(SP), CX // f's caller's SP
MOVL CX, (m_morebuf+gobuf_sp)(BX) MOVL CX, (m_morebuf+gobuf_sp)(BX)
MOVL CX, (m_morefp)(BX) MOVL CX, m_moreargp(BX)
get_tls(CX) get_tls(CX)
MOVL g(CX), SI MOVL g(CX), SI
MOVL SI, (m_morebuf+gobuf_g)(BX) MOVL SI, (m_morebuf+gobuf_g)(BX)
...@@ -213,9 +213,9 @@ TEXT reflect·call(SB), 7, $0 ...@@ -213,9 +213,9 @@ TEXT reflect·call(SB), 7, $0
MOVL 12(SP), CX // arg size MOVL 12(SP), CX // arg size
MOVL AX, m_morepc(BX) // f's PC MOVL AX, m_morepc(BX) // f's PC
MOVL DX, m_morefp(BX) // argument frame pointer MOVL DX, m_moreargp(BX) // f's argument pointer
MOVL CX, m_moreargs(BX) // f's argument size MOVL CX, m_moreargsize(BX) // f's argument size
MOVL $1, m_moreframe(BX) // f's frame size MOVL $1, m_moreframesize(BX) // f's frame size
// Call newstack on m's scheduling stack. // Call newstack on m's scheduling stack.
MOVL m_g0(BX), BP MOVL m_g0(BX), BP
......
...@@ -151,7 +151,7 @@ TEXT runtime·morestack(SB),7,$0 ...@@ -151,7 +151,7 @@ TEXT runtime·morestack(SB),7,$0
MOVQ AX, (m_morebuf+gobuf_pc)(BX) MOVQ AX, (m_morebuf+gobuf_pc)(BX)
LEAQ 16(SP), AX // f's caller's SP LEAQ 16(SP), AX // f's caller's SP
MOVQ AX, (m_morebuf+gobuf_sp)(BX) MOVQ AX, (m_morebuf+gobuf_sp)(BX)
MOVQ AX, (m_morefp)(BX) MOVQ AX, m_moreargp(BX)
get_tls(CX) get_tls(CX)
MOVQ g(CX), SI MOVQ g(CX), SI
MOVQ SI, (m_morebuf+gobuf_g)(BX) MOVQ SI, (m_morebuf+gobuf_g)(BX)
...@@ -197,9 +197,9 @@ TEXT reflect·call(SB), 7, $0 ...@@ -197,9 +197,9 @@ TEXT reflect·call(SB), 7, $0
MOVL 24(SP), CX // arg size MOVL 24(SP), CX // arg size
MOVQ AX, m_morepc(BX) // f's PC MOVQ AX, m_morepc(BX) // f's PC
MOVQ DX, m_morefp(BX) // argument frame pointer MOVQ DX, m_moreargp(BX) // argument frame pointer
MOVL CX, m_moreargs(BX) // f's argument size MOVL CX, m_moreargsize(BX) // f's argument size
MOVL $1, m_moreframe(BX) // f's frame size MOVL $1, m_moreframesize(BX) // f's frame size
// Call newstack on m's scheduling stack. // Call newstack on m's scheduling stack.
MOVQ m_g0(BX), BP MOVQ m_g0(BX), BP
...@@ -230,7 +230,7 @@ TEXT runtime·morestack00(SB),7,$0 ...@@ -230,7 +230,7 @@ TEXT runtime·morestack00(SB),7,$0
get_tls(CX) get_tls(CX)
MOVQ m(CX), BX MOVQ m(CX), BX
MOVQ $0, AX MOVQ $0, AX
MOVQ AX, m_moreframe(BX) MOVQ AX, m_moreframesize(BX)
MOVQ $runtime·morestack(SB), AX MOVQ $runtime·morestack(SB), AX
JMP AX JMP AX
...@@ -238,7 +238,7 @@ TEXT runtime·morestack01(SB),7,$0 ...@@ -238,7 +238,7 @@ TEXT runtime·morestack01(SB),7,$0
get_tls(CX) get_tls(CX)
MOVQ m(CX), BX MOVQ m(CX), BX
SHLQ $32, AX SHLQ $32, AX
MOVQ AX, m_moreframe(BX) MOVQ AX, m_moreframesize(BX)
MOVQ $runtime·morestack(SB), AX MOVQ $runtime·morestack(SB), AX
JMP AX JMP AX
...@@ -246,14 +246,14 @@ TEXT runtime·morestack10(SB),7,$0 ...@@ -246,14 +246,14 @@ TEXT runtime·morestack10(SB),7,$0
get_tls(CX) get_tls(CX)
MOVQ m(CX), BX MOVQ m(CX), BX
MOVLQZX AX, AX MOVLQZX AX, AX
MOVQ AX, m_moreframe(BX) MOVQ AX, m_moreframesize(BX)
MOVQ $runtime·morestack(SB), AX MOVQ $runtime·morestack(SB), AX
JMP AX JMP AX
TEXT runtime·morestack11(SB),7,$0 TEXT runtime·morestack11(SB),7,$0
get_tls(CX) get_tls(CX)
MOVQ m(CX), BX MOVQ m(CX), BX
MOVQ AX, m_moreframe(BX) MOVQ AX, m_moreframesize(BX)
MOVQ $runtime·morestack(SB), AX MOVQ $runtime·morestack(SB), AX
JMP AX JMP AX
...@@ -294,7 +294,7 @@ TEXT morestack<>(SB),7,$0 ...@@ -294,7 +294,7 @@ TEXT morestack<>(SB),7,$0
MOVQ m(CX), BX MOVQ m(CX), BX
POPQ AX POPQ AX
SHLQ $35, AX SHLQ $35, AX
MOVQ AX, m_moreframe(BX) MOVQ AX, m_moreframesize(BX)
MOVQ $runtime·morestack(SB), AX MOVQ $runtime·morestack(SB), AX
JMP AX JMP AX
......
...@@ -145,14 +145,15 @@ TEXT runtime·morestack(SB),7,$-4 ...@@ -145,14 +145,15 @@ TEXT runtime·morestack(SB),7,$-4
BL.EQ runtime·abort(SB) BL.EQ runtime·abort(SB)
// Save in m. // Save in m.
MOVW R1, m_moreframe(m) MOVW R1, m_moreframesize(m)
MOVW R2, m_moreargs(m) MOVW R2, m_moreargsize(m)
// Called from f. // Called from f.
// Set m->morebuf to f's caller. // Set m->morebuf to f's caller.
MOVW R3, (m_morebuf+gobuf_pc)(m) // f's caller's PC MOVW R3, (m_morebuf+gobuf_pc)(m) // f's caller's PC
MOVW SP, (m_morebuf+gobuf_sp)(m) // f's caller's SP MOVW SP, (m_morebuf+gobuf_sp)(m) // f's caller's SP
MOVW SP, m_morefp(m) // f's caller's SP MOVW $4(SP), R3 // f's argument pointer
MOVW R3, m_moreargp(m)
MOVW g, (m_morebuf+gobuf_g)(m) MOVW g, (m_morebuf+gobuf_g)(m)
// Set m->morepc to f's PC. // Set m->morepc to f's PC.
...@@ -185,14 +186,11 @@ TEXT reflect·call(SB), 7, $-4 ...@@ -185,14 +186,11 @@ TEXT reflect·call(SB), 7, $-4
MOVW 8(SP), R1 // arg frame MOVW 8(SP), R1 // arg frame
MOVW 12(SP), R2 // arg size MOVW 12(SP), R2 // arg size
SUB $4,R1 // add the saved LR to the frame
ADD $4,R2
MOVW R0, m_morepc(m) // f's PC MOVW R0, m_morepc(m) // f's PC
MOVW R1, m_morefp(m) // argument frame pointer MOVW R1, m_moreargp(m) // f's argument pointer
MOVW R2, m_moreargs(m) // f's argument size MOVW R2, m_moreargsize(m) // f's argument size
MOVW $1, R3 MOVW $1, R3
MOVW R3, m_moreframe(m) // f's frame size MOVW R3, m_moreframesize(m) // f's frame size
// Call newstack on m's scheduling stack. // Call newstack on m's scheduling stack.
MOVW m_g0(m), g MOVW m_g0(m), g
...@@ -218,8 +216,9 @@ TEXT runtime·lessstack(SB), 7, $-4 ...@@ -218,8 +216,9 @@ TEXT runtime·lessstack(SB), 7, $-4
TEXT runtime·jmpdefer(SB), 7, $0 TEXT runtime·jmpdefer(SB), 7, $0
MOVW 0(SP), LR MOVW 0(SP), LR
MOVW $-4(LR), LR // BL deferreturn MOVW $-4(LR), LR // BL deferreturn
MOVW 4(SP), R0 // fn MOVW fn+0(FP), R0
MOVW 8(SP), SP MOVW argp+4(FP), SP
MOVW $-4(SP), SP // SP is 4 below argp, due to saved LR
B (R0) B (R0)
TEXT runtime·memclr(SB),7,$20 TEXT runtime·memclr(SB),7,$20
......
...@@ -470,8 +470,8 @@ scheduler(void) ...@@ -470,8 +470,8 @@ scheduler(void)
d = gp->defer; d = gp->defer;
gp->defer = d->link; gp->defer = d->link;
// unwind to the stack frame with d->sp in it. // unwind to the stack frame with d's arguments in it.
unwindstack(gp, d->sp); unwindstack(gp, d->argp);
// make the deferproc for this d return again, // make the deferproc for this d return again,
// this time returning 1. function will jump to // this time returning 1. function will jump to
...@@ -481,7 +481,11 @@ scheduler(void) ...@@ -481,7 +481,11 @@ scheduler(void)
// each call to deferproc. // each call to deferproc.
// (the pc we're returning to does pop pop // (the pc we're returning to does pop pop
// before it tests the return value.) // before it tests the return value.)
gp->sched.sp = runtime·getcallersp(d->sp - 2*sizeof(uintptr)); // on the arm there are 2 saved LRs mixed in too.
if(thechar == '5')
gp->sched.sp = (byte*)d->argp - 4*sizeof(uintptr);
else
gp->sched.sp = (byte*)d->argp - 2*sizeof(uintptr);
gp->sched.pc = d->pc; gp->sched.pc = d->pc;
gp->status = Grunning; gp->status = Grunning;
runtime·free(d); runtime·free(d);
...@@ -633,7 +637,6 @@ void ...@@ -633,7 +637,6 @@ void
runtime·startcgocallback(G* g1) runtime·startcgocallback(G* g1)
{ {
Defer *d; Defer *d;
uintptr arg;
runtime·lock(&runtime·sched); runtime·lock(&runtime·sched);
g1->status = Grunning; g1->status = Grunning;
...@@ -687,7 +690,7 @@ runtime·endcgocallback(G* g1) ...@@ -687,7 +690,7 @@ runtime·endcgocallback(G* g1)
* the stack is allowed to protrude StackSmall bytes * the stack is allowed to protrude StackSmall bytes
* below the stack guard. functions with large frames * below the stack guard. functions with large frames
* don't bother with the check and always call morestack. * don't bother with the check and always call morestack.
* the sequences are: * the sequences are (for amd64, others are similar):
* *
* guard = g->stackguard * guard = g->stackguard
* frame = function's stack frame size * frame = function's stack frame size
...@@ -748,7 +751,7 @@ void ...@@ -748,7 +751,7 @@ void
runtime·oldstack(void) runtime·oldstack(void)
{ {
Stktop *top, old; Stktop *top, old;
uint32 args; uint32 argsize;
byte *sp; byte *sp;
G *g1; G *g1;
static int32 goid; static int32 goid;
...@@ -759,10 +762,10 @@ runtime·oldstack(void) ...@@ -759,10 +762,10 @@ runtime·oldstack(void)
top = (Stktop*)g1->stackbase; top = (Stktop*)g1->stackbase;
sp = (byte*)top; sp = (byte*)top;
old = *top; old = *top;
args = old.args; argsize = old.argsize;
if(args > 0) { if(argsize > 0) {
sp -= args; sp -= argsize;
runtime·mcpy(top->fp, sp, args); runtime·mcpy(top->argp, sp, argsize);
} }
goid = old.gobuf.g->goid; // fault if g is bad, before gogo goid = old.gobuf.g->goid; // fault if g is bad, before gogo
...@@ -777,22 +780,26 @@ runtime·oldstack(void) ...@@ -777,22 +780,26 @@ runtime·oldstack(void)
void void
runtime·newstack(void) runtime·newstack(void)
{ {
int32 frame, args; int32 framesize, argsize;
Stktop *top; Stktop *top;
byte *stk, *sp; byte *stk, *sp;
G *g1; G *g1;
Gobuf label; Gobuf label;
bool free; bool free, reflectcall;
frame = m->moreframe; framesize = m->moreframesize;
args = m->moreargs; argsize = m->moreargsize;
g1 = m->curg; g1 = m->curg;
if(m->morebuf.sp < g1->stackguard - StackGuard) if(m->morebuf.sp < g1->stackguard - StackGuard)
runtime·throw("split stack overflow"); runtime·throw("split stack overflow");
if(frame == 1 && args > 0 && m->morebuf.sp - sizeof(Stktop) - args - 32 > g1->stackguard) { reflectcall = framesize==1;
// special case: called from reflect.call (frame == 1) if(reflectcall)
framesize = 0;
if(reflectcall && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > g1->stackguard) {
// special case: called from reflect.call (framesize==1)
// to call code with an arbitrary argument size, // to call code with an arbitrary argument size,
// and we have enough space on the current stack. // and we have enough space on the current stack.
// the new Stktop* is necessary to unwind, but // the new Stktop* is necessary to unwind, but
...@@ -802,14 +809,12 @@ runtime·newstack(void) ...@@ -802,14 +809,12 @@ runtime·newstack(void)
free = false; free = false;
} else { } else {
// allocate new segment. // allocate new segment.
if(frame == 1) // failed reflect.call hint framesize += argsize;
frame = 0; if(framesize < StackBig)
frame += args; framesize = StackBig;
if(frame < StackBig) framesize += 1024; // room for more functions, Stktop.
frame = StackBig; stk = runtime·stackalloc(framesize);
frame += 1024; // room for more functions, Stktop. top = (Stktop*)(stk+framesize-sizeof(*top));
stk = runtime·stackalloc(frame);
top = (Stktop*)(stk+frame-sizeof(*top));
free = true; free = true;
} }
...@@ -819,8 +824,8 @@ runtime·newstack(void) ...@@ -819,8 +824,8 @@ runtime·newstack(void)
top->stackbase = g1->stackbase; top->stackbase = g1->stackbase;
top->stackguard = g1->stackguard; top->stackguard = g1->stackguard;
top->gobuf = m->morebuf; top->gobuf = m->morebuf;
top->fp = m->morefp; top->argp = m->moreargp;
top->args = args; top->argsize = argsize;
top->free = free; top->free = free;
// copy flag from panic // copy flag from panic
...@@ -831,9 +836,14 @@ runtime·newstack(void) ...@@ -831,9 +836,14 @@ runtime·newstack(void)
g1->stackguard = stk + StackGuard; g1->stackguard = stk + StackGuard;
sp = (byte*)top; sp = (byte*)top;
if(args > 0) { if(argsize > 0) {
sp -= args; sp -= argsize;
runtime·mcpy(sp, m->morefp, args); runtime·mcpy(sp, m->moreargp, argsize);
}
if(thechar == '5') {
// caller would have saved its LR below args.
sp -= sizeof(void*);
*(void**)sp = nil;
} }
// Continue as if lessstack had just called m->morepc // Continue as if lessstack had just called m->morepc
...@@ -876,7 +886,13 @@ runtime·malg(int32 stacksize) ...@@ -876,7 +886,13 @@ runtime·malg(int32 stacksize)
void void
runtime·newproc(int32 siz, byte* fn, ...) runtime·newproc(int32 siz, byte* fn, ...)
{ {
runtime·newproc1(fn, (byte*)(&fn+1), siz, 0); byte *argp;
if(thechar == '5')
argp = (byte*)(&fn+2); // skip caller's saved LR
else
argp = (byte*)(&fn+1);
runtime·newproc1(fn, argp, siz, 0);
} }
G* G*
...@@ -908,6 +924,11 @@ runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret) ...@@ -908,6 +924,11 @@ runtime·newproc1(byte *fn, byte *argp, int32 narg, int32 nret)
sp = newg->stackbase; sp = newg->stackbase;
sp -= siz; sp -= siz;
runtime·mcpy(sp, argp, narg); runtime·mcpy(sp, argp, narg);
if(thechar == '5') {
// caller's LR
sp -= sizeof(void*);
*(void**)sp = nil;
}
newg->sched.sp = sp; newg->sched.sp = sp;
newg->sched.pc = (byte*)runtime·goexit; newg->sched.pc = (byte*)runtime·goexit;
...@@ -933,10 +954,13 @@ runtime·deferproc(int32 siz, byte* fn, ...) ...@@ -933,10 +954,13 @@ runtime·deferproc(int32 siz, byte* fn, ...)
d = runtime·malloc(sizeof(*d) + siz - sizeof(d->args)); d = runtime·malloc(sizeof(*d) + siz - sizeof(d->args));
d->fn = fn; d->fn = fn;
d->sp = (byte*)(&fn+1);
d->siz = siz; d->siz = siz;
d->pc = runtime·getcallerpc(&siz); d->pc = runtime·getcallerpc(&siz);
runtime·mcpy(d->args, d->sp, d->siz); if(thechar == '5')
d->argp = (byte*)(&fn+2); // skip caller's saved link register
else
d->argp = (byte*)(&fn+1);
runtime·mcpy(d->args, d->argp, d->siz);
d->link = g->defer; d->link = g->defer;
g->defer = d; g->defer = d;
...@@ -955,19 +979,19 @@ void ...@@ -955,19 +979,19 @@ void
runtime·deferreturn(uintptr arg0) runtime·deferreturn(uintptr arg0)
{ {
Defer *d; Defer *d;
byte *sp, *fn; byte *argp, *fn;
d = g->defer; d = g->defer;
if(d == nil) if(d == nil)
return; return;
sp = runtime·getcallersp(&arg0); argp = (byte*)&arg0;
if(d->sp != sp) if(d->argp != argp)
return; return;
runtime·mcpy(d->sp, d->args, d->siz); runtime·mcpy(argp, d->args, d->siz);
g->defer = d->link; g->defer = d->link;
fn = d->fn; fn = d->fn;
runtime·free(d); runtime·free(d);
runtime·jmpdefer(fn, sp); runtime·jmpdefer(fn, argp);
} }
static void static void
...@@ -983,7 +1007,7 @@ rundefer(void) ...@@ -983,7 +1007,7 @@ rundefer(void)
} }
// Free stack frames until we hit the last one // Free stack frames until we hit the last one
// or until we find the one that contains the sp. // or until we find the one that contains the argp.
static void static void
unwindstack(G *gp, byte *sp) unwindstack(G *gp, byte *sp)
{ {
...@@ -1043,10 +1067,7 @@ runtime·panic(Eface e) ...@@ -1043,10 +1067,7 @@ runtime·panic(Eface e)
// take defer off list in case of recursive panic // take defer off list in case of recursive panic
g->defer = d->link; g->defer = d->link;
g->ispanic = true; // rock for newstack, where reflect.call ends up g->ispanic = true; // rock for newstack, where reflect.call ends up
if(thechar == '5') reflect·call(d->fn, d->args, d->siz);
reflect·call(d->fn, d->args+4, d->siz-4); // reflect.call does not expect LR
else
reflect·call(d->fn, d->args, d->siz);
if(p->recovered) { if(p->recovered) {
g->panic = p->link; g->panic = p->link;
runtime·free(p); runtime·free(p);
...@@ -1068,13 +1089,11 @@ runtime·panic(Eface e) ...@@ -1068,13 +1089,11 @@ runtime·panic(Eface e)
#pragma textflag 7 /* no split, or else g->stackguard is not the stack for fp */ #pragma textflag 7 /* no split, or else g->stackguard is not the stack for fp */
void void
runtime·recover(byte *fp, Eface ret) runtime·recover(byte *argp, Eface ret)
{ {
Stktop *top, *oldtop; Stktop *top, *oldtop;
Panic *p; Panic *p;
fp = runtime·getcallersp(fp);
// Must be a panic going on. // Must be a panic going on.
if((p = g->panic) == nil || p->recovered) if((p = g->panic) == nil || p->recovered)
goto nomatch; goto nomatch;
...@@ -1097,11 +1116,11 @@ runtime·recover(byte *fp, Eface ret) ...@@ -1097,11 +1116,11 @@ runtime·recover(byte *fp, Eface ret)
// allocated a second segment (see below), // allocated a second segment (see below),
// the fp is slightly above top - top->args. // the fp is slightly above top - top->args.
// That condition can't happen normally though // That condition can't happen normally though
// (stack pointer go down, not up), so we can accept // (stack pointers go down, not up), so we can accept
// any fp between top and top - top->args as // any fp between top and top - top->args as
// indicating the top of the segment. // indicating the top of the segment.
top = (Stktop*)g->stackbase; top = (Stktop*)g->stackbase;
if(fp < (byte*)top - top->args || (byte*)top < fp) if(argp < (byte*)top - top->argsize || (byte*)top < argp)
goto nomatch; goto nomatch;
// The deferred call makes a new segment big enough // The deferred call makes a new segment big enough
...@@ -1117,7 +1136,7 @@ runtime·recover(byte *fp, Eface ret) ...@@ -1117,7 +1136,7 @@ runtime·recover(byte *fp, Eface ret)
// bytes above top->fp) abuts the old top of stack. // bytes above top->fp) abuts the old top of stack.
// This is a correct test for both closure and non-closure code. // This is a correct test for both closure and non-closure code.
oldtop = (Stktop*)top->stackbase; oldtop = (Stktop*)top->stackbase;
if(oldtop != nil && top->fp == (byte*)oldtop - top->args) if(oldtop != nil && top->argp == (byte*)oldtop - top->argsize)
top = oldtop; top = oldtop;
// Now we have the segment that was created to // Now we have the segment that was created to
......
...@@ -205,12 +205,12 @@ struct M ...@@ -205,12 +205,12 @@ struct M
// The offsets of these fields are known to (hard-coded in) libmach. // The offsets of these fields are known to (hard-coded in) libmach.
G* g0; // goroutine with scheduling stack G* g0; // goroutine with scheduling stack
void (*morepc)(void); void (*morepc)(void);
void* morefp; // frame pointer for more stack void* moreargp; // argument pointer for more stack
Gobuf morebuf; // gobuf arg to morestack Gobuf morebuf; // gobuf arg to morestack
// Fields not known to debuggers. // Fields not known to debuggers.
uint32 moreframe; // size arguments to morestack uint32 moreframesize; // size arguments to morestack
uint32 moreargs; uint32 moreargsize;
uintptr cret; // return value from C uintptr cret; // return value from C
uint64 procid; // for debuggers, but offset not hard-coded uint64 procid; // for debuggers, but offset not hard-coded
G* gsignal; // signal-handling G G* gsignal; // signal-handling G
...@@ -243,12 +243,9 @@ struct Stktop ...@@ -243,12 +243,9 @@ struct Stktop
uint8* stackguard; uint8* stackguard;
uint8* stackbase; uint8* stackbase;
Gobuf gobuf; Gobuf gobuf;
uint32 args; uint32 argsize;
// Frame pointer: where args start in old frame. uint8* argp; // pointer to arguments in old frame
// fp == gobuf.sp except in the case of a reflected
// function call, which uses an off-stack argument frame.
uint8* fp;
bool free; // call stackfree for this frame? bool free; // call stackfree for this frame?
bool panic; // is this frame the top of a panic? bool panic; // is this frame the top of a panic?
}; };
...@@ -333,7 +330,7 @@ enum { ...@@ -333,7 +330,7 @@ enum {
struct Defer struct Defer
{ {
int32 siz; int32 siz;
byte* sp; byte* argp; // where args were copied from
byte* pc; byte* pc;
byte* fn; byte* fn;
Defer* link; Defer* link;
......
...@@ -84,32 +84,32 @@ type g_ struct { ...@@ -84,32 +84,32 @@ type g_ struct {
} }
type m_ struct { type m_ struct {
g0 *g_ g0 *g_
morepc unsafe.Pointer morepc unsafe.Pointer
morefp unsafe.Pointer moreargp unsafe.Pointer
morebuf gobuf morebuf gobuf
moreframe uint32 moreframesize uint32
moreargs uint32 moreargsize uint32
cret uintptr cret uintptr
procid uint64 procid uint64
gsignal *g_ gsignal *g_
tls [8]uint32 tls [8]uint32
sched gobuf sched gobuf
curg *g_ curg *g_
id int32 id int32
mallocing int32 mallocing int32
gcing int32 gcing int32
locks int32 locks int32
nomemprof int32 nomemprof int32
waitnextg int32 waitnextg int32
havenextg note havenextg note
nextg *g_ nextg *g_
alllink *m_ alllink *m_
schedlink *m_ schedlink *m_
machport uint32 machport uint32
mcache *mCache mcache *mCache
lockedg *g_ lockedg *g_
freg [8]uint64 freg [8]uint64
// gostack unsafe.Pointer // __WINDOWS__ // gostack unsafe.Pointer // __WINDOWS__
} }
......
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