Skip to content

Commit

Permalink
cmd/link: when reading symbols from a shared library, allow duplicate…
Browse files Browse the repository at this point in the history
…s when they are both in bss

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 <[email protected]>
  • Loading branch information
mwhudson authored and ianlancetaylor committed Jun 16, 2015
1 parent b1be121 commit a5f57d7
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
7 changes: 7 additions & 0 deletions misc/cgo/testshared/shared_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 8 additions & 0 deletions misc/cgo/testshared/src/execgo/exe.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package main

/*
*/
import "C"

func main() {
}
27 changes: 18 additions & 9 deletions src/cmd/link/internal/ld/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Expand Down

0 comments on commit a5f57d7

Please sign in to comment.