From d33548d178016122726342911f8e15016a691472 Mon Sep 17 00:00:00 2001 From: Wang Yaduo Date: Fri, 27 Oct 2023 14:48:25 +0800 Subject: [PATCH] cmd/internal/obj/riscv: fix the offset of JALR transformed from JAL MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 TryBot-Result: Gopher Robot Reviewed-by: Heschi Kreinick Reviewed-by: M Zhuo Reviewed-by: Joel Sing Reviewed-by: Cherry Mui --- src/cmd/internal/obj/riscv/asm_test.go | 66 ++++++++++++++++++++++++++ src/cmd/internal/obj/riscv/obj.go | 2 +- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/cmd/internal/obj/riscv/asm_test.go b/src/cmd/internal/obj/riscv/asm_test.go index c22428cdc5..afe0525532 100644 --- a/src/cmd/internal/obj/riscv/asm_test.go +++ b/src/cmd/internal/obj/riscv/asm_test.go @@ -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") diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 501d518019..279c8678a7 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -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 } } } -- 2.44.0