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
objs: []objIdx{{nil, 0}},
symsByName: make(map[nameVer]Sym),
objByPkg: make(map[string]*oReader),
+ overwrite: make(map[Sym]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
// 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)
}
}
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