Skip to content

Commit a9547ad

Browse files
cherrymuidmitshur
authored andcommitted
[release-branch.go1.16] cmd/link: handle types as converted to interface when dynlink
When using plugins, a type (whose value) may be pass to a plugin and get converted to interface there, or vice versa. We need to treat the type as potentially converted to interface, and retain its methods. Updates #44586. Fixes #44638. Change-Id: I80dd35e68baedaa852a317543ccd78d94628d13b Reviewed-on: https://go-review.googlesource.com/c/go/+/296709 Trust: Cherry Zhang <[email protected]> Run-TryBot: Cherry Zhang <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Than McIntosh <[email protected]> (cherry picked from commit a655208) Reviewed-on: https://go-review.googlesource.com/c/go/+/296910
1 parent 292abd9 commit a9547ad

File tree

5 files changed

+65
-7
lines changed

5 files changed

+65
-7
lines changed

misc/cgo/testplugin/plugin_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,11 @@ func TestMethod(t *testing.T) {
201201
// Exported symbol's method must be live.
202202
goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./method/plugin.go")
203203
goCmd(t, "build", "-o", "method.exe", "./method/main.go")
204+
run(t, "./method.exe")
205+
}
204206

205-
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
206-
defer cancel()
207-
cmd := exec.CommandContext(ctx, "./method.exe")
208-
out, err := cmd.CombinedOutput()
209-
if err != nil {
210-
t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out)
211-
}
207+
func TestMethod2(t *testing.T) {
208+
goCmd(t, "build", "-buildmode=plugin", "-o", "method2.so", "./method2/plugin.go")
209+
goCmd(t, "build", "-o", "method2.exe", "./method2/main.go")
210+
run(t, "./method2.exe")
212211
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// A type can be passed to a plugin and converted to interface
6+
// there. So its methods need to be live.
7+
8+
package main
9+
10+
import (
11+
"plugin"
12+
13+
"testplugin/method2/p"
14+
)
15+
16+
var t p.T
17+
18+
type I interface { M() }
19+
20+
func main() {
21+
pl, err := plugin.Open("method2.so")
22+
if err != nil {
23+
panic(err)
24+
}
25+
26+
f, err := pl.Lookup("F")
27+
if err != nil {
28+
panic(err)
29+
}
30+
31+
f.(func(p.T) interface{})(t).(I).M()
32+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
type T int
8+
9+
func (T) M() { println("M") }
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
import "testplugin/method2/p"
8+
9+
func main() {}
10+
11+
func F(t p.T) interface{} { return t }

src/cmd/link/internal/ld/deadcode.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type deadcodePass struct {
2424
ifaceMethod map[methodsig]bool // methods declared in reached interfaces
2525
markableMethods []methodref // methods of reached types
2626
reflectSeen bool // whether we have seen a reflect method call
27+
dynlink bool
2728

2829
methodsigstmp []methodsig // scratch buffer for decoding method signatures
2930
}
@@ -34,6 +35,7 @@ func (d *deadcodePass) init() {
3435
if objabi.Fieldtrack_enabled != 0 {
3536
d.ldr.Reachparent = make([]loader.Sym, d.ldr.NSym())
3637
}
38+
d.dynlink = d.ctxt.DynlinkingGo()
3739

3840
if d.ctxt.BuildMode == BuildModeShared {
3941
// Mark all symbols defined in this library as reachable when
@@ -111,6 +113,11 @@ func (d *deadcodePass) flood() {
111113
var usedInIface bool
112114

113115
if isgotype {
116+
if d.dynlink {
117+
// When dynaamic linking, a type may be passed across DSO
118+
// boundary and get converted to interface at the other side.
119+
d.ldr.SetAttrUsedInIface(symIdx, true)
120+
}
114121
usedInIface = d.ldr.AttrUsedInIface(symIdx)
115122
}
116123

0 commit comments

Comments
 (0)