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 }
1228 sb := ldr.MakeSymbolUpdater(s)
1229 relocs := sb.Relocs()
1230 r := relocs.At(ri)
1231 r.SetSym(tramp)
1232 r.SetAdd(0)
1233 }
1234 default:
1235 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
1236 }
1237 }
1238
1239 func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
1240 tramp.SetSize(16)
1241 P := make([]byte, tramp.Size())
1242 var o1, o2 uint32
1243
1244
1245
1246 if strings.HasPrefix(ldr.SymName(target), "runtime.elf_") {
1247 log.Fatalf("Internal linker does not support trampolines to ELFv2 ABI"+
1248 " register save/restore function %s", ldr.SymName(target))
1249 }
1250
1251 if ctxt.IsAIX() {
1252
1253
1254
1255
1256
1257 o1 = uint32(OP_ADDIS_R12_R2)
1258 o2 = uint32(OP_LD_R12_R12)
1259
1260 toctramp := ldr.CreateSymForUpdate("TOC."+ldr.SymName(tramp.Sym()), 0)
1261 toctramp.SetType(sym.SXCOFFTOC)
1262 toctramp.AddAddrPlus(ctxt.Arch, target, offset)
1263
1264 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_TOCREL_DS)
1265 r.SetOff(0)
1266 r.SetSiz(8)
1267 r.SetSym(toctramp.Sym())
1268 } else if hasPCrel {
1269
1270 o1 = uint32(OP_PLA_PFX)
1271 o2 = uint32(OP_PLA_SFX_R12)
1272
1273
1274 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_PCREL34)
1275 r.SetOff(0)
1276 r.SetSiz(8)
1277 r.SetSym(target)
1278 r.SetAdd(offset)
1279 } else {
1280
1281
1282
1283 o1 = uint32(OP_LIS_R12)
1284 o2 = uint32(OP_ADDI_R12_R12)
1285
1286 t := ldr.SymValue(target)
1287 if t == 0 || r2Valid(ctxt) || ctxt.IsExternal() {
1288
1289 r, _ := tramp.AddRel(objabi.R_ADDRPOWER)
1290 if r2Valid(ctxt) {
1291
1292 o1 |= uint32(2 << 16)
1293 r.SetType(objabi.R_ADDRPOWER_TOCREL)
1294 }
1295 r.SetOff(0)
1296 r.SetSiz(8)
1297 r.SetSym(target)
1298 r.SetAdd(offset)
1299 } else {
1300
1301 t += offset
1302 o1 |= (uint32(t) + 0x8000) >> 16
1303 o2 |= uint32(t) & 0xFFFF
1304 }
1305 }
1306
1307 o3 := uint32(OP_MTCTR_R12)
1308 o4 := uint32(OP_BCTR)
1309 ctxt.Arch.ByteOrder.PutUint32(P, o1)
1310 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
1311 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
1312 ctxt.Arch.ByteOrder.PutUint32(P[12:], o4)
1313 tramp.SetData(P)
1314 }
1315
1316
1317
1318 func unpackInstPair(target *ld.Target, r int64) (uint32, uint32) {
1319 if target.IsBigEndian() {
1320 return uint32(r >> 32), uint32(r)
1321 }
1322 return uint32(r), uint32(r >> 32)
1323 }
1324
1325
1326
1327 func packInstPair(target *ld.Target, o1, o2 uint32) int64 {
1328 if target.IsBigEndian() {
1329 return (int64(o1) << 32) | int64(o2)
1330 }
1331 return int64(o1) | (int64(o2) << 32)
1332 }
1333
1334
1335
1336 func computeHA(val int32) uint32 {
1337 return uint32(uint16((val + 0x8000) >> 16))
1338 }
1339
1340
1341
1342 func computeLO(val int32) uint32 {
1343 return uint32(uint16(val))
1344 }
1345
1346
1347
1348
1349 func computePrefix34HI(val int64) uint32 {
1350 return uint32((val >> 16) & 0x3FFFF)
1351 }
1352
1353 func computeTLSLEReloc(target *ld.Target, ldr *loader.Loader, rs, s loader.Sym) int64 {
1354
1355
1356
1357
1358 v := ldr.SymValue(rs) - 0x7000
1359 if target.IsAIX() {
1360
1361
1362 v -= 0x800
1363 }
1364
1365 if int64(int32(v)) != v {
1366 ldr.Errorf(s, "TLS offset out of range %d", v)
1367 }
1368 return v
1369 }
1370
1371 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) {
1372 rs := r.Sym()
1373 if target.IsExternal() {
1374
1375
1376 switch rt := r.Type(); rt {
1377 default:
1378 if !target.IsAIX() {
1379 return val, nExtReloc, false
1380 }
1381 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_IE_PCREL34, objabi.R_POWER_TLS_LE_TPREL34, objabi.R_ADDRPOWER_GOT_PCREL34:
1382 nExtReloc = 1
1383 return val, nExtReloc, true
1384 case objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
1385 if target.IsAIX() && rt == objabi.R_POWER_TLS_LE {
1386
1387
1388
1389 const expectedOpcodes = 0x3C00000038000000
1390 const expectedOpmasks = 0xFC000000FC000000
1391 if uint64(val)&expectedOpmasks != expectedOpcodes {
1392 ldr.Errorf(s, "relocation for %s+%d is not an addis/addi pair: %16x", ldr.SymName(rs), r.Off(), uint64(val))
1393 }
1394 nval := (int64(uint32(0x380d0000)) | val&0x03e00000) << 32
1395 nval |= int64(OP_NOP)
1396 val = nval
1397 nExtReloc = 1
1398 } else {
1399 nExtReloc = 2
1400 }
1401 return val, nExtReloc, true
1402 case objabi.R_ADDRPOWER,
1403 objabi.R_ADDRPOWER_DS,
1404 objabi.R_ADDRPOWER_TOCREL,
1405 objabi.R_ADDRPOWER_TOCREL_DS,
1406 objabi.R_ADDRPOWER_GOT,
1407 objabi.R_ADDRPOWER_PCREL:
1408 nExtReloc = 2
1409 if !target.IsAIX() {
1410 return val, nExtReloc, true
1411 }
1412 case objabi.R_CALLPOWER, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34:
1413 nExtReloc = 1
1414 if !target.IsAIX() {
1415 return val, nExtReloc, true
1416 }
1417 }
1418 }
1419
1420 switch r.Type() {
1421 case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
1422 return archreloctoc(ldr, target, syms, r, s, val), nExtReloc, true
1423 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS, objabi.R_ADDRPOWER_D34, objabi.R_ADDRPOWER_PCREL34:
1424 return archrelocaddr(ldr, target, syms, r, s, val), nExtReloc, true
1425 case objabi.R_CALLPOWER:
1426
1427
1428 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
1429
1430 tgtName := ldr.SymName(rs)
1431
1432
1433
1434
1435 if !hasPCrel && !ldr.AttrExternal(rs) && ldr.AttrShared(rs) && tgtName != "runtime.duffzero" && tgtName != "runtime.duffcopy" {
1436
1437 if r.Add() == 0 && ldr.SymType(rs).IsText() {
1438 t += 8
1439 }
1440 }
1441
1442 if t&3 != 0 {
1443 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
1444 }
1445
1446
1447 if int64(int32(t<<6)>>6) != t {
1448 ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
1449 }
1450 return val | int64(uint32(t)&^0xfc000003), nExtReloc, true
1451 case objabi.R_POWER_TOC:
1452 return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true
1453
1454 case objabi.R_ADDRPOWER_PCREL:
1455 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
1456 ha, l := unpackInstPair(target, val)
1457 l |= computeLO(int32(t))
1458 ha |= computeHA(int32(t))
1459 return packInstPair(target, ha, l), nExtReloc, true
1460
1461 case objabi.R_POWER_TLS:
1462 const OP_ADD = 31<<26 | 266<<1
1463 const MASK_OP_ADD = 0x3F<<26 | 0x1FF<<1
1464 if val&MASK_OP_ADD != OP_ADD {
1465 ldr.Errorf(s, "R_POWER_TLS reloc only supports XO form ADD, not %08X", val)
1466 }
1467
1468 if (val>>11)&0x1F != 13 {
1469
1470 ldr.Errorf(s, "R_POWER_TLS reloc requires R13 in RB (%08X).", uint32(val))
1471 }
1472 return val, nExtReloc, true
1473
1474 case objabi.R_POWER_TLS_IE:
1475
1476 if !(target.IsPIE() && target.IsElf()) {
1477 log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s))
1478 }
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488 const OP_MASK = 0x3F << 26
1489 const OP_RA_MASK = 0x1F << 16
1490
1491 mask := packInstPair(target, OP_RA_MASK, OP_MASK)
1492 addi_op := packInstPair(target, 0, OP_ADDI)
1493 val &^= mask
1494 val |= addi_op
1495 fallthrough
1496
1497 case objabi.R_POWER_TLS_LE:
1498 v := computeTLSLEReloc(target, ldr, rs, s)
1499 o1, o2 := unpackInstPair(target, val)
1500 o1 |= computeHA(int32(v))
1501 o2 |= computeLO(int32(v))
1502 return packInstPair(target, o1, o2), nExtReloc, true
1503
1504 case objabi.R_POWER_TLS_IE_PCREL34:
1505
1506 if !(target.IsPIE() && target.IsElf()) {
1507 log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s))
1508 }
1509
1510
1511
1512
1513
1514
1515
1516 const OP_MASK_PFX = 0xFFFFFFFF
1517 const OP_MASK = (0x3F << 26) | 0xFFFF
1518 const OP_PFX = 1<<26 | 2<<24
1519 const OP_PLA = 14 << 26
1520 mask := packInstPair(target, OP_MASK_PFX, OP_MASK)
1521 pla_op := packInstPair(target, OP_PFX, OP_PLA)
1522 val &^= mask
1523 val |= pla_op
1524 fallthrough
1525
1526 case objabi.R_POWER_TLS_LE_TPREL34:
1527 v := computeTLSLEReloc(target, ldr, rs, s)
1528 o1, o2 := unpackInstPair(target, val)
1529 o1 |= computePrefix34HI(v)
1530 o2 |= computeLO(int32(v))
1531 return packInstPair(target, o1, o2), nExtReloc, true
1532 }
1533
1534 return val, nExtReloc, false
1535 }
1536
1537 func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc, rv sym.RelocVariant, s loader.Sym, t int64, p []byte) (relocatedOffset int64) {
1538 rs := r.Sym()
1539 switch rv & sym.RV_TYPE_MASK {
1540 default:
1541 ldr.Errorf(s, "unexpected relocation variant %d", rv)
1542 fallthrough
1543
1544 case sym.RV_NONE:
1545 return t
1546
1547 case sym.RV_POWER_LO:
1548 if rv&sym.RV_CHECK_OVERFLOW != 0 {
1549
1550
1551 var o1 uint32
1552 if target.IsBigEndian() {
1553 o1 = binary.BigEndian.Uint32(p[r.Off()-2:])
1554 } else {
1555 o1 = binary.LittleEndian.Uint32(p[r.Off():])
1556 }
1557 switch o1 >> 26 {
1558 case 24,
1559 26,
1560 28:
1561 if t>>16 != 0 {
1562 goto overflow
1563 }
1564
1565 default:
1566 if int64(int16(t)) != t {
1567 goto overflow
1568 }
1569 }
1570 }
1571
1572 return int64(int16(t))
1573
1574 case sym.RV_POWER_HA:
1575 t += 0x8000
1576 fallthrough
1577
1578
1579 case sym.RV_POWER_HI:
1580 t >>= 16
1581
1582 if rv&sym.RV_CHECK_OVERFLOW != 0 {
1583
1584
1585 var o1 uint32
1586 if target.IsBigEndian() {
1587 o1 = binary.BigEndian.Uint32(p[r.Off()-2:])
1588 } else {
1589 o1 = binary.LittleEndian.Uint32(p[r.Off():])
1590 }
1591 switch o1 >> 26 {
1592 case 25,
1593 27,
1594 29:
1595 if t>>16 != 0 {
1596 goto overflow
1597 }
1598
1599 default:
1600 if int64(int16(t)) != t {
1601 goto overflow
1602 }
1603 }
1604 }
1605
1606 return int64(int16(t))
1607
1608 case sym.RV_POWER_DS:
1609 var o1 uint32
1610 if target.IsBigEndian() {
1611 o1 = uint32(binary.BigEndian.Uint16(p[r.Off():]))
1612 } else {
1613 o1 = uint32(binary.LittleEndian.Uint16(p[r.Off():]))
1614 }
1615 if t&3 != 0 {
1616 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
1617 }
1618 if (rv&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
1619 goto overflow
1620 }
1621 return int64(o1)&0x3 | int64(int16(t))
1622 }
1623
1624 overflow:
1625 ldr.Errorf(s, "relocation for %s+%d is too big: %d", ldr.SymName(rs), r.Off(), t)
1626 return t
1627 }
1628
1629 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
1630 switch r.Type() {
1631 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:
1632 return ld.ExtrelocSimple(ldr, r), true
1633 case objabi.R_ADDRPOWER,
1634 objabi.R_ADDRPOWER_DS,
1635 objabi.R_ADDRPOWER_TOCREL,
1636 objabi.R_ADDRPOWER_TOCREL_DS,
1637 objabi.R_ADDRPOWER_GOT,
1638 objabi.R_ADDRPOWER_GOT_PCREL34,
1639 objabi.R_ADDRPOWER_PCREL,
1640 objabi.R_ADDRPOWER_D34,
1641 objabi.R_ADDRPOWER_PCREL34:
1642 return ld.ExtrelocViaOuterSym(ldr, r, s), true
1643 }
1644 return loader.ExtReloc{}, false
1645 }
1646
1647 func addpltsym(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym) {
1648 if ldr.SymPlt(s) >= 0 {
1649 return
1650 }
1651
1652 ld.Adddynsym(ldr, &ctxt.Target, &ctxt.ArchSyms, s)
1653
1654 if ctxt.IsELF {
1655 plt := ldr.MakeSymbolUpdater(ctxt.PLT)
1656 rela := ldr.MakeSymbolUpdater(ctxt.RelaPLT)
1657 if plt.Size() == 0 {
1658 panic("plt is not set up")
1659 }
1660
1661
1662 glink := ensureglinkresolver(ctxt, ldr)
1663
1664
1665
1666 rel, _ := glink.AddRel(objabi.R_CALLPOWER)
1667 rel.SetOff(int32(glink.Size()))
1668 rel.SetSiz(4)
1669 rel.SetSym(glink.Sym())
1670 glink.AddUint32(ctxt.Arch, 0x48000000)
1671
1672
1673
1674
1675
1676
1677
1678 ldr.SetPlt(s, int32(plt.Size()))
1679
1680 plt.Grow(plt.Size() + 8)
1681 plt.SetSize(plt.Size() + 8)
1682
1683 rela.AddAddrPlus(ctxt.Arch, plt.Sym(), int64(ldr.SymPlt(s)))
1684 rela.AddUint64(ctxt.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_PPC64_JMP_SLOT)))
1685 rela.AddUint64(ctxt.Arch, 0)
1686 } else {
1687 ctxt.Errorf(s, "addpltsym: unsupported binary format")
1688 }
1689 }
1690
1691
1692 func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilder {
1693 glink := ldr.CreateSymForUpdate(".glink", 0)
1694 if glink.Size() != 0 {
1695 return glink
1696 }
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707 glink.AddUint32(ctxt.Arch, OP_MFLR_R0)
1708 glink.AddUint32(ctxt.Arch, OP_BCL_NIA)
1709 glink.AddUint32(ctxt.Arch, 0x7d6802a6)
1710 glink.AddUint32(ctxt.Arch, OP_MTLR_R0)
1711
1712
1713
1714 glink.AddUint32(ctxt.Arch, 0x38000000)
1715 glink.AddUint32(ctxt.Arch, 0x7c006214)
1716 glink.AddUint32(ctxt.Arch, 0x7c0b0050)
1717 glink.AddUint32(ctxt.Arch, 0x7800f082)
1718
1719
1720
1721 glink.AddUint32(ctxt.Arch, 0xe98b0000)
1722 glink.AddUint32(ctxt.Arch, 0x7d6b6214)
1723
1724
1725
1726 glink.AddUint32(ctxt.Arch, 0xe98b0000)
1727 glink.AddUint32(ctxt.Arch, 0xe96b0008)
1728
1729
1730 glink.AddUint32(ctxt.Arch, OP_MTCTR_R12)
1731 glink.AddUint32(ctxt.Arch, OP_BCTR)
1732
1733
1734 r, _ := glink.AddRel(objabi.R_PCREL)
1735 r.SetSym(ctxt.PLT)
1736 r.SetSiz(8)
1737 r.SetOff(int32(glink.Size()))
1738 r.SetAdd(glink.Size())
1739 glink.AddUint64(ctxt.Arch, 0)
1740
1741
1742 res0m1b := glink.Size() - 8
1743 glink.SetUint32(ctxt.Arch, 16, 0x38000000|uint32(uint16(-res0m1b)))
1744 glink.SetUint32(ctxt.Arch, 32, 0xe98b0000|uint32(uint16(res0m1b-8)))
1745
1746
1747
1748
1749
1750
1751 du := ldr.MakeSymbolUpdater(ctxt.Dynamic)
1752 ld.Elfwritedynentsymplus(ctxt, du, elf.DT_PPC64_GLINK, glink.Sym(), glink.Size()-32)
1753
1754 return glink
1755 }
1756
View as plain text