Source file src/pkg/cmd/link/internal/amd64/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 amd64
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 "log"
40 )
41
42 func PADDR(x uint32) uint32 {
43 return x &^ 0x80000000
44 }
45
46 func Addcall(ctxt *ld.Link, s *sym.Symbol, t *sym.Symbol) int64 {
47 s.Attr |= sym.AttrReachable
48 i := s.Size
49 s.Size += 4
50 s.Grow(s.Size)
51 r := s.AddRel()
52 r.Sym = t
53 r.Off = int32(i)
54 r.Type = objabi.R_CALL
55 r.Siz = 4
56 return i + int64(r.Siz)
57 }
58
59 func gentext(ctxt *ld.Link) {
60 if !ctxt.DynlinkingGo() {
61 return
62 }
63 addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
64 if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
65
66
67 return
68 }
69 addmoduledata.Attr |= sym.AttrReachable
70 initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
71 initfunc.Type = sym.STEXT
72 initfunc.Attr |= sym.AttrLocal
73 initfunc.Attr |= sym.AttrReachable
74 o := func(op ...uint8) {
75 for _, op1 := range op {
76 initfunc.AddUint8(op1)
77 }
78 }
79
80
81
82 o(0x48, 0x8d, 0x3d)
83 initfunc.AddPCRelPlus(ctxt.Arch, ctxt.Moduledata, 0)
84
85
86 o(0xe8)
87 Addcall(ctxt, initfunc, addmoduledata)
88
89 o(0xc3)
90 if ctxt.BuildMode == ld.BuildModePlugin {
91 ctxt.Textp = append(ctxt.Textp, addmoduledata)
92 }
93 ctxt.Textp = append(ctxt.Textp, initfunc)
94 initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
95 initarray_entry.Attr |= sym.AttrReachable
96 initarray_entry.Attr |= sym.AttrLocal
97 initarray_entry.Type = sym.SINITARR
98 initarray_entry.AddAddr(ctxt.Arch, initfunc)
99 }
100
101 func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
102 targ := r.Sym
103
104 switch r.Type {
105 default:
106 if r.Type >= objabi.ElfRelocOffset {
107 ld.Errorf(s, "unexpected relocation type %d (%s)", r.Type, sym.RelocName(ctxt.Arch, r.Type))
108 return false
109 }
110
111
112 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_PC32):
113 if targ.Type == sym.SDYNIMPORT {
114 ld.Errorf(s, "unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ.Name)
115 }
116
117
118 if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
119 ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
120 }
121 r.Type = objabi.R_PCREL
122 r.Add += 4
123 return true
124
125 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_PC64):
126 if targ.Type == sym.SDYNIMPORT {
127 ld.Errorf(s, "unexpected R_X86_64_PC64 relocation for dynamic symbol %s", targ.Name)
128 }
129 if targ.Type == 0 || targ.Type == sym.SXREF {
130 ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
131 }
132 r.Type = objabi.R_PCREL
133 r.Add += 8
134 return true
135
136 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_PLT32):
137 r.Type = objabi.R_PCREL
138 r.Add += 4
139 if targ.Type == sym.SDYNIMPORT {
140 addpltsym(ctxt, targ)
141 r.Sym = ctxt.Syms.Lookup(".plt", 0)
142 r.Add += int64(targ.Plt())
143 }
144
145 return true
146
147 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_GOTPCREL),
148 objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_GOTPCRELX),
149 objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_REX_GOTPCRELX):
150 if targ.Type != sym.SDYNIMPORT {
151
152 if r.Off >= 2 && s.P[r.Off-2] == 0x8b {
153
154 s.P[r.Off-2] = 0x8d
155
156 r.Type = objabi.R_PCREL
157 r.Add += 4
158 return true
159 }
160 }
161
162
163
164 addgotsym(ctxt, targ)
165
166 r.Type = objabi.R_PCREL
167 r.Sym = ctxt.Syms.Lookup(".got", 0)
168 r.Add += 4
169 r.Add += int64(targ.Got())
170 return true
171
172 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_64):
173 if targ.Type == sym.SDYNIMPORT {
174 ld.Errorf(s, "unexpected R_X86_64_64 relocation for dynamic symbol %s", targ.Name)
175 }
176 r.Type = objabi.R_ADDR
177 return true
178
179
180 case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 0,
181 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED*2 + 0,
182 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_BRANCH*2 + 0:
183
184 r.Type = objabi.R_ADDR
185
186 if targ.Type == sym.SDYNIMPORT {
187 ld.Errorf(s, "unexpected reloc for dynamic symbol %s", targ.Name)
188 }
189 return true
190
191 case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1:
192 if targ.Type == sym.SDYNIMPORT {
193 addpltsym(ctxt, targ)
194 r.Sym = ctxt.Syms.Lookup(".plt", 0)
195 r.Add = int64(targ.Plt())
196 r.Type = objabi.R_PCREL
197 return true
198 }
199 fallthrough
200
201 case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 1,
202 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED*2 + 1,
203 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_1*2 + 1,
204 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_2*2 + 1,
205 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
206 r.Type = objabi.R_PCREL
207
208 if targ.Type == sym.SDYNIMPORT {
209 ld.Errorf(s, "unexpected pc-relative reloc for dynamic symbol %s", targ.Name)
210 }
211 return true
212
213 case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
214 if targ.Type != sym.SDYNIMPORT {
215
216
217 if r.Off < 2 || s.P[r.Off-2] != 0x8b {
218 ld.Errorf(s, "unexpected GOT_LOAD reloc for non-dynamic symbol %s", targ.Name)
219 return false
220 }
221
222 s.P[r.Off-2] = 0x8d
223 r.Type = objabi.R_PCREL
224 return true
225 }
226 fallthrough
227
228 case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_GOT*2 + 1:
229 if targ.Type != sym.SDYNIMPORT {
230 ld.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", targ.Name)
231 }
232 addgotsym(ctxt, targ)
233 r.Type = objabi.R_PCREL
234 r.Sym = ctxt.Syms.Lookup(".got", 0)
235 r.Add += int64(targ.Got())
236 return true
237 }
238
239 switch r.Type {
240 case objabi.R_CALL,
241 objabi.R_PCREL:
242 if targ.Type != sym.SDYNIMPORT {
243
244 return true
245 }
246 if ctxt.LinkMode == ld.LinkExternal {
247
248 return true
249 }
250
251
252 addpltsym(ctxt, targ)
253 r.Sym = ctxt.Syms.Lookup(".plt", 0)
254 r.Add = int64(targ.Plt())
255 return true
256
257 case objabi.R_ADDR:
258 if s.Type == sym.STEXT && ctxt.IsELF {
259 if ctxt.HeadType == objabi.Hsolaris {
260 addpltsym(ctxt, targ)
261 r.Sym = ctxt.Syms.Lookup(".plt", 0)
262 r.Add += int64(targ.Plt())
263 return true
264 }
265
266
267
268 addgotsym(ctxt, targ)
269
270 r.Sym = ctxt.Syms.Lookup(".got", 0)
271 r.Add += int64(targ.Got())
272 return true
273 }
274
275
276 if ctxt.BuildMode == ld.BuildModePIE && ctxt.LinkMode == ld.LinkInternal {
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308 switch s.Name {
309 case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
310 return false
311 }
312 } else {
313
314
315
316
317
318
319 if s.Type != sym.SDATA && s.Type != sym.SRODATA {
320 break
321 }
322 }
323
324 if ctxt.IsELF {
325
326
327
328 ld.Adddynsym(ctxt, targ)
329 rela := ctxt.Syms.Lookup(".rela", 0)
330 rela.AddAddrPlus(ctxt.Arch, s, int64(r.Off))
331 if r.Siz == 8 {
332 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_X86_64_64)))
333 } else {
334
335 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(targ.Dynid), uint32(elf.R_X86_64_32)))
336 }
337 rela.AddUint64(ctxt.Arch, uint64(r.Add))
338 r.Type = objabi.ElfRelocOffset
339 return true
340 }
341
342 if ctxt.HeadType == objabi.Hdarwin && s.Size == int64(ctxt.Arch.PtrSize) && r.Off == 0 {
343
344
345
346
347
348
349
350
351
352
353 ld.Adddynsym(ctxt, targ)
354
355 got := ctxt.Syms.Lookup(".got", 0)
356 s.Type = got.Type
357 s.Attr |= sym.AttrSubSymbol
358 s.Outer = got
359 s.Sub = got.Sub
360 got.Sub = s
361 s.Value = got.Size
362 got.AddUint64(ctxt.Arch, 0)
363 ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(targ.Dynid))
364 r.Type = objabi.ElfRelocOffset
365 return true
366 }
367 }
368
369 return false
370 }
371
372 func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
373 ctxt.Out.Write64(uint64(sectoff))
374
375 elfsym := r.Xsym.ElfsymForReloc()
376 switch r.Type {
377 default:
378 return false
379 case objabi.R_ADDR:
380 if r.Siz == 4 {
381 ctxt.Out.Write64(uint64(elf.R_X86_64_32) | uint64(elfsym)<<32)
382 } else if r.Siz == 8 {
383 ctxt.Out.Write64(uint64(elf.R_X86_64_64) | uint64(elfsym)<<32)
384 } else {
385 return false
386 }
387 case objabi.R_TLS_LE:
388 if r.Siz == 4 {
389 ctxt.Out.Write64(uint64(elf.R_X86_64_TPOFF32) | uint64(elfsym)<<32)
390 } else {
391 return false
392 }
393 case objabi.R_TLS_IE:
394 if r.Siz == 4 {
395 ctxt.Out.Write64(uint64(elf.R_X86_64_GOTTPOFF) | uint64(elfsym)<<32)
396 } else {
397 return false
398 }
399 case objabi.R_CALL:
400 if r.Siz == 4 {
401 if r.Xsym.Type == sym.SDYNIMPORT {
402 if ctxt.DynlinkingGo() {
403 ctxt.Out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
404 } else {
405 ctxt.Out.Write64(uint64(elf.R_X86_64_GOTPCREL) | uint64(elfsym)<<32)
406 }
407 } else {
408 ctxt.Out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32)
409 }
410 } else {
411 return false
412 }
413 case objabi.R_PCREL:
414 if r.Siz == 4 {
415 if r.Xsym.Type == sym.SDYNIMPORT && r.Xsym.ElfType() == elf.STT_FUNC {
416 ctxt.Out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
417 } else {
418 ctxt.Out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32)
419 }
420 } else {
421 return false
422 }
423 case objabi.R_GOTPCREL:
424 if r.Siz == 4 {
425 ctxt.Out.Write64(uint64(elf.R_X86_64_GOTPCREL) | uint64(elfsym)<<32)
426 } else {
427 return false
428 }
429 }
430
431 ctxt.Out.Write64(uint64(r.Xadd))
432 return true
433 }
434
435 func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
436 var v uint32
437
438 rs := r.Xsym
439
440 if rs.Type == sym.SHOSTOBJ || r.Type == objabi.R_PCREL || r.Type == objabi.R_GOTPCREL || r.Type == objabi.R_CALL {
441 if rs.Dynid < 0 {
442 ld.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
443 return false
444 }
445
446 v = uint32(rs.Dynid)
447 v |= 1 << 27
448 } else {
449 v = uint32(rs.Sect.Extnum)
450 if v == 0 {
451 ld.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Sect.Name, rs.Type, rs.Type)
452 return false
453 }
454 }
455
456 switch r.Type {
457 default:
458 return false
459
460 case objabi.R_ADDR:
461 v |= ld.MACHO_X86_64_RELOC_UNSIGNED << 28
462
463 case objabi.R_CALL:
464 v |= 1 << 24
465 v |= ld.MACHO_X86_64_RELOC_BRANCH << 28
466
467
468 case objabi.R_PCREL:
469 v |= 1 << 24
470 v |= ld.MACHO_X86_64_RELOC_SIGNED << 28
471 case objabi.R_GOTPCREL:
472 v |= 1 << 24
473 v |= ld.MACHO_X86_64_RELOC_GOT_LOAD << 28
474 }
475
476 switch r.Siz {
477 default:
478 return false
479
480 case 1:
481 v |= 0 << 25
482
483 case 2:
484 v |= 1 << 25
485
486 case 4:
487 v |= 2 << 25
488
489 case 8:
490 v |= 3 << 25
491 }
492
493 out.Write32(uint32(sectoff))
494 out.Write32(v)
495 return true
496 }
497
498 func pereloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
499 var v uint32
500
501 rs := r.Xsym
502
503 if rs.Dynid < 0 {
504 ld.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", r.Type, sym.RelocName(arch, r.Type), rs.Name, rs.Type, rs.Type)
505 return false
506 }
507
508 out.Write32(uint32(sectoff))
509 out.Write32(uint32(rs.Dynid))
510
511 switch r.Type {
512 default:
513 return false
514
515 case objabi.R_DWARFSECREF:
516 v = ld.IMAGE_REL_AMD64_SECREL
517
518 case objabi.R_ADDR:
519 if r.Siz == 8 {
520 v = ld.IMAGE_REL_AMD64_ADDR64
521 } else {
522 v = ld.IMAGE_REL_AMD64_ADDR32
523 }
524
525 case objabi.R_CALL,
526 objabi.R_PCREL:
527 v = ld.IMAGE_REL_AMD64_REL32
528 }
529
530 out.Write16(uint16(v))
531
532 return true
533 }
534
535 func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
536 return val, false
537 }
538
539 func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
540 log.Fatalf("unexpected relocation variant")
541 return t
542 }
543
544 func elfsetupplt(ctxt *ld.Link) {
545 plt := ctxt.Syms.Lookup(".plt", 0)
546 got := ctxt.Syms.Lookup(".got.plt", 0)
547 if plt.Size == 0 {
548
549 plt.AddUint8(0xff)
550
551 plt.AddUint8(0x35)
552 plt.AddPCRelPlus(ctxt.Arch, got, 8)
553
554
555 plt.AddUint8(0xff)
556
557 plt.AddUint8(0x25)
558 plt.AddPCRelPlus(ctxt.Arch, got, 16)
559
560
561 plt.AddUint32(ctxt.Arch, 0x00401f0f)
562
563
564 got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0)
565
566 got.AddUint64(ctxt.Arch, 0)
567 got.AddUint64(ctxt.Arch, 0)
568 }
569 }
570
571 func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
572 if s.Plt() >= 0 {
573 return
574 }
575
576 ld.Adddynsym(ctxt, s)
577
578 if ctxt.IsELF {
579 plt := ctxt.Syms.Lookup(".plt", 0)
580 got := ctxt.Syms.Lookup(".got.plt", 0)
581 rela := ctxt.Syms.Lookup(".rela.plt", 0)
582 if plt.Size == 0 {
583 elfsetupplt(ctxt)
584 }
585
586
587 plt.AddUint8(0xff)
588
589 plt.AddUint8(0x25)
590 plt.AddPCRelPlus(ctxt.Arch, got, got.Size)
591
592
593 got.AddAddrPlus(ctxt.Arch, plt, plt.Size)
594
595
596 plt.AddUint8(0x68)
597
598 plt.AddUint32(ctxt.Arch, uint32((got.Size-24-8)/8))
599
600
601 plt.AddUint8(0xe9)
602
603 plt.AddUint32(ctxt.Arch, uint32(-(plt.Size + 4)))
604
605
606 rela.AddAddrPlus(ctxt.Arch, got, got.Size-8)
607
608 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_X86_64_JMP_SLOT)))
609 rela.AddUint64(ctxt.Arch, 0)
610
611 s.SetPlt(int32(plt.Size - 16))
612 } else if ctxt.HeadType == objabi.Hdarwin {
613
614
615
616
617
618
619
620
621
622
623 addgotsym(ctxt, s)
624 plt := ctxt.Syms.Lookup(".plt", 0)
625
626 ctxt.Syms.Lookup(".linkedit.plt", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
627
628
629 s.SetPlt(int32(plt.Size))
630
631 plt.AddUint8(0xff)
632 plt.AddUint8(0x25)
633 plt.AddPCRelPlus(ctxt.Arch, ctxt.Syms.Lookup(".got", 0), int64(s.Got()))
634 } else {
635 ld.Errorf(s, "addpltsym: unsupported binary format")
636 }
637 }
638
639 func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
640 if s.Got() >= 0 {
641 return
642 }
643
644 ld.Adddynsym(ctxt, s)
645 got := ctxt.Syms.Lookup(".got", 0)
646 s.SetGot(int32(got.Size))
647 got.AddUint64(ctxt.Arch, 0)
648
649 if ctxt.IsELF {
650 rela := ctxt.Syms.Lookup(".rela", 0)
651 rela.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
652 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_X86_64_GLOB_DAT)))
653 rela.AddUint64(ctxt.Arch, 0)
654 } else if ctxt.HeadType == objabi.Hdarwin {
655 ctxt.Syms.Lookup(".linkedit.got", 0).AddUint32(ctxt.Arch, uint32(s.Dynid))
656 } else {
657 ld.Errorf(s, "addgotsym: unsupported binary format")
658 }
659 }
660
661 func asmb(ctxt *ld.Link) {
662 if ctxt.Debugvlog != 0 {
663 ctxt.Logf("%5.2f asmb\n", ld.Cputime())
664 }
665
666 if ctxt.Debugvlog != 0 {
667 ctxt.Logf("%5.2f codeblk\n", ld.Cputime())
668 }
669
670 if ctxt.IsELF {
671 ld.Asmbelfsetup()
672 }
673
674 sect := ld.Segtext.Sections[0]
675 ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
676
677 ld.CodeblkPad(ctxt, int64(sect.Vaddr), int64(sect.Length), []byte{0xCC})
678 for _, sect = range ld.Segtext.Sections[1:] {
679 ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
680 ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
681 }
682
683 if ld.Segrodata.Filelen > 0 {
684 if ctxt.Debugvlog != 0 {
685 ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
686 }
687 ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
688 ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
689 }
690 if ld.Segrelrodata.Filelen > 0 {
691 if ctxt.Debugvlog != 0 {
692 ctxt.Logf("%5.2f relrodatblk\n", ld.Cputime())
693 }
694 ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
695 ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
696 }
697
698 if ctxt.Debugvlog != 0 {
699 ctxt.Logf("%5.2f datblk\n", ld.Cputime())
700 }
701
702 ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
703 ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
704
705 ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
706 ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
707 }
708
709 func asmb2(ctxt *ld.Link) {
710 machlink := int64(0)
711 if ctxt.HeadType == objabi.Hdarwin {
712 machlink = ld.Domacholink(ctxt)
713 }
714
715 switch ctxt.HeadType {
716 default:
717 ld.Errorf(nil, "unknown header type %v", ctxt.HeadType)
718 fallthrough
719
720 case objabi.Hplan9:
721 break
722
723 case objabi.Hdarwin:
724 ld.Flag8 = true
725
726 case objabi.Hlinux,
727 objabi.Hfreebsd,
728 objabi.Hnetbsd,
729 objabi.Hopenbsd,
730 objabi.Hdragonfly,
731 objabi.Hsolaris:
732 ld.Flag8 = true
733
734 case objabi.Hnacl,
735 objabi.Hwindows:
736 break
737 }
738
739 ld.Symsize = 0
740 ld.Spsize = 0
741 ld.Lcsize = 0
742 symo := int64(0)
743 if !*ld.FlagS {
744 if ctxt.Debugvlog != 0 {
745 ctxt.Logf("%5.2f sym\n", ld.Cputime())
746 }
747 switch ctxt.HeadType {
748 default:
749 case objabi.Hplan9:
750 *ld.FlagS = true
751 symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen)
752
753 case objabi.Hdarwin:
754 symo = int64(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
755
756 case objabi.Hlinux,
757 objabi.Hfreebsd,
758 objabi.Hnetbsd,
759 objabi.Hopenbsd,
760 objabi.Hdragonfly,
761 objabi.Hsolaris,
762 objabi.Hnacl:
763 symo = int64(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
764 symo = ld.Rnd(symo, int64(*ld.FlagRound))
765
766 case objabi.Hwindows:
767 symo = int64(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
768 symo = ld.Rnd(symo, ld.PEFILEALIGN)
769 }
770
771 ctxt.Out.SeekSet(symo)
772 switch ctxt.HeadType {
773 default:
774 if ctxt.IsELF {
775 ctxt.Out.SeekSet(symo)
776 ld.Asmelfsym(ctxt)
777 ctxt.Out.Flush()
778 ctxt.Out.Write(ld.Elfstrdat)
779
780 if ctxt.Debugvlog != 0 {
781 ctxt.Logf("%5.2f dwarf\n", ld.Cputime())
782 }
783
784 if ctxt.LinkMode == ld.LinkExternal {
785 ld.Elfemitreloc(ctxt)
786 }
787 }
788
789 case objabi.Hplan9:
790 ld.Asmplan9sym(ctxt)
791 ctxt.Out.Flush()
792
793 sym := ctxt.Syms.Lookup("pclntab", 0)
794 if sym != nil {
795 ld.Lcsize = int32(len(sym.P))
796 ctxt.Out.Write(sym.P)
797 ctxt.Out.Flush()
798 }
799
800 case objabi.Hwindows:
801 if ctxt.Debugvlog != 0 {
802 ctxt.Logf("%5.2f dwarf\n", ld.Cputime())
803 }
804
805 case objabi.Hdarwin:
806 if ctxt.LinkMode == ld.LinkExternal {
807 ld.Machoemitreloc(ctxt)
808 }
809 }
810 }
811
812 if ctxt.Debugvlog != 0 {
813 ctxt.Logf("%5.2f headr\n", ld.Cputime())
814 }
815 ctxt.Out.SeekSet(0)
816 switch ctxt.HeadType {
817 default:
818 case objabi.Hplan9:
819 magic := int32(4*26*26 + 7)
820
821 magic |= 0x00008000
822 ctxt.Out.Write32b(uint32(magic))
823 ctxt.Out.Write32b(uint32(ld.Segtext.Filelen))
824 ctxt.Out.Write32b(uint32(ld.Segdata.Filelen))
825 ctxt.Out.Write32b(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
826 ctxt.Out.Write32b(uint32(ld.Symsize))
827 vl := ld.Entryvalue(ctxt)
828 ctxt.Out.Write32b(PADDR(uint32(vl)))
829 ctxt.Out.Write32b(uint32(ld.Spsize))
830 ctxt.Out.Write32b(uint32(ld.Lcsize))
831 ctxt.Out.Write64b(uint64(vl))
832
833 case objabi.Hdarwin:
834 ld.Asmbmacho(ctxt)
835
836 case objabi.Hlinux,
837 objabi.Hfreebsd,
838 objabi.Hnetbsd,
839 objabi.Hopenbsd,
840 objabi.Hdragonfly,
841 objabi.Hsolaris,
842 objabi.Hnacl:
843 ld.Asmbelf(ctxt, symo)
844
845 case objabi.Hwindows:
846 ld.Asmbpe(ctxt)
847 }
848
849 ctxt.Out.Flush()
850 }
851
852 func tlsIEtoLE(s *sym.Symbol, off, size int) {
853
854
855
856
857
858
859
860 if off < 3 {
861 log.Fatal("R_X86_64_GOTTPOFF reloc not preceded by MOVQ or ADDQ instruction")
862 }
863 op := s.P[off-3 : off]
864 reg := op[2] >> 3
865
866 if op[1] == 0x8b || reg == 4 {
867
868 if op[0] == 0x4c {
869 op[0] = 0x49
870 } else if size == 4 && op[0] == 0x44 {
871 op[0] = 0x41
872 }
873 if op[1] == 0x8b {
874 op[1] = 0xc7
875 } else {
876 op[1] = 0x81
877 }
878 op[2] = 0xc0 | reg
879 } else {
880
881
882
883
884 log.Fatalf("expected TLS IE op to be MOVQ, got %v", op)
885 }
886 }
887
View as plain text