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