Commit a2fb5cd8 authored by Austin Clements's avatar Austin Clements

cmd/cgo: accept weak dynamic imports

cgo produces dynamic imports for Go binaries by scanning the dynamic
imports table of a binary produced by the system C compiler and
linker. Currently, since it uses elf.File.ImportedSymbols, it only
reads global symbols. Unfortunately, recent versions of lld emit weak
symbol imports for several pthread symbols, which means the cgo tool
doesn't emit dynamic imports for them, which ultimately causes linking
of cgo binaries to fail.

Fix this by using elf.File.DynamicSymbols instead and filtering down
to both global and weak symbols.

Fixes #31912.

Change-Id: If346a7eca6733e3bfa2cccf74a9cda02a3e81d38
Reviewed-on: https://go-review.googlesource.com/c/go/+/184100
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 7aac3436
......@@ -268,6 +268,35 @@ func (p *Package) writeDefs() {
}
}
// elfImportedSymbols is like elf.File.ImportedSymbols, but it
// includes weak symbols.
//
// A bug in some versions of LLD (at least LLD 8) cause it to emit
// several pthreads symbols as weak, but we need to import those. See
// issue #31912 or https://bugs.llvm.org/show_bug.cgi?id=42442.
//
// When doing external linking, we hand everything off to the external
// linker, which will create its own dynamic symbol tables. For
// internal linking, this may turn weak imports into strong imports,
// which could cause dynamic linking to fail if a symbol really isn't
// defined. However, the standard library depends on everything it
// imports, and this is the primary use of dynamic symbol tables with
// internal linking.
func elfImportedSymbols(f *elf.File) []elf.ImportedSymbol {
syms, _ := f.DynamicSymbols()
var imports []elf.ImportedSymbol
for _, s := range syms {
if (elf.ST_BIND(s.Info) == elf.STB_GLOBAL || elf.ST_BIND(s.Info) == elf.STB_WEAK) && s.Section == elf.SHN_UNDEF {
imports = append(imports, elf.ImportedSymbol{
Name: s.Name,
Library: s.Library,
Version: s.Version,
})
}
}
return imports
}
func dynimport(obj string) {
stdout := os.Stdout
if *dynout != "" {
......@@ -290,7 +319,7 @@ func dynimport(obj string) {
}
}
}
sym, _ := f.ImportedSymbols()
sym := elfImportedSymbols(f)
for _, s := range sym {
targ := s.Name
if s.Version != "" {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment