From: Ilya Tocar Date: Mon, 13 Mar 2017 21:30:54 +0000 (-0500) Subject: cmd/internal/obj/x86: fix relocation offset for VEX encoded instructions X-Git-Tag: go1.9beta1~593 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=7f9832254c78266cf8f3bbd632c806e5c71b6d5a;p=gostls13.git cmd/internal/obj/x86: fix relocation offset for VEX encoded instructions VEX encoded instructions don't have a REX byte, so for PC relative addressing we don't need to recalculate relocation offset. Fixes #19518 Change-Id: Icf5414962de4350d76fd220817498337f90614fc Reviewed-on: https://go-review.googlesource.com/38138 Run-TryBot: Ilya Tocar TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index cee1a6516d..721768a185 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -4565,7 +4565,7 @@ func (asmbuf *AsmBuf) asmins(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog) { if int64(r.Off) < p.Pc { break } - if asmbuf.rexflag != 0 { + if asmbuf.rexflag != 0 && asmbuf.vexflag == 0 { r.Off++ } if r.Type == objabi.R_PCREL { diff --git a/src/cmd/internal/obj/x86/issue19518_test.go b/src/cmd/internal/obj/x86/issue19518_test.go new file mode 100644 index 0000000000..2fe227ee3f --- /dev/null +++ b/src/cmd/internal/obj/x86/issue19518_test.go @@ -0,0 +1,110 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package x86_test + +import ( + "bytes" + "internal/testenv" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +const asmData = ` +GLOBL zeros<>(SB),8,$64 +TEXT ·testASM(SB),4,$0 +VMOVDQU zeros<>(SB), Y8 // PC relative relocation is off by 1, for Y8-15 +RET +` + +const goData = ` +package main + +func testASM() + +func main() { + testASM() +} +` + +func objdumpOutput(t *testing.T) []byte { + cwd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + tmpdir, err := ioutil.TempDir("", "19518") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + tmpfile, err := os.Create(filepath.Join(tmpdir, "input.s")) + if err != nil { + t.Fatal(err) + } + defer tmpfile.Close() + _, err = tmpfile.WriteString(asmData) + if err != nil { + t.Fatal(err) + } + tmpfile2, err := os.Create(filepath.Join(tmpdir, "input.go")) + if err != nil { + t.Fatal(err) + } + defer tmpfile2.Close() + _, err = tmpfile2.WriteString(goData) + if err != nil { + t.Fatal(err) + } + err = os.Chdir(tmpdir) + if err != nil { + t.Fatal(err) + } + cmd := exec.Command( + testenv.GoToolPath(t), "build", "-o", + filepath.Join(tmpdir, "output")) + + var env []string + for _, v := range os.Environ() { + if !strings.HasPrefix(v, "GOARCH=") { + env = append(env, v) + } + } + cmd.Env = append(env, "GOARCH=amd64") + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("error %s output %s", err, out) + } + cmd2 := exec.Command( + testenv.GoToolPath(t), "tool", "objdump", "-s", "testASM", + filepath.Join(tmpdir, "output")) + cmd2.Env = cmd.Env + objout, err := cmd2.CombinedOutput() + if err != nil { + t.Fatalf("error %s output %s", err, objout) + } + err = os.Chdir(cwd) + if err != nil { + t.Fatal(err) + } + return objout +} + +func TestVexPCrelative(t *testing.T) { + testenv.MustHaveGoBuild(t) + objout := objdumpOutput(t) + data := bytes.Split(objout, []byte("\n")) + for idx := len(data) - 1; idx >= 0; idx-- { + // OBJDUMP doesn't know about VMOVDQU, + // so instead of checking that it was assembled correctly, + // check that RET wasn't overwritten. + if bytes.Index(data[idx], []byte("RET")) != -1 { + return + } + } + t.Fatal("RET was overwritten") +}