mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[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:
parent
f875f8fe76
commit
83db26ac4a
2 changed files with 43 additions and 12 deletions
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue