]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/internal/goobj: store relocation type as uint16
authorCherry Zhang <cherryyz@google.com>
Sun, 8 Nov 2020 16:27:53 +0000 (11:27 -0500)
committerCherry Zhang <cherryyz@google.com>
Fri, 5 Mar 2021 23:34:43 +0000 (23:34 +0000)
Currently, relocation type is stored as uint8 in object files, as
Go relocations do not exceed 255. In the linker, however, it is
used as a 16-bit type, because external relocations can exceed
255. The linker has to store the extra byte in a side table. This
complicates many things.

Just store it as uint16 in object files. This simplifies things,
with a small cost of increasing the object file sizes.

               before      after
hello.o         1672        1678
runtime.a    7927784     8056194

Change-Id: I313cf44ad0b8b3b76e35055ae55d911ff35e3158
Reviewed-on: https://go-review.googlesource.com/c/go/+/268477
Trust: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/internal/goobj/objfile.go
src/cmd/internal/goobj/objfile_test.go
src/cmd/internal/obj/objfile.go
src/cmd/link/internal/loader/loader.go
src/cmd/link/internal/loader/loader_test.go
src/cmd/link/internal/loader/symbolbuilder.go

index 247cc695f07a1b514c56b29aa59f551c4b8c68c1..e2858bd57da0ca42abe5eafc7f8df2f7c8a36882 100644 (file)
@@ -33,7 +33,7 @@ import (
 // New object file format.
 //
 //    Header struct {
-//       Magic       [...]byte   // "\x00go116ld"
+//       Magic       [...]byte   // "\x00go117ld"
 //       Fingerprint [8]byte
 //       Flags       uint32
 //       Offsets     [...]uint32 // byte offset of each block below
@@ -89,7 +89,7 @@ import (
 //    Relocs [...]struct {
 //       Off  int32
 //       Size uint8
-//       Type uint8
+//       Type uint16
 //       Add  int64
 //       Sym  symRef
 //    }
@@ -219,7 +219,7 @@ type Header struct {
        Offsets     [NBlk]uint32
 }
 
-const Magic = "\x00go116ld"
+const Magic = "\x00go117ld"
 
 func (h *Header) Write(w *Writer) {
        w.RawString(h.Magic)
@@ -373,32 +373,32 @@ const HashSize = sha1.Size
 // Reloc struct {
 //    Off  int32
 //    Siz  uint8
-//    Type uint8
+//    Type uint16
 //    Add  int64
 //    Sym  SymRef
 // }
 type Reloc [RelocSize]byte
 
-const RelocSize = 4 + 1 + 1 + 8 + 8
+const RelocSize = 4 + 1 + 2 + 8 + 8
 
-func (r *Reloc) Off() int32  { return int32(binary.LittleEndian.Uint32(r[:])) }
-func (r *Reloc) Siz() uint8  { return r[4] }
-func (r *Reloc) Type() uint8 { return r[5] }
-func (r *Reloc) Add() int64  { return int64(binary.LittleEndian.Uint64(r[6:])) }
+func (r *Reloc) Off() int32   { return int32(binary.LittleEndian.Uint32(r[:])) }
+func (r *Reloc) Siz() uint8   { return r[4] }
+func (r *Reloc) Type() uint16 { return binary.LittleEndian.Uint16(r[5:]) }
+func (r *Reloc) Add() int64   { return int64(binary.LittleEndian.Uint64(r[7:])) }
 func (r *Reloc) Sym() SymRef {
-       return SymRef{binary.LittleEndian.Uint32(r[14:]), binary.LittleEndian.Uint32(r[18:])}
+       return SymRef{binary.LittleEndian.Uint32(r[15:]), binary.LittleEndian.Uint32(r[19:])}
 }
 
-func (r *Reloc) SetOff(x int32)  { binary.LittleEndian.PutUint32(r[:], uint32(x)) }
-func (r *Reloc) SetSiz(x uint8)  { r[4] = x }
-func (r *Reloc) SetType(x uint8) { r[5] = x }
-func (r *Reloc) SetAdd(x int64)  { binary.LittleEndian.PutUint64(r[6:], uint64(x)) }
+func (r *Reloc) SetOff(x int32)   { binary.LittleEndian.PutUint32(r[:], uint32(x)) }
+func (r *Reloc) SetSiz(x uint8)   { r[4] = x }
+func (r *Reloc) SetType(x uint16) { binary.LittleEndian.PutUint16(r[5:], x) }
+func (r *Reloc) SetAdd(x int64)   { binary.LittleEndian.PutUint64(r[7:], uint64(x)) }
 func (r *Reloc) SetSym(x SymRef) {
-       binary.LittleEndian.PutUint32(r[14:], x.PkgIdx)
-       binary.LittleEndian.PutUint32(r[18:], x.SymIdx)
+       binary.LittleEndian.PutUint32(r[15:], x.PkgIdx)
+       binary.LittleEndian.PutUint32(r[19:], x.SymIdx)
 }
 
-func (r *Reloc) Set(off int32, size uint8, typ uint8, add int64, sym SymRef) {
+func (r *Reloc) Set(off int32, size uint8, typ uint16, add int64, sym SymRef) {
        r.SetOff(off)
        r.SetSiz(size)
        r.SetType(typ)
index 99d02a1bf1d1117be3d2ca89a24feb4893361deb..ad80ede0f38e5035f30011fe5082685ed64a7d09 100644 (file)
@@ -40,7 +40,7 @@ func TestReadWrite(t *testing.T) {
        var r Reloc
        r.SetOff(12)
        r.SetSiz(4)
-       r.SetType(uint8(objabi.R_ADDR))
+       r.SetType(uint16(objabi.R_ADDR))
        r.SetAdd(54321)
        r.SetSym(SymRef{11, 22})
        r.Write(w)
@@ -63,7 +63,7 @@ func TestReadWrite(t *testing.T) {
        b = b[SymSize:]
        var r2 Reloc
        r2.fromBytes(b)
-       if r2.Off() != 12 || r2.Siz() != 4 || r2.Type() != uint8(objabi.R_ADDR) || r2.Add() != 54321 || r2.Sym() != (SymRef{11, 22}) {
+       if r2.Off() != 12 || r2.Siz() != 4 || r2.Type() != uint16(objabi.R_ADDR) || r2.Add() != 54321 || r2.Sym() != (SymRef{11, 22}) {
                t.Errorf("read Reloc2 mismatch: got %v %v %v %v %v", r2.Off(), r2.Siz(), r2.Type(), r2.Add(), r2.Sym())
        }
 
index b031afbc36906c4ed51d4db4e6e83cc282a8a5e9..24fb5a19dec5b1dd48f7da55a4dd79be40ac2fe7 100644 (file)
@@ -498,7 +498,7 @@ func (w *writer) Reloc(r *Reloc) {
        var o goobj.Reloc
        o.SetOff(r.Off)
        o.SetSiz(r.Siz)
-       o.SetType(uint8(r.Type))
+       o.SetType(uint16(r.Type))
        o.SetAdd(r.Add)
        o.SetSym(makeSymRef(r.Sym))
        o.Write(w.Writer)
index c05309a14136de35b7a4006d00ca7712005da27b..6d2e7dcabc4840984f569c1404fa58d3a609a1b0 100644 (file)
@@ -51,30 +51,13 @@ type Reloc struct {
        *goobj.Reloc
        r *oReader
        l *Loader
-
-       // External reloc types may not fit into a uint8 which the Go object file uses.
-       // Store it here, instead of in the byte of goobj.Reloc.
-       // For Go symbols this will always be zero.
-       // goobj.Reloc.Type() + typ is always the right type, for both Go and external
-       // symbols.
-       typ objabi.RelocType
 }
 
-func (rel Reloc) Type() objabi.RelocType { return objabi.RelocType(rel.Reloc.Type()) + rel.typ }
-func (rel Reloc) Sym() Sym               { return rel.l.resolve(rel.r, rel.Reloc.Sym()) }
-func (rel Reloc) SetSym(s Sym)           { rel.Reloc.SetSym(goobj.SymRef{PkgIdx: 0, SymIdx: uint32(s)}) }
-func (rel Reloc) IsMarker() bool         { return rel.Siz() == 0 }
-
-func (rel Reloc) SetType(t objabi.RelocType) {
-       if t != objabi.RelocType(uint8(t)) {
-               panic("SetType: type doesn't fit into Reloc")
-       }
-       rel.Reloc.SetType(uint8(t))
-       if rel.typ != 0 {
-               // should use SymbolBuilder.SetRelocType
-               panic("wrong method to set reloc type")
-       }
-}
+func (rel Reloc) Type() objabi.RelocType     { return objabi.RelocType(rel.Reloc.Type()) }
+func (rel Reloc) SetType(t objabi.RelocType) { rel.Reloc.SetType(uint16(t)) }
+func (rel Reloc) Sym() Sym                   { return rel.l.resolve(rel.r, rel.Reloc.Sym()) }
+func (rel Reloc) SetSym(s Sym)               { rel.Reloc.SetSym(goobj.SymRef{PkgIdx: 0, SymIdx: uint32(s)}) }
+func (rel Reloc) IsMarker() bool             { return rel.Siz() == 0 }
 
 // Aux holds a "handle" to access an aux symbol record from an
 // object file.
@@ -307,15 +290,14 @@ type elfsetstringFunc func(str string, off int)
 // extSymPayload holds the payload (data + relocations) for linker-synthesized
 // external symbols (note that symbol value is stored in a separate slice).
 type extSymPayload struct {
-       name     string // TODO: would this be better as offset into str table?
-       size     int64
-       ver      int
-       kind     sym.SymKind
-       objidx   uint32 // index of original object if sym made by cloneToExternal
-       relocs   []goobj.Reloc
-       reltypes []objabi.RelocType // relocation types
-       data     []byte
-       auxs     []goobj.Aux
+       name   string // TODO: would this be better as offset into str table?
+       size   int64
+       ver    int
+       kind   sym.SymKind
+       objidx uint32 // index of original object if sym made by cloneToExternal
+       relocs []goobj.Reloc
+       data   []byte
+       auxs   []goobj.Aux
 }
 
 const (
@@ -1833,10 +1815,9 @@ func (relocs *Relocs) Count() int { return len(relocs.rs) }
 // At returns the j-th reloc for a global symbol.
 func (relocs *Relocs) At(j int) Reloc {
        if relocs.l.isExtReader(relocs.r) {
-               pp := relocs.l.payloads[relocs.li]
-               return Reloc{&relocs.rs[j], relocs.r, relocs.l, pp.reltypes[j]}
+               return Reloc{&relocs.rs[j], relocs.r, relocs.l}
        }
-       return Reloc{&relocs.rs[j], relocs.r, relocs.l, 0}
+       return Reloc{&relocs.rs[j], relocs.r, relocs.l}
 }
 
 // Relocs returns a Relocs object for the given global sym.
@@ -2337,13 +2318,11 @@ func (l *Loader) cloneToExternal(symIdx Sym) {
                // Copy relocations
                relocs := l.Relocs(symIdx)
                pp.relocs = make([]goobj.Reloc, relocs.Count())
-               pp.reltypes = make([]objabi.RelocType, relocs.Count())
                for i := range pp.relocs {
                        // Copy the relocs slice.
                        // Convert local reference to global reference.
                        rel := relocs.At(i)
-                       pp.relocs[i].Set(rel.Off(), rel.Siz(), 0, rel.Add(), goobj.SymRef{PkgIdx: 0, SymIdx: uint32(rel.Sym())})
-                       pp.reltypes[i] = rel.Type()
+                       pp.relocs[i].Set(rel.Off(), rel.Siz(), uint16(rel.Type()), rel.Add(), goobj.SymRef{PkgIdx: 0, SymIdx: uint32(rel.Sym())})
                }
 
                // Copy data
index 1371c2a5410b798e8be959a0ee665f714a64406e..15ae830dc948af487c7a3313bed61367b52181df 100644 (file)
@@ -237,7 +237,8 @@ func sameRelocSlice(s1 *Relocs, s2 []Reloc) bool {
 type addFunc func(l *Loader, s Sym, s2 Sym) Sym
 
 func mkReloc(l *Loader, typ objabi.RelocType, off int32, siz uint8, add int64, sym Sym) Reloc {
-       r := Reloc{&goobj.Reloc{}, l.extReader, l, typ}
+       r := Reloc{&goobj.Reloc{}, l.extReader, l}
+       r.SetType(typ)
        r.SetOff(off)
        r.SetSiz(siz)
        r.SetAdd(add)
index 5d37da8ac6fac22d80a2316411766f1c16b6aee2..204d04412dc24985fa3cb7a560989a840026170e 100644 (file)
@@ -121,13 +121,11 @@ func (sb *SymbolBuilder) Relocs() Relocs {
 // ResetRelocs removes all relocations on this symbol.
 func (sb *SymbolBuilder) ResetRelocs() {
        sb.relocs = sb.relocs[:0]
-       sb.reltypes = sb.reltypes[:0]
 }
 
 // SetRelocType sets the type of the 'i'-th relocation on this sym to 't'
 func (sb *SymbolBuilder) SetRelocType(i int, t objabi.RelocType) {
-       sb.relocs[i].SetType(0)
-       sb.reltypes[i] = t
+       sb.relocs[i].SetType(uint16(t))
 }
 
 // SetRelocSym sets the target sym of the 'i'-th relocation on this sym to 's'
@@ -143,7 +141,6 @@ func (sb *SymbolBuilder) SetRelocAdd(i int, a int64) {
 // Add n relocations, return a handle to the relocations.
 func (sb *SymbolBuilder) AddRelocs(n int) Relocs {
        sb.relocs = append(sb.relocs, make([]goobj.Reloc, n)...)
-       sb.reltypes = append(sb.reltypes, make([]objabi.RelocType, n)...)
        return sb.l.Relocs(sb.symIdx)
 }
 
@@ -152,7 +149,7 @@ func (sb *SymbolBuilder) AddRelocs(n int) Relocs {
 func (sb *SymbolBuilder) AddRel(typ objabi.RelocType) (Reloc, int) {
        j := len(sb.relocs)
        sb.relocs = append(sb.relocs, goobj.Reloc{})
-       sb.reltypes = append(sb.reltypes, typ)
+       sb.relocs[j].SetType(uint16(typ))
        relocs := sb.Relocs()
        return relocs.At(j), j
 }
@@ -169,7 +166,6 @@ func (p *relocsByOff) Len() int           { return len(p.relocs) }
 func (p *relocsByOff) Less(i, j int) bool { return p.relocs[i].Off() < p.relocs[j].Off() }
 func (p *relocsByOff) Swap(i, j int) {
        p.relocs[i], p.relocs[j] = p.relocs[j], p.relocs[i]
-       p.reltypes[i], p.reltypes[j] = p.reltypes[j], p.reltypes[i]
 }
 
 func (sb *SymbolBuilder) Reachable() bool {