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

[dev.link] cmd/link: implement symbol overwrite logic

If two defined symbols have the same name, one contentless and
one with content, the one with content "wins". This is mainly for
go:linkname on data symbols. Support this logic in newobj mode.

Introduce an "overwrite" mechanism, letting one symbol overwrite
another. This machanism could later be used for the linker
overwriting symbol contents (e.g. -X flag).

Change-Id: I32ee7d4b82df275f11b38c3abefc99b878ff12d7
Reviewed-on: https://go-review.googlesource.com/c/go/+/200097
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Zhang 2019-10-08 15:35:36 -04:00
parent 27111e5fec
commit dab05a0484

View File

@ -97,6 +97,7 @@ type Loader struct {
extSyms []nameVer // externally defined symbols
symsByName map[nameVer]Sym // map symbol name to index
overwrite map[Sym]Sym // overwrite[i]=j if symbol j overwrites symbol i
objByPkg map[string]*oReader // map package path to its Go object reader
@ -111,6 +112,7 @@ func NewLoader() *Loader {
objs: []objIdx{{nil, 0}},
symsByName: make(map[nameVer]Sym),
objByPkg: make(map[string]*oReader),
overwrite: make(map[Sym]Sym),
}
}
@ -137,16 +139,34 @@ func (l *Loader) AddObj(pkg string, r *oReader) Sym {
}
// Add a symbol with a given index, return if it is added.
func (l *Loader) AddSym(name string, ver int, i Sym, dupok bool) bool {
func (l *Loader) AddSym(name string, ver int, i Sym, r *oReader, dupok bool, typ sym.SymKind) bool {
if l.extStart != 0 {
panic("AddSym called after AddExtSym is called")
}
nv := nameVer{name, ver}
if _, ok := l.symsByName[nv]; ok {
if dupok || true { // TODO: "true" isn't quite right. need to implement "overwrite" logic.
if oldi, ok := l.symsByName[nv]; ok {
if dupok {
return false
}
overwrite := r.DataSize(int(i-l.StartIndex(r))) != 0
if overwrite {
// new symbol overwrites old symbol.
oldr, li := l.ToLocal(oldi)
oldsym := goobj2.Sym{}
oldsym.Read(oldr.Reader, oldr.SymOff(li))
oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type)]
if oldsym.Flag&goobj2.SymFlagDupok == 0 && !((oldtyp == sym.SDATA || oldtyp == sym.SNOPTRDATA || oldtyp == sym.SBSS || oldtyp == sym.SNOPTRBSS) && oldr.DataSize(li) == 0) { // only allow overwriting 0-sized data symbol
log.Fatalf("duplicated definition of symbol " + name)
}
l.overwrite[oldi] = i
} else {
// old symbol overwrites new symbol.
if typ != sym.SDATA && typ != sym.SNOPTRDATA && typ != sym.SBSS && typ != sym.SNOPTRBSS { // only allow overwriting data symbol
log.Fatalf("duplicated definition of symbol " + name)
}
l.overwrite[i] = oldi
return false
}
panic("duplicated definition of symbol " + name)
}
l.symsByName[nv] = i
return true
@ -171,11 +191,18 @@ func (l *Loader) AddExtSym(name string, ver int) Sym {
// Convert a local index to a global index.
func (l *Loader) ToGlobal(r *oReader, i int) Sym {
return l.StartIndex(r) + Sym(i)
g := l.StartIndex(r) + Sym(i)
if ov, ok := l.overwrite[g]; ok {
return ov
}
return g
}
// Convert a global index to a local index.
func (l *Loader) ToLocal(i Sym) (*oReader, int) {
if ov, ok := l.overwrite[i]; ok {
i = ov
}
if l.extStart != 0 && i >= l.extStart {
return nil, int(i - l.extStart)
}
@ -389,7 +416,7 @@ func LoadNew(l *Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *s
}
v := abiToVer(osym.ABI, localSymVersion)
dupok := osym.Flag&goobj2.SymFlagDupok != 0
l.AddSym(name, v, istart+Sym(i), dupok)
l.AddSym(name, v, istart+Sym(i), or, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)])
}
// The caller expects us consuming all the data