Commit dab05a04 authored by Cherry Zhang's avatar Cherry Zhang

[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: default avatarThan McIntosh <thanm@google.com>
parent 27111e5f
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment