diff --git a/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go index 41a24efe22c0ed..1f426bb90b0a27 100644 --- a/misc/cgo/testshared/shared_test.go +++ b/misc/cgo/testshared/shared_test.go @@ -917,3 +917,10 @@ func TestTestInstalledShared(t *testing.T) { func TestGeneratedMethod(t *testing.T) { goCmd(t, "install", "-buildmode=shared", "-linkshared", "issue25065") } + +// Test use of shared library struct with generated hash function. +// Issue 30768. +func TestGeneratedHash(t *testing.T) { + goCmd(nil, "install", "-buildmode=shared", "-linkshared", "issue30768/issue30768lib") + goCmd(nil, "test", "-linkshared", "issue30768") +} diff --git a/misc/cgo/testshared/src/issue30768/issue30768lib/lib.go b/misc/cgo/testshared/src/issue30768/issue30768lib/lib.go new file mode 100644 index 00000000000000..9e45ebe6835521 --- /dev/null +++ b/misc/cgo/testshared/src/issue30768/issue30768lib/lib.go @@ -0,0 +1,11 @@ +// Copyright 2019 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 issue30768lib + +// S is a struct that requires a generated hash function. +type S struct { + A string + B int +} diff --git a/misc/cgo/testshared/src/issue30768/x_test.go b/misc/cgo/testshared/src/issue30768/x_test.go new file mode 100644 index 00000000000000..228da6f602cf74 --- /dev/null +++ b/misc/cgo/testshared/src/issue30768/x_test.go @@ -0,0 +1,22 @@ +// Copyright 2019 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 issue30768_test + +import ( + "testing" + + "issue30768/issue30768lib" +) + +type s struct { + s issue30768lib.S +} + +func Test30768(t *testing.T) { + // Calling t.Log will convert S to an empty interface, + // which will force a reference to the generated hash function, + // defined in the shared library. + t.Log(s{}) +} diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 2cb7ae72e4d2dc..e64a1e2b53e682 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -1802,7 +1802,15 @@ func ldshlibsyms(ctxt *Link, shlib string) { if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION { continue } - lsym := ctxt.Syms.Lookup(elfsym.Name, 0) + + // Symbols whose names start with "type." are compiler + // generated, so make functions with that prefix internal. + ver := 0 + if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type.") { + ver = sym.SymVerABIInternal + } + + lsym := ctxt.Syms.Lookup(elfsym.Name, ver) // Because loadlib above loads all .a files before loading any shared // libraries, any non-dynimport symbols we find that duplicate symbols // already loaded should be ignored (the symbols from the .a files @@ -1830,7 +1838,7 @@ func ldshlibsyms(ctxt *Link, shlib string) { // the ABIs are actually different. We might have to // mangle Go function names in the .so to include the // ABI. - if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC { + if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && ver == 0 { alias := ctxt.Syms.Lookup(elfsym.Name, sym.SymVerABIInternal) if alias.Type != 0 { continue