[dev.link] cmd/link: batch allocations when converting external relocations

Change-Id: Iad81cb159e46f694a03d58892ca7dfde3ee3095a
Reviewed-on: https://go-review.googlesource.com/c/go/+/231219
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Zhang 2020-04-30 16:28:49 -04:00
parent f875f8fe76
commit 83db26ac4a
2 changed files with 43 additions and 12 deletions

View file

@ -285,6 +285,7 @@ type Loader struct {
Reachparent []Sym
relocBatch []sym.Reloc // for bulk allocation of relocations
relocExtBatch []sym.RelocExt // for bulk allocation of relocations
flags uint32
@ -2037,9 +2038,16 @@ func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols, needReloc bool) {
l.growSyms(l.NSym())
l.growSects(l.NSym())
if needReloc && len(l.extRelocs) != 0 {
// If needReloc is true, we are going to convert the loader's
// "internal" relocations to sym.Relocs. In this case, external
// relocations shouldn't be used.
panic("phase error")
}
nr := 0 // total number of sym.Reloc's we'll need
for _, o := range l.objs[1:] {
nr += loadObjSyms(l, syms, o.r)
nr += loadObjSyms(l, syms, o.r, needReloc)
}
// Make a first pass through the external symbols, making
@ -2052,7 +2060,12 @@ func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols, needReloc bool) {
continue
}
pp := l.getPayload(i)
if needReloc {
nr += len(pp.relocs)
}
if int(i) < len(l.extRelocs) {
nr += len(l.extRelocs[i])
}
// create and install the sym.Symbol here so that l.Syms will
// be fully populated when we do relocation processing and
// outer/sub processing below. Note that once we do this,
@ -2064,8 +2077,11 @@ func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols, needReloc bool) {
}
// allocate a single large slab of relocations for all live symbols
if needReloc {
if nr != 0 {
l.relocBatch = make([]sym.Reloc, nr)
if len(l.extRelocs) != 0 {
l.relocExtBatch = make([]sym.RelocExt, nr)
}
}
// convert payload-based external symbols into sym.Symbol-based
@ -2101,6 +2117,11 @@ func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols, needReloc bool) {
loadObjFull(l, o.r, needReloc)
}
// Sanity check: we should have consumed all batched allocations.
if len(l.relocBatch) != 0 || len(l.relocExtBatch) != 0 {
panic("batch allocation mismatch")
}
// Note: resolution of ABI aliases is now also handled in
// loader.convertRelocations, so once the host object loaders move
// completely to loader.Sym, we can remove the code below.
@ -2417,7 +2438,7 @@ func topLevelSym(sname string, skind sym.SymKind) bool {
// loadObjSyms creates sym.Symbol objects for the live Syms in the
// object corresponding to object reader "r". Return value is the
// number of sym.Reloc entries required for all the new symbols.
func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int {
func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader, needReloc bool) int {
nr := 0
for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
gi := r.syms[i]
@ -2447,8 +2468,13 @@ func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int {
}
l.addNewSym(gi, name, ver, r.unit, t)
if needReloc {
nr += r.NReloc(i)
}
if int(gi) < len(l.extRelocs) {
nr += len(l.extRelocs[gi])
}
}
return nr
}
@ -2764,13 +2790,18 @@ func (l *Loader) convertExtRelocs(dst *sym.Symbol, src Sym) {
if len(dst.R) != 0 {
panic("bad")
}
dst.R = make([]sym.Reloc, len(extRelocs))
n := len(extRelocs)
batch := l.relocBatch
dst.R = batch[:n:n]
l.relocBatch = batch[n:]
relocs := l.Relocs(src)
for i := range dst.R {
er := &extRelocs[i]
sr := relocs.At2(er.Idx)
r := &dst.R[i]
r.InitExt()
r.RelocExt = &l.relocExtBatch[0]
l.relocExtBatch = l.relocExtBatch[1:]
r.Off = sr.Off()
r.Siz = sr.Siz()
r.Type = sr.Type()

View file

@ -28,20 +28,20 @@ type Reloc struct {
Type objabi.RelocType // the relocation type
Add int64 // addend
Sym *Symbol // symbol the relocation addresses
*relocExt // extra fields (see below), may be nil, call InitExt before use
*RelocExt // extra fields (see below), may be nil, call InitExt before use
}
// relocExt contains extra fields in Reloc that are used only in
// certain cases.
type relocExt struct {
type RelocExt struct {
Xadd int64 // addend passed to external linker
Xsym *Symbol // symbol passed to external linker
Variant RelocVariant // variation on Type, currently used only on PPC64 and S390X
}
func (r *Reloc) InitExt() {
if r.relocExt == nil {
r.relocExt = new(relocExt)
if r.RelocExt == nil {
r.RelocExt = new(RelocExt)
}
}