]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: avoid deadcode of global map vars for programs using plugins
authorThan McIntosh <thanm@google.com>
Wed, 6 Sep 2023 14:15:37 +0000 (10:15 -0400)
committerThan McIntosh <thanm@google.com>
Thu, 7 Sep 2023 13:18:51 +0000 (13:18 +0000)
If a program imports the plugin package, the mechanisms in place for
detecting and deleting unused global map variables are no longer safe,
since it's possibly for a given global map var to be unreferenced in
the main program but referenced by a plugin. This patch changes the
linker to test for plugin use and to avoid removing any unused global
map variables if the main program could possibly load up a plugin.

Fixes #62430.

Change-Id: Ie00b18b681cb0d259e3c859ac947ade5778cd6c8
Reviewed-on: https://go-review.googlesource.com/c/go/+/526115
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/cmd/cgo/internal/testplugin/plugin_test.go
src/cmd/cgo/internal/testplugin/testdata/issue62430/main.go [new file with mode: 0644]
src/cmd/cgo/internal/testplugin/testdata/issue62430/plugin.go [new file with mode: 0644]
src/cmd/link/internal/ld/deadcode.go

index 2950b6c97006c75a8c573670b18c1bb5c33b43b2..1e32ff8a066f30204ab425392ba6a2f0b85076c5 100644 (file)
@@ -388,3 +388,10 @@ func TestSymbolNameMangle(t *testing.T) {
        globalSkip(t)
        goCmd(t, "build", "-buildmode=plugin", "-o", "mangle.so", "./mangle/plugin.go")
 }
+
+func TestIssue62430(t *testing.T) {
+       globalSkip(t)
+       goCmd(t, "build", "-buildmode=plugin", "-o", "issue62430.so", "./issue62430/plugin.go")
+       goCmd(t, "build", "-o", "issue62430.exe", "./issue62430/main.go")
+       run(t, "./issue62430.exe")
+}
diff --git a/src/cmd/cgo/internal/testplugin/testdata/issue62430/main.go b/src/cmd/cgo/internal/testplugin/testdata/issue62430/main.go
new file mode 100644 (file)
index 0000000..8010840
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2023 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 62430: a program that uses plugins may appear
+// to have no references to an initialized global map variable defined
+// in some stdlib package (ex: unicode), however there
+// may be references to that map var from a plugin that
+// gets loaded.
+
+package main
+
+import (
+       "fmt"
+       "plugin"
+       "unicode"
+)
+
+func main() {
+       p, err := plugin.Open("issue62430.so")
+       if err != nil {
+               panic(err)
+       }
+       s, err := p.Lookup("F")
+       if err != nil {
+               panic(err)
+       }
+
+       f := s.(func(string) *unicode.RangeTable)
+       if f("C") == nil {
+               panic("unicode.Categories not properly initialized")
+       } else {
+               fmt.Println("unicode.Categories properly initialized")
+       }
+}
diff --git a/src/cmd/cgo/internal/testplugin/testdata/issue62430/plugin.go b/src/cmd/cgo/internal/testplugin/testdata/issue62430/plugin.go
new file mode 100644 (file)
index 0000000..e42cd8b
--- /dev/null
@@ -0,0 +1,11 @@
+package main
+
+import (
+       "unicode"
+)
+
+func F(s string) *unicode.RangeTable {
+       return unicode.Categories[s]
+}
+
+func main() {}
index b365a3b39e18c651d33341f2d85eb41eedd588c7..a051e43401691575d79116b2f973b30424fdc1af 100644 (file)
@@ -143,10 +143,26 @@ func (d *deadcodePass) flood() {
                methods = methods[:0]
                for i := 0; i < relocs.Count(); i++ {
                        r := relocs.At(i)
-                       // When build with "-linkshared", we can't tell if the interface
-                       // method in itab will be used or not. Ignore the weak attribute.
-                       if r.Weak() && !(d.ctxt.linkShared && d.ldr.IsItab(symIdx)) {
-                               continue
+                       if r.Weak() {
+                               convertWeakToStrong := false
+                               // When build with "-linkshared", we can't tell if the
+                               // interface method in itab will be used or not.
+                               // Ignore the weak attribute.
+                               if d.ctxt.linkShared && d.ldr.IsItab(symIdx) {
+                                       convertWeakToStrong = true
+                               }
+                               // If the program uses plugins, we can no longer treat
+                               // relocs from pkg init functions to outlined map init
+                               // fragments as weak, since doing so can cause package
+                               // init clashes between the main program and the
+                               // plugin. See #62430 for more details.
+                               if d.ctxt.canUsePlugins && r.Type().IsDirectCall() {
+                                       convertWeakToStrong = true
+                               }
+                               if !convertWeakToStrong {
+                                       // skip this reloc
+                                       continue
+                               }
                        }
                        t := r.Type()
                        switch t {