diff options
author | Cherry Mui <cherryyz@google.com> | 2022-06-22 16:28:41 -0400 |
---|---|---|
committer | David Chase <drchase@google.com> | 2022-06-29 16:36:06 +0000 |
commit | 3562977b6fe944b2c3da0455bdd6e9294c47c931 (patch) | |
tree | 53156123107f2bcfa4550627a1758a0fb9a8c8a6 | |
parent | d6481d5b9662b29453004204746945a93a6b4eb2 (diff) | |
download | go-3562977b6fe944b2c3da0455bdd6e9294c47c931.tar.gz go-3562977b6fe944b2c3da0455bdd6e9294c47c931.zip |
cmd/internal/obj/mips,s390x,riscv: save LR after decrementing SP
Following CL 412474, for the rest of the LR architectures. On
MIPS(32/64), S390X, and RISCV, there is no single instruction that
saves the LR and decrements the SP, so we need to insert an
instruction to save the LR after decrementing the SP.
On ARM(32) and PPC64 we already use a single instruction to save
the LR and decrement the SP.
Updates #53374.
Change-Id: I5a2e211026d95edb0e0f7d084ddb784f8077b86d
Reviewed-on: https://go-review.googlesource.com/c/go/+/413428
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
-rw-r--r-- | src/cmd/asm/internal/asm/testdata/mips64.s | 8 | ||||
-rw-r--r-- | src/cmd/internal/obj/mips/obj0.go | 14 | ||||
-rw-r--r-- | src/cmd/internal/obj/riscv/obj.go | 10 | ||||
-rw-r--r-- | src/cmd/internal/obj/s390x/objz.go | 13 |
4 files changed, 41 insertions, 4 deletions
diff --git a/src/cmd/asm/internal/asm/testdata/mips64.s b/src/cmd/asm/internal/asm/testdata/mips64.s index 99044d89f7..8f628e26c9 100644 --- a/src/cmd/asm/internal/asm/testdata/mips64.s +++ b/src/cmd/asm/internal/asm/testdata/mips64.s @@ -21,9 +21,9 @@ label0: BEQ R1, 2(PC) JMP label0+0 // JMP 3 // 1000fffd BEQ R1, 2(PC) - JAL 1(PC) // CALL 1(PC) // 0c00000e + JAL 1(PC) // CALL 1(PC) // 0c00000f BEQ R1, 2(PC) - JAL label0+0 // CALL 3 // 0c000006 + JAL label0+0 // CALL 3 // 0c000007 // LBRA addr // { @@ -32,11 +32,11 @@ label0: BEQ R1, 2(PC) JMP 0(R1) // JMP (R1) // 00200008 BEQ R1, 2(PC) - JMP foo+0(SB) // JMP foo(SB) // 08000018 + JMP foo+0(SB) // JMP foo(SB) // 08000019 BEQ R1, 2(PC) JAL 0(R1) // CALL (R1) // 0020f809 BEQ R1, 2(PC) - JAL foo+0(SB) // CALL foo(SB) // 0c000020 + JAL foo+0(SB) // CALL foo(SB) // 0c000021 // // BEQ/BNE diff --git a/src/cmd/internal/obj/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go index 2a2c8ecb75..9241dfd631 100644 --- a/src/cmd/internal/obj/mips/obj0.go +++ b/src/cmd/internal/obj/mips/obj0.go @@ -343,6 +343,20 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q.Spadj = +autosize q = c.ctxt.EndUnsafePoint(q, c.newprog, -1) + + // On Linux, in a cgo binary we may get a SIGSETXID signal early on + // before the signal stack is set, as glibc doesn't allow us to block + // SIGSETXID. So a signal may land on the current stack and clobber + // the content below the SP. We store the LR again after the SP is + // decremented. + q = obj.Appendp(q, newprog) + q.As = mov + q.Pos = p.Pos + q.From.Type = obj.TYPE_REG + q.From.Reg = REGLINK + q.To.Type = obj.TYPE_MEM + q.To.Offset = 0 + q.To.Reg = REGSP } if c.cursym.Func().Text.From.Sym.Wrapper() && c.cursym.Func().Text.Mark&LEAF == 0 { diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index b30958cb38..34aa923f4a 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -410,6 +410,16 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { prologue.Spadj = int32(stacksize) prologue = ctxt.EndUnsafePoint(prologue, newprog, -1) + + // On Linux, in a cgo binary we may get a SIGSETXID signal early on + // before the signal stack is set, as glibc doesn't allow us to block + // SIGSETXID. So a signal may land on the current stack and clobber + // the content below the SP. We store the LR again after the SP is + // decremented. + prologue = obj.Appendp(prologue, newprog) + prologue.As = AMOV + prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR} + prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0} } if cursym.Func().Text.From.Sym.Wrapper() { diff --git a/src/cmd/internal/obj/s390x/objz.go b/src/cmd/internal/obj/s390x/objz.go index fed7703759..4e8475624d 100644 --- a/src/cmd/internal/obj/s390x/objz.go +++ b/src/cmd/internal/obj/s390x/objz.go @@ -358,6 +358,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q.Spadj = autosize q = c.ctxt.EndUnsafePoint(q, c.newprog, -1) + + // On Linux, in a cgo binary we may get a SIGSETXID signal early on + // before the signal stack is set, as glibc doesn't allow us to block + // SIGSETXID. So a signal may land on the current stack and clobber + // the content below the SP. We store the LR again after the SP is + // decremented. + q = obj.Appendp(q, c.newprog) + q.As = AMOVD + q.From.Type = obj.TYPE_REG + q.From.Reg = REG_LR + q.To.Type = obj.TYPE_MEM + q.To.Reg = REGSP + q.To.Offset = 0 } else if c.cursym.Func().Text.Mark&LEAF == 0 { // A very few functions that do not return to their caller // (e.g. gogo) are not identified as leaves but still have |