Skip to content

Commit ac59d7a

Browse files
cherrymuitoothrot
authored andcommitted
[release-branch.go1.16] cmd/compile, cmd/link: dynamically export writable static tmps
Static tmps are private to a package, but with plugins a package can be shared among multiple DSOs. They need to have a consistent view of the static tmps, especially for writable ones. So export them. (Read-only static tmps have the same values anyway, so it doesn't matter. Also Mach-O doesn't support dynamically exporting read-only symbols anyway.) Updates #44956. Fixes #45030. Change-Id: I921e25b7ab73cd5d5347800eccdb7931e3448779 Reviewed-on: https://go-review.googlesource.com/c/go/+/301793 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 de012bc095359e1b552d4ea6fb6b2995f3ab04f5) Reviewed-on: https://go-review.googlesource.com/c/go/+/302449
1 parent 33fb479 commit ac59d7a

File tree

7 files changed

+93
-5
lines changed

7 files changed

+93
-5
lines changed

misc/cgo/testplugin/plugin_test.go

+7
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,10 @@ func TestMethod2(t *testing.T) {
209209
goCmd(t, "build", "-o", "method2.exe", "./method2/main.go")
210210
run(t, "./method2.exe")
211211
}
212+
213+
func TestIssue44956(t *testing.T) {
214+
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p1.so", "./issue44956/plugin1.go")
215+
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p2.so", "./issue44956/plugin2.go")
216+
goCmd(t, "build", "-o", "issue44956.exe", "./issue44956/main.go")
217+
run(t, "./issue44956.exe")
218+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
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 base
6+
7+
var X = &map[int]int{123: 456}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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+
// Issue 44956: writable static temp is not exported correctly.
6+
// In the test below, package base is
7+
//
8+
// X = &map{...}
9+
//
10+
// which compiles to
11+
//
12+
// X = &stmp // static
13+
// stmp = makemap(...) // in init function
14+
//
15+
// plugin1 and plugin2 both import base. plugin1 doesn't use
16+
// base.X, so that symbol is deadcoded in plugin1.
17+
//
18+
// plugin1 is loaded first. base.init runs at that point, which
19+
// initialize base.stmp.
20+
//
21+
// plugin2 is then loaded. base.init already ran, so it doesn't run
22+
// again. When base.stmp is not exported, plugin2's base.X points to
23+
// its own private base.stmp, which is not initialized, fail.
24+
25+
package main
26+
27+
import "plugin"
28+
29+
func main() {
30+
_, err := plugin.Open("issue44956p1.so")
31+
if err != nil {
32+
panic("FAIL")
33+
}
34+
35+
p2, err := plugin.Open("issue44956p2.so")
36+
if err != nil {
37+
panic("FAIL")
38+
}
39+
f, err := p2.Lookup("F")
40+
if err != nil {
41+
panic("FAIL")
42+
}
43+
x := f.(func() *map[int]int)()
44+
if x == nil || (*x)[123] != 456 {
45+
panic("FAIL")
46+
}
47+
}
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 main
6+
7+
import _ "testplugin/issue44956/base"
8+
9+
func main() {}
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/issue44956/base"
8+
9+
func F() *map[int]int { return base.X }
10+
11+
func main() {}

src/cmd/compile/internal/gc/sinit.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -363,15 +363,15 @@ func staticname(t *types.Type) *Node {
363363
n := newname(lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen)))
364364
statuniqgen++
365365
addvar(n, t, PEXTERN)
366-
n.Sym.Linksym().Set(obj.AttrLocal, true)
367366
return n
368367
}
369368

370-
// readonlystaticname returns a name backed by a (writable) static data symbol.
369+
// readonlystaticname returns a name backed by a read-only static data symbol.
371370
func readonlystaticname(t *types.Type) *Node {
372371
n := staticname(t)
373372
n.MarkReadonly()
374373
n.Sym.Linksym().Set(obj.AttrContentAddressable, true)
374+
n.Sym.Linksym().Set(obj.AttrLocal, true)
375375
return n
376376
}
377377

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

+10-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
package ld
3232

3333
import (
34+
"cmd/internal/obj"
3435
"cmd/internal/objabi"
3536
"cmd/link/internal/loader"
3637
"cmd/link/internal/sym"
@@ -102,10 +103,14 @@ func putelfsym(ctxt *Link, x loader.Sym, typ elf.SymType, curbind elf.SymBind) {
102103
elfshnum = xosect.Elfsect.(*ElfShdr).shnum
103104
}
104105

106+
sname := ldr.SymExtname(x)
107+
105108
// One pass for each binding: elf.STB_LOCAL, elf.STB_GLOBAL,
106109
// maybe one day elf.STB_WEAK.
107110
bind := elf.STB_GLOBAL
108-
if ldr.IsFileLocal(x) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
111+
if ldr.IsFileLocal(x) && !isStaticTmp(sname) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
112+
// Static tmp is package local, but a package can be shared among multiple DSOs.
113+
// They need to have a single view of the static tmp that are writable.
109114
bind = elf.STB_LOCAL
110115
}
111116

@@ -140,8 +145,6 @@ func putelfsym(ctxt *Link, x loader.Sym, typ elf.SymType, curbind elf.SymBind) {
140145
other |= 3 << 5
141146
}
142147

143-
sname := ldr.SymExtname(x)
144-
145148
// When dynamically linking, we create Symbols by reading the names from
146149
// the symbol tables of the shared libraries and so the names need to
147150
// match exactly. Tools like DTrace will have to wait for now.
@@ -823,3 +826,7 @@ func setCarrierSize(typ sym.SymKind, sz int64) {
823826
}
824827
CarrierSymByType[typ].Size = sz
825828
}
829+
830+
func isStaticTmp(name string) bool {
831+
return strings.Contains(name, "."+obj.StaticNamePref)
832+
}

0 commit comments

Comments
 (0)