mirror of
https://github.com/golang/go
synced 2024-11-26 16:46:58 -07:00
cmd/internal/goobj: store relocation type as uint16
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>
This commit is contained in:
parent
87d29939c8
commit
f901ea701d
@ -33,7 +33,7 @@ import (
|
|||||||
// New object file format.
|
// New object file format.
|
||||||
//
|
//
|
||||||
// Header struct {
|
// Header struct {
|
||||||
// Magic [...]byte // "\x00go116ld"
|
// Magic [...]byte // "\x00go117ld"
|
||||||
// Fingerprint [8]byte
|
// Fingerprint [8]byte
|
||||||
// Flags uint32
|
// Flags uint32
|
||||||
// Offsets [...]uint32 // byte offset of each block below
|
// Offsets [...]uint32 // byte offset of each block below
|
||||||
@ -89,7 +89,7 @@ import (
|
|||||||
// Relocs [...]struct {
|
// Relocs [...]struct {
|
||||||
// Off int32
|
// Off int32
|
||||||
// Size uint8
|
// Size uint8
|
||||||
// Type uint8
|
// Type uint16
|
||||||
// Add int64
|
// Add int64
|
||||||
// Sym symRef
|
// Sym symRef
|
||||||
// }
|
// }
|
||||||
@ -219,7 +219,7 @@ type Header struct {
|
|||||||
Offsets [NBlk]uint32
|
Offsets [NBlk]uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
const Magic = "\x00go116ld"
|
const Magic = "\x00go117ld"
|
||||||
|
|
||||||
func (h *Header) Write(w *Writer) {
|
func (h *Header) Write(w *Writer) {
|
||||||
w.RawString(h.Magic)
|
w.RawString(h.Magic)
|
||||||
@ -373,32 +373,32 @@ const HashSize = sha1.Size
|
|||||||
// Reloc struct {
|
// Reloc struct {
|
||||||
// Off int32
|
// Off int32
|
||||||
// Siz uint8
|
// Siz uint8
|
||||||
// Type uint8
|
// Type uint16
|
||||||
// Add int64
|
// Add int64
|
||||||
// Sym SymRef
|
// Sym SymRef
|
||||||
// }
|
// }
|
||||||
type Reloc [RelocSize]byte
|
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) Off() int32 { return int32(binary.LittleEndian.Uint32(r[:])) }
|
||||||
func (r *Reloc) Siz() uint8 { return r[4] }
|
func (r *Reloc) Siz() uint8 { return r[4] }
|
||||||
func (r *Reloc) Type() uint8 { return r[5] }
|
func (r *Reloc) Type() uint16 { return binary.LittleEndian.Uint16(r[5:]) }
|
||||||
func (r *Reloc) Add() int64 { return int64(binary.LittleEndian.Uint64(r[6:])) }
|
func (r *Reloc) Add() int64 { return int64(binary.LittleEndian.Uint64(r[7:])) }
|
||||||
func (r *Reloc) Sym() SymRef {
|
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) SetOff(x int32) { binary.LittleEndian.PutUint32(r[:], uint32(x)) }
|
||||||
func (r *Reloc) SetSiz(x uint8) { r[4] = x }
|
func (r *Reloc) SetSiz(x uint8) { r[4] = x }
|
||||||
func (r *Reloc) SetType(x uint8) { r[5] = x }
|
func (r *Reloc) SetType(x uint16) { binary.LittleEndian.PutUint16(r[5:], x) }
|
||||||
func (r *Reloc) SetAdd(x int64) { binary.LittleEndian.PutUint64(r[6:], uint64(x)) }
|
func (r *Reloc) SetAdd(x int64) { binary.LittleEndian.PutUint64(r[7:], uint64(x)) }
|
||||||
func (r *Reloc) SetSym(x SymRef) {
|
func (r *Reloc) SetSym(x SymRef) {
|
||||||
binary.LittleEndian.PutUint32(r[14:], x.PkgIdx)
|
binary.LittleEndian.PutUint32(r[15:], x.PkgIdx)
|
||||||
binary.LittleEndian.PutUint32(r[18:], x.SymIdx)
|
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.SetOff(off)
|
||||||
r.SetSiz(size)
|
r.SetSiz(size)
|
||||||
r.SetType(typ)
|
r.SetType(typ)
|
||||||
|
@ -40,7 +40,7 @@ func TestReadWrite(t *testing.T) {
|
|||||||
var r Reloc
|
var r Reloc
|
||||||
r.SetOff(12)
|
r.SetOff(12)
|
||||||
r.SetSiz(4)
|
r.SetSiz(4)
|
||||||
r.SetType(uint8(objabi.R_ADDR))
|
r.SetType(uint16(objabi.R_ADDR))
|
||||||
r.SetAdd(54321)
|
r.SetAdd(54321)
|
||||||
r.SetSym(SymRef{11, 22})
|
r.SetSym(SymRef{11, 22})
|
||||||
r.Write(w)
|
r.Write(w)
|
||||||
@ -63,7 +63,7 @@ func TestReadWrite(t *testing.T) {
|
|||||||
b = b[SymSize:]
|
b = b[SymSize:]
|
||||||
var r2 Reloc
|
var r2 Reloc
|
||||||
r2.fromBytes(b)
|
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())
|
t.Errorf("read Reloc2 mismatch: got %v %v %v %v %v", r2.Off(), r2.Siz(), r2.Type(), r2.Add(), r2.Sym())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,7 +498,7 @@ func (w *writer) Reloc(r *Reloc) {
|
|||||||
var o goobj.Reloc
|
var o goobj.Reloc
|
||||||
o.SetOff(r.Off)
|
o.SetOff(r.Off)
|
||||||
o.SetSiz(r.Siz)
|
o.SetSiz(r.Siz)
|
||||||
o.SetType(uint8(r.Type))
|
o.SetType(uint16(r.Type))
|
||||||
o.SetAdd(r.Add)
|
o.SetAdd(r.Add)
|
||||||
o.SetSym(makeSymRef(r.Sym))
|
o.SetSym(makeSymRef(r.Sym))
|
||||||
o.Write(w.Writer)
|
o.Write(w.Writer)
|
||||||
|
@ -51,31 +51,14 @@ type Reloc struct {
|
|||||||
*goobj.Reloc
|
*goobj.Reloc
|
||||||
r *oReader
|
r *oReader
|
||||||
l *Loader
|
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) 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) 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) 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) 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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aux holds a "handle" to access an aux symbol record from an
|
// Aux holds a "handle" to access an aux symbol record from an
|
||||||
// object file.
|
// object file.
|
||||||
type Aux struct {
|
type Aux struct {
|
||||||
@ -313,7 +296,6 @@ type extSymPayload struct {
|
|||||||
kind sym.SymKind
|
kind sym.SymKind
|
||||||
objidx uint32 // index of original object if sym made by cloneToExternal
|
objidx uint32 // index of original object if sym made by cloneToExternal
|
||||||
relocs []goobj.Reloc
|
relocs []goobj.Reloc
|
||||||
reltypes []objabi.RelocType // relocation types
|
|
||||||
data []byte
|
data []byte
|
||||||
auxs []goobj.Aux
|
auxs []goobj.Aux
|
||||||
}
|
}
|
||||||
@ -1833,10 +1815,9 @@ func (relocs *Relocs) Count() int { return len(relocs.rs) }
|
|||||||
// At returns the j-th reloc for a global symbol.
|
// At returns the j-th reloc for a global symbol.
|
||||||
func (relocs *Relocs) At(j int) Reloc {
|
func (relocs *Relocs) At(j int) Reloc {
|
||||||
if relocs.l.isExtReader(relocs.r) {
|
if relocs.l.isExtReader(relocs.r) {
|
||||||
pp := relocs.l.payloads[relocs.li]
|
return Reloc{&relocs.rs[j], relocs.r, relocs.l}
|
||||||
return Reloc{&relocs.rs[j], relocs.r, relocs.l, pp.reltypes[j]}
|
|
||||||
}
|
}
|
||||||
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.
|
// Relocs returns a Relocs object for the given global sym.
|
||||||
@ -2337,13 +2318,11 @@ func (l *Loader) cloneToExternal(symIdx Sym) {
|
|||||||
// Copy relocations
|
// Copy relocations
|
||||||
relocs := l.Relocs(symIdx)
|
relocs := l.Relocs(symIdx)
|
||||||
pp.relocs = make([]goobj.Reloc, relocs.Count())
|
pp.relocs = make([]goobj.Reloc, relocs.Count())
|
||||||
pp.reltypes = make([]objabi.RelocType, relocs.Count())
|
|
||||||
for i := range pp.relocs {
|
for i := range pp.relocs {
|
||||||
// Copy the relocs slice.
|
// Copy the relocs slice.
|
||||||
// Convert local reference to global reference.
|
// Convert local reference to global reference.
|
||||||
rel := relocs.At(i)
|
rel := relocs.At(i)
|
||||||
pp.relocs[i].Set(rel.Off(), rel.Siz(), 0, rel.Add(), goobj.SymRef{PkgIdx: 0, SymIdx: uint32(rel.Sym())})
|
pp.relocs[i].Set(rel.Off(), rel.Siz(), uint16(rel.Type()), rel.Add(), goobj.SymRef{PkgIdx: 0, SymIdx: uint32(rel.Sym())})
|
||||||
pp.reltypes[i] = rel.Type()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy data
|
// Copy data
|
||||||
|
@ -237,7 +237,8 @@ func sameRelocSlice(s1 *Relocs, s2 []Reloc) bool {
|
|||||||
type addFunc func(l *Loader, s Sym, s2 Sym) Sym
|
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 {
|
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.SetOff(off)
|
||||||
r.SetSiz(siz)
|
r.SetSiz(siz)
|
||||||
r.SetAdd(add)
|
r.SetAdd(add)
|
||||||
|
@ -121,13 +121,11 @@ func (sb *SymbolBuilder) Relocs() Relocs {
|
|||||||
// ResetRelocs removes all relocations on this symbol.
|
// ResetRelocs removes all relocations on this symbol.
|
||||||
func (sb *SymbolBuilder) ResetRelocs() {
|
func (sb *SymbolBuilder) ResetRelocs() {
|
||||||
sb.relocs = sb.relocs[:0]
|
sb.relocs = sb.relocs[:0]
|
||||||
sb.reltypes = sb.reltypes[:0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRelocType sets the type of the 'i'-th relocation on this sym to 't'
|
// SetRelocType sets the type of the 'i'-th relocation on this sym to 't'
|
||||||
func (sb *SymbolBuilder) SetRelocType(i int, t objabi.RelocType) {
|
func (sb *SymbolBuilder) SetRelocType(i int, t objabi.RelocType) {
|
||||||
sb.relocs[i].SetType(0)
|
sb.relocs[i].SetType(uint16(t))
|
||||||
sb.reltypes[i] = t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRelocSym sets the target sym of the 'i'-th relocation on this sym to 's'
|
// 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.
|
// Add n relocations, return a handle to the relocations.
|
||||||
func (sb *SymbolBuilder) AddRelocs(n int) Relocs {
|
func (sb *SymbolBuilder) AddRelocs(n int) Relocs {
|
||||||
sb.relocs = append(sb.relocs, make([]goobj.Reloc, n)...)
|
sb.relocs = append(sb.relocs, make([]goobj.Reloc, n)...)
|
||||||
sb.reltypes = append(sb.reltypes, make([]objabi.RelocType, n)...)
|
|
||||||
return sb.l.Relocs(sb.symIdx)
|
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) {
|
func (sb *SymbolBuilder) AddRel(typ objabi.RelocType) (Reloc, int) {
|
||||||
j := len(sb.relocs)
|
j := len(sb.relocs)
|
||||||
sb.relocs = append(sb.relocs, goobj.Reloc{})
|
sb.relocs = append(sb.relocs, goobj.Reloc{})
|
||||||
sb.reltypes = append(sb.reltypes, typ)
|
sb.relocs[j].SetType(uint16(typ))
|
||||||
relocs := sb.Relocs()
|
relocs := sb.Relocs()
|
||||||
return relocs.At(j), j
|
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) Less(i, j int) bool { return p.relocs[i].Off() < p.relocs[j].Off() }
|
||||||
func (p *relocsByOff) Swap(i, j int) {
|
func (p *relocsByOff) Swap(i, j int) {
|
||||||
p.relocs[i], p.relocs[j] = p.relocs[j], p.relocs[i]
|
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 {
|
func (sb *SymbolBuilder) Reachable() bool {
|
||||||
|
Loading…
Reference in New Issue
Block a user