cmd/link: fix bug with -newobj and "ld -r" ELF host objects

When the ELF host object loader encounters a static/hidden symbol, it
creates a sym.Symbol for it but does not enter it into the sym.Symbols
lookup table. Under -newobj mode, this was not happening correctly; we
were adding the sym via loader.LookupOrCreate, which resulted in
collisions when it encountered symbols with the same name + version +
section (this can happen for "ld -r" objects).

Fixes #35779.

Change-Id: I36d40fc1efc03fc1cd8ae6b76cb6a0d2a957389c
Reviewed-on: https://go-review.googlesource.com/c/go/+/208479
Run-TryBot: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Than McIntosh 2019-11-22 15:27:01 -05:00
parent 6ba1bf393a
commit f29e53d664
2 changed files with 37 additions and 4 deletions

View file

@ -130,6 +130,9 @@ const (
FlagStrictDups = 1 << iota
)
// anonVersion is used to tag symbols created by loader.Create.
const anonVersion = -1
func NewLoader(flags uint32) *Loader {
nbuiltin := goobj2.NBuiltin()
return &Loader{
@ -842,13 +845,15 @@ func (l *Loader) ExtractSymbols(syms *sym.Symbols) {
l.Syms[oldI] = nil
}
// For now, add all symbols to ctxt.Syms.
// Add symbols to the ctxt.Syms lookup table. This explicitly
// skips things created via loader.Create (marked with
// anonVersion), since if we tried to add these we'd wind up with
// collisions.
for _, s := range l.Syms {
if s != nil && s.Name != "" {
if s != nil && s.Name != "" && s.Version != anonVersion {
syms.Add(s)
}
}
}
// addNewSym adds a new sym.Symbol to the i-th index in the list of symbols.
@ -980,6 +985,28 @@ func (l *Loader) LookupOrCreate(name string, version int, syms *sym.Symbols) *sy
return s
}
// Create creates a symbol with the specified name, but does not
// insert it into any lookup table (hence it is possible to create a
// symbol name with name X when there is already an existing symbol
// named X entered into the loader). This method is intended for
// static/hidden symbols discovered while loading host objects.
func (l *Loader) Create(name string, syms *sym.Symbols) *sym.Symbol {
i := l.max + 1
l.max++
if l.extStart == 0 {
l.extStart = i
}
// Note the use of anonVersion -- this is to mark the symbol so that
// it can be skipped when ExtractSymbols is adding ext syms to the
// sym.Symbols hash.
l.extSyms = append(l.extSyms, nameVer{name, anonVersion})
l.growSyms(int(i))
s := syms.Newsym(name, -1)
l.Syms[i] = s
return s
}
func loadObjFull(l *Loader, r *oReader) {
lib := r.unit.Lib
istart := l.startIndex(r)