mirror of
https://github.com/golang/go.git
synced 2026-02-06 09:50:02 +00:00
cmd/link: support weak binding on darwin
Symbols loaded from host files can have the N_WEAK_REF bit set, which is used to instruct the loader to not fail if that symbol can't be resolved. The Go internal linker should honor this information by setting the BIND_SYMBOL_FLAGS_WEAK_IMPORT flag in the corresponding bind table entry. Fixes #76023 Cq-Include-Trybots: luci.golang.try:gotip-darwin-amd64-longtest,gotip-darwin-amd64_12,gotip-darwin-arm64_12,gotip-darwin-arm64_15,gotip-darwin-arm64-longtest,gotip-darwin-amd64_14 Change-Id: Id2cef247ec7a9cb08455844f3c30ff874772bb7b Reviewed-on: https://go-review.googlesource.com/c/go/+/713760 Reviewed-by: Michael Knyszek <mknyszek@google.com> Reviewed-by: Michael Pratt <mpratt@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
2dd7e94e16
commit
8cf7a0b4c9
5 changed files with 62 additions and 1 deletions
11
src/cmd/cgo/internal/test/cgo_darwin_test.go
Normal file
11
src/cmd/cgo/internal/test/cgo_darwin_test.go
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2025 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build cgo && darwin
|
||||
|
||||
package cgotest
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestIssue76023(t *testing.T) { issue76023(t) }
|
||||
27
src/cmd/cgo/internal/test/issue76023.go
Normal file
27
src/cmd/cgo/internal/test/issue76023.go
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2025 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -Wl,-undefined,dynamic_lookup
|
||||
|
||||
extern void __gotest_cgo_null_api(void) __attribute__((weak_import));
|
||||
|
||||
int issue76023(void) {
|
||||
if (__gotest_cgo_null_api) return 1;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import "testing"
|
||||
|
||||
func issue76023(t *testing.T) {
|
||||
r := C.issue76023()
|
||||
if r != 0 {
|
||||
t.Error("found __gotest_cgo_null_api")
|
||||
}
|
||||
}
|
||||
|
|
@ -180,6 +180,8 @@ const (
|
|||
BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2
|
||||
BIND_SPECIAL_DYLIB_WEAK_LOOKUP = -3
|
||||
|
||||
BIND_SYMBOL_FLAGS_WEAK_IMPORT = 0x1
|
||||
|
||||
BIND_OPCODE_MASK = 0xF0
|
||||
BIND_IMMEDIATE_MASK = 0x0F
|
||||
BIND_OPCODE_DONE = 0x00
|
||||
|
|
@ -1429,7 +1431,11 @@ func machoDyldInfo(ctxt *Link) {
|
|||
bind.AddUint8(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | uint8(d)&0xf)
|
||||
}
|
||||
|
||||
bind.AddUint8(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM)
|
||||
flags := uint8(0)
|
||||
if ldr.SymWeakBinding(r.targ) {
|
||||
flags |= BIND_SYMBOL_FLAGS_WEAK_IMPORT
|
||||
}
|
||||
bind.AddUint8(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | flags)
|
||||
// target symbol name as a C string, with _ prefix
|
||||
bind.AddUint8('_')
|
||||
bind.Addstring(ldr.SymExtname(r.targ))
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ type Loader struct {
|
|||
plt map[Sym]int32 // stores dynimport for pe objects
|
||||
got map[Sym]int32 // stores got for pe objects
|
||||
dynid map[Sym]int32 // stores Dynid for symbol
|
||||
weakBinding map[Sym]bool // stores whether a symbol has a weak binding
|
||||
|
||||
relocVariant map[relocId]sym.RelocVariant // stores variant relocs
|
||||
|
||||
|
|
@ -326,6 +327,7 @@ func NewLoader(flags uint32, reporter *ErrorReporter) *Loader {
|
|||
plt: make(map[Sym]int32),
|
||||
got: make(map[Sym]int32),
|
||||
dynid: make(map[Sym]int32),
|
||||
weakBinding: make(map[Sym]bool),
|
||||
attrCgoExportDynamic: make(map[Sym]struct{}),
|
||||
attrCgoExportStatic: make(map[Sym]struct{}),
|
||||
deferReturnTramp: make(map[Sym]bool),
|
||||
|
|
@ -1447,6 +1449,18 @@ func (l *Loader) SetSymExtname(i Sym, value string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (l *Loader) SymWeakBinding(i Sym) bool {
|
||||
return l.weakBinding[i]
|
||||
}
|
||||
|
||||
func (l *Loader) SetSymWeakBinding(i Sym, v bool) {
|
||||
// reject bad symbols
|
||||
if i >= Sym(len(l.objSyms)) || i == 0 {
|
||||
panic("bad symbol index in SetSymWeakBinding")
|
||||
}
|
||||
l.weakBinding[i] = v
|
||||
}
|
||||
|
||||
// SymElfType returns the previously recorded ELF type for a symbol
|
||||
// (used only for symbols read from shared libraries by ldshlibsyms).
|
||||
// It is not set for symbols defined by the packages being linked or
|
||||
|
|
|
|||
|
|
@ -613,6 +613,9 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader,
|
|||
}
|
||||
if machsym.desc&(N_WEAK_REF|N_WEAK_DEF) != 0 {
|
||||
l.SetAttrDuplicateOK(s, true)
|
||||
if machsym.desc&N_WEAK_REF != 0 {
|
||||
l.SetSymWeakBinding(s, true)
|
||||
}
|
||||
}
|
||||
machsym.sym = s
|
||||
if machsym.sectnum == 0 { // undefined
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue