summaryrefslogtreecommitdiff
path: root/src/cmd/link/internal
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2018-11-01 12:30:23 -0400
committerAustin Clements <austin@google.com>2018-11-12 20:46:55 +0000
commit685aca45dc8435df7b7e8059a42a8a98efdaf22c (patch)
tree9fa4c1d2e523c8052bc50ed177350eafc77eb9d1 /src/cmd/link/internal
parent1794ee682994ed2efbb9371060856cd7b146f405 (diff)
downloadgo-git-685aca45dc8435df7b7e8059a42a8a98efdaf22c.tar.gz
cmd/compile, cmd/link: separate stable and internal ABIs
This implements compiler and linker support for separating the function calling ABI into two ABIs: a stable and an internal ABI. At the moment, the two ABIs are identical, but we'll be able to evolve the internal ABI without breaking existing assembly code that depends on the stable ABI for calling to and from Go. The Go compiler generates internal ABI symbols for all Go functions. It uses the symabis information produced by the assembler to create ABI wrappers whenever it encounters a body-less Go function that's defined in assembly or a Go function that's referenced from assembly. Since the two ABIs are currently identical, for the moment this is implemented using "ABI alias" symbols, which are just forwarding references to the native ABI symbol for a function. This way there's no actual code involved in the ABI wrapper, which is good because we're not deriving any benefit from it right now. Once the ABIs diverge, we can eliminate ABI aliases. The linker represents these different ABIs internally as different versions of the same symbol. This way, the linker keeps us honest, since every symbol definition and reference also specifies its version. The linker is responsible for resolving ABI aliases. Fixes #27539. Change-Id: I197c52ec9f8fc435db8f7a4259029b20f6d65e95 Reviewed-on: https://go-review.googlesource.com/c/147160 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd/link/internal')
-rw-r--r--src/cmd/link/internal/ld/deadcode.go12
-rw-r--r--src/cmd/link/internal/ld/go.go16
-rw-r--r--src/cmd/link/internal/ld/lib.go32
-rw-r--r--src/cmd/link/internal/ld/symtab.go2
-rw-r--r--src/cmd/link/internal/ppc64/asm.go2
-rw-r--r--src/cmd/link/internal/sym/symbols.go2
-rw-r--r--src/cmd/link/internal/sym/symkind.go4
-rw-r--r--src/cmd/link/internal/sym/symkind_string.go4
8 files changed, 66 insertions, 8 deletions
diff --git a/src/cmd/link/internal/ld/deadcode.go b/src/cmd/link/internal/ld/deadcode.go
index df989cc944..8f582174c5 100644
--- a/src/cmd/link/internal/ld/deadcode.go
+++ b/src/cmd/link/internal/ld/deadcode.go
@@ -60,8 +60,8 @@ func deadcode(ctxt *Link) {
d.init()
d.flood()
- callSym := ctxt.Syms.ROLookup("reflect.Value.Call", 0)
- methSym := ctxt.Syms.ROLookup("reflect.Value.Method", 0)
+ callSym := ctxt.Syms.ROLookup("reflect.Value.Call", sym.SymVerABIInternal)
+ methSym := ctxt.Syms.ROLookup("reflect.Value.Method", sym.SymVerABIInternal)
reflectSeen := false
if ctxt.DynlinkingGo() {
@@ -257,7 +257,10 @@ func (d *deadcodepass) init() {
}
for _, name := range names {
+ // Mark symbol as an data/ABI0 symbol.
d.mark(d.ctxt.Syms.ROLookup(name, 0), nil)
+ // Also mark any Go functions (internal ABI).
+ d.mark(d.ctxt.Syms.ROLookup(name, sym.SymVerABIInternal), nil)
}
}
@@ -308,6 +311,11 @@ func (d *deadcodepass) flood() {
// reachable.
continue
}
+ if r.Sym.Type == sym.SABIALIAS {
+ // Patch this relocation through the
+ // ABI alias before marking.
+ r.Sym = resolveABIAlias(r.Sym)
+ }
if r.Type != objabi.R_METHODOFF {
d.mark(r.Sym, s)
continue
diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go
index d6c6b53a44..c942956cc4 100644
--- a/src/cmd/link/internal/ld/go.go
+++ b/src/cmd/link/internal/ld/go.go
@@ -25,6 +25,17 @@ func expandpkg(t0 string, pkg string) string {
return strings.Replace(t0, `"".`, pkg+".", -1)
}
+func resolveABIAlias(s *sym.Symbol) *sym.Symbol {
+ if s.Type != sym.SABIALIAS {
+ return s
+ }
+ target := s.R[0].Sym
+ if target.Type == sym.SABIALIAS {
+ panic(fmt.Sprintf("ABI alias %s references another ABI alias %s", s, target))
+ }
+ return target
+}
+
// TODO:
// generate debugging section in binary.
// once the dust settles, try to move some code to
@@ -191,6 +202,11 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
}
local = expandpkg(local, pkg)
+ // The compiler arranges for an ABI0 wrapper
+ // to be available for all cgo-exported
+ // functions. Link.loadlib will resolve any
+ // ABI aliases we find here (since we may not
+ // yet know it's an alias).
s := ctxt.Syms.Lookup(local, 0)
switch ctxt.BuildMode {
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index aa472ee07f..3038b79574 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -169,7 +169,7 @@ func (ctxt *Link) DynlinkingGo() bool {
// CanUsePlugins returns whether a plugins can be used
func (ctxt *Link) CanUsePlugins() bool {
- return ctxt.Syms.ROLookup("plugin.Open", 0) != nil
+ return ctxt.Syms.ROLookup("plugin.Open", sym.SymVerABIInternal) != nil
}
// UseRelro returns whether to make use of "read only relocations" aka
@@ -635,6 +635,19 @@ func (ctxt *Link) loadlib() {
}
ctxt.Textp = textp
}
+
+ // Resolve ABI aliases in the list of cgo-exported functions.
+ // This is necessary because we load the ABI0 symbol for all
+ // cgo exports.
+ for i, s := range dynexp {
+ if s.Type != sym.SABIALIAS {
+ continue
+ }
+ t := resolveABIAlias(s)
+ t.Attr |= s.Attr
+ t.SetExtname(s.Extname())
+ dynexp[i] = t
+ }
}
// mangleTypeSym shortens the names of symbols that represent Go types
@@ -651,7 +664,7 @@ func (ctxt *Link) loadlib() {
// those programs loaded dynamically in multiple parts need these
// symbols to have entries in the symbol table.
func (ctxt *Link) mangleTypeSym() {
- if ctxt.BuildMode != BuildModeShared && !ctxt.linkShared && ctxt.BuildMode != BuildModePlugin && ctxt.Syms.ROLookup("plugin.Open", 0) == nil {
+ if ctxt.BuildMode != BuildModeShared && !ctxt.linkShared && ctxt.BuildMode != BuildModePlugin && !ctxt.CanUsePlugins() {
return
}
@@ -1801,6 +1814,21 @@ func ldshlibsyms(ctxt *Link, shlib string) {
gcdataLocations[elfsym.Value+2*uint64(ctxt.Arch.PtrSize)+8+1*uint64(ctxt.Arch.PtrSize)] = lsym
}
}
+ // For function symbols, we don't know what ABI is
+ // available, so alias it under both ABIs.
+ //
+ // 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 {
+ alias := ctxt.Syms.Lookup(elfsym.Name, sym.SymVerABIInternal)
+ if alias.Type != 0 {
+ continue
+ }
+ alias.Type = sym.SABIALIAS
+ alias.R = []sym.Reloc{{Sym: lsym}}
+ }
}
gcdataAddresses := make(map[*sym.Symbol]uint64)
if ctxt.Arch.Family == sys.ARM64 {
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index 276a3a1cbb..7c296d766c 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -506,7 +506,7 @@ func (ctxt *Link) symtab() {
abihashgostr.AddAddr(ctxt.Arch, hashsym)
abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size))
}
- if ctxt.BuildMode == BuildModePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil {
+ if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
for _, l := range ctxt.Library {
s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0)
s.Attr |= sym.AttrReachable
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
index c4a49c6a1e..11a7aa2164 100644
--- a/src/cmd/link/internal/ppc64/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -133,7 +133,7 @@ func genplt(ctxt *ld.Link) {
}
func genaddmoduledata(ctxt *ld.Link) {
- addmoduledata := ctxt.Syms.ROLookup("runtime.addmoduledata", 0)
+ addmoduledata := ctxt.Syms.ROLookup("runtime.addmoduledata", sym.SymVerABI0)
if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
return
}
diff --git a/src/cmd/link/internal/sym/symbols.go b/src/cmd/link/internal/sym/symbols.go
index d7266c840b..f0fcf2361b 100644
--- a/src/cmd/link/internal/sym/symbols.go
+++ b/src/cmd/link/internal/sym/symbols.go
@@ -43,6 +43,8 @@ func NewSymbols() *Symbols {
hash := make([]map[string]*Symbol, SymVerStatic)
// Preallocate about 2mb for hash of non static symbols
hash[0] = make(map[string]*Symbol, 100000)
+ // And another 1mb for internal ABI text symbols.
+ hash[SymVerABIInternal] = make(map[string]*Symbol, 50000)
return &Symbols{
hash: hash,
Allsym: make([]*Symbol, 0, 100000),
diff --git a/src/cmd/link/internal/sym/symkind.go b/src/cmd/link/internal/sym/symkind.go
index b1756d6145..6e1e1b58a1 100644
--- a/src/cmd/link/internal/sym/symkind.go
+++ b/src/cmd/link/internal/sym/symkind.go
@@ -109,6 +109,9 @@ const (
SDWARFRANGE
SDWARFLOC
SDWARFMISC // Not really a section; informs/affects other DWARF section generation
+
+ // ABI aliases (these never appear in the output)
+ SABIALIAS
)
// AbiSymKindToSymKind maps values read from object files (which are
@@ -126,6 +129,7 @@ var AbiSymKindToSymKind = [...]SymKind{
SDWARFRANGE,
SDWARFLOC,
SDWARFMISC,
+ SABIALIAS,
}
// ReadOnly are the symbol kinds that form read-only sections. In some
diff --git a/src/cmd/link/internal/sym/symkind_string.go b/src/cmd/link/internal/sym/symkind_string.go
index 7428503b1c..4da6c656f7 100644
--- a/src/cmd/link/internal/sym/symkind_string.go
+++ b/src/cmd/link/internal/sym/symkind_string.go
@@ -4,9 +4,9 @@ package sym
import "strconv"
-const _SymKind_name = "SxxxSTEXTSELFRXSECTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSMACHOPLTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASBSSSNOPTRBSSSTLSBSSSXCOFFTOCSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSCONSTSDYNIMPORTSHOSTOBJSDWARFSECTSDWARFINFOSDWARFRANGESDWARFLOCSDWARFMISC"
+const _SymKind_name = "SxxxSTEXTSELFRXSECTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSMACHOPLTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASBSSSNOPTRBSSSTLSBSSSXCOFFTOCSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSCONSTSDYNIMPORTSHOSTOBJSDWARFSECTSDWARFINFOSDWARFRANGESDWARFLOCSDWARFMISCSABIALIAS"
-var _SymKind_index = [...]uint16{0, 4, 9, 19, 24, 31, 40, 47, 54, 61, 69, 79, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 214, 220, 229, 237, 244, 254, 262, 267, 271, 280, 287, 296, 301, 313, 325, 342, 359, 368, 374, 384, 392, 402, 412, 423, 432, 442}
+var _SymKind_index = [...]uint16{0, 4, 9, 19, 24, 31, 40, 47, 54, 61, 69, 79, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 214, 220, 229, 237, 244, 254, 262, 267, 271, 280, 287, 296, 301, 313, 325, 342, 359, 368, 374, 384, 392, 402, 412, 423, 432, 442, 451}
func (i SymKind) String() string {
if i >= SymKind(len(_SymKind_index)-1) {