]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.16] cmd/{compile,link}: fix bug in map.zero handling
authorThan McIntosh <thanm@google.com>
Thu, 15 Jul 2021 20:29:36 +0000 (16:29 -0400)
committerCarlos Amedee <carlos@golang.org>
Mon, 2 Aug 2021 22:26:52 +0000 (22:26 +0000)
In CL 326211 a change was made to switch "go.map.zero" symbols from
non-pkg DUPOK symbols to hashed symbols. The intent of this change was
ensure that in cases where there are multiple competing go.map.zero
symbols feeding into a link, the largest map.zero symbol is selected.
The change was buggy, however, and resulted in duplicate symbols in
the final binary (see bug cited below for details). This duplication
was relatively benign for linux/ELF, but causes duplicate definition
errors on Windows.

This patch switches "go.map.zero" symbols back from hashed symbols to
non-pkg DUPOK symbols, and updates the relevant code in the loader to
ensure that we do the right thing when there are multiple competing
DUPOK symbols with different sizes.

Fixes #47289.

Change-Id: I8aeb910c65827f5380144d07646006ba553c9251
Reviewed-on: https://go-review.googlesource.com/c/go/+/334930
Trust: Than McIntosh <thanm@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
(cherry picked from commit 49402bee36fd3d5cee9f4b2d2e1e8560ead0203b)
Reviewed-on: https://go-review.googlesource.com/c/go/+/335629

src/cmd/compile/internal/gc/obj.go
src/cmd/link/internal/loader/loader.go
test/fixedbugs/issue47185.dir/bad/bad.go [new file with mode: 0644]
test/fixedbugs/issue47185.dir/main.go [new file with mode: 0644]
test/fixedbugs/issue47185.go [new file with mode: 0644]

index 579e8bd823c86639b9016872f4660fd123f63d2f..da1869e945716b28ea7319dc3d7b1c79fdcdb720 100644 (file)
@@ -163,7 +163,7 @@ func dumpdata() {
        if zerosize > 0 {
                zero := mappkg.Lookup("zero")
                ggloblsym(zero.Linksym(), int32(zerosize), obj.DUPOK|obj.RODATA)
-               zero.Linksym().Set(obj.AttrContentAddressable, true)
+               zero.Linksym().Set(obj.AttrStatic, true)
        }
 
        addGCLocals()
index 971cc432ff54b10921202e6a96df60494131a039..85b948990a01c0ccf37dca261ef79c18b546000b 100644 (file)
@@ -474,6 +474,15 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
                if l.flags&FlagStrictDups != 0 {
                        l.checkdup(name, r, li, oldi)
                }
+               // Fix for issue #47185 -- given two dupok symbols with
+               // different sizes, favor symbol with larger size. See
+               // also issue #46653.
+               szdup := l.SymSize(oldi)
+               sz := int64(r.Sym(li).Siz())
+               if szdup < sz {
+                       // new symbol overwrites old symbol.
+                       l.objSyms[oldi] = objSym{r.objidx, li}
+               }
                return oldi
        }
        oldr, oldli := l.toLocal(oldi)
diff --git a/test/fixedbugs/issue47185.dir/bad/bad.go b/test/fixedbugs/issue47185.dir/bad/bad.go
new file mode 100644 (file)
index 0000000..1aa4fbb
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright 2021 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 a
+
+// Note that the use of CGO here is solely to trigger external
+// linking, since that is required to trigger that bad behavior
+// in this bug.
+
+// #include <stdlib.h>
+import "C"
+
+func Bad() {
+       m := make(map[int64]A)
+       a := m[0]
+       if len(a.B.C1.D2.E2.F1) != 0 ||
+               len(a.B.C1.D2.E2.F2) != 0 ||
+               len(a.B.C1.D2.E2.F3) != 0 ||
+               len(a.B.C1.D2.E2.F4) != 0 ||
+               len(a.B.C1.D2.E2.F5) != 0 ||
+               len(a.B.C1.D2.E2.F6) != 0 ||
+               len(a.B.C1.D2.E2.F7) != 0 ||
+               len(a.B.C1.D2.E2.F8) != 0 ||
+               len(a.B.C1.D2.E2.F9) != 0 ||
+               len(a.B.C1.D2.E2.F10) != 0 ||
+               len(a.B.C1.D2.E2.F11) != 0 ||
+               len(a.B.C1.D2.E2.F16) != 0 {
+               panic("bad")
+       }
+       C.malloc(100)
+}
+
+type A struct {
+       B
+}
+
+type B struct {
+       C1 C
+       C2 C
+}
+
+type C struct {
+       D1 D
+       D2 D
+}
+
+type D struct {
+       E1 E
+       E2 E
+       E3 E
+       E4 E
+}
+
+type E struct {
+       F1  string
+       F2  string
+       F3  string
+       F4  string
+       F5  string
+       F6  string
+       F7  string
+       F8  string
+       F9  string
+       F10 string
+       F11 string
+       F12 string
+       F13 string
+       F14 string
+       F15 string
+       F16 string
+}
diff --git a/test/fixedbugs/issue47185.dir/main.go b/test/fixedbugs/issue47185.dir/main.go
new file mode 100644 (file)
index 0000000..7b46e55
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2021 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
+
+import (
+       bad "issue47185.dir/bad"
+)
+
+func main() {
+       another()
+       bad.Bad()
+}
+
+func another() L {
+       m := make(map[string]L)
+       return m[""]
+}
+
+type L struct {
+       A Data
+       B Data
+}
+
+type Data struct {
+       F1 [22][]string
+}
diff --git a/test/fixedbugs/issue47185.go b/test/fixedbugs/issue47185.go
new file mode 100644 (file)
index 0000000..9c921b8
--- /dev/null
@@ -0,0 +1,11 @@
+// +build cgo
+// runindir
+
+// Copyright 2021 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.
+
+// Another test to verify compiler and linker handling of multiple
+// competing map.zero symbol definitions.
+
+package ignored