1
0
mirror of https://github.com/golang/go synced 2024-11-26 14:36:52 -07:00

cmd/link: mangle ABI name for shared linkage

Currently, when ABI wrappers are used, we don't use ABI aliases.
One exception is shared linkage. When loading a shared library, if
a symbol has only one ABI, and the name is not mangled, we don't
know what ABI it is, so we have to use ABI aliases.

This CL makes it always mangle ABIInternal function name in shared
linkage, so we know what ABI to choose when loading a shared
library. And we now can fully stop using ABI aliases when ABI
wrappers are used.

Change-Id: Id15d9cd72a59f391f54574710ebba7dc44cb6e23
Reviewed-on: https://go-review.googlesource.com/c/go/+/315869
Trust: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Zhang 2021-04-30 17:21:22 -04:00
parent 879db69ce2
commit d7473fd907
4 changed files with 22 additions and 42 deletions

View File

@ -503,10 +503,8 @@ func (ctxt *Link) loadlib() {
default: default:
log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups) log.Fatalf("invalid -strictdups flag value %d", *FlagStrictDups)
} }
if !buildcfg.Experiment.RegabiWrappers || ctxt.linkShared { if !buildcfg.Experiment.RegabiWrappers {
// Use ABI aliases if ABI wrappers are not used. // Use ABI aliases if ABI wrappers are not used.
// TODO: for now we still use ABI aliases in shared linkage, even if
// the wrapper is enabled.
flags |= loader.FlagUseABIAlias flags |= loader.FlagUseABIAlias
} }
elfsetstring1 := func(str string, off int) { elfsetstring(ctxt, 0, str, off) } elfsetstring1 := func(str string, off int) { elfsetstring(ctxt, 0, str, off) }
@ -2088,25 +2086,6 @@ func ldshlibsyms(ctxt *Link, shlib string) {
return return
} }
// collect text symbol ABI versions.
symabi := make(map[string]int) // map (unmangled) symbol name to version
if buildcfg.Experiment.RegabiWrappers {
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
@ -2119,14 +2098,13 @@ func ldshlibsyms(ctxt *Link, shlib string) {
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 buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC { } else if buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC {
// Demangle the ABI name. Keep in sync with symtab.go:mangleABIName.
if strings.HasSuffix(elfsym.Name, ".abiinternal") { if strings.HasSuffix(elfsym.Name, ".abiinternal") {
ver = sym.SymVerABIInternal ver = sym.SymVerABIInternal
symname = strings.TrimSuffix(elfsym.Name, ".abiinternal") symname = strings.TrimSuffix(elfsym.Name, ".abiinternal")
} else if strings.HasSuffix(elfsym.Name, ".abi0") { } else if strings.HasSuffix(elfsym.Name, ".abi0") {
ver = 0 ver = 0
symname = strings.TrimSuffix(elfsym.Name, ".abi0") symname = strings.TrimSuffix(elfsym.Name, ".abi0")
} else if abi, ok := symabi[elfsym.Name]; ok {
ver = abi
} }
} }
@ -2160,19 +2138,9 @@ func ldshlibsyms(ctxt *Link, shlib string) {
l.SetSymExtname(s, elfsym.Name) l.SetSymExtname(s, elfsym.Name)
} }
// For function symbols, we don't know what ABI is // For function symbols, if ABI wrappers are not used, we don't
// available, so alias it under both ABIs. // know what ABI is available, so alias it under both ABIs.
// if !buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && ver == 0 {
// TODO(austin): This is almost certainly wrong once
// the ABIs are actually different. We might have to
// mangle Go function names in the .so to include the
// ABI.
if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && ver == 0 {
if buildcfg.Experiment.RegabiWrappers {
if _, ok := symabi[symname]; ok {
continue // only use alias for functions w/o ABI wrappers
}
}
alias := ctxt.loader.LookupOrCreateSym(symname, sym.SymVerABIInternal) alias := ctxt.loader.LookupOrCreateSym(symname, sym.SymVerABIInternal)
if l.SymType(alias) != 0 { if l.SymType(alias) != 0 {
continue continue

View File

@ -1047,7 +1047,7 @@ func machosymtab(ctxt *Link) {
// replace "·" as ".", because DTrace cannot handle it. // replace "·" as ".", because DTrace cannot handle it.
name := strings.Replace(ldr.SymExtname(s), "·", ".", -1) name := strings.Replace(ldr.SymExtname(s), "·", ".", -1)
name = mangleABIName(ldr, s, name) name = mangleABIName(ctxt, ldr, s, name)
symstr.Addstring(name) symstr.Addstring(name)
if t := ldr.SymType(s); t == sym.SDYNIMPORT || t == sym.SHOSTOBJ || t == sym.SUNDEFEXT { if t := ldr.SymType(s); t == sym.SDYNIMPORT || t == sym.SHOSTOBJ || t == sym.SUNDEFEXT {

View File

@ -727,7 +727,7 @@ func (f *peFile) writeSymbols(ctxt *Link) {
name = "_" + name name = "_" + name
} }
name = mangleABIName(ldr, s, name) name = mangleABIName(ctxt, ldr, s, name)
var peSymType uint16 var peSymType uint16
if ctxt.IsExternal() { if ctxt.IsExternal() {

View File

@ -105,7 +105,7 @@ func putelfsym(ctxt *Link, x loader.Sym, typ elf.SymType, curbind elf.SymBind) {
} }
sname := ldr.SymExtname(x) sname := ldr.SymExtname(x)
sname = mangleABIName(ldr, x, sname) sname = mangleABIName(ctxt, ldr, x, sname)
// One pass for each binding: elf.STB_LOCAL, elf.STB_GLOBAL, // One pass for each binding: elf.STB_LOCAL, elf.STB_GLOBAL,
// maybe one day elf.STB_WEAK. // maybe one day elf.STB_WEAK.
@ -834,9 +834,9 @@ func isStaticTmp(name string) bool {
} }
// Mangle function name with ABI information. // Mangle function name with ABI information.
func mangleABIName(ldr *loader.Loader, x loader.Sym, name string) string { func mangleABIName(ctxt *Link, ldr *loader.Loader, x loader.Sym, name string) string {
// For functions with ABI wrappers, we have to make sure that we // For functions with ABI wrappers, we have to make sure that we
// don't wind up with two elf symbol table entries with the same // don't wind up with two symbol table entries with the same
// name (since this will generated an error from the external // name (since this will generated an error from the external
// linker). If we have wrappers, keep the ABIInternal name // linker). If we have wrappers, keep the ABIInternal name
// unmangled since we want cross-load-module calls to target // unmangled since we want cross-load-module calls to target
@ -854,5 +854,17 @@ func mangleABIName(ldr *loader.Loader, x loader.Sym, name string) string {
name = fmt.Sprintf("%s.abi%d", name, ldr.SymVersion(x)) name = fmt.Sprintf("%s.abi%d", name, ldr.SymVersion(x))
} }
} }
// When loading a shared library, if a symbol has only one ABI,
// and the name is not mangled, we don't know what ABI it is.
// So we always mangle ABIInternal function name in shared linkage,
// except symbols that are exported to C. Type symbols are always
// ABIInternal so they are not mangled.
if ctxt.IsShared() {
if ldr.SymType(x) == sym.STEXT && ldr.SymVersion(x) == sym.SymVerABIInternal && !ldr.AttrCgoExport(x) && !strings.HasPrefix(name, "type.") {
name = fmt.Sprintf("%s.abiinternal", name)
}
}
return name return name
} }