github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/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 // Trampolines are created if the branch offset is too large and the linker cannot insert a call stub to handle it. 527 // For internal linking, trampolines are always created for long calls. 528 // For external linking, the linker can insert a call stub to handle a long call, but depends on having the TOC address in 529 // r2. For those build modes with external linking where the TOC address is not maintained in r2, trampolines must be created. 530 if ctxt.LinkMode == ld.LinkExternal && (ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE) { 531 // No trampolines needed since r2 contains the TOC 532 return 533 } 534 535 t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off)) 536 switch r.Type { 537 case objabi.R_CALLPOWER: 538 539 // If branch offset is too far then create a trampoline. 540 541 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) { 542 var tramp *sym.Symbol 543 for i := 0; ; i++ { 544 // Using r.Add as part of the name is significant in functions like duffzero where the call 545 // target is at some offset within the function. Calls to duff+8 and duff+256 must appear as 546 // distinct trampolines. 547 548 name := r.Sym.Name 549 if r.Add == 0 { 550 name = name + fmt.Sprintf("-tramp%d", i) 551 } else { 552 name = name + fmt.Sprintf("%+x-tramp%d", r.Add, i) 553 } 554 555 // Look up the trampoline in case it already exists 556 557 tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version)) 558 if tramp.Value == 0 { 559 break 560 } 561 562 t = ld.Symaddr(tramp) + r.Add - (s.Value + int64(r.Off)) 563 564 // With internal linking, the trampoline can be used if it is not too far. 565 // With external linking, the trampoline must be in this section for it to be reused. 566 if (ctxt.LinkMode == ld.LinkInternal && int64(int32(t<<6)>>6) == t) || (ctxt.LinkMode == ld.LinkExternal && s.Sect == tramp.Sect) { 567 break 568 } 569 } 570 if tramp.Type == 0 { 571 if ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE { 572 // Should have returned for above cases 573 ld.Errorf(s, "unexpected trampoline for shared or dynamic linking\n") 574 } else { 575 ctxt.AddTramp(tramp) 576 gentramp(ctxt.Arch, ctxt.LinkMode, tramp, r.Sym, int64(r.Add)) 577 } 578 } 579 r.Sym = tramp 580 r.Add = 0 // This was folded into the trampoline target address 581 r.Done = false 582 } 583 default: 584 ld.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type)) 585 } 586 } 587 588 func gentramp(arch *sys.Arch, linkmode ld.LinkMode, tramp, target *sym.Symbol, offset int64) { 589 // Used for default build mode for an executable 590 // Address of the call target is generated using 591 // relocation and doesn't depend on r2 (TOC). 592 tramp.Size = 16 // 4 instructions 593 tramp.P = make([]byte, tramp.Size) 594 t := ld.Symaddr(target) + offset 595 o1 := uint32(0x3fe00000) // lis r31,targetaddr hi 596 o2 := uint32(0x3bff0000) // addi r31,targetaddr lo 597 // With external linking, the target address must be 598 // relocated using LO and HA 599 if linkmode == ld.LinkExternal { 600 tr := tramp.AddRel() 601 tr.Off = 0 602 tr.Type = objabi.R_ADDRPOWER 603 tr.Siz = 8 // generates 2 relocations: HA + LO 604 tr.Sym = target 605 tr.Add = offset 606 } else { 607 // adjustment needed if lo has sign bit set 608 // when using addi to compute address 609 val := uint32((t & 0xffff0000) >> 16) 610 if t&0x8000 != 0 { 611 val += 1 612 } 613 o1 |= val // hi part of addr 614 o2 |= uint32(t & 0xffff) // lo part of addr 615 } 616 o3 := uint32(0x7fe903a6) // mtctr r31 617 o4 := uint32(0x4e800420) // bctr 618 arch.ByteOrder.PutUint32(tramp.P, o1) 619 arch.ByteOrder.PutUint32(tramp.P[4:], o2) 620 arch.ByteOrder.PutUint32(tramp.P[8:], o3) 621 arch.ByteOrder.PutUint32(tramp.P[12:], o4) 622 } 623 624 func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val *int64) bool { 625 if ctxt.LinkMode == ld.LinkExternal { 626 switch r.Type { 627 default: 628 return false 629 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE: 630 r.Done = false 631 // check Outer is nil, Type is TLSBSS? 632 r.Xadd = r.Add 633 r.Xsym = r.Sym 634 return true 635 case objabi.R_ADDRPOWER, 636 objabi.R_ADDRPOWER_DS, 637 objabi.R_ADDRPOWER_TOCREL, 638 objabi.R_ADDRPOWER_TOCREL_DS, 639 objabi.R_ADDRPOWER_GOT, 640 objabi.R_ADDRPOWER_PCREL: 641 r.Done = false 642 643 // set up addend for eventual relocation via outer symbol. 644 rs := r.Sym 645 r.Xadd = r.Add 646 for rs.Outer != nil { 647 r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer) 648 rs = rs.Outer 649 } 650 651 if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil { 652 ld.Errorf(s, "missing section for %s", rs.Name) 653 } 654 r.Xsym = rs 655 656 return true 657 case objabi.R_CALLPOWER: 658 r.Done = false 659 r.Xsym = r.Sym 660 r.Xadd = r.Add 661 return true 662 } 663 } 664 665 switch r.Type { 666 case objabi.R_CONST: 667 *val = r.Add 668 return true 669 case objabi.R_GOTOFF: 670 *val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)) 671 return true 672 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS: 673 return archrelocaddr(ctxt, r, s, val) 674 case objabi.R_CALLPOWER: 675 // Bits 6 through 29 = (S + A - P) >> 2 676 677 t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off)) 678 679 if t&3 != 0 { 680 ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t) 681 } 682 // If branch offset is too far then create a trampoline. 683 684 if int64(int32(t<<6)>>6) != t { 685 ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t) 686 } 687 *val |= int64(uint32(t) &^ 0xfc000003) 688 return true 689 case objabi.R_POWER_TOC: // S + A - .TOC. 690 *val = ld.Symaddr(r.Sym) + r.Add - symtoc(ctxt, s) 691 692 return true 693 case objabi.R_POWER_TLS_LE: 694 // The thread pointer points 0x7000 bytes after the start of the the 695 // thread local storage area as documented in section "3.7.2 TLS 696 // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI 697 // Specification". 698 v := r.Sym.Value - 0x7000 699 if int64(int16(v)) != v { 700 ld.Errorf(s, "TLS offset out of range %d", v) 701 } 702 *val = (*val &^ 0xffff) | (v & 0xffff) 703 return true 704 } 705 706 return false 707 } 708 709 func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 { 710 switch r.Variant & sym.RV_TYPE_MASK { 711 default: 712 ld.Errorf(s, "unexpected relocation variant %d", r.Variant) 713 fallthrough 714 715 case sym.RV_NONE: 716 return t 717 718 case sym.RV_POWER_LO: 719 if r.Variant&sym.RV_CHECK_OVERFLOW != 0 { 720 // Whether to check for signed or unsigned 721 // overflow depends on the instruction 722 var o1 uint32 723 if ctxt.Arch.ByteOrder == binary.BigEndian { 724 o1 = ld.Be32(s.P[r.Off-2:]) 725 } else { 726 o1 = ld.Le32(s.P[r.Off:]) 727 } 728 switch o1 >> 26 { 729 case 24, // ori 730 26, // xori 731 28: // andi 732 if t>>16 != 0 { 733 goto overflow 734 } 735 736 default: 737 if int64(int16(t)) != t { 738 goto overflow 739 } 740 } 741 } 742 743 return int64(int16(t)) 744 745 case sym.RV_POWER_HA: 746 t += 0x8000 747 fallthrough 748 749 // Fallthrough 750 case sym.RV_POWER_HI: 751 t >>= 16 752 753 if r.Variant&sym.RV_CHECK_OVERFLOW != 0 { 754 // Whether to check for signed or unsigned 755 // overflow depends on the instruction 756 var o1 uint32 757 if ctxt.Arch.ByteOrder == binary.BigEndian { 758 o1 = ld.Be32(s.P[r.Off-2:]) 759 } else { 760 o1 = ld.Le32(s.P[r.Off:]) 761 } 762 switch o1 >> 26 { 763 case 25, // oris 764 27, // xoris 765 29: // andis 766 if t>>16 != 0 { 767 goto overflow 768 } 769 770 default: 771 if int64(int16(t)) != t { 772 goto overflow 773 } 774 } 775 } 776 777 return int64(int16(t)) 778 779 case sym.RV_POWER_DS: 780 var o1 uint32 781 if ctxt.Arch.ByteOrder == binary.BigEndian { 782 o1 = uint32(ld.Be16(s.P[r.Off:])) 783 } else { 784 o1 = uint32(ld.Le16(s.P[r.Off:])) 785 } 786 if t&3 != 0 { 787 ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t) 788 } 789 if (r.Variant&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t { 790 goto overflow 791 } 792 return int64(o1)&0x3 | int64(int16(t)) 793 } 794 795 overflow: 796 ld.Errorf(s, "relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t) 797 return t 798 } 799 800 func addpltsym(ctxt *ld.Link, s *sym.Symbol) { 801 if s.Plt >= 0 { 802 return 803 } 804 805 ld.Adddynsym(ctxt, s) 806 807 if ctxt.IsELF { 808 plt := ctxt.Syms.Lookup(".plt", 0) 809 rela := ctxt.Syms.Lookup(".rela.plt", 0) 810 if plt.Size == 0 { 811 elfsetupplt(ctxt) 812 } 813 814 // Create the glink resolver if necessary 815 glink := ensureglinkresolver(ctxt) 816 817 // Write symbol resolver stub (just a branch to the 818 // glink resolver stub) 819 r := glink.AddRel() 820 821 r.Sym = glink 822 r.Off = int32(glink.Size) 823 r.Siz = 4 824 r.Type = objabi.R_CALLPOWER 825 glink.AddUint32(ctxt.Arch, 0x48000000) // b .glink 826 827 // In the ppc64 ABI, the dynamic linker is responsible 828 // for writing the entire PLT. We just need to 829 // reserve 8 bytes for each PLT entry and generate a 830 // JMP_SLOT dynamic relocation for it. 831 // 832 // TODO(austin): ABI v1 is different 833 s.Plt = int32(plt.Size) 834 835 plt.Size += 8 836 837 rela.AddAddrPlus(ctxt.Arch, plt, int64(s.Plt)) 838 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_PPC64_JMP_SLOT))) 839 rela.AddUint64(ctxt.Arch, 0) 840 } else { 841 ld.Errorf(s, "addpltsym: unsupported binary format") 842 } 843 } 844 845 // Generate the glink resolver stub if necessary and return the .glink section 846 func ensureglinkresolver(ctxt *ld.Link) *sym.Symbol { 847 glink := ctxt.Syms.Lookup(".glink", 0) 848 if glink.Size != 0 { 849 return glink 850 } 851 852 // This is essentially the resolver from the ppc64 ELF ABI. 853 // At entry, r12 holds the address of the symbol resolver stub 854 // for the target routine and the argument registers hold the 855 // arguments for the target routine. 856 // 857 // This stub is PIC, so first get the PC of label 1 into r11. 858 // Other things will be relative to this. 859 glink.AddUint32(ctxt.Arch, 0x7c0802a6) // mflr r0 860 glink.AddUint32(ctxt.Arch, 0x429f0005) // bcl 20,31,1f 861 glink.AddUint32(ctxt.Arch, 0x7d6802a6) // 1: mflr r11 862 glink.AddUint32(ctxt.Arch, 0x7c0803a6) // mtlf r0 863 864 // Compute the .plt array index from the entry point address. 865 // Because this is PIC, everything is relative to label 1b (in 866 // r11): 867 // r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4 868 glink.AddUint32(ctxt.Arch, 0x3800ffd0) // li r0,-(res_0-1b)=-48 869 glink.AddUint32(ctxt.Arch, 0x7c006214) // add r0,r0,r12 870 glink.AddUint32(ctxt.Arch, 0x7c0b0050) // sub r0,r0,r11 871 glink.AddUint32(ctxt.Arch, 0x7800f082) // srdi r0,r0,2 872 873 // r11 = address of the first byte of the PLT 874 r := glink.AddRel() 875 876 r.Off = int32(glink.Size) 877 r.Sym = ctxt.Syms.Lookup(".plt", 0) 878 r.Siz = 8 879 r.Type = objabi.R_ADDRPOWER 880 881 glink.AddUint32(ctxt.Arch, 0x3d600000) // addis r11,0,.plt@ha 882 glink.AddUint32(ctxt.Arch, 0x396b0000) // addi r11,r11,.plt@l 883 884 // Load r12 = dynamic resolver address and r11 = DSO 885 // identifier from the first two doublewords of the PLT. 886 glink.AddUint32(ctxt.Arch, 0xe98b0000) // ld r12,0(r11) 887 glink.AddUint32(ctxt.Arch, 0xe96b0008) // ld r11,8(r11) 888 889 // Jump to the dynamic resolver 890 glink.AddUint32(ctxt.Arch, 0x7d8903a6) // mtctr r12 891 glink.AddUint32(ctxt.Arch, 0x4e800420) // bctr 892 893 // The symbol resolvers must immediately follow. 894 // res_0: 895 896 // Add DT_PPC64_GLINK .dynamic entry, which points to 32 bytes 897 // before the first symbol resolver stub. 898 s := ctxt.Syms.Lookup(".dynamic", 0) 899 900 ld.Elfwritedynentsymplus(ctxt, s, ld.DT_PPC64_GLINK, glink, glink.Size-32) 901 902 return glink 903 } 904 905 func asmb(ctxt *ld.Link) { 906 if ctxt.Debugvlog != 0 { 907 ctxt.Logf("%5.2f asmb\n", ld.Cputime()) 908 } 909 910 if ctxt.IsELF { 911 ld.Asmbelfsetup() 912 } 913 914 for _, sect := range ld.Segtext.Sections { 915 ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 916 // Handle additional text sections with Codeblk 917 if sect.Name == ".text" { 918 ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length)) 919 } else { 920 ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length)) 921 } 922 } 923 924 if ld.Segrodata.Filelen > 0 { 925 if ctxt.Debugvlog != 0 { 926 ctxt.Logf("%5.2f rodatblk\n", ld.Cputime()) 927 } 928 ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff)) 929 ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen)) 930 } 931 if ld.Segrelrodata.Filelen > 0 { 932 if ctxt.Debugvlog != 0 { 933 ctxt.Logf("%5.2f relrodatblk\n", ld.Cputime()) 934 } 935 ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff)) 936 ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen)) 937 } 938 939 if ctxt.Debugvlog != 0 { 940 ctxt.Logf("%5.2f datblk\n", ld.Cputime()) 941 } 942 943 ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff)) 944 ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 945 946 ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff)) 947 ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen)) 948 949 /* output symbol table */ 950 ld.Symsize = 0 951 952 ld.Lcsize = 0 953 symo := uint32(0) 954 if !*ld.FlagS { 955 // TODO: rationalize 956 if ctxt.Debugvlog != 0 { 957 ctxt.Logf("%5.2f sym\n", ld.Cputime()) 958 } 959 switch ctxt.HeadType { 960 default: 961 if ctxt.IsELF { 962 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 963 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound))) 964 } 965 966 case objabi.Hplan9: 967 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 968 } 969 970 ctxt.Out.SeekSet(int64(symo)) 971 switch ctxt.HeadType { 972 default: 973 if ctxt.IsELF { 974 if ctxt.Debugvlog != 0 { 975 ctxt.Logf("%5.2f elfsym\n", ld.Cputime()) 976 } 977 ld.Asmelfsym(ctxt) 978 ctxt.Out.Flush() 979 ctxt.Out.Write(ld.Elfstrdat) 980 981 if ctxt.LinkMode == ld.LinkExternal { 982 ld.Elfemitreloc(ctxt) 983 } 984 } 985 986 case objabi.Hplan9: 987 ld.Asmplan9sym(ctxt) 988 ctxt.Out.Flush() 989 990 sym := ctxt.Syms.Lookup("pclntab", 0) 991 if sym != nil { 992 ld.Lcsize = int32(len(sym.P)) 993 ctxt.Out.Write(sym.P) 994 ctxt.Out.Flush() 995 } 996 } 997 } 998 999 if ctxt.Debugvlog != 0 { 1000 ctxt.Logf("%5.2f header\n", ld.Cputime()) 1001 } 1002 ctxt.Out.SeekSet(0) 1003 switch ctxt.HeadType { 1004 default: 1005 case objabi.Hplan9: /* plan 9 */ 1006 ctxt.Out.Write32(0x647) /* magic */ 1007 ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */ 1008 ctxt.Out.Write32(uint32(ld.Segdata.Filelen)) 1009 ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) 1010 ctxt.Out.Write32(uint32(ld.Symsize)) /* nsyms */ 1011 ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */ 1012 ctxt.Out.Write32(0) 1013 ctxt.Out.Write32(uint32(ld.Lcsize)) 1014 1015 case objabi.Hlinux, 1016 objabi.Hfreebsd, 1017 objabi.Hnetbsd, 1018 objabi.Hopenbsd, 1019 objabi.Hnacl: 1020 ld.Asmbelf(ctxt, int64(symo)) 1021 } 1022 1023 ctxt.Out.Flush() 1024 if *ld.FlagC { 1025 fmt.Printf("textsize=%d\n", ld.Segtext.Filelen) 1026 fmt.Printf("datsize=%d\n", ld.Segdata.Filelen) 1027 fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen) 1028 fmt.Printf("symsize=%d\n", ld.Symsize) 1029 fmt.Printf("lcsize=%d\n", ld.Lcsize) 1030 fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize)) 1031 } 1032 }