Skip to content

Commit a2fb5cd

Browse files
committed
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 7aac343 commit a2fb5cd

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

src/cmd/cgo/out.go

+30-1
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,35 @@ func (p *Package) writeDefs() {
268268
}
269269
}
270270

271+
// elfImportedSymbols is like elf.File.ImportedSymbols, but it
272+
// includes weak symbols.
273+
//
274+
// A bug in some versions of LLD (at least LLD 8) cause it to emit
275+
// several pthreads symbols as weak, but we need to import those. See
276+
// issue #31912 or https://bugs.llvm.org/show_bug.cgi?id=42442.
277+
//
278+
// When doing external linking, we hand everything off to the external
279+
// linker, which will create its own dynamic symbol tables. For
280+
// internal linking, this may turn weak imports into strong imports,
281+
// which could cause dynamic linking to fail if a symbol really isn't
282+
// defined. However, the standard library depends on everything it
283+
// imports, and this is the primary use of dynamic symbol tables with
284+
// internal linking.
285+
func elfImportedSymbols(f *elf.File) []elf.ImportedSymbol {
286+
syms, _ := f.DynamicSymbols()
287+
var imports []elf.ImportedSymbol
288+
for _, s := range syms {
289+
if (elf.ST_BIND(s.Info) == elf.STB_GLOBAL || elf.ST_BIND(s.Info) == elf.STB_WEAK) && s.Section == elf.SHN_UNDEF {
290+
imports = append(imports, elf.ImportedSymbol{
291+
Name: s.Name,
292+
Library: s.Library,
293+
Version: s.Version,
294+
})
295+
}
296+
}
297+
return imports
298+
}
299+
271300
func dynimport(obj string) {
272301
stdout := os.Stdout
273302
if *dynout != "" {
@@ -290,7 +319,7 @@ func dynimport(obj string) {
290319
}
291320
}
292321
}
293-
sym, _ := f.ImportedSymbols()
322+
sym := elfImportedSymbols(f)
294323
for _, s := range sym {
295324
targ := s.Name
296325
if s.Version != "" {

0 commit comments

Comments
 (0)