]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: when reading symbols from a shared library, allow duplicates when they...
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Tue, 16 Jun 2015 01:41:11 +0000 (13:41 +1200)
committerIan Lance Taylor <iant@golang.org>
Tue, 16 Jun 2015 22:33:36 +0000 (22:33 +0000)
This makes the behaviour match what happens when duplicate symbols are read
from regular object files and fixes errors about cgoAlwaysFalse when linking
an executable that uses cgo against a shared library.

Change-Id: Ibb8cd8fe3f7813cde504b7483f1e857868d7e063
Reviewed-on: https://go-review.googlesource.com/11117
Reviewed-by: Ian Lance Taylor <iant@golang.org>
misc/cgo/testshared/shared_test.go
misc/cgo/testshared/src/execgo/exe.go [new file with mode: 0644]
src/cmd/link/internal/ld/lib.go

index ae977c00637deef4f598a11c56cd21923f7f0dc0..c73abbf0f42de9e813de5c0630527a04b4501de9 100644 (file)
@@ -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 (file)
index 0000000..0427be8
--- /dev/null
@@ -0,0 +1,8 @@
+package main
+
+/*
+ */
+import "C"
+
+func main() {
+}
index ba906fbde3ba1630774b9a1edd64976f8c1e6021..faa5fc9fd68b5cb5d656223c406731be1a4a2124 100644 (file)
@@ -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)
                        }
                }
        }