1
0
mirror of https://github.com/golang/go synced 2024-11-23 10:30:03 -07:00

[dev.regabi] cmd/link: resolve symbol ABI in shared linkage

In shared build mode and linkage, currently we assume all
function symbols are ABI0 (except for generated type algorithm
functions), and alias them to ABIInternal. When the two ABIs
actually differ (as it is now), this is not actually correct.
This CL resolves symbol ABI based on their mangled names.
If the symbol's name has a ".abi0" or ".abiinternal" suffix, it
is of the corresponding ABI. The symbol without the suffix is
the other ABI. For functions without ABI wrapper generated,
only one ABI exists but we don't know what it is, so we still
use alias (for now).

Change-Id: I2165f149bc83d513e81eb1eb4ee95464335b0e75
Reviewed-on: https://go-review.googlesource.com/c/go/+/289289
Trust: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Zhang 2021-02-03 15:07:33 -05:00
parent 8fa84772ba
commit a21de9ec73

View File

@ -2091,6 +2091,26 @@ func ldshlibsyms(ctxt *Link, shlib string) {
Errorf(nil, "cannot read symbols from shared library: %s", libpath) Errorf(nil, "cannot read symbols from shared library: %s", libpath)
return return
} }
// collect text symbol ABI versions.
symabi := make(map[string]int) // map (unmangled) symbol name to version
if *flagAbiWrap {
for _, elfsym := range syms {
if elf.ST_TYPE(elfsym.Info) != elf.STT_FUNC {
continue
}
// Demangle the name. Keep in sync with symtab.go:putelfsym.
if strings.HasSuffix(elfsym.Name, ".abiinternal") {
// ABIInternal symbol has mangled name, so the primary symbol is ABI0.
symabi[strings.TrimSuffix(elfsym.Name, ".abiinternal")] = 0
}
if strings.HasSuffix(elfsym.Name, ".abi0") {
// ABI0 symbol has mangled name, so the primary symbol is ABIInternal.
symabi[strings.TrimSuffix(elfsym.Name, ".abi0")] = sym.SymVerABIInternal
}
}
}
for _, elfsym := range syms { for _, elfsym := range syms {
if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION { if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
continue continue
@ -2099,12 +2119,23 @@ func ldshlibsyms(ctxt *Link, shlib string) {
// Symbols whose names start with "type." are compiler // Symbols whose names start with "type." are compiler
// generated, so make functions with that prefix internal. // generated, so make functions with that prefix internal.
ver := 0 ver := 0
symname := elfsym.Name // (unmangled) symbol name
if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type.") { if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type.") {
ver = sym.SymVerABIInternal ver = sym.SymVerABIInternal
} else if *flagAbiWrap && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC {
if strings.HasSuffix(elfsym.Name, ".abiinternal") {
ver = sym.SymVerABIInternal
symname = strings.TrimSuffix(elfsym.Name, ".abiinternal")
} else if strings.HasSuffix(elfsym.Name, ".abi0") {
ver = 0
symname = strings.TrimSuffix(elfsym.Name, ".abi0")
} else if abi, ok := symabi[elfsym.Name]; ok {
ver = abi
}
} }
l := ctxt.loader l := ctxt.loader
s := l.LookupOrCreateSym(elfsym.Name, ver) s := l.LookupOrCreateSym(symname, ver)
// Because loadlib above loads all .a files before loading // Because loadlib above loads all .a files before loading
// any shared libraries, any non-dynimport symbols we find // any shared libraries, any non-dynimport symbols we find
@ -2129,6 +2160,10 @@ func ldshlibsyms(ctxt *Link, shlib string) {
} }
} }
if symname != elfsym.Name {
l.SetSymExtname(s, elfsym.Name)
}
// For function symbols, we don't know what ABI is // For function symbols, we don't know what ABI is
// available, so alias it under both ABIs. // available, so alias it under both ABIs.
// //
@ -2137,7 +2172,12 @@ func ldshlibsyms(ctxt *Link, shlib string) {
// mangle Go function names in the .so to include the // mangle Go function names in the .so to include the
// ABI. // ABI.
if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && ver == 0 { if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && ver == 0 {
alias := ctxt.loader.LookupOrCreateSym(elfsym.Name, sym.SymVerABIInternal) if *flagAbiWrap {
if _, ok := symabi[symname]; ok {
continue // only use alias for functions w/o ABI wrappers
}
}
alias := ctxt.loader.LookupOrCreateSym(symname, sym.SymVerABIInternal)
if l.SymType(alias) != 0 { if l.SymType(alias) != 0 {
continue continue
} }