]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: accept weak dynamic imports
authorAustin Clements <austin@google.com>
Thu, 27 Jun 2019 22:14:03 +0000 (18:14 -0400)
committerAustin Clements <austin@google.com>
Fri, 5 Jul 2019 18:18:28 +0000 (18:18 +0000)
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: Ian Lance Taylor <iant@golang.org>
src/cmd/cgo/out.go

index 488db52c2ea78bdf568237e38567c302973fa819..1fddbb6b54d27d3544bbf378d1917fd970de150c 100644 (file)
@@ -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 != "" {