Update to go1.24.4
This commit is contained in:
@@ -452,33 +452,50 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
|
||||
if oldsym.Dupok() {
|
||||
return oldi
|
||||
}
|
||||
// If one is a DATA symbol (i.e. has content, DataSize != 0)
|
||||
// and the other is BSS, the one with content wins.
|
||||
// If one is a DATA symbol (i.e. has content, DataSize != 0,
|
||||
// including RODATA) and the other is BSS, the one with content wins.
|
||||
// If both are BSS, the one with larger size wins.
|
||||
// Specifically, the "overwrite" variable and the final result are
|
||||
//
|
||||
// new sym old sym overwrite
|
||||
// For a special case, we allow a TEXT symbol overwrites a BSS symbol
|
||||
// even if the BSS symbol has larger size. This is because there is
|
||||
// code like below to take the address of a function
|
||||
//
|
||||
// //go:linkname fn
|
||||
// var fn uintptr
|
||||
// var fnAddr = uintptr(unsafe.Pointer(&fn))
|
||||
//
|
||||
// TODO: maybe limit this case to just pointer sized variable?
|
||||
//
|
||||
// In summary, the "overwrite" variable and the final result are
|
||||
//
|
||||
// new sym old sym result
|
||||
// ---------------------------------------------
|
||||
// DATA DATA true => ERROR
|
||||
// DATA lg/eq BSS sm/eq true => new wins
|
||||
// DATA small BSS large true => ERROR
|
||||
// BSS large DATA small true => ERROR
|
||||
// BSS large BSS small true => new wins
|
||||
// BSS sm/eq D/B lg/eq false => old wins
|
||||
overwrite := r.DataSize(li) != 0 || oldsz < sz
|
||||
if overwrite {
|
||||
// TEXT BSS new wins
|
||||
// DATA DATA ERROR
|
||||
// DATA lg/eq BSS sm/eq new wins
|
||||
// DATA small BSS large ERROR
|
||||
// BSS large DATA small ERROR
|
||||
// BSS large BSS small new wins
|
||||
// BSS sm/eq D/B lg/eq old wins
|
||||
// BSS TEXT old wins
|
||||
oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
|
||||
newtyp := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
|
||||
oldIsText := oldtyp.IsText()
|
||||
newIsText := newtyp.IsText()
|
||||
oldHasContent := oldr.DataSize(oldli) != 0
|
||||
newHasContent := r.DataSize(li) != 0
|
||||
oldIsBSS := oldtyp.IsData() && !oldHasContent
|
||||
newIsBSS := newtyp.IsData() && !newHasContent
|
||||
switch {
|
||||
case newIsText && oldIsBSS,
|
||||
newHasContent && oldIsBSS && sz >= oldsz,
|
||||
newIsBSS && oldIsBSS && sz > oldsz:
|
||||
// new symbol overwrites old symbol.
|
||||
oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
|
||||
if !(oldtyp.IsData() && oldr.DataSize(oldli) == 0) || oldsz > sz {
|
||||
log.Fatalf("duplicated definition of symbol %s, from %s and %s", name, r.unit.Lib.Pkg, oldr.unit.Lib.Pkg)
|
||||
}
|
||||
l.objSyms[oldi] = objSym{r.objidx, li}
|
||||
} else {
|
||||
// old symbol overwrites new symbol.
|
||||
typ := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
|
||||
if !typ.IsData() { // only allow overwriting data symbol
|
||||
log.Fatalf("duplicated definition of symbol %s, from %s and %s", name, r.unit.Lib.Pkg, oldr.unit.Lib.Pkg)
|
||||
}
|
||||
case newIsBSS && (oldsz >= sz || oldIsText):
|
||||
// old win, just ignore the new symbol.
|
||||
default:
|
||||
log.Fatalf("duplicated definition of symbol %s, from %s (type %s size %d) and %s (type %s size %d)", name, r.unit.Lib.Pkg, newtyp, sz, oldr.unit.Lib.Pkg, oldtyp, oldsz)
|
||||
}
|
||||
return oldi
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user