[dev.link] cmd/link: support updates to contents of obj-based Syms

Add in the hooks to SymbolBuilder and to the loader to allow
the linker to make modifications to a non-external symbol (e.g.
a sym whose index is less than loader.extStart).

The basic idea is to manufacture a new external symbol with the same
name and version, then import the old symbol's content (type, data,
relocations, etc) into the payload struct for the new symbol, and
finally redirect the name lookup tables to target the new sym for the
specified name/version.

This change is needed in order to convert over the host object loaders
to avoid use of sym.Symbol.

Change-Id: I79cd42b23794e830bbdbcbcd2c500c35c351f01f
Reviewed-on: https://go-review.googlesource.com/c/go/+/211897
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Than McIntosh 2019-12-16 14:14:29 -05:00
parent a52cea446d
commit d5854bf8e6
3 changed files with 261 additions and 85 deletions

View file

@ -18,7 +18,7 @@ type SymbolBuilder struct {
l *Loader // loader
}
// NewSymbolBuilder creates a symbol builder for use in constructing
// MakeSymbolBuilder creates a symbol builder for use in constructing
// an entirely new symbol.
func (l *Loader) MakeSymbolBuilder(name string) *SymbolBuilder {
// for now assume that any new sym is intended to be static
@ -31,18 +31,31 @@ func (l *Loader) MakeSymbolBuilder(name string) *SymbolBuilder {
return sb
}
// NewSymbolBuilder creates a symbol builder helper for an already-allocated
// external symbol 'symIdx'.
func (l *Loader) MakeSymbolUpdater(symIdx Sym) *SymbolBuilder {
// MakeSymbolUpdater creates a symbol builder helper for an existing
// symbol 'symIdx'. If 'symIdx' is not an external symbol, then create
// a clone of it (copy name, properties, etc) fix things up so that
// the lookup tables and caches point to the new version, not the old
// version. Returns a SymbolBuilder and a Sym (which may be different
// from the original if we had to clone).
func (l *Loader) MakeSymbolUpdater(symIdx Sym) (*SymbolBuilder, Sym) {
if symIdx == 0 {
panic("can't update the null symbol")
}
if ov, ok := l.overwrite[symIdx]; ok {
symIdx = ov
}
if !l.IsExternal(symIdx) {
panic("can't build on non-external sym")
// Create a clone with the same name/version/kind etc.
symIdx = l.cloneToExternal(symIdx)
}
if l.Syms[symIdx] != nil {
panic("can't build if sym.Symbol already present")
}
// Construct updater and return.
sb := &SymbolBuilder{l: l, symIdx: symIdx}
sb.extSymPayload = &l.payloads[symIdx-l.extStart]
return sb
return sb, symIdx
}
// Getters for properties of the symbol we're working on.