mirror of
https://github.com/golang/go
synced 2024-11-23 14:40:02 -07:00
cmd/compile: generate ABI wrappers for //go:linkname'd symbols
Calling a Go symbol from assembly in another package currently results in a link failure because the Go symbol is defined as ABIInternal, but the assembly call is from ABI0. In general this is okay because you shouldn't do this anyway, but there are special cases where this is necessary, especially between the runtime and packages closely tied to the runtime in std. Currently, we address this for runtime symbols with a hack in cmd/go that knows to scan related packages when building the symabis file for the runtime and runtime/internal/atomic. However, in addition to being a messy solution in the first place, this hack causes races in cmd/go that are difficult to work around. We considered creating dummy references from assembly in the runtime to these symbols, just to make sure they get ABI0 wrappers. However, there are a fairly large number of these symbols on some platforms, and it can vary significantly depending on build flags (e.g., race mode), so even this solution is fairly unpalatable. This CL addresses this by providing a way to mark symbols in Go code that should be made available to assembly in other packages. Rather than introduce a new pragma, we lightly expand the meaning of "//go:linkname", since that pragma already generally indicates that you're making the symbol available in a way it wasn't before. This also dovetails nicely with the behavior of go:linkname in gccgo, which makes unexported symbols available to other packages. Follow-up CLs will make use of this and then remove the hack from cmd/go. Updates #31230. Change-Id: I23060c97280626581f025c5c01fb8d24bb4c5159 Reviewed-on: https://go-review.googlesource.com/c/go/+/179860 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
ac8dbe7747
commit
b402bd4499
@ -201,7 +201,8 @@ func (f *Func) initLSym(hasBody bool) {
|
|||||||
|
|
||||||
var aliasABI obj.ABI
|
var aliasABI obj.ABI
|
||||||
needABIAlias := false
|
needABIAlias := false
|
||||||
if abi, ok := symabiDefs[f.lsym.Name]; ok && abi == obj.ABI0 {
|
defABI, hasDefABI := symabiDefs[f.lsym.Name]
|
||||||
|
if hasDefABI && defABI == obj.ABI0 {
|
||||||
// Symbol is defined as ABI0. Create an
|
// Symbol is defined as ABI0. Create an
|
||||||
// Internal -> ABI0 wrapper.
|
// Internal -> ABI0 wrapper.
|
||||||
f.lsym.SetABI(obj.ABI0)
|
f.lsym.SetABI(obj.ABI0)
|
||||||
@ -215,9 +216,19 @@ func (f *Func) initLSym(hasBody bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if abi, ok := symabiRefs[f.lsym.Name]; ok && abi == obj.ABI0 {
|
isLinknameExported := nam.Sym.Linkname != "" && (hasBody || hasDefABI)
|
||||||
// Symbol is referenced as ABI0. Create an
|
if abi, ok := symabiRefs[f.lsym.Name]; (ok && abi == obj.ABI0) || isLinknameExported {
|
||||||
// ABI0 -> Internal wrapper if necessary.
|
// Either 1) this symbol is definitely
|
||||||
|
// referenced as ABI0 from this package; or 2)
|
||||||
|
// this symbol is defined in this package but
|
||||||
|
// given a linkname, indicating that it may be
|
||||||
|
// referenced from another package. Create an
|
||||||
|
// ABI0 -> Internal wrapper so it can be
|
||||||
|
// called as ABI0. In case 2, it's important
|
||||||
|
// that we know it's defined in this package
|
||||||
|
// since other packages may "pull" symbols
|
||||||
|
// using linkname and we don't want to create
|
||||||
|
// duplicate ABI wrappers.
|
||||||
if f.lsym.ABI() != obj.ABI0 {
|
if f.lsym.ABI() != obj.ABI0 {
|
||||||
needABIAlias, aliasABI = true, obj.ABI0
|
needABIAlias, aliasABI = true, obj.ABI0
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user