]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/link: new loader method for reading relocations in batch
authorThan McIntosh <thanm@google.com>
Wed, 16 Oct 2019 20:21:42 +0000 (16:21 -0400)
committerThan McIntosh <thanm@google.com>
Thu, 17 Oct 2019 20:08:33 +0000 (20:08 +0000)
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 <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/link/internal/loader/loader.go

index 5f631f16256d2227c2fd70f8c0aaceaf572e8032..6ad37d60618eb11d3d23914a33773a0b27feb670 100644 (file)
@@ -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