diff --git a/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go index ae977c00637..c73abbf0f42 100644 --- a/misc/cgo/testshared/shared_test.go +++ b/misc/cgo/testshared/shared_test.go @@ -309,6 +309,13 @@ func TestTrivialExecutable(t *testing.T) { AssertHasRPath(t, "./bin/trivial", gorootInstallDir) } +// Build an executable that uses cgo linked against the shared runtime and check it +// runs. +func TestCgoExecutable(t *testing.T) { + goCmd(t, "install", "-linkshared", "execgo") + run(t, "cgo executable", "./bin/execgo") +} + // Build a GOPATH package into a shared library that links against the goroot runtime // and an executable that links against both. func TestGopathShlib(t *testing.T) { diff --git a/misc/cgo/testshared/src/execgo/exe.go b/misc/cgo/testshared/src/execgo/exe.go new file mode 100644 index 00000000000..0427be8bdfd --- /dev/null +++ b/misc/cgo/testshared/src/execgo/exe.go @@ -0,0 +1,8 @@ +package main + +/* + */ +import "C" + +func main() { +} diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index ba906fbde3b..faa5fc9fd68 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -1290,25 +1290,34 @@ func ldshlibsyms(shlib string) { Diag("cannot read symbols from shared library: %s", libpath) return } - for _, s := range syms { - if elf.ST_TYPE(s.Info) == elf.STT_NOTYPE || elf.ST_TYPE(s.Info) == elf.STT_SECTION { + for _, elfsym := range syms { + if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION { continue } - lsym := Linklookup(Ctxt, s.Name, 0) + lsym := Linklookup(Ctxt, elfsym.Name, 0) if lsym.Type != 0 && lsym.Type != obj.SDYNIMPORT && lsym.Dupok == 0 { - Diag( - "Found duplicate symbol %s reading from %s, first found in %s", - s.Name, shlib, lsym.File) + if (lsym.Type != obj.SBSS && lsym.Type != obj.SNOPTRBSS) || len(lsym.R) != 0 || len(lsym.P) != 0 || f.Sections[elfsym.Section].Type != elf.SHT_NOBITS { + Diag("Found duplicate symbol %s reading from %s, first found in %s", elfsym.Name, shlib, lsym.File) + } + if lsym.Size > int64(elfsym.Size) { + // If the existing symbol is a BSS value that is + // larger than the one read from the shared library, + // keep references to that. Conversely, if the + // version from the shared libray is larger, we want + // to make all references be to that. + continue + } } lsym.Type = obj.SDYNIMPORT - lsym.ElfType = elf.ST_TYPE(s.Info) - if s.Section != elf.SHN_UNDEF { + lsym.ElfType = elf.ST_TYPE(elfsym.Info) + lsym.Size = int64(elfsym.Size) + if elfsym.Section != elf.SHN_UNDEF { // Set .File for the library that actually defines the symbol. lsym.File = libpath // The decodetype_* functions in decodetype.go need access to // the type data. if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") { - lsym.P = readelfsymboldata(f, &s) + lsym.P = readelfsymboldata(f, &elfsym) } } }