From b661547d94b89f6279710e4f4c58282b664e7b9c Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Wed, 16 Oct 2019 16:21:42 -0400 Subject: [PATCH] [dev.link] cmd/link: new loader method for reading relocations in batch Add a new loader.Relocs method that reads all of the relocations for a symbol into a slice. Handy in cases where the client knows in advance that it wants to visit all the relocations on a symbol (as opposed to just one or two). Change-Id: I1a420513e160c8bb4b90c9824ae8d5b5de060c15 Reviewed-on: https://go-review.googlesource.com/c/go/+/201721 Run-TryBot: Than McIntosh TryBot-Result: Gobot Gobot Reviewed-by: Jeremy Faller Reviewed-by: Cherry Zhang --- src/cmd/link/internal/loader/loader.go | 49 +++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 5f631f1625..6ad37d6061 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -442,6 +442,51 @@ func (relocs *Relocs) At(j int) Reloc { } } +// ReadAll method reads all relocations for a symbol into the +// specified slice. If the slice capacity is not large enough, a new +// larger slice will be allocated. Final slice is returned. +func (relocs *Relocs) ReadAll(dst []Reloc) []Reloc { + if relocs.Count == 0 { + return dst + } + + if cap(dst) < relocs.Count { + dst = make([]Reloc, relocs.Count) + } + dst = dst[:0] + + if relocs.ext != nil { + for i := 0; i < relocs.Count; i++ { + erel := &relocs.ext.R[i] + rel := Reloc{ + Off: erel.Off, + Size: erel.Siz, + Type: erel.Type, + Add: erel.Add, + Sym: relocs.l.Lookup(erel.Sym.Name, int(erel.Sym.Version)), + } + dst = append(dst, rel) + } + return dst + } + + off := relocs.r.RelocOff(relocs.li, 0) + for i := 0; i < relocs.Count; i++ { + rel := goobj2.Reloc{} + rel.Read(relocs.r.Reader, off) + off += uint32(rel.Size()) + target := relocs.l.resolve(relocs.r, rel.Sym) + dst = append(dst, Reloc{ + Off: rel.Off, + Size: rel.Siz, + Type: objabi.RelocType(rel.Type), + Add: rel.Add, + Sym: target, + }) + } + return dst +} + // Relocs returns a Relocs object for the given global sym. func (l *Loader) Relocs(i Sym) Relocs { if l.isExternal(i) { @@ -651,6 +696,7 @@ func loadObjFull(l *Loader, r *oReader) { } pcdataBase := r.PcdataBase() + rslice := []Reloc{} for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ { osym := goobj2.Sym{} osym.Read(r.Reader, r.SymOff(i)) @@ -692,9 +738,10 @@ func loadObjFull(l *Loader, r *oReader) { // Relocs relocs := l.relocs(r, i) + rslice = relocs.ReadAll(rslice) s.R = make([]sym.Reloc, relocs.Count) for j := range s.R { - r := relocs.At(j) + r := rslice[j] rs := r.Sym sz := r.Size rt := r.Type -- 2.48.1