github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/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) int64 { 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 -1 514 } 515 516 if ctxt.Arch.ByteOrder == binary.BigEndian { 517 return int64(o1)<<32 | int64(o2) 518 } 519 return int64(o2)<<32 | int64(o1) 520 } 521 522 // resolve direct jump relocation r in s, and add trampoline if necessary 523 func trampoline(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol) { 524 525 // Trampolines are created if the branch offset is too large and the linker cannot insert a call stub to handle it. 526 // For internal linking, trampolines are always created for long calls. 527 // For external linking, the linker can insert a call stub to handle a long call, but depends on having the TOC address in 528 // r2. For those build modes with external linking where the TOC address is not maintained in r2, trampolines must be created. 529 if ctxt.LinkMode == ld.LinkExternal && (ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE) { 530 // No trampolines needed since r2 contains the TOC 531 return 532 } 533 534 t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off)) 535 switch r.Type { 536 case objabi.R_CALLPOWER: 537 538 // If branch offset is too far then create a trampoline. 539 540 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) { 541 var tramp *sym.Symbol 542 for i := 0; ; i++ { 543 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, 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) (int64, bool) { 625 if ctxt.LinkMode == ld.LinkExternal { 626 switch r.Type { 627 default: 628 return val, 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 val, 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 val, true 657 case objabi.R_CALLPOWER: 658 r.Done = false 659 r.Xsym = r.Sym 660 r.Xadd = r.Add 661 return val, true 662 } 663 } 664 665 switch r.Type { 666 case objabi.R_CONST: 667 return r.Add, true 668 case objabi.R_GOTOFF: 669 return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true 670 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS: 671 return archrelocaddr(ctxt, r, s, val), true 672 case objabi.R_CALLPOWER: 673 // Bits 6 through 29 = (S + A - P) >> 2 674 675 t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off)) 676 677 if t&3 != 0 { 678 ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t) 679 } 680 // If branch offset is too far then create a trampoline. 681 682 if int64(int32(t<<6)>>6) != t { 683 ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t) 684 } 685 return val | int64(uint32(t)&^0xfc000003), true 686 case objabi.R_POWER_TOC: // S + A - .TOC. 687 return ld.Symaddr(r.Sym) + r.Add - symtoc(ctxt, s), true 688 689 case objabi.R_POWER_TLS_LE: 690 // The thread pointer points 0x7000 bytes after the start of the 691 // thread local storage area as documented in section "3.7.2 TLS 692 // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI 693 // Specification". 694 v := r.Sym.Value - 0x7000 695 if ctxt.HeadType == objabi.Haix { 696 // On AIX, the thread pointer points 0x7800 bytes after 697 // the TLS. 698 v -= 0x800 699 } 700 if int64(int16(v)) != v { 701 ld.Errorf(s, "TLS offset out of range %d", v) 702 } 703 return (val &^ 0xffff) | (v & 0xffff), true 704 } 705 706 return val, 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 = binary.BigEndian.Uint32(s.P[r.Off-2:]) 725 } else { 726 o1 = binary.LittleEndian.Uint32(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 = binary.BigEndian.Uint32(s.P[r.Off-2:]) 759 } else { 760 o1 = binary.LittleEndian.Uint32(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(binary.BigEndian.Uint16(s.P[r.Off:])) 783 } else { 784 o1 = uint32(binary.LittleEndian.Uint16(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.SetPlt(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 loadersize := uint64(0) 950 if ctxt.HeadType == objabi.Haix && ctxt.BuildMode == ld.BuildModeExe { 951 loadero := uint64(ld.Rnd(int64(ld.Segdwarf.Fileoff+ld.Segdwarf.Filelen), int64(*ld.FlagRound))) 952 ctxt.Out.SeekSet(int64(loadero)) 953 loadersize = ld.Loaderblk(ctxt, loadero) 954 } 955 956 /* output symbol table */ 957 ld.Symsize = 0 958 959 ld.Lcsize = 0 960 symo := uint32(0) 961 if !*ld.FlagS { 962 // TODO: rationalize 963 if ctxt.Debugvlog != 0 { 964 ctxt.Logf("%5.2f sym\n", ld.Cputime()) 965 } 966 switch ctxt.HeadType { 967 default: 968 if ctxt.IsELF { 969 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 970 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound))) 971 } 972 973 case objabi.Hplan9: 974 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 975 976 case objabi.Haix: 977 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 978 979 // Add loader size if needed 980 if ctxt.BuildMode == ld.BuildModeExe { 981 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound))) 982 symo += uint32(loadersize) 983 } 984 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound))) 985 } 986 987 ctxt.Out.SeekSet(int64(symo)) 988 switch ctxt.HeadType { 989 default: 990 if ctxt.IsELF { 991 if ctxt.Debugvlog != 0 { 992 ctxt.Logf("%5.2f elfsym\n", ld.Cputime()) 993 } 994 ld.Asmelfsym(ctxt) 995 ctxt.Out.Flush() 996 ctxt.Out.Write(ld.Elfstrdat) 997 998 if ctxt.LinkMode == ld.LinkExternal { 999 ld.Elfemitreloc(ctxt) 1000 } 1001 } 1002 1003 case objabi.Hplan9: 1004 ld.Asmplan9sym(ctxt) 1005 ctxt.Out.Flush() 1006 1007 sym := ctxt.Syms.Lookup("pclntab", 0) 1008 if sym != nil { 1009 ld.Lcsize = int32(len(sym.P)) 1010 ctxt.Out.Write(sym.P) 1011 ctxt.Out.Flush() 1012 } 1013 1014 case objabi.Haix: 1015 ld.Asmaixsym(ctxt) 1016 ctxt.Out.Flush() 1017 } 1018 } 1019 1020 if ctxt.Debugvlog != 0 { 1021 ctxt.Logf("%5.2f header\n", ld.Cputime()) 1022 } 1023 ctxt.Out.SeekSet(0) 1024 switch ctxt.HeadType { 1025 default: 1026 case objabi.Hplan9: /* plan 9 */ 1027 ctxt.Out.Write32(0x647) /* magic */ 1028 ctxt.Out.Write32(uint32(ld.Segtext.Filelen)) /* sizes */ 1029 ctxt.Out.Write32(uint32(ld.Segdata.Filelen)) 1030 ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) 1031 ctxt.Out.Write32(uint32(ld.Symsize)) /* nsyms */ 1032 ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt))) /* va of entry */ 1033 ctxt.Out.Write32(0) 1034 ctxt.Out.Write32(uint32(ld.Lcsize)) 1035 1036 case objabi.Hlinux, 1037 objabi.Hfreebsd, 1038 objabi.Hnetbsd, 1039 objabi.Hopenbsd, 1040 objabi.Hnacl: 1041 ld.Asmbelf(ctxt, int64(symo)) 1042 1043 case objabi.Haix: 1044 ld.Asmbxcoff(ctxt) 1045 } 1046 1047 ctxt.Out.Flush() 1048 if *ld.FlagC { 1049 fmt.Printf("textsize=%d\n", ld.Segtext.Filelen) 1050 fmt.Printf("datsize=%d\n", ld.Segdata.Filelen) 1051 fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen) 1052 fmt.Printf("symsize=%d\n", ld.Symsize) 1053 fmt.Printf("lcsize=%d\n", ld.Lcsize) 1054 fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize)) 1055 } 1056 }