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