mirror of https://github.com/golang/go.git
[dev.power64] cmd/ld, runtime: detect, fix nosplit overflows
LGTM=minux R=minux CC=golang-codereviews https://golang.org/cl/121690043
This commit is contained in:
parent
6edd1c6d1a
commit
ed68c7df55
|
|
@ -1026,7 +1026,7 @@ static LSym *newstack;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
HasLinkRegister = (thechar == '5'),
|
HasLinkRegister = (thechar == '5' || thechar == '9'),
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Record enough information in new object files to
|
// TODO: Record enough information in new object files to
|
||||||
|
|
@ -1035,7 +1035,7 @@ enum
|
||||||
static int
|
static int
|
||||||
callsize(void)
|
callsize(void)
|
||||||
{
|
{
|
||||||
if(thechar == '5')
|
if(HasLinkRegister)
|
||||||
return 0;
|
return 0;
|
||||||
return RegSize;
|
return RegSize;
|
||||||
}
|
}
|
||||||
|
|
@ -1046,9 +1046,6 @@ dostkcheck(void)
|
||||||
Chain ch;
|
Chain ch;
|
||||||
LSym *s;
|
LSym *s;
|
||||||
|
|
||||||
if(thechar == '9')
|
|
||||||
return;
|
|
||||||
|
|
||||||
morestack = linklookup(ctxt, "runtime.morestack", 0);
|
morestack = linklookup(ctxt, "runtime.morestack", 0);
|
||||||
newstack = linklookup(ctxt, "runtime.newstack", 0);
|
newstack = linklookup(ctxt, "runtime.newstack", 0);
|
||||||
|
|
||||||
|
|
@ -1072,19 +1069,19 @@ dostkcheck(void)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(s->nosplit) {
|
if(s->nosplit) {
|
||||||
ctxt->cursym = s;
|
ctxt->cursym = s;
|
||||||
ch.sym = s;
|
ch.sym = s;
|
||||||
stkcheck(&ch, 0);
|
stkcheck(&ch, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(s = ctxt->textp; s != nil; s = s->next) {
|
for(s = ctxt->textp; s != nil; s = s->next) {
|
||||||
if(!s->nosplit) {
|
if(!s->nosplit) {
|
||||||
ctxt->cursym = s;
|
ctxt->cursym = s;
|
||||||
ch.sym = s;
|
ch.sym = s;
|
||||||
stkcheck(&ch, 0);
|
stkcheck(&ch, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
stkcheck(Chain *up, int depth)
|
stkcheck(Chain *up, int depth)
|
||||||
|
|
@ -1102,7 +1099,7 @@ stkcheck(Chain *up, int depth)
|
||||||
// function at top of safe zone once.
|
// function at top of safe zone once.
|
||||||
if(limit == StackLimit-callsize()) {
|
if(limit == StackLimit-callsize()) {
|
||||||
if(s->stkcheck)
|
if(s->stkcheck)
|
||||||
return 0;
|
return 0;
|
||||||
s->stkcheck = 1;
|
s->stkcheck = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1161,8 +1158,8 @@ stkcheck(Chain *up, int depth)
|
||||||
// to StackLimit beyond the frame size.
|
// to StackLimit beyond the frame size.
|
||||||
if(strncmp(r->sym->name, "runtime.morestack", 17) == 0) {
|
if(strncmp(r->sym->name, "runtime.morestack", 17) == 0) {
|
||||||
limit = StackLimit + s->locals;
|
limit = StackLimit + s->locals;
|
||||||
if(thechar == '5')
|
if(HasLinkRegister)
|
||||||
limit += 4; // saved LR
|
limit += RegSize;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -1181,7 +1178,7 @@ stkcheck(Chain *up, int depth)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1210,7 +1207,7 @@ stkprint(Chain *ch, int limit)
|
||||||
else
|
else
|
||||||
print("\t%d\tguaranteed after split check in %s\n", ch->limit, name);
|
print("\t%d\tguaranteed after split check in %s\n", ch->limit, name);
|
||||||
} else {
|
} else {
|
||||||
stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize);
|
stkprint(ch->up, ch->limit + (!HasLinkRegister)*RegSize);
|
||||||
if(!HasLinkRegister)
|
if(!HasLinkRegister)
|
||||||
print("\t%d\ton entry to %s\n", ch->limit, name);
|
print("\t%d\ton entry to %s\n", ch->limit, name);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,9 +49,22 @@ runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
|
||||||
runtime·futex(addr, FUTEX_WAIT, val, nil, nil, 0);
|
runtime·futex(addr, FUTEX_WAIT, val, nil, nil, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
|
|
||||||
|
// It's difficult to live within the no-split stack limits here.
|
||||||
|
// On ARM and 386, a 64-bit divide invokes a general software routine
|
||||||
|
// that needs more stack than we can afford. So we use timediv instead.
|
||||||
|
// But on real 64-bit systems, where words are larger but the stack limit
|
||||||
|
// is not, even timediv is too heavy, and we really need to use just an
|
||||||
|
// ordinary machine instruction.
|
||||||
|
// Sorry for the #ifdef.
|
||||||
|
// For what it's worth, the #ifdef eliminated an implicit little-endian assumption.
|
||||||
|
#ifdef _64BIT
|
||||||
|
ts.tv_sec = ns / 1000000000LL;
|
||||||
|
ts.tv_nsec = ns % 1000000000LL;
|
||||||
|
#else
|
||||||
ts.tv_nsec = 0;
|
ts.tv_nsec = 0;
|
||||||
ts.tv_sec = runtime·timediv(ns, 1000000000LL, (int32*)&ts.tv_nsec);
|
ts.tv_sec = runtime·timediv(ns, 1000000000LL, (int32*)&ts.tv_nsec);
|
||||||
|
#endif
|
||||||
runtime·futex(addr, FUTEX_WAIT, val, &ts, nil, 0);
|
runtime·futex(addr, FUTEX_WAIT, val, &ts, nil, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,22 +39,18 @@ func concatstrings(a []string) string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
|
||||||
func concatstring2(a [2]string) string {
|
func concatstring2(a [2]string) string {
|
||||||
return concatstrings(a[:])
|
return concatstrings(a[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
|
||||||
func concatstring3(a [3]string) string {
|
func concatstring3(a [3]string) string {
|
||||||
return concatstrings(a[:])
|
return concatstrings(a[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
|
||||||
func concatstring4(a [4]string) string {
|
func concatstring4(a [4]string) string {
|
||||||
return concatstrings(a[:])
|
return concatstrings(a[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
|
||||||
func concatstring5(a [5]string) string {
|
func concatstring5(a [5]string) string {
|
||||||
return concatstrings(a[:])
|
return concatstrings(a[:])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,8 +126,9 @@ main 136 nosplit; REJECT
|
||||||
# Calling a nosplit function from a nosplit function requires
|
# Calling a nosplit function from a nosplit function requires
|
||||||
# having room for the saved caller PC and the called frame.
|
# having room for the saved caller PC and the called frame.
|
||||||
# Because ARM doesn't save LR in the leaf, it gets an extra 4 bytes.
|
# Because ARM doesn't save LR in the leaf, it gets an extra 4 bytes.
|
||||||
|
# Because Power64 doesn't save LR in the leaf, it gets an extra 8 bytes.
|
||||||
main 112 nosplit call f; f 0 nosplit
|
main 112 nosplit call f; f 0 nosplit
|
||||||
main 116 nosplit call f; f 0 nosplit; REJECT amd64
|
main 116 nosplit call f; f 0 nosplit
|
||||||
main 120 nosplit call f; f 0 nosplit; REJECT amd64
|
main 120 nosplit call f; f 0 nosplit; REJECT amd64
|
||||||
main 124 nosplit call f; f 0 nosplit; REJECT amd64 386
|
main 124 nosplit call f; f 0 nosplit; REJECT amd64 386
|
||||||
main 128 nosplit call f; f 0 nosplit; REJECT
|
main 128 nosplit call f; f 0 nosplit; REJECT
|
||||||
|
|
@ -136,8 +137,8 @@ main 136 nosplit call f; f 0 nosplit; REJECT
|
||||||
|
|
||||||
# Calling a splitting function from a nosplit function requires
|
# Calling a splitting function from a nosplit function requires
|
||||||
# having room for the saved caller PC of the call but also the
|
# having room for the saved caller PC of the call but also the
|
||||||
# saved caller PC for the call to morestack. Again the ARM works
|
# saved caller PC for the call to morestack.
|
||||||
# in less space.
|
# Again the ARM and Power64 work in less space.
|
||||||
main 104 nosplit call f; f 0 call f
|
main 104 nosplit call f; f 0 call f
|
||||||
main 108 nosplit call f; f 0 call f
|
main 108 nosplit call f; f 0 call f
|
||||||
main 112 nosplit call f; f 0 call f; REJECT amd64
|
main 112 nosplit call f; f 0 call f; REJECT amd64
|
||||||
|
|
@ -235,7 +236,7 @@ TestCases:
|
||||||
switch goarch {
|
switch goarch {
|
||||||
case "power64", "power64le":
|
case "power64", "power64le":
|
||||||
ptrSize = 8
|
ptrSize = 8
|
||||||
fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n#define RET RETURN\n")
|
fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (CTR)\n#define RET RETURN\n")
|
||||||
case "arm":
|
case "arm":
|
||||||
fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n")
|
fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (R0)\n")
|
||||||
case "amd64":
|
case "amd64":
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue