Skip to content

Commit 3839b60

Browse files
committed
cmd/{asm,compile,internal/obj}: add "maymorestack" support
This adds a debugging hook for optionally calling a "maymorestack" function in the prologue of any function that might call morestack (whether it does at run time or not). The maymorestack function will let us improve lock checking and add debugging modes that stress function preemption and stack growth. Passes toolstash-check -all (except on js/wasm, where toolstash appears to be broken) Fixes #48297. Change-Id: I27197947482b329af75dafb9971fc0d3a52eaf31 Reviewed-on: https://go-review.googlesource.com/c/go/+/359795 Trust: Austin Clements <[email protected]> Run-TryBot: Austin Clements <[email protected]> Reviewed-by: Cherry Mui <[email protected]>
1 parent 1c4cfd8 commit 3839b60

File tree

14 files changed

+620
-46
lines changed

14 files changed

+620
-46
lines changed

src/cmd/asm/internal/flags/flags.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ var (
2828
CompilingRuntime = flag.Bool("compiling-runtime", false, "source to be compiled is part of the Go runtime")
2929
)
3030

31+
var DebugFlags struct {
32+
MayMoreStack string `help:"call named function before all stack growth checks"`
33+
}
34+
3135
var (
3236
D MultiFlag
3337
I MultiFlag
@@ -39,6 +43,7 @@ func init() {
3943
flag.Var(&D, "D", "predefined symbol with optional simple value -D=identifier=value; can be set multiple times")
4044
flag.Var(&I, "I", "include directory; can be set multiple times")
4145
flag.BoolVar(&DebugV, "v", false, "print debug output")
46+
flag.Var(objabi.NewDebugFlag(&DebugFlags, nil), "d", "enable debugging settings; try -d help")
4247
objabi.AddVersionFlag() // -V
4348
objabi.Flagcount("S", "print assembly and machine code", &PrintOut)
4449
}

src/cmd/asm/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func main() {
4242
ctxt.Flag_dynlink = *flags.Dynlink
4343
ctxt.Flag_linkshared = *flags.Linkshared
4444
ctxt.Flag_shared = *flags.Shared || *flags.Dynlink
45+
ctxt.Flag_maymorestack = flags.DebugFlags.MayMoreStack
4546
ctxt.IsAsm = true
4647
ctxt.Pkgpath = *flags.Importpath
4748
switch *flags.Spectre {

src/cmd/compile/internal/base/debug.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type DebugFlags struct {
4242
UnifiedQuirks int `help:"enable unified IR construction's quirks mode"`
4343
WB int `help:"print information about write barriers"`
4444
ABIWrap int `help:"print information about ABI wrapper generation"`
45+
MayMoreStack string `help:"call named function before all stack growth checks"`
4546

4647
Any bool // set when any of the debug flags have been set
4748
}

src/cmd/compile/internal/base/flag.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ func ParseFlags() {
192192
Ctxt.Flag_shared = Ctxt.Flag_dynlink || Ctxt.Flag_shared
193193
Ctxt.Flag_optimize = Flag.N == 0
194194
Ctxt.Debugasm = int(Flag.S)
195+
Ctxt.Flag_maymorestack = Debug.MayMoreStack
195196

196197
if flag.NArg() < 1 {
197198
usage()

src/cmd/internal/obj/arm/obj5.go

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,61 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
634634
}
635635

636636
func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
637+
if c.ctxt.Flag_maymorestack != "" {
638+
// Save LR and make room for REGCTXT.
639+
const frameSize = 8
640+
// MOVW.W R14,$-8(SP)
641+
p = obj.Appendp(p, c.newprog)
642+
p.As = AMOVW
643+
p.Scond |= C_WBIT
644+
p.From.Type = obj.TYPE_REG
645+
p.From.Reg = REGLINK
646+
p.To.Type = obj.TYPE_MEM
647+
p.To.Offset = -frameSize
648+
p.To.Reg = REGSP
649+
p.Spadj = frameSize
650+
651+
// MOVW REGCTXT, 4(SP)
652+
p = obj.Appendp(p, c.newprog)
653+
p.As = AMOVW
654+
p.From.Type = obj.TYPE_REG
655+
p.From.Reg = REGCTXT
656+
p.To.Type = obj.TYPE_MEM
657+
p.To.Offset = 4
658+
p.To.Reg = REGSP
659+
660+
// CALL maymorestack
661+
p = obj.Appendp(p, c.newprog)
662+
p.As = obj.ACALL
663+
p.To.Type = obj.TYPE_BRANCH
664+
// See ../x86/obj6.go
665+
p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI())
666+
667+
// Restore REGCTXT and LR.
668+
669+
// MOVW 4(SP), REGCTXT
670+
p = obj.Appendp(p, c.newprog)
671+
p.As = AMOVW
672+
p.From.Type = obj.TYPE_MEM
673+
p.From.Offset = 4
674+
p.From.Reg = REGSP
675+
p.To.Type = obj.TYPE_REG
676+
p.To.Reg = REGCTXT
677+
678+
// MOVW.P 8(SP), R14
679+
p.As = AMOVW
680+
p.Scond |= C_PBIT
681+
p.From.Type = obj.TYPE_MEM
682+
p.From.Offset = frameSize
683+
p.From.Reg = REGSP
684+
p.To.Type = obj.TYPE_REG
685+
p.To.Reg = REGLINK
686+
p.Spadj = -frameSize
687+
}
688+
689+
// Jump back to here after morestack returns.
690+
startPred := p
691+
637692
// MOVW g_stackguard(g), R1
638693
p = obj.Appendp(p, c.newprog)
639694

@@ -761,7 +816,7 @@ func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
761816
b := obj.Appendp(pcdata, c.newprog)
762817
b.As = obj.AJMP
763818
b.To.Type = obj.TYPE_BRANCH
764-
b.To.SetTarget(c.cursym.Func().Text.Link)
819+
b.To.SetTarget(startPred.Link)
765820
b.Spadj = +framesize
766821

767822
return end

src/cmd/internal/obj/arm64/obj7.go

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,91 @@ var noZRreplace = map[obj.As]bool{
5858
}
5959

6060
func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
61+
if c.ctxt.Flag_maymorestack != "" {
62+
p = c.cursym.Func().SpillRegisterArgs(p, c.newprog)
63+
64+
// Save LR and make room for FP, REGCTXT. Leave room
65+
// for caller's saved FP.
66+
const frameSize = 32
67+
p = obj.Appendp(p, c.newprog)
68+
p.As = AMOVD
69+
p.From.Type = obj.TYPE_REG
70+
p.From.Reg = REGLINK
71+
p.To.Type = obj.TYPE_MEM
72+
p.Scond = C_XPRE
73+
p.To.Offset = -frameSize
74+
p.To.Reg = REGSP
75+
p.Spadj = frameSize
76+
77+
// Save FP.
78+
p = obj.Appendp(p, c.newprog)
79+
p.As = AMOVD
80+
p.From.Type = obj.TYPE_REG
81+
p.From.Reg = REGFP
82+
p.To.Type = obj.TYPE_MEM
83+
p.To.Reg = REGSP
84+
p.To.Offset = -8
85+
86+
p = obj.Appendp(p, c.newprog)
87+
p.As = ASUB
88+
p.From.Type = obj.TYPE_CONST
89+
p.From.Offset = 8
90+
p.Reg = REGSP
91+
p.To.Type = obj.TYPE_REG
92+
p.To.Reg = REGFP
93+
94+
// Save REGCTXT (for simplicity we do this whether or
95+
// not we need it.)
96+
p = obj.Appendp(p, c.newprog)
97+
p.As = AMOVD
98+
p.From.Type = obj.TYPE_REG
99+
p.From.Reg = REGCTXT
100+
p.To.Type = obj.TYPE_MEM
101+
p.To.Reg = REGSP
102+
p.To.Offset = 8
103+
104+
// BL maymorestack
105+
p = obj.Appendp(p, c.newprog)
106+
p.As = ABL
107+
p.To.Type = obj.TYPE_BRANCH
108+
// See ../x86/obj6.go
109+
p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI())
110+
111+
// Restore REGCTXT.
112+
p = obj.Appendp(p, c.newprog)
113+
p.As = AMOVD
114+
p.From.Type = obj.TYPE_MEM
115+
p.From.Reg = REGSP
116+
p.From.Offset = 8
117+
p.To.Type = obj.TYPE_REG
118+
p.To.Reg = REGCTXT
119+
120+
// Restore FP.
121+
p = obj.Appendp(p, c.newprog)
122+
p.As = AMOVD
123+
p.From.Type = obj.TYPE_MEM
124+
p.From.Reg = REGSP
125+
p.From.Offset = -8
126+
p.To.Type = obj.TYPE_REG
127+
p.To.Reg = REGFP
128+
129+
// Restore LR and SP.
130+
p = obj.Appendp(p, c.newprog)
131+
p.As = AMOVD
132+
p.From.Type = obj.TYPE_MEM
133+
p.Scond = C_XPOST
134+
p.From.Offset = frameSize
135+
p.From.Reg = REGSP
136+
p.To.Type = obj.TYPE_REG
137+
p.To.Reg = REGLINK
138+
p.Spadj = -frameSize
139+
140+
p = c.cursym.Func().UnspillRegisterArgs(p, c.newprog)
141+
}
142+
143+
// Jump back to here after morestack returns.
144+
startPred := p
145+
61146
// MOV g_stackguard(g), RT1
62147
p = obj.Appendp(p, c.newprog)
63148

@@ -212,7 +297,7 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
212297
jmp := obj.Appendp(pcdata, c.newprog)
213298
jmp.As = AB
214299
jmp.To.Type = obj.TYPE_BRANCH
215-
jmp.To.SetTarget(c.cursym.Func().Text.Link)
300+
jmp.To.SetTarget(startPred.Link)
216301
jmp.Spadj = +framesize
217302

218303
return end

src/cmd/internal/obj/link.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,8 @@ type Link struct {
880880
Flag_linkshared bool
881881
Flag_optimize bool
882882
Flag_locationlists bool
883-
Retpoline bool // emit use of retpoline stubs for indirect jmp/call
883+
Retpoline bool // emit use of retpoline stubs for indirect jmp/call
884+
Flag_maymorestack string // If not "", call this function before stack checks
884885
Bso *bufio.Writer
885886
Pathname string
886887
Pkgpath string // the current package's import path, "" if unknown

src/cmd/internal/obj/mips/obj0.go

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,82 @@ func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
658658
mov = AMOVW
659659
}
660660

661+
if c.ctxt.Flag_maymorestack != "" {
662+
// Save LR and REGCTXT.
663+
frameSize := 2 * c.ctxt.Arch.PtrSize
664+
665+
p = c.ctxt.StartUnsafePoint(p, c.newprog)
666+
667+
// MOV REGLINK, -8/-16(SP)
668+
p = obj.Appendp(p, c.newprog)
669+
p.As = mov
670+
p.From.Type = obj.TYPE_REG
671+
p.From.Reg = REGLINK
672+
p.To.Type = obj.TYPE_MEM
673+
p.To.Offset = int64(-frameSize)
674+
p.To.Reg = REGSP
675+
676+
// MOV REGCTXT, -4/-8(SP)
677+
p = obj.Appendp(p, c.newprog)
678+
p.As = mov
679+
p.From.Type = obj.TYPE_REG
680+
p.From.Reg = REGCTXT
681+
p.To.Type = obj.TYPE_MEM
682+
p.To.Offset = -int64(c.ctxt.Arch.PtrSize)
683+
p.To.Reg = REGSP
684+
685+
// ADD $-8/$-16, SP
686+
p = obj.Appendp(p, c.newprog)
687+
p.As = add
688+
p.From.Type = obj.TYPE_CONST
689+
p.From.Offset = int64(-frameSize)
690+
p.To.Type = obj.TYPE_REG
691+
p.To.Reg = REGSP
692+
p.Spadj = int32(frameSize)
693+
694+
// JAL maymorestack
695+
p = obj.Appendp(p, c.newprog)
696+
p.As = AJAL
697+
p.To.Type = obj.TYPE_BRANCH
698+
// See ../x86/obj6.go
699+
p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI())
700+
p.Mark |= BRANCH
701+
702+
// Restore LR and REGCTXT.
703+
704+
// MOV 0(SP), REGLINK
705+
p = obj.Appendp(p, c.newprog)
706+
p.As = mov
707+
p.From.Type = obj.TYPE_MEM
708+
p.From.Offset = 0
709+
p.From.Reg = REGSP
710+
p.To.Type = obj.TYPE_REG
711+
p.To.Reg = REGLINK
712+
713+
// MOV 4/8(SP), REGCTXT
714+
p = obj.Appendp(p, c.newprog)
715+
p.As = mov
716+
p.From.Type = obj.TYPE_MEM
717+
p.From.Offset = int64(c.ctxt.Arch.PtrSize)
718+
p.From.Reg = REGSP
719+
p.To.Type = obj.TYPE_REG
720+
p.To.Reg = REGCTXT
721+
722+
// ADD $8/$16, SP
723+
p = obj.Appendp(p, c.newprog)
724+
p.As = add
725+
p.From.Type = obj.TYPE_CONST
726+
p.From.Offset = int64(frameSize)
727+
p.To.Type = obj.TYPE_REG
728+
p.To.Reg = REGSP
729+
p.Spadj = int32(-frameSize)
730+
731+
p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
732+
}
733+
734+
// Jump back to here after morestack returns.
735+
startPred := p
736+
661737
// MOV g_stackguard(g), R1
662738
p = obj.Appendp(p, c.newprog)
663739

@@ -787,7 +863,8 @@ func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
787863

788864
p.As = AJMP
789865
p.To.Type = obj.TYPE_BRANCH
790-
p.To.SetTarget(c.cursym.Func().Text.Link)
866+
p.To.SetTarget(startPred.Link)
867+
startPred.Link.Mark |= LABEL
791868
p.Mark |= BRANCH
792869

793870
// placeholder for q1's jump target

0 commit comments

Comments
 (0)