mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal/ld: store the libraries a shared library was linked against in a note
The motivation for this is the innocuous looking test case that is added. This creates a stack exe -> libdep2.so -> libdep.so -> libruntime.so. The problem comes from the fact that a function from libdep.so gets inlined all the way into exe. This (unsurprisingly) means that the object file for exe references symbols from libdep.so, which means that -ldep needs to be passed when linking exe and it isn't. The fix is simply to pass it -- there is no harm in passing it when it's not needed. The thing is, it's not clear at all in the current code to see how the linker can know that libdep2 is linked against libdep. It could look through the DT_NEEDED entries in libdep2 and try to guess which are Go libraries, but it feels better to be explicit. So this adds another SHT_NOTE section that lists the shared libraries a shared library was linked against, and makes sure the complete set of depended upon shared libraries is passed to the external linker. Change-Id: I79aa6f98b4db4721d657a7eb7b7f062269bf49e2 Reviewed-on: https://go-review.googlesource.com/10376 Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
02f4084299
commit
bcc1870fcf
7 changed files with 112 additions and 27 deletions
|
|
@ -983,15 +983,35 @@ func hostlink() {
|
|||
argv = append(argv, fmt.Sprintf("%s/go.o", tmpdir))
|
||||
|
||||
if Linkshared {
|
||||
for _, shlib := range Ctxt.Shlibs {
|
||||
dir, base := filepath.Split(shlib.Path)
|
||||
argv = append(argv, "-L"+dir)
|
||||
if !rpath.set {
|
||||
argv = append(argv, "-Wl,-rpath="+dir)
|
||||
seenDirs := make(map[string]bool)
|
||||
seenLibs := make(map[string]bool)
|
||||
addshlib := func(path string) {
|
||||
dir, base := filepath.Split(path)
|
||||
if !seenDirs[dir] {
|
||||
argv = append(argv, "-L"+dir)
|
||||
if !rpath.set {
|
||||
argv = append(argv, "-Wl,-rpath="+dir)
|
||||
}
|
||||
seenDirs[dir] = true
|
||||
}
|
||||
base = strings.TrimSuffix(base, ".so")
|
||||
base = strings.TrimPrefix(base, "lib")
|
||||
argv = append(argv, "-l"+base)
|
||||
if !seenLibs[base] {
|
||||
argv = append(argv, "-l"+base)
|
||||
seenLibs[base] = true
|
||||
}
|
||||
}
|
||||
for _, shlib := range Ctxt.Shlibs {
|
||||
addshlib(shlib.Path)
|
||||
for _, dep := range shlib.Deps {
|
||||
if dep == "" {
|
||||
continue
|
||||
}
|
||||
libpath := findshlib(dep)
|
||||
if libpath != "" {
|
||||
addshlib(libpath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1214,18 +1234,20 @@ func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func ldshlibsyms(shlib string) {
|
||||
found := false
|
||||
libpath := ""
|
||||
func findshlib(shlib string) string {
|
||||
for _, libdir := range Ctxt.Libdir {
|
||||
libpath = filepath.Join(libdir, shlib)
|
||||
libpath := filepath.Join(libdir, shlib)
|
||||
if _, err := os.Stat(libpath); err == nil {
|
||||
found = true
|
||||
break
|
||||
return libpath
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
Diag("cannot find shared library: %s", shlib)
|
||||
Diag("cannot find shared library: %s", shlib)
|
||||
return ""
|
||||
}
|
||||
|
||||
func ldshlibsyms(shlib string) {
|
||||
libpath := findshlib(shlib)
|
||||
if libpath == "" {
|
||||
return
|
||||
}
|
||||
for _, processedlib := range Ctxt.Shlibs {
|
||||
|
|
@ -1251,6 +1273,13 @@ func ldshlibsyms(shlib string) {
|
|||
return
|
||||
}
|
||||
|
||||
depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
|
||||
if err != nil {
|
||||
Diag("cannot read dep list from shared library %s: %v", libpath, err)
|
||||
return
|
||||
}
|
||||
deps := strings.Split(string(depsbytes), "\n")
|
||||
|
||||
syms, err := f.Symbols()
|
||||
if err != nil {
|
||||
Diag("cannot read symbols from shared library: %s", libpath)
|
||||
|
|
@ -1272,12 +1301,6 @@ func ldshlibsyms(shlib string) {
|
|||
if elf.ST_TYPE(s.Info) == elf.STT_NOTYPE || elf.ST_TYPE(s.Info) == elf.STT_SECTION {
|
||||
continue
|
||||
}
|
||||
if s.Section == elf.SHN_UNDEF {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(s.Name, "_") {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(s.Name, "runtime.gcbits.") {
|
||||
gcmasks[s.Value] = readelfsymboldata(f, &s)
|
||||
}
|
||||
|
|
@ -1285,7 +1308,7 @@ func ldshlibsyms(shlib string) {
|
|||
continue
|
||||
}
|
||||
lsym := Linklookup(Ctxt, s.Name, 0)
|
||||
if lsym.Type != 0 && lsym.Dupok == 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)
|
||||
|
|
@ -1342,7 +1365,7 @@ func ldshlibsyms(shlib string) {
|
|||
Ctxt.Etextp = last
|
||||
}
|
||||
|
||||
Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash})
|
||||
Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps})
|
||||
}
|
||||
|
||||
func mywhatsys() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue