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 }
325 return true
326
327 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16):
328 su := ldr.MakeSymbolUpdater(s)
329 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
330 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO|sym.RV_CHECK_OVERFLOW)
331 return true
332
333 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO):
334 su := ldr.MakeSymbolUpdater(s)
335 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
336 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
337 return true
338
339 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA):
340 su := ldr.MakeSymbolUpdater(s)
341 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
342 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
343 return true
344
345 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI):
346 su := ldr.MakeSymbolUpdater(s)
347 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
348 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
349 return true
350
351 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS):
352 su := ldr.MakeSymbolUpdater(s)
353 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
354 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS|sym.RV_CHECK_OVERFLOW)
355 return true
356
357 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO_DS):
358 su := ldr.MakeSymbolUpdater(s)
359 su.SetRelocType(rIdx, objabi.R_POWER_TOC)
360 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_DS)
361 return true
362
363 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO):
364 su := ldr.MakeSymbolUpdater(s)
365 su.SetRelocType(rIdx, objabi.R_PCREL)
366 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_LO)
367 su.SetRelocAdd(rIdx, r.Add()+2)
368 return true
369
370 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI):
371 su := ldr.MakeSymbolUpdater(s)
372 su.SetRelocType(rIdx, objabi.R_PCREL)
373 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HI|sym.RV_CHECK_OVERFLOW)
374 su.SetRelocAdd(rIdx, r.Add()+2)
375 return true
376
377 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA):
378 su := ldr.MakeSymbolUpdater(s)
379 su.SetRelocType(rIdx, objabi.R_PCREL)
380 ldr.SetRelocVariant(s, rIdx, sym.RV_POWER_HA|sym.RV_CHECK_OVERFLOW)
381 su.SetRelocAdd(rIdx, r.Add()+2)
382 return true
383 }
384
385
386 if targType != sym.SDYNIMPORT {
387 return true
388 }
389
390
391
392 return false
393 }
394
395 func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool {
396 rs := r.Xsym
397
398 emitReloc := func(v uint16, off uint64) {
399 out.Write64(uint64(sectoff) + off)
400 out.Write32(uint32(ldr.SymDynid(rs)))
401 out.Write16(v)
402 }
403
404 var v uint16
405 switch r.Type {
406 default:
407 return false
408 case objabi.R_ADDR, objabi.R_DWARFSECREF:
409 v = ld.XCOFF_R_POS
410 if r.Size == 4 {
411 v |= 0x1F << 8
412 } else {
413 v |= 0x3F << 8
414 }
415 emitReloc(v, 0)
416 case objabi.R_ADDRPOWER_TOCREL:
417 case objabi.R_ADDRPOWER_TOCREL_DS:
418 emitReloc(ld.XCOFF_R_TOCU|(0x0F<<8), 2)
419 emitReloc(ld.XCOFF_R_TOCL|(0x0F<<8), 6)
420 case objabi.R_POWER_TLS_LE:
421
422 emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2)
423 case objabi.R_CALLPOWER:
424 if r.Size != 4 {
425 return false
426 }
427 emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
428 case objabi.R_XCOFFREF:
429 emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0)
430 }
431 return true
432
433 }
434
435 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
436
437 rt := r.Type
438 if rt == objabi.R_ADDR || rt == objabi.R_POWER_TLS || rt == objabi.R_CALLPOWER {
439 } else {
440 if ctxt.Arch.ByteOrder == binary.BigEndian {
441 sectoff += 2
442 }
443 }
444 out.Write64(uint64(sectoff))
445
446 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
447 switch rt {
448 default:
449 return false
450 case objabi.R_ADDR, objabi.R_DWARFSECREF:
451 switch r.Size {
452 case 4:
453 out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32)
454 case 8:
455 out.Write64(uint64(elf.R_PPC64_ADDR64) | uint64(elfsym)<<32)
456 default:
457 return false
458 }
459 case objabi.R_POWER_TLS:
460 out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32)
461 case objabi.R_POWER_TLS_LE:
462 out.Write64(uint64(elf.R_PPC64_TPREL16_HA) | uint64(elfsym)<<32)
463 out.Write64(uint64(r.Xadd))
464 out.Write64(uint64(sectoff + 4))
465 out.Write64(uint64(elf.R_PPC64_TPREL16_LO) | uint64(elfsym)<<32)
466 case objabi.R_POWER_TLS_IE:
467 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32)
468 out.Write64(uint64(r.Xadd))
469 out.Write64(uint64(sectoff + 4))
470 out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_LO_DS) | uint64(elfsym)<<32)
471 case objabi.R_ADDRPOWER:
472 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
473 out.Write64(uint64(r.Xadd))
474 out.Write64(uint64(sectoff + 4))
475 out.Write64(uint64(elf.R_PPC64_ADDR16_LO) | uint64(elfsym)<<32)
476 case objabi.R_ADDRPOWER_DS:
477 out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
478 out.Write64(uint64(r.Xadd))
479 out.Write64(uint64(sectoff + 4))
480 out.Write64(uint64(elf.R_PPC64_ADDR16_LO_DS) | uint64(elfsym)<<32)
481 case objabi.R_ADDRPOWER_GOT:
482 out.Write64(uint64(elf.R_PPC64_GOT16_HA) | uint64(elfsym)<<32)
483 out.Write64(uint64(r.Xadd))
484 out.Write64(uint64(sectoff + 4))
485 out.Write64(uint64(elf.R_PPC64_GOT16_LO_DS) | uint64(elfsym)<<32)
486 case objabi.R_ADDRPOWER_PCREL:
487 out.Write64(uint64(elf.R_PPC64_REL16_HA) | uint64(elfsym)<<32)
488 out.Write64(uint64(r.Xadd))
489 out.Write64(uint64(sectoff + 4))
490 out.Write64(uint64(elf.R_PPC64_REL16_LO) | uint64(elfsym)<<32)
491 r.Xadd += 4
492 case objabi.R_ADDRPOWER_TOCREL:
493 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
494 out.Write64(uint64(r.Xadd))
495 out.Write64(uint64(sectoff + 4))
496 out.Write64(uint64(elf.R_PPC64_TOC16_LO) | uint64(elfsym)<<32)
497 case objabi.R_ADDRPOWER_TOCREL_DS:
498 out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
499 out.Write64(uint64(r.Xadd))
500 out.Write64(uint64(sectoff + 4))
501 out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32)
502 case objabi.R_CALLPOWER:
503 if r.Size != 4 {
504 return false
505 }
506 out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32)
507
508 }
509 out.Write64(uint64(r.Xadd))
510
511 return true
512 }
513
514 func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
515 if plt.Size() == 0 {
516
517
518
519
520 plt.SetSize(16)
521 }
522 }
523
524 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
525 return false
526 }
527
528
529 func symtoc(ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) int64 {
530 v := ldr.SymVersion(s)
531 if out := ldr.OuterSym(s); out != 0 {
532 v = ldr.SymVersion(out)
533 }
534
535 toc := syms.DotTOC[v]
536 if toc == 0 {
537 ldr.Errorf(s, "TOC-relative relocation in object without .TOC.")
538 return 0
539 }
540
541 return ldr.SymValue(toc)
542 }
543
544
545
546
547
548
549 func archreloctoc(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
550 rs := ldr.ResolveABIAlias(r.Sym())
551 if target.IsLinux() {
552 ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
553 }
554 var o1, o2 uint32
555
556 o1 = uint32(val >> 32)
557 o2 = uint32(val)
558
559 if !strings.HasPrefix(ldr.SymName(rs), "TOC.") {
560 ldr.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
561 }
562 var t int64
563 useAddi := false
564 relocs := ldr.Relocs(rs)
565 tarSym := ldr.ResolveABIAlias(relocs.At(0).Sym())
566
567 if target.IsInternal() && tarSym != 0 && ldr.AttrReachable(tarSym) && ldr.SymSect(tarSym).Seg == &ld.Segdata {
568 t = ldr.SymValue(tarSym) + r.Add() - ldr.SymValue(syms.TOC)
569
570 o2 = (o2 & 0x03FF0000) | 0xE<<26
571 useAddi = true
572 } else {
573 t = ldr.SymValue(rs) + r.Add() - ldr.SymValue(syms.TOC)
574 }
575
576 if t != int64(int32(t)) {
577 ldr.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", ldr.SymName(s), rs, t)
578 }
579
580 if t&0x8000 != 0 {
581 t += 0x10000
582 }
583
584 o1 |= uint32((t >> 16) & 0xFFFF)
585
586 switch r.Type() {
587 case objabi.R_ADDRPOWER_TOCREL_DS:
588 if useAddi {
589 o2 |= uint32(t) & 0xFFFF
590 } else {
591 if t&3 != 0 {
592 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
593 }
594 o2 |= uint32(t) & 0xFFFC
595 }
596 default:
597 return -1
598 }
599
600 return int64(o1)<<32 | int64(o2)
601 }
602
603
604
605 func archrelocaddr(ldr *loader.Loader, target *ld.Target, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) int64 {
606 rs := ldr.ResolveABIAlias(r.Sym())
607 if target.IsAIX() {
608 ldr.Errorf(s, "archrelocaddr called for %s relocation\n", ldr.SymName(rs))
609 }
610 var o1, o2 uint32
611 if target.IsBigEndian() {
612 o1 = uint32(val >> 32)
613 o2 = uint32(val)
614 } else {
615 o1 = uint32(val)
616 o2 = uint32(val >> 32)
617 }
618
619
620
621
622
623
624
625
626 t := ldr.SymAddr(rs) + r.Add()
627 if t < 0 || t >= 1<<31 {
628 ldr.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", ldr.SymName(s), ldr.SymValue(rs))
629 }
630 if t&0x8000 != 0 {
631 t += 0x10000
632 }
633
634 switch r.Type() {
635 case objabi.R_ADDRPOWER:
636 o1 |= (uint32(t) >> 16) & 0xffff
637 o2 |= uint32(t) & 0xffff
638 case objabi.R_ADDRPOWER_DS:
639 o1 |= (uint32(t) >> 16) & 0xffff
640 if t&3 != 0 {
641 ldr.Errorf(s, "bad DS reloc for %s: %d", ldr.SymName(s), ldr.SymValue(rs))
642 }
643 o2 |= uint32(t) & 0xfffc
644 default:
645 return -1
646 }
647
648 if target.IsBigEndian() {
649 return int64(o1)<<32 | int64(o2)
650 }
651 return int64(o2)<<32 | int64(o1)
652 }
653
654
655 func r2Valid(ctxt *ld.Link) bool {
656 switch ctxt.BuildMode {
657 case ld.BuildModeCArchive, ld.BuildModeCShared, ld.BuildModePIE, ld.BuildModeShared, ld.BuildModePlugin:
658 return true
659 }
660
661 return ctxt.IsSharedGoLink()
662 }
663
664
665 func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
666
667
668
669
670
671 if ctxt.IsExternal() && r2Valid(ctxt) {
672
673 return
674 }
675
676 relocs := ldr.Relocs(s)
677 r := relocs.At(ri)
678 var t int64
679
680
681
682 if ldr.SymValue(rs) != 0 {
683 t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
684 }
685 switch r.Type() {
686 case objabi.R_CALLPOWER:
687
688
689
690 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)) {
691 var tramp loader.Sym
692 for i := 0; ; i++ {
693
694
695
696
697
698 oName := ldr.SymName(rs)
699 name := oName
700 if r.Add() == 0 {
701 name += fmt.Sprintf("-tramp%d", i)
702 } else {
703 name += fmt.Sprintf("%+x-tramp%d", r.Add(), i)
704 }
705
706
707
708 tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
709 if oName == "runtime.deferreturn" {
710 ldr.SetIsDeferReturnTramp(tramp, true)
711 }
712 if ldr.SymValue(tramp) == 0 {
713 break
714 }
715
716 t = ldr.SymValue(tramp) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
717
718
719
720 if (ctxt.IsInternal() && int64(int32(t<<6)>>6) == t) || (ctxt.IsExternal() && ldr.SymSect(s) == ldr.SymSect(tramp)) {
721 break
722 }
723 }
724 if ldr.SymType(tramp) == 0 {
725 if r2Valid(ctxt) {
726
727 ctxt.Errorf(s, "unexpected trampoline for shared or dynamic linking")
728 } else {
729 trampb := ldr.MakeSymbolUpdater(tramp)
730 ctxt.AddTramp(trampb)
731 gentramp(ctxt, ldr, trampb, rs, r.Add())
732 }
733 }
734 sb := ldr.MakeSymbolUpdater(s)
735 relocs := sb.Relocs()
736 r := relocs.At(ri)
737 r.SetSym(tramp)
738 r.SetAdd(0)
739 }
740 default:
741 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
742 }
743 }
744
745 func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
746 tramp.SetSize(16)
747 P := make([]byte, tramp.Size())
748 t := ldr.SymValue(target) + offset
749 var o1, o2 uint32
750
751 if ctxt.IsAIX() {
752
753
754
755
756
757 o1 = uint32(0x3fe20000)
758 o2 = uint32(0xebff0000)
759
760 toctramp := ldr.CreateSymForUpdate("TOC."+ldr.SymName(tramp.Sym()), 0)
761 toctramp.SetType(sym.SXCOFFTOC)
762 toctramp.AddAddrPlus(ctxt.Arch, target, offset)
763
764 r, _ := tramp.AddRel(objabi.R_ADDRPOWER_TOCREL_DS)
765 r.SetOff(0)
766 r.SetSiz(8)
767 r.SetSym(toctramp.Sym())
768 } else {
769
770
771
772 o1 = uint32(0x3fe00000)
773 o2 = uint32(0x3bff0000)
774
775
776
777 if ctxt.IsExternal() || ldr.SymValue(target) == 0 {
778 r, _ := tramp.AddRel(objabi.R_ADDRPOWER)
779 r.SetOff(0)
780 r.SetSiz(8)
781 r.SetSym(target)
782 r.SetAdd(offset)
783 } else {
784
785
786 val := uint32((t & 0xffff0000) >> 16)
787 if t&0x8000 != 0 {
788 val += 1
789 }
790 o1 |= val
791 o2 |= uint32(t & 0xffff)
792 }
793 }
794
795 o3 := uint32(0x7fe903a6)
796 o4 := uint32(0x4e800420)
797 ctxt.Arch.ByteOrder.PutUint32(P, o1)
798 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
799 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
800 ctxt.Arch.ByteOrder.PutUint32(P[12:], o4)
801 tramp.SetData(P)
802 }
803
804 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) {
805 rs := ldr.ResolveABIAlias(r.Sym())
806 if target.IsExternal() {
807
808
809 switch rt := r.Type(); rt {
810 default:
811 if !target.IsAIX() {
812 return val, nExtReloc, false
813 }
814 case objabi.R_POWER_TLS:
815 nExtReloc = 1
816 return val, nExtReloc, true
817 case objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
818 if target.IsAIX() && rt == objabi.R_POWER_TLS_LE {
819
820
821
822 const expectedOpcodes = 0x3C00000038000000
823 const expectedOpmasks = 0xFC000000FC000000
824 if uint64(val)&expectedOpmasks != expectedOpcodes {
825 ldr.Errorf(s, "relocation for %s+%d is not an addis/addi pair: %16x", ldr.SymName(rs), r.Off(), uint64(val))
826 }
827 nval := (int64(uint32(0x380d0000)) | val&0x03e00000) << 32
828 nval |= int64(0x60000000)
829 val = nval
830 nExtReloc = 1
831 } else {
832 nExtReloc = 2
833 }
834 return val, nExtReloc, true
835 case objabi.R_ADDRPOWER,
836 objabi.R_ADDRPOWER_DS,
837 objabi.R_ADDRPOWER_TOCREL,
838 objabi.R_ADDRPOWER_TOCREL_DS,
839 objabi.R_ADDRPOWER_GOT,
840 objabi.R_ADDRPOWER_PCREL:
841 nExtReloc = 2
842 if !target.IsAIX() {
843 return val, nExtReloc, true
844 }
845 case objabi.R_CALLPOWER:
846 nExtReloc = 1
847 if !target.IsAIX() {
848 return val, nExtReloc, true
849 }
850 }
851 }
852
853 switch r.Type() {
854 case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
855 return archreloctoc(ldr, target, syms, r, s, val), nExtReloc, true
856 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
857 return archrelocaddr(ldr, target, syms, r, s, val), nExtReloc, true
858 case objabi.R_CALLPOWER:
859
860
861 t := ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
862
863 if t&3 != 0 {
864 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
865 }
866
867
868 if int64(int32(t<<6)>>6) != t {
869 ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
870 }
871 return val | int64(uint32(t)&^0xfc000003), nExtReloc, true
872 case objabi.R_POWER_TOC:
873 return ldr.SymValue(rs) + r.Add() - symtoc(ldr, syms, s), nExtReloc, true
874
875 case objabi.R_POWER_TLS_LE:
876
877
878
879
880 v := ldr.SymValue(rs) - 0x7000
881 if target.IsAIX() {
882
883
884 v -= 0x800
885 }
886
887 var o1, o2 uint32
888 if int64(int32(v)) != v {
889 ldr.Errorf(s, "TLS offset out of range %d", v)
890 }
891 if target.IsBigEndian() {
892 o1 = uint32(val >> 32)
893 o2 = uint32(val)
894 } else {
895 o1 = uint32(val)
896 o2 = uint32(val >> 32)
897 }
898
899 o1 |= uint32(((v + 0x8000) >> 16) & 0xFFFF)
900 o2 |= uint32(v & 0xFFFF)
901
902 if target.IsBigEndian() {
903 return int64(o1)<<32 | int64(o2), nExtReloc, true
904 }
905 return int64(o2)<<32 | int64(o1), nExtReloc, true
906 }
907
908 return val, nExtReloc, false
909 }
910
911 func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc, rv sym.RelocVariant, s loader.Sym, t int64, p []byte) (relocatedOffset int64) {
912 rs := ldr.ResolveABIAlias(r.Sym())
913 switch rv & sym.RV_TYPE_MASK {
914 default:
915 ldr.Errorf(s, "unexpected relocation variant %d", rv)
916 fallthrough
917
918 case sym.RV_NONE:
919 return t
920
921 case sym.RV_POWER_LO:
922 if rv&sym.RV_CHECK_OVERFLOW != 0 {
923
924
925 var o1 uint32
926 if target.IsBigEndian() {
927 o1 = binary.BigEndian.Uint32(p[r.Off()-2:])
928
929 } else {
930 o1 = binary.LittleEndian.Uint32(p[r.Off():])
931 }
932 switch o1 >> 26 {
933 case 24,
934 26,
935 28:
936 if t>>16 != 0 {
937 goto overflow
938 }
939
940 default:
941 if int64(int16(t)) != t {
942 goto overflow
943 }
944 }
945 }
946
947 return int64(int16(t))
948
949 case sym.RV_POWER_HA:
950 t += 0x8000
951 fallthrough
952
953
954 case sym.RV_POWER_HI:
955 t >>= 16
956
957 if rv&sym.RV_CHECK_OVERFLOW != 0 {
958
959
960 var o1 uint32
961 if target.IsBigEndian() {
962 o1 = binary.BigEndian.Uint32(p[r.Off()-2:])
963 } else {
964 o1 = binary.LittleEndian.Uint32(p[r.Off():])
965 }
966 switch o1 >> 26 {
967 case 25,
968 27,
969 29:
970 if t>>16 != 0 {
971 goto overflow
972 }
973
974 default:
975 if int64(int16(t)) != t {
976 goto overflow
977 }
978 }
979 }
980
981 return int64(int16(t))
982
983 case sym.RV_POWER_DS:
984 var o1 uint32
985 if target.IsBigEndian() {
986 o1 = uint32(binary.BigEndian.Uint16(p[r.Off():]))
987 } else {
988 o1 = uint32(binary.LittleEndian.Uint16(p[r.Off():]))
989 }
990 if t&3 != 0 {
991 ldr.Errorf(s, "relocation for %s+%d is not aligned: %d", ldr.SymName(rs), r.Off(), t)
992 }
993 if (rv&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
994 goto overflow
995 }
996 return int64(o1)&0x3 | int64(int16(t))
997 }
998
999 overflow:
1000 ldr.Errorf(s, "relocation for %s+%d is too big: %d", ldr.SymName(rs), r.Off(), t)
1001 return t
1002 }
1003
1004 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
1005 switch r.Type() {
1006 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE, objabi.R_CALLPOWER:
1007 return ld.ExtrelocSimple(ldr, r), true
1008 case objabi.R_ADDRPOWER,
1009 objabi.R_ADDRPOWER_DS,
1010 objabi.R_ADDRPOWER_TOCREL,
1011 objabi.R_ADDRPOWER_TOCREL_DS,
1012 objabi.R_ADDRPOWER_GOT,
1013 objabi.R_ADDRPOWER_PCREL:
1014 return ld.ExtrelocViaOuterSym(ldr, r, s), true
1015 }
1016 return loader.ExtReloc{}, false
1017 }
1018
1019 func addpltsym(ctxt *ld.Link, ldr *loader.Loader, s loader.Sym) {
1020 if ldr.SymPlt(s) >= 0 {
1021 return
1022 }
1023
1024 ld.Adddynsym(ldr, &ctxt.Target, &ctxt.ArchSyms, s)
1025
1026 if ctxt.IsELF {
1027 plt := ldr.MakeSymbolUpdater(ctxt.PLT)
1028 rela := ldr.MakeSymbolUpdater(ctxt.RelaPLT)
1029 if plt.Size() == 0 {
1030 panic("plt is not set up")
1031 }
1032
1033
1034 glink := ensureglinkresolver(ctxt, ldr)
1035
1036
1037
1038 rel, _ := glink.AddRel(objabi.R_CALLPOWER)
1039 rel.SetOff(int32(glink.Size()))
1040 rel.SetSiz(4)
1041 rel.SetSym(glink.Sym())
1042 glink.AddUint32(ctxt.Arch, 0x48000000)
1043
1044
1045
1046
1047
1048
1049
1050 ldr.SetPlt(s, int32(plt.Size()))
1051
1052 plt.Grow(plt.Size() + 8)
1053 plt.SetSize(plt.Size() + 8)
1054
1055 rela.AddAddrPlus(ctxt.Arch, plt.Sym(), int64(ldr.SymPlt(s)))
1056 rela.AddUint64(ctxt.Arch, elf.R_INFO(uint32(ldr.SymDynid(s)), uint32(elf.R_PPC64_JMP_SLOT)))
1057 rela.AddUint64(ctxt.Arch, 0)
1058 } else {
1059 ctxt.Errorf(s, "addpltsym: unsupported binary format")
1060 }
1061 }
1062
1063
1064 func ensureglinkresolver(ctxt *ld.Link, ldr *loader.Loader) *loader.SymbolBuilder {
1065 glink := ldr.CreateSymForUpdate(".glink", 0)
1066 if glink.Size() != 0 {
1067 return glink
1068 }
1069
1070
1071
1072
1073
1074
1075
1076
1077 glink.AddUint32(ctxt.Arch, 0x7c0802a6)
1078 glink.AddUint32(ctxt.Arch, 0x429f0005)
1079 glink.AddUint32(ctxt.Arch, 0x7d6802a6)
1080 glink.AddUint32(ctxt.Arch, 0x7c0803a6)
1081
1082
1083
1084
1085
1086 glink.AddUint32(ctxt.Arch, 0x3800ffd0)
1087 glink.AddUint32(ctxt.Arch, 0x7c006214)
1088 glink.AddUint32(ctxt.Arch, 0x7c0b0050)
1089 glink.AddUint32(ctxt.Arch, 0x7800f082)
1090
1091
1092 r, _ := glink.AddRel(objabi.R_ADDRPOWER)
1093 r.SetSym(ctxt.PLT)
1094 r.SetSiz(8)
1095 r.SetOff(int32(glink.Size()))
1096 r.SetAdd(0)
1097 glink.AddUint32(ctxt.Arch, 0x3d600000)
1098 glink.AddUint32(ctxt.Arch, 0x396b0000)
1099
1100
1101
1102 glink.AddUint32(ctxt.Arch, 0xe98b0000)
1103 glink.AddUint32(ctxt.Arch, 0xe96b0008)
1104
1105
1106 glink.AddUint32(ctxt.Arch, 0x7d8903a6)
1107 glink.AddUint32(ctxt.Arch, 0x4e800420)
1108
1109
1110
1111
1112
1113
1114 du := ldr.MakeSymbolUpdater(ctxt.Dynamic)
1115 ld.Elfwritedynentsymplus(ctxt, du, elf.DT_PPC64_GLINK, glink.Sym(), glink.Size()-32)
1116
1117 return glink
1118 }
1119
View as plain text