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 if ldr.AttrReadOnly(s) {
126 panic("can't write to read-only sym data")
127 }
128
129
130
131 sp := ldr.Data(s)
132 const o1 = 0xe8410018
133 ctxt.Arch.ByteOrder.PutUint32(sp[r.Off()+4:], o1)
134 }
135 }
136
137
138
139
140 ctxt.Textp = append(stubs, ctxt.Textp...)
141 }
142
143 func genaddmoduledata(ctxt *ld.Link, ldr *loader.Loader) {
144 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
145 if initfunc == nil {
146 return
147 }
148
149 o := func(op uint32) {
150 initfunc.AddUint32(ctxt.Arch, op)
151 }
152
153
154 toc := ctxt.DotTOC[0]
155 rel1, _ := initfunc.AddRel(objabi.R_ADDRPOWER_PCREL)
156 rel1.SetOff(0)
157 rel1.SetSiz(8)
158 rel1.SetSym(toc)
159 o(0x3c4c0000)
160
161 o(0x38420000)
162
163 o(0x7c0802a6)
164
165 o(0xf801ffe1)
166
167 var tgt loader.Sym
168 if s := ldr.Lookup("local.moduledata", 0); s != 0 {
169 tgt = s
170 } else if s := ldr.Lookup("local.pluginmoduledata", 0); s != 0 {
171 tgt = s
172 } else {
173 tgt = ldr.LookupOrCreateSym("runtime.firstmoduledata", 0)
174 }
175 rel2, _ := initfunc.AddRel(objabi.R_ADDRPOWER_GOT)
176 rel2.SetOff(int32(initfunc.Size()))
177 rel2.SetSiz(8)
178 rel2.SetSym(tgt)
179 o(0x3c620000)
180
181 o(0xe8630000)
182
183 rel3, _ := initfunc.AddRel(objabi.R_CALLPOWER)
184 rel3.SetOff(int32(initfunc.Size()))
185 rel3.SetSiz(4)
186 rel3.SetSym(addmoduledata)
187 o(0x48000001)
188
189 o(0x60000000)
190
191 o(0xe8010000)
192
193 o(0x7c0803a6)
194
195 o(0x38210020)
196
197 o(0x4e800020)
198 }
199
200 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
201 if ctxt.DynlinkingGo() {
202 genaddmoduledata(ctxt, ldr)
203 }
204
205 if ctxt.LinkMode == ld.LinkInternal {
206 genplt(ctxt, ldr)
207 }
208 }
209
210
211
212 func gencallstub(ctxt *ld.Link, ldr *loader.Loader, abicase int, stub *loader.SymbolBuilder, targ loader.Sym) {
213 if abicase != 1 {
214
215
216 log.Fatalf("gencallstub only implements case 1 calls")
217 }
218
219 plt := ctxt.PLT
220
221 stub.SetType(sym.STEXT)
222
223
224 stub.AddUint32(ctxt.Arch, 0xf8410018)
225
226
227 rel, ri1 := stub.AddRel(objabi.R_POWER_TOC)
228 rel.SetOff(int32(stub.Size()))
229 rel.SetSiz(2)
230 rel.SetAdd(int64(ldr.SymPlt(targ)))
231 rel.SetSym(plt)
232 if ctxt.Arch.ByteOrder == binary.BigEndian {
233 rel.SetOff(rel.Off() + int32(rel.Siz()))
234 }
235 ldr.SetRelocVariant(stub.Sym(), int(ri1), sym.RV_POWER_HA)
236 stub.AddUint32(ctxt.Arch, 0x3d820000)
237
238 rel2, ri2 := stub.AddRel(objabi.R_POWER_TOC)
239 rel2.SetOff(int32(stub.Size()))
240 rel2.SetSiz(2)
241 rel2.SetAdd(int64(ldr.SymPlt(targ)))
242 rel2.SetSym(plt)
243 if ctxt.Arch.ByteOrder == binary.BigEndian {
244 rel2.SetOff(rel2.Off() + int32(rel2.Siz()))
245 }
246 ldr.SetRelocVariant(stub.Sym(), int(ri2), sym.RV_POWER_LO)
247 stub.AddUint32(ctxt.Arch, 0xe98c0000)
248
249
250 stub.AddUint32(ctxt.Arch, 0x7d8903a6)
251 stub.AddUint32(ctxt.Arch, 0x4e800420)
252 }
253
254 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
255 if target.IsElf() {
256 return addelfdynrel(target, ldr, syms, s, r, rIdx)
257 } else if target.IsAIX() {
258 return ld.Xcoffadddynrel(target, ldr, syms, s, r, rIdx)
259 }
260 return false
261 }
262
263 func addelfdynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
264 targ := r.Sym()
265 var targType sym.SymKind
266 if targ != 0 {
267 targType = ldr.SymType(targ)
268 }
269
270 switch r.Type() {
271 default:
272 if r.Type() >= objabi.ElfRelocOffset {
273 ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
274 return false
275 }
276
277
278 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24):
279 su := ldr.MakeSymbolUpdater(s)
280 su.SetRelocType(rIdx, objabi.R_CALLPOWER)
281
282
283
284
285
286
287 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymLocalentry(targ))*4)
288
289 if targType == sym.SDYNIMPORT {
290
291 ldr.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
292 }
293
294 return true
295
296 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32):
297 su := ldr.MakeSymbolUpdater(s)
298 su.SetRelocType(rIdx, objabi.R_PCREL)
299 su.SetRelocAdd(rIdx, r.Add()+4)
300
301 if targType == sym.SDYNIMPORT {
302 ldr.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
303 }
304
305 return true
306
307 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_ADDR64):
308 su := ldr.MakeSymbolUpdater(s)
309 su.SetRelocType(rIdx, objabi.R_ADDR)
310 if targType == sym.SDYNIMPORT {
311
312 ld.Adddynsym(ldr, target, syms, targ)
313
314 rela := ldr.MakeSymbolUpdater(syms.Rela)
315 rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
316 rela.AddUint64(target.Arch, elf.R_INFO(uint32(ldr.SymDynid(targ)), uint32(elf.R_PPC64_ADDR64)))
317 rela.AddUint64(target.Arch, uint64(r.Add()))
318 su.SetRelocType(rIdx, objabi.ElfRelocOffset)
319 }
320 return true
321
322 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16):
323 su := ldr.MakeSymbolUpdater(s)
324 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
325 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO|sym.RV_CHECK_OVERFLOW)
326 return true
327
328 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO):
329 su := ldr.MakeSymbolUpdater(s)
330 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
331 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
332 return true
333
334 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA):
335 su := ldr.MakeSymbolUpdater(s)
336 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
337 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
338 return true
339
340 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI):
341 su := ldr.MakeSymbolUpdater(s)
342 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
343 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
344 return true
345
346 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS):
347 su := ldr.MakeSymbolUpdater(s)
348 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
349 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS|sym.RV_CHECK_OVERFLOW)
350 return true
351
352 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS):
353 su := ldr.MakeSymbolUpdater(s)
354 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
355 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS)
356 return true
357
358 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO):
359 su := ldr.MakeSymbolUpdater(s)
360 su.SetRelocType(rIdx, objabi.R_PCREL)
361 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
362 su.SetRelocAdd(rIdx, r.Add()+2)
363 return true
364
365 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI):
366 su := ldr.MakeSymbolUpdater(s)
367 su.SetRelocType(rIdx, objabi.R_PCREL)
368 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
369 su.SetRelocAdd(rIdx, r.Add()+2)
370 return true
371
372 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA):
373 su := ldr.MakeSymbolUpdater(s)
374 su.SetRelocType(rIdx, objabi.R_PCREL)
375 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
376 su.SetRelocAdd(rIdx, r.Add()+2)
377 return true
378 }
379
380
381 if targType != sym.SDYNIMPORT {
382 return true
383 }
384
385
386
387 return false
388 }
389
390 func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool {
391 rs := r.Xsym
392
393 emitReloc := func(v uint16, off uint64) {
394 out.Write64(uint64(sectoff) + off)
395 out.Write32(uint32(ldr.SymDynid(rs)))
396 out.Write16(v)
397 }
398
399 var v uint16
400 switch r.Type {
401 default:
402 return false
403 case objabi.R_ADDR, objabi.R_DWARFSECREF:
404 v = ld.XCOFF_R_POS
405 if r.Size == 4 {
406 v |= 0x1F << 8
407 } else {
408 v |= 0x3F << 8
409 }
410 emitReloc(v, 0)
411 case objabi.R_ADDRPOWER_TOCREL:
412 case objabi.R_ADDRPOWER_TOCREL_DS:
413 emitReloc(ld.XCOFF_R_TOCU|(0x0F<<8), 2)
414 emitReloc(ld.XCOFF_R_TOCL|(0x0F<<8), 6)
415 case objabi.R_POWER_TLS_LE:
416 emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2)
417 case objabi.R_CALLPOWER:
418 if r.Size != 4 {
419 return false
420 }
421 emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
422 case objabi.R_XCOFFREF:
423 emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0)
424 }
425 return true
426
427 }
428
429 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
430
431 rt := r.Type
432 if rt == objabi.R_ADDR || rt == objabi.R_POWER_TLS || rt == objabi.R_CALLPOWER {
433 } else {
434 if ctxt.Arch.ByteOrder == binary.BigEndian {
435 sectoff += 2
436 }
437 }
438 out.Write64(uint64(sectoff))
439
440 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
441 switch rt {
442 default:
443 return false
444 case objabi.R_ADDR, objabi.R_DWARFSECREF:
445 switch r.Size {
446 case 4:
447 out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32)
448 case 8:
449 out.Write64(uint64(elf.R_PPC64_ADDR64) | uint64(elfsym)<<32)
450 default:
451 return false
452 }
453 case objabi.R_POWER_TLS:
454 out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32)
455 case objabi.R_POWER_TLS_LE:
456 out.Write64(uint64(elf.R_PPC64_TPREL16) | uint64(elfsym)<<32)
457 case objabi.R_POWER_TLS_IE:
458 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32)
459 out.Write64(uint64(r.Xadd))
460 out.Write64(uint64(sectoff + 4))
461 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_LO_DS) | uint64(elfsym)<<32)
462 case objabi.R_ADDRPOWER:
463 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
464 out.Write64(uint64(r.Xadd))
465 out.Write64(uint64(sectoff + 4))
466 out.Write64(uint64(elf.R_PPC64_ADDR16_LO) | uint64(elfsym)<<32)
467 case objabi.R_ADDRPOWER_DS:
468 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
469 out.Write64(uint64(r.Xadd))
470 out.Write64(uint64(sectoff + 4))
471 out.Write64(uint64(elf.R_PPC64_ADDR16_LO_DS) | uint64(elfsym)<<32)
472 case objabi.R_ADDRPOWER_GOT:
473 out.Write64(uint64(elf.R_PPC64_GOT16_HA) | uint64(elfsym)<<32)
474 out.Write64(uint64(r.Xadd))
475 out.Write64(uint64(sectoff + 4))
476 out.Write64(uint64(elf.R_PPC64_GOT16_LO_DS) | uint64(elfsym)<<32)
477 case objabi.R_ADDRPOWER_PCREL:
478 out.Write64(uint64(elf.R_PPC64_REL16_HA) | uint64(elfsym)<<32)
479 out.Write64(uint64(r.Xadd))
480 out.Write64(uint64(sectoff + 4))
481 out.Write64(uint64(elf.R_PPC64_REL16_LO) | uint64(elfsym)<<32)
482 r.Xadd += 4
483 case objabi.R_ADDRPOWER_TOCREL:
484 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
485 out.Write64(uint64(r.Xadd))
486 out.Write64(uint64(sectoff + 4))
487 out.Write64(uint64(elf.R_PPC64_TOC16_LO) | uint64(elfsym)<<32)
488 case objabi.R_ADDRPOWER_TOCREL_DS:
489 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
490 out.Write64(uint64(r.Xadd))
491 out.Write64(uint64(sectoff + 4))
492 out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32)
493 case objabi.R_CALLPOWER:
494 if r.Size != 4 {
495 return false
496 }
497 out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32)
498
499 }
500 out.Write64(uint64(r.Xadd))
501
502 return true
503 }
504
505 func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
506 if plt.Size() == 0 {
507
508
509
510
511 plt.SetSize(16)
512 }
513 }
514
515 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
516 return false
517 }
518
519
520 func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 {
521 v := ldr.SymVersion(s)
522 if out := ldr.OuterSym(s); out != 0 {
523 v = ldr.SymVersion(out)
524 }
525
526 toc := syms.DotTOC[v]
527 if toc == 0 {
528 ldr.Errorf(s, "TOC-relative relocation in object without .TOC.")
529 return 0
530 }
531
532 return ldr.SymValue(toc)
533 }
534
535
536
537
538
539
540 func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
541 rs := ldr.ResolveABIAlias(r.Sym())
542 if target.IsLinux() {
543 ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
544 }
545 var o1, o2 uint32
546
547 o1 = uint32(val >> 32)
548 o2 = uint32(val)
549
550 if !strings.HasPrefix(ldr.SymName(rs), "TOC.") {
551 ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
552 }
553 var t int64
554 useAddi := false
555 relocs := ldr.Relocs(rs)
556 tarSym := ldr.ResolveABIAlias(relocs.At(0).Sym())
557
558 if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata {
559 t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC)
560
561 o2 = (o2 & 0x03FF0000) | 0xE<<26
562 useAddi = true
563 } else {
564 t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC)
565 }
566
567 if t != int64(int32(t)) {
568 ldr.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", ldr.SymName(s), rs, t)
569 }
570
571 if t&0x8000 != 0 {
572 t += 0x10000
573 }
574
575 o1 |= uint32((t >> 16) & 0xFFFF)
576
577 switch r.Type() {
578 case objabi.R_ADDRPOWER_TOCREL_DS:
579 if useAddi {
580 o2 |= uint32(t) & 0xFFFF
581 } else {
582 if t&3 != 0 {
583 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
584 }
585 o2 |= uint32(t) & 0xFFFC
586 }
587 default:
588 return -1
589 }
590
591 return int64(o1)<<32 | int64(o2)
592 }
593
594
595
596 func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
597 rs := ldr.ResolveABIAlias(r.Sym())
598 if target.IsAIX() {
599 ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
600 }
601 var o1, o2 uint32
602 if target.IsBigEndian() {
603 o1 = uint32(val >> 32)
604 o2 = uint32(val)
605 } else {
606 o1 = uint32(val)
607 o2 = uint32(val >> 32)
608 }
609
610
611
612
613
614
615
616
617 t := ldr.SymAddr(rs) + r.Add()
618 if t < 0 || t >= 1<<31 {
619 ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs))
620 }
621 if t&0x8000 != 0 {
622 t += 0x10000
623 }
624
625 switch r.Type() {
626 case objabi.R_ADDRPOWER:
627 o1 |= (uint32(t) >> 16) & 0xffff
628 o2 |= uint32(t) & 0xffff
629 case objabi.R_ADDRPOWER_DS:
630 o1 |= (uint32(t) >> 16) & 0xffff
631 if t&3 != 0 {
632 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
633 }
634 o2 |= uint32(t) & 0xfffc
635 default:
636 return -1
637 }
638
639 if target.IsBigEndian() {
640 return int64(o1)<<32 | int64(o2)
641 }
642 return int64(o2)<<32 | int64(o1)
643 }
644
645
646 func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
647
648
649
650
651
652 if ctxt.IsExternal() && (ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE) {
653
654 return
655 }
656
657 relocs := ldr.Relocs(s)
658 r := relocs.At(ri)
659 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
660 switch r.Type() {
661 case objabi.R_CALLPOWER:
662
663
664
665 if (ctxt.IsExternal() && ldr.SymSect(s) != ldr.SymSect(rs)) || (ctxt.IsInternal() && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && ldr.SymPkg(s) != ldr.SymPkg(rs)) {
666 var tramp loader.Sym
667 for i := 0; ; i++ {
668
669
670
671
672
673 oName := ldr.SymName(rs)
674 name := oName
675 if r.Add() == 0 {
676 name += fmt.Sprintf("-tramp%d", i)
677 } else {
678 name += fmt.Sprintf("%+x-tramp%d", r.Add(), i)
679 }
680
681
682
683 tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
684 if oName == "runtime.deferreturn" {
685 ldr.SetIsDeferReturnTramp(tramp, true)
686 }
687 if ldr.SymValue(tramp) == 0 {
688 break
689 }
690
691 t = ldr.SymValue(tramp) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
692
693
694
695 if (ctxt.IsInternal() && int64(int32(t<<6)>>6) == t) || (ctxt.IsExternal() && ldr.SymSect(s) == ldr.SymSect(tramp)) {
696 break
697 }
698 }
699 if ldr.SymType(tramp) == 0 {
700 if ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE {
701
702 ctxt.Errorf(s, "unexpected trampoline for shared or dynamic linking")
703 } else {
704 trampb := ldr.MakeSymbolUpdater(tramp)
705 ctxt.AddTramp(trampb)
706 gentramp(ctxt, ldr, trampb, rs, r.Add())
707 }
708 }
709 sb := ldr.MakeSymbolUpdater(s)
710 relocs := sb.Relocs()
711 r := relocs.At(ri)
712 r.SetSym(tramp)
713 r.SetAdd(0)
714 }
715 default:
716 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
717 }
718 }
719
720 func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
721 tramp.SetSize(16)
722 P := make([]byte, tramp.Size())
723 t := ldr.SymValue(target) + offset
724 var o1, o2 uint32
725
726 if ctxt.IsAIX() {
727
728
729
730
731
732 o1 = uint32(0x3fe20000)
733 o2 = uint32(0xebff0000)
734
735 toctramp := ldr.CreateSymForUpdate("TOC."+ldr.SymName(tramp.Sym()), 0)
736 toctramp.SetType(sym.SXCOFFTOC)
737 toctramp.AddAddrPlus(ctxt.Arch, target, offset)
738
739 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_TOCREL_DS)
740 r.SetOff(0)
741 r.SetSiz(8)
742 r.SetSym(toctramp.Sym())
743 } else {
744
745
746
747 o1 = uint32(0x3fe00000)
748 o2 = uint32(0x3bff0000)
749
750
751
752 if ctxt.IsExternal() {
753 r, _ := tramp.AddRel(objabi.R_ADDRPOWER)
754 r.SetOff(0)
755 r.SetSiz(8)
756 r.SetSym(target)
757 r.SetAdd(offset)
758 } else {
759
760
761 val := uint32((t & 0xffff0000) >> 16)
762 if t&0x8000 != 0 {
763 val += 1
764 }
765 o1 |= val
766 o2 |= uint32(t & 0xffff)
767 }
768 }
769
770 o3 := uint32(0x7fe903a6)
771 o4 := uint32(0x4e800420)
772 ctxt.Arch.ByteOrder.PutUint32(P, o1)
773 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
774 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
775 ctxt.Arch.ByteOrder.PutUint32(P[12:], o4)
776 tramp.SetData(P)
777 }
778
779 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) {
780 rs := ldr.ResolveABIAlias(r.Sym())
781 if target.IsExternal() {
782
783
784 switch rt := r.Type(); rt {
785 default:
786 if !target.IsAIX() {
787 return val, nExtReloc, false
788 }
789 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
790
791 nExtReloc = 1
792 if rt == objabi.R_POWER_TLS_IE {
793 nExtReloc = 2
794 }
795 return val, nExtReloc, true
796 case objabi.R_ADDRPOWER,
797 objabi.R_ADDRPOWER_DS,
798 objabi.R_ADDRPOWER_TOCREL,
799 objabi.R_ADDRPOWER_TOCREL_DS,
800 objabi.R_ADDRPOWER_GOT,
801 objabi.R_ADDRPOWER_PCREL:
802 nExtReloc = 2
803 if !target.IsAIX() {
804 return val, nExtReloc, true
805 }
806 case objabi.R_CALLPOWER:
807 nExtReloc = 1
808 if !target.IsAIX() {
809 return val, nExtReloc, true
810 }
811 }
812 }
813
814 switch r.Type() {
815 case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
816 return archreloctoc(ldr, target, syms, r, s, val), nExtReloc, true
817 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
818 return archrelocaddr(ldr, target, syms, r, s, val), nExtReloc, true
819 case objabi.R_CALLPOWER:
820
821
822 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
823
824 if t&3 != 0 {
825 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
826 }
827
828
829 if int64(int32(t<<6)>>6) != t {
830 ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
831 }
832 return val | int64(uint32(t)&^0xfc000003), nExtReloc, true
833 case objabi.R_POWER_TOC:
834 return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true
835
836 case objabi.R_POWER_TLS_LE:
837
838
839
840
841 v := ldr.SymValue(rs) - 0x7000
842 if target.IsAIX() {
843
844
845 v -= 0x800
846 }
847 if int64(int16(v)) != v {
848 ldr.Errorf(s, "TLS offset out of range %d", v)
849 }
850 return (val &^ 0xffff) | (v & 0xffff), nExtReloc, true
851 }
852
853 return val, nExtReloc, false
854 }
855
856 func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc, rv sym.RelocVariant, s loader.Sym, t int64) (relocatedOffset int64) {
857 rs := ldr.ResolveABIAlias(r.Sym())
858 switch rv & sym.RV_TYPE_MASK {
859 default:
860 ldr.Errorf(s, "unexpected relocation variant %d", rv)
861 fallthrough
862
863 case sym.RV_NONE:
864 return t
865
866 case sym.RV_POWER_LO:
867 if rv&sym.RV_CHECK_OVERFLOW != 0 {
868
869
870 var o1 uint32
871 if target.IsBigEndian() {
872 o1 = binary.BigEndian.Uint32(ldr.Data(s)[r.Off()-2:])
873 } else {
874 o1 = binary.LittleEndian.Uint32(ldr.Data(s)[r.Off():])
875 }
876 switch o1 >> 26 {
877 case 24,
878 26,
879 28:
880 if t>>16 != 0 {
881 goto overflow
882 }
883
884 default:
885 if int64(int16(t)) != t {
886 goto overflow
887 }
888 }
889 }
890
891 return int64(int16(t))
892
893 case sym.RV_POWER_HA:
894 t += 0x8000
895 fallthrough
896
897
898 case sym.RV_POWER_HI:
899 t >>= 16
900
901 if rv&sym.RV_CHECK_OVERFLOW != 0 {
902
903
904 var o1 uint32
905 if target.IsBigEndian() {
906 o1 = binary.BigEndian.Uint32(ldr.Data(s)[r.Off()-2:])
907 } else {
908 o1 = binary.LittleEndian.Uint32(ldr.Data(s)[r.Off():])
909 }
910 switch o1 >> 26 {
911 case 25,
912 27,
913 29:
914 if t>>16 != 0 {
915 goto overflow
916 }
917
918 default:
919 if int64(int16(t)) != t {
920 goto overflow
921 }
922 }
923 }
924
925 return int64(int16(t))
926
927 case sym.RV_POWER_DS:
928 var o1 uint32
929 if target.IsBigEndian() {
930 o1 = uint32(binary.BigEndian.Uint16(ldr.Data(s)[r.Off():]))
931 } else {
932 o1 = uint32(binary.LittleEndian.Uint16(ldr.Data(s)[r.Off():]))
933 }
934 if t&3 != 0 {
935 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
936 }
937 if (rv&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
938 goto overflow
939 }
940 return int64(o1)&0x3 | int64(int16(t))
941 }
942
943 overflow:
944 ldr.Errorf(s, "relocation for %s+%d is too big: %d", ldr.SymName(rs), r.Off(), t)
945 return t
946 }
947
948 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
949 switch r.Type() {
950 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE, objabi.R_CALLPOWER:
951 return ld.ExtrelocSimple(ldr, r), true
952 case objabi.R_ADDRPOWER,
953 objabi.R_ADDRPOWER_DS,
954 objabi.R_ADDRPOWER_TOCREL,
955 objabi.R_ADDRPOWER_TOCREL_DS,
956 objabi.R_ADDRPOWER_GOT,
957 objabi.R_ADDRPOWER_PCREL:
958 return ld.ExtrelocViaOuterSym(ldr, r, s), true
959 }
960 return loader.ExtReloc{}, false
961 }
962
963 func addpltsym(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym) {
964 if ldr.SymPlt(s) >= 0 {
965 return
966 }
967
968 ld.Adddynsym(ldr, &ctxt.Target, &ctxt.ArchSyms, s)
969
970 if ctxt.IsELF {
971 plt := ldr.MakeSymbolUpdater(ctxt.PLT)
972 rela := ldr.MakeSymbolUpdater(ctxt.RelaPLT)
973 if plt.Size() == 0 {
974 panic("plt is not set up")
975 }
976
977
978 glink := ensureglinkresolver(ctxt, ldr)
979
980
981
982 rel, _ := glink.AddRel(objabi.R_CALLPOWER)
983 rel.SetOff(int32(glink.Size()))
984 rel.SetSiz(4)
985 rel.SetSym(glink.Sym())
986 glink.AddUint32(ctxt.Arch, 0x48000000)
987
988
989
990
991
992
993
994 ldr.SetPlt(s, int32(plt.Size()))
995
996 plt.Grow(plt.Size() + 8)
997 plt.SetSize(plt.Size() + 8)
998
999 rela.AddAddrPlus(ctxt.Arch, plt.Sym(), int64(ldr.SymPlt(s)))
1000 rela.AddUint64(ctxt.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_PPC64_JMP_SLOT)))
1001 rela.AddUint64(ctxt.Arch, 0)
1002 } else {
1003 ctxt.Errorf(s, "addpltsym: unsupported binary format")
1004 }
1005 }
1006
1007
1008 func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilder {
1009 glink := ldr.CreateSymForUpdate(".glink", 0)
1010 if glink.Size() != 0 {
1011 return glink
1012 }
1013
1014
1015
1016
1017
1018
1019
1020
1021 glink.AddUint32(ctxt.Arch, 0x7c0802a6)
1022 glink.AddUint32(ctxt.Arch, 0x429f0005)
1023 glink.AddUint32(ctxt.Arch, 0x7d6802a6)
1024 glink.AddUint32(ctxt.Arch, 0x7c0803a6)
1025
1026
1027
1028
1029
1030 glink.AddUint32(ctxt.Arch, 0x3800ffd0)
1031 glink.AddUint32(ctxt.Arch, 0x7c006214)
1032 glink.AddUint32(ctxt.Arch, 0x7c0b0050)
1033 glink.AddUint32(ctxt.Arch, 0x7800f082)
1034
1035
1036 glink.AddSymRef(ctxt.Arch, ctxt.PLT, 0, objabi.R_ADDRPOWER, 8)
1037
1038 glink.AddUint32(ctxt.Arch, 0x3d600000)
1039 glink.AddUint32(ctxt.Arch, 0x396b0000)
1040
1041
1042
1043 glink.AddUint32(ctxt.Arch, 0xe98b0000)
1044 glink.AddUint32(ctxt.Arch, 0xe96b0008)
1045
1046
1047 glink.AddUint32(ctxt.Arch, 0x7d8903a6)
1048 glink.AddUint32(ctxt.Arch, 0x4e800420)
1049
1050
1051
1052
1053
1054
1055 du := ldr.MakeSymbolUpdater(ctxt.Dynamic)
1056 ld.Elfwritedynentsymplus(ctxt, du, elf.DT_PPC64_GLINK, glink.Sym(), glink.Size()-32)
1057
1058 return glink
1059 }
1060
View as plain text