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 ([email protected]) 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 ([email protected]) 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 31package ppc64 32 33import ( 34 "cmd/internal/objabi" 35 "cmd/internal/sys" 36 "cmd/link/internal/ld" 37 "cmd/link/internal/loader" 38 "cmd/link/internal/sym" 39 "debug/elf" 40 "encoding/binary" 41 "fmt" 42 "internal/buildcfg" 43 "log" 44 "strconv" 45 "strings" 46) 47 48// The build configuration supports PC-relative instructions and relocations (limited to tested targets). 49var hasPCrel = buildcfg.GOPPC64 >= 10 && buildcfg.GOOS == "linux" 50 51const ( 52 // For genstub, the type of stub required by the caller. 53 STUB_TOC = iota 54 STUB_PCREL 55) 56 57var stubStrs = []string{ 58 STUB_TOC: "_callstub_toc", 59 STUB_PCREL: "_callstub_pcrel", 60} 61 62const ( 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. 108func 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 163func 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. 267func 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 376func 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. 448func 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 // This function only becomes reachable now. It has been dropped from 478 // the text section (it was unreachable until now), it needs included. 479 ldr.SetAttrReachable(ts, true) 480 } 481 return ts, firstUse 482} 483 484func gentext(ctxt *ld.Link, ldr *loader.Loader) { 485 if ctxt.DynlinkingGo() { 486 genaddmoduledata(ctxt, ldr) 487 } 488 489 if ctxt.LinkMode == ld.LinkInternal { 490 genstubs(ctxt, ldr) 491 } 492} 493 494// Create a calling stub. The stubType maps directly to the properties listed in the ELFv2 1.5 495// section 4.2.5.3. 496// 497// There are 3 cases today (as paraphrased from the ELFv2 document): 498// 499// 1. R2 holds the TOC pointer on entry. The call stub must save R2 into the ELFv2 TOC stack save slot. 500// 501// 2. R2 holds the TOC pointer on entry. The caller has already saved R2 to the TOC stack save slot. 502// 503// 3. R2 does not hold the TOC pointer on entry. The caller has no expectations of R2. 504// 505// Go only needs case 1 and 3 today. Go symbols which have AttrShare set could use case 2, but case 1 always 506// works in those cases too. 507func gencallstub(ctxt *ld.Link, ldr *loader.Loader, stubType int, stub *loader.SymbolBuilder, targ loader.Sym) { 508 plt := ctxt.PLT 509 stub.SetType(sym.STEXT) 510 511 switch stubType { 512 case 1: 513 // Save TOC, then load targ address from PLT using TOC. 514 stub.AddUint32(ctxt.Arch, OP_TOCSAVE) // std r2,24(r1) 515 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ)), objabi.R_ADDRPOWER_TOCREL_DS, 8) 516 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_ADDIS_R12_R2) // addis r12,r2,targ@plt@toc@ha 517 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_LD_R12_R12) // ld r12,targ@plt@toc@l(r12) 518 case 3: 519 // No TOC needs to be saved, but the stub may need to position-independent. 520 if buildcfg.GOPPC64 >= 10 { 521 // Power10 is supported, load targ address into r12 using PCrel load. 522 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ)), objabi.R_ADDRPOWER_PCREL34, 8) 523 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_PLD_PFX_PCREL) 524 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_PLD_SFX_R12) // pld r12, targ@plt 525 } else if !isLinkingPIC(ctxt) { 526 // This stub doesn't need to be PIC. Load targ address from the PLT via its absolute address. 527 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ)), objabi.R_ADDRPOWER_DS, 8) 528 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_LIS_R12) // lis r12,targ@plt@ha 529 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_LD_R12_R12) // ld r12,targ@plt@l(r12) 530 } else { 531 // Generate a PIC stub. This is ugly as the stub must determine its location using 532 // POWER8 or older instruction. These stubs are likely the combination of using 533 // GOPPC64 < 8 and linking external objects built with CFLAGS="... -mcpu=power10 ..." 534 stub.AddUint32(ctxt.Arch, OP_MFLR_R0) // mflr r0 535 stub.AddUint32(ctxt.Arch, OP_BCL_NIA) // bcl 20,31,1f 536 stub.AddUint32(ctxt.Arch, OP_MFLR_R12) // 1: mflr r12 (r12 is the address of this instruction) 537 stub.AddUint32(ctxt.Arch, OP_MTLR_R0) // mtlr r0 538 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ))+8, objabi.R_ADDRPOWER_PCREL, 8) 539 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_ADDIS_R12_R12) // addis r12,(targ@plt - 1b) + 8 540 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_ADDI_R12_R12) // addi r12,(targ@plt - 1b) + 12 541 stub.AddUint32(ctxt.Arch, OP_LD_R12_R12) // ld r12, 0(r12) 542 } 543 default: 544 log.Fatalf("gencallstub does not support ELFv2 ABI property %d", stubType) 545 } 546 547 // Jump to the loaded pointer 548 stub.AddUint32(ctxt.Arch, OP_MTCTR_R12) // mtctr r12 549 stub.AddUint32(ctxt.Arch, OP_BCTR) // bctr 550} 551 552// Rewrite the instruction at offset into newinsn. Also, verify the 553// existing instruction under mask matches the check value. 554func rewritetoinsn(target *ld.Target, ldr *loader.Loader, su *loader.SymbolBuilder, offset int64, mask, check, newinsn uint32) { 555 su.MakeWritable() 556 op := target.Arch.ByteOrder.Uint32(su.Data()[offset:]) 557 if op&mask != check { 558 ldr.Errorf(su.Sym(), "Rewrite offset 0x%x to 0x%08X failed check (0x%08X&0x%08X != 0x%08X)", offset, newinsn, op, mask, check) 559 } 560 su.SetUint32(target.Arch, offset, newinsn) 561} 562 563// Rewrite the instruction at offset into a hardware nop instruction. Also, verify the 564// existing instruction under mask matches the check value. 565func rewritetonop(target *ld.Target, ldr *loader.Loader, su *loader.SymbolBuilder, offset int64, mask, check uint32) { 566 rewritetoinsn(target, ldr, su, offset, mask, check, OP_NOP) 567} 568 569func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool { 570 if target.IsElf() { 571 return addelfdynrel(target, ldr, syms, s, r, rIdx) 572 } else if target.IsAIX() { 573 return ld.Xcoffadddynrel(target, ldr, syms, s, r, rIdx) 574 } 575 return false 576} 577 578func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool { 579 targ := r.Sym() 580 var targType sym.SymKind 581 if targ != 0 { 582 targType = ldr.SymType(targ) 583 } 584 585 switch r.Type() { 586 default: 587 if r.Type() >= objabi.ElfRelocOffset { 588 ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type())) 589 return false 590 } 591 592 // Handle relocations found in ELF object files. 593 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24_NOTOC), 594 objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24_P9NOTOC): 595 su := ldr.MakeSymbolUpdater(s) 596 su.SetRelocType(rIdx, objabi.R_CALLPOWER) 597 598 if targType == sym.SDYNIMPORT { 599 // Should have been handled in elfsetupplt 600 ldr.Errorf(s, "unexpected R_PPC64_REL24_NOTOC/R_PPC64_REL24_P9NOTOC for dyn import") 601 } 602 return true 603 604 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24): 605 su := ldr.MakeSymbolUpdater(s) 606 su.SetRelocType(rIdx, objabi.R_CALLPOWER) 607 608 // This is a local call, so the caller isn't setting 609 // up r12 and r2 is the same for the caller and 610 // callee. Hence, we need to go to the local entry 611 // point. (If we don't do this, the callee will try 612 // to use r12 to compute r2.) 613 localEoffset := int64(ldr.SymLocalentry(targ)) 614 if localEoffset == 1 { 615 ldr.Errorf(s, "Unsupported NOTOC call to %s", targ) 616 } 617 su.SetRelocAdd(rIdx, r.Add()+localEoffset) 618 619 if targType == sym.SDYNIMPORT { 620 // Should have been handled in genstubs 621 ldr.Errorf(s, "unexpected R_PPC64_REL24 for dyn import") 622 } 623 624 return true 625 626 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PCREL34): 627 su := ldr.MakeSymbolUpdater(s) 628 su.SetRelocType(rIdx, objabi.R_ADDRPOWER_PCREL34) 629 return true 630 631 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_GOT_PCREL34): 632 su := ldr.MakeSymbolUpdater(s) 633 su.SetRelocType(rIdx, objabi.R_ADDRPOWER_PCREL34) 634 if targType != sym.STEXT { 635 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_PPC64_GLOB_DAT)) 636 su.SetRelocSym(rIdx, syms.GOT) 637 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ))) 638 } else { 639 // The address of targ is known at link time. Rewrite to "pla rt,targ" from "pld rt,targ@got" 640 rewritetoinsn(target, ldr, su, int64(r.Off()), MASK_PLD_PFX, OP_PLD_PFX_PCREL, OP_PLA_PFX) 641 pla_sfx := target.Arch.ByteOrder.Uint32(su.Data()[r.Off()+4:])&MASK_PLD_RT | OP_PLA_SFX 642 rewritetoinsn(target, ldr, su, int64(r.Off()+4), MASK_PLD_SFX, OP_PLD_SFX, pla_sfx) 643 } 644 return true 645 646 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32): 647 su := ldr.MakeSymbolUpdater(s) 648 su.SetRelocType(rIdx, objabi.R_PCREL) 649 su.SetRelocAdd(rIdx, r.Add()+4) 650 651 if targType == sym.SDYNIMPORT { 652 ldr.Errorf(s, "unexpected R_PPC_REL32 for dyn import") 653 } 654 655 return true 656 657 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_ADDR64): 658 su := ldr.MakeSymbolUpdater(s) 659 su.SetRelocType(rIdx, objabi.R_ADDR) 660 if targType == sym.SDYNIMPORT { 661 // These happen in .toc sections 662 ld.Adddynsym(ldr, target, syms, targ) 663 664 rela := ldr.MakeSymbolUpdater(syms.Rela) 665 rela.AddAddrPlus(target.Arch, s, int64(r.Off())) 666 rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_PPC64_ADDR64))) 667 rela.AddUint64(target.Arch, uint64(r.Add())) 668 su.SetRelocType(rIdx, objabi.ElfRelocOffset) // ignore during relocsym 669 } else if target.IsPIE() && target.IsInternal() { 670 // For internal linking PIE, this R_ADDR relocation cannot 671 // be resolved statically. We need to generate a dynamic 672 // relocation. Let the code below handle it. 673 break 674 } 675 return true 676 677 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16): 678 su := ldr.MakeSymbolUpdater(s) 679 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 680 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO|sym.RV_CHECK_OVERFLOW) 681 return true 682 683 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO): 684 su := ldr.MakeSymbolUpdater(s) 685 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 686 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO) 687 return true 688 689 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA): 690 su := ldr.MakeSymbolUpdater(s) 691 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 692 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW) 693 return true 694 695 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI): 696 su := ldr.MakeSymbolUpdater(s) 697 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 698 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW) 699 return true 700 701 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS): 702 su := ldr.MakeSymbolUpdater(s) 703 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 704 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS|sym.RV_CHECK_OVERFLOW) 705 return true 706 707 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS): 708 su := ldr.MakeSymbolUpdater(s) 709 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 710 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS) 711 return true 712 713 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO): 714 su := ldr.MakeSymbolUpdater(s) 715 su.SetRelocType(rIdx, objabi.R_PCREL) 716 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO) 717 su.SetRelocAdd(rIdx, r.Add()+2) // Compensate for relocation size of 2 718 return true 719 720 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI): 721 su := ldr.MakeSymbolUpdater(s) 722 su.SetRelocType(rIdx, objabi.R_PCREL) 723 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW) 724 su.SetRelocAdd(rIdx, r.Add()+2) 725 return true 726 727 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA): 728 su := ldr.MakeSymbolUpdater(s) 729 su.SetRelocType(rIdx, objabi.R_PCREL) 730 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW) 731 su.SetRelocAdd(rIdx, r.Add()+2) 732 return true 733 734 // When compiling with gcc's -fno-plt option (no PLT), the following code and relocation 735 // sequences may be present to call an external function: 736 // 737 // 1. addis Rx,foo@R_PPC64_PLT16_HA 738 // 2. ld 12,foo@R_PPC64_PLT16_LO_DS(Rx) 739 // 3. mtctr 12 ; foo@R_PPC64_PLTSEQ 740 // 4. bctrl ; foo@R_PPC64_PLTCALL 741 // 5. ld r2,24(r1) 742 // 743 // Note, 5 is required to follow the R_PPC64_PLTCALL. Similarly, relocations targeting 744 // instructions 3 and 4 are zero sized informational relocations. 745 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PLT16_HA), 746 objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PLT16_LO_DS): 747 su := ldr.MakeSymbolUpdater(s) 748 isPLT16_LO_DS := r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_PPC64_PLT16_LO_DS) 749 if isPLT16_LO_DS { 750 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS) 751 } else { 752 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW) 753 } 754 su.SetRelocType(rIdx, objabi.R_POWER_TOC) 755 if targType == sym.SDYNIMPORT { 756 // This is an external symbol, make space in the GOT and retarget the reloc. 757 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_PPC64_GLOB_DAT)) 758 su.SetRelocSym(rIdx, syms.GOT) 759 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ))) 760 } else if targType == sym.STEXT { 761 if isPLT16_LO_DS { 762 // Expect an ld opcode to nop 763 rewritetonop(target, ldr, su, int64(r.Off()), MASK_OP_LD, OP_LD) 764 } else { 765 // Expect an addis opcode to nop 766 rewritetonop(target, ldr, su, int64(r.Off()), MASK_OP_ADDIS, OP_ADDIS) 767 } 768 // And we can ignore this reloc now. 769 su.SetRelocType(rIdx, objabi.ElfRelocOffset) 770 } else { 771 ldr.Errorf(s, "unexpected PLT relocation target symbol type %s", targType.String()) 772 } 773 return true 774 } 775 776 // Handle references to ELF symbols from our own object files. 777 relocs := ldr.Relocs(s) 778 r = relocs.At(rIdx) 779 780 switch r.Type() { 781 case objabi.R_ADDR: 782 if ldr.SymType(s) == sym.STEXT { 783 log.Fatalf("R_ADDR relocation in text symbol %s is unsupported\n", ldr.SymName(s)) 784 } 785 if target.IsPIE() && target.IsInternal() { 786 // When internally linking, generate dynamic relocations 787 // for all typical R_ADDR relocations. The exception 788 // are those R_ADDR that are created as part of generating 789 // the dynamic relocations and must be resolved statically. 790 // 791 // There are three phases relevant to understanding this: 792 // 793 // dodata() // we are here 794 // address() // symbol address assignment 795 // reloc() // resolution of static R_ADDR relocs 796 // 797 // At this point symbol addresses have not been 798 // assigned yet (as the final size of the .rela section 799 // will affect the addresses), and so we cannot write 800 // the Elf64_Rela.r_offset now. Instead we delay it 801 // until after the 'address' phase of the linker is 802 // complete. We do this via Addaddrplus, which creates 803 // a new R_ADDR relocation which will be resolved in 804 // the 'reloc' phase. 805 // 806 // These synthetic static R_ADDR relocs must be skipped 807 // now, or else we will be caught in an infinite loop 808 // of generating synthetic relocs for our synthetic 809 // relocs. 810 // 811 // Furthermore, the rela sections contain dynamic 812 // relocations with R_ADDR relocations on 813 // Elf64_Rela.r_offset. This field should contain the 814 // symbol offset as determined by reloc(), not the 815 // final dynamically linked address as a dynamic 816 // relocation would provide. 817 switch ldr.SymName(s) { 818 case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic": 819 return false 820 } 821 } else { 822 // Either internally linking a static executable, 823 // in which case we can resolve these relocations 824 // statically in the 'reloc' phase, or externally 825 // linking, in which case the relocation will be 826 // prepared in the 'reloc' phase and passed to the 827 // external linker in the 'asmb' phase. 828 if ldr.SymType(s) != sym.SDATA && ldr.SymType(s) != sym.SRODATA { 829 break 830 } 831 } 832 // Generate R_PPC64_RELATIVE relocations for best 833 // efficiency in the dynamic linker. 834 // 835 // As noted above, symbol addresses have not been 836 // assigned yet, so we can't generate the final reloc 837 // entry yet. We ultimately want: 838 // 839 // r_offset = s + r.Off 840 // r_info = R_PPC64_RELATIVE 841 // r_addend = targ + r.Add 842 // 843 // The dynamic linker will set *offset = base address + 844 // addend. 845 // 846 // AddAddrPlus is used for r_offset and r_addend to 847 // generate new R_ADDR relocations that will update 848 // these fields in the 'reloc' phase. 849 rela := ldr.MakeSymbolUpdater(syms.Rela) 850 rela.AddAddrPlus(target.Arch, s, int64(r.Off())) 851 if r.Siz() == 8 { 852 rela.AddUint64(target.Arch, elf.R_INFO(0, uint32(elf.R_PPC64_RELATIVE))) 853 } else { 854 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ)) 855 } 856 rela.AddAddrPlus(target.Arch, targ, int64(r.Add())) 857 858 // Not mark r done here. So we still apply it statically, 859 // so in the file content we'll also have the right offset 860 // to the relocation target. So it can be examined statically 861 // (e.g. go version). 862 return true 863 } 864 865 return false 866} 867 868func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool { 869 rs := r.Xsym 870 871 emitReloc := func(v uint16, off uint64) { 872 out.Write64(uint64(sectoff) + off) 873 out.Write32(uint32(ldr.SymDynid(rs))) 874 out.Write16(v) 875 } 876 877 var v uint16 878 switch r.Type { 879 default: 880 return false 881 case objabi.R_ADDR, objabi.R_DWARFSECREF: 882 v = ld.XCOFF_R_POS 883 if r.Size == 4 { 884 v |= 0x1F << 8 885 } else { 886 v |= 0x3F << 8 887 } 888 emitReloc(v, 0) 889 case objabi.R_ADDRPOWER_TOCREL: 890 case objabi.R_ADDRPOWER_TOCREL_DS: 891 emitReloc(ld.XCOFF_R_TOCU|(0x0F<<8), 2) 892 emitReloc(ld.XCOFF_R_TOCL|(0x0F<<8), 6) 893 case objabi.R_POWER_TLS_LE: 894 // This only supports 16b relocations. It is fixed up in archreloc. 895 emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2) 896 case objabi.R_CALLPOWER: 897 if r.Size != 4 { 898 return false 899 } 900 emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0) 901 case objabi.R_XCOFFREF: 902 emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0) 903 } 904 return true 905} 906 907func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool { 908 // Beware that bit0~bit15 start from the third byte of an instruction in Big-Endian machines. 909 rt := r.Type 910 if rt == objabi.R_ADDR || rt == objabi.R_POWER_TLS || rt == objabi.R_CALLPOWER || rt == objabi.R_DWARFSECREF { 911 } else { 912 if ctxt.Arch.ByteOrder == binary.BigEndian { 913 sectoff += 2 914 } 915 } 916 out.Write64(uint64(sectoff)) 917 918 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym) 919 switch rt { 920 default: 921 return false 922 case objabi.R_ADDR, objabi.R_DWARFSECREF: 923 switch r.Size { 924 case 4: 925 out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32) 926 case 8: 927 out.Write64(uint64(elf.R_PPC64_ADDR64) | uint64(elfsym)<<32) 928 default: 929 return false 930 } 931 case objabi.R_ADDRPOWER_D34: 932 out.Write64(uint64(elf.R_PPC64_D34) | uint64(elfsym)<<32) 933 case objabi.R_ADDRPOWER_PCREL34: 934 out.Write64(uint64(elf.R_PPC64_PCREL34) | uint64(elfsym)<<32) 935 case objabi.R_POWER_TLS: 936 out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32) 937 case objabi.R_POWER_TLS_LE: 938 out.Write64(uint64(elf.R_PPC64_TPREL16_HA) | uint64(elfsym)<<32) 939 out.Write64(uint64(r.Xadd)) 940 out.Write64(uint64(sectoff + 4)) 941 out.Write64(uint64(elf.R_PPC64_TPREL16_LO) | uint64(elfsym)<<32) 942 case objabi.R_POWER_TLS_LE_TPREL34: 943 out.Write64(uint64(elf.R_PPC64_TPREL34) | uint64(elfsym)<<32) 944 case objabi.R_POWER_TLS_IE_PCREL34: 945 out.Write64(uint64(elf.R_PPC64_GOT_TPREL_PCREL34) | uint64(elfsym)<<32) 946 case objabi.R_POWER_TLS_IE: 947 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32) 948 out.Write64(uint64(r.Xadd)) 949 out.Write64(uint64(sectoff + 4)) 950 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_LO_DS) | uint64(elfsym)<<32) 951 case objabi.R_ADDRPOWER: 952 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32) 953 out.Write64(uint64(r.Xadd)) 954 out.Write64(uint64(sectoff + 4)) 955 out.Write64(uint64(elf.R_PPC64_ADDR16_LO) | uint64(elfsym)<<32) 956 case objabi.R_ADDRPOWER_DS: 957 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32) 958 out.Write64(uint64(r.Xadd)) 959 out.Write64(uint64(sectoff + 4)) 960 out.Write64(uint64(elf.R_PPC64_ADDR16_LO_DS) | uint64(elfsym)<<32) 961 case objabi.R_ADDRPOWER_GOT: 962 out.Write64(uint64(elf.R_PPC64_GOT16_HA) | uint64(elfsym)<<32) 963 out.Write64(uint64(r.Xadd)) 964 out.Write64(uint64(sectoff + 4)) 965 out.Write64(uint64(elf.R_PPC64_GOT16_LO_DS) | uint64(elfsym)<<32) 966 case objabi.R_ADDRPOWER_GOT_PCREL34: 967 out.Write64(uint64(elf.R_PPC64_GOT_PCREL34) | uint64(elfsym)<<32) 968 case objabi.R_ADDRPOWER_PCREL: 969 out.Write64(uint64(elf.R_PPC64_REL16_HA) | uint64(elfsym)<<32) 970 out.Write64(uint64(r.Xadd)) 971 out.Write64(uint64(sectoff + 4)) 972 out.Write64(uint64(elf.R_PPC64_REL16_LO) | uint64(elfsym)<<32) 973 r.Xadd += 4 974 case objabi.R_ADDRPOWER_TOCREL: 975 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32) 976 out.Write64(uint64(r.Xadd)) 977 out.Write64(uint64(sectoff + 4)) 978 out.Write64(uint64(elf.R_PPC64_TOC16_LO) | uint64(elfsym)<<32) 979 case objabi.R_ADDRPOWER_TOCREL_DS: 980 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32) 981 out.Write64(uint64(r.Xadd)) 982 out.Write64(uint64(sectoff + 4)) 983 out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32) 984 case objabi.R_CALLPOWER: 985 if r.Size != 4 { 986 return false 987 } 988 if !hasPCrel { 989 out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32) 990 } else { 991 // TOC is not used in PCrel compiled Go code. 992 out.Write64(uint64(elf.R_PPC64_REL24_NOTOC) | uint64(elfsym)<<32) 993 } 994 995 } 996 out.Write64(uint64(r.Xadd)) 997 998 return true 999} 1000 1001func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, got *loader.SymbolBuilder, dynamic loader.Sym) { 1002 if plt.Size() == 0 { 1003 // The dynamic linker stores the address of the 1004 // dynamic resolver and the DSO identifier in the two 1005 // doublewords at the beginning of the .plt section 1006 // before the PLT array. Reserve space for these. 1007 plt.SetSize(16) 1008 } 1009} 1010 1011func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool { 1012 return false 1013} 1014 1015// Return the value of .TOC. for symbol s 1016func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 { 1017 v := ldr.SymVersion(s) 1018 if out := ldr.OuterSym(s); out != 0 { 1019 v = ldr.SymVersion(out) 1020 } 1021 1022 toc := syms.DotTOC[v] 1023 if toc == 0 { 1024 ldr.Errorf(s, "TOC-relative relocation in object without .TOC.") 1025 return 0 1026 } 1027 1028 return ldr.SymValue(toc) 1029} 1030 1031// archreloctoc relocates a TOC relative symbol. 1032func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 { 1033 rs := r.Sym() 1034 var o1, o2 uint32 1035 var t int64 1036 useAddi := false 1037 1038 if target.IsBigEndian() { 1039 o1 = uint32(val >> 32) 1040 o2 = uint32(val) 1041 } else { 1042 o1 = uint32(val) 1043 o2 = uint32(val >> 32) 1044 } 1045 1046 // On AIX, TOC data accesses are always made indirectly against R2 (a sequence of addis+ld+load/store). If the 1047 // The target of the load is known, the sequence can be written into addis+addi+load/store. On Linux, 1048 // TOC data accesses are always made directly against R2 (e.g addis+load/store). 1049 if target.IsAIX() { 1050 if !strings.HasPrefix(ldr.SymName(rs), "TOC.") { 1051 ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor") 1052 } 1053 relocs := ldr.Relocs(rs) 1054 tarSym := relocs.At(0).Sym() 1055 1056 if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata { 1057 t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC) 1058 // change ld to addi in the second instruction 1059 o2 = (o2 & 0x03FF0000) | 0xE<<26 1060 useAddi = true 1061 } else { 1062 t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC) 1063 } 1064 } else { 1065 t = ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s) 1066 } 1067 1068 if t != int64(int32(t)) { 1069 ldr.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", ldr.SymName(s), rs, t) 1070 } 1071 1072 if t&0x8000 != 0 { 1073 t += 0x10000 1074 } 1075 1076 o1 |= uint32((t >> 16) & 0xFFFF) 1077 1078 switch r.Type() { 1079 case objabi.R_ADDRPOWER_TOCREL_DS: 1080 if useAddi { 1081 o2 |= uint32(t) & 0xFFFF 1082 } else { 1083 if t&3 != 0 { 1084 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs)) 1085 } 1086 o2 |= uint32(t) & 0xFFFC 1087 } 1088 case objabi.R_ADDRPOWER_TOCREL: 1089 o2 |= uint32(t) & 0xffff 1090 default: 1091 return -1 1092 } 1093 1094 if target.IsBigEndian() { 1095 return int64(o1)<<32 | int64(o2) 1096 } 1097 return int64(o2)<<32 | int64(o1) 1098} 1099 1100// archrelocaddr relocates a symbol address. 1101// This code is for linux only. 1102func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 { 1103 rs := r.Sym() 1104 if target.IsAIX() { 1105 ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs)) 1106 } 1107 o1, o2 := unpackInstPair(target, val) 1108 1109 // Verify resulting address fits within a 31 bit (2GB) address space. 1110 // This is a restriction arising from the usage of lis (HA) + d-form 1111 // (LO) instruction sequences used to implement absolute relocations 1112 // on PPC64 prior to ISA 3.1 (P10). For consistency, maintain this 1113 // restriction for ISA 3.1 unless it becomes problematic. 1114 t := ldr.SymAddr(rs) + r.Add() 1115 if t < 0 || t >= 1<<31 { 1116 ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs)) 1117 } 1118 1119 // Note, relocations imported from external objects may not have cleared bits 1120 // within a relocatable field. They need cleared before applying the relocation. 1121 switch r.Type() { 1122 case objabi.R_ADDRPOWER_PCREL34: 1123 // S + A - P 1124 t -= (ldr.SymValue(s) + int64(r.Off())) 1125 o1 &^= 0x3ffff 1126 o2 &^= 0x0ffff 1127 o1 |= computePrefix34HI(t) 1128 o2 |= computeLO(int32(t)) 1129 case objabi.R_ADDRPOWER_D34: 1130 o1 &^= 0x3ffff 1131 o2 &^= 0x0ffff 1132 o1 |= computePrefix34HI(t) 1133 o2 |= computeLO(int32(t)) 1134 case objabi.R_ADDRPOWER: 1135 o1 &^= 0xffff 1136 o2 &^= 0xffff 1137 o1 |= computeHA(int32(t)) 1138 o2 |= computeLO(int32(t)) 1139 case objabi.R_ADDRPOWER_DS: 1140 o1 &^= 0xffff 1141 o2 &^= 0xfffc 1142 o1 |= computeHA(int32(t)) 1143 o2 |= computeLO(int32(t)) 1144 if t&3 != 0 { 1145 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs)) 1146 } 1147 default: 1148 return -1 1149 } 1150 1151 return packInstPair(target, o1, o2) 1152} 1153 1154// Determine if the code was compiled so that the TOC register R2 is initialized and maintained. 1155func r2Valid(ctxt *ld.Link) bool { 1156 return isLinkingPIC(ctxt) 1157} 1158 1159// Determine if this is linking a position-independent binary. 1160func isLinkingPIC(ctxt *ld.Link) bool { 1161 switch ctxt.BuildMode { 1162 case ld.BuildModeCArchive, ld.BuildModeCShared, ld.BuildModePIE, ld.BuildModeShared, ld.BuildModePlugin: 1163 return true 1164 } 1165 // -linkshared option 1166 return ctxt.IsSharedGoLink() 1167} 1168 1169// resolve direct jump relocation r in s, and add trampoline if necessary. 1170func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) { 1171 1172 // Trampolines are created if the branch offset is too large and the linker cannot insert a call stub to handle it. 1173 // For internal linking, trampolines are always created for long calls. 1174 // For external linking, the linker can insert a call stub to handle a long call, but depends on having the TOC address in 1175 // r2. For those build modes with external linking where the TOC address is not maintained in r2, trampolines must be created. 1176 if ctxt.IsExternal() && r2Valid(ctxt) { 1177 // The TOC pointer is valid. The external linker will insert trampolines. 1178 return 1179 } 1180 1181 relocs := ldr.Relocs(s) 1182 r := relocs.At(ri) 1183 var t int64 1184 // ldr.SymValue(rs) == 0 indicates a cross-package jump to a function that is not yet 1185 // laid out. Conservatively use a trampoline. This should be rare, as we lay out packages 1186 // in dependency order. 1187 if ldr.SymValue(rs) != 0 { 1188 t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) 1189 } 1190 switch r.Type() { 1191 case objabi.R_CALLPOWER: 1192 1193 // If branch offset is too far then create a trampoline. 1194 1195 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)) { 1196 var tramp loader.Sym 1197 for i := 0; ; i++ { 1198 1199 // Using r.Add as part of the name is significant in functions like duffzero where the call 1200 // target is at some offset within the function. Calls to duff+8 and duff+256 must appear as 1201 // distinct trampolines. 1202 1203 oName := ldr.SymName(rs) 1204 name := oName 1205 if r.Add() == 0 { 1206 name += fmt.Sprintf("-tramp%d", i) 1207 } else { 1208 name += fmt.Sprintf("%+x-tramp%d", r.Add(), i) 1209 } 1210 1211 // Look up the trampoline in case it already exists 1212 1213 tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs))) 1214 if oName == "runtime.deferreturn" { 1215 ldr.SetIsDeferReturnTramp(tramp, true) 1216 } 1217 if ldr.SymValue(tramp) == 0 { 1218 break 1219 } 1220 // Note, the trampoline is always called directly. The addend of the original relocation is accounted for in the 1221 // trampoline itself. 1222 t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off())) 1223 1224 // With internal linking, the trampoline can be used if it is not too far. 1225 // With external linking, the trampoline must be in this section for it to be reused. 1226 if (ctxt.IsInternal() && int64(int32(t<<6)>>6) == t) || (ctxt.IsExternal() && ldr.SymSect(s) == ldr.SymSect(tramp)) { 1227 break 1228 } 1229 } 1230 if ldr.SymType(tramp) == 0 { 1231 trampb := ldr.MakeSymbolUpdater(tramp) 1232 ctxt.AddTramp(trampb) 1233 gentramp(ctxt, ldr, trampb, rs, r.Add()) 1234 } 1235 sb := ldr.MakeSymbolUpdater(s) 1236 relocs := sb.Relocs() 1237 r := relocs.At(ri) 1238 r.SetSym(tramp) 1239 r.SetAdd(0) // This was folded into the trampoline target address 1240 } 1241 default: 1242 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type())) 1243 } 1244} 1245 1246func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) { 1247 tramp.SetSize(16) // 4 instructions 1248 P := make([]byte, tramp.Size()) 1249 var o1, o2 uint32 1250 1251 // ELFv2 save/restore functions use R0/R12 in special ways, therefore trampolines 1252 // as generated here will not always work correctly. 1253 if strings.HasPrefix(ldr.SymName(target), "runtime.elf_") { 1254 log.Fatalf("Internal linker does not support trampolines to ELFv2 ABI"+ 1255 " register save/restore function %s", ldr.SymName(target)) 1256 } 1257 1258 if ctxt.IsAIX() { 1259 // On AIX, the address is retrieved with a TOC symbol. 1260 // For internal linking, the "Linux" way might still be used. 1261 // However, all text symbols are accessed with a TOC symbol as 1262 // text relocations aren't supposed to be possible. 1263 // So, keep using the external linking way to be more AIX friendly. 1264 o1 = uint32(OP_ADDIS_R12_R2) // addis r12, r2, toctargetaddr hi 1265 o2 = uint32(OP_LD_R12_R12) // ld r12, r12, toctargetaddr lo 1266 1267 toctramp := ldr.CreateSymForUpdate("TOC."+ldr.SymName(tramp.Sym()), 0) 1268 toctramp.SetType(sym.SXCOFFTOC) 1269 toctramp.AddAddrPlus(ctxt.Arch, target, offset) 1270 1271 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_TOCREL_DS) 1272 r.SetOff(0) 1273 r.SetSiz(8) // generates 2 relocations: HA + LO 1274 r.SetSym(toctramp.Sym()) 1275 } else if hasPCrel { 1276 // pla r12, addr (PCrel). This works for static or PIC, with or without a valid TOC pointer. 1277 o1 = uint32(OP_PLA_PFX) 1278 o2 = uint32(OP_PLA_SFX_R12) // pla r12, addr 1279 1280 // The trampoline's position is not known yet, insert a relocation. 1281 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_PCREL34) 1282 r.SetOff(0) 1283 r.SetSiz(8) // This spans 2 words. 1284 r.SetSym(target) 1285 r.SetAdd(offset) 1286 } else { 1287 // Used for default build mode for an executable 1288 // Address of the call target is generated using 1289 // relocation and doesn't depend on r2 (TOC). 1290 o1 = uint32(OP_LIS_R12) // lis r12,targetaddr hi 1291 o2 = uint32(OP_ADDI_R12_R12) // addi r12,r12,targetaddr lo 1292 1293 t := ldr.SymValue(target) 1294 if t == 0 || r2Valid(ctxt) || ctxt.IsExternal() { 1295 // Target address is unknown, generate relocations 1296 r, _ := tramp.AddRel(objabi.R_ADDRPOWER) 1297 if r2Valid(ctxt) { 1298 // Use a TOC relative address if R2 holds the TOC pointer 1299 o1 |= uint32(2 << 16) // Transform lis r31,ha into addis r31,r2,ha 1300 r.SetType(objabi.R_ADDRPOWER_TOCREL) 1301 } 1302 r.SetOff(0) 1303 r.SetSiz(8) // generates 2 relocations: HA + LO 1304 r.SetSym(target) 1305 r.SetAdd(offset) 1306 } else { 1307 // The target address is known, resolve it 1308 t += offset 1309 o1 |= (uint32(t) + 0x8000) >> 16 // HA 1310 o2 |= uint32(t) & 0xFFFF // LO 1311 } 1312 } 1313 1314 o3 := uint32(OP_MTCTR_R12) // mtctr r12 1315 o4 := uint32(OP_BCTR) // bctr 1316 ctxt.Arch.ByteOrder.PutUint32(P, o1) 1317 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2) 1318 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3) 1319 ctxt.Arch.ByteOrder.PutUint32(P[12:], o4) 1320 tramp.SetData(P) 1321} 1322 1323// Unpack a pair of 32 bit instruction words from 1324// a 64 bit relocation into instN and instN+1 in endian order. 1325func unpackInstPair(target *ld.Target, r int64) (uint32, uint32) { 1326 if target.IsBigEndian() { 1327 return uint32(r >> 32), uint32(r) 1328 } 1329 return uint32(r), uint32(r >> 32) 1330} 1331 1332// Pack a pair of 32 bit instruction words o1, o2 into 64 bit relocation 1333// in endian order. 1334func packInstPair(target *ld.Target, o1, o2 uint32) int64 { 1335 if target.IsBigEndian() { 1336 return (int64(o1) << 32) | int64(o2) 1337 } 1338 return int64(o1) | (int64(o2) << 32) 1339} 1340 1341// Compute the high-adjusted value (always a signed 32b value) per the ELF ABI. 1342// The returned value is always 0 <= x <= 0xFFFF. 1343func computeHA(val int32) uint32 { 1344 return uint32(uint16((val + 0x8000) >> 16)) 1345} 1346 1347// Compute the low value (the lower 16 bits of any 32b value) per the ELF ABI. 1348// The returned value is always 0 <= x <= 0xFFFF. 1349func computeLO(val int32) uint32 { 1350 return uint32(uint16(val)) 1351} 1352 1353// Compute the high 18 bits of a signed 34b constant. Used to pack the high 18 bits 1354// of a prefix34 relocation field. This assumes the input is already restricted to 1355// 34 bits. 1356func computePrefix34HI(val int64) uint32 { 1357 return uint32((val >> 16) & 0x3FFFF) 1358} 1359 1360func computeTLSLEReloc(target *ld.Target, ldr *loader.Loader, rs, s loader.Sym) int64 { 1361 // The thread pointer points 0x7000 bytes after the start of the 1362 // thread local storage area as documented in section "3.7.2 TLS 1363 // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI 1364 // Specification". 1365 v := ldr.SymValue(rs) - 0x7000 1366 if target.IsAIX() { 1367 // On AIX, the thread pointer points 0x7800 bytes after 1368 // the TLS. 1369 v -= 0x800 1370 } 1371 1372 if int64(int32(v)) != v { 1373 ldr.Errorf(s, "TLS offset out of range %d", v) 1374 } 1375 return v 1376} 1377 1378func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (relocatedOffset int64, nExtReloc int, ok bool) { 1379 rs := r.Sym() 1380 if target.IsExternal() { 1381 // On AIX, relocations (except TLS ones) must be also done to the 1382 // value with the current addresses. 1383 switch rt := r.Type(); rt { 1384 default: 1385 if !target.IsAIX() { 1386 return val, nExtReloc, false 1387 } 1388 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_IE_PCREL34, objabi.R_POWER_TLS_LE_TPREL34, objabi.R_ADDRPOWER_GOT_PCREL34: 1389 nExtReloc = 1 1390 return val, nExtReloc, true 1391 case objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE: 1392 if target.IsAIX() && rt == objabi.R_POWER_TLS_LE { 1393 // Fixup val, an addis/addi pair of instructions, which generate a 32b displacement 1394 // from the threadpointer (R13), into a 16b relocation. XCOFF only supports 16b 1395 // TLS LE relocations. Likewise, verify this is an addis/addi sequence. 1396 const expectedOpcodes = 0x3C00000038000000 1397 const expectedOpmasks = 0xFC000000FC000000 1398 if uint64(val)&expectedOpmasks != expectedOpcodes { 1399 ldr.Errorf(s, "relocation for %s+%d is not an addis/addi pair: %16x", ldr.SymName(rs), r.Off(), uint64(val)) 1400 } 1401 nval := (int64(uint32(0x380d0000)) | val&0x03e00000) << 32 // addi rX, r13, $0 1402 nval |= int64(OP_NOP) // nop 1403 val = nval 1404 nExtReloc = 1 1405 } else { 1406 nExtReloc = 2 1407 } 1408 return val, nExtReloc, true 1409 case objabi.R_ADDRPOWER, 1410 objabi.R_ADDRPOWER_DS, 1411 objabi.R_ADDRPOWER_TOCREL, 1412 objabi.R_ADDRPOWER_TOCREL_DS, 1413 objabi.R_ADDRPOWER_GOT, 1414 objabi.R_ADDRPOWER_PCREL: 1415 nExtReloc = 2 // need two ELF relocations, see elfreloc1 1416 if !target.IsAIX() { 1417 return val, nExtReloc, true 1418 } 1419 case objabi.R_CALLPOWER, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34: 1420 nExtReloc = 1 1421 if !target.IsAIX() { 1422 return val, nExtReloc, true 1423 } 1424 } 1425 } 1426 1427 switch r.Type() { 1428 case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS: 1429 return archreloctoc(ldr, target, syms, r, s, val), nExtReloc, true 1430 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34: 1431 return archrelocaddr(ldr, target, syms, r, s, val), nExtReloc, true 1432 case objabi.R_CALLPOWER: 1433 // Bits 6 through 29 = (S + A - P) >> 2 1434 1435 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) 1436 1437 tgtName := ldr.SymName(rs) 1438 1439 // If we are linking PIE or shared code, non-PCrel golang generated object files have an extra 2 instruction prologue 1440 // to regenerate the TOC pointer from R12. The exception are two special case functions tested below. Note, 1441 // local call offsets for externally generated objects are accounted for when converting into golang relocs. 1442 if !hasPCrel && !ldr.AttrExternal(rs) && ldr.AttrShared(rs) && tgtName != "runtime.duffzero" && tgtName != "runtime.duffcopy" { 1443 // Furthermore, only apply the offset if the target looks like the start of a function call. 1444 if r.Add() == 0 && ldr.SymType(rs) == sym.STEXT { 1445 t += 8 1446 } 1447 } 1448 1449 if t&3 != 0 { 1450 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t) 1451 } 1452 // If branch offset is too far then create a trampoline. 1453 1454 if int64(int32(t<<6)>>6) != t { 1455 ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t) 1456 } 1457 return val | int64(uint32(t)&^0xfc000003), nExtReloc, true 1458 case objabi.R_POWER_TOC: // S + A - .TOC. 1459 return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true 1460 1461 case objabi.R_ADDRPOWER_PCREL: // S + A - P 1462 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off())) 1463 ha, l := unpackInstPair(target, val) 1464 l |= computeLO(int32(t)) 1465 ha |= computeHA(int32(t)) 1466 return packInstPair(target, ha, l), nExtReloc, true 1467 1468 case objabi.R_POWER_TLS: 1469 const OP_ADD = 31<<26 | 266<<1 1470 const MASK_OP_ADD = 0x3F<<26 | 0x1FF<<1 1471 if val&MASK_OP_ADD != OP_ADD { 1472 ldr.Errorf(s, "R_POWER_TLS reloc only supports XO form ADD, not %08X", val) 1473 } 1474 // Verify RB is R13 in ADD RA,RB,RT. 1475 if (val>>11)&0x1F != 13 { 1476 // If external linking is made to support this, it may expect the linker to rewrite RB. 1477 ldr.Errorf(s, "R_POWER_TLS reloc requires R13 in RB (%08X).", uint32(val)) 1478 } 1479 return val, nExtReloc, true 1480 1481 case objabi.R_POWER_TLS_IE: 1482 // Convert TLS_IE relocation to TLS_LE if supported. 1483 if !(target.IsPIE() && target.IsElf()) { 1484 log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s)) 1485 } 1486 1487 // We are an ELF binary, we can safely convert to TLS_LE from: 1488 // addis to, r2, x@got@tprel@ha 1489 // ld to, to, x@got@tprel@l(to) 1490 // 1491 // to TLS_LE by converting to: 1492 // addis to, r0, x@tprel@ha 1493 // addi to, to, x@tprel@l(to) 1494 1495 const OP_MASK = 0x3F << 26 1496 const OP_RA_MASK = 0x1F << 16 1497 // convert r2 to r0, and ld to addi 1498 mask := packInstPair(target, OP_RA_MASK, OP_MASK) 1499 addi_op := packInstPair(target, 0, OP_ADDI) 1500 val &^= mask 1501 val |= addi_op 1502 fallthrough 1503 1504 case objabi.R_POWER_TLS_LE: 1505 v := computeTLSLEReloc(target, ldr, rs, s) 1506 o1, o2 := unpackInstPair(target, val) 1507 o1 |= computeHA(int32(v)) 1508 o2 |= computeLO(int32(v)) 1509 return packInstPair(target, o1, o2), nExtReloc, true 1510 1511 case objabi.R_POWER_TLS_IE_PCREL34: 1512 // Convert TLS_IE relocation to TLS_LE if supported. 1513 if !(target.IsPIE() && target.IsElf()) { 1514 log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s)) 1515 } 1516 1517 // We are an ELF binary, we can safely convert to TLS_LE_TPREL34 from: 1518 // pld rX, x@got@tprel@pcrel 1519 // 1520 // to TLS_LE_TPREL32 by converting to: 1521 // pla rX, x@tprel 1522 1523 const OP_MASK_PFX = 0xFFFFFFFF // Discard prefix word 1524 const OP_MASK = (0x3F << 26) | 0xFFFF // Preserve RT, RA 1525 const OP_PFX = 1<<26 | 2<<24 1526 const OP_PLA = 14 << 26 1527 mask := packInstPair(target, OP_MASK_PFX, OP_MASK) 1528 pla_op := packInstPair(target, OP_PFX, OP_PLA) 1529 val &^= mask 1530 val |= pla_op 1531 fallthrough 1532 1533 case objabi.R_POWER_TLS_LE_TPREL34: 1534 v := computeTLSLEReloc(target, ldr, rs, s) 1535 o1, o2 := unpackInstPair(target, val) 1536 o1 |= computePrefix34HI(v) 1537 o2 |= computeLO(int32(v)) 1538 return packInstPair(target, o1, o2), nExtReloc, true 1539 } 1540 1541 return val, nExtReloc, false 1542} 1543 1544func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc, rv sym.RelocVariant, s loader.Sym, t int64, p []byte) (relocatedOffset int64) { 1545 rs := r.Sym() 1546 switch rv & sym.RV_TYPE_MASK { 1547 default: 1548 ldr.Errorf(s, "unexpected relocation variant %d", rv) 1549 fallthrough 1550 1551 case sym.RV_NONE: 1552 return t 1553 1554 case sym.RV_POWER_LO: 1555 if rv&sym.RV_CHECK_OVERFLOW != 0 { 1556 // Whether to check for signed or unsigned 1557 // overflow depends on the instruction 1558 var o1 uint32 1559 if target.IsBigEndian() { 1560 o1 = binary.BigEndian.Uint32(p[r.Off()-2:]) 1561 } else { 1562 o1 = binary.LittleEndian.Uint32(p[r.Off():]) 1563 } 1564 switch o1 >> 26 { 1565 case 24, // ori 1566 26, // xori 1567 28: // andi 1568 if t>>16 != 0 { 1569 goto overflow 1570 } 1571 1572 default: 1573 if int64(int16(t)) != t { 1574 goto overflow 1575 } 1576 } 1577 } 1578 1579 return int64(int16(t)) 1580 1581 case sym.RV_POWER_HA: 1582 t += 0x8000 1583 fallthrough 1584 1585 // Fallthrough 1586 case sym.RV_POWER_HI: 1587 t >>= 16 1588 1589 if rv&sym.RV_CHECK_OVERFLOW != 0 { 1590 // Whether to check for signed or unsigned 1591 // overflow depends on the instruction 1592 var o1 uint32 1593 if target.IsBigEndian() { 1594 o1 = binary.BigEndian.Uint32(p[r.Off()-2:]) 1595 } else { 1596 o1 = binary.LittleEndian.Uint32(p[r.Off():]) 1597 } 1598 switch o1 >> 26 { 1599 case 25, // oris 1600 27, // xoris 1601 29: // andis 1602 if t>>16 != 0 { 1603 goto overflow 1604 } 1605 1606 default: 1607 if int64(int16(t)) != t { 1608 goto overflow 1609 } 1610 } 1611 } 1612 1613 return int64(int16(t)) 1614 1615 case sym.RV_POWER_DS: 1616 var o1 uint32 1617 if target.IsBigEndian() { 1618 o1 = uint32(binary.BigEndian.Uint16(p[r.Off():])) 1619 } else { 1620 o1 = uint32(binary.LittleEndian.Uint16(p[r.Off():])) 1621 } 1622 if t&3 != 0 { 1623 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t) 1624 } 1625 if (rv&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t { 1626 goto overflow 1627 } 1628 return int64(o1)&0x3 | int64(int16(t)) 1629 } 1630 1631overflow: 1632 ldr.Errorf(s, "relocation for %s+%d is too big: %d", ldr.SymName(rs), r.Off(), t) 1633 return t 1634} 1635 1636func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) { 1637 switch r.Type() { 1638 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: 1639 return ld.ExtrelocSimple(ldr, r), true 1640 case objabi.R_ADDRPOWER, 1641 objabi.R_ADDRPOWER_DS, 1642 objabi.R_ADDRPOWER_TOCREL, 1643 objabi.R_ADDRPOWER_TOCREL_DS, 1644 objabi.R_ADDRPOWER_GOT, 1645 objabi.R_ADDRPOWER_GOT_PCREL34, 1646 objabi.R_ADDRPOWER_PCREL, 1647 objabi.R_ADDRPOWER_D34, 1648 objabi.R_ADDRPOWER_PCREL34: 1649 return ld.ExtrelocViaOuterSym(ldr, r, s), true 1650 } 1651 return loader.ExtReloc{}, false 1652} 1653 1654func addpltsym(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym) { 1655 if ldr.SymPlt(s) >= 0 { 1656 return 1657 } 1658 1659 ld.Adddynsym(ldr, &ctxt.Target, &ctxt.ArchSyms, s) 1660 1661 if ctxt.IsELF { 1662 plt := ldr.MakeSymbolUpdater(ctxt.PLT) 1663 rela := ldr.MakeSymbolUpdater(ctxt.RelaPLT) 1664 if plt.Size() == 0 { 1665 panic("plt is not set up") 1666 } 1667 1668 // Create the glink resolver if necessary 1669 glink := ensureglinkresolver(ctxt, ldr) 1670 1671 // Write symbol resolver stub (just a branch to the 1672 // glink resolver stub) 1673 rel, _ := glink.AddRel(objabi.R_CALLPOWER) 1674 rel.SetOff(int32(glink.Size())) 1675 rel.SetSiz(4) 1676 rel.SetSym(glink.Sym()) 1677 glink.AddUint32(ctxt.Arch, 0x48000000) // b .glink 1678 1679 // In the ppc64 ABI, the dynamic linker is responsible 1680 // for writing the entire PLT. We just need to 1681 // reserve 8 bytes for each PLT entry and generate a 1682 // JMP_SLOT dynamic relocation for it. 1683 // 1684 // TODO(austin): ABI v1 is different 1685 ldr.SetPlt(s, int32(plt.Size())) 1686 1687 plt.Grow(plt.Size() + 8) 1688 plt.SetSize(plt.Size() + 8) 1689 1690 rela.AddAddrPlus(ctxt.Arch, plt.Sym(), int64(ldr.SymPlt(s))) 1691 rela.AddUint64(ctxt.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_PPC64_JMP_SLOT))) 1692 rela.AddUint64(ctxt.Arch, 0) 1693 } else { 1694 ctxt.Errorf(s, "addpltsym: unsupported binary format") 1695 } 1696} 1697 1698// Generate the glink resolver stub if necessary and return the .glink section. 1699func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilder { 1700 glink := ldr.CreateSymForUpdate(".glink", 0) 1701 if glink.Size() != 0 { 1702 return glink 1703 } 1704 1705 // This is essentially the resolver from the ppc64 ELFv2 ABI. 1706 // At entry, r12 holds the address of the symbol resolver stub 1707 // for the target routine and the argument registers hold the 1708 // arguments for the target routine. 1709 // 1710 // PC-rel offsets are computed once the final codesize of the 1711 // resolver is known. 1712 // 1713 // This stub is PIC, so first get the PC of label 1 into r11. 1714 glink.AddUint32(ctxt.Arch, OP_MFLR_R0) // mflr r0 1715 glink.AddUint32(ctxt.Arch, OP_BCL_NIA) // bcl 20,31,1f 1716 glink.AddUint32(ctxt.Arch, 0x7d6802a6) // 1: mflr r11 1717 glink.AddUint32(ctxt.Arch, OP_MTLR_R0) // mtlr r0 1718 1719 // Compute the .plt array index from the entry point address 1720 // into r0. This is computed relative to label 1 above. 1721 glink.AddUint32(ctxt.Arch, 0x38000000) // li r0,-(res_0-1b) 1722 glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12 1723 glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11 1724 glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2 1725 1726 // Load the PC-rel offset of ".plt - 1b", and add it to 1b. 1727 // This is stored after this stub and before the resolvers. 1728 glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,res_0-1b-8(r11) 1729 glink.AddUint32(ctxt.Arch, 0x7d6b6214) // add r11,r11,r12 1730 1731 // Load r12 = dynamic resolver address and r11 = DSO 1732 // identifier from the first two doublewords of the PLT. 1733 glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,0(r11) 1734 glink.AddUint32(ctxt.Arch, 0xe96b0008) // ld r11,8(r11) 1735 1736 // Jump to the dynamic resolver 1737 glink.AddUint32(ctxt.Arch, OP_MTCTR_R12) // mtctr r12 1738 glink.AddUint32(ctxt.Arch, OP_BCTR) // bctr 1739 1740 // Store the PC-rel offset to the PLT 1741 r, _ := glink.AddRel(objabi.R_PCREL) 1742 r.SetSym(ctxt.PLT) 1743 r.SetSiz(8) 1744 r.SetOff(int32(glink.Size())) 1745 r.SetAdd(glink.Size()) // Adjust the offset to be relative to label 1 above. 1746 glink.AddUint64(ctxt.Arch, 0) // The offset to the PLT. 1747 1748 // Resolve PC-rel offsets above now the final size of the stub is known. 1749 res0m1b := glink.Size() - 8 // res_0 - 1b 1750 glink.SetUint32(ctxt.Arch, 16, 0x38000000|uint32(uint16(-res0m1b))) 1751 glink.SetUint32(ctxt.Arch, 32, 0xe98b0000|uint32(uint16(res0m1b-8))) 1752 1753 // The symbol resolvers must immediately follow. 1754 // res_0: 1755 1756 // Add DT_PPC64_GLINK .dynamic entry, which points to 32 bytes 1757 // before the first symbol resolver stub. 1758 du := ldr.MakeSymbolUpdater(ctxt.Dynamic) 1759 ld.Elfwritedynentsymplus(ctxt, du, elf.DT_PPC64_GLINK, glink.Sym(), glink.Size()-32) 1760 1761 return glink 1762} 1763