diff --git a/src/cmd/internal/objabi/reloctype.go b/src/cmd/internal/objabi/reloctype.go index f619e017d8..94d5469d9c 100644 --- a/src/cmd/internal/objabi/reloctype.go +++ b/src/cmd/internal/objabi/reloctype.go @@ -30,7 +30,7 @@ package objabi -type RelocType int32 +type RelocType int16 //go:generate stringer -type=RelocType const ( diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 3b551db853..8e35f5c9dc 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -189,13 +189,19 @@ func relocsym(ctxt *Link, s *sym.Symbol) { Errorf(s, "unreachable sym in relocation: %s", r.Sym.Name) } + if ctxt.LinkMode == LinkExternal { + r.InitExt() + } + // TODO(mundaym): remove this special case - see issue 14218. if ctxt.Arch.Family == sys.S390X { switch r.Type { case objabi.R_PCRELDBL: + r.InitExt() r.Type = objabi.R_PCREL r.Variant = sym.RV_390_DBL case objabi.R_CALL: + r.InitExt() r.Variant = sym.RV_390_DBL } } @@ -499,8 +505,11 @@ func relocsym(ctxt *Link, s *sym.Symbol) { o = r.Add } - if r.Variant != sym.RV_NONE { - o = thearch.Archrelocvariant(ctxt, r, s, o) + if ctxt.Arch.Family == sys.PPC64 || ctxt.Arch.Family == sys.S390X { + r.InitExt() + if r.Variant != sym.RV_NONE { + o = thearch.Archrelocvariant(ctxt, r, s, o) + } } if false { diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index 365a45ec13..c315b4bfc2 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -272,6 +272,7 @@ func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { } func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { targ := r.Sym + r.InitExt() switch r.Type { default: diff --git a/src/cmd/link/internal/s390x/asm.go b/src/cmd/link/internal/s390x/asm.go index 8540377400..040c573705 100644 --- a/src/cmd/link/internal/s390x/asm.go +++ b/src/cmd/link/internal/s390x/asm.go @@ -104,6 +104,7 @@ func gentext(ctxt *ld.Link) { func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { targ := r.Sym + r.InitExt() switch r.Type { default: diff --git a/src/cmd/link/internal/sym/reloc.go b/src/cmd/link/internal/sym/reloc.go index 9c862f109d..4809db8c80 100644 --- a/src/cmd/link/internal/sym/reloc.go +++ b/src/cmd/link/internal/sym/reloc.go @@ -22,15 +22,27 @@ import ( // // Some relocations are created by cmd/link. type Reloc struct { - Off int32 // offset to rewrite - Siz uint8 // number of bytes to rewrite, 1, 2, or 4 - Done bool // set to true when relocation is complete - Variant RelocVariant // variation on Type - Type objabi.RelocType // the relocation type - Add int64 // addend - Xadd int64 // addend passed to external linker - Sym *Symbol // symbol the relocation addresses - Xsym *Symbol // symbol passed to external linker + Off int32 // offset to rewrite + Siz uint8 // number of bytes to rewrite, 1, 2, or 4 + Done bool // set to true when relocation is complete + Type objabi.RelocType // the relocation type + Add int64 // addend + Sym *Symbol // symbol the relocation addresses + *relocExt // extra fields (see below), may be nil, call InitExt before use +} + +// relocExt contains extra fields in Reloc that are used only in +// certain cases. +type relocExt struct { + Xadd int64 // addend passed to external linker + Xsym *Symbol // symbol passed to external linker + Variant RelocVariant // variation on Type, currently used only on PPC64 and S390X +} + +func (r *Reloc) InitExt() { + if r.relocExt == nil { + r.relocExt = new(relocExt) + } } // RelocVariant is a linker-internal variation on a relocation. diff --git a/src/cmd/link/internal/sym/symbol.go b/src/cmd/link/internal/sym/symbol.go index 88a28f5b99..d115a3326f 100644 --- a/src/cmd/link/internal/sym/symbol.go +++ b/src/cmd/link/internal/sym/symbol.go @@ -211,6 +211,9 @@ func (s *Symbol) AddPCRelPlus(arch *sys.Arch, t *Symbol, add int64) int64 { r.Add = add r.Type = objabi.R_PCREL r.Siz = 4 + if arch.Family == sys.S390X || arch.Family == sys.PPC64 { + r.InitExt() + } if arch.Family == sys.S390X { r.Variant = RV_390_DBL }