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 "log"
43 "strings"
44 )
45
46 func genplt(ctxt *ld.Link, ldr *loader.Loader) {
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 var stubs []loader.Sym
96 for _, s := range ctxt.Textp {
97 relocs := ldr.Relocs(s)
98 for i := 0; i < relocs.Count(); i++ {
99 r := relocs.At(i)
100 if r.Type() != objabi.ElfRelocOffset+objabi.RelocType(elf.R_PPC64_REL24) || ldr.SymType(r.Sym()) != sym.SDYNIMPORT {
101 continue
102 }
103
104
105
106 addpltsym(ctxt, ldr, r.Sym())
107
108
109
110
111
112
113
114 n := fmt.Sprintf("%s.%s", ldr.SymName(s), ldr.SymName(r.Sym()))
115 stub := ldr.CreateSymForUpdate(n, ldr.SymVersion(s))
116 if stub.Size() == 0 {
117 stubs = append(stubs, stub.Sym())
118 gencallstub(ctxt, ldr, 1, stub, r.Sym())
119 }
120
121
122 r.SetSym(stub.Sym())
123
124
125 su := ldr.MakeSymbolUpdater(s)
126 su.MakeWritable()
127 p := su.Data()
128
129
130 var nop uint32
131 if len(p) >= int(r.Off()+8) {
132 nop = ctxt.Arch.ByteOrder.Uint32(p[r.Off()+4:])
133 }
134 if nop != 0x60000000 {
135 ldr.Errorf(s, "Symbol %s is missing toc restoration slot at offset %d", ldr.SymName(s), r.Off()+4)
136 }
137 const o1 = 0xe8410018
138 ctxt.Arch.ByteOrder.PutUint32(p[r.Off()+4:], o1)
139 }
140 }
141
142
143
144
145 ctxt.Textp = append(stubs, ctxt.Textp...)
146 }
147
148 func genaddmoduledata(ctxt *ld.Link, ldr *loader.Loader) {
149 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
150 if initfunc == nil {
151 return
152 }
153
154 o := func(op uint32) {
155 initfunc.AddUint32(ctxt.Arch, op)
156 }
157
158
159 toc := ctxt.DotTOC[0]
160 rel1, _ := initfunc.AddRel(objabi.R_ADDRPOWER_PCREL)
161 rel1.SetOff(0)
162 rel1.SetSiz(8)
163 rel1.SetSym(toc)
164 o(0x3c4c0000)
165
166 o(0x38420000)
167
168 o(0x7c0802a6)
169
170 o(0xf801ffe1)
171
172 var tgt loader.Sym
173 if s := ldr.Lookup("local.moduledata", 0); s != 0 {
174 tgt = s
175 } else if s := ldr.Lookup("local.pluginmoduledata", 0); s != 0 {
176 tgt = s
177 } else {
178 tgt = ldr.LookupOrCreateSym("runtime.firstmoduledata", 0)
179 }
180 rel2, _ := initfunc.AddRel(objabi.R_ADDRPOWER_GOT)
181 rel2.SetOff(int32(initfunc.Size()))
182 rel2.SetSiz(8)
183 rel2.SetSym(tgt)
184 o(0x3c620000)
185
186 o(0xe8630000)
187
188 rel3, _ := initfunc.AddRel(objabi.R_CALLPOWER)
189 rel3.SetOff(int32(initfunc.Size()))
190 rel3.SetSiz(4)
191 rel3.SetSym(addmoduledata)
192 o(0x48000001)
193
194 o(0x60000000)
195
196 o(0xe8010000)
197
198 o(0x7c0803a6)
199
200 o(0x38210020)
201
202 o(0x4e800020)
203 }
204
205 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
206 if ctxt.DynlinkingGo() {
207 genaddmoduledata(ctxt, ldr)
208 }
209
210 if ctxt.LinkMode == ld.LinkInternal {
211 genplt(ctxt, ldr)
212 }
213 }
214
215
216
217 func gencallstub(ctxt *ld.Link, ldr *loader.Loader, abicase int, stub *loader.SymbolBuilder, targ loader.Sym) {
218 if abicase != 1 {
219
220
221 log.Fatalf("gencallstub only implements case 1 calls")
222 }
223
224 plt := ctxt.PLT
225
226 stub.SetType(sym.STEXT)
227
228
229 stub.AddUint32(ctxt.Arch, 0xf8410018)
230
231
232 rel, ri1 := stub.AddRel(objabi.R_POWER_TOC)
233 rel.SetOff(int32(stub.Size()))
234 rel.SetSiz(2)
235 rel.SetAdd(int64(ldr.SymPlt(targ)))
236 rel.SetSym(plt)
237 if ctxt.Arch.ByteOrder == binary.BigEndian {
238 rel.SetOff(rel.Off() + int32(rel.Siz()))
239 }
240 ldr.SetRelocVariant(stub.Sym(), int(ri1), sym.RV_POWER_HA)
241 stub.AddUint32(ctxt.Arch, 0x3d820000)
242
243 rel2, ri2 := stub.AddRel(objabi.R_POWER_TOC)
244 rel2.SetOff(int32(stub.Size()))
245 rel2.SetSiz(2)
246 rel2.SetAdd(int64(ldr.SymPlt(targ)))
247 rel2.SetSym(plt)
248 if ctxt.Arch.ByteOrder == binary.BigEndian {
249 rel2.SetOff(rel2.Off() + int32(rel2.Siz()))
250 }
251 ldr.SetRelocVariant(stub.Sym(), int(ri2), sym.RV_POWER_LO)
252 stub.AddUint32(ctxt.Arch, 0xe98c0000)
253
254
255 stub.AddUint32(ctxt.Arch, 0x7d8903a6)
256 stub.AddUint32(ctxt.Arch, 0x4e800420)
257 }
258
259 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
260 if target.IsElf() {
261 return addelfdynrel(target, ldr, syms, s, r, rIdx)
262 } else if target.IsAIX() {
263 return ld.Xcoffadddynrel(target, ldr, syms, s, r, rIdx)
264 }
265 return false
266 }
267
268 func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
269 targ := r.Sym()
270 var targType sym.SymKind
271 if targ != 0 {
272 targType = ldr.SymType(targ)
273 }
274
275 switch r.Type() {
276 default:
277 if r.Type() >= objabi.ElfRelocOffset {
278 ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
279 return false
280 }
281
282
283 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24):
284 su := ldr.MakeSymbolUpdater(s)
285 su.SetRelocType(rIdx, objabi.R_CALLPOWER)
286
287
288
289
290
291
292 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymLocalentry(targ))*4)
293
294 if targType == sym.SDYNIMPORT {
295
296 ldr.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
297 }
298
299 return true
300
301 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32):
302 su := ldr.MakeSymbolUpdater(s)
303 su.SetRelocType(rIdx, objabi.R_PCREL)
304 su.SetRelocAdd(rIdx, r.Add()+4)
305
306 if targType == sym.SDYNIMPORT {
307 ldr.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
308 }
309
310 return true
311
312 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_ADDR64):
313 su := ldr.MakeSymbolUpdater(s)
314 su.SetRelocType(rIdx, objabi.R_ADDR)
315 if targType == sym.SDYNIMPORT {
316
317 ld.Adddynsym(ldr, target, syms, targ)
318
319 rela := ldr.MakeSymbolUpdater(syms.Rela)
320 rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
321 rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_PPC64_ADDR64)))
322 rela.AddUint64(target.Arch, uint64(r.Add()))
323 su.SetRelocType(rIdx, objabi.ElfRelocOffset)
324 } else if target.IsPIE() && target.IsInternal() {
325
326
327
328 break
329 }
330 return true
331
332 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16):
333 su := ldr.MakeSymbolUpdater(s)
334 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
335 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO|sym.RV_CHECK_OVERFLOW)
336 return true
337
338 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO):
339 su := ldr.MakeSymbolUpdater(s)
340 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
341 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
342 return true
343
344 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA):
345 su := ldr.MakeSymbolUpdater(s)
346 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
347 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
348 return true
349
350 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI):
351 su := ldr.MakeSymbolUpdater(s)
352 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
353 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
354 return true
355
356 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS):
357 su := ldr.MakeSymbolUpdater(s)
358 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
359 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS|sym.RV_CHECK_OVERFLOW)
360 return true
361
362 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS):
363 su := ldr.MakeSymbolUpdater(s)
364 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
365 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS)
366 return true
367
368 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO):
369 su := ldr.MakeSymbolUpdater(s)
370 su.SetRelocType(rIdx, objabi.R_PCREL)
371 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
372 su.SetRelocAdd(rIdx, r.Add()+2)
373 return true
374
375 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI):
376 su := ldr.MakeSymbolUpdater(s)
377 su.SetRelocType(rIdx, objabi.R_PCREL)
378 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
379 su.SetRelocAdd(rIdx, r.Add()+2)
380 return true
381
382 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA):
383 su := ldr.MakeSymbolUpdater(s)
384 su.SetRelocType(rIdx, objabi.R_PCREL)
385 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
386 su.SetRelocAdd(rIdx, r.Add()+2)
387 return true
388 }
389
390
391 relocs := ldr.Relocs(s)
392 r = relocs.At(rIdx)
393
394 switch r.Type() {
395 case objabi.R_ADDR:
396 if ldr.SymType(s) == sym.STEXT {
397 log.Fatalf("R_ADDR relocation in text symbol %s is unsupported\n", ldr.SymName(s))
398 }
399 if target.IsPIE() && target.IsInternal() {
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431 switch ldr.SymName(s) {
432 case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
433 return false
434 }
435 } else {
436
437
438
439
440
441
442 if ldr.SymType(s) != sym.SDATA && ldr.SymType(s) != sym.SRODATA {
443 break
444 }
445 }
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463 rela := ldr.MakeSymbolUpdater(syms.Rela)
464 rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
465 if r.Siz() == 8 {
466 rela.AddUint64(target.Arch, elf.R_INFO(0, uint32(elf.R_PPC64_RELATIVE)))
467 } else {
468 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
469 }
470 rela.AddAddrPlus(target.Arch, targ, int64(r.Add()))
471
472
473
474
475
476 return true
477 }
478
479 return false
480 }
481
482 func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool {
483 rs := r.Xsym
484
485 emitReloc := func(v uint16, off uint64) {
486 out.Write64(uint64(sectoff) + off)
487 out.Write32(uint32(ldr.SymDynid(rs)))
488 out.Write16(v)
489 }
490
491 var v uint16
492 switch r.Type {
493 default:
494 return false
495 case objabi.R_ADDR, objabi.R_DWARFSECREF:
496 v = ld.XCOFF_R_POS
497 if r.Size == 4 {
498 v |= 0x1F << 8
499 } else {
500 v |= 0x3F << 8
501 }
502 emitReloc(v, 0)
503 case objabi.R_ADDRPOWER_TOCREL:
504 case objabi.R_ADDRPOWER_TOCREL_DS:
505 emitReloc(ld.XCOFF_R_TOCU|(0x0F<<8), 2)
506 emitReloc(ld.XCOFF_R_TOCL|(0x0F<<8), 6)
507 case objabi.R_POWER_TLS_LE:
508
509 emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2)
510 case objabi.R_CALLPOWER:
511 if r.Size != 4 {
512 return false
513 }
514 emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
515 case objabi.R_XCOFFREF:
516 emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0)
517 }
518 return true
519
520 }
521
522 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
523
524 rt := r.Type
525 if rt == objabi.R_ADDR || rt == objabi.R_POWER_TLS || rt == objabi.R_CALLPOWER {
526 } else {
527 if ctxt.Arch.ByteOrder == binary.BigEndian {
528 sectoff += 2
529 }
530 }
531 out.Write64(uint64(sectoff))
532
533 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
534 switch rt {
535 default:
536 return false
537 case objabi.R_ADDR, objabi.R_DWARFSECREF:
538 switch r.Size {
539 case 4:
540 out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32)
541 case 8:
542 out.Write64(uint64(elf.R_PPC64_ADDR64) | uint64(elfsym)<<32)
543 default:
544 return false
545 }
546 case objabi.R_POWER_TLS:
547 out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32)
548 case objabi.R_POWER_TLS_LE:
549 out.Write64(uint64(elf.R_PPC64_TPREL16_HA) | uint64(elfsym)<<32)
550 out.Write64(uint64(r.Xadd))
551 out.Write64(uint64(sectoff + 4))
552 out.Write64(uint64(elf.R_PPC64_TPREL16_LO) | uint64(elfsym)<<32)
553 case objabi.R_POWER_TLS_IE:
554 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32)
555 out.Write64(uint64(r.Xadd))
556 out.Write64(uint64(sectoff + 4))
557 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_LO_DS) | uint64(elfsym)<<32)
558 case objabi.R_ADDRPOWER:
559 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
560 out.Write64(uint64(r.Xadd))
561 out.Write64(uint64(sectoff + 4))
562 out.Write64(uint64(elf.R_PPC64_ADDR16_LO) | uint64(elfsym)<<32)
563 case objabi.R_ADDRPOWER_DS:
564 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
565 out.Write64(uint64(r.Xadd))
566 out.Write64(uint64(sectoff + 4))
567 out.Write64(uint64(elf.R_PPC64_ADDR16_LO_DS) | uint64(elfsym)<<32)
568 case objabi.R_ADDRPOWER_GOT:
569 out.Write64(uint64(elf.R_PPC64_GOT16_HA) | uint64(elfsym)<<32)
570 out.Write64(uint64(r.Xadd))
571 out.Write64(uint64(sectoff + 4))
572 out.Write64(uint64(elf.R_PPC64_GOT16_LO_DS) | uint64(elfsym)<<32)
573 case objabi.R_ADDRPOWER_PCREL:
574 out.Write64(uint64(elf.R_PPC64_REL16_HA) | uint64(elfsym)<<32)
575 out.Write64(uint64(r.Xadd))
576 out.Write64(uint64(sectoff + 4))
577 out.Write64(uint64(elf.R_PPC64_REL16_LO) | uint64(elfsym)<<32)
578 r.Xadd += 4
579 case objabi.R_ADDRPOWER_TOCREL:
580 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
581 out.Write64(uint64(r.Xadd))
582 out.Write64(uint64(sectoff + 4))
583 out.Write64(uint64(elf.R_PPC64_TOC16_LO) | uint64(elfsym)<<32)
584 case objabi.R_ADDRPOWER_TOCREL_DS:
585 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
586 out.Write64(uint64(r.Xadd))
587 out.Write64(uint64(sectoff + 4))
588 out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32)
589 case objabi.R_CALLPOWER:
590 if r.Size != 4 {
591 return false
592 }
593 out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32)
594
595 }
596 out.Write64(uint64(r.Xadd))
597
598 return true
599 }
600
601 func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
602 if plt.Size() == 0 {
603
604
605
606
607 plt.SetSize(16)
608 }
609 }
610
611 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
612 return false
613 }
614
615
616 func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 {
617 v := ldr.SymVersion(s)
618 if out := ldr.OuterSym(s); out != 0 {
619 v = ldr.SymVersion(out)
620 }
621
622 toc := syms.DotTOC[v]
623 if toc == 0 {
624 ldr.Errorf(s, "TOC-relative relocation in object without .TOC.")
625 return 0
626 }
627
628 return ldr.SymValue(toc)
629 }
630
631
632 func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
633 rs := r.Sym()
634 var o1, o2 uint32
635 var t int64
636 useAddi := false
637
638 if target.IsBigEndian() {
639 o1 = uint32(val >> 32)
640 o2 = uint32(val)
641 } else {
642 o1 = uint32(val)
643 o2 = uint32(val >> 32)
644 }
645
646
647
648
649 if target.IsAIX() {
650 if !strings.HasPrefix(ldr.SymName(rs), "TOC.") {
651 ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
652 }
653 relocs := ldr.Relocs(rs)
654 tarSym := relocs.At(0).Sym()
655
656 if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata {
657 t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC)
658
659 o2 = (o2 & 0x03FF0000) | 0xE<<26
660 useAddi = true
661 } else {
662 t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC)
663 }
664 } else {
665 t = ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s)
666 }
667
668 if t != int64(int32(t)) {
669 ldr.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", ldr.SymName(s), rs, t)
670 }
671
672 if t&0x8000 != 0 {
673 t += 0x10000
674 }
675
676 o1 |= uint32((t >> 16) & 0xFFFF)
677
678 switch r.Type() {
679 case objabi.R_ADDRPOWER_TOCREL_DS:
680 if useAddi {
681 o2 |= uint32(t) & 0xFFFF
682 } else {
683 if t&3 != 0 {
684 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
685 }
686 o2 |= uint32(t) & 0xFFFC
687 }
688 case objabi.R_ADDRPOWER_TOCREL:
689 o2 |= uint32(t) & 0xffff
690 default:
691 return -1
692 }
693
694 if target.IsBigEndian() {
695 return int64(o1)<<32 | int64(o2)
696 }
697 return int64(o2)<<32 | int64(o1)
698 }
699
700
701
702 func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
703 rs := r.Sym()
704 if target.IsAIX() {
705 ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
706 }
707 var o1, o2 uint32
708 if target.IsBigEndian() {
709 o1 = uint32(val >> 32)
710 o2 = uint32(val)
711 } else {
712 o1 = uint32(val)
713 o2 = uint32(val >> 32)
714 }
715
716
717
718
719
720
721
722
723 t := ldr.SymAddr(rs) + r.Add()
724 if t < 0 || t >= 1<<31 {
725 ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs))
726 }
727 if t&0x8000 != 0 {
728 t += 0x10000
729 }
730
731 switch r.Type() {
732 case objabi.R_ADDRPOWER:
733 o1 |= (uint32(t) >> 16) & 0xffff
734 o2 |= uint32(t) & 0xffff
735 case objabi.R_ADDRPOWER_DS:
736 o1 |= (uint32(t) >> 16) & 0xffff
737 if t&3 != 0 {
738 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
739 }
740 o2 |= uint32(t) & 0xfffc
741 default:
742 return -1
743 }
744
745 if target.IsBigEndian() {
746 return int64(o1)<<32 | int64(o2)
747 }
748 return int64(o2)<<32 | int64(o1)
749 }
750
751
752 func r2Valid(ctxt *ld.Link) bool {
753 switch ctxt.BuildMode {
754 case ld.BuildModeCArchive, ld.BuildModeCShared, ld.BuildModePIE, ld.BuildModeShared, ld.BuildModePlugin:
755 return true
756 }
757
758 return ctxt.IsSharedGoLink()
759 }
760
761
762 func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
763
764
765
766
767
768 if ctxt.IsExternal() && r2Valid(ctxt) {
769
770 return
771 }
772
773 relocs := ldr.Relocs(s)
774 r := relocs.At(ri)
775 var t int64
776
777
778
779 if ldr.SymValue(rs) != 0 {
780 t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
781 }
782 switch r.Type() {
783 case objabi.R_CALLPOWER:
784
785
786
787 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)) {
788 var tramp loader.Sym
789 for i := 0; ; i++ {
790
791
792
793
794
795 oName := ldr.SymName(rs)
796 name := oName
797 if r.Add() == 0 {
798 name += fmt.Sprintf("-tramp%d", i)
799 } else {
800 name += fmt.Sprintf("%+x-tramp%d", r.Add(), i)
801 }
802
803
804
805 tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
806 if oName == "runtime.deferreturn" {
807 ldr.SetIsDeferReturnTramp(tramp, true)
808 }
809 if ldr.SymValue(tramp) == 0 {
810 break
811 }
812
813 t = ldr.SymValue(tramp) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
814
815
816
817 if (ctxt.IsInternal() && int64(int32(t<<6)>>6) == t) || (ctxt.IsExternal() && ldr.SymSect(s) == ldr.SymSect(tramp)) {
818 break
819 }
820 }
821 if ldr.SymType(tramp) == 0 {
822 if r2Valid(ctxt) {
823
824 ctxt.Errorf(s, "unexpected trampoline for shared or dynamic linking")
825 } else {
826 trampb := ldr.MakeSymbolUpdater(tramp)
827 ctxt.AddTramp(trampb)
828 gentramp(ctxt, ldr, trampb, rs, r.Add())
829 }
830 }
831 sb := ldr.MakeSymbolUpdater(s)
832 relocs := sb.Relocs()
833 r := relocs.At(ri)
834 r.SetSym(tramp)
835 r.SetAdd(0)
836 }
837 default:
838 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
839 }
840 }
841
842 func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
843 tramp.SetSize(16)
844 P := make([]byte, tramp.Size())
845 t := ldr.SymValue(target) + offset
846 var o1, o2 uint32
847
848 if ctxt.IsAIX() {
849
850
851
852
853
854 o1 = uint32(0x3fe20000)
855 o2 = uint32(0xebff0000)
856
857 toctramp := ldr.CreateSymForUpdate("TOC."+ldr.SymName(tramp.Sym()), 0)
858 toctramp.SetType(sym.SXCOFFTOC)
859 toctramp.AddAddrPlus(ctxt.Arch, target, offset)
860
861 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_TOCREL_DS)
862 r.SetOff(0)
863 r.SetSiz(8)
864 r.SetSym(toctramp.Sym())
865 } else {
866
867
868
869 o1 = uint32(0x3fe00000)
870 o2 = uint32(0x3bff0000)
871
872
873
874 if ctxt.IsExternal() || ldr.SymValue(target) == 0 {
875 r, _ := tramp.AddRel(objabi.R_ADDRPOWER)
876 r.SetOff(0)
877 r.SetSiz(8)
878 r.SetSym(target)
879 r.SetAdd(offset)
880 } else {
881
882
883 val := uint32((t & 0xffff0000) >> 16)
884 if t&0x8000 != 0 {
885 val += 1
886 }
887 o1 |= val
888 o2 |= uint32(t & 0xffff)
889 }
890 }
891
892 o3 := uint32(0x7fe903a6)
893 o4 := uint32(0x4e800420)
894 ctxt.Arch.ByteOrder.PutUint32(P, o1)
895 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
896 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
897 ctxt.Arch.ByteOrder.PutUint32(P[12:], o4)
898 tramp.SetData(P)
899 }
900
901 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) {
902 rs := r.Sym()
903 if target.IsExternal() {
904
905
906 switch rt := r.Type(); rt {
907 default:
908 if !target.IsAIX() {
909 return val, nExtReloc, false
910 }
911 case objabi.R_POWER_TLS:
912 nExtReloc = 1
913 return val, nExtReloc, true
914 case objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
915 if target.IsAIX() && rt == objabi.R_POWER_TLS_LE {
916
917
918
919 const expectedOpcodes = 0x3C00000038000000
920 const expectedOpmasks = 0xFC000000FC000000
921 if uint64(val)&expectedOpmasks != expectedOpcodes {
922 ldr.Errorf(s, "relocation for %s+%d is not an addis/addi pair: %16x", ldr.SymName(rs), r.Off(), uint64(val))
923 }
924 nval := (int64(uint32(0x380d0000)) | val&0x03e00000) << 32
925 nval |= int64(0x60000000)
926 val = nval
927 nExtReloc = 1
928 } else {
929 nExtReloc = 2
930 }
931 return val, nExtReloc, true
932 case objabi.R_ADDRPOWER,
933 objabi.R_ADDRPOWER_DS,
934 objabi.R_ADDRPOWER_TOCREL,
935 objabi.R_ADDRPOWER_TOCREL_DS,
936 objabi.R_ADDRPOWER_GOT,
937 objabi.R_ADDRPOWER_PCREL:
938 nExtReloc = 2
939 if !target.IsAIX() {
940 return val, nExtReloc, true
941 }
942 case objabi.R_CALLPOWER:
943 nExtReloc = 1
944 if !target.IsAIX() {
945 return val, nExtReloc, true
946 }
947 }
948 }
949
950 switch r.Type() {
951 case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
952 return archreloctoc(ldr, target, syms, r, s, val), nExtReloc, true
953 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
954 return archrelocaddr(ldr, target, syms, r, s, val), nExtReloc, true
955 case objabi.R_CALLPOWER:
956
957
958 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
959
960 tgtName := ldr.SymName(rs)
961
962
963
964
965 if !ldr.IsExternal(rs) && ldr.AttrShared(rs) && tgtName != "runtime.duffzero" && tgtName != "runtime.duffcopy" {
966
967 if r.Add() == 0 && ldr.SymType(rs) == sym.STEXT {
968 t += 8
969 }
970 }
971
972 if t&3 != 0 {
973 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
974 }
975
976
977 if int64(int32(t<<6)>>6) != t {
978 ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
979 }
980 return val | int64(uint32(t)&^0xfc000003), nExtReloc, true
981 case objabi.R_POWER_TOC:
982 return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true
983
984 case objabi.R_ADDRPOWER_PCREL:
985 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
986 ha := uint16(((t + 0x8000) >> 16) & 0xFFFF)
987 l := uint16(t)
988 if target.IsBigEndian() {
989 val |= int64(l)
990 val |= int64(ha) << 32
991 } else {
992 val |= int64(ha)
993 val |= int64(l) << 32
994 }
995 return val, nExtReloc, true
996
997 case objabi.R_POWER_TLS:
998 const OP_ADD = 31<<26 | 266<<1
999 const MASK_OP_ADD = 0x3F<<26 | 0x1FF<<1
1000 if val&MASK_OP_ADD != OP_ADD {
1001 ldr.Errorf(s, "R_POWER_TLS reloc only supports XO form ADD, not %08X", val)
1002 }
1003
1004 if (val>>11)&0x1F != 13 {
1005
1006 ldr.Errorf(s, "R_POWER_TLS reloc requires R13 in RB (%08X).", uint32(val))
1007 }
1008 return val, nExtReloc, true
1009
1010 case objabi.R_POWER_TLS_IE:
1011
1012 if !(target.IsPIE() && target.IsElf()) {
1013 log.Fatalf("cannot handle R_POWER_TLS_IE (sym %s) when linking non-PIE, non-ELF binaries internally", ldr.SymName(s))
1014 }
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024 const OP_ADDI = 14 << 26
1025 const OP_MASK = 0x3F << 26
1026 const OP_RA_MASK = 0x1F << 16
1027 uval := uint64(val)
1028
1029 if target.IsBigEndian() {
1030 uval = uval &^ (OP_RA_MASK << 32)
1031 uval = (uval &^ OP_MASK) | OP_ADDI
1032 } else {
1033 uval = uval &^ (OP_RA_MASK)
1034 uval = (uval &^ (OP_MASK << 32)) | (OP_ADDI << 32)
1035 }
1036 val = int64(uval)
1037
1038 fallthrough
1039
1040 case objabi.R_POWER_TLS_LE:
1041
1042
1043
1044
1045 v := ldr.SymValue(rs) - 0x7000
1046 if target.IsAIX() {
1047
1048
1049 v -= 0x800
1050 }
1051
1052 var o1, o2 uint32
1053 if int64(int32(v)) != v {
1054 ldr.Errorf(s, "TLS offset out of range %d", v)
1055 }
1056 if target.IsBigEndian() {
1057 o1 = uint32(val >> 32)
1058 o2 = uint32(val)
1059 } else {
1060 o1 = uint32(val)
1061 o2 = uint32(val >> 32)
1062 }
1063
1064 o1 |= uint32(((v + 0x8000) >> 16) & 0xFFFF)
1065 o2 |= uint32(v & 0xFFFF)
1066
1067 if target.IsBigEndian() {
1068 return int64(o1)<<32 | int64(o2), nExtReloc, true
1069 }
1070 return int64(o2)<<32 | int64(o1), nExtReloc, true
1071 }
1072
1073 return val, nExtReloc, false
1074 }
1075
1076 func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc, rv sym.RelocVariant, s loader.Sym, t int64, p []byte) (relocatedOffset int64) {
1077 rs := r.Sym()
1078 switch rv & sym.RV_TYPE_MASK {
1079 default:
1080 ldr.Errorf(s, "unexpected relocation variant %d", rv)
1081 fallthrough
1082
1083 case sym.RV_NONE:
1084 return t
1085
1086 case sym.RV_POWER_LO:
1087 if rv&sym.RV_CHECK_OVERFLOW != 0 {
1088
1089
1090 var o1 uint32
1091 if target.IsBigEndian() {
1092 o1 = binary.BigEndian.Uint32(p[r.Off()-2:])
1093
1094 } else {
1095 o1 = binary.LittleEndian.Uint32(p[r.Off():])
1096 }
1097 switch o1 >> 26 {
1098 case 24,
1099 26,
1100 28:
1101 if t>>16 != 0 {
1102 goto overflow
1103 }
1104
1105 default:
1106 if int64(int16(t)) != t {
1107 goto overflow
1108 }
1109 }
1110 }
1111
1112 return int64(int16(t))
1113
1114 case sym.RV_POWER_HA:
1115 t += 0x8000
1116 fallthrough
1117
1118
1119 case sym.RV_POWER_HI:
1120 t >>= 16
1121
1122 if rv&sym.RV_CHECK_OVERFLOW != 0 {
1123
1124
1125 var o1 uint32
1126 if target.IsBigEndian() {
1127 o1 = binary.BigEndian.Uint32(p[r.Off()-2:])
1128 } else {
1129 o1 = binary.LittleEndian.Uint32(p[r.Off():])
1130 }
1131 switch o1 >> 26 {
1132 case 25,
1133 27,
1134 29:
1135 if t>>16 != 0 {
1136 goto overflow
1137 }
1138
1139 default:
1140 if int64(int16(t)) != t {
1141 goto overflow
1142 }
1143 }
1144 }
1145
1146 return int64(int16(t))
1147
1148 case sym.RV_POWER_DS:
1149 var o1 uint32
1150 if target.IsBigEndian() {
1151 o1 = uint32(binary.BigEndian.Uint16(p[r.Off():]))
1152 } else {
1153 o1 = uint32(binary.LittleEndian.Uint16(p[r.Off():]))
1154 }
1155 if t&3 != 0 {
1156 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
1157 }
1158 if (rv&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
1159 goto overflow
1160 }
1161 return int64(o1)&0x3 | int64(int16(t))
1162 }
1163
1164 overflow:
1165 ldr.Errorf(s, "relocation for %s+%d is too big: %d", ldr.SymName(rs), r.Off(), t)
1166 return t
1167 }
1168
1169 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
1170 switch r.Type() {
1171 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE, objabi.R_CALLPOWER:
1172 return ld.ExtrelocSimple(ldr, r), true
1173 case objabi.R_ADDRPOWER,
1174 objabi.R_ADDRPOWER_DS,
1175 objabi.R_ADDRPOWER_TOCREL,
1176 objabi.R_ADDRPOWER_TOCREL_DS,
1177 objabi.R_ADDRPOWER_GOT,
1178 objabi.R_ADDRPOWER_PCREL:
1179 return ld.ExtrelocViaOuterSym(ldr, r, s), true
1180 }
1181 return loader.ExtReloc{}, false
1182 }
1183
1184 func addpltsym(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym) {
1185 if ldr.SymPlt(s) >= 0 {
1186 return
1187 }
1188
1189 ld.Adddynsym(ldr, &ctxt.Target, &ctxt.ArchSyms, s)
1190
1191 if ctxt.IsELF {
1192 plt := ldr.MakeSymbolUpdater(ctxt.PLT)
1193 rela := ldr.MakeSymbolUpdater(ctxt.RelaPLT)
1194 if plt.Size() == 0 {
1195 panic("plt is not set up")
1196 }
1197
1198
1199 glink := ensureglinkresolver(ctxt, ldr)
1200
1201
1202
1203 rel, _ := glink.AddRel(objabi.R_CALLPOWER)
1204 rel.SetOff(int32(glink.Size()))
1205 rel.SetSiz(4)
1206 rel.SetSym(glink.Sym())
1207 glink.AddUint32(ctxt.Arch, 0x48000000)
1208
1209
1210
1211
1212
1213
1214
1215 ldr.SetPlt(s, int32(plt.Size()))
1216
1217 plt.Grow(plt.Size() + 8)
1218 plt.SetSize(plt.Size() + 8)
1219
1220 rela.AddAddrPlus(ctxt.Arch, plt.Sym(), int64(ldr.SymPlt(s)))
1221 rela.AddUint64(ctxt.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_PPC64_JMP_SLOT)))
1222 rela.AddUint64(ctxt.Arch, 0)
1223 } else {
1224 ctxt.Errorf(s, "addpltsym: unsupported binary format")
1225 }
1226 }
1227
1228
1229 func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilder {
1230 glink := ldr.CreateSymForUpdate(".glink", 0)
1231 if glink.Size() != 0 {
1232 return glink
1233 }
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244 glink.AddUint32(ctxt.Arch, 0x7c0802a6)
1245 glink.AddUint32(ctxt.Arch, 0x429f0005)
1246 glink.AddUint32(ctxt.Arch, 0x7d6802a6)
1247 glink.AddUint32(ctxt.Arch, 0x7c0803a6)
1248
1249
1250
1251 glink.AddUint32(ctxt.Arch, 0x38000000)
1252 glink.AddUint32(ctxt.Arch, 0x7c006214)
1253 glink.AddUint32(ctxt.Arch, 0x7c0b0050)
1254 glink.AddUint32(ctxt.Arch, 0x7800f082)
1255
1256
1257
1258 glink.AddUint32(ctxt.Arch, 0xe98b0000)
1259 glink.AddUint32(ctxt.Arch, 0x7d6b6214)
1260
1261
1262
1263 glink.AddUint32(ctxt.Arch, 0xe98b0000)
1264 glink.AddUint32(ctxt.Arch, 0xe96b0008)
1265
1266
1267 glink.AddUint32(ctxt.Arch, 0x7d8903a6)
1268 glink.AddUint32(ctxt.Arch, 0x4e800420)
1269
1270
1271 r, _ := glink.AddRel(objabi.R_PCREL)
1272 r.SetSym(ctxt.PLT)
1273 r.SetSiz(8)
1274 r.SetOff(int32(glink.Size()))
1275 r.SetAdd(glink.Size())
1276 glink.AddUint64(ctxt.Arch, 0)
1277
1278
1279 res0m1b := glink.Size() - 8
1280 glink.SetUint32(ctxt.Arch, 16, 0x38000000|uint32(uint16(-res0m1b)))
1281 glink.SetUint32(ctxt.Arch, 32, 0xe98b0000|uint32(uint16(res0m1b-8)))
1282
1283
1284
1285
1286
1287
1288 du := ldr.MakeSymbolUpdater(ctxt.Dynamic)
1289 ld.Elfwritedynentsymplus(ctxt, du, elf.DT_PPC64_GLINK, glink.Sym(), glink.Size()-32)
1290
1291 return glink
1292 }
1293
View as plain text