mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] cmd/link: experiment new reloc accessors in deadcode pass
There is a small speedup: (linking cmd/compile) name old time/op new time/op delta Deadcode 57.1ms ± 1% 53.5ms ± 1% -6.44% (p=0.008 n=5+5) With this, we don't need a slice to read the relocations, reduce some allocations. name old alloc/op new alloc/op delta Deadcode 4.16MB ± 0% 3.84MB ± 0% -7.85% (p=0.008 n=5+5) Change-Id: Icd41c05682ba3f293a8cb9d2fe818e39d7276e5a Reviewed-on: https://go-review.googlesource.com/c/go/+/222244 Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
c951514da9
commit
cf5c718cba
4 changed files with 93 additions and 59 deletions
|
|
@ -321,6 +321,15 @@ func (r *Reloc2) Sym() SymRef {
|
||||||
return SymRef{binary.LittleEndian.Uint32(r[14:]), binary.LittleEndian.Uint32(r[18:])}
|
return SymRef{binary.LittleEndian.Uint32(r[14:]), binary.LittleEndian.Uint32(r[18:])}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Reloc2) Set(off int32, size uint8, typ uint8, add int64, sym SymRef) {
|
||||||
|
binary.LittleEndian.PutUint32(r[:], uint32(off))
|
||||||
|
r[4] = size
|
||||||
|
r[5] = typ
|
||||||
|
binary.LittleEndian.PutUint64(r[6:], uint64(add))
|
||||||
|
binary.LittleEndian.PutUint32(r[14:], sym.PkgIdx)
|
||||||
|
binary.LittleEndian.PutUint32(r[18:], sym.SymIdx)
|
||||||
|
}
|
||||||
|
|
||||||
// Aux symbol info.
|
// Aux symbol info.
|
||||||
type Aux struct {
|
type Aux struct {
|
||||||
Type uint8
|
Type uint8
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ type deadcodePass2 struct {
|
||||||
ctxt *Link
|
ctxt *Link
|
||||||
ldr *loader.Loader
|
ldr *loader.Loader
|
||||||
wq workQueue
|
wq workQueue
|
||||||
rtmp []loader.Reloc
|
|
||||||
|
|
||||||
ifaceMethod map[methodsig]bool // methods declared in reached interfaces
|
ifaceMethod map[methodsig]bool // methods declared in reached interfaces
|
||||||
markableMethods []methodref2 // methods of reached types
|
markableMethods []methodref2 // methods of reached types
|
||||||
|
|
@ -86,9 +85,9 @@ func (d *deadcodePass2) init() {
|
||||||
// but we do keep the symbols it refers to.
|
// but we do keep the symbols it refers to.
|
||||||
exportsIdx := d.ldr.Lookup("go.plugin.exports", 0)
|
exportsIdx := d.ldr.Lookup("go.plugin.exports", 0)
|
||||||
if exportsIdx != 0 {
|
if exportsIdx != 0 {
|
||||||
d.ReadRelocSyms(exportsIdx)
|
relocs := d.ldr.Relocs(exportsIdx)
|
||||||
for i := 0; i < len(d.rtmp); i++ {
|
for i := 0; i < relocs.Count; i++ {
|
||||||
d.mark(d.rtmp[i].Sym, 0)
|
d.mark(relocs.At2(i).Sym(), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +118,6 @@ func (d *deadcodePass2) init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *deadcodePass2) flood() {
|
func (d *deadcodePass2) flood() {
|
||||||
symRelocs := []loader.Reloc{}
|
|
||||||
auxSyms := []loader.Sym{}
|
auxSyms := []loader.Sym{}
|
||||||
for !d.wq.empty() {
|
for !d.wq.empty() {
|
||||||
symIdx := d.wq.pop()
|
symIdx := d.wq.pop()
|
||||||
|
|
@ -128,22 +126,11 @@ func (d *deadcodePass2) flood() {
|
||||||
|
|
||||||
isgotype := d.ldr.IsGoType(symIdx)
|
isgotype := d.ldr.IsGoType(symIdx)
|
||||||
relocs := d.ldr.Relocs(symIdx)
|
relocs := d.ldr.Relocs(symIdx)
|
||||||
// For non-type symbols, we only need the target and the reloc
|
|
||||||
// type, so don't read other fields.
|
|
||||||
// For type symbols we may need all fields for interface
|
|
||||||
// satisfaction check.
|
|
||||||
// TODO: we don't even need the reloc type for non-type non-dwarf
|
|
||||||
// symbols.
|
|
||||||
if isgotype {
|
|
||||||
symRelocs = relocs.ReadAll(symRelocs)
|
|
||||||
} else {
|
|
||||||
symRelocs = relocs.ReadSyms(symRelocs)
|
|
||||||
}
|
|
||||||
|
|
||||||
if isgotype {
|
if isgotype {
|
||||||
p := d.ldr.Data(symIdx)
|
p := d.ldr.Data(symIdx)
|
||||||
if len(p) != 0 && decodetypeKind(d.ctxt.Arch, p)&kindMask == kindInterface {
|
if len(p) != 0 && decodetypeKind(d.ctxt.Arch, p)&kindMask == kindInterface {
|
||||||
for _, sig := range d.decodeIfaceMethods2(d.ldr, d.ctxt.Arch, symIdx, symRelocs) {
|
for _, sig := range d.decodeIfaceMethods2(d.ldr, d.ctxt.Arch, symIdx, &relocs) {
|
||||||
if d.ctxt.Debugvlog > 1 {
|
if d.ctxt.Debugvlog > 1 {
|
||||||
d.ctxt.Logf("reached iface method: %s\n", sig)
|
d.ctxt.Logf("reached iface method: %s\n", sig)
|
||||||
}
|
}
|
||||||
|
|
@ -154,11 +141,12 @@ func (d *deadcodePass2) flood() {
|
||||||
|
|
||||||
var methods []methodref2
|
var methods []methodref2
|
||||||
for i := 0; i < relocs.Count; i++ {
|
for i := 0; i < relocs.Count; i++ {
|
||||||
r := symRelocs[i]
|
r := relocs.At2(i)
|
||||||
if r.Type == objabi.R_WEAKADDROFF {
|
t := r.Type()
|
||||||
|
if t == objabi.R_WEAKADDROFF {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if r.Type == objabi.R_METHODOFF {
|
if t == objabi.R_METHODOFF {
|
||||||
if i+2 >= relocs.Count {
|
if i+2 >= relocs.Count {
|
||||||
panic("expect three consecutive R_METHODOFF relocs")
|
panic("expect three consecutive R_METHODOFF relocs")
|
||||||
}
|
}
|
||||||
|
|
@ -166,13 +154,13 @@ func (d *deadcodePass2) flood() {
|
||||||
i += 2
|
i += 2
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if r.Type == objabi.R_USETYPE {
|
if t == objabi.R_USETYPE {
|
||||||
// type symbol used for DWARF. we need to load the symbol but it may not
|
// type symbol used for DWARF. we need to load the symbol but it may not
|
||||||
// be otherwise reachable in the program.
|
// be otherwise reachable in the program.
|
||||||
// do nothing for now as we still load all type symbols.
|
// do nothing for now as we still load all type symbols.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
d.mark(r.Sym, symIdx)
|
d.mark(r.Sym(), symIdx)
|
||||||
}
|
}
|
||||||
auxSyms = d.ldr.ReadAuxSyms(symIdx, auxSyms)
|
auxSyms = d.ldr.ReadAuxSyms(symIdx, auxSyms)
|
||||||
for i := 0; i < len(auxSyms); i++ {
|
for i := 0; i < len(auxSyms); i++ {
|
||||||
|
|
@ -194,7 +182,7 @@ func (d *deadcodePass2) flood() {
|
||||||
// Decode runtime type information for type methods
|
// Decode runtime type information for type methods
|
||||||
// to help work out which methods can be called
|
// to help work out which methods can be called
|
||||||
// dynamically via interfaces.
|
// dynamically via interfaces.
|
||||||
methodsigs := d.decodetypeMethods2(d.ldr, d.ctxt.Arch, symIdx, symRelocs)
|
methodsigs := d.decodetypeMethods2(d.ldr, d.ctxt.Arch, symIdx, &relocs)
|
||||||
if len(methods) != len(methodsigs) {
|
if len(methods) != len(methodsigs) {
|
||||||
panic(fmt.Sprintf("%q has %d method relocations for %d methods", d.ldr.SymName(symIdx), len(methods), len(methodsigs)))
|
panic(fmt.Sprintf("%q has %d method relocations for %d methods", d.ldr.SymName(symIdx), len(methods), len(methodsigs)))
|
||||||
}
|
}
|
||||||
|
|
@ -227,10 +215,10 @@ func (d *deadcodePass2) mark(symIdx, parent loader.Sym) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *deadcodePass2) markMethod(m methodref2) {
|
func (d *deadcodePass2) markMethod(m methodref2) {
|
||||||
d.ReadRelocSyms(m.src)
|
relocs := d.ldr.Relocs(m.src)
|
||||||
d.mark(d.rtmp[m.r].Sym, m.src)
|
d.mark(relocs.At2(m.r).Sym(), m.src)
|
||||||
d.mark(d.rtmp[m.r+1].Sym, m.src)
|
d.mark(relocs.At2(m.r+1).Sym(), m.src)
|
||||||
d.mark(d.rtmp[m.r+2].Sym, m.src)
|
d.mark(relocs.At2(m.r+2).Sym(), m.src)
|
||||||
}
|
}
|
||||||
|
|
||||||
func deadcode2(ctxt *Link) {
|
func deadcode2(ctxt *Link) {
|
||||||
|
|
@ -313,15 +301,15 @@ func (m methodref2) isExported() bool {
|
||||||
// the function type.
|
// the function type.
|
||||||
//
|
//
|
||||||
// Conveniently this is the layout of both runtime.method and runtime.imethod.
|
// Conveniently this is the layout of both runtime.method and runtime.imethod.
|
||||||
func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, off, size, count int) []methodsig {
|
func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, off, size, count int) []methodsig {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
var methods []methodsig
|
var methods []methodsig
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
buf.WriteString(decodetypeName2(ldr, symIdx, symRelocs, off))
|
buf.WriteString(decodetypeName3(ldr, symIdx, relocs, off))
|
||||||
mtypSym := decodeRelocSym2(ldr, symIdx, symRelocs, int32(off+4))
|
mtypSym := decodeRelocSym3(ldr, symIdx, relocs, int32(off+4))
|
||||||
// FIXME: add some sort of caching here, since we may see some of the
|
// FIXME: add some sort of caching here, since we may see some of the
|
||||||
// same symbols over time for param types.
|
// same symbols over time for param types.
|
||||||
d.ReadRelocs(mtypSym)
|
mrelocs := ldr.Relocs(mtypSym)
|
||||||
mp := ldr.Data(mtypSym)
|
mp := ldr.Data(mtypSym)
|
||||||
|
|
||||||
buf.WriteRune('(')
|
buf.WriteRune('(')
|
||||||
|
|
@ -330,7 +318,7 @@ func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, sym
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
buf.WriteString(", ")
|
buf.WriteString(", ")
|
||||||
}
|
}
|
||||||
a := decodetypeFuncInType2(ldr, arch, mtypSym, d.rtmp, i)
|
a := decodetypeFuncInType3(ldr, arch, mtypSym, &mrelocs, i)
|
||||||
buf.WriteString(ldr.SymName(a))
|
buf.WriteString(ldr.SymName(a))
|
||||||
}
|
}
|
||||||
buf.WriteString(") (")
|
buf.WriteString(") (")
|
||||||
|
|
@ -339,7 +327,7 @@ func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, sym
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
buf.WriteString(", ")
|
buf.WriteString(", ")
|
||||||
}
|
}
|
||||||
a := decodetypeFuncOutType2(ldr, arch, mtypSym, d.rtmp, i)
|
a := decodetypeFuncOutType3(ldr, arch, mtypSym, &mrelocs, i)
|
||||||
buf.WriteString(ldr.SymName(a))
|
buf.WriteString(ldr.SymName(a))
|
||||||
}
|
}
|
||||||
buf.WriteRune(')')
|
buf.WriteRune(')')
|
||||||
|
|
@ -351,25 +339,26 @@ func (d *deadcodePass2) decodeMethodSig2(ldr *loader.Loader, arch *sys.Arch, sym
|
||||||
return methods
|
return methods
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *deadcodePass2) decodeIfaceMethods2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc) []methodsig {
|
func (d *deadcodePass2) decodeIfaceMethods2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs) []methodsig {
|
||||||
p := ldr.Data(symIdx)
|
p := ldr.Data(symIdx)
|
||||||
if decodetypeKind(arch, p)&kindMask != kindInterface {
|
if decodetypeKind(arch, p)&kindMask != kindInterface {
|
||||||
panic(fmt.Sprintf("symbol %q is not an interface", ldr.SymName(symIdx)))
|
panic(fmt.Sprintf("symbol %q is not an interface", ldr.SymName(symIdx)))
|
||||||
}
|
}
|
||||||
rel := decodeReloc2(ldr, symIdx, symRelocs, int32(commonsize(arch)+arch.PtrSize))
|
rel := decodeReloc3(ldr, symIdx, relocs, int32(commonsize(arch)+arch.PtrSize))
|
||||||
if rel.Sym == 0 {
|
s := rel.Sym()
|
||||||
|
if s == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if rel.Sym != symIdx {
|
if s != symIdx {
|
||||||
panic(fmt.Sprintf("imethod slice pointer in %q leads to a different symbol", ldr.SymName(symIdx)))
|
panic(fmt.Sprintf("imethod slice pointer in %q leads to a different symbol", ldr.SymName(symIdx)))
|
||||||
}
|
}
|
||||||
off := int(rel.Add) // array of reflect.imethod values
|
off := int(rel.Add()) // array of reflect.imethod values
|
||||||
numMethods := int(decodetypeIfaceMethodCount(arch, p))
|
numMethods := int(decodetypeIfaceMethodCount(arch, p))
|
||||||
sizeofIMethod := 4 + 4
|
sizeofIMethod := 4 + 4
|
||||||
return d.decodeMethodSig2(ldr, arch, symIdx, symRelocs, off, sizeofIMethod, numMethods)
|
return d.decodeMethodSig2(ldr, arch, symIdx, relocs, off, sizeofIMethod, numMethods)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *deadcodePass2) decodetypeMethods2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc) []methodsig {
|
func (d *deadcodePass2) decodetypeMethods2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs) []methodsig {
|
||||||
p := ldr.Data(symIdx)
|
p := ldr.Data(symIdx)
|
||||||
if !decodetypeHasUncommon(arch, p) {
|
if !decodetypeHasUncommon(arch, p) {
|
||||||
panic(fmt.Sprintf("no methods on %q", ldr.SymName(symIdx)))
|
panic(fmt.Sprintf("no methods on %q", ldr.SymName(symIdx)))
|
||||||
|
|
@ -400,19 +389,5 @@ func (d *deadcodePass2) decodetypeMethods2(ldr *loader.Loader, arch *sys.Arch, s
|
||||||
moff := int(decodeInuxi(arch, p[off+4+2+2:], 4))
|
moff := int(decodeInuxi(arch, p[off+4+2+2:], 4))
|
||||||
off += moff // offset to array of reflect.method values
|
off += moff // offset to array of reflect.method values
|
||||||
const sizeofMethod = 4 * 4 // sizeof reflect.method in program
|
const sizeofMethod = 4 * 4 // sizeof reflect.method in program
|
||||||
return d.decodeMethodSig2(ldr, arch, symIdx, symRelocs, off, sizeofMethod, mcount)
|
return d.decodeMethodSig2(ldr, arch, symIdx, relocs, off, sizeofMethod, mcount)
|
||||||
}
|
|
||||||
|
|
||||||
// readRelocs reads the relocations for the specified symbol into the
|
|
||||||
// deadcode relocs work array. Use with care, since the work array
|
|
||||||
// is a singleton.
|
|
||||||
func (d *deadcodePass2) ReadRelocs(symIdx loader.Sym) {
|
|
||||||
relocs := d.ldr.Relocs(symIdx)
|
|
||||||
d.rtmp = relocs.ReadAll(d.rtmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Like ReadRelocs, but only reads target symbols.
|
|
||||||
func (d *deadcodePass2) ReadRelocSyms(symIdx loader.Sym) {
|
|
||||||
relocs := d.ldr.Relocs(symIdx)
|
|
||||||
d.rtmp = relocs.ReadSyms(d.rtmp)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,24 @@ func decodeReloc2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Relo
|
||||||
return loader.Reloc{}
|
return loader.Reloc{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodeReloc3(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int32) loader.Reloc2 {
|
||||||
|
for j := 0; j < relocs.Count; j++ {
|
||||||
|
rel := relocs.At2(j)
|
||||||
|
if rel.Off() == off {
|
||||||
|
return rel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return loader.Reloc2{}
|
||||||
|
}
|
||||||
|
|
||||||
func decodeRelocSym2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int32) loader.Sym {
|
func decodeRelocSym2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int32) loader.Sym {
|
||||||
return decodeReloc2(ldr, symIdx, symRelocs, off).Sym
|
return decodeReloc2(ldr, symIdx, symRelocs, off).Sym
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodeRelocSym3(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int32) loader.Sym {
|
||||||
|
return decodeReloc3(ldr, symIdx, relocs, off).Sym()
|
||||||
|
}
|
||||||
|
|
||||||
// decodetypeName2 decodes the name from a reflect.name.
|
// decodetypeName2 decodes the name from a reflect.name.
|
||||||
func decodetypeName2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int) string {
|
func decodetypeName2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.Reloc, off int) string {
|
||||||
r := decodeRelocSym2(ldr, symIdx, symRelocs, int32(off))
|
r := decodeRelocSym2(ldr, symIdx, symRelocs, int32(off))
|
||||||
|
|
@ -41,6 +55,17 @@ func decodetypeName2(ldr *loader.Loader, symIdx loader.Sym, symRelocs []loader.R
|
||||||
return string(data[3 : 3+namelen])
|
return string(data[3 : 3+namelen])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodetypeName3(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int) string {
|
||||||
|
r := decodeRelocSym3(ldr, symIdx, relocs, int32(off))
|
||||||
|
if r == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
data := ldr.Data(r)
|
||||||
|
namelen := int(uint16(data[1])<<8 | uint16(data[2]))
|
||||||
|
return string(data[3 : 3+namelen])
|
||||||
|
}
|
||||||
|
|
||||||
func decodetypeFuncInType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, i int) loader.Sym {
|
func decodetypeFuncInType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, i int) loader.Sym {
|
||||||
uadd := commonsize(arch) + 4
|
uadd := commonsize(arch) + 4
|
||||||
if arch.PtrSize == 8 {
|
if arch.PtrSize == 8 {
|
||||||
|
|
@ -52,10 +77,25 @@ func decodetypeFuncInType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym
|
||||||
return decodeRelocSym2(ldr, symIdx, symRelocs, int32(uadd+i*arch.PtrSize))
|
return decodeRelocSym2(ldr, symIdx, symRelocs, int32(uadd+i*arch.PtrSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodetypeFuncInType3(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym {
|
||||||
|
uadd := commonsize(arch) + 4
|
||||||
|
if arch.PtrSize == 8 {
|
||||||
|
uadd += 4
|
||||||
|
}
|
||||||
|
if decodetypeHasUncommon(arch, ldr.Data(symIdx)) {
|
||||||
|
uadd += uncommonSize()
|
||||||
|
}
|
||||||
|
return decodeRelocSym3(ldr, symIdx, relocs, int32(uadd+i*arch.PtrSize))
|
||||||
|
}
|
||||||
|
|
||||||
func decodetypeFuncOutType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, i int) loader.Sym {
|
func decodetypeFuncOutType2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, symRelocs []loader.Reloc, i int) loader.Sym {
|
||||||
return decodetypeFuncInType2(ldr, arch, symIdx, symRelocs, i+decodetypeFuncInCount(arch, ldr.Data(symIdx)))
|
return decodetypeFuncInType2(ldr, arch, symIdx, symRelocs, i+decodetypeFuncInCount(arch, ldr.Data(symIdx)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func decodetypeFuncOutType3(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym {
|
||||||
|
return decodetypeFuncInType3(ldr, arch, symIdx, relocs, i+decodetypeFuncInCount(arch, ldr.Data(symIdx)))
|
||||||
|
}
|
||||||
|
|
||||||
func decodetypeArrayElem2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
|
func decodetypeArrayElem2(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
|
||||||
// FIXME: it's inefficient to read the relocations each time. Add some
|
// FIXME: it's inefficient to read the relocations each time. Add some
|
||||||
// sort of cache here, or pass in the relocs. Alternatively we could
|
// sort of cache here, or pass in the relocs. Alternatively we could
|
||||||
|
|
|
||||||
|
|
@ -520,6 +520,12 @@ func (l *Loader) resolve(r *oReader, s goobj2.SymRef) Sym {
|
||||||
var rr *oReader
|
var rr *oReader
|
||||||
switch p := s.PkgIdx; p {
|
switch p := s.PkgIdx; p {
|
||||||
case goobj2.PkgIdxInvalid:
|
case goobj2.PkgIdxInvalid:
|
||||||
|
// {0, X} with non-zero X is never a valid sym reference from a Go object.
|
||||||
|
// We steal this space for symbol references from external objects.
|
||||||
|
// In this case, X is just the global index.
|
||||||
|
if l.isExtReader(r) {
|
||||||
|
return Sym(s.SymIdx)
|
||||||
|
}
|
||||||
if s.SymIdx != 0 {
|
if s.SymIdx != 0 {
|
||||||
panic("bad sym ref")
|
panic("bad sym ref")
|
||||||
}
|
}
|
||||||
|
|
@ -1448,10 +1454,14 @@ func (relocs *Relocs) At(j int) Reloc {
|
||||||
|
|
||||||
func (relocs *Relocs) At2(j int) Reloc2 {
|
func (relocs *Relocs) At2(j int) Reloc2 {
|
||||||
if relocs.l.isExtReader(relocs.r) {
|
if relocs.l.isExtReader(relocs.r) {
|
||||||
// TODO: implement this. How? Maybe we can construct the reloc
|
pp := relocs.l.payloads[relocs.li]
|
||||||
// data for external symbols in the same byte form as the one
|
r := pp.relocs[j]
|
||||||
// in the object file?
|
// XXX populate a goobj2.Reloc from external reloc record.
|
||||||
panic("not implemented")
|
// Ugly. Maybe we just want to use this format to store the
|
||||||
|
// reloc record in the first place?
|
||||||
|
var b goobj2.Reloc2
|
||||||
|
b.Set(r.Off, r.Size, uint8(r.Type), r.Add, goobj2.SymRef{PkgIdx: 0, SymIdx: uint32(r.Sym)})
|
||||||
|
return Reloc2{&b, relocs.r, relocs.l}
|
||||||
}
|
}
|
||||||
return Reloc2{relocs.r.Reloc2(relocs.li, j), relocs.r, relocs.l}
|
return Reloc2{relocs.r.Reloc2(relocs.li, j), relocs.r, relocs.l}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue