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