github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/cmd/link/internal/ppc64/asm.go (about) 1 // Inferno utils/5l/asm.c 2 // http://code.google.com/p/inferno-os/source/browse/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/obj" 35 "cmd/link/internal/ld" 36 "encoding/binary" 37 "fmt" 38 "log" 39 ) 40 41 func genplt() { 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 ld.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(ld.Ctxt, r.Sym) 100 101 // Generate call stub 102 n := fmt.Sprintf("%s.%s", s.Name, r.Sym.Name) 103 104 stub := ld.Linklookup(ld.Ctxt, 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 ld.Ctxt.Textp = append(ld.Ctxt.Textp, stub) 112 gencallstub(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 ld.Ctxt.Arch.ByteOrder.PutUint32(s.P[r.Off+4:], o1) 122 } 123 } 124 } 125 126 func genaddmoduledata() { 127 addmoduledata := ld.Linkrlookup(ld.Ctxt, "runtime.addmoduledata", 0) 128 if addmoduledata.Type == obj.STEXT { 129 return 130 } 131 addmoduledata.Attr |= ld.AttrReachable 132 initfunc := ld.Linklookup(ld.Ctxt, "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(ld.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 = ld.Linklookup(ld.Ctxt, ".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 = ld.Linklookup(ld.Ctxt, "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 ld.Ctxt.Textp = append(ld.Ctxt.Textp, initfunc) 180 initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0) 181 initarray_entry.Attr |= ld.AttrReachable 182 initarray_entry.Attr |= ld.AttrLocal 183 initarray_entry.Type = obj.SINITARR 184 ld.Addaddr(ld.Ctxt, initarray_entry, initfunc) 185 } 186 187 func gentext() { 188 if ld.DynlinkingGo() { 189 genaddmoduledata() 190 } 191 192 if ld.Linkmode == ld.LinkInternal { 193 genplt() 194 } 195 } 196 197 // Construct a call stub in stub that calls symbol targ via its PLT 198 // entry. 199 func gencallstub(abicase int, stub *ld.LSym, targ *ld.LSym) { 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 := ld.Linklookup(ld.Ctxt, ".plt", 0) 207 208 stub.Type = obj.STEXT 209 210 // Save TOC pointer in TOC save slot 211 ld.Adduint32(ld.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 ld.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(ld.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 ld.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(ld.Ctxt, stub, 0xe98c0000) // ld r12,targ@plt@toc@l(r12) 237 238 // Jump to the loaded pointer 239 ld.Adduint32(ld.Ctxt, stub, 0x7d8903a6) // mtctr r12 240 ld.Adduint32(ld.Ctxt, stub, 0x4e800420) // bctr 241 } 242 243 func adddynrel(s *ld.LSym, r *ld.Reloc) { 244 targ := r.Sym 245 ld.Ctxt.Cursym = s 246 247 switch r.Type { 248 default: 249 if r.Type >= 256 { 250 ld.Diag("unexpected relocation type %d", r.Type) 251 return 252 } 253 254 // Handle relocations found in ELF object files. 255 case 256 + ld.R_PPC64_REL24: 256 r.Type = obj.R_CALLPOWER 257 258 // This is a local call, so the caller isn't setting 259 // up r12 and r2 is the same for the caller and 260 // callee. Hence, we need to go to the local entry 261 // point. (If we don't do this, the callee will try 262 // to use r12 to compute r2.) 263 r.Add += int64(r.Sym.Localentry) * 4 264 265 if targ.Type == obj.SDYNIMPORT { 266 // Should have been handled in elfsetupplt 267 ld.Diag("unexpected R_PPC64_REL24 for dyn import") 268 } 269 270 return 271 272 case 256 + ld.R_PPC_REL32: 273 r.Type = obj.R_PCREL 274 r.Add += 4 275 276 if targ.Type == obj.SDYNIMPORT { 277 ld.Diag("unexpected R_PPC_REL32 for dyn import") 278 } 279 280 return 281 282 case 256 + ld.R_PPC64_ADDR64: 283 r.Type = obj.R_ADDR 284 if targ.Type == obj.SDYNIMPORT { 285 // These happen in .toc sections 286 ld.Adddynsym(ld.Ctxt, targ) 287 288 rela := ld.Linklookup(ld.Ctxt, ".rela", 0) 289 ld.Addaddrplus(ld.Ctxt, rela, s, int64(r.Off)) 290 ld.Adduint64(ld.Ctxt, rela, ld.ELF64_R_INFO(uint32(targ.Dynid), ld.R_PPC64_ADDR64)) 291 ld.Adduint64(ld.Ctxt, rela, uint64(r.Add)) 292 r.Type = 256 // ignore during relocsym 293 } 294 295 return 296 297 case 256 + ld.R_PPC64_TOC16: 298 r.Type = obj.R_POWER_TOC 299 r.Variant = ld.RV_POWER_LO | ld.RV_CHECK_OVERFLOW 300 return 301 302 case 256 + ld.R_PPC64_TOC16_LO: 303 r.Type = obj.R_POWER_TOC 304 r.Variant = ld.RV_POWER_LO 305 return 306 307 case 256 + ld.R_PPC64_TOC16_HA: 308 r.Type = obj.R_POWER_TOC 309 r.Variant = ld.RV_POWER_HA | ld.RV_CHECK_OVERFLOW 310 return 311 312 case 256 + ld.R_PPC64_TOC16_HI: 313 r.Type = obj.R_POWER_TOC 314 r.Variant = ld.RV_POWER_HI | ld.RV_CHECK_OVERFLOW 315 return 316 317 case 256 + ld.R_PPC64_TOC16_DS: 318 r.Type = obj.R_POWER_TOC 319 r.Variant = ld.RV_POWER_DS | ld.RV_CHECK_OVERFLOW 320 return 321 322 case 256 + ld.R_PPC64_TOC16_LO_DS: 323 r.Type = obj.R_POWER_TOC 324 r.Variant = ld.RV_POWER_DS 325 return 326 327 case 256 + ld.R_PPC64_REL16_LO: 328 r.Type = obj.R_PCREL 329 r.Variant = ld.RV_POWER_LO 330 r.Add += 2 // Compensate for relocation size of 2 331 return 332 333 case 256 + ld.R_PPC64_REL16_HI: 334 r.Type = obj.R_PCREL 335 r.Variant = ld.RV_POWER_HI | ld.RV_CHECK_OVERFLOW 336 r.Add += 2 337 return 338 339 case 256 + ld.R_PPC64_REL16_HA: 340 r.Type = obj.R_PCREL 341 r.Variant = ld.RV_POWER_HA | ld.RV_CHECK_OVERFLOW 342 r.Add += 2 343 return 344 } 345 346 // Handle references to ELF symbols from our own object files. 347 if targ.Type != obj.SDYNIMPORT { 348 return 349 } 350 351 // TODO(austin): Translate our relocations to ELF 352 353 ld.Diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ.Name, r.Type, targ.Type) 354 } 355 356 func elfreloc1(r *ld.Reloc, sectoff int64) int { 357 ld.Thearch.Vput(uint64(sectoff)) 358 359 elfsym := r.Xsym.ElfsymForReloc() 360 switch r.Type { 361 default: 362 return -1 363 364 case obj.R_ADDR: 365 switch r.Siz { 366 case 4: 367 ld.Thearch.Vput(ld.R_PPC64_ADDR32 | uint64(elfsym)<<32) 368 case 8: 369 ld.Thearch.Vput(ld.R_PPC64_ADDR64 | uint64(elfsym)<<32) 370 default: 371 return -1 372 } 373 374 case obj.R_POWER_TLS: 375 ld.Thearch.Vput(ld.R_PPC64_TLS | uint64(elfsym)<<32) 376 377 case obj.R_POWER_TLS_LE: 378 ld.Thearch.Vput(ld.R_PPC64_TPREL16 | uint64(elfsym)<<32) 379 380 case obj.R_POWER_TLS_IE: 381 ld.Thearch.Vput(ld.R_PPC64_GOT_TPREL16_HA | uint64(elfsym)<<32) 382 ld.Thearch.Vput(uint64(r.Xadd)) 383 ld.Thearch.Vput(uint64(sectoff + 4)) 384 ld.Thearch.Vput(ld.R_PPC64_GOT_TPREL16_LO_DS | uint64(elfsym)<<32) 385 386 case obj.R_ADDRPOWER: 387 ld.Thearch.Vput(ld.R_PPC64_ADDR16_HA | uint64(elfsym)<<32) 388 ld.Thearch.Vput(uint64(r.Xadd)) 389 ld.Thearch.Vput(uint64(sectoff + 4)) 390 ld.Thearch.Vput(ld.R_PPC64_ADDR16_LO | uint64(elfsym)<<32) 391 392 case obj.R_ADDRPOWER_DS: 393 ld.Thearch.Vput(ld.R_PPC64_ADDR16_HA | uint64(elfsym)<<32) 394 ld.Thearch.Vput(uint64(r.Xadd)) 395 ld.Thearch.Vput(uint64(sectoff + 4)) 396 ld.Thearch.Vput(ld.R_PPC64_ADDR16_LO_DS | uint64(elfsym)<<32) 397 398 case obj.R_ADDRPOWER_GOT: 399 ld.Thearch.Vput(ld.R_PPC64_GOT16_HA | uint64(elfsym)<<32) 400 ld.Thearch.Vput(uint64(r.Xadd)) 401 ld.Thearch.Vput(uint64(sectoff + 4)) 402 ld.Thearch.Vput(ld.R_PPC64_GOT16_LO_DS | uint64(elfsym)<<32) 403 404 case obj.R_ADDRPOWER_PCREL: 405 ld.Thearch.Vput(ld.R_PPC64_REL16_HA | uint64(elfsym)<<32) 406 ld.Thearch.Vput(uint64(r.Xadd)) 407 ld.Thearch.Vput(uint64(sectoff + 4)) 408 ld.Thearch.Vput(ld.R_PPC64_REL16_LO | uint64(elfsym)<<32) 409 r.Xadd += 4 410 411 case obj.R_ADDRPOWER_TOCREL: 412 ld.Thearch.Vput(ld.R_PPC64_TOC16_HA | uint64(elfsym)<<32) 413 ld.Thearch.Vput(uint64(r.Xadd)) 414 ld.Thearch.Vput(uint64(sectoff + 4)) 415 ld.Thearch.Vput(ld.R_PPC64_TOC16_LO | uint64(elfsym)<<32) 416 417 case obj.R_ADDRPOWER_TOCREL_DS: 418 ld.Thearch.Vput(ld.R_PPC64_TOC16_HA | uint64(elfsym)<<32) 419 ld.Thearch.Vput(uint64(r.Xadd)) 420 ld.Thearch.Vput(uint64(sectoff + 4)) 421 ld.Thearch.Vput(ld.R_PPC64_TOC16_LO_DS | uint64(elfsym)<<32) 422 423 case obj.R_CALLPOWER: 424 if r.Siz != 4 { 425 return -1 426 } 427 ld.Thearch.Vput(ld.R_PPC64_REL24 | uint64(elfsym)<<32) 428 429 } 430 ld.Thearch.Vput(uint64(r.Xadd)) 431 432 return 0 433 } 434 435 func elfsetupplt() { 436 plt := ld.Linklookup(ld.Ctxt, ".plt", 0) 437 if plt.Size == 0 { 438 // The dynamic linker stores the address of the 439 // dynamic resolver and the DSO identifier in the two 440 // doublewords at the beginning of the .plt section 441 // before the PLT array. Reserve space for these. 442 plt.Size = 16 443 } 444 } 445 446 func machoreloc1(r *ld.Reloc, sectoff int64) int { 447 return -1 448 } 449 450 // Return the value of .TOC. for symbol s 451 func symtoc(s *ld.LSym) int64 { 452 var toc *ld.LSym 453 454 if s.Outer != nil { 455 toc = ld.Linkrlookup(ld.Ctxt, ".TOC.", int(s.Outer.Version)) 456 } else { 457 toc = ld.Linkrlookup(ld.Ctxt, ".TOC.", int(s.Version)) 458 } 459 460 if toc == nil { 461 ld.Diag("TOC-relative relocation in object without .TOC.") 462 return 0 463 } 464 465 return toc.Value 466 } 467 468 func archrelocaddr(r *ld.Reloc, s *ld.LSym, val *int64) int { 469 var o1, o2 uint32 470 if ld.Ctxt.Arch.ByteOrder == binary.BigEndian { 471 o1 = uint32(*val >> 32) 472 o2 = uint32(*val) 473 } else { 474 o1 = uint32(*val) 475 o2 = uint32(*val >> 32) 476 } 477 478 // We are spreading a 31-bit address across two instructions, putting the 479 // high (adjusted) part in the low 16 bits of the first instruction and the 480 // low part in the low 16 bits of the second instruction, or, in the DS case, 481 // bits 15-2 (inclusive) of the address into bits 15-2 of the second 482 // instruction (it is an error in this case if the low 2 bits of the address 483 // are non-zero). 484 485 t := ld.Symaddr(r.Sym) + r.Add 486 if t < 0 || t >= 1<<31 { 487 ld.Ctxt.Diag("relocation for %s is too big (>=2G): %d", s.Name, ld.Symaddr(r.Sym)) 488 } 489 if t&0x8000 != 0 { 490 t += 0x10000 491 } 492 493 switch r.Type { 494 case obj.R_ADDRPOWER: 495 o1 |= (uint32(t) >> 16) & 0xffff 496 o2 |= uint32(t) & 0xffff 497 498 case obj.R_ADDRPOWER_DS: 499 o1 |= (uint32(t) >> 16) & 0xffff 500 if t&3 != 0 { 501 ld.Ctxt.Diag("bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym)) 502 } 503 o2 |= uint32(t) & 0xfffc 504 505 default: 506 return -1 507 } 508 509 if ld.Ctxt.Arch.ByteOrder == binary.BigEndian { 510 *val = int64(o1)<<32 | int64(o2) 511 } else { 512 *val = int64(o2)<<32 | int64(o1) 513 } 514 return 0 515 } 516 517 func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int { 518 if ld.Linkmode == ld.LinkExternal { 519 switch r.Type { 520 default: 521 return -1 522 523 case obj.R_POWER_TLS, obj.R_POWER_TLS_LE, obj.R_POWER_TLS_IE: 524 r.Done = 0 525 // check Outer is nil, Type is TLSBSS? 526 r.Xadd = r.Add 527 r.Xsym = r.Sym 528 return 0 529 530 case obj.R_ADDRPOWER, 531 obj.R_ADDRPOWER_DS, 532 obj.R_ADDRPOWER_TOCREL, 533 obj.R_ADDRPOWER_TOCREL_DS, 534 obj.R_ADDRPOWER_GOT, 535 obj.R_ADDRPOWER_PCREL: 536 r.Done = 0 537 538 // set up addend for eventual relocation via outer symbol. 539 rs := r.Sym 540 r.Xadd = r.Add 541 for rs.Outer != nil { 542 r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer) 543 rs = rs.Outer 544 } 545 546 if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil { 547 ld.Diag("missing section for %s", rs.Name) 548 } 549 r.Xsym = rs 550 551 return 0 552 553 case obj.R_CALLPOWER: 554 r.Done = 0 555 r.Xsym = r.Sym 556 r.Xadd = r.Add 557 return 0 558 } 559 } 560 561 switch r.Type { 562 case obj.R_CONST: 563 *val = r.Add 564 return 0 565 566 case obj.R_GOTOFF: 567 *val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0)) 568 return 0 569 570 case obj.R_ADDRPOWER, obj.R_ADDRPOWER_DS: 571 return archrelocaddr(r, s, val) 572 573 case obj.R_CALLPOWER: 574 // Bits 6 through 29 = (S + A - P) >> 2 575 576 t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off)) 577 if t&3 != 0 { 578 ld.Ctxt.Diag("relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t) 579 } 580 if int64(int32(t<<6)>>6) != t { 581 // TODO(austin) This can happen if text > 32M. 582 // Add a call trampoline to .text in that case. 583 ld.Ctxt.Diag("relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t) 584 } 585 586 *val |= int64(uint32(t) &^ 0xfc000003) 587 return 0 588 589 case obj.R_POWER_TOC: // S + A - .TOC. 590 *val = ld.Symaddr(r.Sym) + r.Add - symtoc(s) 591 592 return 0 593 594 case obj.R_POWER_TLS_LE: 595 // The thread pointer points 0x7000 bytes after the start of the the 596 // thread local storage area as documented in section "3.7.2 TLS 597 // Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI 598 // Specification". 599 v := r.Sym.Value - 0x7000 600 if int64(int16(v)) != v { 601 ld.Diag("TLS offset out of range %d", v) 602 } 603 *val = (*val &^ 0xffff) | (v & 0xffff) 604 return 0 605 } 606 607 return -1 608 } 609 610 func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 { 611 switch r.Variant & ld.RV_TYPE_MASK { 612 default: 613 ld.Diag("unexpected relocation variant %d", r.Variant) 614 fallthrough 615 616 case ld.RV_NONE: 617 return t 618 619 case ld.RV_POWER_LO: 620 if r.Variant&ld.RV_CHECK_OVERFLOW != 0 { 621 // Whether to check for signed or unsigned 622 // overflow depends on the instruction 623 var o1 uint32 624 if ld.Ctxt.Arch.ByteOrder == binary.BigEndian { 625 o1 = ld.Be32(s.P[r.Off-2:]) 626 } else { 627 o1 = ld.Le32(s.P[r.Off:]) 628 } 629 switch o1 >> 26 { 630 case 24, // ori 631 26, // xori 632 28: // andi 633 if t>>16 != 0 { 634 goto overflow 635 } 636 637 default: 638 if int64(int16(t)) != t { 639 goto overflow 640 } 641 } 642 } 643 644 return int64(int16(t)) 645 646 case ld.RV_POWER_HA: 647 t += 0x8000 648 fallthrough 649 650 // Fallthrough 651 case ld.RV_POWER_HI: 652 t >>= 16 653 654 if r.Variant&ld.RV_CHECK_OVERFLOW != 0 { 655 // Whether to check for signed or unsigned 656 // overflow depends on the instruction 657 var o1 uint32 658 if ld.Ctxt.Arch.ByteOrder == binary.BigEndian { 659 o1 = ld.Be32(s.P[r.Off-2:]) 660 } else { 661 o1 = ld.Le32(s.P[r.Off:]) 662 } 663 switch o1 >> 26 { 664 case 25, // oris 665 27, // xoris 666 29: // andis 667 if t>>16 != 0 { 668 goto overflow 669 } 670 671 default: 672 if int64(int16(t)) != t { 673 goto overflow 674 } 675 } 676 } 677 678 return int64(int16(t)) 679 680 case ld.RV_POWER_DS: 681 var o1 uint32 682 if ld.Ctxt.Arch.ByteOrder == binary.BigEndian { 683 o1 = uint32(ld.Be16(s.P[r.Off:])) 684 } else { 685 o1 = uint32(ld.Le16(s.P[r.Off:])) 686 } 687 if t&3 != 0 { 688 ld.Diag("relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t) 689 } 690 if (r.Variant&ld.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t { 691 goto overflow 692 } 693 return int64(o1)&0x3 | int64(int16(t)) 694 } 695 696 overflow: 697 ld.Diag("relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t) 698 return t 699 } 700 701 func addpltsym(ctxt *ld.Link, s *ld.LSym) { 702 if s.Plt >= 0 { 703 return 704 } 705 706 ld.Adddynsym(ctxt, s) 707 708 if ld.Iself { 709 plt := ld.Linklookup(ctxt, ".plt", 0) 710 rela := ld.Linklookup(ctxt, ".rela.plt", 0) 711 if plt.Size == 0 { 712 elfsetupplt() 713 } 714 715 // Create the glink resolver if necessary 716 glink := ensureglinkresolver() 717 718 // Write symbol resolver stub (just a branch to the 719 // glink resolver stub) 720 r := ld.Addrel(glink) 721 722 r.Sym = glink 723 r.Off = int32(glink.Size) 724 r.Siz = 4 725 r.Type = obj.R_CALLPOWER 726 ld.Adduint32(ctxt, glink, 0x48000000) // b .glink 727 728 // In the ppc64 ABI, the dynamic linker is responsible 729 // for writing the entire PLT. We just need to 730 // reserve 8 bytes for each PLT entry and generate a 731 // JMP_SLOT dynamic relocation for it. 732 // 733 // TODO(austin): ABI v1 is different 734 s.Plt = int32(plt.Size) 735 736 plt.Size += 8 737 738 ld.Addaddrplus(ctxt, rela, plt, int64(s.Plt)) 739 ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_PPC64_JMP_SLOT)) 740 ld.Adduint64(ctxt, rela, 0) 741 } else { 742 ld.Diag("addpltsym: unsupported binary format") 743 } 744 } 745 746 // Generate the glink resolver stub if necessary and return the .glink section 747 func ensureglinkresolver() *ld.LSym { 748 glink := ld.Linklookup(ld.Ctxt, ".glink", 0) 749 if glink.Size != 0 { 750 return glink 751 } 752 753 // This is essentially the resolver from the ppc64 ELF ABI. 754 // At entry, r12 holds the address of the symbol resolver stub 755 // for the target routine and the argument registers hold the 756 // arguments for the target routine. 757 // 758 // This stub is PIC, so first get the PC of label 1 into r11. 759 // Other things will be relative to this. 760 ld.Adduint32(ld.Ctxt, glink, 0x7c0802a6) // mflr r0 761 ld.Adduint32(ld.Ctxt, glink, 0x429f0005) // bcl 20,31,1f 762 ld.Adduint32(ld.Ctxt, glink, 0x7d6802a6) // 1: mflr r11 763 ld.Adduint32(ld.Ctxt, glink, 0x7c0803a6) // mtlf r0 764 765 // Compute the .plt array index from the entry point address. 766 // Because this is PIC, everything is relative to label 1b (in 767 // r11): 768 // r0 = ((r12 - r11) - (res_0 - r11)) / 4 = (r12 - res_0) / 4 769 ld.Adduint32(ld.Ctxt, glink, 0x3800ffd0) // li r0,-(res_0-1b)=-48 770 ld.Adduint32(ld.Ctxt, glink, 0x7c006214) // add r0,r0,r12 771 ld.Adduint32(ld.Ctxt, glink, 0x7c0b0050) // sub r0,r0,r11 772 ld.Adduint32(ld.Ctxt, glink, 0x7800f082) // srdi r0,r0,2 773 774 // r11 = address of the first byte of the PLT 775 r := ld.Addrel(glink) 776 777 r.Off = int32(glink.Size) 778 r.Sym = ld.Linklookup(ld.Ctxt, ".plt", 0) 779 r.Siz = 8 780 r.Type = obj.R_ADDRPOWER 781 782 ld.Adduint32(ld.Ctxt, glink, 0x3d600000) // addis r11,0,.plt@ha 783 ld.Adduint32(ld.Ctxt, glink, 0x396b0000) // addi r11,r11,.plt@l 784 785 // Load r12 = dynamic resolver address and r11 = DSO 786 // identifier from the first two doublewords of the PLT. 787 ld.Adduint32(ld.Ctxt, glink, 0xe98b0000) // ld r12,0(r11) 788 ld.Adduint32(ld.Ctxt, glink, 0xe96b0008) // ld r11,8(r11) 789 790 // Jump to the dynamic resolver 791 ld.Adduint32(ld.Ctxt, glink, 0x7d8903a6) // mtctr r12 792 ld.Adduint32(ld.Ctxt, glink, 0x4e800420) // bctr 793 794 // The symbol resolvers must immediately follow. 795 // res_0: 796 797 // Add DT_PPC64_GLINK .dynamic entry, which points to 32 bytes 798 // before the first symbol resolver stub. 799 s := ld.Linklookup(ld.Ctxt, ".dynamic", 0) 800 801 ld.Elfwritedynentsymplus(s, ld.DT_PPC64_GLINK, glink, glink.Size-32) 802 803 return glink 804 } 805 806 func asmb() { 807 if ld.Debug['v'] != 0 { 808 fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime()) 809 } 810 ld.Bso.Flush() 811 812 if ld.Iself { 813 ld.Asmbelfsetup() 814 } 815 816 sect := ld.Segtext.Sect 817 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 818 ld.Codeblk(int64(sect.Vaddr), int64(sect.Length)) 819 for sect = sect.Next; sect != nil; sect = sect.Next { 820 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 821 ld.Datblk(int64(sect.Vaddr), int64(sect.Length)) 822 } 823 824 if ld.Segrodata.Filelen > 0 { 825 if ld.Debug['v'] != 0 { 826 fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime()) 827 } 828 ld.Bso.Flush() 829 830 ld.Cseek(int64(ld.Segrodata.Fileoff)) 831 ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen)) 832 } 833 834 if ld.Debug['v'] != 0 { 835 fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime()) 836 } 837 ld.Bso.Flush() 838 839 ld.Cseek(int64(ld.Segdata.Fileoff)) 840 ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 841 842 ld.Cseek(int64(ld.Segdwarf.Fileoff)) 843 ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen)) 844 845 /* output symbol table */ 846 ld.Symsize = 0 847 848 ld.Lcsize = 0 849 symo := uint32(0) 850 if ld.Debug['s'] == 0 { 851 // TODO: rationalize 852 if ld.Debug['v'] != 0 { 853 fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime()) 854 } 855 ld.Bso.Flush() 856 switch ld.HEADTYPE { 857 default: 858 if ld.Iself { 859 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 860 symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND))) 861 } 862 863 case obj.Hplan9: 864 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen) 865 } 866 867 ld.Cseek(int64(symo)) 868 switch ld.HEADTYPE { 869 default: 870 if ld.Iself { 871 if ld.Debug['v'] != 0 { 872 fmt.Fprintf(ld.Bso, "%5.2f elfsym\n", obj.Cputime()) 873 } 874 ld.Asmelfsym() 875 ld.Cflush() 876 ld.Cwrite(ld.Elfstrdat) 877 878 if ld.Linkmode == ld.LinkExternal { 879 ld.Elfemitreloc() 880 } 881 } 882 883 case obj.Hplan9: 884 ld.Asmplan9sym() 885 ld.Cflush() 886 887 sym := ld.Linklookup(ld.Ctxt, "pclntab", 0) 888 if sym != nil { 889 ld.Lcsize = int32(len(sym.P)) 890 for i := 0; int32(i) < ld.Lcsize; i++ { 891 ld.Cput(sym.P[i]) 892 } 893 894 ld.Cflush() 895 } 896 } 897 } 898 899 ld.Ctxt.Cursym = nil 900 if ld.Debug['v'] != 0 { 901 fmt.Fprintf(ld.Bso, "%5.2f header\n", obj.Cputime()) 902 } 903 ld.Bso.Flush() 904 ld.Cseek(0) 905 switch ld.HEADTYPE { 906 default: 907 case obj.Hplan9: /* plan 9 */ 908 ld.Thearch.Lput(0x647) /* magic */ 909 ld.Thearch.Lput(uint32(ld.Segtext.Filelen)) /* sizes */ 910 ld.Thearch.Lput(uint32(ld.Segdata.Filelen)) 911 ld.Thearch.Lput(uint32(ld.Segdata.Length - ld.Segdata.Filelen)) 912 ld.Thearch.Lput(uint32(ld.Symsize)) /* nsyms */ 913 ld.Thearch.Lput(uint32(ld.Entryvalue())) /* va of entry */ 914 ld.Thearch.Lput(0) 915 ld.Thearch.Lput(uint32(ld.Lcsize)) 916 917 case obj.Hlinux, 918 obj.Hfreebsd, 919 obj.Hnetbsd, 920 obj.Hopenbsd, 921 obj.Hnacl: 922 ld.Asmbelf(int64(symo)) 923 } 924 925 ld.Cflush() 926 if ld.Debug['c'] != 0 { 927 fmt.Printf("textsize=%d\n", ld.Segtext.Filelen) 928 fmt.Printf("datsize=%d\n", ld.Segdata.Filelen) 929 fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen) 930 fmt.Printf("symsize=%d\n", ld.Symsize) 931 fmt.Printf("lcsize=%d\n", ld.Lcsize) 932 fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize)) 933 } 934 }