From: Jeremy Faller Date: Tue, 5 May 2020 16:34:10 +0000 (-0400) Subject: [dev.link] cmd/link: convert ppc64 archreloc over to Loader X-Git-Tag: go1.16beta1~1378^2~145 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=fee06a6bda8e7ca5a35b13c7b5befc1d73e93c35;p=gostls13.git [dev.link] cmd/link: convert ppc64 archreloc over to Loader Change-Id: I68945a8284fb3dd9ceb5a9cd774b5b4b91e63ce0 Reviewed-on: https://go-review.googlesource.com/c/go/+/230917 Reviewed-by: Cherry Zhang Reviewed-by: Than McIntosh --- diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 7b06972c0a..c6270af42f 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -372,7 +372,7 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { } else if target.IsWindows() { // nothing to do } else if target.IsAIX() { - o = ldr.SymValue(rs) + r.Add() + o = ldr.SymValue(rs) + rr.Xadd } else { st.err.Errorf(s, "unhandled pcrel relocation to %s on %v", ldr.SymName(rs), target.HeadType) } @@ -391,8 +391,7 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { // symbol which isn't in .data. However, as .text has the // same address once loaded, this is possible. if ldr.SymSect(s).Seg == &Segdata { - panic("not implemented") - //Xcoffadddynrel(target, ldr, err, s, &r) // XXX + Xcoffadddynrel2(target, ldr, syms, s, r, ri) } } @@ -543,10 +542,7 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { needExtReloc = true rr.Xsym = rs rr.Xadd = r.Add() - - // This isn't a real relocation so it must not update - // its offset value. - continue + goto addExtReloc case objabi.R_DWARFFILEREF: // We don't renumber files in dwarf.go:writelines anymore. @@ -590,6 +586,7 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { target.Arch.ByteOrder.PutUint64(P[off:], uint64(o)) } + addExtReloc: if needExtReloc { extRelocs = append(extRelocs, rr) } diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 838f92af9e..75d6bbf05d 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -318,7 +318,7 @@ func Main(arch *sys.Arch, theArch Arch) { bench.Start("Asmb") ctxt.loader.InitOutData() thearch.Asmb(ctxt, ctxt.loader) - newreloc := ctxt.Is386() || ctxt.IsAMD64() || ctxt.IsARM() || ctxt.IsARM64() || ctxt.IsMIPS() || ctxt.IsMIPS64() || ctxt.IsRISCV64() || ctxt.IsS390X() || ctxt.IsWasm() + newreloc := ctxt.Is386() || ctxt.IsAMD64() || ctxt.IsARM() || ctxt.IsARM64() || ctxt.IsMIPS() || ctxt.IsMIPS64() || ctxt.IsRISCV64() || ctxt.IsS390X() || ctxt.IsWasm() || ctxt.IsPPC64() newasmb2 := ctxt.IsDarwin() if newreloc { bench.Start("reloc") diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go index 281747b64d..f0ddc408fe 100644 --- a/src/cmd/link/internal/ld/xcoff.go +++ b/src/cmd/link/internal/ld/xcoff.go @@ -1122,7 +1122,7 @@ func Xcoffadddynrel2(target *Target, ldr *loader.Loader, syms *ArchSyms, s loade sym2: s, roff: r.Off(), } - targ := r.Sym() + targ := ldr.ResolveABIAlias(r.Sym()) var targType sym.SymKind if targ != 0 { targType = ldr.SymType(targ) diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go index ab923c324e..22021ee8c4 100644 --- a/src/cmd/link/internal/ppc64/asm.go +++ b/src/cmd/link/internal/ppc64/asm.go @@ -416,7 +416,7 @@ func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se switch r.Type { default: return false - case objabi.R_ADDR: + case objabi.R_ADDR, objabi.R_DWARFSECREF: v = ld.XCOFF_R_POS if r.Siz == 4 { v |= 0x1F << 8 @@ -437,7 +437,6 @@ func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, se emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0) case objabi.R_XCOFFREF: emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0) - } return true @@ -533,19 +532,19 @@ func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRe } // Return the value of .TOC. for symbol s -func symtoc(syms *ld.ArchSyms, s *sym.Symbol) int64 { - v := s.Version - if s.Outer != nil { - v = s.Outer.Version +func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 { + v := ldr.SymVersion(s) + if out := ldr.OuterSym(s); out != 0 { + v = ldr.SymVersion(out) } - toc := syms.DotTOC[v] - if toc == nil { - ld.Errorf(s, "TOC-relative relocation in object without .TOC.") + toc := syms.DotTOC2[v] + if toc == 0 { + ldr.Errorf(s, "TOC-relative relocation in object without .TOC.") return 0 } - return toc.Value + return ldr.SymValue(toc) } // archreloctoc relocates a TOC relative symbol. @@ -553,36 +552,35 @@ func symtoc(syms *ld.ArchSyms, s *sym.Symbol) int64 { // default load instruction can be changed to an addi instruction and the // symbol address can be used directly. // This code is for AIX only. -func archreloctoc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) int64 { +func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc2, s loader.Sym, val int64) int64 { + rs := ldr.ResolveABIAlias(r.Sym()) if target.IsLinux() { - ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name) + ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs)) } var o1, o2 uint32 o1 = uint32(val >> 32) o2 = uint32(val) + if !strings.HasPrefix(ldr.SymName(rs), "TOC.") { + ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor") + } var t int64 useAddi := false - const prefix = "TOC." - var tarSym *sym.Symbol - if strings.HasPrefix(r.Sym.Name, prefix) { - tarSym = r.Sym.R[0].Sym - } else { - ld.Errorf(s, "archreloctoc called for a symbol without TOC anchor") - } + relocs := ldr.Relocs(rs) + tarSym := ldr.ResolveABIAlias(relocs.At2(0).Sym()) - if target.IsInternal() && tarSym != nil && tarSym.Attr.Reachable() && (tarSym.Sect.Seg == &ld.Segdata) { - t = ld.Symaddr(tarSym) + r.Add - syms.TOC.Value + if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata { + t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC2) // change ld to addi in the second instruction o2 = (o2 & 0x03FF0000) | 0xE<<26 useAddi = true } else { - t = ld.Symaddr(r.Sym) + r.Add - syms.TOC.Value + t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC2) } if t != int64(int32(t)) { - ld.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", s.Name, r.Sym, t) + ldr.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", ldr.SymName(s), rs, t) } if t&0x8000 != 0 { @@ -591,13 +589,13 @@ func archreloctoc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Sym o1 |= uint32((t >> 16) & 0xFFFF) - switch r.Type { + switch r.Type() { case objabi.R_ADDRPOWER_TOCREL_DS: if useAddi { o2 |= uint32(t) & 0xFFFF } else { if t&3 != 0 { - ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym)) + ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs)) } o2 |= uint32(t) & 0xFFFC } @@ -610,9 +608,10 @@ func archreloctoc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Sym // archrelocaddr relocates a symbol address. // This code is for AIX only. -func archrelocaddr(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) int64 { +func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc2, s loader.Sym, val int64) int64 { + rs := ldr.ResolveABIAlias(r.Sym()) if target.IsAIX() { - ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name) + ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs)) } var o1, o2 uint32 if target.IsBigEndian() { @@ -630,22 +629,22 @@ func archrelocaddr(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Sy // instruction (it is an error in this case if the low 2 bits of the address // are non-zero). - t := ld.Symaddr(r.Sym) + r.Add + t := ldr.SymAddr(rs) + r.Add() if t < 0 || t >= 1<<31 { - ld.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", s.Name, ld.Symaddr(r.Sym)) + ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs)) } if t&0x8000 != 0 { t += 0x10000 } - switch r.Type { + switch r.Type() { case objabi.R_ADDRPOWER: o1 |= (uint32(t) >> 16) & 0xffff o2 |= uint32(t) & 0xffff case objabi.R_ADDRPOWER_DS: o1 |= (uint32(t) >> 16) & 0xffff if t&3 != 0 { - ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym)) + ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs)) } o2 |= uint32(t) & 0xfffc default: @@ -795,113 +794,114 @@ func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, ta tramp.SetData(P) } -func archreloc(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) { +func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc2, rr *loader.ExtReloc, s loader.Sym, val int64) (relocatedOffset int64, needExtReloc bool, ok bool) { + needExternal := false + rs := ldr.ResolveABIAlias(r.Sym()) if target.IsExternal() { // On AIX, relocations (except TLS ones) must be also done to the // value with the current addresses. - switch r.Type { + switch r.Type() { default: if target.IsAIX() { - return val, false + return val, needExternal, false } case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE: - r.Done = false // check Outer is nil, Type is TLSBSS? - r.Xadd = r.Add - r.Xsym = r.Sym - return val, true + needExternal = true + rr.Xadd = r.Add() + rr.Xsym = rs + return val, needExternal, true case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS, objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS, objabi.R_ADDRPOWER_GOT, objabi.R_ADDRPOWER_PCREL: - r.Done = false + needExternal = true // set up addend for eventual relocation via outer symbol. - rs := ld.ApplyOuterToXAdd(r) - if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil { - ld.Errorf(s, "missing section for %s", rs.Name) + rs, off := ld.FoldSubSymbolOffset(ldr, rs) + rr.Xadd = r.Add() + off + rst := ldr.SymType(rs) + if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && rst != sym.SUNDEFEXT && ldr.SymSect(rs) == nil { + ldr.Errorf(s, "missing section for %s", ldr.SymName(rs)) } - r.Xsym = rs + rr.Xsym = rs if !target.IsAIX() { - return val, true + return val, needExternal, true } case objabi.R_CALLPOWER: - r.Done = false - r.Xsym = r.Sym - r.Xadd = r.Add + needExternal = true + rr.Xsym = rs + rr.Xadd = r.Add() if !target.IsAIX() { - return val, true + return val, needExternal, true } } } - switch r.Type { - case objabi.R_CONST: - return r.Add, true - case objabi.R_GOTOFF: - return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(syms.GOT), true + switch r.Type() { case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS: - return archreloctoc(target, syms, r, s, val), true + return archreloctoc(ldr, target, syms, r, s, val), needExternal, true case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS: - return archrelocaddr(target, syms, r, s, val), true + return archrelocaddr(ldr, target, syms, r, s, val), needExternal, true case objabi.R_CALLPOWER: // Bits 6 through 29 = (S + A - P) >> 2 - t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off)) + t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) if t&3 != 0 { - ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t) + ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t) } // If branch offset is too far then create a trampoline. if int64(int32(t<<6)>>6) != t { - ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t) + ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t) } - return val | int64(uint32(t)&^0xfc000003), true + return val | int64(uint32(t)&^0xfc000003), needExternal, true case objabi.R_POWER_TOC: // S + A - .TOC. - return ld.Symaddr(r.Sym) + r.Add - symtoc(syms, s), true + return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), needExternal, true case objabi.R_POWER_TLS_LE: // The thread pointer points 0x7000 bytes after the start of the // thread local storage area as documented in section "3.7.2 TLS // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI // Specification". - v := r.Sym.Value - 0x7000 + v := ldr.SymValue(rs) - 0x7000 if target.IsAIX() { // On AIX, the thread pointer points 0x7800 bytes after // the TLS. v -= 0x800 } if int64(int16(v)) != v { - ld.Errorf(s, "TLS offset out of range %d", v) + ldr.Errorf(s, "TLS offset out of range %d", v) } - return (val &^ 0xffff) | (v & 0xffff), true + return (val &^ 0xffff) | (v & 0xffff), needExternal, true } - return val, false + return val, needExternal, false } -func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym.Symbol, t int64) int64 { - switch r.Variant & sym.RV_TYPE_MASK { +func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc2, rv sym.RelocVariant, s loader.Sym, t int64) (relocatedOffset int64) { + rs := ldr.ResolveABIAlias(r.Sym()) + switch rv & sym.RV_TYPE_MASK { default: - ld.Errorf(s, "unexpected relocation variant %d", r.Variant) + ldr.Errorf(s, "unexpected relocation variant %d", rv) fallthrough case sym.RV_NONE: return t case sym.RV_POWER_LO: - if r.Variant&sym.RV_CHECK_OVERFLOW != 0 { + if rv&sym.RV_CHECK_OVERFLOW != 0 { // Whether to check for signed or unsigned // overflow depends on the instruction var o1 uint32 if target.IsBigEndian() { - o1 = binary.BigEndian.Uint32(s.P[r.Off-2:]) + o1 = binary.BigEndian.Uint32(ldr.Data(s)[r.Off()-2:]) } else { - o1 = binary.LittleEndian.Uint32(s.P[r.Off:]) + o1 = binary.LittleEndian.Uint32(ldr.Data(s)[r.Off():]) } switch o1 >> 26 { case 24, // ori @@ -928,14 +928,14 @@ func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym case sym.RV_POWER_HI: t >>= 16 - if r.Variant&sym.RV_CHECK_OVERFLOW != 0 { + if rv&sym.RV_CHECK_OVERFLOW != 0 { // Whether to check for signed or unsigned // overflow depends on the instruction var o1 uint32 if target.IsBigEndian() { - o1 = binary.BigEndian.Uint32(s.P[r.Off-2:]) + o1 = binary.BigEndian.Uint32(ldr.Data(s)[r.Off()-2:]) } else { - o1 = binary.LittleEndian.Uint32(s.P[r.Off:]) + o1 = binary.LittleEndian.Uint32(ldr.Data(s)[r.Off():]) } switch o1 >> 26 { case 25, // oris @@ -957,21 +957,21 @@ func archrelocvariant(target *ld.Target, syms *ld.ArchSyms, r *sym.Reloc, s *sym case sym.RV_POWER_DS: var o1 uint32 if target.IsBigEndian() { - o1 = uint32(binary.BigEndian.Uint16(s.P[r.Off:])) + o1 = uint32(binary.BigEndian.Uint16(ldr.Data(s)[r.Off():])) } else { - o1 = uint32(binary.LittleEndian.Uint16(s.P[r.Off:])) + o1 = uint32(binary.LittleEndian.Uint16(ldr.Data(s)[r.Off():])) } if t&3 != 0 { - ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t) + ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t) } - if (r.Variant&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t { + if (rv&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t { goto overflow } return int64(o1)&0x3 | int64(int16(t)) } overflow: - ld.Errorf(s, "relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t) + ldr.Errorf(s, "relocation for %s+%d is too big: %d", ldr.SymName(rs), r.Off(), t) return t } diff --git a/src/cmd/link/internal/ppc64/obj.go b/src/cmd/link/internal/ppc64/obj.go index 67002bc719..16882d4d45 100644 --- a/src/cmd/link/internal/ppc64/obj.go +++ b/src/cmd/link/internal/ppc64/obj.go @@ -49,18 +49,18 @@ func Init() (*sys.Arch, ld.Arch) { Dwarfregsp: dwarfRegSP, Dwarfreglr: dwarfRegLR, - Adddynrel2: adddynrel2, - Archinit: archinit, - Archreloc: archreloc, - Archrelocvariant: archrelocvariant, - Asmb: asmb, - Asmb2: asmb2, - Elfreloc1: elfreloc1, - Elfsetupplt: elfsetupplt, - Gentext2: gentext2, - Trampoline: trampoline, - Machoreloc1: machoreloc1, - Xcoffreloc1: xcoffreloc1, + Adddynrel2: adddynrel2, + Archinit: archinit, + Archreloc2: archreloc, + Archrelocvariant2: archrelocvariant, + Asmb: asmb, + Asmb2: asmb2, + Elfreloc1: elfreloc1, + Elfsetupplt: elfsetupplt, + Gentext2: gentext2, + Trampoline: trampoline, + Machoreloc1: machoreloc1, + Xcoffreloc1: xcoffreloc1, // TODO(austin): ABI v1 uses /usr/lib/ld.so.1, Linuxdynld: "/lib64/ld64.so.1",