github.com/bir3/gocompiler@v0.9.2202/src/cmd/link/internal/ppc64/asm.go (about) 1 // Inferno utils/5l/asm.c 2 // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/asm.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 package ppc64 32 33 import ( 34 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 35 "github.com/bir3/gocompiler/src/cmd/internal/sys" 36 "github.com/bir3/gocompiler/src/cmd/link/internal/ld" 37 "github.com/bir3/gocompiler/src/cmd/link/internal/loader" 38 "github.com/bir3/gocompiler/src/cmd/link/internal/sym" 39 "debug/elf" 40 "encoding/binary" 41 "fmt" 42 "github.com/bir3/gocompiler/src/internal/buildcfg" 43 "log" 44 "strconv" 45 "strings" 46 ) 47 48 // The build configuration supports PC-relative instructions and relocations (limited to tested targets). 49 var hasPCrel = buildcfg.GOPPC64 >= 10 && buildcfg.GOOS == "linux" 50 51 const ( 52 // For genstub, the type of stub required by the caller. 53 STUB_TOC = iota 54 STUB_PCREL 55 ) 56 57 var stubStrs = []string{ 58 STUB_TOC: "_callstub_toc", 59 STUB_PCREL: "_callstub_pcrel", 60 } 61 62 const ( 63 OP_TOCRESTORE = 0xe8410018 // ld r2,24(r1) 64 OP_TOCSAVE = 0xf8410018 // std r2,24(r1) 65 OP_NOP = 0x60000000 // nop 66 OP_BL = 0x48000001 // bl 0 67 OP_BCTR = 0x4e800420 // bctr 68 OP_BCTRL = 0x4e800421 // bctrl 69 OP_BCL = 0x40000001 // bcl 70 OP_ADDI = 0x38000000 // addi 71 OP_ADDIS = 0x3c000000 // addis 72 OP_LD = 0xe8000000 // ld 73 OP_PLA_PFX = 0x06100000 // pla (prefix instruction word) 74 OP_PLA_SFX = 0x38000000 // pla (suffix instruction word) 75 OP_PLD_PFX_PCREL = 0x04100000 // pld (prefix instruction word, R=1) 76 OP_PLD_SFX = 0xe4000000 // pld (suffix instruction word) 77 OP_MFLR = 0x7c0802a6 // mflr 78 OP_MTLR = 0x7c0803a6 // mtlr 79 OP_MFCTR = 0x7c0902a6 // mfctr 80 OP_MTCTR = 0x7c0903a6 // mtctr 81 82 OP_ADDIS_R12_R2 = OP_ADDIS | 12<<21 | 2<<16 // addis r12,r2,0 83 OP_ADDIS_R12_R12 = OP_ADDIS | 12<<21 | 12<<16 // addis r12,r12,0 84 OP_ADDI_R12_R12 = OP_ADDI | 12<<21 | 12<<16 // addi r12,r12,0 85 OP_PLD_SFX_R12 = OP_PLD_SFX | 12<<21 // pld r12,0 (suffix instruction word) 86 OP_PLA_SFX_R12 = OP_PLA_SFX | 12<<21 // pla r12,0 (suffix instruction word) 87 OP_LIS_R12 = OP_ADDIS | 12<<21 // lis r12,0 88 OP_LD_R12_R12 = OP_LD | 12<<21 | 12<<16 // ld r12,0(r12) 89 OP_MTCTR_R12 = OP_MTCTR | 12<<21 // mtctr r12 90 OP_MFLR_R12 = OP_MFLR | 12<<21 // mflr r12 91 OP_MFLR_R0 = OP_MFLR | 0<<21 // mflr r0 92 OP_MTLR_R0 = OP_MTLR | 0<<21 // mtlr r0 93 94 // This is a special, preferred form of bcl to obtain the next 95 // instruction address (NIA, aka PC+4) in LR. 96 OP_BCL_NIA = OP_BCL | 20<<21 | 31<<16 | 1<<2 // bcl 20,31,$+4 97 98 // Masks to match opcodes 99 MASK_PLD_PFX = 0xfff70000 100 MASK_PLD_SFX = 0xfc1f0000 // Also checks RA = 0 if check value is OP_PLD_SFX. 101 MASK_PLD_RT = 0x03e00000 // Extract RT from the pld suffix. 102 MASK_OP_LD = 0xfc000003 103 MASK_OP_ADDIS = 0xfc000000 104 ) 105 106 // Generate a stub to call between TOC and NOTOC functions. See genpltstub for more details about calling stubs. 107 // This is almost identical to genpltstub, except the location of the target symbol is known at link time. 108 func genstub(ctxt *ld.Link, ldr *loader.Loader, r loader.Reloc, ri int, s loader.Sym, stubType int) (ssym loader.Sym, firstUse bool) { 109 addendStr := "" 110 if r.Add() != 0 { 111 addendStr = fmt.Sprintf("%+d", r.Add()) 112 } 113 114 stubName := fmt.Sprintf("%s%s.%s", stubStrs[stubType], addendStr, ldr.SymName(r.Sym())) 115 stub := ldr.CreateSymForUpdate(stubName, 0) 116 firstUse = stub.Size() == 0 117 if firstUse { 118 switch stubType { 119 // A call from a function using a TOC pointer. 120 case STUB_TOC: 121 stub.AddUint32(ctxt.Arch, OP_TOCSAVE) // std r2,24(r1) 122 stub.AddSymRef(ctxt.Arch, r.Sym(), r.Add(), objabi.R_ADDRPOWER_TOCREL_DS, 8) 123 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_ADDIS_R12_R2) // addis r12,r2,targ@toc@ha 124 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_ADDI_R12_R12) // addi r12,targ@toc@l(r12) 125 126 // A call from PC relative function. 127 case STUB_PCREL: 128 if buildcfg.GOPPC64 >= 10 { 129 // Set up address of targ in r12, PCrel 130 stub.AddSymRef(ctxt.Arch, r.Sym(), r.Add(), objabi.R_ADDRPOWER_PCREL34, 8) 131 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_PLA_PFX) 132 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_PLA_SFX_R12) // pla r12, r 133 } else { 134 // The target may not be a P10. Generate a P8 compatible stub. 135 stub.AddUint32(ctxt.Arch, OP_MFLR_R0) // mflr r0 136 stub.AddUint32(ctxt.Arch, OP_BCL_NIA) // bcl 20,31,1f 137 stub.AddUint32(ctxt.Arch, OP_MFLR_R12) // 1: mflr r12 (r12 is the address of this instruction) 138 stub.AddUint32(ctxt.Arch, OP_MTLR_R0) // mtlr r0 139 stub.AddSymRef(ctxt.Arch, r.Sym(), r.Add()+8, objabi.R_ADDRPOWER_PCREL, 8) 140 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_ADDIS_R12_R12) // addis r12,(r - 1b) + 8 141 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_ADDI_R12_R12) // addi r12,(r - 1b) + 12 142 } 143 } 144 // Jump to the loaded pointer 145 stub.AddUint32(ctxt.Arch, OP_MTCTR_R12) // mtctr r12 146 stub.AddUint32(ctxt.Arch, OP_BCTR) // bctr 147 stub.SetType(sym.STEXT) 148 } 149 150 // Update the relocation to use the call stub 151 su := ldr.MakeSymbolUpdater(s) 152 su.SetRelocSym(ri, stub.Sym()) 153 154 // Rewrite the TOC restore slot (a nop) if the caller uses a TOC pointer. 155 switch stubType { 156 case STUB_TOC: 157 rewritetoinsn(&ctxt.Target, ldr, su, int64(r.Off()+4), 0xFFFFFFFF, OP_NOP, OP_TOCRESTORE) 158 } 159 160 return stub.Sym(), firstUse 161 } 162 163 func genpltstub(ctxt *ld.Link, ldr *loader.Loader, r loader.Reloc, ri int, s loader.Sym) (sym loader.Sym, firstUse bool) { 164 // The ppc64 ABI PLT has similar concepts to other 165 // architectures, but is laid out quite differently. When we 166 // see a relocation to a dynamic symbol (indicating that the 167 // call needs to go through the PLT), we generate up to three 168 // stubs and reserve a PLT slot. 169 // 170 // 1) The call site is a "bl x" where genpltstub rewrites it to 171 // "bl x_stub". Depending on the properties of the caller 172 // (see ELFv2 1.5 4.2.5.3), a nop may be expected immediately 173 // after the bl. This nop is rewritten to ld r2,24(r1) to 174 // restore the toc pointer saved by x_stub. 175 // 176 // 2) We reserve space for a pointer in the .plt section (once 177 // per referenced dynamic function). .plt is a data 178 // section filled solely by the dynamic linker (more like 179 // .plt.got on other architectures). Initially, the 180 // dynamic linker will fill each slot with a pointer to the 181 // corresponding x@plt entry point. 182 // 183 // 3) We generate a "call stub" x_stub based on the properties 184 // of the caller. 185 // 186 // 4) We generate the "symbol resolver stub" x@plt (once per 187 // dynamic function). This is solely a branch to the glink 188 // resolver stub. 189 // 190 // 5) We generate the glink resolver stub (only once). This 191 // computes which symbol resolver stub we came through and 192 // invokes the dynamic resolver via a pointer provided by 193 // the dynamic linker. This will patch up the .plt slot to 194 // point directly at the function so future calls go 195 // straight from the call stub to the real function, and 196 // then call the function. 197 198 // NOTE: It's possible we could make ppc64 closer to other 199 // architectures: ppc64's .plt is like .plt.got on other 200 // platforms and ppc64's .glink is like .plt on other 201 // platforms. 202 203 // Find all relocations that reference dynamic imports. 204 // Reserve PLT entries for these symbols and generate call 205 // stubs. The call stubs need to live in .text, which is why we 206 // need to do this pass this early. 207 208 // Reserve PLT entry and generate symbol resolver 209 addpltsym(ctxt, ldr, r.Sym()) 210 211 // The stub types are described in gencallstub. 212 stubType := 0 213 stubTypeStr := "" 214 215 // For now, the choice of call stub type is determined by whether 216 // the caller maintains a TOC pointer in R2. A TOC pointer implies 217 // we can always generate a position independent stub. 218 // 219 // For dynamic calls made from an external object, a caller maintains 220 // a TOC pointer only when an R_PPC64_REL24 relocation is used. 221 // An R_PPC64_REL24_NOTOC relocation does not use or maintain 222 // a TOC pointer, and almost always implies a Power10 target. 223 // 224 // For dynamic calls made from a Go caller, a TOC relative stub is 225 // always needed when a TOC pointer is maintained (specifically, if 226 // the Go caller is PIC, and cannot use PCrel instructions). 227 if (r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_PPC64_REL24)) || (!ldr.AttrExternal(s) && ldr.AttrShared(s) && !hasPCrel) { 228 stubTypeStr = "_tocrel" 229 stubType = 1 230 } else { 231 stubTypeStr = "_notoc" 232 stubType = 3 233 } 234 n := fmt.Sprintf("_pltstub%s.%s", stubTypeStr, ldr.SymName(r.Sym())) 235 236 // When internal linking, all text symbols share the same toc pointer. 237 stub := ldr.CreateSymForUpdate(n, 0) 238 firstUse = stub.Size() == 0 239 if firstUse { 240 gencallstub(ctxt, ldr, stubType, stub, r.Sym()) 241 } 242 243 // Update the relocation to use the call stub 244 su := ldr.MakeSymbolUpdater(s) 245 su.SetRelocSym(ri, stub.Sym()) 246 247 // A type 1 call must restore the toc pointer after the call. 248 if stubType == 1 { 249 su.MakeWritable() 250 p := su.Data() 251 252 // Check for a toc pointer restore slot (a nop), and rewrite to restore the toc pointer. 253 var nop uint32 254 if len(p) >= int(r.Off()+8) { 255 nop = ctxt.Arch.ByteOrder.Uint32(p[r.Off()+4:]) 256 } 257 if nop != OP_NOP { 258 ldr.Errorf(s, "Symbol %s is missing toc restoration slot at offset %d", ldr.SymName(s), r.Off()+4) 259 } 260 ctxt.Arch.ByteOrder.PutUint32(p[r.Off()+4:], OP_TOCRESTORE) 261 } 262 263 return stub.Sym(), firstUse 264 } 265 266 // Scan relocs and generate PLT stubs and generate/fixup ABI defined functions created by the linker. 267 func genstubs(ctxt *ld.Link, ldr *loader.Loader) { 268 var stubs []loader.Sym 269 var abifuncs []loader.Sym 270 for _, s := range ctxt.Textp { 271 relocs := ldr.Relocs(s) 272 for i := 0; i < relocs.Count(); i++ { 273 switch r := relocs.At(i); r.Type() { 274 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24), objabi.R_CALLPOWER: 275 switch ldr.SymType(r.Sym()) { 276 case sym.SDYNIMPORT: 277 // This call goes through the PLT, generate and call through a PLT stub. 278 if sym, firstUse := genpltstub(ctxt, ldr, r, i, s); firstUse { 279 stubs = append(stubs, sym) 280 } 281 282 case sym.SXREF: 283 // Is this an ELF ABI defined function which is (in practice) 284 // generated by the linker to save/restore callee save registers? 285 // These are defined similarly for both PPC64 ELF and ELFv2. 286 targName := ldr.SymName(r.Sym()) 287 if strings.HasPrefix(targName, "_save") || strings.HasPrefix(targName, "_rest") { 288 if sym, firstUse := rewriteABIFuncReloc(ctxt, ldr, targName, r); firstUse { 289 abifuncs = append(abifuncs, sym) 290 } 291 } 292 case sym.STEXT: 293 targ := r.Sym() 294 if (ldr.AttrExternal(targ) && ldr.SymLocalentry(targ) != 1) || !ldr.AttrExternal(targ) { 295 // All local symbols share the same TOC pointer. This caller has a valid TOC 296 // pointer in R2. Calls into a Go symbol preserve R2. No call stub is needed. 297 } else { 298 // This caller has a TOC pointer. The callee might clobber it. R2 needs to be saved 299 // and restored. 300 if sym, firstUse := genstub(ctxt, ldr, r, i, s, STUB_TOC); firstUse { 301 stubs = append(stubs, sym) 302 } 303 } 304 } 305 306 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24_P9NOTOC): 307 // This can be treated identically to R_PPC64_REL24_NOTOC, as stubs are determined by 308 // GOPPC64 and -buildmode. 309 fallthrough 310 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24_NOTOC): 311 switch ldr.SymType(r.Sym()) { 312 case sym.SDYNIMPORT: 313 // This call goes through the PLT, generate and call through a PLT stub. 314 if sym, firstUse := genpltstub(ctxt, ldr, r, i, s); firstUse { 315 stubs = append(stubs, sym) 316 } 317 318 case sym.SXREF: 319 // TODO: This is not supported yet. 320 ldr.Errorf(s, "Unsupported NOTOC external reference call into %s", ldr.SymName(r.Sym())) 321 322 case sym.STEXT: 323 targ := r.Sym() 324 if (ldr.AttrExternal(targ) && ldr.SymLocalentry(targ) <= 1) || (!ldr.AttrExternal(targ) && (!ldr.AttrShared(targ) || hasPCrel)) { 325 // This is NOTOC to NOTOC call (st_other is 0 or 1). No call stub is needed. 326 } else { 327 // This is a NOTOC to TOC function. Generate a calling stub. 328 if sym, firstUse := genstub(ctxt, ldr, r, i, s, STUB_PCREL); firstUse { 329 stubs = append(stubs, sym) 330 } 331 } 332 } 333 334 // Handle objects compiled with -fno-plt. Rewrite local calls to avoid indirect calling. 335 // These are 0 sized relocs. They mark the mtctr r12, or bctrl + ld r2,24(r1). 336 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PLTSEQ): 337 if ldr.SymType(r.Sym()) == sym.STEXT { 338 // This should be an mtctr instruction. Turn it into a nop. 339 su := ldr.MakeSymbolUpdater(s) 340 const MASK_OP_MTCTR = 63<<26 | 0x3FF<<11 | 0x1FF<<1 341 rewritetonop(&ctxt.Target, ldr, su, int64(r.Off()), MASK_OP_MTCTR, OP_MTCTR) 342 } 343 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PLTCALL): 344 if ldr.SymType(r.Sym()) == sym.STEXT { 345 // This relocation should point to a bctrl followed by a ld r2, 24(41) 346 // Convert the bctrl into a bl. 347 su := ldr.MakeSymbolUpdater(s) 348 rewritetoinsn(&ctxt.Target, ldr, su, int64(r.Off()), 0xFFFFFFFF, OP_BCTRL, OP_BL) 349 350 // Turn this reloc into an R_CALLPOWER, and convert the TOC restore into a nop. 351 su.SetRelocType(i, objabi.R_CALLPOWER) 352 localEoffset := int64(ldr.SymLocalentry(r.Sym())) 353 if localEoffset == 1 { 354 ldr.Errorf(s, "Unsupported NOTOC call to %s", ldr.SymName(r.Sym())) 355 } 356 su.SetRelocAdd(i, r.Add()+localEoffset) 357 r.SetSiz(4) 358 rewritetonop(&ctxt.Target, ldr, su, int64(r.Off()+4), 0xFFFFFFFF, OP_TOCRESTORE) 359 } 360 } 361 } 362 } 363 364 // Append any usage of the go versions of ELF save/restore 365 // functions to the end of the callstub list to minimize 366 // chances a trampoline might be needed. 367 stubs = append(stubs, abifuncs...) 368 369 // Put stubs at the beginning (instead of the end). 370 // So when resolving the relocations to calls to the stubs, 371 // the addresses are known and trampolines can be inserted 372 // when necessary. 373 ctxt.Textp = append(stubs, ctxt.Textp...) 374 } 375 376 func genaddmoduledata(ctxt *ld.Link, ldr *loader.Loader) { 377 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt) 378 if initfunc == nil { 379 return 380 } 381 382 o := func(op uint32) { 383 initfunc.AddUint32(ctxt.Arch, op) 384 } 385 386 // Write a function to load this module's local.moduledata. This is shared code. 387 // 388 // package link 389 // void addmoduledata() { 390 // runtime.addmoduledata(local.moduledata) 391 // } 392 393 if !hasPCrel { 394 // Regenerate TOC from R12 (the address of this function). 395 sz := initfunc.AddSymRef(ctxt.Arch, ctxt.DotTOC[0], 0, objabi.R_ADDRPOWER_PCREL, 8) 396 initfunc.SetUint32(ctxt.Arch, sz-8, 0x3c4c0000) // addis r2, r12, .TOC.-func@ha 397 initfunc.SetUint32(ctxt.Arch, sz-4, 0x38420000) // addi r2, r2, .TOC.-func@l 398 } 399 400 // This is Go ABI. Stack a frame and save LR. 401 o(OP_MFLR_R0) // mflr r0 402 o(0xf801ffe1) // stdu r0, -32(r1) 403 404 // Get the moduledata pointer from GOT and put into R3. 405 var tgt loader.Sym 406 if s := ldr.Lookup("local.moduledata", 0); s != 0 { 407 tgt = s 408 } else if s := ldr.Lookup("local.pluginmoduledata", 0); s != 0 { 409 tgt = s 410 } else { 411 tgt = ldr.LookupOrCreateSym("runtime.firstmoduledata", 0) 412 } 413 414 if !hasPCrel { 415 sz := initfunc.AddSymRef(ctxt.Arch, tgt, 0, objabi.R_ADDRPOWER_GOT, 8) 416 initfunc.SetUint32(ctxt.Arch, sz-8, 0x3c620000) // addis r3, r2, local.moduledata@got@ha 417 initfunc.SetUint32(ctxt.Arch, sz-4, 0xe8630000) // ld r3, local.moduledata@got@l(r3) 418 } else { 419 sz := initfunc.AddSymRef(ctxt.Arch, tgt, 0, objabi.R_ADDRPOWER_GOT_PCREL34, 8) 420 // Note, this is prefixed instruction. It must not cross a 64B boundary. 421 // It is doubleworld aligned here, so it will never cross (this function is 16B aligned, minimum). 422 initfunc.SetUint32(ctxt.Arch, sz-8, OP_PLD_PFX_PCREL) 423 initfunc.SetUint32(ctxt.Arch, sz-4, OP_PLD_SFX|(3<<21)) // pld r3, local.moduledata@got@pcrel 424 } 425 426 // Call runtime.addmoduledata 427 sz := initfunc.AddSymRef(ctxt.Arch, addmoduledata, 0, objabi.R_CALLPOWER, 4) 428 initfunc.SetUint32(ctxt.Arch, sz-4, OP_BL) // bl runtime.addmoduledata 429 o(OP_NOP) // nop (for TOC restore) 430 431 // Pop stack frame and return. 432 o(0xe8010000) // ld r0, 0(r1) 433 o(OP_MTLR_R0) // mtlr r0 434 o(0x38210020) // addi r1,r1,32 435 o(0x4e800020) // blr 436 } 437 438 // Rewrite ELF (v1 or v2) calls to _savegpr0_n, _savegpr1_n, _savefpr_n, _restfpr_n, _savevr_m, or 439 // _restvr_m (14<=n<=31, 20<=m<=31). Redirect them to runtime.elf_restgpr0+(n-14)*4, 440 // runtime.elf_restvr+(m-20)*8, and similar. 441 // 442 // These functions are defined in the ELFv2 ABI (generated when using gcc -Os option) to save and 443 // restore callee-saved registers (as defined in the PPC64 ELF ABIs) from registers n or m to 31 of 444 // the named type. R12 and R0 are sometimes used in exceptional ways described in the ABI. 445 // 446 // Final note, this is only needed when linking internally. The external linker will generate these 447 // functions if they are used. 448 func rewriteABIFuncReloc(ctxt *ld.Link, ldr *loader.Loader, tname string, r loader.Reloc) (sym loader.Sym, firstUse bool) { 449 s := strings.Split(tname, "_") 450 // A valid call will split like {"", "savegpr0", "20"} 451 if len(s) != 3 { 452 return 0, false // Not an abi func. 453 } 454 minReg := 14 // _savegpr0_{n}, _savegpr1_{n}, _savefpr_{n}, 14 <= n <= 31 455 offMul := 4 // 1 instruction per register op. 456 switch s[1] { 457 case "savegpr0", "savegpr1", "savefpr": 458 case "restgpr0", "restgpr1", "restfpr": 459 case "savevr", "restvr": 460 minReg = 20 // _savevr_{n} or _restvr_{n}, 20 <= n <= 31 461 offMul = 8 // 2 instructions per register op. 462 default: 463 return 0, false // Not an abi func 464 } 465 n, e := strconv.Atoi(s[2]) 466 if e != nil || n < minReg || n > 31 || r.Add() != 0 { 467 return 0, false // Invalid register number, or non-zero addend. Not an abi func. 468 } 469 470 // tname is a valid relocation to an ABI defined register save/restore function. Re-relocate 471 // them to a go version of these functions in runtime/asm_ppc64x.s 472 ts := ldr.LookupOrCreateSym("runtime.elf_"+s[1], 0) 473 r.SetSym(ts) 474 r.SetAdd(int64((n - minReg) * offMul)) 475 firstUse = !ldr.AttrReachable(ts) 476 if firstUse { 477 ldr.SetAttrReachable(ts, true) 478 // This function only becomes reachable now. It has been dropped from 479 // the text section (it was unreachable until now), it needs included. 480 // 481 // Similarly, TOC regeneration should not happen for these functions, 482 // remove it from this save/restore function. 483 if ldr.AttrShared(ts) { 484 sb := ldr.MakeSymbolUpdater(ts) 485 sb.SetData(sb.Data()[8:]) 486 sb.SetSize(sb.Size() - 8) 487 relocs := sb.Relocs() 488 // Only one PCREL reloc to .TOC. should be present. 489 if relocs.Count() != 1 { 490 log.Fatalf("Unexpected number of relocs in %s\n", ldr.SymName(ts)) 491 } 492 sb.ResetRelocs() 493 494 } 495 } 496 return ts, firstUse 497 } 498 499 func gentext(ctxt *ld.Link, ldr *loader.Loader) { 500 if ctxt.DynlinkingGo() { 501 genaddmoduledata(ctxt, ldr) 502 } 503 504 if ctxt.LinkMode == ld.LinkInternal { 505 genstubs(ctxt, ldr) 506 } 507 } 508 509 // Create a calling stub. The stubType maps directly to the properties listed in the ELFv2 1.5 510 // section 4.2.5.3. 511 // 512 // There are 3 cases today (as paraphrased from the ELFv2 document): 513 // 514 // 1. R2 holds the TOC pointer on entry. The call stub must save R2 into the ELFv2 TOC stack save slot. 515 // 516 // 2. R2 holds the TOC pointer on entry. The caller has already saved R2 to the TOC stack save slot. 517 // 518 // 3. R2 does not hold the TOC pointer on entry. The caller has no expectations of R2. 519 // 520 // Go only needs case 1 and 3 today. Go symbols which have AttrShare set could use case 2, but case 1 always 521 // works in those cases too. 522 func gencallstub(ctxt *ld.Link, ldr *loader.Loader, stubType int, stub *loader.SymbolBuilder, targ loader.Sym) { 523 plt := ctxt.PLT 524 stub.SetType(sym.STEXT) 525 526 switch stubType { 527 case 1: 528 // Save TOC, then load targ address from PLT using TOC. 529 stub.AddUint32(ctxt.Arch, OP_TOCSAVE) // std r2,24(r1) 530 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ)), objabi.R_ADDRPOWER_TOCREL_DS, 8) 531 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_ADDIS_R12_R2) // addis r12,r2,targ@plt@toc@ha 532 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_LD_R12_R12) // ld r12,targ@plt@toc@l(r12) 533 case 3: 534 // No TOC needs to be saved, but the stub may need to position-independent. 535 if buildcfg.GOPPC64 >= 10 { 536 // Power10 is supported, load targ address into r12 using PCrel load. 537 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ)), objabi.R_ADDRPOWER_PCREL34, 8) 538 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_PLD_PFX_PCREL) 539 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_PLD_SFX_R12) // pld r12, targ@plt 540 } else if !isLinkingPIC(ctxt) { 541 // This stub doesn't need to be PIC. Load targ address from the PLT via its absolute address. 542 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ)), objabi.R_ADDRPOWER_DS, 8) 543 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_LIS_R12) // lis r12,targ@plt@ha 544 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_LD_R12_R12) // ld r12,targ@plt@l(r12) 545 } else { 546 // Generate a PIC stub. This is ugly as the stub must determine its location using 547 // POWER8 or older instruction. These stubs are likely the combination of using 548 // GOPPC64 < 8 and linking external objects built with CFLAGS="... -mcpu=power10 ..." 549 stub.AddUint32(ctxt.Arch, OP_MFLR_R0) // mflr r0 550 stub.AddUint32(ctxt.Arch, OP_BCL_NIA) // bcl 20,31,1f 551 stub.AddUint32(ctxt.Arch, OP_MFLR_R12) // 1: mflr r12 (r12 is the address of this instruction) 552 stub.AddUint32(ctxt.Arch, OP_MTLR_R0) // mtlr r0 553 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ))+8, objabi.R_ADDRPOWER_PCREL, 8) 554 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_ADDIS_R12_R12) // addis r12,(targ@plt - 1b) + 8 555 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_ADDI_R12_R12) // addi r12,(targ@plt - 1b) + 12 556 stub.AddUint32(ctxt.Arch, OP_LD_R12_R12) // ld r12, 0(r12) 557 } 558 default: 559 log.Fatalf("gencallstub does not support ELFv2 ABI property %d", stubType) 560 } 561 562 // Jump to the loaded pointer 563 stub.AddUint32(ctxt.Arch, OP_MTCTR_R12) // mtctr r12 564 stub.AddUint32(ctxt.Arch, OP_BCTR) // bctr 565 } 566 567 // Rewrite the instruction at offset into newinsn. Also, verify the 568 // existing instruction under mask matches the check value. 569 func rewritetoinsn(target *ld.Target, ldr *loader.Loader, su *loader.SymbolBuilder, offset int64, mask, check, newinsn uint32) { 570 su.MakeWritable() 571 op := target.Arch.ByteOrder.Uint32(su.Data()[offset:]) 572 if op&mask != check { 573 ldr.Errorf(su.Sym(), "Rewrite offset 0x%x to 0x%08X failed check (0x%08X&0x%08X != 0x%08X)", offset, newinsn, op, mask, check) 574 } 575 su.SetUint32(target.Arch, offset, newinsn) 576 } 577 578 // Rewrite the instruction at offset into a hardware nop instruction. Also, verify the 579 // existing instruction under mask matches the check value. 580 func rewritetonop(target *ld.Target, ldr *loader.Loader, su *loader.SymbolBuilder, offset int64, mask, check uint32) { 581 rewritetoinsn(target, ldr, su, offset, mask, check, OP_NOP) 582 } 583 584 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool { 585 if target.IsElf() { 586 return addelfdynrel(target, ldr, syms, s, r, rIdx) 587 } else if target.IsAIX() { 588 return ld.Xcoffadddynrel(target, ldr, syms, s, r, rIdx) 589 } 590 return false 591 } 592 593 func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool { 594 targ := r.Sym() 595 var targType sym.SymKind 596 if targ != 0 { 597 targType = ldr.SymType(targ) 598 } 599 600 switch r.Type() { 601 default: 602 if r.Type() >= objabi.ElfRelocOffset { 603 ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type())) 604 return false 605 } 606 607 // Handle relocations found in ELF object files. 608 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24_NOTOC), 609 objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24_P9NOTOC): 610 su := ldr.MakeSymbolUpdater(s) 611 su.SetRelocType(rIdx, objabi.R_CALLPOWER) 612 613 if targType == sym.SDYNIMPORT { 614 // Should have been handled in elfsetupplt 615 ldr.Errorf(s, "unexpected R_PPC64_REL24_NOTOC/R_PPC64_REL24_P9NOTOC for dyn import") 616 } 617 return true 618 619 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24): 620 su := ldr.MakeSymbolUpdater(s) 621 su.SetRelocType(rIdx, objabi.R_CALLPOWER) 622 623 // This is a local call, so the caller isn't setting 624 // up r12 and r2 is the same for the caller and 625 // callee. Hence, we need to go to the local entry 626 // point. (If we don't do this, the callee will try 627 // to use r12 to compute r2.) 628 localEoffset := int64(ldr.SymLocalentry(targ)) 629 if localEoffset == 1 { 630 ldr.Errorf(s, "Unsupported NOTOC call to %s", targ) 631 } 632 su.SetRelocAdd(rIdx, r.Add()+localEoffset) 633 634 if targType == sym.SDYNIMPORT { 635 // Should have been handled in genstubs 636 ldr.Errorf(s, "unexpected R_PPC64_REL24 for dyn import") 637 } 638 639 return true 640 641 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PCREL34): 642 su := ldr.MakeSymbolUpdater(s) 643 su.SetRelocType(rIdx, objabi.R_ADDRPOWER_PCREL34) 644 return true 645 646 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_GOT_PCREL34): 647 su := ldr.MakeSymbolUpdater(s) 648 su.SetRelocType(rIdx, objabi.R_ADDRPOWER_PCREL34) 649 if targType != sym.STEXT { 650 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_PPC64_GLOB_DAT)) 651 su.SetRelocSym(rIdx, syms.GOT) 652 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ))) 653 } else { 654 // The address of targ is known at link time. Rewrite to "pla rt,targ" from "pld rt,targ@got" 655 rewritetoinsn(target, ldr, su, int64(r.Off()), MASK_PLD_PFX, OP_PLD_PFX_PCREL, OP_PLA_PFX) 656 pla_sfx := target.Arch.ByteOrder.Uint32(su.Data()[r.Off()+4:])&MASK_PLD_RT | OP_PLA_SFX 657 rewritetoinsn(target, ldr, su, int64(r.Off()+4), MASK_PLD_SFX, OP_PLD_SFX, pla_sfx) 658 } 659 return true 660 661 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32): 662 su := ldr.MakeSymbolUpdater(s) 663 su.SetRelocType(rIdx, objabi.R_PCREL) 664 su.SetRelocAdd(rIdx, r.Add()+4) 665 666 if targType == sym.SDYNIMPORT { 667 ldr.Errorf(s, "unexpected R_PPC_REL32 for dyn import") 668 } 669 670 return true 671 672 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_ADDR64): 673 su := ldr.MakeSymbolUpdater(s) 674 su.SetRelocType(rIdx, objabi.R_ADDR) 675 if targType == sym.SDYNIMPORT { 676 // These happen in .toc sections 677 ld.Adddynsym(ldr, target, syms, targ) 678 679 rela := ldr.MakeSymbolUpdater(syms.Rela) 680 rela.AddAddrPlus(target.Arch, s, int64(r.Off())) 681 rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_PPC64_ADDR64))) 682 rela.AddUint64(target.Arch, uint64(r.Add())) 683 su.SetRelocType(rIdx, objabi.ElfRelocOffset) // ignore during relocsym 684 } else if target.IsPIE() && target.IsInternal() { 685 // For internal linking PIE, this R_ADDR relocation cannot 686 // be resolved statically. We need to generate a dynamic 687 // relocation. Let the code below handle it. 688 break 689 } 690 return true 691 692 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16): 693 su := ldr.MakeSymbolUpdater(s) 694 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 695 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO|sym.RV_CHECK_OVERFLOW) 696 return true 697 698 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO): 699 su := ldr.MakeSymbolUpdater(s) 700 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 701 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO) 702 return true 703 704 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA): 705 su := ldr.MakeSymbolUpdater(s) 706 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 707 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW) 708 return true 709 710 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI): 711 su := ldr.MakeSymbolUpdater(s) 712 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 713 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW) 714 return true 715 716 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS): 717 su := ldr.MakeSymbolUpdater(s) 718 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 719 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS|sym.RV_CHECK_OVERFLOW) 720 return true 721 722 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS): 723 su := ldr.MakeSymbolUpdater(s) 724 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 725 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS) 726 return true 727 728 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO): 729 su := ldr.MakeSymbolUpdater(s) 730 su.SetRelocType(rIdx, objabi.R_PCREL) 731 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO) 732 su.SetRelocAdd(rIdx, r.Add()+2) // Compensate for relocation size of 2 733 return true 734 735 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI): 736 su := ldr.MakeSymbolUpdater(s) 737 su.SetRelocType(rIdx, objabi.R_PCREL) 738 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW) 739 su.SetRelocAdd(rIdx, r.Add()+2) 740 return true 741 742 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA): 743 su := ldr.MakeSymbolUpdater(s) 744 su.SetRelocType(rIdx, objabi.R_PCREL) 745 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW) 746 su.SetRelocAdd(rIdx, r.Add()+2) 747 return true 748 749 // When compiling with gcc's -fno-plt option (no PLT), the following code and relocation 750 // sequences may be present to call an external function: 751 // 752 // 1. addis Rx,foo@R_PPC64_PLT16_HA 753 // 2. ld 12,foo@R_PPC64_PLT16_LO_DS(Rx) 754 // 3. mtctr 12 ; foo@R_PPC64_PLTSEQ 755 // 4. bctrl ; foo@R_PPC64_PLTCALL 756 // 5. ld r2,24(r1) 757 // 758 // Note, 5 is required to follow the R_PPC64_PLTCALL. Similarly, relocations targeting 759 // instructions 3 and 4 are zero sized informational relocations. 760 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PLT16_HA), 761 objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PLT16_LO_DS): 762 su := ldr.MakeSymbolUpdater(s) 763 isPLT16_LO_DS := r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_PPC64_PLT16_LO_DS) 764 if isPLT16_LO_DS { 765 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS) 766 } else { 767 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW) 768 } 769 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 770 if targType == sym.SDYNIMPORT { 771 // This is an external symbol, make space in the GOT and retarget the reloc. 772 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_PPC64_GLOB_DAT)) 773 su.SetRelocSym(rIdx, syms.GOT) 774 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ))) 775 } else if targType == sym.STEXT { 776 if isPLT16_LO_DS { 777 // Expect an ld opcode to nop 778 rewritetonop(target, ldr, su, int64(r.Off()), MASK_OP_LD, OP_LD) 779 } else { 780 // Expect an addis opcode to nop 781 rewritetonop(target, ldr, su, int64(r.Off()), MASK_OP_ADDIS, OP_ADDIS) 782 } 783 // And we can ignore this reloc now. 784 su.SetRelocType(rIdx, objabi.ElfRelocOffset) 785 } else { 786 ldr.Errorf(s, "unexpected PLT relocation target symbol type %s", targType.String()) 787 } 788 return true 789 } 790 791 // Handle references to ELF symbols from our own object files. 792 relocs := ldr.Relocs(s) 793 r = relocs.At(rIdx) 794 795 switch r.Type() { 796 case objabi.R_ADDR: 797 if ldr.SymType(s) == sym.STEXT { 798 log.Fatalf("R_ADDR relocation in text symbol %s is unsupported\n", ldr.SymName(s)) 799 } 800 if target.IsPIE() && target.IsInternal() { 801 // When internally linking, generate dynamic relocations 802 // for all typical R_ADDR relocations. The exception 803 // are those R_ADDR that are created as part of generating 804 // the dynamic relocations and must be resolved statically. 805 // 806 // There are three phases relevant to understanding this: 807 // 808 // dodata() // we are here 809 // address() // symbol address assignment 810 // reloc() // resolution of static R_ADDR relocs 811 // 812 // At this point symbol addresses have not been 813 // assigned yet (as the final size of the .rela section 814 // will affect the addresses), and so we cannot write 815 // the Elf64_Rela.r_offset now. Instead we delay it 816 // until after the 'address' phase of the linker is 817 // complete. We do this via Addaddrplus, which creates 818 // a new R_ADDR relocation which will be resolved in 819 // the 'reloc' phase. 820 // 821 // These synthetic static R_ADDR relocs must be skipped 822 // now, or else we will be caught in an infinite loop 823 // of generating synthetic relocs for our synthetic 824 // relocs. 825 // 826 // Furthermore, the rela sections contain dynamic 827 // relocations with R_ADDR relocations on 828 // Elf64_Rela.r_offset. This field should contain the 829 // symbol offset as determined by reloc(), not the 830 // final dynamically linked address as a dynamic 831 // relocation would provide. 832 switch ldr.SymName(s) { 833 case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic": 834 return false 835 } 836 } else { 837 // Either internally linking a static executable, 838 // in which case we can resolve these relocations 839 // statically in the 'reloc' phase, or externally 840 // linking, in which case the relocation will be 841 // prepared in the 'reloc' phase and passed to the 842 // external linker in the 'asmb' phase. 843 if ldr.SymType(s) != sym.SDATA && ldr.SymType(s) != sym.SRODATA { 844 break 845 } 846 } 847 // Generate R_PPC64_RELATIVE relocations for best 848 // efficiency in the dynamic linker. 849 // 850 // As noted above, symbol addresses have not been 851 // assigned yet, so we can't generate the final reloc 852 // entry yet. We ultimately want: 853 // 854 // r_offset = s + r.Off 855 // r_info = R_PPC64_RELATIVE 856 // r_addend = targ + r.Add 857 // 858 // The dynamic linker will set *offset = base address + 859 // addend. 860 // 861 // AddAddrPlus is used for r_offset and r_addend to 862 // generate new R_ADDR relocations that will update 863 // these fields in the 'reloc' phase. 864 rela := ldr.MakeSymbolUpdater(syms.Rela) 865 rela.AddAddrPlus(target.Arch, s, int64(r.Off())) 866 if r.Siz() == 8 { 867 rela.AddUint64(target.Arch, elf.R_INFO(0, uint32(elf.R_PPC64_RELATIVE))) 868 } else { 869 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ)) 870 } 871 rela.AddAddrPlus(target.Arch, targ, int64(r.Add())) 872 873 // Not mark r done here. So we still apply it statically, 874 // so in the file content we'll also have the right offset 875 // to the relocation target. So it can be examined statically 876 // (e.g. go version). 877 return true 878 } 879 880 return false 881 } 882 883 func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool { 884 rs := r.Xsym 885 886 emitReloc := func(v uint16, off uint64) { 887 out.Write64(uint64(sectoff) + off) 888 out.Write32(uint32(ldr.SymDynid(rs))) 889 out.Write16(v) 890 } 891 892 var v uint16 893 switch r.Type { 894 default: 895 return false 896 case objabi.R_ADDR, objabi.R_DWARFSECREF: 897 v = ld.XCOFF_R_POS 898 if r.Size == 4 { 899 v |= 0x1F << 8 900 } else { 901 v |= 0x3F << 8 902 } 903 emitReloc(v, 0) 904 case objabi.R_ADDRPOWER_TOCREL: 905 case objabi.R_ADDRPOWER_TOCREL_DS: 906 emitReloc(ld.XCOFF_R_TOCU|(0x0F<<8), 2) 907 emitReloc(ld.XCOFF_R_TOCL|(0x0F<<8), 6) 908 case objabi.R_POWER_TLS_LE: 909 // This only supports 16b relocations. It is fixed up in archreloc. 910 emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2) 911 case objabi.R_CALLPOWER: 912 if r.Size != 4 { 913 return false 914 } 915 emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0) 916 case objabi.R_XCOFFREF: 917 emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0) 918 } 919 return true 920 } 921 922 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool { 923 // Beware that bit0~bit15 start from the third byte of an instruction in Big-Endian machines. 924 rt := r.Type 925 if rt == objabi.R_ADDR || rt == objabi.R_POWER_TLS || rt == objabi.R_CALLPOWER || rt == objabi.R_DWARFSECREF { 926 } else { 927 if ctxt.Arch.ByteOrder == binary.BigEndian { 928 sectoff += 2 929 } 930 } 931 out.Write64(uint64(sectoff)) 932 933 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym) 934 switch rt { 935 default: 936 return false 937 case objabi.R_ADDR, objabi.R_DWARFSECREF: 938 switch r.Size { 939 case 4: 940 out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32) 941 case 8: 942 out.Write64(uint64(elf.R_PPC64_ADDR64) | uint64(elfsym)<<32) 943 default: 944 return false 945 } 946 case objabi.R_ADDRPOWER_D34: 947 out.Write64(uint64(elf.R_PPC64_D34) | uint64(elfsym)<<32) 948 case objabi.R_ADDRPOWER_PCREL34: 949 out.Write64(uint64(elf.R_PPC64_PCREL34) | uint64(elfsym)<<32) 950 case objabi.R_POWER_TLS: 951 out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32) 952 case objabi.R_POWER_TLS_LE: 953 out.Write64(uint64(elf.R_PPC64_TPREL16_HA) | uint64(elfsym)<<32) 954 out.Write64(uint64(r.Xadd)) 955 out.Write64(uint64(sectoff + 4)) 956 out.Write64(uint64(elf.R_PPC64_TPREL16_LO) | uint64(elfsym)<<32) 957 case objabi.R_POWER_TLS_LE_TPREL34: 958 out.Write64(uint64(elf.R_PPC64_TPREL34) | uint64(elfsym)<<32) 959 case objabi.R_POWER_TLS_IE_PCREL34: 960 out.Write64(uint64(elf.R_PPC64_GOT_TPREL_PCREL34) | uint64(elfsym)<<32) 961 case objabi.R_POWER_TLS_IE: 962 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32) 963 out.Write64(uint64(r.Xadd)) 964 out.Write64(uint64(sectoff + 4)) 965 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_LO_DS) | uint64(elfsym)<<32) 966 case objabi.R_ADDRPOWER: 967 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32) 968 out.Write64(uint64(r.Xadd)) 969 out.Write64(uint64(sectoff + 4)) 970 out.Write64(uint64(elf.R_PPC64_ADDR16_LO) | uint64(elfsym)<<32) 971 case objabi.R_ADDRPOWER_DS: 972 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32) 973 out.Write64(uint64(r.Xadd)) 974 out.Write64(uint64(sectoff + 4)) 975 out.Write64(uint64(elf.R_PPC64_ADDR16_LO_DS) | uint64(elfsym)<<32) 976 case objabi.R_ADDRPOWER_GOT: 977 out.Write64(uint64(elf.R_PPC64_GOT16_HA) | uint64(elfsym)<<32) 978 out.Write64(uint64(r.Xadd)) 979 out.Write64(uint64(sectoff + 4)) 980 out.Write64(uint64(elf.R_PPC64_GOT16_LO_DS) | uint64(elfsym)<<32) 981 case objabi.R_ADDRPOWER_GOT_PCREL34: 982 out.Write64(uint64(elf.R_PPC64_GOT_PCREL34) | uint64(elfsym)<<32) 983 case objabi.R_ADDRPOWER_PCREL: 984 out.Write64(uint64(elf.R_PPC64_REL16_HA) | uint64(elfsym)<<32) 985 out.Write64(uint64(r.Xadd)) 986 out.Write64(uint64(sectoff + 4)) 987 out.Write64(uint64(elf.R_PPC64_REL16_LO) | uint64(elfsym)<<32) 988 r.Xadd += 4 989 case objabi.R_ADDRPOWER_TOCREL: 990 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32) 991 out.Write64(uint64(r.Xadd)) 992 out.Write64(uint64(sectoff + 4)) 993 out.Write64(uint64(elf.R_PPC64_TOC16_LO) | uint64(elfsym)<<32) 994 case objabi.R_ADDRPOWER_TOCREL_DS: 995 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32) 996 out.Write64(uint64(r.Xadd)) 997 out.Write64(uint64(sectoff + 4)) 998 out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32) 999 case objabi.R_CALLPOWER: 1000 if r.Size != 4 { 1001 return false 1002 } 1003 if !hasPCrel { 1004 out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32) 1005 } else { 1006 // TOC is not used in PCrel compiled Go code. 1007 out.Write64(uint64(elf.R_PPC64_REL24_NOTOC) | uint64(elfsym)<<32) 1008 } 1009 1010 } 1011 out.Write64(uint64(r.Xadd)) 1012 1013 return true 1014 } 1015 1016 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, got *loader.SymbolBuilder, dynamic loader.Sym) { 1017 if plt.Size() == 0 { 1018 // The dynamic linker stores the address of the 1019 // dynamic resolver and the DSO identifier in the two 1020 // doublewords at the beginning of the .plt section 1021 // before the PLT array. Reserve space for these. 1022 plt.SetSize(16) 1023 } 1024 } 1025 1026 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool { 1027 return false 1028 } 1029 1030 // Return the value of .TOC. for symbol s 1031 func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 { 1032 v := ldr.SymVersion(s) 1033 if out := ldr.OuterSym(s); out != 0 { 1034 v = ldr.SymVersion(out) 1035 } 1036 1037 toc := syms.DotTOC[v] 1038 if toc == 0 { 1039 ldr.Errorf(s, "TOC-relative relocation in object without .TOC.") 1040 return 0 1041 } 1042 1043 return ldr.SymValue(toc) 1044 } 1045 1046 // archreloctoc relocates a TOC relative symbol. 1047 func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 { 1048 rs := r.Sym() 1049 var o1, o2 uint32 1050 var t int64 1051 useAddi := false 1052 1053 if target.IsBigEndian() { 1054 o1 = uint32(val >> 32) 1055 o2 = uint32(val) 1056 } else { 1057 o1 = uint32(val) 1058 o2 = uint32(val >> 32) 1059 } 1060 1061 // On AIX, TOC data accesses are always made indirectly against R2 (a sequence of addis+ld+load/store). If the 1062 // The target of the load is known, the sequence can be written into addis+addi+load/store. On Linux, 1063 // TOC data accesses are always made directly against R2 (e.g addis+load/store). 1064 if target.IsAIX() { 1065 if !strings.HasPrefix(ldr.SymName(rs), "TOC.") { 1066 ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor") 1067 } 1068 relocs := ldr.Relocs(rs) 1069 tarSym := relocs.At(0).Sym() 1070 1071 if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata { 1072 t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC) 1073 // change ld to addi in the second instruction 1074 o2 = (o2 & 0x03FF0000) | 0xE<<26 1075 useAddi = true 1076 } else { 1077 t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC) 1078 } 1079 } else { 1080 t = ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s) 1081 } 1082 1083 if t != int64(int32(t)) { 1084 ldr.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", ldr.SymName(s), rs, t) 1085 } 1086 1087 if t&0x8000 != 0 { 1088 t += 0x10000 1089 } 1090 1091 o1 |= uint32((t >> 16) & 0xFFFF) 1092 1093 switch r.Type() { 1094 case objabi.R_ADDRPOWER_TOCREL_DS: 1095 if useAddi { 1096 o2 |= uint32(t) & 0xFFFF 1097 } else { 1098 if t&3 != 0 { 1099 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs)) 1100 } 1101 o2 |= uint32(t) & 0xFFFC 1102 } 1103 case objabi.R_ADDRPOWER_TOCREL: 1104 o2 |= uint32(t) & 0xffff 1105 default: 1106 return -1 1107 } 1108 1109 if target.IsBigEndian() { 1110 return int64(o1)<<32 | int64(o2) 1111 } 1112 return int64(o2)<<32 | int64(o1) 1113 } 1114 1115 // archrelocaddr relocates a symbol address. 1116 // This code is for linux only. 1117 func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 { 1118 rs := r.Sym() 1119 if target.IsAIX() { 1120 ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs)) 1121 } 1122 o1, o2 := unpackInstPair(target, val) 1123 1124 // Verify resulting address fits within a 31 bit (2GB) address space. 1125 // This is a restriction arising from the usage of lis (HA) + d-form 1126 // (LO) instruction sequences used to implement absolute relocations 1127 // on PPC64 prior to ISA 3.1 (P10). For consistency, maintain this 1128 // restriction for ISA 3.1 unless it becomes problematic. 1129 t := ldr.SymAddr(rs) + r.Add() 1130 if t < 0 || t >= 1<<31 { 1131 ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs)) 1132 } 1133 1134 // Note, relocations imported from external objects may not have cleared bits 1135 // within a relocatable field. They need cleared before applying the relocation. 1136 switch r.Type() { 1137 case objabi.R_ADDRPOWER_PCREL34: 1138 // S + A - P 1139 t -= (ldr.SymValue(s) + int64(r.Off())) 1140 o1 &^= 0x3ffff 1141 o2 &^= 0x0ffff 1142 o1 |= computePrefix34HI(t) 1143 o2 |= computeLO(int32(t)) 1144 case objabi.R_ADDRPOWER_D34: 1145 o1 &^= 0x3ffff 1146 o2 &^= 0x0ffff 1147 o1 |= computePrefix34HI(t) 1148 o2 |= computeLO(int32(t)) 1149 case objabi.R_ADDRPOWER: 1150 o1 &^= 0xffff 1151 o2 &^= 0xffff 1152 o1 |= computeHA(int32(t)) 1153 o2 |= computeLO(int32(t)) 1154 case objabi.R_ADDRPOWER_DS: 1155 o1 &^= 0xffff 1156 o2 &^= 0xfffc 1157 o1 |= computeHA(int32(t)) 1158 o2 |= computeLO(int32(t)) 1159 if t&3 != 0 { 1160 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs)) 1161 } 1162 default: 1163 return -1 1164 } 1165 1166 return packInstPair(target, o1, o2) 1167 } 1168 1169 // Determine if the code was compiled so that the TOC register R2 is initialized and maintained. 1170 func r2Valid(ctxt *ld.Link) bool { 1171 return isLinkingPIC(ctxt) 1172 } 1173 1174 // Determine if this is linking a position-independent binary. 1175 func isLinkingPIC(ctxt *ld.Link) bool { 1176 switch ctxt.BuildMode { 1177 case ld.BuildModeCArchive, ld.BuildModeCShared, ld.BuildModePIE, ld.BuildModeShared, ld.BuildModePlugin: 1178 return true 1179 } 1180 // -linkshared option 1181 return ctxt.IsSharedGoLink() 1182 } 1183 1184 // resolve direct jump relocation r in s, and add trampoline if necessary. 1185 func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { 1186 1187 // Trampolines are created if the branch offset is too large and the linker cannot insert a call stub to handle it. 1188 // For internal linking, trampolines are always created for long calls. 1189 // For external linking, the linker can insert a call stub to handle a long call, but depends on having the TOC address in 1190 // r2. For those build modes with external linking where the TOC address is not maintained in r2, trampolines must be created. 1191 if ctxt.IsExternal() && r2Valid(ctxt) { 1192 // The TOC pointer is valid. The external linker will insert trampolines. 1193 return 1194 } 1195 1196 relocs := ldr.Relocs(s) 1197 r := relocs.At(ri) 1198 var t int64 1199 // ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet 1200 // laid out. Conservatively use a trampoline. This should be rare, as we lay out packages 1201 // in dependency order. 1202 if ldr.SymValue(rs) != 0 { 1203 t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) 1204 } 1205 switch r.Type() { 1206 case objabi.R_CALLPOWER: 1207 1208 // If branch offset is too far then create a trampoline. 1209 1210 if (ctxt.IsExternal() && ldr.SymSect(s) != ldr.SymSect(rs)) || (ctxt.IsInternal() && int64(int32(t<<6)>>6) != t) || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) { 1211 var tramp loader.Sym 1212 for i := 0; ; i++ { 1213 1214 // Using r.Add as part of the name is significant in functions like duffzero where the call 1215 // target is at some offset within the function. Calls to duff+8 and duff+256 must appear as 1216 // distinct trampolines. 1217 1218 oName := ldr.SymName(rs) 1219 name := oName 1220 if r.Add() == 0 { 1221 name += fmt.Sprintf("-tramp%d", i) 1222 } else { 1223 name += fmt.Sprintf("%+x-tramp%d", r.Add(), i) 1224 } 1225 1226 // Look up the trampoline in case it already exists 1227 1228 tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs))) 1229 if oName == "runtime.deferreturn" { 1230 ldr.SetIsDeferReturnTramp(tramp, true) 1231 } 1232 if ldr.SymValue(tramp) == 0 { 1233 break 1234 } 1235 // Note, the trampoline is always called directly. The addend of the original relocation is accounted for in the 1236 // trampoline itself. 1237 t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off())) 1238 1239 // With internal linking, the trampoline can be used if it is not too far. 1240 // With external linking, the trampoline must be in this section for it to be reused. 1241 if (ctxt.IsInternal() && int64(int32(t<<6)>>6) == t) || (ctxt.IsExternal() && ldr.SymSect(s) == ldr.SymSect(tramp)) { 1242 break 1243 } 1244 } 1245 if ldr.SymType(tramp) == 0 { 1246 trampb := ldr.MakeSymbolUpdater(tramp) 1247 ctxt.AddTramp(trampb) 1248 gentramp(ctxt, ldr, trampb, rs, r.Add()) 1249 } 1250 sb := ldr.MakeSymbolUpdater(s) 1251 relocs := sb.Relocs() 1252 r := relocs.At(ri) 1253 r.SetSym(tramp) 1254 r.SetAdd(0) // This was folded into the trampoline target address 1255 } 1256 default: 1257 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type())) 1258 } 1259 } 1260 1261 func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) { 1262 tramp.SetSize(16) // 4 instructions 1263 P := make([]byte, tramp.Size()) 1264 var o1, o2 uint32 1265 1266 // ELFv2 save/restore functions use R0/R12 in special ways, therefore trampolines 1267 // as generated here will not always work correctly. 1268 if strings.HasPrefix(ldr.SymName(target), "runtime.elf_") { 1269 log.Fatalf("Internal linker does not support trampolines to ELFv2 ABI"+ 1270 " register save/restore function %s", ldr.SymName(target)) 1271 } 1272 1273 if ctxt.IsAIX() { 1274 // On AIX, the address is retrieved with a TOC symbol. 1275 // For internal linking, the "Linux" way might still be used. 1276 // However, all text symbols are accessed with a TOC symbol as 1277 // text relocations aren't supposed to be possible. 1278 // So, keep using the external linking way to be more AIX friendly. 1279 o1 = uint32(OP_ADDIS_R12_R2) // addis r12, r2, toctargetaddr hi 1280 o2 = uint32(OP_LD_R12_R12) // ld r12, r12, toctargetaddr lo 1281 1282 toctramp := ldr.CreateSymForUpdate("TOC."+ldr.SymName(tramp.Sym()), 0) 1283 toctramp.SetType(sym.SXCOFFTOC) 1284 toctramp.AddAddrPlus(ctxt.Arch, target, offset) 1285 1286 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_TOCREL_DS) 1287 r.SetOff(0) 1288 r.SetSiz(8) // generates 2 relocations: HA + LO 1289 r.SetSym(toctramp.Sym()) 1290 } else if hasPCrel { 1291 // pla r12, addr (PCrel). This works for static or PIC, with or without a valid TOC pointer. 1292 o1 = uint32(OP_PLA_PFX) 1293 o2 = uint32(OP_PLA_SFX_R12) // pla r12, addr 1294 1295 // The trampoline's position is not known yet, insert a relocation. 1296 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_PCREL34) 1297 r.SetOff(0) 1298 r.SetSiz(8) // This spans 2 words. 1299 r.SetSym(target) 1300 r.SetAdd(offset) 1301 } else { 1302 // Used for default build mode for an executable 1303 // Address of the call target is generated using 1304 // relocation and doesn't depend on r2 (TOC). 1305 o1 = uint32(OP_LIS_R12) // lis r12,targetaddr hi 1306 o2 = uint32(OP_ADDI_R12_R12) // addi r12,r12,targetaddr lo 1307 1308 t := ldr.SymValue(target) 1309 if t == 0 || r2Valid(ctxt) || ctxt.IsExternal() { 1310 // Target address is unknown, generate relocations 1311 r, _ := tramp.AddRel(objabi.R_ADDRPOWER) 1312 if r2Valid(ctxt) { 1313 // Use a TOC relative address if R2 holds the TOC pointer 1314 o1 |= uint32(2 << 16) // Transform lis r31,ha into addis r31,r2,ha 1315 r.SetType(objabi.R_ADDRPOWER_TOCREL) 1316 } 1317 r.SetOff(0) 1318 r.SetSiz(8) // generates 2 relocations: HA + LO 1319 r.SetSym(target) 1320 r.SetAdd(offset) 1321 } else { 1322 // The target address is known, resolve it 1323 t += offset 1324 o1 |= (uint32(t) + 0x8000) >> 16 // HA 1325 o2 |= uint32(t) & 0xFFFF // LO 1326 } 1327 } 1328 1329 o3 := uint32(OP_MTCTR_R12) // mtctr r12 1330 o4 := uint32(OP_BCTR) // bctr 1331 ctxt.Arch.ByteOrder.PutUint32(P, o1) 1332 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2) 1333 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3) 1334 ctxt.Arch.ByteOrder.PutUint32(P[12:], o4) 1335 tramp.SetData(P) 1336 } 1337 1338 // Unpack a pair of 32 bit instruction words from 1339 // a 64 bit relocation into instN and instN+1 in endian order. 1340 func unpackInstPair(target *ld.Target, r int64) (uint32, uint32) { 1341 if target.IsBigEndian() { 1342 return uint32(r >> 32), uint32(r) 1343 } 1344 return uint32(r), uint32(r >> 32) 1345 } 1346 1347 // Pack a pair of 32 bit instruction words o1, o2 into 64 bit relocation 1348 // in endian order. 1349 func packInstPair(target *ld.Target, o1, o2 uint32) int64 { 1350 if target.IsBigEndian() { 1351 return (int64(o1) << 32) | int64(o2) 1352 } 1353 return int64(o1) | (int64(o2) << 32) 1354 } 1355 1356 // Compute the high-adjusted value (always a signed 32b value) per the ELF ABI. 1357 // The returned value is always 0 <= x <= 0xFFFF. 1358 func computeHA(val int32) uint32 { 1359 return uint32(uint16((val + 0x8000) >> 16)) 1360 } 1361 1362 // Compute the low value (the lower 16 bits of any 32b value) per the ELF ABI. 1363 // The returned value is always 0 <= x <= 0xFFFF. 1364 func computeLO(val int32) uint32 { 1365 return uint32(uint16(val)) 1366 } 1367 1368 // Compute the high 18 bits of a signed 34b constant. Used to pack the high 18 bits 1369 // of a prefix34 relocation field. This assumes the input is already restricted to 1370 // 34 bits. 1371 func computePrefix34HI(val int64) uint32 { 1372 return uint32((val >> 16) & 0x3FFFF) 1373 } 1374 1375 func computeTLSLEReloc(target *ld.Target, ldr *loader.Loader, rs, s loader.Sym) int64 { 1376 // The thread pointer points 0x7000 bytes after the start of the 1377 // thread local storage area as documented in section "3.7.2 TLS 1378 // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI 1379 // Specification". 1380 v := ldr.SymValue(rs) - 0x7000 1381 if target.IsAIX() { 1382 // On AIX, the thread pointer points 0x7800 bytes after 1383 // the TLS. 1384 v -= 0x800 1385 } 1386 1387 if int64(int32(v)) != v { 1388 ldr.Errorf(s, "TLS offset out of range %d", v) 1389 } 1390 return v 1391 } 1392 1393 func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (relocatedOffset int64, nExtReloc int, ok bool) { 1394 rs := r.Sym() 1395 if target.IsExternal() { 1396 // On AIX, relocations (except TLS ones) must be also done to the 1397 // value with the current addresses. 1398 switch rt := r.Type(); rt { 1399 default: 1400 if !target.IsAIX() { 1401 return val, nExtReloc, false 1402 } 1403 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_IE_PCREL34, objabi.R_POWER_TLS_LE_TPREL34, objabi.R_ADDRPOWER_GOT_PCREL34: 1404 nExtReloc = 1 1405 return val, nExtReloc, true 1406 case objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE: 1407 if target.IsAIX() && rt == objabi.R_POWER_TLS_LE { 1408 // Fixup val, an addis/addi pair of instructions, which generate a 32b displacement 1409 // from the threadpointer (R13), into a 16b relocation. XCOFF only supports 16b 1410 // TLS LE relocations. Likewise, verify this is an addis/addi sequence. 1411 const expectedOpcodes = 0x3C00000038000000 1412 const expectedOpmasks = 0xFC000000FC000000 1413 if uint64(val)&expectedOpmasks != expectedOpcodes { 1414 ldr.Errorf(s, "relocation for %s+%d is not an addis/addi pair: %16x", ldr.SymName(rs), r.Off(), uint64(val)) 1415 } 1416 nval := (int64(uint32(0x380d0000)) | val&0x03e00000) << 32 // addi rX, r13, $0 1417 nval |= int64(OP_NOP) // nop 1418 val = nval 1419 nExtReloc = 1 1420 } else { 1421 nExtReloc = 2 1422 } 1423 return val, nExtReloc, true 1424 case objabi.R_ADDRPOWER, 1425 objabi.R_ADDRPOWER_DS, 1426 objabi.R_ADDRPOWER_TOCREL, 1427 objabi.R_ADDRPOWER_TOCREL_DS, 1428 objabi.R_ADDRPOWER_GOT, 1429 objabi.R_ADDRPOWER_PCREL: 1430 nExtReloc = 2 // need two ELF relocations, see elfreloc1 1431 if !target.IsAIX() { 1432 return val, nExtReloc, true 1433 } 1434 case objabi.R_CALLPOWER, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34: 1435 nExtReloc = 1 1436 if !target.IsAIX() { 1437 return val, nExtReloc, true 1438 } 1439 } 1440 } 1441 1442 switch r.Type() { 1443 case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS: 1444 return archreloctoc(ldr, target, syms, r, s, val), nExtReloc, true 1445 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34: 1446 return archrelocaddr(ldr, target, syms, r, s, val), nExtReloc, true 1447 case objabi.R_CALLPOWER: 1448 // Bits 6 through 29 = (S + A - P) >> 2 1449 1450 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) 1451 1452 tgtName := ldr.SymName(rs) 1453 1454 // If we are linking PIE or shared code, non-PCrel golang generated object files have an extra 2 instruction prologue 1455 // to regenerate the TOC pointer from R12. The exception are two special case functions tested below. Note, 1456 // local call offsets for externally generated objects are accounted for when converting into golang relocs. 1457 if !hasPCrel && !ldr.AttrExternal(rs) && ldr.AttrShared(rs) && tgtName != "runtime.duffzero" && tgtName != "runtime.duffcopy" { 1458 // Furthermore, only apply the offset if the target looks like the start of a function call. 1459 if r.Add() == 0 && ldr.SymType(rs) == sym.STEXT { 1460 t += 8 1461 } 1462 } 1463 1464 if t&3 != 0 { 1465 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t) 1466 } 1467 // If branch offset is too far then create a trampoline. 1468 1469 if int64(int32(t<<6)>>6) != t { 1470 ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t) 1471 } 1472 return val | int64(uint32(t)&^0xfc000003), nExtReloc, true 1473 case objabi.R_POWER_TOC: // S + A - .TOC. 1474 return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true 1475 1476 case objabi.R_ADDRPOWER_PCREL: // S + A - P 1477 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) 1478 ha, l := unpackInstPair(target, val) 1479 l |= computeLO(int32(t)) 1480 ha |= computeHA(int32(t)) 1481 return packInstPair(target, ha, l), nExtReloc, true 1482 1483 case objabi.R_POWER_TLS: 1484 const OP_ADD = 31<<26 | 266<<1 1485 const MASK_OP_ADD = 0x3F<<26 | 0x1FF<<1 1486 if val&MASK_OP_ADD != OP_ADD { 1487 ldr.Errorf(s, "R_POWER_TLS reloc only supports XO form ADD, not %08X", val) 1488 } 1489 // Verify RB is R13 in ADD RA,RB,RT. 1490 if (val>>11)&0x1F != 13 { 1491 // If external linking is made to support this, it may expect the linker to rewrite RB. 1492 ldr.Errorf(s, "R_POWER_TLS reloc requires R13 in RB (%08X).", uint32(val)) 1493 } 1494 return val, nExtReloc, true 1495 1496 case objabi.R_POWER_TLS_IE: 1497 // Convert TLS_IE relocation to TLS_LE if supported. 1498 if !(target.IsPIE() && target.IsElf()) { 1499 log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s)) 1500 } 1501 1502 // We are an ELF binary, we can safely convert to TLS_LE from: 1503 // addis to, r2, x@got@tprel@ha 1504 // ld to, to, x@got@tprel@l(to) 1505 // 1506 // to TLS_LE by converting to: 1507 // addis to, r0, x@tprel@ha 1508 // addi to, to, x@tprel@l(to) 1509 1510 const OP_MASK = 0x3F << 26 1511 const OP_RA_MASK = 0x1F << 16 1512 // convert r2 to r0, and ld to addi 1513 mask := packInstPair(target, OP_RA_MASK, OP_MASK) 1514 addi_op := packInstPair(target, 0, OP_ADDI) 1515 val &^= mask 1516 val |= addi_op 1517 fallthrough 1518 1519 case objabi.R_POWER_TLS_LE: 1520 v := computeTLSLEReloc(target, ldr, rs, s) 1521 o1, o2 := unpackInstPair(target, val) 1522 o1 |= computeHA(int32(v)) 1523 o2 |= computeLO(int32(v)) 1524 return packInstPair(target, o1, o2), nExtReloc, true 1525 1526 case objabi.R_POWER_TLS_IE_PCREL34: 1527 // Convert TLS_IE relocation to TLS_LE if supported. 1528 if !(target.IsPIE() && target.IsElf()) { 1529 log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s)) 1530 } 1531 1532 // We are an ELF binary, we can safely convert to TLS_LE_TPREL34 from: 1533 // pld rX, x@got@tprel@pcrel 1534 // 1535 // to TLS_LE_TPREL32 by converting to: 1536 // pla rX, x@tprel 1537 1538 const OP_MASK_PFX = 0xFFFFFFFF // Discard prefix word 1539 const OP_MASK = (0x3F << 26) | 0xFFFF // Preserve RT, RA 1540 const OP_PFX = 1<<26 | 2<<24 1541 const OP_PLA = 14 << 26 1542 mask := packInstPair(target, OP_MASK_PFX, OP_MASK) 1543 pla_op := packInstPair(target, OP_PFX, OP_PLA) 1544 val &^= mask 1545 val |= pla_op 1546 fallthrough 1547 1548 case objabi.R_POWER_TLS_LE_TPREL34: 1549 v := computeTLSLEReloc(target, ldr, rs, s) 1550 o1, o2 := unpackInstPair(target, val) 1551 o1 |= computePrefix34HI(v) 1552 o2 |= computeLO(int32(v)) 1553 return packInstPair(target, o1, o2), nExtReloc, true 1554 } 1555 1556 return val, nExtReloc, false 1557 } 1558 1559 func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc, rv sym.RelocVariant, s loader.Sym, t int64, p []byte) (relocatedOffset int64) { 1560 rs := r.Sym() 1561 switch rv & sym.RV_TYPE_MASK { 1562 default: 1563 ldr.Errorf(s, "unexpected relocation variant %d", rv) 1564 fallthrough 1565 1566 case sym.RV_NONE: 1567 return t 1568 1569 case sym.RV_POWER_LO: 1570 if rv&sym.RV_CHECK_OVERFLOW != 0 { 1571 // Whether to check for signed or unsigned 1572 // overflow depends on the instruction 1573 var o1 uint32 1574 if target.IsBigEndian() { 1575 o1 = binary.BigEndian.Uint32(p[r.Off()-2:]) 1576 } else { 1577 o1 = binary.LittleEndian.Uint32(p[r.Off():]) 1578 } 1579 switch o1 >> 26 { 1580 case 24, // ori 1581 26, // xori 1582 28: // andi 1583 if t>>16 != 0 { 1584 goto overflow 1585 } 1586 1587 default: 1588 if int64(int16(t)) != t { 1589 goto overflow 1590 } 1591 } 1592 } 1593 1594 return int64(int16(t)) 1595 1596 case sym.RV_POWER_HA: 1597 t += 0x8000 1598 fallthrough 1599 1600 // Fallthrough 1601 case sym.RV_POWER_HI: 1602 t >>= 16 1603 1604 if rv&sym.RV_CHECK_OVERFLOW != 0 { 1605 // Whether to check for signed or unsigned 1606 // overflow depends on the instruction 1607 var o1 uint32 1608 if target.IsBigEndian() { 1609 o1 = binary.BigEndian.Uint32(p[r.Off()-2:]) 1610 } else { 1611 o1 = binary.LittleEndian.Uint32(p[r.Off():]) 1612 } 1613 switch o1 >> 26 { 1614 case 25, // oris 1615 27, // xoris 1616 29: // andis 1617 if t>>16 != 0 { 1618 goto overflow 1619 } 1620 1621 default: 1622 if int64(int16(t)) != t { 1623 goto overflow 1624 } 1625 } 1626 } 1627 1628 return int64(int16(t)) 1629 1630 case sym.RV_POWER_DS: 1631 var o1 uint32 1632 if target.IsBigEndian() { 1633 o1 = uint32(binary.BigEndian.Uint16(p[r.Off():])) 1634 } else { 1635 o1 = uint32(binary.LittleEndian.Uint16(p[r.Off():])) 1636 } 1637 if t&3 != 0 { 1638 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t) 1639 } 1640 if (rv&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t { 1641 goto overflow 1642 } 1643 return int64(o1)&0x3 | int64(int16(t)) 1644 } 1645 1646 overflow: 1647 ldr.Errorf(s, "relocation for %s+%d is too big: %d", ldr.SymName(rs), r.Off(), t) 1648 return t 1649 } 1650 1651 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) { 1652 switch r.Type() { 1653 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE, objabi.R_POWER_TLS_IE_PCREL34, objabi.R_POWER_TLS_LE_TPREL34, objabi.R_CALLPOWER: 1654 return ld.ExtrelocSimple(ldr, r), true 1655 case objabi.R_ADDRPOWER, 1656 objabi.R_ADDRPOWER_DS, 1657 objabi.R_ADDRPOWER_TOCREL, 1658 objabi.R_ADDRPOWER_TOCREL_DS, 1659 objabi.R_ADDRPOWER_GOT, 1660 objabi.R_ADDRPOWER_GOT_PCREL34, 1661 objabi.R_ADDRPOWER_PCREL, 1662 objabi.R_ADDRPOWER_D34, 1663 objabi.R_ADDRPOWER_PCREL34: 1664 return ld.ExtrelocViaOuterSym(ldr, r, s), true 1665 } 1666 return loader.ExtReloc{}, false 1667 } 1668 1669 func addpltsym(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym) { 1670 if ldr.SymPlt(s) >= 0 { 1671 return 1672 } 1673 1674 ld.Adddynsym(ldr, &ctxt.Target, &ctxt.ArchSyms, s) 1675 1676 if ctxt.IsELF { 1677 plt := ldr.MakeSymbolUpdater(ctxt.PLT) 1678 rela := ldr.MakeSymbolUpdater(ctxt.RelaPLT) 1679 if plt.Size() == 0 { 1680 panic("plt is not set up") 1681 } 1682 1683 // Create the glink resolver if necessary 1684 glink := ensureglinkresolver(ctxt, ldr) 1685 1686 // Write symbol resolver stub (just a branch to the 1687 // glink resolver stub) 1688 rel, _ := glink.AddRel(objabi.R_CALLPOWER) 1689 rel.SetOff(int32(glink.Size())) 1690 rel.SetSiz(4) 1691 rel.SetSym(glink.Sym()) 1692 glink.AddUint32(ctxt.Arch, 0x48000000) // b .glink 1693 1694 // In the ppc64 ABI, the dynamic linker is responsible 1695 // for writing the entire PLT. We just need to 1696 // reserve 8 bytes for each PLT entry and generate a 1697 // JMP_SLOT dynamic relocation for it. 1698 // 1699 // TODO(austin): ABI v1 is different 1700 ldr.SetPlt(s, int32(plt.Size())) 1701 1702 plt.Grow(plt.Size() + 8) 1703 plt.SetSize(plt.Size() + 8) 1704 1705 rela.AddAddrPlus(ctxt.Arch, plt.Sym(), int64(ldr.SymPlt(s))) 1706 rela.AddUint64(ctxt.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_PPC64_JMP_SLOT))) 1707 rela.AddUint64(ctxt.Arch, 0) 1708 } else { 1709 ctxt.Errorf(s, "addpltsym: unsupported binary format") 1710 } 1711 } 1712 1713 // Generate the glink resolver stub if necessary and return the .glink section. 1714 func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilder { 1715 glink := ldr.CreateSymForUpdate(".glink", 0) 1716 if glink.Size() != 0 { 1717 return glink 1718 } 1719 1720 // This is essentially the resolver from the ppc64 ELFv2 ABI. 1721 // At entry, r12 holds the address of the symbol resolver stub 1722 // for the target routine and the argument registers hold the 1723 // arguments for the target routine. 1724 // 1725 // PC-rel offsets are computed once the final codesize of the 1726 // resolver is known. 1727 // 1728 // This stub is PIC, so first get the PC of label 1 into r11. 1729 glink.AddUint32(ctxt.Arch, OP_MFLR_R0) // mflr r0 1730 glink.AddUint32(ctxt.Arch, OP_BCL_NIA) // bcl 20,31,1f 1731 glink.AddUint32(ctxt.Arch, 0x7d6802a6) // 1: mflr r11 1732 glink.AddUint32(ctxt.Arch, OP_MTLR_R0) // mtlr r0 1733 1734 // Compute the .plt array index from the entry point address 1735 // into r0. This is computed relative to label 1 above. 1736 glink.AddUint32(ctxt.Arch, 0x38000000) // li r0,-(res_0-1b) 1737 glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12 1738 glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11 1739 glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2 1740 1741 // Load the PC-rel offset of ".plt - 1b", and add it to 1b. 1742 // This is stored after this stub and before the resolvers. 1743 glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,res_0-1b-8(r11) 1744 glink.AddUint32(ctxt.Arch, 0x7d6b6214) // add r11,r11,r12 1745 1746 // Load r12 = dynamic resolver address and r11 = DSO 1747 // identifier from the first two doublewords of the PLT. 1748 glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,0(r11) 1749 glink.AddUint32(ctxt.Arch, 0xe96b0008) // ld r11,8(r11) 1750 1751 // Jump to the dynamic resolver 1752 glink.AddUint32(ctxt.Arch, OP_MTCTR_R12) // mtctr r12 1753 glink.AddUint32(ctxt.Arch, OP_BCTR) // bctr 1754 1755 // Store the PC-rel offset to the PLT 1756 r, _ := glink.AddRel(objabi.R_PCREL) 1757 r.SetSym(ctxt.PLT) 1758 r.SetSiz(8) 1759 r.SetOff(int32(glink.Size())) 1760 r.SetAdd(glink.Size()) // Adjust the offset to be relative to label 1 above. 1761 glink.AddUint64(ctxt.Arch, 0) // The offset to the PLT. 1762 1763 // Resolve PC-rel offsets above now the final size of the stub is known. 1764 res0m1b := glink.Size() - 8 // res_0 - 1b 1765 glink.SetUint32(ctxt.Arch, 16, 0x38000000|uint32(uint16(-res0m1b))) 1766 glink.SetUint32(ctxt.Arch, 32, 0xe98b0000|uint32(uint16(res0m1b-8))) 1767 1768 // The symbol resolvers must immediately follow. 1769 // res_0: 1770 1771 // Add DT_PPC64_GLINK .dynamic entry, which points to 32 bytes 1772 // before the first symbol resolver stub. 1773 du := ldr.MakeSymbolUpdater(ctxt.Dynamic) 1774 ld.Elfwritedynentsymplus(ctxt, du, elf.DT_PPC64_GLINK, glink.Sym(), glink.Size()-32) 1775 1776 return glink 1777 }