aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCherry Mui <cherryyz@google.com>2022-07-21 18:23:39 -0400
committerCherry Mui <cherryyz@google.com>2022-07-22 20:12:19 +0000
commitc5da4fb7ac5cb7434b41fc9a1df3bee66c7f1a4d (patch)
treeb08e68f973f410d1291c00e7fa0cb1f279f730a1
parent774fa58d1d3c9926709e108afdf83af7010bde72 (diff)
downloadgo-c5da4fb7ac5cb7434b41fc9a1df3bee66c7f1a4d.tar.gz
go-c5da4fb7ac5cb7434b41fc9a1df3bee66c7f1a4d.zip
cmd/compile: make jump table symbol local
When using plugins, if the plugin and the main executable both have the same function, and if it uses jump table, currently the jump table symbol have the same name so it will be deduplicated by the dynamic linker. This causes a function in the plugin may (in the middle of the function) jump to the function with the same name in the main executable (or vice versa). But the function may be compiled slightly differently, because the plugin needs to be PIC. Jumping from the middle of one function to the other will not work. Avoid this problem by marking the jump table symbol local to a DSO. Fixes #53989. Change-Id: I2b573b9dfc22401c8a09ffe9b9ea8bb83d3700ca Reviewed-on: https://go-review.googlesource.com/c/go/+/418960 Reviewed-by: Keith Randall <khr@google.com> Run-TryBot: Cherry Mui <cherryyz@google.com> Reviewed-by: Than McIntosh <thanm@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
-rw-r--r--misc/cgo/testplugin/plugin_test.go6
-rw-r--r--misc/cgo/testplugin/testdata/issue53989/main.go32
-rw-r--r--misc/cgo/testplugin/testdata/issue53989/p/p.go52
-rw-r--r--misc/cgo/testplugin/testdata/issue53989/plugin.go13
-rw-r--r--src/cmd/compile/internal/ssa/rewrite.go1
5 files changed, 104 insertions, 0 deletions
diff --git a/misc/cgo/testplugin/plugin_test.go b/misc/cgo/testplugin/plugin_test.go
index e8587e69ba..285681018a 100644
--- a/misc/cgo/testplugin/plugin_test.go
+++ b/misc/cgo/testplugin/plugin_test.go
@@ -307,6 +307,12 @@ func TestIssue52937(t *testing.T) {
goCmd(t, "build", "-buildmode=plugin", "-o", "issue52937.so", "./issue52937/main.go")
}
+func TestIssue53989(t *testing.T) {
+ goCmd(t, "build", "-buildmode=plugin", "-o", "issue53989.so", "./issue53989/plugin.go")
+ goCmd(t, "build", "-o", "issue53989.exe", "./issue53989/main.go")
+ run(t, "./issue53989.exe")
+}
+
func TestForkExec(t *testing.T) {
// Issue 38824: importing the plugin package causes it hang in forkExec on darwin.
diff --git a/misc/cgo/testplugin/testdata/issue53989/main.go b/misc/cgo/testplugin/testdata/issue53989/main.go
new file mode 100644
index 0000000000..6907dfd858
--- /dev/null
+++ b/misc/cgo/testplugin/testdata/issue53989/main.go
@@ -0,0 +1,32 @@
+// Copyright 2022 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.
+
+// Issue 53989: the use of jump table caused a function
+// from the plugin jumps in the middle of the function
+// to the function with the same name in the main
+// executable. As these two functions may be compiled
+// differently as plugin needs to be PIC, this causes
+// crash.
+
+package main
+
+import (
+ "plugin"
+
+ "testplugin/issue53989/p"
+)
+
+func main() {
+ p.Square(7) // call the function in main executable
+
+ p, err := plugin.Open("issue53989.so")
+ if err != nil {
+ panic(err)
+ }
+ f, err := p.Lookup("Square")
+ if err != nil {
+ panic(err)
+ }
+ f.(func(int))(7) // call the plugin one
+}
diff --git a/misc/cgo/testplugin/testdata/issue53989/p/p.go b/misc/cgo/testplugin/testdata/issue53989/p/p.go
new file mode 100644
index 0000000000..02567c1cee
--- /dev/null
+++ b/misc/cgo/testplugin/testdata/issue53989/p/p.go
@@ -0,0 +1,52 @@
+// Copyright 2022 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 p
+
+import (
+ "fmt"
+ "runtime"
+)
+
+var y int
+
+//go:noinline
+func Square(x int) {
+ var pc0, pc1 [1]uintptr
+ runtime.Callers(1, pc0[:]) // get PC at entry
+
+ // a switch using jump table
+ switch x {
+ case 1:
+ y = 1
+ case 2:
+ y = 4
+ case 3:
+ y = 9
+ case 4:
+ y = 16
+ case 5:
+ y = 25
+ case 6:
+ y = 36
+ case 7:
+ y = 49
+ case 8:
+ y = 64
+ default:
+ panic("too large")
+ }
+
+ // check PC is in the same function
+ runtime.Callers(1, pc1[:])
+ if pc1[0] < pc0[0] || pc1[0] > pc0[0]+1000000 {
+ fmt.Printf("jump across DSO boundary. pc0=%x, pc1=%x\n", pc0[0], pc1[0])
+ panic("FAIL")
+ }
+
+ if y != x*x {
+ fmt.Printf("x=%d y=%d!=%d\n", x, y, x*x)
+ panic("FAIL")
+ }
+}
diff --git a/misc/cgo/testplugin/testdata/issue53989/plugin.go b/misc/cgo/testplugin/testdata/issue53989/plugin.go
new file mode 100644
index 0000000000..a753ee4419
--- /dev/null
+++ b/misc/cgo/testplugin/testdata/issue53989/plugin.go
@@ -0,0 +1,13 @@
+// Copyright 2022 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 main
+
+import "testplugin/issue53989/p"
+
+func Square(x int) { // export Square for plugin
+ p.Square(x)
+}
+
+func main() {}
diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go
index d41772ad8a..05fb2f2776 100644
--- a/src/cmd/compile/internal/ssa/rewrite.go
+++ b/src/cmd/compile/internal/ssa/rewrite.go
@@ -1959,5 +1959,6 @@ func logicFlags32(x int32) flagConstant {
func makeJumpTableSym(b *Block) *obj.LSym {
s := base.Ctxt.Lookup(fmt.Sprintf("%s.jump%d", b.Func.fe.LSym(), b.ID))
s.Set(obj.AttrDuplicateOK, true)
+ s.Set(obj.AttrLocal, true)
return s
}