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 t := ldr.SymType(r.Sym()); {
276 case t == sym.SDYNIMPORT:
277
278 if sym, firstUse := genpltstub(ctxt, ldr, r, i, s); firstUse {
279 stubs = append(stubs, sym)
280 }
281
282 case t == 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 t.IsText():
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 rt := ldr.SymType(r.Sym()); {
312 case rt == sym.SDYNIMPORT:
313
314 if sym, firstUse := genpltstub(ctxt, ldr, r, i, s); firstUse {
315 stubs = append(stubs, sym)
316 }
317
318 case rt == sym.SXREF:
319
320 ldr.Errorf(s, "Unsupported NOTOC external reference call into %s", ldr.SymName(r.Sym()))
321
322 case rt.IsText():
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()).IsText() {
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()).IsText() {
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.IsText() {
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.IsText() {
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).IsText() {
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 t := ldr.SymType(s); !t.IsDATA() && !t.IsRODATA() {
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, 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 rt := r.Type
909 fixupBe := int64(0)
910
911
912 if ctxt.Arch.ByteOrder == binary.BigEndian {
913 fixupBe = 2
914 }
915
916
917 writeElfReloc := func(rtyp elf.R_PPC64, offset int64, sym int32, addend int64) {
918 out.Write64(uint64(offset))
919 out.Write64(uint64(rtyp) | uint64(sym)<<32)
920 out.Write64(uint64(addend))
921 }
922
923 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
924 switch rt {
925 default:
926 return false
927 case objabi.R_ADDR, objabi.R_DWARFSECREF:
928 switch r.Size {
929 case 4:
930 writeElfReloc(elf.R_PPC64_ADDR32, sectoff, elfsym, r.Xadd)
931 case 8:
932 writeElfReloc(elf.R_PPC64_ADDR64, sectoff, elfsym, r.Xadd)
933 default:
934 return false
935 }
936 case objabi.R_ADDRPOWER_D34:
937 writeElfReloc(elf.R_PPC64_D34, sectoff, elfsym, r.Xadd)
938 case objabi.R_ADDRPOWER_PCREL34:
939 writeElfReloc(elf.R_PPC64_PCREL34, sectoff, elfsym, r.Xadd)
940 case objabi.R_POWER_TLS:
941 writeElfReloc(elf.R_PPC64_TLS, sectoff, elfsym, r.Xadd)
942 case objabi.R_POWER_TLS_LE:
943 sectoff += fixupBe
944 writeElfReloc(elf.R_PPC64_TPREL16_HA, sectoff, elfsym, r.Xadd)
945 writeElfReloc(elf.R_PPC64_TPREL16_LO, sectoff+4, elfsym, r.Xadd)
946 case objabi.R_POWER_TLS_LE_TPREL34:
947 writeElfReloc(elf.R_PPC64_TPREL34, sectoff, elfsym, r.Xadd)
948 case objabi.R_POWER_TLS_IE_PCREL34:
949 writeElfReloc(elf.R_PPC64_GOT_TPREL_PCREL34, sectoff, elfsym, r.Xadd)
950 case objabi.R_POWER_TLS_IE:
951 sectoff += fixupBe
952 writeElfReloc(elf.R_PPC64_GOT_TPREL16_HA, sectoff, elfsym, r.Xadd)
953 writeElfReloc(elf.R_PPC64_GOT_TPREL16_LO_DS, sectoff+4, elfsym, r.Xadd)
954 case objabi.R_ADDRPOWER:
955 sectoff += fixupBe
956 writeElfReloc(elf.R_PPC64_ADDR16_HA, sectoff, elfsym, r.Xadd)
957 writeElfReloc(elf.R_PPC64_ADDR16_LO, sectoff+4, elfsym, r.Xadd)
958 case objabi.R_ADDRPOWER_DS:
959 sectoff += fixupBe
960 writeElfReloc(elf.R_PPC64_ADDR16_HA, sectoff, elfsym, r.Xadd)
961 writeElfReloc(elf.R_PPC64_ADDR16_LO_DS, sectoff+4, elfsym, r.Xadd)
962 case objabi.R_ADDRPOWER_GOT:
963 sectoff += fixupBe
964 writeElfReloc(elf.R_PPC64_GOT16_HA, sectoff, elfsym, r.Xadd)
965 writeElfReloc(elf.R_PPC64_GOT16_LO_DS, sectoff+4, elfsym, r.Xadd)
966 case objabi.R_ADDRPOWER_GOT_PCREL34:
967 writeElfReloc(elf.R_PPC64_GOT_PCREL34, sectoff, elfsym, r.Xadd)
968 case objabi.R_ADDRPOWER_PCREL:
969 sectoff += fixupBe
970 addend := r.Xadd + fixupBe
971 writeElfReloc(elf.R_PPC64_REL16_HA, sectoff, elfsym, addend)
972 writeElfReloc(elf.R_PPC64_REL16_LO, sectoff+4, elfsym, addend+4)
973 case objabi.R_ADDRPOWER_TOCREL:
974 sectoff += fixupBe
975 writeElfReloc(elf.R_PPC64_TOC16_HA, sectoff, elfsym, r.Xadd)
976 writeElfReloc(elf.R_PPC64_TOC16_LO, sectoff+4, elfsym, r.Xadd)
977 case objabi.R_ADDRPOWER_TOCREL_DS:
978 sectoff += fixupBe
979 writeElfReloc(elf.R_PPC64_TOC16_HA, sectoff, elfsym, r.Xadd)
980 writeElfReloc(elf.R_PPC64_TOC16_LO_DS, sectoff+4, elfsym, r.Xadd)
981 case objabi.R_CALLPOWER:
982 if r.Size != 4 {
983 return false
984 }
985 if !hasPCrel {
986 writeElfReloc(elf.R_PPC64_REL24, sectoff, elfsym, r.Xadd)
987 } else {
988
989 writeElfReloc(elf.R_PPC64_REL24_NOTOC, sectoff, elfsym, r.Xadd)
990 }
991 }
992
993 return true
994 }
995
996 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
997 if plt.Size() == 0 {
998
999
1000
1001
1002 plt.SetSize(16)
1003 }
1004 }
1005
1006 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
1007 return false
1008 }
1009
1010
1011 func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 {
1012 v := ldr.SymVersion(s)
1013 if out := ldr.OuterSym(s); out != 0 {
1014 v = ldr.SymVersion(out)
1015 }
1016
1017 toc := syms.DotTOC[v]
1018 if toc == 0 {
1019 ldr.Errorf(s, "TOC-relative relocation in object without .TOC.")
1020 return 0
1021 }
1022
1023 return ldr.SymValue(toc)
1024 }
1025
1026
1027 func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
1028 rs := r.Sym()
1029 var o1, o2 uint32
1030 var t int64
1031 useAddi := false
1032
1033 if target.IsBigEndian() {
1034 o1 = uint32(val >> 32)
1035 o2 = uint32(val)
1036 } else {
1037 o1 = uint32(val)
1038 o2 = uint32(val >> 32)
1039 }
1040
1041
1042
1043
1044 if target.IsAIX() {
1045 if !strings.HasPrefix(ldr.SymName(rs), "TOC.") {
1046 ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
1047 }
1048 relocs := ldr.Relocs(rs)
1049 tarSym := relocs.At(0).Sym()
1050
1051 if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata {
1052 t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC)
1053
1054 o2 = (o2 & 0x03FF0000) | 0xE<<26
1055 useAddi = true
1056 } else {
1057 t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC)
1058 }
1059 } else {
1060 t = ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s)
1061 }
1062
1063 if t != int64(int32(t)) {
1064 ldr.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", ldr.SymName(s), rs, t)
1065 }
1066
1067 if t&0x8000 != 0 {
1068 t += 0x10000
1069 }
1070
1071 o1 |= uint32((t >> 16) & 0xFFFF)
1072
1073 switch r.Type() {
1074 case objabi.R_ADDRPOWER_TOCREL_DS:
1075 if useAddi {
1076 o2 |= uint32(t) & 0xFFFF
1077 } else {
1078 if t&3 != 0 {
1079 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
1080 }
1081 o2 |= uint32(t) & 0xFFFC
1082 }
1083 case objabi.R_ADDRPOWER_TOCREL:
1084 o2 |= uint32(t) & 0xffff
1085 default:
1086 return -1
1087 }
1088
1089 if target.IsBigEndian() {
1090 return int64(o1)<<32 | int64(o2)
1091 }
1092 return int64(o2)<<32 | int64(o1)
1093 }
1094
1095
1096
1097 func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
1098 rs := r.Sym()
1099 if target.IsAIX() {
1100 ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
1101 }
1102 o1, o2 := unpackInstPair(target, val)
1103
1104
1105
1106
1107
1108
1109 t := ldr.SymAddr(rs) + r.Add()
1110 if t < 0 || t >= 1<<31 {
1111 ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs))
1112 }
1113
1114
1115
1116 switch r.Type() {
1117 case objabi.R_ADDRPOWER_PCREL34:
1118
1119 t -= (ldr.SymValue(s) + int64(r.Off()))
1120 o1 &^= 0x3ffff
1121 o2 &^= 0x0ffff
1122 o1 |= computePrefix34HI(t)
1123 o2 |= computeLO(int32(t))
1124 case objabi.R_ADDRPOWER_D34:
1125 o1 &^= 0x3ffff
1126 o2 &^= 0x0ffff
1127 o1 |= computePrefix34HI(t)
1128 o2 |= computeLO(int32(t))
1129 case objabi.R_ADDRPOWER:
1130 o1 &^= 0xffff
1131 o2 &^= 0xffff
1132 o1 |= computeHA(int32(t))
1133 o2 |= computeLO(int32(t))
1134 case objabi.R_ADDRPOWER_DS:
1135 o1 &^= 0xffff
1136 o2 &^= 0xfffc
1137 o1 |= computeHA(int32(t))
1138 o2 |= computeLO(int32(t))
1139 if t&3 != 0 {
1140 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
1141 }
1142 default:
1143 return -1
1144 }
1145
1146 return packInstPair(target, o1, o2)
1147 }
1148
1149
1150 func r2Valid(ctxt *ld.Link) bool {
1151 return isLinkingPIC(ctxt)
1152 }
1153
1154
1155 func isLinkingPIC(ctxt *ld.Link) bool {
1156 switch ctxt.BuildMode {
1157 case ld.BuildModeCArchive, ld.BuildModeCShared, ld.BuildModePIE, ld.BuildModeShared, ld.BuildModePlugin:
1158 return true
1159 }
1160
1161 return ctxt.IsSharedGoLink()
1162 }
1163
1164
1165 func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
1166
1167
1168
1169
1170
1171 if ctxt.IsExternal() && r2Valid(ctxt) {
1172
1173 return
1174 }
1175
1176 relocs := ldr.Relocs(s)
1177 r := relocs.At(ri)
1178 var t int64
1179
1180
1181
1182 if ldr.SymValue(rs) != 0 {
1183 t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
1184 }
1185 switch r.Type() {
1186 case objabi.R_CALLPOWER:
1187
1188 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)) {
1189 var tramp loader.Sym
1190 for i := 0; ; i++ {
1191
1192
1193
1194
1195
1196 oName := ldr.SymName(rs)
1197 name := oName
1198 if r.Add() == 0 {
1199 name += fmt.Sprintf("-tramp%d", i)
1200 } else {
1201 name += fmt.Sprintf("%+x-tramp%d", r.Add(), i)
1202 }
1203
1204
1205
1206 tramp = ldr.LookupOrCreateSym(name, ldr.SymVersion(rs))
1207 if oName == "runtime.deferreturn" {
1208 ldr.SetIsDeferReturnTramp(tramp, true)
1209 }
1210 if ldr.SymValue(tramp) == 0 {
1211 break
1212 }
1213
1214
1215 t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off()))
1216
1217
1218
1219 if (ctxt.IsInternal() && int64(int32(t<<6)>>6) == t) || (ctxt.IsExternal() && ldr.SymSect(s) == ldr.SymSect(tramp)) {
1220 break
1221 }
1222 }
1223 if ldr.SymType(tramp) == 0 {
1224 trampb := ldr.MakeSymbolUpdater(tramp)
1225 ctxt.AddTramp(trampb, ldr.SymType(s))
1226 gentramp(ctxt, ldr, trampb, rs, r.Add())
1227 ctxt.AddDwarfDirectTrampoline(tramp, rs, r.Add(), ldr.SymUnit(s))
1228 }
1229 sb := ldr.MakeSymbolUpdater(s)
1230 relocs := sb.Relocs()
1231 r := relocs.At(ri)
1232 r.SetSym(tramp)
1233 r.SetAdd(0)
1234 }
1235 default:
1236 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
1237 }
1238 }
1239
1240 func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
1241 tramp.SetSize(16)
1242 P := make([]byte, tramp.Size())
1243 var o1, o2 uint32
1244
1245
1246
1247 if strings.HasPrefix(ldr.SymName(target), "runtime.elf_") {
1248 log.Fatalf("Internal linker does not support trampolines to ELFv2 ABI"+
1249 " register save/restore function %s", ldr.SymName(target))
1250 }
1251
1252 if ctxt.IsAIX() {
1253
1254
1255
1256
1257
1258 o1 = uint32(OP_ADDIS_R12_R2)
1259 o2 = uint32(OP_LD_R12_R12)
1260
1261 toctramp := ldr.CreateSymForUpdate("TOC."+ldr.SymName(tramp.Sym()), 0)
1262 toctramp.SetType(sym.SXCOFFTOC)
1263 toctramp.AddAddrPlus(ctxt.Arch, target, offset)
1264
1265 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_TOCREL_DS)
1266 r.SetOff(0)
1267 r.SetSiz(8)
1268 r.SetSym(toctramp.Sym())
1269 } else if hasPCrel {
1270
1271 o1 = uint32(OP_PLA_PFX)
1272 o2 = uint32(OP_PLA_SFX_R12)
1273
1274
1275 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_PCREL34)
1276 r.SetOff(0)
1277 r.SetSiz(8)
1278 r.SetSym(target)
1279 r.SetAdd(offset)
1280 } else {
1281
1282
1283
1284 o1 = uint32(OP_LIS_R12)
1285 o2 = uint32(OP_ADDI_R12_R12)
1286
1287 t := ldr.SymValue(target)
1288 if t == 0 || r2Valid(ctxt) || ctxt.IsExternal() {
1289
1290 r, _ := tramp.AddRel(objabi.R_ADDRPOWER)
1291 if r2Valid(ctxt) {
1292
1293 o1 |= uint32(2 << 16)
1294 r.SetType(objabi.R_ADDRPOWER_TOCREL)
1295 }
1296 r.SetOff(0)
1297 r.SetSiz(8)
1298 r.SetSym(target)
1299 r.SetAdd(offset)
1300 } else {
1301
1302 t += offset
1303 o1 |= (uint32(t) + 0x8000) >> 16
1304 o2 |= uint32(t) & 0xFFFF
1305 }
1306 }
1307
1308 o3 := uint32(OP_MTCTR_R12)
1309 o4 := uint32(OP_BCTR)
1310 ctxt.Arch.ByteOrder.PutUint32(P, o1)
1311 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
1312 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
1313 ctxt.Arch.ByteOrder.PutUint32(P[12:], o4)
1314 tramp.SetData(P)
1315 }
1316
1317
1318
1319 func unpackInstPair(target *ld.Target, r int64) (uint32, uint32) {
1320 if target.IsBigEndian() {
1321 return uint32(r >> 32), uint32(r)
1322 }
1323 return uint32(r), uint32(r >> 32)
1324 }
1325
1326
1327
1328 func packInstPair(target *ld.Target, o1, o2 uint32) int64 {
1329 if target.IsBigEndian() {
1330 return (int64(o1) << 32) | int64(o2)
1331 }
1332 return int64(o1) | (int64(o2) << 32)
1333 }
1334
1335
1336
1337 func computeHA(val int32) uint32 {
1338 return uint32(uint16((val + 0x8000) >> 16))
1339 }
1340
1341
1342
1343 func computeLO(val int32) uint32 {
1344 return uint32(uint16(val))
1345 }
1346
1347
1348
1349
1350 func computePrefix34HI(val int64) uint32 {
1351 return uint32((val >> 16) & 0x3FFFF)
1352 }
1353
1354 func computeTLSLEReloc(target *ld.Target, ldr *loader.Loader, rs, s loader.Sym) int64 {
1355
1356
1357
1358
1359 v := ldr.SymValue(rs) - 0x7000
1360 if target.IsAIX() {
1361
1362
1363 v -= 0x800
1364 }
1365
1366 if int64(int32(v)) != v {
1367 ldr.Errorf(s, "TLS offset out of range %d", v)
1368 }
1369 return v
1370 }
1371
1372 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) {
1373 rs := r.Sym()
1374 if target.IsExternal() {
1375
1376
1377 switch rt := r.Type(); rt {
1378 default:
1379 if !target.IsAIX() {
1380 return val, nExtReloc, false
1381 }
1382 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_IE_PCREL34, objabi.R_POWER_TLS_LE_TPREL34, objabi.R_ADDRPOWER_GOT_PCREL34:
1383 nExtReloc = 1
1384 return val, nExtReloc, true
1385 case objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
1386 if target.IsAIX() && rt == objabi.R_POWER_TLS_LE {
1387
1388
1389
1390 const expectedOpcodes = 0x3C00000038000000
1391 const expectedOpmasks = 0xFC000000FC000000
1392 if uint64(val)&expectedOpmasks != expectedOpcodes {
1393 ldr.Errorf(s, "relocation for %s+%d is not an addis/addi pair: %16x", ldr.SymName(rs), r.Off(), uint64(val))
1394 }
1395 nval := (int64(uint32(0x380d0000)) | val&0x03e00000) << 32
1396 nval |= int64(OP_NOP)
1397 val = nval
1398 nExtReloc = 1
1399 } else {
1400 nExtReloc = 2
1401 }
1402 return val, nExtReloc, true
1403 case objabi.R_ADDRPOWER,
1404 objabi.R_ADDRPOWER_DS,
1405 objabi.R_ADDRPOWER_TOCREL,
1406 objabi.R_ADDRPOWER_TOCREL_DS,
1407 objabi.R_ADDRPOWER_GOT,
1408 objabi.R_ADDRPOWER_PCREL:
1409 nExtReloc = 2
1410 if !target.IsAIX() {
1411 return val, nExtReloc, true
1412 }
1413 case objabi.R_CALLPOWER, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34:
1414 nExtReloc = 1
1415 if !target.IsAIX() {
1416 return val, nExtReloc, true
1417 }
1418 }
1419 }
1420
1421 switch r.Type() {
1422 case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
1423 return archreloctoc(ldr, target, syms, r, s, val), nExtReloc, true
1424 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34:
1425 return archrelocaddr(ldr, target, syms, r, s, val), nExtReloc, true
1426 case objabi.R_CALLPOWER:
1427
1428
1429 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
1430
1431 tgtName := ldr.SymName(rs)
1432
1433
1434
1435
1436 if !hasPCrel && !ldr.AttrExternal(rs) && ldr.AttrShared(rs) && tgtName != "runtime.duffzero" && tgtName != "runtime.duffcopy" {
1437
1438 if r.Add() == 0 && ldr.SymType(rs).IsText() {
1439 t += 8
1440 }
1441 }
1442
1443 if t&3 != 0 {
1444 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
1445 }
1446
1447
1448 if int64(int32(t<<6)>>6) != t {
1449 ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
1450 }
1451 return val | int64(uint32(t)&^0xfc000003), nExtReloc, true
1452 case objabi.R_POWER_TOC:
1453 return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true
1454
1455 case objabi.R_ADDRPOWER_PCREL:
1456 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
1457 ha, l := unpackInstPair(target, val)
1458 l |= computeLO(int32(t))
1459 ha |= computeHA(int32(t))
1460 return packInstPair(target, ha, l), nExtReloc, true
1461
1462 case objabi.R_POWER_TLS:
1463 const OP_ADD = 31<<26 | 266<<1
1464 const MASK_OP_ADD = 0x3F<<26 | 0x1FF<<1
1465 if val&MASK_OP_ADD != OP_ADD {
1466 ldr.Errorf(s, "R_POWER_TLS reloc only supports XO form ADD, not %08X", val)
1467 }
1468
1469 if (val>>11)&0x1F != 13 {
1470
1471 ldr.Errorf(s, "R_POWER_TLS reloc requires R13 in RB (%08X).", uint32(val))
1472 }
1473 return val, nExtReloc, true
1474
1475 case objabi.R_POWER_TLS_IE:
1476
1477 if !(target.IsPIE() && target.IsElf()) {
1478 log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s))
1479 }
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489 const OP_MASK = 0x3F << 26
1490 const OP_RA_MASK = 0x1F << 16
1491
1492 mask := packInstPair(target, OP_RA_MASK, OP_MASK)
1493 addi_op := packInstPair(target, 0, OP_ADDI)
1494 val &^= mask
1495 val |= addi_op
1496 fallthrough
1497
1498 case objabi.R_POWER_TLS_LE:
1499 v := computeTLSLEReloc(target, ldr, rs, s)
1500 o1, o2 := unpackInstPair(target, val)
1501 o1 |= computeHA(int32(v))
1502 o2 |= computeLO(int32(v))
1503 return packInstPair(target, o1, o2), nExtReloc, true
1504
1505 case objabi.R_POWER_TLS_IE_PCREL34:
1506
1507 if !(target.IsPIE() && target.IsElf()) {
1508 log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s))
1509 }
1510
1511
1512
1513
1514
1515
1516
1517 const OP_MASK_PFX = 0xFFFFFFFF
1518 const OP_MASK = (0x3F << 26) | 0xFFFF
1519 const OP_PFX = 1<<26 | 2<<24
1520 const OP_PLA = 14 << 26
1521 mask := packInstPair(target, OP_MASK_PFX, OP_MASK)
1522 pla_op := packInstPair(target, OP_PFX, OP_PLA)
1523 val &^= mask
1524 val |= pla_op
1525 fallthrough
1526
1527 case objabi.R_POWER_TLS_LE_TPREL34:
1528 v := computeTLSLEReloc(target, ldr, rs, s)
1529 o1, o2 := unpackInstPair(target, val)
1530 o1 |= computePrefix34HI(v)
1531 o2 |= computeLO(int32(v))
1532 return packInstPair(target, o1, o2), nExtReloc, true
1533 }
1534
1535 return val, nExtReloc, false
1536 }
1537
1538 func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc, rv sym.RelocVariant, s loader.Sym, t int64, p []byte) (relocatedOffset int64) {
1539 rs := r.Sym()
1540 switch rv & sym.RV_TYPE_MASK {
1541 default:
1542 ldr.Errorf(s, "unexpected relocation variant %d", rv)
1543 fallthrough
1544
1545 case sym.RV_NONE:
1546 return t
1547
1548 case sym.RV_POWER_LO:
1549 if rv&sym.RV_CHECK_OVERFLOW != 0 {
1550
1551
1552 var o1 uint32
1553 if target.IsBigEndian() {
1554 o1 = binary.BigEndian.Uint32(p[r.Off()-2:])
1555 } else {
1556 o1 = binary.LittleEndian.Uint32(p[r.Off():])
1557 }
1558 switch o1 >> 26 {
1559 case 24,
1560 26,
1561 28:
1562 if t>>16 != 0 {
1563 goto overflow
1564 }
1565
1566 default:
1567 if int64(int16(t)) != t {
1568 goto overflow
1569 }
1570 }
1571 }
1572
1573 return int64(int16(t))
1574
1575 case sym.RV_POWER_HA:
1576 t += 0x8000
1577 fallthrough
1578
1579
1580 case sym.RV_POWER_HI:
1581 t >>= 16
1582
1583 if rv&sym.RV_CHECK_OVERFLOW != 0 {
1584
1585
1586 var o1 uint32
1587 if target.IsBigEndian() {
1588 o1 = binary.BigEndian.Uint32(p[r.Off()-2:])
1589 } else {
1590 o1 = binary.LittleEndian.Uint32(p[r.Off():])
1591 }
1592 switch o1 >> 26 {
1593 case 25,
1594 27,
1595 29:
1596 if t>>16 != 0 {
1597 goto overflow
1598 }
1599
1600 default:
1601 if int64(int16(t)) != t {
1602 goto overflow
1603 }
1604 }
1605 }
1606
1607 return int64(int16(t))
1608
1609 case sym.RV_POWER_DS:
1610 var o1 uint32
1611 if target.IsBigEndian() {
1612 o1 = uint32(binary.BigEndian.Uint16(p[r.Off():]))
1613 } else {
1614 o1 = uint32(binary.LittleEndian.Uint16(p[r.Off():]))
1615 }
1616 if t&3 != 0 {
1617 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
1618 }
1619 if (rv&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
1620 goto overflow
1621 }
1622 return int64(o1)&0x3 | int64(int16(t))
1623 }
1624
1625 overflow:
1626 ldr.Errorf(s, "relocation for %s+%d is too big: %d", ldr.SymName(rs), r.Off(), t)
1627 return t
1628 }
1629
1630 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
1631 switch r.Type() {
1632 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:
1633 return ld.ExtrelocSimple(ldr, r), true
1634 case objabi.R_ADDRPOWER,
1635 objabi.R_ADDRPOWER_DS,
1636 objabi.R_ADDRPOWER_TOCREL,
1637 objabi.R_ADDRPOWER_TOCREL_DS,
1638 objabi.R_ADDRPOWER_GOT,
1639 objabi.R_ADDRPOWER_GOT_PCREL34,
1640 objabi.R_ADDRPOWER_PCREL,
1641 objabi.R_ADDRPOWER_D34,
1642 objabi.R_ADDRPOWER_PCREL34:
1643 return ld.ExtrelocViaOuterSym(ldr, r, s), true
1644 }
1645 return loader.ExtReloc{}, false
1646 }
1647
1648 func addpltsym(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym) {
1649 if ldr.SymPlt(s) >= 0 {
1650 return
1651 }
1652
1653 ld.Adddynsym(ldr, &ctxt.Target, &ctxt.ArchSyms, s)
1654
1655 if ctxt.IsELF {
1656 plt := ldr.MakeSymbolUpdater(ctxt.PLT)
1657 rela := ldr.MakeSymbolUpdater(ctxt.RelaPLT)
1658 if plt.Size() == 0 {
1659 panic("plt is not set up")
1660 }
1661
1662
1663 glink := ensureglinkresolver(ctxt, ldr)
1664
1665
1666
1667 rel, _ := glink.AddRel(objabi.R_CALLPOWER)
1668 rel.SetOff(int32(glink.Size()))
1669 rel.SetSiz(4)
1670 rel.SetSym(glink.Sym())
1671 glink.AddUint32(ctxt.Arch, 0x48000000)
1672
1673
1674
1675
1676
1677
1678
1679 ldr.SetPlt(s, int32(plt.Size()))
1680
1681 plt.Grow(plt.Size() + 8)
1682 plt.SetSize(plt.Size() + 8)
1683
1684 rela.AddAddrPlus(ctxt.Arch, plt.Sym(), int64(ldr.SymPlt(s)))
1685 rela.AddUint64(ctxt.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_PPC64_JMP_SLOT)))
1686 rela.AddUint64(ctxt.Arch, 0)
1687 } else {
1688 ctxt.Errorf(s, "addpltsym: unsupported binary format")
1689 }
1690 }
1691
1692
1693 func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilder {
1694 glink := ldr.CreateSymForUpdate(".glink", 0)
1695 if glink.Size() != 0 {
1696 return glink
1697 }
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708 glink.AddUint32(ctxt.Arch, OP_MFLR_R0)
1709 glink.AddUint32(ctxt.Arch, OP_BCL_NIA)
1710 glink.AddUint32(ctxt.Arch, 0x7d6802a6)
1711 glink.AddUint32(ctxt.Arch, OP_MTLR_R0)
1712
1713
1714
1715 glink.AddUint32(ctxt.Arch, 0x38000000)
1716 glink.AddUint32(ctxt.Arch, 0x7c006214)
1717 glink.AddUint32(ctxt.Arch, 0x7c0b0050)
1718 glink.AddUint32(ctxt.Arch, 0x7800f082)
1719
1720
1721
1722 glink.AddUint32(ctxt.Arch, 0xe98b0000)
1723 glink.AddUint32(ctxt.Arch, 0x7d6b6214)
1724
1725
1726
1727 glink.AddUint32(ctxt.Arch, 0xe98b0000)
1728 glink.AddUint32(ctxt.Arch, 0xe96b0008)
1729
1730
1731 glink.AddUint32(ctxt.Arch, OP_MTCTR_R12)
1732 glink.AddUint32(ctxt.Arch, OP_BCTR)
1733
1734
1735 r, _ := glink.AddRel(objabi.R_PCREL)
1736 r.SetSym(ctxt.PLT)
1737 r.SetSiz(8)
1738 r.SetOff(int32(glink.Size()))
1739 r.SetAdd(glink.Size())
1740 glink.AddUint64(ctxt.Arch, 0)
1741
1742
1743 res0m1b := glink.Size() - 8
1744 glink.SetUint32(ctxt.Arch, 16, 0x38000000|uint32(uint16(-res0m1b)))
1745 glink.SetUint32(ctxt.Arch, 32, 0xe98b0000|uint32(uint16(res0m1b-8)))
1746
1747
1748
1749
1750
1751
1752 du := ldr.MakeSymbolUpdater(ctxt.Dynamic)
1753 ld.Elfwritedynentsymplus(ctxt, du, elf.DT_PPC64_GLINK, glink.Sym(), glink.Size()-32)
1754
1755 return glink
1756 }
1757
View as plain text