From fd5e0bd385660275a8049a2499e0bbbffd465bc8 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 24 Mar 2021 11:19:19 -0400 Subject: [PATCH] cmd/link: mangle function names with ABI on PE When ABI wrappers are used, we may end up with two functions having the same name. On ELF we mangle the name with ABI. Do the same for PE. TODO: other platforms? Change-Id: If89f214a6286bc28c062c1aa1bad78dc353a9231 Reviewed-on: https://go-review.googlesource.com/c/go/+/304432 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/pe.go | 2 + src/cmd/link/internal/ld/symtab.go | 71 ++++++++++++++++-------------- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index a0aba866dcb..b590d5082d4 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -694,6 +694,8 @@ func (f *peFile) writeSymbols(ctxt *Link) { name = "_" + name } + name = mangleABIName(ldr, s, name) + var peSymType uint16 if ctxt.IsExternal() { peSymType = IMAGE_SYM_TYPE_NULL diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index f48822a72ee..bd8e4cb4bde 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -104,39 +104,7 @@ func putelfsym(ctxt *Link, x loader.Sym, typ elf.SymType, curbind elf.SymBind) { } sname := ldr.SymExtname(x) - - // 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 - // name (since this will generated an error from the external - // linker). In the CgoExportStatic case, we want the ABI0 symbol - // to have the primary symbol table entry (since it's going to be - // called from C), so we rename the ABIInternal symbol. In all - // other cases, we rename the ABI0 symbol, since we want - // cross-load-module calls to target ABIInternal. - // - // TODO: generalize this for non-ELF (put the rename code in the - // loader, and store the rename result in SymExtname). - // - // TODO: avoid the ldr.Lookup calls below by instead using an aux - // sym or marker relocation to associate the wrapper with the - // wrapped function. - // - if objabi.Experiment.RegabiWrappers { - if !ldr.IsExternal(x) && ldr.SymType(x) == sym.STEXT { - // First case - if ldr.SymVersion(x) == sym.SymVerABIInternal { - if s2 := ldr.Lookup(sname, sym.SymVerABI0); s2 != 0 && ldr.AttrCgoExportStatic(s2) && ldr.SymType(s2) == sym.STEXT { - sname = sname + ".abiinternal" - } - } - // Second case - if ldr.SymVersion(x) == sym.SymVerABI0 && !ldr.AttrCgoExportStatic(x) { - if s2 := ldr.Lookup(sname, sym.SymVerABIInternal); s2 != 0 && ldr.SymType(s2) == sym.STEXT { - sname = sname + ".abi0" - } - } - } - } + sname = mangleABIName(ldr, x, sname) // One pass for each binding: elf.STB_LOCAL, elf.STB_GLOBAL, // maybe one day elf.STB_WEAK. @@ -863,3 +831,40 @@ func setCarrierSize(typ sym.SymKind, sz int64) { func isStaticTmp(name string) bool { return strings.Contains(name, "."+obj.StaticNamePref) } + +// Mangle function name with ABI information. +func mangleABIName(ldr *loader.Loader, x loader.Sym, name string) string { + // 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 + // name (since this will generated an error from the external + // linker). In the CgoExportStatic case, we want the ABI0 symbol + // to have the primary symbol table entry (since it's going to be + // called from C), so we rename the ABIInternal symbol. In all + // other cases, we rename the ABI0 symbol, since we want + // cross-load-module calls to target ABIInternal. + // + // TODO: this is currently only used on ELF and PE. Other platforms? + // + // TODO: avoid the ldr.Lookup calls below by instead using an aux + // sym or marker relocation to associate the wrapper with the + // wrapped function. + // + if !objabi.Experiment.RegabiWrappers { + return name + } + if !ldr.IsExternal(x) && ldr.SymType(x) == sym.STEXT { + // First case + if ldr.SymVersion(x) == sym.SymVerABIInternal { + if s2 := ldr.Lookup(name, sym.SymVerABI0); s2 != 0 && ldr.AttrCgoExportStatic(s2) && ldr.SymType(s2) == sym.STEXT { + name = name + ".abiinternal" + } + } + // Second case + if ldr.SymVersion(x) == sym.SymVerABI0 && !ldr.AttrCgoExportStatic(x) { + if s2 := ldr.Lookup(name, sym.SymVerABIInternal); s2 != 0 && ldr.SymType(s2) == sym.STEXT { + name = name + ".abi0" + } + } + } + return name +}