[dev.link] cmd/link: better naming for Loader container/subsym methods, part 2 of 2

Introduce a new loader method "SetCarrierSym", to be used when
establishing container/containee symbol relationships for symbol
bucketing in the symtab phase.

This new method is intended to be employed in situations where you
have a series of related symbols will be represented by a single
carrier symbol as a combined entity. The pattern here is that the
sub-symbols contain content but will be anonymous from a symbol table
perspective; the carrier symbol has no content itself but will appear
in the symbol table. Examples of carrier symbols that follow this
model are "runtime.itablink" and "runtime.typelink".

Change-Id: I1a3391a71062c7c740cb108b3fa210b7f69b81ed
Reviewed-on: https://go-review.googlesource.com/c/go/+/240509
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
This commit is contained in:
Than McIntosh 2020-07-01 08:45:16 -04:00
parent 3c3cc19564
commit 1e9381207e
2 changed files with 43 additions and 20 deletions

View file

@ -515,10 +515,14 @@ func (ctxt *Link) symtab() []sym.SymKind {
} }
if ctxt.UseRelro() { if ctxt.UseRelro() {
symGroupType[s] = sym.STYPERELRO symGroupType[s] = sym.STYPERELRO
ldr.SetOuterSym(s, symtyperel) if symtyperel != 0 {
ldr.SetCarrierSym(s, symtyperel)
}
} else { } else {
symGroupType[s] = sym.STYPE symGroupType[s] = sym.STYPE
ldr.SetOuterSym(s, symtype) if symtyperel != 0 {
ldr.SetCarrierSym(s, symtype)
}
} }
case strings.HasPrefix(name, "go.importpath.") && ctxt.UseRelro(): case strings.HasPrefix(name, "go.importpath.") && ctxt.UseRelro():
@ -530,17 +534,17 @@ func (ctxt *Link) symtab() []sym.SymKind {
nitablinks++ nitablinks++
symGroupType[s] = sym.SITABLINK symGroupType[s] = sym.SITABLINK
ldr.SetAttrNotInSymbolTable(s, true) ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetOuterSym(s, symitablink.Sym()) ldr.SetCarrierSym(s, symitablink.Sym())
case strings.HasPrefix(name, "go.string."): case strings.HasPrefix(name, "go.string."):
symGroupType[s] = sym.SGOSTRING symGroupType[s] = sym.SGOSTRING
ldr.SetAttrNotInSymbolTable(s, true) ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetOuterSym(s, symgostring) ldr.SetCarrierSym(s, symgostring)
case strings.HasPrefix(name, "runtime.gcbits."): case strings.HasPrefix(name, "runtime.gcbits."):
symGroupType[s] = sym.SGCBITS symGroupType[s] = sym.SGCBITS
ldr.SetAttrNotInSymbolTable(s, true) ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetOuterSym(s, symgcbits) ldr.SetCarrierSym(s, symgcbits)
case strings.HasSuffix(name, "·f"): case strings.HasSuffix(name, "·f"):
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
@ -548,10 +552,12 @@ func (ctxt *Link) symtab() []sym.SymKind {
} }
if ctxt.UseRelro() { if ctxt.UseRelro() {
symGroupType[s] = sym.SGOFUNCRELRO symGroupType[s] = sym.SGOFUNCRELRO
ldr.SetOuterSym(s, symgofuncrel) if symgofuncrel != 0 {
ldr.SetCarrierSym(s, symgofuncrel)
}
} else { } else {
symGroupType[s] = sym.SGOFUNC symGroupType[s] = sym.SGOFUNC
ldr.SetOuterSym(s, symgofunc) ldr.SetCarrierSym(s, symgofunc)
} }
case strings.HasPrefix(name, "gcargs."), case strings.HasPrefix(name, "gcargs."),
@ -561,7 +567,7 @@ func (ctxt *Link) symtab() []sym.SymKind {
strings.HasSuffix(name, ".opendefer"): strings.HasSuffix(name, ".opendefer"):
symGroupType[s] = sym.SGOFUNC symGroupType[s] = sym.SGOFUNC
ldr.SetAttrNotInSymbolTable(s, true) ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetOuterSym(s, symgofunc) ldr.SetCarrierSym(s, symgofunc)
const align = 4 const align = 4
ldr.SetSymAlign(s, align) ldr.SetSymAlign(s, align)
liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1) liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1)

View file

@ -1661,18 +1661,35 @@ func (l *Loader) SubSym(i Sym) Sym {
return l.sub[i] return l.sub[i]
} }
// SetOuterSym sets the outer symbol of i to o (without setting // SetCarrierSym declares that 'c' is the carrier or container symbol
// sub symbols). // for 's'. Carrier symbols are used in the linker to as a container
func (l *Loader) SetOuterSym(i Sym, o Sym) { // for a collection of sub-symbols where the content of the
if o != 0 { // sub-symbols is effectively concatenated to form the content of the
l.outer[i] = o // carrier. The carrier is given a name in the output symbol table
// relocsym's foldSubSymbolOffset requires that we only // while the sub-symbol names are not. For example, the Go compiler
// have a single level of containment-- enforce here. // emits named string symbols (type SGOSTRING) when compiling a
if l.outer[o] != 0 { // package; after being deduplicated, these symbols are collected into
panic("multiply nested outer sym") // a single unit by assigning them a new carrier symbol named
} // "go.string.*" (which appears in the final symbol table for the
} else { // output load module).
delete(l.outer, i) func (l *Loader) SetCarrierSym(s Sym, c Sym) {
if c == 0 {
panic("invalid carrier in SetCarrierSym")
}
if s == 0 {
panic("invalid sub-symbol in SetCarrierSym")
}
// Carrier symbols are not expected to have content/data. It is
// ok for them to have non-zero size (to allow for use of generator
// symbols).
if len(l.Data(c)) != 0 {
panic("unexpected non-empty carrier symbol")
}
l.outer[s] = c
// relocsym's foldSubSymbolOffset requires that we only
// have a single level of containment-- enforce here.
if l.outer[c] != 0 {
panic("invalid nested carrier sym")
} }
} }