1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package ppc64
32
33 import (
34 "cmd/internal/objabi"
35 "cmd/internal/sys"
36 "cmd/link/internal/ld"
37 "cmd/link/internal/loader"
38 "cmd/link/internal/sym"
39 "debug/elf"
40 "encoding/binary"
41 "fmt"
42 "internal/buildcfg"
43 "log"
44 "strconv"
45 "strings"
46 )
47
48
49 var hasPCrel = buildcfg.GOPPC64 >= 10 && buildcfg.GOOS == "linux"
50
51 const (
52
53 STUB_TOC = iota
54 STUB_PCREL
55 )
56
57 var stubStrs = []string{
58 STUB_TOC: "_callstub_toc",
59 STUB_PCREL: "_callstub_pcrel",
60 }
61
62 const (
63 OP_TOCRESTORE = 0xe8410018
64 OP_TOCSAVE = 0xf8410018
65 OP_NOP = 0x60000000
66 OP_BL = 0x48000001
67 OP_BCTR = 0x4e800420
68 OP_BCTRL = 0x4e800421
69 OP_BCL = 0x40000001
70 OP_ADDI = 0x38000000
71 OP_ADDIS = 0x3c000000
72 OP_LD = 0xe8000000
73 OP_PLA_PFX = 0x06100000
74 OP_PLA_SFX = 0x38000000
75 OP_PLD_PFX_PCREL = 0x04100000
76 OP_PLD_SFX = 0xe4000000
77 OP_MFLR = 0x7c0802a6
78 OP_MTLR = 0x7c0803a6
79 OP_MFCTR = 0x7c0902a6
80 OP_MTCTR = 0x7c0903a6
81
82 OP_ADDIS_R12_R2 = OP_ADDIS | 12<<21 | 2<<16
83 OP_ADDIS_R12_R12 = OP_ADDIS | 12<<21 | 12<<16
84 OP_ADDI_R12_R12 = OP_ADDI | 12<<21 | 12<<16
85 OP_PLD_SFX_R12 = OP_PLD_SFX | 12<<21
86 OP_PLA_SFX_R12 = OP_PLA_SFX | 12<<21
87 OP_LIS_R12 = OP_ADDIS | 12<<21
88 OP_LD_R12_R12 = OP_LD | 12<<21 | 12<<16
89 OP_MTCTR_R12 = OP_MTCTR | 12<<21
90 OP_MFLR_R12 = OP_MFLR | 12<<21
91 OP_MFLR_R0 = OP_MFLR | 0<<21
92 OP_MTLR_R0 = OP_MTLR | 0<<21
93
94
95
96 OP_BCL_NIA = OP_BCL | 20<<21 | 31<<16 | 1<<2
97
98
99 MASK_PLD_PFX = 0xfff70000
100 MASK_PLD_SFX = 0xfc1f0000
101 MASK_PLD_RT = 0x03e00000
102 MASK_OP_LD = 0xfc000003
103 MASK_OP_ADDIS = 0xfc000000
104 )
105
106
107
108 func genstub(ctxt *ld.Link, ldr *loader.Loader, r loader.Reloc, ri int, s loader.Sym, stubType int) (ssym loader.Sym, firstUse bool) {
109 addendStr := ""
110 if r.Add() != 0 {
111 addendStr = fmt.Sprintf("%+d", r.Add())
112 }
113
114 stubName := fmt.Sprintf("%s%s.%s", stubStrs[stubType], addendStr, ldr.SymName(r.Sym()))
115 stub := ldr.CreateSymForUpdate(stubName, 0)
116 firstUse = stub.Size() == 0
117 if firstUse {
118 switch stubType {
119
120 case STUB_TOC:
121 stub.AddUint32(ctxt.Arch, OP_TOCSAVE)
122 stub.AddSymRef(ctxt.Arch, r.Sym(), r.Add(), objabi.R_ADDRPOWER_TOCREL_DS, 8)
123 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_ADDIS_R12_R2)
124 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_ADDI_R12_R12)
125
126
127 case STUB_PCREL:
128 if buildcfg.GOPPC64 >= 10 {
129
130 stub.AddSymRef(ctxt.Arch, r.Sym(), r.Add(), objabi.R_ADDRPOWER_PCREL34, 8)
131 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_PLA_PFX)
132 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_PLA_SFX_R12)
133 } else {
134
135 stub.AddUint32(ctxt.Arch, OP_MFLR_R0)
136 stub.AddUint32(ctxt.Arch, OP_BCL_NIA)
137 stub.AddUint32(ctxt.Arch, OP_MFLR_R12)
138 stub.AddUint32(ctxt.Arch, OP_MTLR_R0)
139 stub.AddSymRef(ctxt.Arch, r.Sym(), r.Add()+8, objabi.R_ADDRPOWER_PCREL, 8)
140 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_ADDIS_R12_R12)
141 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_ADDI_R12_R12)
142 }
143 }
144
145 stub.AddUint32(ctxt.Arch, OP_MTCTR_R12)
146 stub.AddUint32(ctxt.Arch, OP_BCTR)
147 stub.SetType(sym.STEXT)
148 }
149
150
151 su := ldr.MakeSymbolUpdater(s)
152 su.SetRelocSym(ri, stub.Sym())
153
154
155 switch stubType {
156 case STUB_TOC:
157 rewritetoinsn(&ctxt.Target, ldr, su, int64(r.Off()+4), 0xFFFFFFFF, OP_NOP, OP_TOCRESTORE)
158 }
159
160 return stub.Sym(), firstUse
161 }
162
163 func genpltstub(ctxt *ld.Link, ldr *loader.Loader, r loader.Reloc, ri int, s loader.Sym) (sym loader.Sym, firstUse bool) {
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 addpltsym(ctxt, ldr, r.Sym())
210
211
212 stubType := 0
213 stubTypeStr := ""
214
215
216
217
218
219
220
221
222
223
224
225
226
227 if (r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_PPC64_REL24)) || (!ldr.AttrExternal(s) && ldr.AttrShared(s) && !hasPCrel) {
228 stubTypeStr = "_tocrel"
229 stubType = 1
230 } else {
231 stubTypeStr = "_notoc"
232 stubType = 3
233 }
234 n := fmt.Sprintf("_pltstub%s.%s", stubTypeStr, ldr.SymName(r.Sym()))
235
236
237 stub := ldr.CreateSymForUpdate(n, 0)
238 firstUse = stub.Size() == 0
239 if firstUse {
240 gencallstub(ctxt, ldr, stubType, stub, r.Sym())
241 }
242
243
244 su := ldr.MakeSymbolUpdater(s)
245 su.SetRelocSym(ri, stub.Sym())
246
247
248 if stubType == 1 {
249 su.MakeWritable()
250 p := su.Data()
251
252
253 var nop uint32
254 if len(p) >= int(r.Off()+8) {
255 nop = ctxt.Arch.ByteOrder.Uint32(p[r.Off()+4:])
256 }
257 if nop != OP_NOP {
258 ldr.Errorf(s, "Symbol %s is missing toc restoration slot at offset %d", ldr.SymName(s), r.Off()+4)
259 }
260 ctxt.Arch.ByteOrder.PutUint32(p[r.Off()+4:], OP_TOCRESTORE)
261 }
262
263 return stub.Sym(), firstUse
264 }
265
266
267 func genstubs(ctxt *ld.Link, ldr *loader.Loader) {
268 var stubs []loader.Sym
269 var abifuncs []loader.Sym
270 for _, s := range ctxt.Textp {
271 relocs := ldr.Relocs(s)
272 for i := 0; i < relocs.Count(); i++ {
273 switch r := relocs.At(i); r.Type() {
274 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24), objabi.R_CALLPOWER:
275 switch ldr.SymType(r.Sym()) {
276 case sym.SDYNIMPORT:
277
278 if sym, firstUse := genpltstub(ctxt, ldr, r, i, s); firstUse {
279 stubs = append(stubs, sym)
280 }
281
282 case sym.SXREF:
283
284
285
286 targName := ldr.SymName(r.Sym())
287 if strings.HasPrefix(targName, "_save") || strings.HasPrefix(targName, "_rest") {
288 if sym, firstUse := rewriteABIFuncReloc(ctxt, ldr, targName, r); firstUse {
289 abifuncs = append(abifuncs, sym)
290 }
291 }
292 case sym.STEXT:
293 targ := r.Sym()
294 if (ldr.AttrExternal(targ) && ldr.SymLocalentry(targ) != 1) || !ldr.AttrExternal(targ) {
295
296
297 } else {
298
299
300 if sym, firstUse := genstub(ctxt, ldr, r, i, s, STUB_TOC); firstUse {
301 stubs = append(stubs, sym)
302 }
303 }
304 }
305
306 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24_P9NOTOC):
307
308
309 fallthrough
310 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24_NOTOC):
311 switch ldr.SymType(r.Sym()) {
312 case sym.SDYNIMPORT:
313
314 if sym, firstUse := genpltstub(ctxt, ldr, r, i, s); firstUse {
315 stubs = append(stubs, sym)
316 }
317
318 case sym.SXREF:
319
320 ldr.Errorf(s, "Unsupported NOTOC external reference call into %s", ldr.SymName(r.Sym()))
321
322 case sym.STEXT:
323 targ := r.Sym()
324 if (ldr.AttrExternal(targ) && ldr.SymLocalentry(targ) <= 1) || (!ldr.AttrExternal(targ) && (!ldr.AttrShared(targ) || hasPCrel)) {
325
326 } else {
327
328 if sym, firstUse := genstub(ctxt, ldr, r, i, s, STUB_PCREL); firstUse {
329 stubs = append(stubs, sym)
330 }
331 }
332 }
333
334
335
336 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PLTSEQ):
337 if ldr.SymType(r.Sym()) == sym.STEXT {
338
339 su := ldr.MakeSymbolUpdater(s)
340 const MASK_OP_MTCTR = 63<<26 | 0x3FF<<11 | 0x1FF<<1
341 rewritetonop(&ctxt.Target, ldr, su, int64(r.Off()), MASK_OP_MTCTR, OP_MTCTR)
342 }
343 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PLTCALL):
344 if ldr.SymType(r.Sym()) == sym.STEXT {
345
346
347 su := ldr.MakeSymbolUpdater(s)
348 rewritetoinsn(&ctxt.Target, ldr, su, int64(r.Off()), 0xFFFFFFFF, OP_BCTRL, OP_BL)
349
350
351 su.SetRelocType(i, objabi.R_CALLPOWER)
352 localEoffset := int64(ldr.SymLocalentry(r.Sym()))
353 if localEoffset == 1 {
354 ldr.Errorf(s, "Unsupported NOTOC call to %s", ldr.SymName(r.Sym()))
355 }
356 su.SetRelocAdd(i, r.Add()+localEoffset)
357 r.SetSiz(4)
358 rewritetonop(&ctxt.Target, ldr, su, int64(r.Off()+4), 0xFFFFFFFF, OP_TOCRESTORE)
359 }
360 }
361 }
362 }
363
364
365
366
367 stubs = append(stubs, abifuncs...)
368
369
370
371
372
373 ctxt.Textp = append(stubs, ctxt.Textp...)
374 }
375
376 func genaddmoduledata(ctxt *ld.Link, ldr *loader.Loader) {
377 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
378 if initfunc == nil {
379 return
380 }
381
382 o := func(op uint32) {
383 initfunc.AddUint32(ctxt.Arch, op)
384 }
385
386
387
388
389
390
391
392
393 if !hasPCrel {
394
395 sz := initfunc.AddSymRef(ctxt.Arch, ctxt.DotTOC[0], 0, objabi.R_ADDRPOWER_PCREL, 8)
396 initfunc.SetUint32(ctxt.Arch, sz-8, 0x3c4c0000)
397 initfunc.SetUint32(ctxt.Arch, sz-4, 0x38420000)
398 }
399
400
401 o(OP_MFLR_R0)
402 o(0xf801ffe1)
403
404
405 var tgt loader.Sym
406 if s := ldr.Lookup("local.moduledata", 0); s != 0 {
407 tgt = s
408 } else if s := ldr.Lookup("local.pluginmoduledata", 0); s != 0 {
409 tgt = s
410 } else {
411 tgt = ldr.LookupOrCreateSym("runtime.firstmoduledata", 0)
412 }
413
414 if !hasPCrel {
415 sz := initfunc.AddSymRef(ctxt.Arch, tgt, 0, objabi.R_ADDRPOWER_GOT, 8)
416 initfunc.SetUint32(ctxt.Arch, sz-8, 0x3c620000)
417 initfunc.SetUint32(ctxt.Arch, sz-4, 0xe8630000)
418 } else {
419 sz := initfunc.AddSymRef(ctxt.Arch, tgt, 0, objabi.R_ADDRPOWER_GOT_PCREL34, 8)
420
421
422 initfunc.SetUint32(ctxt.Arch, sz-8, OP_PLD_PFX_PCREL)
423 initfunc.SetUint32(ctxt.Arch, sz-4, OP_PLD_SFX|(3<<21))
424 }
425
426
427 sz := initfunc.AddSymRef(ctxt.Arch, addmoduledata, 0, objabi.R_CALLPOWER, 4)
428 initfunc.SetUint32(ctxt.Arch, sz-4, OP_BL)
429 o(OP_NOP)
430
431
432 o(0xe8010000)
433 o(OP_MTLR_R0)
434 o(0x38210020)
435 o(0x4e800020)
436 }
437
438
439
440
441
442
443
444
445
446
447
448 func rewriteABIFuncReloc(ctxt *ld.Link, ldr *loader.Loader, tname string, r loader.Reloc) (sym loader.Sym, firstUse bool) {
449 s := strings.Split(tname, "_")
450
451 if len(s) != 3 {
452 return 0, false
453 }
454 minReg := 14
455 offMul := 4
456 switch s[1] {
457 case "savegpr0", "savegpr1", "savefpr":
458 case "restgpr0", "restgpr1", "restfpr":
459 case "savevr", "restvr":
460 minReg = 20
461 offMul = 8
462 default:
463 return 0, false
464 }
465 n, e := strconv.Atoi(s[2])
466 if e != nil || n < minReg || n > 31 || r.Add() != 0 {
467 return 0, false
468 }
469
470
471
472 ts := ldr.LookupOrCreateSym("runtime.elf_"+s[1], 0)
473 r.SetSym(ts)
474 r.SetAdd(int64((n - minReg) * offMul))
475 firstUse = !ldr.AttrReachable(ts)
476 if firstUse {
477
478
479 ldr.SetAttrReachable(ts, true)
480 }
481 return ts, firstUse
482 }
483
484 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
485 if ctxt.DynlinkingGo() {
486 genaddmoduledata(ctxt, ldr)
487 }
488
489 if ctxt.LinkMode == ld.LinkInternal {
490 genstubs(ctxt, ldr)
491 }
492 }
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507 func gencallstub(ctxt *ld.Link, ldr *loader.Loader, stubType int, stub *loader.SymbolBuilder, targ loader.Sym) {
508 plt := ctxt.PLT
509 stub.SetType(sym.STEXT)
510
511 switch stubType {
512 case 1:
513
514 stub.AddUint32(ctxt.Arch, OP_TOCSAVE)
515 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ)), objabi.R_ADDRPOWER_TOCREL_DS, 8)
516 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_ADDIS_R12_R2)
517 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_LD_R12_R12)
518 case 3:
519
520 if buildcfg.GOPPC64 >= 10 {
521
522 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ)), objabi.R_ADDRPOWER_PCREL34, 8)
523 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_PLD_PFX_PCREL)
524 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_PLD_SFX_R12)
525 } else if !isLinkingPIC(ctxt) {
526
527 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ)), objabi.R_ADDRPOWER_DS, 8)
528 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_LIS_R12)
529 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_LD_R12_R12)
530 } else {
531
532
533
534 stub.AddUint32(ctxt.Arch, OP_MFLR_R0)
535 stub.AddUint32(ctxt.Arch, OP_BCL_NIA)
536 stub.AddUint32(ctxt.Arch, OP_MFLR_R12)
537 stub.AddUint32(ctxt.Arch, OP_MTLR_R0)
538 stub.AddSymRef(ctxt.Arch, plt, int64(ldr.SymPlt(targ))+8, objabi.R_ADDRPOWER_PCREL, 8)
539 stub.SetUint32(ctxt.Arch, stub.Size()-8, OP_ADDIS_R12_R12)
540 stub.SetUint32(ctxt.Arch, stub.Size()-4, OP_ADDI_R12_R12)
541 stub.AddUint32(ctxt.Arch, OP_LD_R12_R12)
542 }
543 default:
544 log.Fatalf("gencallstub does not support ELFv2 ABI property %d", stubType)
545 }
546
547
548 stub.AddUint32(ctxt.Arch, OP_MTCTR_R12)
549 stub.AddUint32(ctxt.Arch, OP_BCTR)
550 }
551
552
553
554 func rewritetoinsn(target *ld.Target, ldr *loader.Loader, su *loader.SymbolBuilder, offset int64, mask, check, newinsn uint32) {
555 su.MakeWritable()
556 op := target.Arch.ByteOrder.Uint32(su.Data()[offset:])
557 if op&mask != check {
558 ldr.Errorf(su.Sym(), "Rewrite offset 0x%x to 0x%08X failed check (0x%08X&0x%08X != 0x%08X)", offset, newinsn, op, mask, check)
559 }
560 su.SetUint32(target.Arch, offset, newinsn)
561 }
562
563
564
565 func rewritetonop(target *ld.Target, ldr *loader.Loader, su *loader.SymbolBuilder, offset int64, mask, check uint32) {
566 rewritetoinsn(target, ldr, su, offset, mask, check, OP_NOP)
567 }
568
569 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
570 if target.IsElf() {
571 return addelfdynrel(target, ldr, syms, s, r, rIdx)
572 } else if target.IsAIX() {
573 return ld.Xcoffadddynrel(target, ldr, syms, s, r, rIdx)
574 }
575 return false
576 }
577
578 func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
579 targ := r.Sym()
580 var targType sym.SymKind
581 if targ != 0 {
582 targType = ldr.SymType(targ)
583 }
584
585 switch r.Type() {
586 default:
587 if r.Type() >= objabi.ElfRelocOffset {
588 ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
589 return false
590 }
591
592
593 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24_NOTOC),
594 objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24_P9NOTOC):
595 su := ldr.MakeSymbolUpdater(s)
596 su.SetRelocType(rIdx, objabi.R_CALLPOWER)
597
598 if targType == sym.SDYNIMPORT {
599
600 ldr.Errorf(s, "unexpected R_PPC64_REL24_NOTOC/R_PPC64_REL24_P9NOTOC for dyn import")
601 }
602 return true
603
604 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24):
605 su := ldr.MakeSymbolUpdater(s)
606 su.SetRelocType(rIdx, objabi.R_CALLPOWER)
607
608
609
610
611
612
613 localEoffset := int64(ldr.SymLocalentry(targ))
614 if localEoffset == 1 {
615 ldr.Errorf(s, "Unsupported NOTOC call to %s", targ)
616 }
617 su.SetRelocAdd(rIdx, r.Add()+localEoffset)
618
619 if targType == sym.SDYNIMPORT {
620
621 ldr.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
622 }
623
624 return true
625
626 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PCREL34):
627 su := ldr.MakeSymbolUpdater(s)
628 su.SetRelocType(rIdx, objabi.R_ADDRPOWER_PCREL34)
629 return true
630
631 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_GOT_PCREL34):
632 su := ldr.MakeSymbolUpdater(s)
633 su.SetRelocType(rIdx, objabi.R_ADDRPOWER_PCREL34)
634 if targType != sym.STEXT {
635 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_PPC64_GLOB_DAT))
636 su.SetRelocSym(rIdx, syms.GOT)
637 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
638 } else {
639
640 rewritetoinsn(target, ldr, su, int64(r.Off()), MASK_PLD_PFX, OP_PLD_PFX_PCREL, OP_PLA_PFX)
641 pla_sfx := target.Arch.ByteOrder.Uint32(su.Data()[r.Off()+4:])&MASK_PLD_RT | OP_PLA_SFX
642 rewritetoinsn(target, ldr, su, int64(r.Off()+4), MASK_PLD_SFX, OP_PLD_SFX, pla_sfx)
643 }
644 return true
645
646 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32):
647 su := ldr.MakeSymbolUpdater(s)
648 su.SetRelocType(rIdx, objabi.R_PCREL)
649 su.SetRelocAdd(rIdx, r.Add()+4)
650
651 if targType == sym.SDYNIMPORT {
652 ldr.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
653 }
654
655 return true
656
657 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_ADDR64):
658 su := ldr.MakeSymbolUpdater(s)
659 su.SetRelocType(rIdx, objabi.R_ADDR)
660 if targType == sym.SDYNIMPORT {
661
662 ld.Adddynsym(ldr, target, syms, targ)
663
664 rela := ldr.MakeSymbolUpdater(syms.Rela)
665 rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
666 rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_PPC64_ADDR64)))
667 rela.AddUint64(target.Arch, uint64(r.Add()))
668 su.SetRelocType(rIdx, objabi.ElfRelocOffset)
669 } else if target.IsPIE() && target.IsInternal() {
670
671
672
673 break
674 }
675 return true
676
677 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16):
678 su := ldr.MakeSymbolUpdater(s)
679 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
680 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO|sym.RV_CHECK_OVERFLOW)
681 return true
682
683 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO):
684 su := ldr.MakeSymbolUpdater(s)
685 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
686 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
687 return true
688
689 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA):
690 su := ldr.MakeSymbolUpdater(s)
691 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
692 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
693 return true
694
695 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI):
696 su := ldr.MakeSymbolUpdater(s)
697 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
698 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
699 return true
700
701 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS):
702 su := ldr.MakeSymbolUpdater(s)
703 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
704 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS|sym.RV_CHECK_OVERFLOW)
705 return true
706
707 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS):
708 su := ldr.MakeSymbolUpdater(s)
709 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
710 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS)
711 return true
712
713 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO):
714 su := ldr.MakeSymbolUpdater(s)
715 su.SetRelocType(rIdx, objabi.R_PCREL)
716 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
717 su.SetRelocAdd(rIdx, r.Add()+2)
718 return true
719
720 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI):
721 su := ldr.MakeSymbolUpdater(s)
722 su.SetRelocType(rIdx, objabi.R_PCREL)
723 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
724 su.SetRelocAdd(rIdx, r.Add()+2)
725 return true
726
727 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA):
728 su := ldr.MakeSymbolUpdater(s)
729 su.SetRelocType(rIdx, objabi.R_PCREL)
730 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
731 su.SetRelocAdd(rIdx, r.Add()+2)
732 return true
733
734
735
736
737
738
739
740
741
742
743
744
745 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PLT16_HA),
746 objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_PLT16_LO_DS):
747 su := ldr.MakeSymbolUpdater(s)
748 isPLT16_LO_DS := r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_PPC64_PLT16_LO_DS)
749 if isPLT16_LO_DS {
750 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS)
751 } else {
752 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
753 }
754 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
755 if targType == sym.SDYNIMPORT {
756
757 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_PPC64_GLOB_DAT))
758 su.SetRelocSym(rIdx, syms.GOT)
759 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
760 } else if targType == sym.STEXT {
761 if isPLT16_LO_DS {
762
763 rewritetonop(target, ldr, su, int64(r.Off()), MASK_OP_LD, OP_LD)
764 } else {
765
766 rewritetonop(target, ldr, su, int64(r.Off()), MASK_OP_ADDIS, OP_ADDIS)
767 }
768
769 su.SetRelocType(rIdx, objabi.ElfRelocOffset)
770 } else {
771 ldr.Errorf(s, "unexpected PLT relocation target symbol type %s", targType.String())
772 }
773 return true
774 }
775
776
777 relocs := ldr.Relocs(s)
778 r = relocs.At(rIdx)
779
780 switch r.Type() {
781 case objabi.R_ADDR:
782 if ldr.SymType(s) == sym.STEXT {
783 log.Fatalf("R_ADDR relocation in text symbol %s is unsupported\n", ldr.SymName(s))
784 }
785 if target.IsPIE() && target.IsInternal() {
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817 switch ldr.SymName(s) {
818 case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
819 return false
820 }
821 } else {
822
823
824
825
826
827
828 if ldr.SymType(s) != sym.SDATA && ldr.SymType(s) != sym.SRODATA {
829 break
830 }
831 }
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849 rela := ldr.MakeSymbolUpdater(syms.Rela)
850 rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
851 if r.Siz() == 8 {
852 rela.AddUint64(target.Arch, elf.R_INFO(0, uint32(elf.R_PPC64_RELATIVE)))
853 } else {
854 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
855 }
856 rela.AddAddrPlus(target.Arch, targ, int64(r.Add()))
857
858
859
860
861
862 return true
863 }
864
865 return false
866 }
867
868 func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool {
869 rs := r.Xsym
870
871 emitReloc := func(v uint16, off uint64) {
872 out.Write64(uint64(sectoff) + off)
873 out.Write32(uint32(ldr.SymDynid(rs)))
874 out.Write16(v)
875 }
876
877 var v uint16
878 switch r.Type {
879 default:
880 return false
881 case objabi.R_ADDR, objabi.R_DWARFSECREF:
882 v = ld.XCOFF_R_POS
883 if r.Size == 4 {
884 v |= 0x1F << 8
885 } else {
886 v |= 0x3F << 8
887 }
888 emitReloc(v, 0)
889 case objabi.R_ADDRPOWER_TOCREL:
890 case objabi.R_ADDRPOWER_TOCREL_DS:
891 emitReloc(ld.XCOFF_R_TOCU|(0x0F<<8), 2)
892 emitReloc(ld.XCOFF_R_TOCL|(0x0F<<8), 6)
893 case objabi.R_POWER_TLS_LE:
894
895 emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2)
896 case objabi.R_CALLPOWER:
897 if r.Size != 4 {
898 return false
899 }
900 emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
901 case objabi.R_XCOFFREF:
902 emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0)
903 }
904 return true
905 }
906
907 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
908
909 rt := r.Type
910 if rt == objabi.R_ADDR || rt == objabi.R_POWER_TLS || rt == objabi.R_CALLPOWER || rt == objabi.R_DWARFSECREF {
911 } else {
912 if ctxt.Arch.ByteOrder == binary.BigEndian {
913 sectoff += 2
914 }
915 }
916 out.Write64(uint64(sectoff))
917
918 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
919 switch rt {
920 default:
921 return false
922 case objabi.R_ADDR, objabi.R_DWARFSECREF:
923 switch r.Size {
924 case 4:
925 out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32)
926 case 8:
927 out.Write64(uint64(elf.R_PPC64_ADDR64) | uint64(elfsym)<<32)
928 default:
929 return false
930 }
931 case objabi.R_ADDRPOWER_D34:
932 out.Write64(uint64(elf.R_PPC64_D34) | uint64(elfsym)<<32)
933 case objabi.R_ADDRPOWER_PCREL34:
934 out.Write64(uint64(elf.R_PPC64_PCREL34) | uint64(elfsym)<<32)
935 case objabi.R_POWER_TLS:
936 out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32)
937 case objabi.R_POWER_TLS_LE:
938 out.Write64(uint64(elf.R_PPC64_TPREL16_HA) | uint64(elfsym)<<32)
939 out.Write64(uint64(r.Xadd))
940 out.Write64(uint64(sectoff + 4))
941 out.Write64(uint64(elf.R_PPC64_TPREL16_LO) | uint64(elfsym)<<32)
942 case objabi.R_POWER_TLS_LE_TPREL34:
943 out.Write64(uint64(elf.R_PPC64_TPREL34) | uint64(elfsym)<<32)
944 case objabi.R_POWER_TLS_IE_PCREL34:
945 out.Write64(uint64(elf.R_PPC64_GOT_TPREL_PCREL34) | uint64(elfsym)<<32)
946 case objabi.R_POWER_TLS_IE:
947 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32)
948 out.Write64(uint64(r.Xadd))
949 out.Write64(uint64(sectoff + 4))
950 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_LO_DS) | uint64(elfsym)<<32)
951 case objabi.R_ADDRPOWER:
952 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
953 out.Write64(uint64(r.Xadd))
954 out.Write64(uint64(sectoff + 4))
955 out.Write64(uint64(elf.R_PPC64_ADDR16_LO) | uint64(elfsym)<<32)
956 case objabi.R_ADDRPOWER_DS:
957 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
958 out.Write64(uint64(r.Xadd))
959 out.Write64(uint64(sectoff + 4))
960 out.Write64(uint64(elf.R_PPC64_ADDR16_LO_DS) | uint64(elfsym)<<32)
961 case objabi.R_ADDRPOWER_GOT:
962 out.Write64(uint64(elf.R_PPC64_GOT16_HA) | uint64(elfsym)<<32)
963 out.Write64(uint64(r.Xadd))
964 out.Write64(uint64(sectoff + 4))
965 out.Write64(uint64(elf.R_PPC64_GOT16_LO_DS) | uint64(elfsym)<<32)
966 case objabi.R_ADDRPOWER_GOT_PCREL34:
967 out.Write64(uint64(elf.R_PPC64_GOT_PCREL34) | uint64(elfsym)<<32)
968 case objabi.R_ADDRPOWER_PCREL:
969 out.Write64(uint64(elf.R_PPC64_REL16_HA) | uint64(elfsym)<<32)
970 out.Write64(uint64(r.Xadd))
971 out.Write64(uint64(sectoff + 4))
972 out.Write64(uint64(elf.R_PPC64_REL16_LO) | uint64(elfsym)<<32)
973 r.Xadd += 4
974 case objabi.R_ADDRPOWER_TOCREL:
975 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
976 out.Write64(uint64(r.Xadd))
977 out.Write64(uint64(sectoff + 4))
978 out.Write64(uint64(elf.R_PPC64_TOC16_LO) | uint64(elfsym)<<32)
979 case objabi.R_ADDRPOWER_TOCREL_DS:
980 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
981 out.Write64(uint64(r.Xadd))
982 out.Write64(uint64(sectoff + 4))
983 out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32)
984 case objabi.R_CALLPOWER:
985 if r.Size != 4 {
986 return false
987 }
988 if !hasPCrel {
989 out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32)
990 } else {
991
992 out.Write64(uint64(elf.R_PPC64_REL24_NOTOC) | uint64(elfsym)<<32)
993 }
994
995 }
996 out.Write64(uint64(r.Xadd))
997
998 return true
999 }
1000
1001 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
1002 if plt.Size() == 0 {
1003
1004
1005
1006
1007 plt.SetSize(16)
1008 }
1009 }
1010
1011 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
1012 return false
1013 }
1014
1015
1016 func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 {
1017 v := ldr.SymVersion(s)
1018 if out := ldr.OuterSym(s); out != 0 {
1019 v = ldr.SymVersion(out)
1020 }
1021
1022 toc := syms.DotTOC[v]
1023 if toc == 0 {
1024 ldr.Errorf(s, "TOC-relative relocation in object without .TOC.")
1025 return 0
1026 }
1027
1028 return ldr.SymValue(toc)
1029 }
1030
1031
1032 func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
1033 rs := r.Sym()
1034 var o1, o2 uint32
1035 var t int64
1036 useAddi := false
1037
1038 if target.IsBigEndian() {
1039 o1 = uint32(val >> 32)
1040 o2 = uint32(val)
1041 } else {
1042 o1 = uint32(val)
1043 o2 = uint32(val >> 32)
1044 }
1045
1046
1047
1048
1049 if target.IsAIX() {
1050 if !strings.HasPrefix(ldr.SymName(rs), "TOC.") {
1051 ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
1052 }
1053 relocs := ldr.Relocs(rs)
1054 tarSym := relocs.At(0).Sym()
1055
1056 if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata {
1057 t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC)
1058
1059 o2 = (o2 & 0x03FF0000) | 0xE<<26
1060 useAddi = true
1061 } else {
1062 t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC)
1063 }
1064 } else {
1065 t = ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s)
1066 }
1067
1068 if t != int64(int32(t)) {
1069 ldr.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", ldr.SymName(s), rs, t)
1070 }
1071
1072 if t&0x8000 != 0 {
1073 t += 0x10000
1074 }
1075
1076 o1 |= uint32((t >> 16) & 0xFFFF)
1077
1078 switch r.Type() {
1079 case objabi.R_ADDRPOWER_TOCREL_DS:
1080 if useAddi {
1081 o2 |= uint32(t) & 0xFFFF
1082 } else {
1083 if t&3 != 0 {
1084 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
1085 }
1086 o2 |= uint32(t) & 0xFFFC
1087 }
1088 case objabi.R_ADDRPOWER_TOCREL:
1089 o2 |= uint32(t) & 0xffff
1090 default:
1091 return -1
1092 }
1093
1094 if target.IsBigEndian() {
1095 return int64(o1)<<32 | int64(o2)
1096 }
1097 return int64(o2)<<32 | int64(o1)
1098 }
1099
1100
1101
1102 func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
1103 rs := r.Sym()
1104 if target.IsAIX() {
1105 ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
1106 }
1107 o1, o2 := unpackInstPair(target, val)
1108
1109
1110
1111
1112
1113
1114 t := ldr.SymAddr(rs) + r.Add()
1115 if t < 0 || t >= 1<<31 {
1116 ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs))
1117 }
1118
1119
1120
1121 switch r.Type() {
1122 case objabi.R_ADDRPOWER_PCREL34:
1123
1124 t -= (ldr.SymValue(s) + int64(r.Off()))
1125 o1 &^= 0x3ffff
1126 o2 &^= 0x0ffff
1127 o1 |= computePrefix34HI(t)
1128 o2 |= computeLO(int32(t))
1129 case objabi.R_ADDRPOWER_D34:
1130 o1 &^= 0x3ffff
1131 o2 &^= 0x0ffff
1132 o1 |= computePrefix34HI(t)
1133 o2 |= computeLO(int32(t))
1134 case objabi.R_ADDRPOWER:
1135 o1 &^= 0xffff
1136 o2 &^= 0xffff
1137 o1 |= computeHA(int32(t))
1138 o2 |= computeLO(int32(t))
1139 case objabi.R_ADDRPOWER_DS:
1140 o1 &^= 0xffff
1141 o2 &^= 0xfffc
1142 o1 |= computeHA(int32(t))
1143 o2 |= computeLO(int32(t))
1144 if t&3 != 0 {
1145 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
1146 }
1147 default:
1148 return -1
1149 }
1150
1151 return packInstPair(target, o1, o2)
1152 }
1153
1154
1155 func r2Valid(ctxt *ld.Link) bool {
1156 return isLinkingPIC(ctxt)
1157 }
1158
1159
1160 func isLinkingPIC(ctxt *ld.Link) bool {
1161 switch ctxt.BuildMode {
1162 case ld.BuildModeCArchive, ld.BuildModeCShared, ld.BuildModePIE, ld.BuildModeShared, ld.BuildModePlugin:
1163 return true
1164 }
1165
1166 return ctxt.IsSharedGoLink()
1167 }
1168
1169
1170 func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
1171
1172
1173
1174
1175
1176 if ctxt.IsExternal() && r2Valid(ctxt) {
1177
1178 return
1179 }
1180
1181 relocs := ldr.Relocs(s)
1182 r := relocs.At(ri)
1183 var t int64
1184
1185
1186
1187 if ldr.SymValue(rs) != 0 {
1188 t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
1189 }
1190 switch r.Type() {
1191 case objabi.R_CALLPOWER:
1192
1193
1194
1195 if (ctxt.IsExternal() && ldr.SymSect(s) != ldr.SymSect(rs)) || (ctxt.IsInternal() && int64(int32(t<<6)>>6) != t) || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
1196 var tramp loader.Sym
1197 for i := 0; ; i++ {
1198
1199
1200
1201
1202
1203 oName := ldr.SymName(rs)
1204 name := oName
1205 if r.Add() == 0 {
1206 name += fmt.Sprintf("-tramp%d", i)
1207 } else {
1208 name += fmt.Sprintf("%+x-tramp%d", r.Add(), i)
1209 }
1210
1211
1212
1213 tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
1214 if oName == "runtime.deferreturn" {
1215 ldr.SetIsDeferReturnTramp(tramp, true)
1216 }
1217 if ldr.SymValue(tramp) == 0 {
1218 break
1219 }
1220
1221
1222 t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off()))
1223
1224
1225
1226 if (ctxt.IsInternal() && int64(int32(t<<6)>>6) == t) || (ctxt.IsExternal() && ldr.SymSect(s) == ldr.SymSect(tramp)) {
1227 break
1228 }
1229 }
1230 if ldr.SymType(tramp) == 0 {
1231 trampb := ldr.MakeSymbolUpdater(tramp)
1232 ctxt.AddTramp(trampb)
1233 gentramp(ctxt, ldr, trampb, rs, r.Add())
1234 }
1235 sb := ldr.MakeSymbolUpdater(s)
1236 relocs := sb.Relocs()
1237 r := relocs.At(ri)
1238 r.SetSym(tramp)
1239 r.SetAdd(0)
1240 }
1241 default:
1242 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
1243 }
1244 }
1245
1246 func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
1247 tramp.SetSize(16)
1248 P := make([]byte, tramp.Size())
1249 var o1, o2 uint32
1250
1251
1252
1253 if strings.HasPrefix(ldr.SymName(target), "runtime.elf_") {
1254 log.Fatalf("Internal linker does not support trampolines to ELFv2 ABI"+
1255 " register save/restore function %s", ldr.SymName(target))
1256 }
1257
1258 if ctxt.IsAIX() {
1259
1260
1261
1262
1263
1264 o1 = uint32(OP_ADDIS_R12_R2)
1265 o2 = uint32(OP_LD_R12_R12)
1266
1267 toctramp := ldr.CreateSymForUpdate("TOC."+ldr.SymName(tramp.Sym()), 0)
1268 toctramp.SetType(sym.SXCOFFTOC)
1269 toctramp.AddAddrPlus(ctxt.Arch, target, offset)
1270
1271 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_TOCREL_DS)
1272 r.SetOff(0)
1273 r.SetSiz(8)
1274 r.SetSym(toctramp.Sym())
1275 } else if hasPCrel {
1276
1277 o1 = uint32(OP_PLA_PFX)
1278 o2 = uint32(OP_PLA_SFX_R12)
1279
1280
1281 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_PCREL34)
1282 r.SetOff(0)
1283 r.SetSiz(8)
1284 r.SetSym(target)
1285 r.SetAdd(offset)
1286 } else {
1287
1288
1289
1290 o1 = uint32(OP_LIS_R12)
1291 o2 = uint32(OP_ADDI_R12_R12)
1292
1293 t := ldr.SymValue(target)
1294 if t == 0 || r2Valid(ctxt) || ctxt.IsExternal() {
1295
1296 r, _ := tramp.AddRel(objabi.R_ADDRPOWER)
1297 if r2Valid(ctxt) {
1298
1299 o1 |= uint32(2 << 16)
1300 r.SetType(objabi.R_ADDRPOWER_TOCREL)
1301 }
1302 r.SetOff(0)
1303 r.SetSiz(8)
1304 r.SetSym(target)
1305 r.SetAdd(offset)
1306 } else {
1307
1308 t += offset
1309 o1 |= (uint32(t) + 0x8000) >> 16
1310 o2 |= uint32(t) & 0xFFFF
1311 }
1312 }
1313
1314 o3 := uint32(OP_MTCTR_R12)
1315 o4 := uint32(OP_BCTR)
1316 ctxt.Arch.ByteOrder.PutUint32(P, o1)
1317 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
1318 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
1319 ctxt.Arch.ByteOrder.PutUint32(P[12:], o4)
1320 tramp.SetData(P)
1321 }
1322
1323
1324
1325 func unpackInstPair(target *ld.Target, r int64) (uint32, uint32) {
1326 if target.IsBigEndian() {
1327 return uint32(r >> 32), uint32(r)
1328 }
1329 return uint32(r), uint32(r >> 32)
1330 }
1331
1332
1333
1334 func packInstPair(target *ld.Target, o1, o2 uint32) int64 {
1335 if target.IsBigEndian() {
1336 return (int64(o1) << 32) | int64(o2)
1337 }
1338 return int64(o1) | (int64(o2) << 32)
1339 }
1340
1341
1342
1343 func computeHA(val int32) uint32 {
1344 return uint32(uint16((val + 0x8000) >> 16))
1345 }
1346
1347
1348
1349 func computeLO(val int32) uint32 {
1350 return uint32(uint16(val))
1351 }
1352
1353
1354
1355
1356 func computePrefix34HI(val int64) uint32 {
1357 return uint32((val >> 16) & 0x3FFFF)
1358 }
1359
1360 func computeTLSLEReloc(target *ld.Target, ldr *loader.Loader, rs, s loader.Sym) int64 {
1361
1362
1363
1364
1365 v := ldr.SymValue(rs) - 0x7000
1366 if target.IsAIX() {
1367
1368
1369 v -= 0x800
1370 }
1371
1372 if int64(int32(v)) != v {
1373 ldr.Errorf(s, "TLS offset out of range %d", v)
1374 }
1375 return v
1376 }
1377
1378 func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (relocatedOffset int64, nExtReloc int, ok bool) {
1379 rs := r.Sym()
1380 if target.IsExternal() {
1381
1382
1383 switch rt := r.Type(); rt {
1384 default:
1385 if !target.IsAIX() {
1386 return val, nExtReloc, false
1387 }
1388 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_IE_PCREL34, objabi.R_POWER_TLS_LE_TPREL34, objabi.R_ADDRPOWER_GOT_PCREL34:
1389 nExtReloc = 1
1390 return val, nExtReloc, true
1391 case objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
1392 if target.IsAIX() && rt == objabi.R_POWER_TLS_LE {
1393
1394
1395
1396 const expectedOpcodes = 0x3C00000038000000
1397 const expectedOpmasks = 0xFC000000FC000000
1398 if uint64(val)&expectedOpmasks != expectedOpcodes {
1399 ldr.Errorf(s, "relocation for %s+%d is not an addis/addi pair: %16x", ldr.SymName(rs), r.Off(), uint64(val))
1400 }
1401 nval := (int64(uint32(0x380d0000)) | val&0x03e00000) << 32
1402 nval |= int64(OP_NOP)
1403 val = nval
1404 nExtReloc = 1
1405 } else {
1406 nExtReloc = 2
1407 }
1408 return val, nExtReloc, true
1409 case objabi.R_ADDRPOWER,
1410 objabi.R_ADDRPOWER_DS,
1411 objabi.R_ADDRPOWER_TOCREL,
1412 objabi.R_ADDRPOWER_TOCREL_DS,
1413 objabi.R_ADDRPOWER_GOT,
1414 objabi.R_ADDRPOWER_PCREL:
1415 nExtReloc = 2
1416 if !target.IsAIX() {
1417 return val, nExtReloc, true
1418 }
1419 case objabi.R_CALLPOWER, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34:
1420 nExtReloc = 1
1421 if !target.IsAIX() {
1422 return val, nExtReloc, true
1423 }
1424 }
1425 }
1426
1427 switch r.Type() {
1428 case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
1429 return archreloctoc(ldr, target, syms, r, s, val), nExtReloc, true
1430 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34:
1431 return archrelocaddr(ldr, target, syms, r, s, val), nExtReloc, true
1432 case objabi.R_CALLPOWER:
1433
1434
1435 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
1436
1437 tgtName := ldr.SymName(rs)
1438
1439
1440
1441
1442 if !hasPCrel && !ldr.AttrExternal(rs) && ldr.AttrShared(rs) && tgtName != "runtime.duffzero" && tgtName != "runtime.duffcopy" {
1443
1444 if r.Add() == 0 && ldr.SymType(rs) == sym.STEXT {
1445 t += 8
1446 }
1447 }
1448
1449 if t&3 != 0 {
1450 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
1451 }
1452
1453
1454 if int64(int32(t<<6)>>6) != t {
1455 ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
1456 }
1457 return val | int64(uint32(t)&^0xfc000003), nExtReloc, true
1458 case objabi.R_POWER_TOC:
1459 return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true
1460
1461 case objabi.R_ADDRPOWER_PCREL:
1462 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
1463 ha, l := unpackInstPair(target, val)
1464 l |= computeLO(int32(t))
1465 ha |= computeHA(int32(t))
1466 return packInstPair(target, ha, l), nExtReloc, true
1467
1468 case objabi.R_POWER_TLS:
1469 const OP_ADD = 31<<26 | 266<<1
1470 const MASK_OP_ADD = 0x3F<<26 | 0x1FF<<1
1471 if val&MASK_OP_ADD != OP_ADD {
1472 ldr.Errorf(s, "R_POWER_TLS reloc only supports XO form ADD, not %08X", val)
1473 }
1474
1475 if (val>>11)&0x1F != 13 {
1476
1477 ldr.Errorf(s, "R_POWER_TLS reloc requires R13 in RB (%08X).", uint32(val))
1478 }
1479 return val, nExtReloc, true
1480
1481 case objabi.R_POWER_TLS_IE:
1482
1483 if !(target.IsPIE() && target.IsElf()) {
1484 log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s))
1485 }
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495 const OP_MASK = 0x3F << 26
1496 const OP_RA_MASK = 0x1F << 16
1497
1498 mask := packInstPair(target, OP_RA_MASK, OP_MASK)
1499 addi_op := packInstPair(target, 0, OP_ADDI)
1500 val &^= mask
1501 val |= addi_op
1502 fallthrough
1503
1504 case objabi.R_POWER_TLS_LE:
1505 v := computeTLSLEReloc(target, ldr, rs, s)
1506 o1, o2 := unpackInstPair(target, val)
1507 o1 |= computeHA(int32(v))
1508 o2 |= computeLO(int32(v))
1509 return packInstPair(target, o1, o2), nExtReloc, true
1510
1511 case objabi.R_POWER_TLS_IE_PCREL34:
1512
1513 if !(target.IsPIE() && target.IsElf()) {
1514 log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s))
1515 }
1516
1517
1518
1519
1520
1521
1522
1523 const OP_MASK_PFX = 0xFFFFFFFF
1524 const OP_MASK = (0x3F << 26) | 0xFFFF
1525 const OP_PFX = 1<<26 | 2<<24
1526 const OP_PLA = 14 << 26
1527 mask := packInstPair(target, OP_MASK_PFX, OP_MASK)
1528 pla_op := packInstPair(target, OP_PFX, OP_PLA)
1529 val &^= mask
1530 val |= pla_op
1531 fallthrough
1532
1533 case objabi.R_POWER_TLS_LE_TPREL34:
1534 v := computeTLSLEReloc(target, ldr, rs, s)
1535 o1, o2 := unpackInstPair(target, val)
1536 o1 |= computePrefix34HI(v)
1537 o2 |= computeLO(int32(v))
1538 return packInstPair(target, o1, o2), nExtReloc, true
1539 }
1540
1541 return val, nExtReloc, false
1542 }
1543
1544 func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc, rv sym.RelocVariant, s loader.Sym, t int64, p []byte) (relocatedOffset int64) {
1545 rs := r.Sym()
1546 switch rv & sym.RV_TYPE_MASK {
1547 default:
1548 ldr.Errorf(s, "unexpected relocation variant %d", rv)
1549 fallthrough
1550
1551 case sym.RV_NONE:
1552 return t
1553
1554 case sym.RV_POWER_LO:
1555 if rv&sym.RV_CHECK_OVERFLOW != 0 {
1556
1557
1558 var o1 uint32
1559 if target.IsBigEndian() {
1560 o1 = binary.BigEndian.Uint32(p[r.Off()-2:])
1561 } else {
1562 o1 = binary.LittleEndian.Uint32(p[r.Off():])
1563 }
1564 switch o1 >> 26 {
1565 case 24,
1566 26,
1567 28:
1568 if t>>16 != 0 {
1569 goto overflow
1570 }
1571
1572 default:
1573 if int64(int16(t)) != t {
1574 goto overflow
1575 }
1576 }
1577 }
1578
1579 return int64(int16(t))
1580
1581 case sym.RV_POWER_HA:
1582 t += 0x8000
1583 fallthrough
1584
1585
1586 case sym.RV_POWER_HI:
1587 t >>= 16
1588
1589 if rv&sym.RV_CHECK_OVERFLOW != 0 {
1590
1591
1592 var o1 uint32
1593 if target.IsBigEndian() {
1594 o1 = binary.BigEndian.Uint32(p[r.Off()-2:])
1595 } else {
1596 o1 = binary.LittleEndian.Uint32(p[r.Off():])
1597 }
1598 switch o1 >> 26 {
1599 case 25,
1600 27,
1601 29:
1602 if t>>16 != 0 {
1603 goto overflow
1604 }
1605
1606 default:
1607 if int64(int16(t)) != t {
1608 goto overflow
1609 }
1610 }
1611 }
1612
1613 return int64(int16(t))
1614
1615 case sym.RV_POWER_DS:
1616 var o1 uint32
1617 if target.IsBigEndian() {
1618 o1 = uint32(binary.BigEndian.Uint16(p[r.Off():]))
1619 } else {
1620 o1 = uint32(binary.LittleEndian.Uint16(p[r.Off():]))
1621 }
1622 if t&3 != 0 {
1623 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
1624 }
1625 if (rv&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
1626 goto overflow
1627 }
1628 return int64(o1)&0x3 | int64(int16(t))
1629 }
1630
1631 overflow:
1632 ldr.Errorf(s, "relocation for %s+%d is too big: %d", ldr.SymName(rs), r.Off(), t)
1633 return t
1634 }
1635
1636 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
1637 switch r.Type() {
1638 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE, objabi.R_POWER_TLS_IE_PCREL34, objabi.R_POWER_TLS_LE_TPREL34, objabi.R_CALLPOWER:
1639 return ld.ExtrelocSimple(ldr, r), true
1640 case objabi.R_ADDRPOWER,
1641 objabi.R_ADDRPOWER_DS,
1642 objabi.R_ADDRPOWER_TOCREL,
1643 objabi.R_ADDRPOWER_TOCREL_DS,
1644 objabi.R_ADDRPOWER_GOT,
1645 objabi.R_ADDRPOWER_GOT_PCREL34,
1646 objabi.R_ADDRPOWER_PCREL,
1647 objabi.R_ADDRPOWER_D34,
1648 objabi.R_ADDRPOWER_PCREL34:
1649 return ld.ExtrelocViaOuterSym(ldr, r, s), true
1650 }
1651 return loader.ExtReloc{}, false
1652 }
1653
1654 func addpltsym(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym) {
1655 if ldr.SymPlt(s) >= 0 {
1656 return
1657 }
1658
1659 ld.Adddynsym(ldr, &ctxt.Target, &ctxt.ArchSyms, s)
1660
1661 if ctxt.IsELF {
1662 plt := ldr.MakeSymbolUpdater(ctxt.PLT)
1663 rela := ldr.MakeSymbolUpdater(ctxt.RelaPLT)
1664 if plt.Size() == 0 {
1665 panic("plt is not set up")
1666 }
1667
1668
1669 glink := ensureglinkresolver(ctxt, ldr)
1670
1671
1672
1673 rel, _ := glink.AddRel(objabi.R_CALLPOWER)
1674 rel.SetOff(int32(glink.Size()))
1675 rel.SetSiz(4)
1676 rel.SetSym(glink.Sym())
1677 glink.AddUint32(ctxt.Arch, 0x48000000)
1678
1679
1680
1681
1682
1683
1684
1685 ldr.SetPlt(s, int32(plt.Size()))
1686
1687 plt.Grow(plt.Size() + 8)
1688 plt.SetSize(plt.Size() + 8)
1689
1690 rela.AddAddrPlus(ctxt.Arch, plt.Sym(), int64(ldr.SymPlt(s)))
1691 rela.AddUint64(ctxt.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_PPC64_JMP_SLOT)))
1692 rela.AddUint64(ctxt.Arch, 0)
1693 } else {
1694 ctxt.Errorf(s, "addpltsym: unsupported binary format")
1695 }
1696 }
1697
1698
1699 func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilder {
1700 glink := ldr.CreateSymForUpdate(".glink", 0)
1701 if glink.Size() != 0 {
1702 return glink
1703 }
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714 glink.AddUint32(ctxt.Arch, OP_MFLR_R0)
1715 glink.AddUint32(ctxt.Arch, OP_BCL_NIA)
1716 glink.AddUint32(ctxt.Arch, 0x7d6802a6)
1717 glink.AddUint32(ctxt.Arch, OP_MTLR_R0)
1718
1719
1720
1721 glink.AddUint32(ctxt.Arch, 0x38000000)
1722 glink.AddUint32(ctxt.Arch, 0x7c006214)
1723 glink.AddUint32(ctxt.Arch, 0x7c0b0050)
1724 glink.AddUint32(ctxt.Arch, 0x7800f082)
1725
1726
1727
1728 glink.AddUint32(ctxt.Arch, 0xe98b0000)
1729 glink.AddUint32(ctxt.Arch, 0x7d6b6214)
1730
1731
1732
1733 glink.AddUint32(ctxt.Arch, 0xe98b0000)
1734 glink.AddUint32(ctxt.Arch, 0xe96b0008)
1735
1736
1737 glink.AddUint32(ctxt.Arch, OP_MTCTR_R12)
1738 glink.AddUint32(ctxt.Arch, OP_BCTR)
1739
1740
1741 r, _ := glink.AddRel(objabi.R_PCREL)
1742 r.SetSym(ctxt.PLT)
1743 r.SetSiz(8)
1744 r.SetOff(int32(glink.Size()))
1745 r.SetAdd(glink.Size())
1746 glink.AddUint64(ctxt.Arch, 0)
1747
1748
1749 res0m1b := glink.Size() - 8
1750 glink.SetUint32(ctxt.Arch, 16, 0x38000000|uint32(uint16(-res0m1b)))
1751 glink.SetUint32(ctxt.Arch, 32, 0xe98b0000|uint32(uint16(res0m1b-8)))
1752
1753
1754
1755
1756
1757
1758 du := ldr.MakeSymbolUpdater(ctxt.Dynamic)
1759 ld.Elfwritedynentsymplus(ctxt, du, elf.DT_PPC64_GLINK, glink.Sym(), glink.Size()-32)
1760
1761 return glink
1762 }
1763
View as plain text