1
0
mirror of https://github.com/golang/go synced 2024-11-26 17:16:54 -07:00

cmd/internal/objabi: use a separate bit to mark weak relocation

Instead of using two relocation types R_XXX and R_WEAKXXX, use a
separate bit, R_WEAK, to mark weak relocations. This makes it
easier to add more weak relocation types.

Change-Id: Iec4195c2aefa65f59e464c83018246e17cd08173
Reviewed-on: https://go-review.googlesource.com/c/go/+/268478
Trust: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Zhang 2020-11-08 11:50:10 -05:00
parent 009bfeae86
commit 414fa8c35e
5 changed files with 85 additions and 78 deletions

View File

@ -50,11 +50,6 @@ const (
// R_ADDROFF resolves to a 32-bit offset from the beginning of the section // R_ADDROFF resolves to a 32-bit offset from the beginning of the section
// holding the data being relocated to the referenced symbol. // holding the data being relocated to the referenced symbol.
R_ADDROFF R_ADDROFF
// R_WEAKADDROFF resolves just like R_ADDROFF but is a weak relocation.
// A weak relocation does not make the symbol it refers to reachable,
// and is only honored by the linker if the symbol is in some other way
// reachable.
R_WEAKADDROFF
R_SIZE R_SIZE
R_CALL R_CALL
R_CALLARM R_CALLARM
@ -256,6 +251,14 @@ const (
// of a symbol. This isn't a real relocation, it can be placed in anywhere // of a symbol. This isn't a real relocation, it can be placed in anywhere
// in a symbol and target any symbols. // in a symbol and target any symbols.
R_XCOFFREF R_XCOFFREF
// R_WEAK marks the relocation as a weak reference.
// A weak relocation does not make the symbol it refers to reachable,
// and is only honored by the linker if the symbol is in some other way
// reachable.
R_WEAK = -1 << 15
R_WEAKADDROFF = R_WEAK | R_ADDROFF
) )
// IsDirectCall reports whether r is a relocation for a direct call. // IsDirectCall reports whether r is a relocation for a direct call.

View File

