]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: mark plugin-exported types as used in interface
authorCherry Zhang <cherryyz@google.com>
Fri, 13 Nov 2020 19:42:45 +0000 (14:42 -0500)
committerCherry Zhang <cherryyz@google.com>
Fri, 13 Nov 2020 22:01:37 +0000 (22:01 +0000)
Plugin exports symbols as interfaces. Mark their types as used in
interfaces, so their methods will be kept alive by the linker.

Fixes #42579.

Change-Id: If1b5aacc21510c20c25f88bb131bca61db6f1d56
Reviewed-on: https://go-review.googlesource.com/c/go/+/269819
Trust: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
misc/cgo/testplugin/plugin_test.go
misc/cgo/testplugin/testdata/method/main.go [new file with mode: 0644]
misc/cgo/testplugin/testdata/method/plugin.go [new file with mode: 0644]
src/cmd/compile/internal/gc/reflect.go

index 2875271c03be39bb3e97ed9daaf95992547fecf3..9055dbda0442a63a20a81e69745b870bd61282e3 100644 (file)
@@ -196,3 +196,17 @@ func TestIssue25756(t *testing.T) {
                })
        }
 }
+
+func TestMethod(t *testing.T) {
+       // Exported symbol's method must be live.
+       goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./method/plugin.go")
+       goCmd(t, "build", "-o", "method.exe", "./method/main.go")
+
+       ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+       defer cancel()
+       cmd := exec.CommandContext(ctx, "./method.exe")
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out)
+       }
+}
diff --git a/misc/cgo/testplugin/testdata/method/main.go b/misc/cgo/testplugin/testdata/method/main.go
new file mode 100644 (file)
index 0000000..5e9189b
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2020 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 42579: methods of symbols exported from plugin must be live.
+
+package main
+
+import (
+       "plugin"
+       "reflect"
+)
+
+func main() {
+       p, err := plugin.Open("plugin.so")
+       if err != nil {
+               panic(err)
+       }
+
+       x, err := p.Lookup("X")
+       if err != nil {
+               panic(err)
+       }
+
+       reflect.ValueOf(x).Elem().MethodByName("M").Call(nil)
+}
diff --git a/misc/cgo/testplugin/testdata/method/plugin.go b/misc/cgo/testplugin/testdata/method/plugin.go
new file mode 100644 (file)
index 0000000..240edd3
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2020 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
+
+func main() {}
+
+type T int
+
+func (T) M() { println("M") }
+
+var X T
index 21429af782eb963a7ae6e822c273689732dd56fa..9401eba7a5021af1ecdd7dea5555363dcfa17d53 100644 (file)
@@ -1591,8 +1591,12 @@ func dumptabs() {
                        //      typ  typeOff // pointer to symbol
                        // }
                        nsym := dname(p.s.Name, "", nil, true)
+                       tsym := dtypesym(p.t)
                        ot = dsymptrOff(s, ot, nsym)
-                       ot = dsymptrOff(s, ot, dtypesym(p.t))
+                       ot = dsymptrOff(s, ot, tsym)
+                       // Plugin exports symbols as interfaces. Mark their types
+                       // as UsedInIface.
+                       tsym.Set(obj.AttrUsedInIface, true)
                }
                ggloblsym(s, int32(ot), int16(obj.RODATA))