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