@ -13,66 +13,65 @@ func _() {
_ = x[R_ADDRARM64-3] _ = x[R_ADDRARM64-3]
_ = x[R_ADDRMIPS-4] _ = x[R_ADDRMIPS-4]
_ = x[R_ADDROFF-5] _ = x[R_ADDROFF-5]
_ = x[R_WEAKADDROFF-6] _ = x[R_SIZE-6]
_ = x[R_SIZE-7] _ = x[R_CALL-7]
_ = x[R_CALL-8] _ = x[R_CALLARM-8]
_ = x[R_CALLARM-9] _ = x[R_CALLARM64-9]
_ = x[R_CALLARM64-10] _ = x[R_CALLIND-10]
_ = x[R_CALLIND-11] _ = x[R_CALLPOWER-11]
_ = x[R_CALLPOWER-12] _ = x[R_CALLMIPS-12]
_ = x[R_CALLMIPS-13] _ = x[R_CALLRISCV-13]
_ = x[R_CALLRISCV-14] _ = x[R_CONST-14]
_ = x[R_CONST-15] _ = x[R_PCREL-15]
_ = x[R_PCREL-16] _ = x[R_TLS_LE-16]
_ = x[R_TLS_LE-17] _ = x[R_TLS_IE-17]
_ = x[R_TLS_IE-18] _ = x[R_GOTOFF-18]
_ = x[R_GOTOFF-19] _ = x[R_PLT0-19]
_ = x[R_PLT0-20] _ = x[R_PLT1-20]
_ = x[R_PLT1-21] _ = x[R_PLT2-21]
_ = x[R_PLT2-22] _ = x[R_USEFIELD-22]
_ = x[R_USEFIELD-23] _ = x[R_USETYPE-23]
_ = x[R_USETYPE-24] _ = x[R_USEIFACE-24]
_ = x[R_USEIFACE-25] _ = x[R_USEIFACEMETHOD-25]
_ = x[R_USEIFACEMETHOD-26] _ = x[R_METHODOFF-26]
_ = x[R_METHODOFF-27] _ = x[R_POWER_TOC-27]
_ = x[R_POWER_TOC-28] _ = x[R_GOTPCREL-28]
_ = x[R_GOTPCREL-29] _ = x[R_JMPMIPS-29]
_ = x[R_JMPMIPS-30] _ = x[R_DWARFSECREF-30]
_ = x[R_DWARFSECREF-31] _ = x[R_DWARFFILEREF-31]
_ = x[R_DWARFFILEREF-32] _ = x[R_ARM64_TLS_LE-32]
_ = x[R_ARM64_TLS_LE-33] _ = x[R_ARM64_TLS_IE-33]
_ = x[R_ARM64_TLS_IE-34] _ = x[R_ARM64_GOTPCREL-34]
_ = x[R_ARM64_GOTPCREL-35] _ = x[R_ARM64_GOT-35]
_ = x[R_ARM64_GOT-36] _ = x[R_ARM64_PCREL-36]
_ = x[R_ARM64_PCREL-37] _ = x[R_ARM64_LDST8-37]
_ = x[R_ARM64_LDST8-38] _ = x[R_ARM64_LDST16-38]
_ = x[R_ARM64_LDST16-39] _ = x[R_ARM64_LDST32-39]
_ = x[R_ARM64_LDST32-40] _ = x[R_ARM64_LDST64-40]
_ = x[R_ARM64_LDST64-41] _ = x[R_ARM64_LDST128-41]
_ = x[R_ARM64_LDST128-42] _ = x[R_POWER_TLS_LE-42]
_ = x[R_POWER_TLS_LE-43] _ = x[R_POWER_TLS_IE-43]
_ = x[R_POWER_TLS_IE-44] _ = x[R_POWER_TLS-44]
_ = x[R_POWER_TLS-45] _ = x[R_ADDRPOWER_DS-45]
_ = x[R_ADDRPOWER_DS-46] _ = x[R_ADDRPOWER_GOT-46]
_ = x[R_ADDRPOWER_GOT-47] _ = x[R_ADDRPOWER_PCREL-47]
_ = x[R_ADDRPOWER_PCREL-48] _ = x[R_ADDRPOWER_TOCREL-48]
_ = x[R_ADDRPOWER_TOCREL-49] _ = x[R_ADDRPOWER_TOCREL_DS-49]
_ = x[R_ADDRPOWER_TOCREL_DS-50] _ = x[R_RISCV_PCREL_ITYPE-50]
_ = x[R_RISCV_PCREL_ITYPE-51] _ = x[R_RISCV_PCREL_STYPE-51]
_ = x[R_RISCV_PCREL_STYPE-52] _ = x[R_RISCV_TLS_IE_ITYPE-52]
_ = x[R_RISCV_TLS_IE_ITYPE-53] _ = x[R_RISCV_TLS_IE_STYPE-53]
_ = x[R_RISCV_TLS_IE_STYPE-54] _ = x[R_PCRELDBL-54]
_ = x[R_PCRELDBL-55] _ = x[R_ADDRMIPSU-55]
_ = x[R_ADDRMIPSU-56] _ = x[R_ADDRMIPSTLS-56]
_ = x[R_ADDRMIPSTLS-57] _ = x[R_ADDRCUOFF-57]
_ = x[R_ADDRCUOFF-58] _ = x[R_WASMIMPORT-58]
_ = x[R_WASMIMPORT-59] _ = x[R_XCOFFREF-59]
_ = x[R_XCOFFREF-60]
} }
const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CALLRISCVR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF" const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CALLRISCVR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IE_ITYPER_RISCV_TLS_IE_STYPER_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREF"
var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 133, 140, 147, 155, 163, 171, 177, 183, 189, 199, 208, 218, 234, 245, 256, 266, 275, 288, 302, 316, 330, 346, 357, 370, 383, 397, 411, 425, 440, 454, 468, 479, 493, 508, 525, 543, 564, 583, 602, 622, 642, 652, 663, 676, 687, 699, 709} var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 120, 127, 134, 142, 150, 158, 164, 170, 176, 186, 195, 205, 221, 232, 243, 253, 262, 275, 289, 303, 317, 333, 344, 357, 370, 384, 398, 412, 427, 441, 455, 466, 480, 495, 512, 530, 551, 570, 589, 609, 629, 639, 650, 663, 674, 686, 696}
func (i RelocType) String() string { func (i RelocType) String() string {
i -= 1 i -= 1

View File

@ -165,6 +165,7 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
rs := r.Sym() rs := r.Sym()
rs = ldr.ResolveABIAlias(rs) rs = ldr.ResolveABIAlias(rs)
rt := r.Type() rt := r.Type()
weak := r.Weak()
if off < 0 || off+siz > int32(len(P)) { if off < 0 || off+siz > int32(len(P)) {
rname := "" rname := ""
if rs != 0 { if rs != 0 {
@ -211,7 +212,7 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
st.err.Errorf(s, "unhandled relocation for %s (type %d (%s) rtype %d (%s))", ldr.SymName(rs), rst, rst, rt, sym.RelocName(target.Arch, rt)) st.err.Errorf(s, "unhandled relocation for %s (type %d (%s) rtype %d (%s))", ldr.SymName(rs), rst, rst, rt, sym.RelocName(target.Arch, rt))
} }
} }
if rs != 0 && rst != sym.STLSBSS && rt != objabi.R_WEAKADDROFF && rt != objabi.R_METHODOFF && !ldr.AttrReachable(rs) { if rs != 0 && rst != sym.STLSBSS && !weak && rt != objabi.R_METHODOFF && !ldr.AttrReachable(rs) {
st.err.Errorf(s, "unreachable sym in relocation: %s", ldr.SymName(rs)) st.err.Errorf(s, "unreachable sym in relocation: %s", ldr.SymName(rs))
} }
@ -387,18 +388,18 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
break break
} }
o = ldr.SymValue(rs) + r.Add() - int64(ldr.SymSect(rs).Vaddr) o = ldr.SymValue(rs) + r.Add() - int64(ldr.SymSect(rs).Vaddr)
case objabi.R_WEAKADDROFF, objabi.R_METHODOFF: case objabi.R_METHODOFF:
if !ldr.AttrReachable(rs) { if !ldr.AttrReachable(rs) {
if rt == objabi.R_METHODOFF { // Set it to a sentinel value. The runtime knows this is not pointing to
// Set it to a sentinel value. The runtime knows this is not pointing to // anything valid.
// anything valid. o = -1
o = -1 break
break
}
continue
} }
fallthrough fallthrough
case objabi.R_ADDROFF: case objabi.R_ADDROFF:
if weak && !ldr.AttrReachable(rs) {
continue
}
// The method offset tables using this relocation expect the offset to be relative // The method offset tables using this relocation expect the offset to be relative
// to the start of the first text section, even if there are multiple. // to the start of the first text section, even if there are multiple.
if ldr.SymSect(rs).Name == ".text" { if ldr.SymSect(rs).Name == ".text" {
@ -635,7 +636,7 @@ func extreloc(ctxt *Link, ldr *loader.Loader, s loader.Sym, r loader.Reloc) (loa
return ExtrelocSimple(ldr, r), true return ExtrelocSimple(ldr, r), true
// These reloc types don't need external relocations. // These reloc types don't need external relocations.
case objabi.R_ADDROFF, objabi.R_WEAKADDROFF, objabi.R_METHODOFF, objabi.R_ADDRCUOFF, case objabi.R_ADDROFF, objabi.R_METHODOFF, objabi.R_ADDRCUOFF,
objabi.R_SIZE, objabi.R_CONST, objabi.R_GOTOFF: objabi.R_SIZE, objabi.R_CONST, objabi.R_GOTOFF:
return rr, false return rr, false
} }
@ -710,9 +711,8 @@ func windynrelocsym(ctxt *Link, rel *loader.SymbolBuilder, s loader.Sym) {
if targ == 0 { if targ == 0 {
continue continue
} }
rt := r.Type()
if !ctxt.loader.AttrReachable(targ) { if !ctxt.loader.AttrReachable(targ) {
if rt == objabi.R_WEAKADDROFF { if r.Weak() {
continue continue
} }
ctxt.Errorf(s, "dynamic relocation to unreachable symbol %s", ctxt.Errorf(s, "dynamic relocation to unreachable symbol %s",
@ -786,6 +786,10 @@ func dynrelocsym(ctxt *Link, s loader.Sym) {
if r.IsMarker() { if r.IsMarker() {
continue // skip marker relocations continue // skip marker relocations
} }
rSym := r.Sym()
if r.Weak() && !ldr.AttrReachable(rSym) {
continue
}
if ctxt.BuildMode == BuildModePIE && ctxt.LinkMode == LinkInternal { if ctxt.BuildMode == BuildModePIE && ctxt.LinkMode == LinkInternal {
// It's expected that some relocations will be done // It's expected that some relocations will be done
// later by relocsym (R_TLS_LE, R_ADDROFF), so // later by relocsym (R_TLS_LE, R_ADDROFF), so
@ -794,7 +798,6 @@ func dynrelocsym(ctxt *Link, s loader.Sym) {
continue continue
} }
rSym := r.Sym()
if rSym != 0 && ldr.SymType(rSym) == sym.SDYNIMPORT || r.Type() >= objabi.ElfRelocOffset { if rSym != 0 && ldr.SymType(rSym) == sym.SDYNIMPORT || r.Type() >= objabi.ElfRelocOffset {
if rSym != 0 && !ldr.AttrReachable(rSym) { if rSym != 0 && !ldr.AttrReachable(rSym) {
ctxt.Errorf(s, "dynamic relocation to unreachable symbol %s", ldr.SymName(rSym)) ctxt.Errorf(s, "dynamic relocation to unreachable symbol %s", ldr.SymName(rSym))

View File

@ -128,10 +128,11 @@ func (d *deadcodePass) flood() {
methods = methods[:0] methods = methods[:0]
for i := 0; i < relocs.Count(); i++ { for i := 0; i < relocs.Count(); i++ {
r := relocs.At(i) r := relocs.At(i)
if r.Weak() {
continue
}
t := r.Type() t := r.Type()
switch t { switch t {
case objabi.R_WEAKADDROFF:
continue
case objabi.R_METHODOFF: case 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")

View File

@ -53,7 +53,8 @@ type Reloc struct {
l *Loader l *Loader
} }
func (rel Reloc) Type() objabi.RelocType { return objabi.RelocType(rel.Reloc.Type()) } func (rel Reloc) Type() objabi.RelocType { return objabi.RelocType(rel.Reloc.Type()) &^ objabi.R_WEAK }
func (rel Reloc) Weak() bool { return objabi.RelocType(rel.Reloc.Type())&objabi.R_WEAK != 0 }
func (rel Reloc) SetType(t objabi.RelocType) { rel.Reloc.SetType(uint16(t)) } 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)}) }