]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/internal/obj/riscv: fix the offset of JALR transformed from JAL
authorWang Yaduo <wangyaduo@linux.alibaba.com>
Fri, 27 Oct 2023 06:48:25 +0000 (14:48 +0800)
committerM Zhuo <mzh@golangcn.org>
Tue, 7 Nov 2023 01:22:04 +0000 (01:22 +0000)
Currently, the offset of JALR is zero all the time, which is transformed
from JAL with over ±1MB offset. This causes the segment fault for the
wrong address.

Change-Id: I4dcb3eb13bd1ea71e9eb27f07c03ffec376608ab
Reviewed-on: https://go-review.googlesource.com/c/go/+/538135
Run-TryBot: M Zhuo <mzh@golangcn.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: M Zhuo <mzh@golangcn.org>
Reviewed-by: Joel Sing <joel@sing.id.au>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/cmd/internal/obj/riscv/asm_test.go
src/cmd/internal/obj/riscv/obj.go

index c22428cdc5b816ee3a6dc71dbd5e2c4af261a04a..afe0525532bba7a9d7cc3a26f4c77bcec755828f 100644 (file)
@@ -126,6 +126,72 @@ func genLargeCall(buf *bytes.Buffer) {
        fmt.Fprintln(buf, "RET")
 }
 
+// TestLargeJump generates a large jump (>1MB of text) with a JMP to the
+// end of the function, in order to ensure that it assembles correctly.
+func TestLargeJump(t *testing.T) {
+       if testing.Short() {
+               t.Skip("Skipping test in short mode")
+       }
+       if runtime.GOARCH != "riscv64" {
+               t.Skip("Require riscv64 to run")
+       }
+       testenv.MustHaveGoBuild(t)
+
+       dir := t.TempDir()
+
+       if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module largejump"), 0644); err != nil {
+               t.Fatalf("Failed to write file: %v\n", err)
+       }
+       main := `package main
+
+import "fmt"
+
+func main() {
+        fmt.Print(x())
+}
+
+func x() uint64
+`
+       if err := os.WriteFile(filepath.Join(dir, "x.go"), []byte(main), 0644); err != nil {
+               t.Fatalf("failed to write main: %v\n", err)
+       }
+
+       // Generate a very large jump instruction.
+       buf := bytes.NewBuffer(make([]byte, 0, 7000000))
+       genLargeJump(buf)
+
+       if err := os.WriteFile(filepath.Join(dir, "x.s"), buf.Bytes(), 0644); err != nil {
+               t.Fatalf("Failed to write file: %v\n", err)
+       }
+
+       // Build generated files.
+       cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", "x.exe")
+       cmd.Dir = dir
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               t.Errorf("Build failed: %v, output: %s", err, out)
+       }
+
+       cmd = testenv.Command(t, filepath.Join(dir, "x.exe"))
+       out, err = cmd.CombinedOutput()
+       if string(out) != "1" {
+               t.Errorf(`Got test output %q, want "1"`, string(out))
+       }
+}
+
+func genLargeJump(buf *bytes.Buffer) {
+       fmt.Fprintln(buf, "TEXT ·x(SB),0,$0-8")
+       fmt.Fprintln(buf, "MOV  X0, X10")
+       fmt.Fprintln(buf, "JMP end")
+       for i := 0; i < 1<<18; i++ {
+               fmt.Fprintln(buf, "ADD $1, X10, X10")
+       }
+       fmt.Fprintln(buf, "end:")
+       fmt.Fprintln(buf, "ADD $1, X10, X10")
+       fmt.Fprintln(buf, "MOV X10, r+0(FP)")
+       fmt.Fprintln(buf, "RET")
+}
+
 // Issue 20348.
 func TestNoRet(t *testing.T) {
        dir, err := os.MkdirTemp("", "testnoret")
index 501d518019044593e076166e0fef1a3cd6286f73..279c8678a782a3eff292c952c4c2f0244ab0b704 100644 (file)
@@ -727,7 +727,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
                                        ctxt.Diag("%v: jump displacement %d too large", p, p.To.Target().Pc-p.Pc)
                                }
                                p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high, Sym: cursym}
-                               p.Link.From.Offset = low
+                               p.Link.To.Offset = low
                        }
                }
        }