mirror of
https://github.com/golang/go
synced 2024-11-07 09: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:
parent
27111e5fec
commit
dab05a0484
@ -97,6 +97,7 @@ type Loader struct {
|
|||||||
extSyms []nameVer // externally defined symbols
|
extSyms []nameVer // externally defined symbols
|
||||||
|
|
||||||
symsByName map[nameVer]Sym // map symbol name to index
|
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
|
objByPkg map[string]*oReader // map package path to its Go object reader
|
||||||
|
|
||||||
@ -111,6 +112,7 @@ func NewLoader() *Loader {
|
|||||||
objs: []objIdx{{nil, 0}},
|
objs: []objIdx{{nil, 0}},
|
||||||
symsByName: make(map[nameVer]Sym),
|
symsByName: make(map[nameVer]Sym),
|
||||||
objByPkg: make(map[string]*oReader),
|
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.
|
// 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 {
|
if l.extStart != 0 {
|
||||||
panic("AddSym called after AddExtSym is called")
|
panic("AddSym called after AddExtSym is called")
|
||||||
}
|
}
|
||||||
nv := nameVer{name, ver}
|
nv := nameVer{name, ver}
|
||||||
if _, ok := l.symsByName[nv]; ok {
|
if oldi, ok := l.symsByName[nv]; ok {
|
||||||
if dupok || true { // TODO: "true" isn't quite right. need to implement "overwrite" logic.
|
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
|
return false
|
||||||
}
|
}
|
||||||
panic("duplicated definition of symbol " + name)
|
|
||||||
}
|
}
|
||||||
l.symsByName[nv] = i
|
l.symsByName[nv] = i
|
||||||
return true
|
return true
|
||||||
@ -171,11 +191,18 @@ func (l *Loader) AddExtSym(name string, ver int) Sym {
|
|||||||
|
|
||||||
// Convert a local index to a global index.
|
// Convert a local index to a global index.
|
||||||
func (l *Loader) ToGlobal(r *oReader, i int) Sym {
|
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.
|
// Convert a global index to a local index.
|
||||||
func (l *Loader) ToLocal(i Sym) (*oReader, int) {
|
func (l *Loader) ToLocal(i Sym) (*oReader, int) {
|
||||||
|
if ov, ok := l.overwrite[i]; ok {
|
||||||
|
i = ov
|
||||||
|
}
|
||||||
if l.extStart != 0 && i >= l.extStart {
|
if l.extStart != 0 && i >= l.extStart {
|
||||||
return nil, int(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)
|
v := abiToVer(osym.ABI, localSymVersion)
|
||||||
dupok := osym.Flag&goobj2.SymFlagDupok != 0
|
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
|
// The caller expects us consuming all the data
|
||||||
|
Loading…
Reference in New Issue
Block a user