]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: support plugins with no exported symbols
authorDavid Crawshaw <crawshaw@golang.org>
Mon, 31 Oct 2016 03:53:09 +0000 (23:53 -0400)
committerDavid Crawshaw <crawshaw@golang.org>
Tue, 1 Nov 2016 20:56:30 +0000 (20:56 +0000)
A plugin with no exported symbols is still potentially very useful.
Its init functions are called on load, and it so it can have visible
side effects.

Fixes #17681

Change-Id: Icdca31f48e5ab13c99020a2ef724f3de47dcd74b
Reviewed-on: https://go-review.googlesource.com/32437
Run-TryBot: David Crawshaw <crawshaw@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
misc/cgo/testplugin/src/host/host.go
misc/cgo/testplugin/src/plugin2/plugin2.go [new file with mode: 0644]
misc/cgo/testplugin/test.bash
src/cmd/link/internal/ld/deadcode.go
src/cmd/link/internal/ld/symtab.go

index 0fe28663c7cefb1775c3edf2c4e9b4ac059637b0..636655aa5c92d25c65e11a1a01d3e7b7e61bb6ef 100644 (file)
@@ -84,5 +84,13 @@ func main() {
                log.Fatalf(`plugin1.F()=%d, want 17`, gotf)
        }
 
+       // plugin2 has no exported symbols, only an init function.
+       if _, err := plugin.Open("plugin2.so"); err != nil {
+               log.Fatalf("plugin.Open failed: %v", err)
+       }
+       if got, want := common.X, 2; got != want {
+               log.Fatalf("after loading plugin2, common.X=%d, want %d", got, want)
+       }
+
        fmt.Println("PASS")
 }
diff --git a/misc/cgo/testplugin/src/plugin2/plugin2.go b/misc/cgo/testplugin/src/plugin2/plugin2.go
new file mode 100644 (file)
index 0000000..6c23a5e
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2016 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
+
+// // No C code required.
+import "C"
+
+import "common"
+
+func init() {
+       common.X = 2
+}
+
+func main() {
+       panic("plugin1.main called")
+}
index 7a40934e0e4acefd86baac6ea1dcd5b6d6c6b909..322d43901da6b178123d9577292a9c474074cdfa 100755 (executable)
@@ -23,6 +23,7 @@ rm -rf pkg sub
 mkdir sub
 
 GOPATH=$(pwd) go build -buildmode=plugin plugin1
+GOPATH=$(pwd) go build -buildmode=plugin plugin2
 GOPATH=$(pwd) go build -buildmode=plugin -o=sub/plugin1.so sub/plugin1
 GOPATH=$(pwd) go build host
 
index 7ecc5b1ec2298c1b04762185694420ad2698c8d7..ac6481322819e6840e4a4b475de3a64e4cc9172c 100644 (file)
@@ -252,8 +252,10 @@ func (d *deadcodepass) init() {
                        // We don't keep the go.plugin.exports symbol,
                        // but we do keep the symbols it refers to.
                        exports := d.ctxt.Syms.ROLookup("go.plugin.exports", 0)
-                       for _, r := range exports.R {
-                               d.mark(r.Sym, nil)
+                       if exports != nil {
+                               for _, r := range exports.R {
+                                       d.mark(r.Sym, nil)
+                               }
                        }
                }
                for _, name := range markextra {
index ef96c04067510a567daf87b726fc277a7485a4f7..323136c6f918d14a4f6059851590866253134981 100644 (file)
@@ -588,8 +588,7 @@ func (ctxt *Link) symtab() {
        adduint(ctxt, moduledata, uint64(nitablinks))
        adduint(ctxt, moduledata, uint64(nitablinks))
        // The ptab slice
-       if Buildmode == BuildmodePlugin {
-               ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0)
+       if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil {
                ptab.Attr |= AttrReachable
                ptab.Attr |= AttrLocal
                ptab.Type = obj.SRODATA