github.com/ltltlt/go-source-code@v0.0.0-20190830023027-95be009773aa/cmd/link/internal/ppc64/asm.go (about) 1 // Inferno utils/5l/asm.c 2 // https://bitbucket.org/inferno-os/inferno-os/src/default/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 "cmd/internal/objabi" 35 "cmd/internal/sys" 36 "cmd/link/internal/ld" 37 "cmd/link/internal/sym" 38 "debug/elf" 39 "encoding/binary" 40 "fmt" 41 "log" 42 ) 43 44 func genplt(ctxt *ld.Link) { 45 // The ppc64 ABI PLT has similar concepts to other 46 // architectures, but is laid out quite differently. When we 47 // see an R_PPC64_REL24 relocation to a dynamic symbol 48 // (indicating that the call needs to go through the PLT), we 49 // generate up to three stubs and reserve a PLT slot. 50 // 51 // 1) The call site will be bl x; nop (where the relocation 52 // applies to the bl). We rewrite this to bl x_stub; ld 53 // r2,24(r1). The ld is necessary because x_stub will save 54 // r2 (the TOC pointer) at 24(r1) (the "TOC save slot"). 55 // 56 // 2) We reserve space for a pointer in the .plt section (once 57 // per referenced dynamic function). .plt is a data 58 // section filled solely by the dynamic linker (more like 59 // .plt.got on other architectures). Initially, the 60 // dynamic linker will fill each slot with a pointer to the 61 // corresponding x@plt entry point. 62 // 63 // 3) We generate the "call stub" x_stub (once per dynamic 64 // function/object file pair). This saves the TOC in the 65 // TOC save slot, reads the function pointer from x's .plt 66 // slot and calls it like any other global entry point 67 // (including setting r12 to the function address). 68 // 69 // 4) We generate the "symbol resolver stub" x@plt (once per 70 // dynamic function). This is solely a branch to the glink 71 // resolver stub. 72 // 73 // 5) We generate the glink resolver stub (only once). This 74 // computes which symbol resolver stub we came through and 75 // invokes the dynamic resolver via a pointer provided by 76 // the dynamic linker. This will patch up the .plt slot to 77 // point directly at the function so future calls go 78 // straight from the call stub to the real function, and 79 // then call the function. 80 81 // NOTE: It's possible we could make ppc64 closer to other 82 // architectures: ppc64's .plt is like .plt.got on other 83 // platforms and ppc64's .glink is like .plt on other 84 // platforms. 85 86 // Find all R_PPC64_REL24 relocations that reference dynamic 87 // imports. Reserve PLT entries for these symbols and 88 // generate call stubs. The call stubs need to live in .text, 89 // which is why we need to do this pass this early. 90 // 91 // This assumes "case 1" from the ABI, where the caller needs 92 // us to save and restore the TOC pointer. 93 var stubs []*sym.Symbol 94 for _, s := range ctxt.Textp { 95 for i := range s.R { 96 r := &s.R[i] 97 if r.Type != 256+objabi.RelocType(elf.R_PPC64_REL24) || r.Sym.Type != sym.SDYNIMPORT { 98 continue 99 } 100 101 // Reserve PLT entry and generate symbol 102 // resolver 103 addpltsym(ctxt, r.Sym) 104 105 // Generate call stub 106 n := fmt.Sprintf("%s.%s", s.Name, r.Sym.Name) 107 108 stub := ctxt.Syms.Lookup(n, 0) 109 if s.Attr.Reachable() { 110 stub.Attr |= sym.AttrReachable 111 } 112 if stub.Size == 0 { 113 // Need outer to resolve .TOC. 114 stub.Outer = s 115 stubs = append(stubs, stub) 116 gencallstub(ctxt, 1, stub, r.Sym) 117 } 118 119 // Update the relocation to use the call stub 120 r.Sym = stub 121 122 // Restore TOC after bl. The compiler put a 123 // nop here for us to overwrite. 124 const o1 = 0xe8410018 // ld r2,24(r1) 125 ctxt.Arch.ByteOrder.PutUint32(s.P[r.Off+4:], o1) 126 } 127 } 128 // Put call stubs at the beginning (instead of the end). 129 // So when resolving the relocations to calls to the stubs, 130 // the addresses are known and trampolines can be inserted 131 // when necessary. 132 ctxt.Textp = append(stubs, ctxt.Textp...) 133 } 134 135 func genaddmoduledata(ctxt *ld.Link) { 136 addmoduledata := ctxt.Syms.ROLookup("runtime.addmoduledata", 0) 137 if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin { 138 return 139 } 140 addmoduledata.Attr |= sym.AttrReachable 141 initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0) 142 initfunc.Type = sym.STEXT 143 initfunc.Attr |= sym.AttrLocal 144 initfunc.Attr |= sym.AttrReachable 145 o := func(op uint32) { 146 initfunc.AddUint32(ctxt.Arch, op) 147 } 148 // addis r2, r12, .TOC.-func@ha 149 rel := initfunc.AddRel() 150 rel.Off = int32(initfunc.Size) 151 rel.Siz = 8 152 rel.Sym = ctxt.Syms.Lookup(".TOC.", 0) 153 rel.Sym.Attr |= sym.AttrReachable 154 rel.Type = objabi.R_ADDRPOWER_PCREL 155 o(0x3c4c0000) 156 // addi r2, r2, .TOC.-func@l 157 o(0x38420000) 158 // mflr r31 159 o(0x7c0802a6) 160 // stdu r31, -32(r1) 161 o(0xf801ffe1) 162 // addis r3, r2, local.moduledata@got@ha 163 rel = initfunc.AddRel() 164 rel.Off = int32(initfunc.Size) 165 rel.Siz = 8 166 if s := ctxt.Syms.ROLookup("local.moduledata", 0); s != nil { 167 rel.Sym = s 168 } else if s := ctxt.Syms.ROLookup("local.pluginmoduledata", 0); s != nil { 169 rel.Sym = s 170 } else { 171 rel.Sym = ctxt.Syms.Lookup("runtime.firstmoduledata", 0) 172 } 173 rel.Sym.Attr |= sym.AttrReachable 174 rel.Sym.Attr |= sym.AttrLocal 175 rel.Type = objabi.R_ADDRPOWER_GOT 176 o(0x3c620000) 177 // ld r3, local.moduledata@got@l(r3) 178 o(0xe8630000) 179 // bl runtime.addmoduledata 180 rel = initfunc.AddRel() 181 rel.Off = int32(initfunc.Size) 182 rel.Siz = 4 183 rel.Sym = addmoduledata 184 rel.Type = objabi.R_CALLPOWER 185 o(0x48000001) 186 // nop 187 o(0x60000000) 188 // ld r31, 0(r1) 189 o(0xe8010000) 190 // mtlr r31 191 o(0x7c0803a6) 192 // addi r1,r1,32 193 o(0x38210020) 194 // blr 195 o(0x4e800020) 196 197 if ctxt.BuildMode == ld.BuildModePlugin { 198 ctxt.Textp = append(ctxt.Textp, addmoduledata) 199 } 200 initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0) 201 ctxt.Textp = append(ctxt.Textp, initfunc) 202 initarray_entry.Attr |= sym.AttrReachable 203 initarray_entry.Attr |= sym.AttrLocal 204 initarray_entry.Type = sym.SINITARR 205 initarray_entry.AddAddr(ctxt.Arch, initfunc) 206 } 207 208 func gentext(ctxt *ld.Link) { 209 if ctxt.DynlinkingGo() { 210 genaddmoduledata(ctxt) 211 } 212 213 if ctxt.LinkMode == ld.LinkInternal { 214 genplt(ctxt) 215 } 216 } 217 218 // Construct a call stub in stub that calls symbol targ via its PLT 219 // entry. 220 func gencallstub(ctxt *ld.Link, abicase int, stub *sym.Symbol, targ *sym.Symbol) { 221 if abicase != 1 { 222 // If we see R_PPC64_TOCSAVE or R_PPC64_REL24_NOTOC 223 // relocations, we'll need to implement cases 2 and 3. 224 log.Fatalf("gencallstub only implements case 1 calls") 225 } 226 227 plt := ctxt.Syms.Lookup(".plt", 0) 228 229 stub.Type = sym.STEXT 230 231 // Save TOC pointer in TOC save slot 232 stub.AddUint32(ctxt.Arch, 0xf8410018) // std r2,24(r1) 233 234 // Load the function pointer from the PLT. 235 r := stub.AddRel() 236 237 r.Off = int32(stub.Size) 238 r.Sym = plt 239 r.Add = int64(targ.Plt) 240 r.Siz = 2 241 if ctxt.Arch.ByteOrder == binary.BigEndian { 242 r.Off += int32(r.Siz) 243 } 244 r.Type = objabi.R_POWER_TOC 245 r.Variant = sym.RV_POWER_HA 246 stub.AddUint32(ctxt.Arch, 0x3d820000) // addis r12,r2,targ@plt@toc@ha 247 r = stub.AddRel() 248 r.Off = int32(stub.Size) 249 r.Sym = plt 250 r.Add = int64(targ.Plt) 251 r.Siz = 2 252 if ctxt.Arch.ByteOrder == binary.BigEndian { 253 r.Off += int32(r.Siz) 254 } 255 r.Type = objabi.R_POWER_TOC 256 r.Variant = sym.RV_POWER_LO 257 stub.AddUint32(ctxt.Arch, 0xe98c0000) // ld r12,targ@plt@toc@l(r12) 258 259 // Jump to the loaded pointer 260 stub.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12 261 stub.AddUint32(ctxt.Arch, 0x4e800420) // bctr 262 } 263 264 func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool { 265 targ := r.Sym 266 267 switch r.Type { 268 default: 269 if r.Type >= 256 { 270 ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type)) 271 return false 272 } 273 274 // Handle relocations found in ELF object files. 275 case 256 + objabi.RelocType(elf.R_PPC64_REL24): 276 r.Type = objabi.R_CALLPOWER 277 278 // This is a local call, so the caller isn't setting 279 // up r12 and r2 is the same for the caller and 280 // callee. Hence, we need to go to the local entry 281 // point. (If we don't do this, the callee will try 282 // to use r12 to compute r2.) 283 r.Add += int64(r.Sym.Localentry) * 4 284 285 if targ.Type == sym.SDYNIMPORT { 286 // Should have been handled in elfsetupplt 287 ld.Errorf(s, "unexpected R_PPC64_REL24 for dyn import") 288 } 289 290 return true 291 292 case 256 + objabi.RelocType(elf.R_PPC_REL32): 293 r.Type = objabi.R_PCREL 294 r.Add += 4 295 296 if targ.Type == sym.SDYNIMPORT { 297 ld.Errorf(s, "unexpected R_PPC_REL32 for dyn import") 298 } 299 300 return true 301 302 case 256 + objabi.RelocType(elf.R_PPC64_ADDR64): 303 r.Type = objabi.R_ADDR 304 if targ.Type == sym.SDYNIMPORT { 305 // These happen in .toc sections 306 ld.Adddynsym(ctxt, targ) 307 308 rela := ctxt.Syms.Lookup(".rela", 0) 309 rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off)) 310 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_PPC64_ADDR64))) 311 rela.AddUint64(ctxt.Arch, uint64(r.Add)) 312 r.Type = 256 // ignore during relocsym 313 } 314 315 return true 316 317 case 256 + objabi.RelocType(elf.R_PPC64_TOC16): 318 r.Type = objabi.R_POWER_TOC 319 r.Variant = sym.RV_POWER_LO | sym.RV_CHECK_OVERFLOW 320 return true 321 322 case 256 + objabi.RelocType(elf.R_PPC64_TOC16_LO): 323 r.Type = objabi.R_POWER_TOC 324 r.Variant = sym.RV_POWER_LO 325 return true 326 327 case 256 + objabi.RelocType(elf.R_PPC64_TOC16_HA): 328 r.Type = objabi.R_POWER_TOC 329 r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW 330 return true 331 332 case 256 + objabi.RelocType(elf.R_PPC64_TOC16_HI): 333 r.Type = objabi.R_POWER_TOC 334 r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW 335 return true 336 337 case 256 + objabi.RelocType(elf.R_PPC64_TOC16_DS): 338 r.Type = objabi.R_POWER_TOC 339 r.Variant = sym.RV_POWER_DS | sym.RV_CHECK_OVERFLOW 340 return true 341 342 case 256 + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS): 343 r.Type = objabi.R_POWER_TOC 344 r.Variant = sym.RV_POWER_DS 345 return true 346 347 case 256 + objabi.RelocType(elf.R_PPC64_REL16_LO): 348 r.Type = objabi.R_PCREL 349 r.Variant = sym.RV_POWER_LO 350 r.Add += 2 // Compensate for relocation size of 2 351 return true 352 353 case 256 + objabi.RelocType(elf.R_PPC64_REL16_HI): 354 r.Type = objabi.R_PCREL 355 r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW 356 r.Add += 2 357 return true 358 359 case 256 + objabi.RelocType(elf.R_PPC64_REL16_HA): 360 r.Type = objabi.R_PCREL 361 r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW 362 r.Add += 2 363 return true 364 } 365 366 // Handle references to ELF symbols from our own object files. 367 if targ.Type != sym.SDYNIMPORT { 368 return true 369 } 370 371 // TODO(austin): Translate our relocations to ELF 372 373 return false 374 } 375 376 func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool { 377 ctxt.Out.Write64(uint64(sectoff)) 378 379 elfsym := r.Xsym.ElfsymForReloc() 380 switch r.Type { 381 default: 382 return false 383 case objabi.R_ADDR: 384 switch r.Siz { 385 case 4: 386 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32) 387 case 8: 388 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR64) | uint64(elfsym)<<32) 389 default: 390 return false 391 } 392 case objabi.R_POWER_TLS: 393 ctxt.Out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32) 394 case objabi.R_POWER_TLS_LE: 395 ctxt.Out.Write64(uint64(elf.R_PPC64_TPREL16) | uint64(elfsym)<<32) 396 case objabi.R_POWER_TLS_IE: 397 ctxt.Out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32) 398 ctxt.Out.Write64(uint64(r.Xadd)) 399 ctxt.Out.Write64(uint64(sectoff + 4)) 400 ctxt.Out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_LO_DS) | uint64(elfsym)<<32) 401 case objabi.R_ADDRPOWER: 402 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32) 403 ctxt.Out.Write64(uint64(r.Xadd)) 404 ctxt.Out.Write64(uint64(sectoff + 4)) 405 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_LO) | uint64(elfsym)<<32) 406 case objabi.R_ADDRPOWER_DS: 407 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32) 408 ctxt.Out.Write64(uint64(r.Xadd)) 409 ctxt.Out.Write64(uint64(sectoff + 4)) 410 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_LO_DS) | uint64(elfsym)<<32) 411 case objabi.R_ADDRPOWER_GOT: 412 ctxt.Out.Write64(uint64(elf.R_PPC64_GOT16_HA) | uint64(elfsym)<<32) 413 ctxt.Out.Write64(uint64(r.Xadd)) 414 ctxt.Out.Write64(uint64(sectoff + 4)) 415 ctxt.Out.Write64(uint64(elf.R_PPC64_GOT16_LO_DS) | uint64(elfsym)<<32) 416 case objabi.R_ADDRPOWER_PCREL: 417 ctxt.Out.Write64(uint64(elf.R_PPC64_REL16_HA) | uint64(elfsym)<<32) 418 ctxt.Out.Write64(uint64(r.Xadd)) 419 ctxt.Out.Write64(uint64(sectoff + 4)) 420 ctxt.Out.Write64(uint64(elf.R_PPC64_REL16_LO) | uint64(elfsym)<<32) 421 r.Xadd += 4 422 case objabi.R_ADDRPOWER_TOCREL: 423 ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32) 424 ctxt.Out.Write64(uint64(r.Xadd)) 425 ctxt.Out.Write64(uint64(sectoff + 4)) 426 ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_LO) | uint64(elfsym)<<32) 427 case objabi.R_ADDRPOWER_TOCREL_DS: 428 ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32) 429 ctxt.Out.Write64(uint64(r.Xadd)) 430 ctxt.Out.Write64(uint64(sectoff + 4)) 431 ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32) 432 case objabi.R_CALLPOWER: 433 if r.Siz != 4 { 434 return false 435 } 436 ctxt.Out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32) 437 438 } 439 ctxt.Out.Write64(uint64(r.Xadd)) 440 441 return true 442 } 443 444 func elfsetupplt(ctxt *ld.Link) { 445 plt := ctxt.Syms.Lookup(".plt", 0) 446 if plt.Size == 0 { 447 // The dynamic linker stores the address of the 448 // dynamic resolver and the DSO identifier in the two 449 // doublewords at the beginning of the .plt section 450 // before the PLT array. Reserve space for these. 451 plt.Size = 16 452 } 453 } 454 455 func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool { 456 return false 457 } 458 459 // Return the value of .TOC. for symbol s 460 func symtoc(ctxt *ld.Link, s *sym.Symbol) int64 { 461 var toc *sym.Symbol 462 463 if s.Outer != nil { 464 toc = ctxt.Syms.ROLookup(".TOC.", int(s.Outer.Version)) 465 } else { 466 toc = ctxt.Syms.ROLookup(".TOC.", int(s.Version)) 467 } 468 469 if toc == nil { 470 ld.Errorf(s, "TOC-relative relocation in object without .TOC.") 471 return 0 472 } 473 474 return toc.Value 475 } 476 477 func archrelocaddr(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool { 478 var o1, o2 uint32 479 if ctxt.Arch.ByteOrder == binary.BigEndian { 480 o1 = uint32(*val >> 32) 481 o2 = uint32(*val) 482 } else { 483 o1 = uint32(*val) 484 o2 = uint32(*val >> 32) 485 } 486 487 // We are spreading a 31-bit address across two instructions, putting the 488 // high (adjusted) part in the low 16 bits of the first instruction and the 489 // low part in the low 16 bits of the second instruction, or, in the DS case, 490 // bits 15-2 (inclusive) of the address into bits 15-2 of the second 491 // instruction (it is an error in this case if the low 2 bits of the address 492 // are non-zero). 493 494 t := ld.Symaddr(r.Sym) + r.Add 495 if t < 0 || t >= 1<<31 { 496 ld.Errorf(s, "relocation for %s is too big (>=2G): %d", s.Name, ld.Symaddr(r.Sym)) 497 } 498 if t&0x8000 != 0 { 499 t += 0x10000 500 } 501 502 switch r.Type { 503 case objabi.R_ADDRPOWER: 504 o1 |= (uint32(t) >> 16) & 0xffff 505 o2 |= uint32(t) & 0xffff 506 case objabi.R_ADDRPOWER_DS: 507 o1 |= (uint32(t) >> 16) & 0xffff 508 if t&3 != 0 { 509 ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym)) 510 } 511 o2 |= uint32(t) & 0xfffc 512 default: 513 return false 514 } 515 516 if ctxt.Arch.ByteOrder == binary.BigEndian { 517 *val = int64(o1)<<32 | int64(o2) 518 } else { 519 *val = int64(o2)<<32 | int64(o1) 520 } 521 return true 522 } 523 524 // resolve direct jump relocation r in s, and add trampoline if necessary 525 func trampoline(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol) { 526 527 // Trampolines are created if the branch offset is too large and the linker cannot insert a call stub to handle it. 528 // For internal linking, trampolines are always created for long calls. 529 // For external linking, the linker can insert a call stub to handle a long call, but depends on having the TOC address in 530 // r2. For those build modes with external linking where the TOC address is not maintained in r2, trampolines must be created. 531 if ctxt.LinkMode == ld.LinkExternal && (ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE) { 532 // No trampolines needed since r2 contains the TOC 533 return 534 } 535 536 t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off)) 537 switch r.Type { 538 case objabi.R_CALLPOWER: 539 540 // If branch offset is too far then create a trampoline. 541 542 if (ctxt.LinkMode == ld.LinkExternal && s.Sect != r.Sym.Sect) || (ctxt.LinkMode == ld.LinkInternal && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && s.File != r.Sym.File) { 543 var tramp *sym.Symbol 544 for i := 0; ; i++ { 545 546 // Using r.Add as part of the name is significant in functions like duffzero where the call 547 // target is at some offset within the function. Calls to duff+8 and duff+256 must appear as 548 // distinct trampolines. 549 550 name := r.Sym.Name 551 if r.Add == 0 { 552 name = name + fmt.Sprintf("-tramp%d", i) 553 } else { 554 name = name + fmt.Sprintf("%+x-tramp%d", r.Add, i) 555 } 556 557 // Look up the trampoline in case it already exists 558 559 tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version)) 560 if tramp.Value == 0 { 561 break 562 } 563 564 t = ld.Symaddr(tramp) + r.Add - (s.Value + int64(r.Off)) 565 566 // With internal linking, the trampoline can be used if it is not too far. 567 // With external linking, the trampoline must be in this section for it to be reused. 568 if (ctxt.LinkMode == ld.LinkInternal && int64(int32(t<<6)>>6) == t) || (ctxt.LinkMode == ld.LinkExternal && s.Sect == tramp.Sect) { 569 break 570 } 571 } 572 if tramp.Type == 0 { 573 if ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE { 574 // Should have returned for above cases 575 ld.Errorf(s, "unexpected trampoline for shared or dynamic linking\n") 576 } else { 577 ctxt.AddTramp(tramp) 578 gentramp(ctxt.Arch, ctxt.LinkMode, tramp, r.Sym, int64(r.Add)) 579 } 580 } 581 r.Sym = tramp 582 r.Add = 0 // This was folded into the trampoline target address 583 r.Done = false 584 } 585 default: 586 ld.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type)) 587 } 588 } 589 590 func gentramp(arch *sys.Arch, linkmode ld.LinkMode, tramp, target *sym.Symbol, offset int64) { 591 // Used for default build mode for an executable 592 // Address of the call target is generated using 593 // relocation and doesn't depend on r2 (TOC). 594 tramp.Size = 16 // 4 instructions 595 tramp.P = make([]byte, tramp.Size) 596 t := ld.Symaddr(target) + offset 597 o1 := uint32(0x3fe00000) // lis r31,targetaddr hi 598 o2 := uint32(0x3bff0000) // addi r31,targetaddr lo 599 // With external linking, the target address must be 600 // relocated using LO and HA 601 if linkmode == ld.LinkExternal { 602 tr := tramp.AddRel() 603 tr.Off = 0 604 tr.Type = objabi.R_ADDRPOWER 605 tr.Siz = 8 // generates 2 relocations: HA + LO 606 tr.Sym = target 607 tr.Add = offset 608 } else { 609 // adjustment needed if lo has sign bit set 610 // when using addi to compute address 611 val := uint32((t & 0xffff0000) >> 16) 612 if t&0x8000 != 0 { 613 val += 1 614 } 615 o1 |= val // hi part of addr 616 o2 |= uint32(t & 0xffff) // lo part of addr 617 } 618 o3 := uint32(0x7fe903a6) // mtctr r31 619 o4 := uint32(0x4e800420) // bctr 620 arch.ByteOrder.PutUint32(tramp.P, o1) 621 arch.ByteOrder.PutUint32(tramp.P[4:], o2) 622 arch.ByteOrder.PutUint32(tramp.P[8:], o3) 623 arch.ByteOrder.PutUint32(tramp.P[12:], o4) 624 } 625 626 func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool { 627 if ctxt.LinkMode == ld.LinkExternal { 628 switch r.Type { 629 default: 630 return false 631 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE: 632 r.Done = false 633 // check Outer is nil, Type is TLSBSS? 634 r.Xadd = r.Add 635 r.Xsym = r.Sym 636 return true 637 case objabi.R_ADDRPOWER, 638 objabi.R_ADDRPOWER_DS, 639 objabi.R_ADDRPOWER_TOCREL, 640 objabi.R_ADDRPOWER_TOCREL_DS, 641 objabi.R_ADDRPOWER_GOT, 642 objabi.R_ADDRPOWER_PCREL: 643 r.Done = false 644 645 // set up addend for eventual relocation via outer symbol. 646 rs := r.Sym 647 r.Xadd = r.Add 648 for rs.Outer != nil { 649 r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer) 650 rs = rs.Outer 651 } 652 653 if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil { 654 ld.Errorf(s, "missing section for %s", rs.Name) 655 } 656 r.Xsym = rs 657 658 return true 659 case objabi.R_CALLPOWER: 660 r.Done = false 661 r.Xsym = r.Sym 662 r.Xadd = r.Add 663 return true 664 } 665 } 666 667 switch r.Type { 668 case objabi.R_CONST: 669 *val = r.Add 670 return true 671 case objabi.R_GOTOFF: 672 *val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)) 673 return true 674 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS: 675 return archrelocaddr(ctxt, r, s, val) 676 case objabi.R_CALLPOWER: 677 // Bits 6 through 29 = (S + A - P) >> 2 678 679 t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off)) 680 681 if t&3 != 0 { 682 ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t) 683 } 684 // If branch offset is too far then create a trampoline. 685 686 if int64(int32(t<<6)>>6) != t { 687 ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t) 688 } 689 *val |= int64(uint32(t) &^ 0xfc000003) 690 return true 691 case objabi.R_POWER_TOC: // S + A - .TOC. 692 *val = ld.Symaddr(r.Sym) + r.Add - symtoc(ctxt, s) 693 694 return true 695 case objabi.R_POWER_TLS_LE: 696 // The thread pointer points 0x7000 bytes after the start of the the 697 // thread local storage area as documented in section "3.7.2 TLS 698 // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI 699 // Specification". 700 v := r.Sym.Value - 0x7000 701 if int64(int16(v)) != v { 702 ld.Errorf(s, "TLS offset out of range %d", v) 703 } 704 *val = (*val &^ 0xffff) | (v & 0xffff) 705 return true 706 } 707 708 return false 709 } 710 711 func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 { 712 switch r.Variant & sym.RV_TYPE_MASK { 713 default: 714 ld.Errorf(s, "unexpected relocation variant %d", r.Variant) 715 fallthrough 716 717 case sym.RV_NONE: 718 return t 719 720 case sym.RV_POWER_LO: 721 if r.Variant&sym.RV_CHECK_OVERFLOW != 0 { 722 // Whether to check for signed or unsigned 723 // overflow depends on the instruction 724 var o1 uint32 725 if ctxt.Arch.ByteOrder == binary.BigEndian { 726 o1 = ld.Be32(s.P[r.Off-2:]) 727 } else { 728 o1 = ld.Le32(s.P[r.Off:]) 729 } 730 switch o1 >> 26 { 731 case 24, // ori 732 26, // xori 733 28: // andi 734 if t>>16 != 0 { 735 goto overflow 736 } 737 738 default: 739 if int64(int16(t)) != t { 740 goto overflow 741 } 742 } 743 } 744 745 return int64(int16(t)) 746 747 case sym.RV_POWER_HA: 748 t += 0x8000 749 fallthrough 750 751 // Fallthrough 752 case sym.RV_POWER_HI: 753 t >>= 16 754 755 if r.Variant&sym.RV_CHECK_OVERFLOW != 0 { 756 // Whether to check for signed or unsigned 757 // overflow depends on the instruction 758 var o1 uint32 759 if ctxt.Arch.ByteOrder == binary.BigEndian { 760 o1 = ld.Be32(s.P[r.Off-2:]) 761 } else { 762 o1 = ld.Le32(s.P[r.Off:]) 763 } 764 switch o1 >> 26 { 765 case 25, // oris 766 27, // xoris 767 29: // andis 768 if t>>16 != 0 { 769 goto overflow 770 } 771 772 default: 773 if int64(int16(t)) != t { 774 goto overflow 775 } 776 } 777 } 778 779 return int64(int16(t)) 780 781 case sym.RV_POWER_DS: 782 var o1 uint32 783 if ctxt.Arch.ByteOrder == binary.BigEndian { 784 o1 = uint32(ld.Be16(s.P[r.Off:])) 785 } else { 786 o1 = uint32(ld.Le16(s.P[r.Off:])) 787 } 788 if t&3 != 0 { 789 ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t) 790 } 791 if (r.Variant&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t { 792 goto overflow 793 } 794 return int64(o1)&0x3 | int64(int16(t)) 795 } 796 797 overflow: 798 ld.Errorf(s, "relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t) 799 return t 800 } 801 802 func addpltsym(ctxt *ld.Link, s *sym.Symbol) { 803 if s.Plt >= 0 { 804 return 805 } 806 807 ld.Adddynsym(ctxt, s) 808 809 if ctxt.IsELF { 810 plt := ctxt.Syms.Lookup(".plt", 0) 811 rela := ctxt.Syms.Lookup(".rela.plt", 0) 812 if plt.Size == 0 { 813 elfsetupplt(ctxt) 814 } 815 816 // Create the glink resolver if necessary 817 glink := ensureglinkresolver(ctxt) 818 819 // Write symbol resolver stub (just a branch to the 820 // glink resolver stub) 821 r := glink.AddRel() 822 823 r.Sym = glink 824 r.Off = int32(glink.Size) 825 r.Siz = 4 826 r.Type = objabi.R_CALLPOWER 827 glink.AddUint32(ctxt.Arch, 0x48000000) // b .glink 828 829 // In the ppc64 ABI, the dynamic linker is responsible 830 // for writing the entire PLT. We just need to 831 // reserve 8 bytes for each PLT entry and generate a 832 // JMP_SLOT dynamic relocation for it. 833 // 834 // TODO(austin): ABI v1 is different 835 s.Plt = int32(plt.Size) 836 837 plt.Size += 8 838 839 rela.AddAddrPlus(ctxt.Arch, plt, int64(s.Plt)) 840 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_PPC64_JMP_SLOT))) 841 rela.AddUint64(ctxt.Arch, 0) 842 } else { 843 ld.Errorf(s, "addpltsym: unsupported binary format") 844 } 845 } 846 847 // Generate the glink resolver stub if necessary and return the .glink section 848 func ensureglinkresolver(ctxt *ld.Link) *sym.Symbol { 849 glink := ctxt.Syms.Lookup(".glink", 0) 850 if glink.Size != 0 { 851 return glink 852 } 853 854 // This is essentially the resolver from the ppc64 ELF ABI. 855 // At entry, r12 holds the address of the symbol resolver stub 856 // for the target routine and the argument registers hold the 857 // arguments for the target routine. 858 // 859 // This stub is PIC, so first get the PC of label 1 into r11. 860 // Other things will be relative to this. 861 glink.AddUint32(ctxt.Arch, 0x7c0802a6) // mflr r0 862 glink.AddUint32(ctxt.Arch, 0x429f0005) // bcl 20,31,1f 863 glink.AddUint32(ctxt.Arch, 0x7d6802a6) // 1: mflr r11 864 glink.AddUint32(ctxt.Arch, 0x7c0803a6) // mtlf r0 865 866 // Compute the .plt array index from the entry point address. 867 // Because this is PIC, everything is relative to label 1b (in 868 // r11): 869 // r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4 870 glink.AddUint32(ctxt.Arch, 0x3800ffd0) // li r0,-(res_0-1b)=-48 871 glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12 872 glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11 873 glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2 874 875 // r11 = address of the first byte of the PLT 876 r := glink.AddRel() 877 878 r.Off = int32(glink.Size) 879 r.Sym = ctxt.Syms.Lookup(".plt", 0) 880 r.Siz = 8 881 r.Type = objabi.R_ADDRPOWER 882 883 glink.AddUint32(ctxt.Arch, 0x3d600000) // addis r11,0,.plt@ha 884 glink.AddUint32(ctxt.Arch, 0x396b0000) // addi r11,r11,.plt@l 885 886 // Load r12 = dynamic resolver address and r11 = DSO 887 // identifier from the first two doublewords of the PLT. 888 glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,0(r11) 889 glink.AddUint32(ctxt.Arch, 0xe96b0008) // ld r11,8(r11) 890 891 // Jump to the dynamic resolver 892 glink.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12 893 glink.AddUint32(ctxt.Arch, 0x4e800420) // bctr 894 895 // The symbol resolvers must immediately follow. 896 // res_0: 897 898 // Add DT_PPC64_GLINK .dynamic entry, which points to 32 bytes 899 // before the first symbol resolver stub. 900 s := ctxt.Syms.Lookup(".dynamic", 0) 901 902 ld.Elfwritedynentsymplus(ctxt, s, ld.DT_PPC64_GLINK, glink, glink.Size-32) 903 904 return glink 905 } 906 907 func asmb(ctxt *ld.Link) { 908 if ctxt.Debugvlog != 0 { 909 ctxt.Logf("%5.2f asmb\n", ld.Cputime()) 910 } 911 912 if ctxt.IsELF { 913 ld.Asmbelfsetup() 914 } 915 916 for _, sect := range ld.Segtext.Sections { 917 ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 918 // Handle additional text sections with Codeblk 919 if sect.Name == ".text" { 920 ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length)) 921 } else { 922 ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length)) 923 } 924 } 925 926 if ld.Segrodata.Filelen > 0 { 927 if ctxt.Debugvlog != 0 { 928 ctxt.Logf("%5.2f rodatblk\n", ld.Cputime()) 929 } 930 ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff)) 931 ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen)) 932 } 933 if ld.Segrelrodata.Filelen > 0 { 934 if ctxt.Debugvlog != 0 { 935 ctxt.Logf("%5.2f relrodatblk\n", ld.Cputime()) 936 } 937 ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff)) 938 ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen)) 939 } 940 941 if ctxt.Debugvlog != 0 { 942 ctxt.Logf("%5.2f datblk\n", ld.Cputime()) 943 } 944 945 ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff)) 946 ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 947 948 ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff)) 949 ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen)) 950 951 /* output symbol table */ 952 ld.Symsize = 0 953 954 ld.Lcsize = 0 955 symo := uint32(0) 956 if !*ld.FlagS { 957 // TODO: rationalize 958 if ctxt.Debugvlog != 0 { 959 ctxt.Logf("%5.2f sym\n", ld.Cputime()) 960 } 961 switch ctxt.HeadType { 962 default: 963 if ctxt.IsELF { 964 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 965 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound))) 966 } 967 968 case objabi.Hplan9: 969 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 970 } 971 972 ctxt.Out.SeekSet(int64(symo)) 973 switch ctxt.HeadType { 974 default: 975 if ctxt.IsELF { 976 if ctxt.Debugvlog != 0 { 977 ctxt.Logf("%5.2f elfsym\n", ld.Cputime()) 978 } 979 ld.Asmelfsym(ctxt) 980 ctxt.Out.Flush() 981 ctxt.Out.Write(ld.Elfstrdat) 982 983 if ctxt.LinkMode == ld.LinkExternal { 984 ld.Elfemitreloc(ctxt) 985 } 986 } 987 988 case objabi.Hplan9: 989 ld.Asmplan9sym(ctxt) 990 ctxt.Out.Flush() 991 992 sym := ctxt.Syms.Lookup("pclntab", 0) 993 if sym != nil { 994 ld.Lcsize = int32(len(sym.P)) 995 ctxt.Out.Write(sym.P) 996 ctxt.Out.Flush() 997 } 998 } 999 } 1000 1001 if ctxt.Debugvlog != 0 { 1002 ctxt.Logf("%5.2f header\n", ld.Cputime()) 1003 } 1004 ctxt.Out.SeekSet(0) 1005 switch ctxt.HeadType { 1006 default: 1007 case objabi.Hplan9: /* plan 9 */ 1008 ctxt.Out.Write32(0x647) /* magic */ 1009 ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */ 1010 ctxt.Out.Write32(uint32(ld.Segdata.Filelen)) 1011 ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) 1012 ctxt.Out.Write32(uint32(ld.Symsize)) /* nsyms */ 1013 ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */ 1014 ctxt.Out.Write32(0) 1015 ctxt.Out.Write32(uint32(ld.Lcsize)) 1016 1017 case objabi.Hlinux, 1018 objabi.Hfreebsd, 1019 objabi.Hnetbsd, 1020 objabi.Hopenbsd, 1021 objabi.Hnacl: 1022 ld.Asmbelf(ctxt, int64(symo)) 1023 } 1024 1025 ctxt.Out.Flush() 1026 if *ld.FlagC { 1027 fmt.Printf("textsize=%d\n", ld.Segtext.Filelen) 1028 fmt.Printf("datsize=%d\n", ld.Segdata.Filelen) 1029 fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen) 1030 fmt.Printf("symsize=%d\n", ld.Symsize) 1031 fmt.Printf("lcsize=%d\n", ld.Lcsize) 1032 fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize)) 1033 } 1034 }