Source file src/pkg/cmd/link/internal/ppc64/asm.go
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/sym"
38 "debug/elf"
39 "encoding/binary"
40 "fmt"
41 "log"
42 "strings"
43 )
44
45 func genplt(ctxt *ld.Link) {
46
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 var stubs []*sym.Symbol
95 for _, s := range ctxt.Textp {
96 for i := range s.R {
97 r := &s.R[i]
98 if r.Type != objabi.ElfRelocOffset+objabi.RelocType(elf.R_PPC64_REL24) || r.Sym.Type != sym.SDYNIMPORT {
99 continue
100 }
101
102
103
104 addpltsym(ctxt, r.Sym)
105
106
107 n := fmt.Sprintf("%s.%s", s.Name, r.Sym.Name)
108
109 stub := ctxt.Syms.Lookup(n, 0)
110 if s.Attr.Reachable() {
111 stub.Attr |= sym.AttrReachable
112 }
113 if stub.Size == 0 {
114
115 stub.Outer = s
116 stubs = append(stubs, stub)
117 gencallstub(ctxt, 1, stub, r.Sym)
118 }
119
120
121 r.Sym = stub
122
123
124
125 const o1 = 0xe8410018
126 ctxt.Arch.ByteOrder.PutUint32(s.P[r.Off+4:], o1)
127 }
128 }
129
130
131
132
133 ctxt.Textp = append(stubs, ctxt.Textp...)
134 }
135
136 func genaddmoduledata(ctxt *ld.Link) {
137 addmoduledata := ctxt.Syms.ROLookup("runtime.addmoduledata", sym.SymVerABI0)
138 if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
139 return
140 }
141 addmoduledata.Attr |= sym.AttrReachable
142 initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
143 initfunc.Type = sym.STEXT
144 initfunc.Attr |= sym.AttrLocal
145 initfunc.Attr |= sym.AttrReachable
146 o := func(op uint32) {
147 initfunc.AddUint32(ctxt.Arch, op)
148 }
149
150 rel := initfunc.AddRel()
151 rel.Off = int32(initfunc.Size)
152 rel.Siz = 8
153 rel.Sym = ctxt.Syms.Lookup(".TOC.", 0)
154 rel.Sym.Attr |= sym.AttrReachable
155 rel.Type = objabi.R_ADDRPOWER_PCREL
156 o(0x3c4c0000)
157
158 o(0x38420000)
159
160 o(0x7c0802a6)
161
162 o(0xf801ffe1)
163
164 rel = initfunc.AddRel()
165 rel.Off = int32(initfunc.Size)
166 rel.Siz = 8
167 if s := ctxt.Syms.ROLookup("local.moduledata", 0); s != nil {
168 rel.Sym = s
169 } else if s := ctxt.Syms.ROLookup("local.pluginmoduledata", 0); s != nil {
170 rel.Sym = s
171 } else {
172 rel.Sym = ctxt.Syms.Lookup("runtime.firstmoduledata", 0)
173 }
174 rel.Sym.Attr |= sym.AttrReachable
175 rel.Sym.Attr |= sym.AttrLocal
176 rel.Type = objabi.R_ADDRPOWER_GOT
177 o(0x3c620000)
178
179 o(0xe8630000)
180
181 rel = initfunc.AddRel()
182 rel.Off = int32(initfunc.Size)
183 rel.Siz = 4
184 rel.Sym = addmoduledata
185 rel.Type = objabi.R_CALLPOWER
186 o(0x48000001)
187
188 o(0x60000000)
189
190 o(0xe8010000)
191
192 o(0x7c0803a6)
193
194 o(0x38210020)
195
196 o(0x4e800020)
197
198 if ctxt.BuildMode == ld.BuildModePlugin {
199 ctxt.Textp = append(ctxt.Textp, addmoduledata)
200 }
201 initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
202 ctxt.Textp = append(ctxt.Textp, initfunc)
203 initarray_entry.Attr |= sym.AttrReachable
204 initarray_entry.Attr |= sym.AttrLocal
205 initarray_entry.Type = sym.SINITARR
206 initarray_entry.AddAddr(ctxt.Arch, initfunc)
207 }
208
209 func gentext(ctxt *ld.Link) {
210 if ctxt.DynlinkingGo() {
211 genaddmoduledata(ctxt)
212 }
213
214 if ctxt.LinkMode == ld.LinkInternal {
215 genplt(ctxt)
216 }
217 }
218
219
220
221 func gencallstub(ctxt *ld.Link, abicase int, stub *sym.Symbol, targ *sym.Symbol) {
222 if abicase != 1 {
223
224
225 log.Fatalf("gencallstub only implements case 1 calls")
226 }
227
228 plt := ctxt.Syms.Lookup(".plt", 0)
229
230 stub.Type = sym.STEXT
231
232
233 stub.AddUint32(ctxt.Arch, 0xf8410018)
234
235
236 r := stub.AddRel()
237
238 r.Off = int32(stub.Size)
239 r.Sym = plt
240 r.Add = int64(targ.Plt())
241 r.Siz = 2
242 if ctxt.Arch.ByteOrder == binary.BigEndian {
243 r.Off += int32(r.Siz)
244 }
245 r.Type = objabi.R_POWER_TOC
246 r.Variant = sym.RV_POWER_HA
247 stub.AddUint32(ctxt.Arch, 0x3d820000)
248 r = stub.AddRel()
249 r.Off = int32(stub.Size)
250 r.Sym = plt
251 r.Add = int64(targ.Plt())
252 r.Siz = 2
253 if ctxt.Arch.ByteOrder == binary.BigEndian {
254 r.Off += int32(r.Siz)
255 }
256 r.Type = objabi.R_POWER_TOC
257 r.Variant = sym.RV_POWER_LO
258 stub.AddUint32(ctxt.Arch, 0xe98c0000)
259
260
261 stub.AddUint32(ctxt.Arch, 0x7d8903a6)
262 stub.AddUint32(ctxt.Arch, 0x4e800420)
263 }
264
265 func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
266 if ctxt.IsELF {
267 return addelfdynrel(ctxt, s, r)
268 } else if ctxt.HeadType == objabi.Haix {
269 return ld.Xcoffadddynrel(ctxt, s, r)
270 }
271 return false
272 }
273 func addelfdynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
274 targ := r.Sym
275 r.InitExt()
276
277 switch r.Type {
278 default:
279 if r.Type >= objabi.ElfRelocOffset {
280 ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
281 return false
282 }
283
284
285 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL24):
286 r.Type = objabi.R_CALLPOWER
287
288
289
290
291
292
293 r.Add += int64(r.Sym.Localentry()) * 4
294
295 if targ.Type == sym.SDYNIMPORT {
296
297 ld.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
298 }
299
300 return true
301
302 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC_REL32):
303 r.Type = objabi.R_PCREL
304 r.Add += 4
305
306 if targ.Type == sym.SDYNIMPORT {
307 ld.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 r.Type = objabi.R_ADDR
314 if targ.Type == sym.SDYNIMPORT {
315
316 ld.Adddynsym(ctxt, targ)
317
318 rela := ctxt.Syms.Lookup(".rela", 0)
319 rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
320 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_PPC64_ADDR64)))
321 rela.AddUint64(ctxt.Arch, uint64(r.Add))
322 r.Type = objabi.ElfRelocOffset
323 }
324
325 return true
326
327 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16):
328 r.Type = objabi.R_POWER_TOC
329 r.Variant = sym.RV_POWER_LO | sym.RV_CHECK_OVERFLOW
330 return true
331
332 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_LO):
333 r.Type = objabi.R_POWER_TOC
334 r.Variant = sym.RV_POWER_LO
335 return true
336
337 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HA):
338 r.Type = objabi.R_POWER_TOC
339 r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
340 return true
341
342 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_HI):
343 r.Type = objabi.R_POWER_TOC
344 r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
345 return true
346
347 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_TOC16_DS):
348 r.Type = objabi.R_POWER_TOC
349 r.Variant = 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 r.Type = objabi.R_POWER_TOC
354 r.Variant = sym.RV_POWER_DS
355 return true
356
357 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_LO):
358 r.Type = objabi.R_PCREL
359 r.Variant = sym.RV_POWER_LO
360 r.Add += 2
361 return true
362
363 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HI):
364 r.Type = objabi.R_PCREL
365 r.Variant = sym.RV_POWER_HI | sym.RV_CHECK_OVERFLOW
366 r.Add += 2
367 return true
368
369 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_PPC64_REL16_HA):
370 r.Type = objabi.R_PCREL
371 r.Variant = sym.RV_POWER_HA | sym.RV_CHECK_OVERFLOW
372 r.Add += 2
373 return true
374 }
375
376
377 if targ.Type != sym.SDYNIMPORT {
378 return true
379 }
380
381
382
383 return false
384 }
385
386 func xcoffreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
387 rs := r.Xsym
388
389 emitReloc := func(v uint16, off uint64) {
390 out.Write64(uint64(sectoff) + off)
391 out.Write32(uint32(rs.Dynid))
392 out.Write16(v)
393 }
394
395 var v uint16
396 switch r.Type {
397 default:
398 return false
399 case objabi.R_ADDR:
400 v = ld.XCOFF_R_POS
401 if r.Siz == 4 {
402 v |= 0x1F << 8
403 } else {
404 v |= 0x3F << 8
405 }
406 emitReloc(v, 0)
407 case objabi.R_ADDRPOWER_TOCREL:
408 case objabi.R_ADDRPOWER_TOCREL_DS:
409 emitReloc(ld.XCOFF_R_TOCU|(0x0F<<8), 2)
410 emitReloc(ld.XCOFF_R_TOCL|(0x0F<<8), 6)
411 case objabi.R_POWER_TLS_LE:
412 emitReloc(ld.XCOFF_R_TLS_LE|0x0F<<8, 2)
413 case objabi.R_CALLPOWER:
414 if r.Siz != 4 {
415 return false
416 }
417 emitReloc(ld.XCOFF_R_RBR|0x19<<8, 0)
418 case objabi.R_XCOFFREF:
419 emitReloc(ld.XCOFF_R_REF|0x3F<<8, 0)
420
421 }
422 return true
423
424 }
425
426 func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
427
428 if r.Type == objabi.R_ADDR || r.Type == objabi.R_POWER_TLS || r.Type == objabi.R_CALLPOWER {
429 } else {
430 if ctxt.Arch.ByteOrder == binary.BigEndian {
431 sectoff += 2
432 }
433 }
434 ctxt.Out.Write64(uint64(sectoff))
435
436 elfsym := r.Xsym.ElfsymForReloc()
437 switch r.Type {
438 default:
439 return false
440 case objabi.R_ADDR:
441 switch r.Siz {
442 case 4:
443 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR32) | uint64(elfsym)<<32)
444 case 8:
445 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR64) | uint64(elfsym)<<32)
446 default:
447 return false
448 }
449 case objabi.R_POWER_TLS:
450 ctxt.Out.Write64(uint64(elf.R_PPC64_TLS) | uint64(elfsym)<<32)
451 case objabi.R_POWER_TLS_LE:
452 ctxt.Out.Write64(uint64(elf.R_PPC64_TPREL16) | uint64(elfsym)<<32)
453 case objabi.R_POWER_TLS_IE:
454 ctxt.Out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_HA) | uint64(elfsym)<<32)
455 ctxt.Out.Write64(uint64(r.Xadd))
456 ctxt.Out.Write64(uint64(sectoff + 4))
457 ctxt.Out.Write64(uint64(elf.R_PPC64_GOT_TPREL16_LO_DS) | uint64(elfsym)<<32)
458 case objabi.R_ADDRPOWER:
459 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
460 ctxt.Out.Write64(uint64(r.Xadd))
461 ctxt.Out.Write64(uint64(sectoff + 4))
462 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_LO) | uint64(elfsym)<<32)
463 case objabi.R_ADDRPOWER_DS:
464 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_HA) | uint64(elfsym)<<32)
465 ctxt.Out.Write64(uint64(r.Xadd))
466 ctxt.Out.Write64(uint64(sectoff + 4))
467 ctxt.Out.Write64(uint64(elf.R_PPC64_ADDR16_LO_DS) | uint64(elfsym)<<32)
468 case objabi.R_ADDRPOWER_GOT:
469 ctxt.Out.Write64(uint64(elf.R_PPC64_GOT16_HA) | uint64(elfsym)<<32)
470 ctxt.Out.Write64(uint64(r.Xadd))
471 ctxt.Out.Write64(uint64(sectoff + 4))
472 ctxt.Out.Write64(uint64(elf.R_PPC64_GOT16_LO_DS) | uint64(elfsym)<<32)
473 case objabi.R_ADDRPOWER_PCREL:
474 ctxt.Out.Write64(uint64(elf.R_PPC64_REL16_HA) | uint64(elfsym)<<32)
475 ctxt.Out.Write64(uint64(r.Xadd))
476 ctxt.Out.Write64(uint64(sectoff + 4))
477 ctxt.Out.Write64(uint64(elf.R_PPC64_REL16_LO) | uint64(elfsym)<<32)
478 r.Xadd += 4
479 case objabi.R_ADDRPOWER_TOCREL:
480 ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
481 ctxt.Out.Write64(uint64(r.Xadd))
482 ctxt.Out.Write64(uint64(sectoff + 4))
483 ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_LO) | uint64(elfsym)<<32)
484 case objabi.R_ADDRPOWER_TOCREL_DS:
485 ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_HA) | uint64(elfsym)<<32)
486 ctxt.Out.Write64(uint64(r.Xadd))
487 ctxt.Out.Write64(uint64(sectoff + 4))
488 ctxt.Out.Write64(uint64(elf.R_PPC64_TOC16_LO_DS) | uint64(elfsym)<<32)
489 case objabi.R_CALLPOWER:
490 if r.Siz != 4 {
491 return false
492 }
493 ctxt.Out.Write64(uint64(elf.R_PPC64_REL24) | uint64(elfsym)<<32)
494
495 }
496 ctxt.Out.Write64(uint64(r.Xadd))
497
498 return true
499 }
500
501 func elfsetupplt(ctxt *ld.Link) {
502 plt := ctxt.Syms.Lookup(".plt", 0)
503 if plt.Size == 0 {
504
505
506
507
508 plt.Size = 16
509 }
510 }
511
512 func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
513 return false
514 }
515
516
517 func symtoc(ctxt *ld.Link, s *sym.Symbol) int64 {
518 var toc *sym.Symbol
519
520 if s.Outer != nil {
521 toc = ctxt.Syms.ROLookup(".TOC.", int(s.Outer.Version))
522 } else {
523 toc = ctxt.Syms.ROLookup(".TOC.", int(s.Version))
524 }
525
526 if toc == nil {
527 ld.Errorf(s, "TOC-relative relocation in object without .TOC.")
528 return 0
529 }
530
531 return toc.Value
532 }
533
534
535
536
537
538
539 func archreloctoc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
540 if ctxt.HeadType == objabi.Hlinux {
541 ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
542 }
543 var o1, o2 uint32
544
545 o1 = uint32(val >> 32)
546 o2 = uint32(val)
547
548 var t int64
549 useAddi := false
550 const prefix = "TOC."
551 var tarSym *sym.Symbol
552 if strings.HasPrefix(r.Sym.Name, prefix) {
553 tarSym = ctxt.Syms.ROLookup(strings.TrimPrefix(r.Sym.Name, prefix), 0)
554 } else {
555 ld.Errorf(s, "archreloctoc called for a symbol without TOC anchor")
556 }
557
558 if ctxt.LinkMode == ld.LinkInternal && tarSym != nil && tarSym.Attr.Reachable() && (tarSym.Sect.Seg == &ld.Segdata) {
559 t = ld.Symaddr(tarSym) + r.Add - ctxt.Syms.ROLookup("TOC", 0).Value
560
561 o2 = (o2 & 0x03FF0000) | 0xE<<26
562 useAddi = true
563 } else {
564 t = ld.Symaddr(r.Sym) + r.Add - ctxt.Syms.ROLookup("TOC", 0).Value
565 }
566
567 if t != int64(int32(t)) {
568 ld.Errorf(s, "TOC relocation for %s is too big to relocate %s: 0x%x", s.Name, r.Sym, 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 ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
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(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) int64 {
597 if ctxt.HeadType == objabi.Haix {
598 ld.Errorf(s, "archrelocaddr called for %s relocation\n", r.Sym.Name)
599 }
600 var o1, o2 uint32
601 if ctxt.Arch.ByteOrder == binary.BigEndian {
602 o1 = uint32(val >> 32)
603 o2 = uint32(val)
604 } else {
605 o1 = uint32(val)
606 o2 = uint32(val >> 32)
607 }
608
609
610
611
612
613
614
615
616 t := ld.Symaddr(r.Sym) + r.Add
617 if t < 0 || t >= 1<<31 {
618 ld.Errorf(s, "relocation for %s is too big (>=2G): 0x%x", s.Name, ld.Symaddr(r.Sym))
619 }
620 if t&0x8000 != 0 {
621 t += 0x10000
622 }
623
624 switch r.Type {
625 case objabi.R_ADDRPOWER:
626 o1 |= (uint32(t) >> 16) & 0xffff
627 o2 |= uint32(t) & 0xffff
628 case objabi.R_ADDRPOWER_DS:
629 o1 |= (uint32(t) >> 16) & 0xffff
630 if t&3 != 0 {
631 ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
632 }
633 o2 |= uint32(t) & 0xfffc
634 default:
635 return -1
636 }
637
638 if ctxt.Arch.ByteOrder == binary.BigEndian {
639 return int64(o1)<<32 | int64(o2)
640 }
641 return int64(o2)<<32 | int64(o1)
642 }
643
644
645 func trampoline(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol) {
646
647
648
649
650
651 if ctxt.LinkMode == ld.LinkExternal && (ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE) {
652
653 return
654 }
655
656 t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
657 switch r.Type {
658 case objabi.R_CALLPOWER:
659
660
661
662 if (ctxt.LinkMode == ld.LinkExternal && s.Sect != r.Sym.Sect) || (ctxt.LinkMode == ld.LinkInternal && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && s.File != r.Sym.File) {
663 var tramp *sym.Symbol
664 for i := 0; ; i++ {
665
666
667
668
669
670 name := r.Sym.Name
671 if r.Add == 0 {
672 name = name + fmt.Sprintf("-tramp%d", i)
673 } else {
674 name = name + fmt.Sprintf("%+x-tramp%d", r.Add, i)
675 }
676
677
678
679 tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version))
680 if tramp.Value == 0 {
681 break
682 }
683
684 t = ld.Symaddr(tramp) + r.Add - (s.Value + int64(r.Off))
685
686
687
688 if (ctxt.LinkMode == ld.LinkInternal && int64(int32(t<<6)>>6) == t) || (ctxt.LinkMode == ld.LinkExternal && s.Sect == tramp.Sect) {
689 break
690 }
691 }
692 if tramp.Type == 0 {
693 if ctxt.DynlinkingGo() || ctxt.BuildMode == ld.BuildModeCArchive || ctxt.BuildMode == ld.BuildModeCShared || ctxt.BuildMode == ld.BuildModePIE {
694
695 ld.Errorf(s, "unexpected trampoline for shared or dynamic linking\n")
696 } else {
697 ctxt.AddTramp(tramp)
698 gentramp(ctxt, tramp, r.Sym, r.Add)
699 }
700 }
701 r.Sym = tramp
702 r.Add = 0
703 r.Done = false
704 }
705 default:
706 ld.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
707 }
708 }
709
710 func gentramp(ctxt *ld.Link, tramp, target *sym.Symbol, offset int64) {
711 tramp.Size = 16
712 tramp.P = make([]byte, tramp.Size)
713 t := ld.Symaddr(target) + offset
714 var o1, o2 uint32
715
716 if ctxt.HeadType == objabi.Haix {
717
718
719
720
721
722 o1 = uint32(0x3fe20000)
723 o2 = uint32(0xebff0000)
724
725 toctramp := ctxt.Syms.Lookup("TOC."+tramp.Name, 0)
726 toctramp.Type = sym.SXCOFFTOC
727 toctramp.Attr |= sym.AttrReachable
728 toctramp.AddAddr(ctxt.Arch, target)
729
730 tr := tramp.AddRel()
731 tr.Off = 0
732 tr.Type = objabi.R_ADDRPOWER_TOCREL_DS
733 tr.Siz = 8
734 tr.Sym = toctramp
735 tr.Add = offset
736 } else {
737
738
739
740 o1 = uint32(0x3fe00000)
741 o2 = uint32(0x3bff0000)
742
743
744
745 if ctxt.LinkMode == ld.LinkExternal {
746 tr := tramp.AddRel()
747 tr.Off = 0
748 tr.Type = objabi.R_ADDRPOWER
749 tr.Siz = 8
750 tr.Sym = target
751 tr.Add = offset
752
753 } else {
754
755
756 val := uint32((t & 0xffff0000) >> 16)
757 if t&0x8000 != 0 {
758 val += 1
759 }
760 o1 |= val
761 o2 |= uint32(t & 0xffff)
762 }
763 }
764
765 o3 := uint32(0x7fe903a6)
766 o4 := uint32(0x4e800420)
767 ctxt.Arch.ByteOrder.PutUint32(tramp.P, o1)
768 ctxt.Arch.ByteOrder.PutUint32(tramp.P[4:], o2)
769 ctxt.Arch.ByteOrder.PutUint32(tramp.P[8:], o3)
770 ctxt.Arch.ByteOrder.PutUint32(tramp.P[12:], o4)
771 }
772
773 func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
774 if ctxt.LinkMode == ld.LinkExternal {
775
776
777 switch r.Type {
778 default:
779 if ctxt.HeadType != objabi.Haix {
780 return val, false
781 }
782 case objabi.R_POWER_TLS, objabi.R_POWER_TLS_LE, objabi.R_POWER_TLS_IE:
783 r.Done = false
784
785 r.Xadd = r.Add
786 r.Xsym = r.Sym
787 return val, true
788 case objabi.R_ADDRPOWER,
789 objabi.R_ADDRPOWER_DS,
790 objabi.R_ADDRPOWER_TOCREL,
791 objabi.R_ADDRPOWER_TOCREL_DS,
792 objabi.R_ADDRPOWER_GOT,
793 objabi.R_ADDRPOWER_PCREL:
794 r.Done = false
795
796
797 rs := r.Sym
798 r.Xadd = r.Add
799 for rs.Outer != nil {
800 r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
801 rs = rs.Outer
802 }
803
804 if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
805 ld.Errorf(s, "missing section for %s", rs.Name)
806 }
807 r.Xsym = rs
808
809 if ctxt.HeadType != objabi.Haix {
810 return val, true
811 }
812 case objabi.R_CALLPOWER:
813 r.Done = false
814 r.Xsym = r.Sym
815 r.Xadd = r.Add
816 if ctxt.HeadType != objabi.Haix {
817 return val, true
818 }
819 }
820 }
821
822 switch r.Type {
823 case objabi.R_CONST:
824 return r.Add, true
825 case objabi.R_GOTOFF:
826 return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
827 case objabi.R_ADDRPOWER_TOCREL, objabi.R_ADDRPOWER_TOCREL_DS:
828 return archreloctoc(ctxt, r, s, val), true
829 case objabi.R_ADDRPOWER, objabi.R_ADDRPOWER_DS:
830 return archrelocaddr(ctxt, r, s, val), true
831 case objabi.R_CALLPOWER:
832
833
834 t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
835
836 if t&3 != 0 {
837 ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
838 }
839
840
841 if int64(int32(t<<6)>>6) != t {
842 ld.Errorf(s, "direct call too far: %s %x", r.Sym.Name, t)
843 }
844 return val | int64(uint32(t)&^0xfc000003), true
845 case objabi.R_POWER_TOC:
846 return ld.Symaddr(r.Sym) + r.Add - symtoc(ctxt, s), true
847
848 case objabi.R_POWER_TLS_LE:
849
850
851
852
853 v := r.Sym.Value - 0x7000
854 if ctxt.HeadType == objabi.Haix {
855
856
857 v -= 0x800
858 }
859 if int64(int16(v)) != v {
860 ld.Errorf(s, "TLS offset out of range %d", v)
861 }
862 return (val &^ 0xffff) | (v & 0xffff), true
863 }
864
865 return val, false
866 }
867
868 func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
869 switch r.Variant & sym.RV_TYPE_MASK {
870 default:
871 ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
872 fallthrough
873
874 case sym.RV_NONE:
875 return t
876
877 case sym.RV_POWER_LO:
878 if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
879
880
881 var o1 uint32
882 if ctxt.Arch.ByteOrder == binary.BigEndian {
883 o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
884 } else {
885 o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
886 }
887 switch o1 >> 26 {
888 case 24,
889 26,
890 28:
891 if t>>16 != 0 {
892 goto overflow
893 }
894
895 default:
896 if int64(int16(t)) != t {
897 goto overflow
898 }
899 }
900 }
901
902 return int64(int16(t))
903
904 case sym.RV_POWER_HA:
905 t += 0x8000
906 fallthrough
907
908
909 case sym.RV_POWER_HI:
910 t >>= 16
911
912 if r.Variant&sym.RV_CHECK_OVERFLOW != 0 {
913
914
915 var o1 uint32
916 if ctxt.Arch.ByteOrder == binary.BigEndian {
917 o1 = binary.BigEndian.Uint32(s.P[r.Off-2:])
918 } else {
919 o1 = binary.LittleEndian.Uint32(s.P[r.Off:])
920 }
921 switch o1 >> 26 {
922 case 25,
923 27,
924 29:
925 if t>>16 != 0 {
926 goto overflow
927 }
928
929 default:
930 if int64(int16(t)) != t {
931 goto overflow
932 }
933 }
934 }
935
936 return int64(int16(t))
937
938 case sym.RV_POWER_DS:
939 var o1 uint32
940 if ctxt.Arch.ByteOrder == binary.BigEndian {
941 o1 = uint32(binary.BigEndian.Uint16(s.P[r.Off:]))
942 } else {
943 o1 = uint32(binary.LittleEndian.Uint16(s.P[r.Off:]))
944 }
945 if t&3 != 0 {
946 ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
947 }
948 if (r.Variant&sym.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
949 goto overflow
950 }
951 return int64(o1)&0x3 | int64(int16(t))
952 }
953
954 overflow:
955 ld.Errorf(s, "relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
956 return t
957 }
958
959 func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
960 if s.Plt() >= 0 {
961 return
962 }
963
964 ld.Adddynsym(ctxt, s)
965
966 if ctxt.IsELF {
967 plt := ctxt.Syms.Lookup(".plt", 0)
968 rela := ctxt.Syms.Lookup(".rela.plt", 0)
969 if plt.Size == 0 {
970 elfsetupplt(ctxt)
971 }
972
973
974 glink := ensureglinkresolver(ctxt)
975
976
977
978 r := glink.AddRel()
979
980 r.Sym = glink
981 r.Off = int32(glink.Size)
982 r.Siz = 4
983 r.Type = objabi.R_CALLPOWER
984 glink.AddUint32(ctxt.Arch, 0x48000000)
985
986
987
988
989
990
991
992 s.SetPlt(int32(plt.Size))
993
994 plt.Size += 8
995
996 rela.AddAddrPlus(ctxt.Arch, plt, int64(s.Plt()))
997 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_PPC64_JMP_SLOT)))
998 rela.AddUint64(ctxt.Arch, 0)
999 } else {
1000 ld.Errorf(s, "addpltsym: unsupported binary format")
1001 }
1002 }
1003
1004
1005 func ensureglinkresolver(ctxt *ld.Link) *sym.Symbol {
1006 glink := ctxt.Syms.Lookup(".glink", 0)
1007 if glink.Size != 0 {
1008 return glink
1009 }
1010
1011
1012
1013
1014
1015
1016
1017
1018 glink.AddUint32(ctxt.Arch, 0x7c0802a6)
1019 glink.AddUint32(ctxt.Arch, 0x429f0005)
1020 glink.AddUint32(ctxt.Arch, 0x7d6802a6)
1021 glink.AddUint32(ctxt.Arch, 0x7c0803a6)
1022
1023
1024
1025
1026
1027 glink.AddUint32(ctxt.Arch, 0x3800ffd0)
1028 glink.AddUint32(ctxt.Arch, 0x7c006214)
1029 glink.AddUint32(ctxt.Arch, 0x7c0b0050)
1030 glink.AddUint32(ctxt.Arch, 0x7800f082)
1031
1032
1033 r := glink.AddRel()
1034
1035 r.Off = int32(glink.Size)
1036 r.Sym = ctxt.Syms.Lookup(".plt", 0)
1037 r.Siz = 8
1038 r.Type = objabi.R_ADDRPOWER
1039
1040 glink.AddUint32(ctxt.Arch, 0x3d600000)
1041 glink.AddUint32(ctxt.Arch, 0x396b0000)
1042
1043
1044
1045 glink.AddUint32(ctxt.Arch, 0xe98b0000)
1046 glink.AddUint32(ctxt.Arch, 0xe96b0008)
1047
1048
1049 glink.AddUint32(ctxt.Arch, 0x7d8903a6)
1050 glink.AddUint32(ctxt.Arch, 0x4e800420)
1051
1052
1053
1054
1055
1056
1057 s := ctxt.Syms.Lookup(".dynamic", 0)
1058
1059 ld.Elfwritedynentsymplus(ctxt, s, ld.DT_PPC64_GLINK, glink, glink.Size-32)
1060
1061 return glink
1062 }
1063
1064 func asmb(ctxt *ld.Link) {
1065 if ctxt.Debugvlog != 0 {
1066 ctxt.Logf("%5.2f asmb\n", ld.Cputime())
1067 }
1068
1069 if ctxt.IsELF {
1070 ld.Asmbelfsetup()
1071 }
1072
1073 for _, sect := range ld.Segtext.Sections {
1074 ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
1075
1076 if sect.Name == ".text" {
1077 ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
1078 } else {
1079 ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
1080 }
1081 }
1082
1083 if ld.Segrodata.Filelen > 0 {
1084 if ctxt.Debugvlog != 0 {
1085 ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
1086 }
1087 ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
1088 ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
1089 }
1090 if ld.Segrelrodata.Filelen > 0 {
1091 if ctxt.Debugvlog != 0 {
1092 ctxt.Logf("%5.2f relrodatblk\n", ld.Cputime())
1093 }
1094 ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
1095 ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
1096 }
1097
1098 if ctxt.Debugvlog != 0 {
1099 ctxt.Logf("%5.2f datblk\n", ld.Cputime())
1100 }
1101
1102 ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
1103 ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
1104
1105 ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
1106 ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
1107 }
1108
1109 func asmb2(ctxt *ld.Link) {
1110
1111 ld.Symsize = 0
1112
1113 ld.Lcsize = 0
1114 symo := uint32(0)
1115 if !*ld.FlagS {
1116
1117 if ctxt.Debugvlog != 0 {
1118 ctxt.Logf("%5.2f sym\n", ld.Cputime())
1119 }
1120 switch ctxt.HeadType {
1121 default:
1122 if ctxt.IsELF {
1123 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
1124 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
1125 }
1126
1127 case objabi.Hplan9:
1128 symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
1129
1130 case objabi.Haix:
1131
1132 }
1133
1134 ctxt.Out.SeekSet(int64(symo))
1135 switch ctxt.HeadType {
1136 default:
1137 if ctxt.IsELF {
1138 if ctxt.Debugvlog != 0 {
1139 ctxt.Logf("%5.2f elfsym\n", ld.Cputime())
1140 }
1141 ld.Asmelfsym(ctxt)
1142 ctxt.Out.Flush()
1143 ctxt.Out.Write(ld.Elfstrdat)
1144
1145 if ctxt.LinkMode == ld.LinkExternal {
1146 ld.Elfemitreloc(ctxt)
1147 }
1148 }
1149
1150 case objabi.Hplan9:
1151 ld.Asmplan9sym(ctxt)
1152 ctxt.Out.Flush()
1153
1154 sym := ctxt.Syms.Lookup("pclntab", 0)
1155 if sym != nil {
1156 ld.Lcsize = int32(len(sym.P))
1157 ctxt.Out.Write(sym.P)
1158 ctxt.Out.Flush()
1159 }
1160
1161 case objabi.Haix:
1162
1163 ctxt.Out.Flush()
1164 }
1165 }
1166
1167 if ctxt.Debugvlog != 0 {
1168 ctxt.Logf("%5.2f header\n", ld.Cputime())
1169 }
1170 ctxt.Out.SeekSet(0)
1171 switch ctxt.HeadType {
1172 default:
1173 case objabi.Hplan9:
1174 ctxt.Out.Write32(0x647)
1175 ctxt.Out.Write32(uint32(ld.Segtext.Filelen))
1176 ctxt.Out.Write32(uint32(ld.Segdata.Filelen))
1177 ctxt.Out.Write32(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
1178 ctxt.Out.Write32(uint32(ld.Symsize))
1179 ctxt.Out.Write32(uint32(ld.Entryvalue(ctxt)))
1180 ctxt.Out.Write32(0)
1181 ctxt.Out.Write32(uint32(ld.Lcsize))
1182
1183 case objabi.Hlinux,
1184 objabi.Hfreebsd,
1185 objabi.Hnetbsd,
1186 objabi.Hopenbsd,
1187 objabi.Hnacl:
1188 ld.Asmbelf(ctxt, int64(symo))
1189
1190 case objabi.Haix:
1191 fileoff := uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
1192 fileoff = uint32(ld.Rnd(int64(fileoff), int64(*ld.FlagRound)))
1193 ld.Asmbxcoff(ctxt, int64(fileoff))
1194 }
1195
1196 ctxt.Out.Flush()
1197 if *ld.FlagC {
1198 fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
1199 fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
1200 fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
1201 fmt.Printf("symsize=%d\n", ld.Symsize)
1202 fmt.Printf("lcsize=%d\n", ld.Lcsize)
1203 fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
1204 }
1205 }
1206
View as plain text