1
2
3
4
5 package ld
6
7 import (
8 "bytes"
9 "encoding/binary"
10 "fmt"
11 "math/bits"
12 "os"
13 "path/filepath"
14 "sort"
15 "strings"
16 "sync"
17
18 "cmd/internal/objabi"
19 "cmd/link/internal/loader"
20 "cmd/link/internal/sym"
21 )
22
23
24
25
26
27
28 const (
29
30
31
32 XCOFFHDRRESERVE = FILHSZ_64 + AOUTHSZ_EXEC64 + SCNHSZ_64*23
33
34
35
36 XCOFFSECTALIGN int64 = 64
37
38
39
40
41
42
43 XCOFFTEXTBASE = 0x100000000
44 XCOFFDATABASE = 0x200000000
45 )
46
47
48 type XcoffFileHdr64 struct {
49 Fmagic uint16
50 Fnscns uint16
51 Ftimedat int32
52 Fsymptr uint64
53 Fopthdr uint16
54 Fflags uint16
55 Fnsyms int32
56 }
57
58 const (
59 U64_TOCMAGIC = 0767
60 )
61
62
63 const (
64 F_RELFLG = 0x0001
65 F_EXEC = 0x0002
66 F_LNNO = 0x0004
67 F_FDPR_PROF = 0x0010
68 F_FDPR_OPTI = 0x0020
69 F_DSA = 0x0040
70 F_VARPG = 0x0100
71 F_DYNLOAD = 0x1000
72 F_SHROBJ = 0x2000
73 F_LOADONLY = 0x4000
74 )
75
76
77 type XcoffAoutHdr64 struct {
78 Omagic int16
79 Ovstamp int16
80 Odebugger uint32
81 Otextstart uint64
82 Odatastart uint64
83 Otoc uint64
84 Osnentry int16
85 Osntext int16
86 Osndata int16
87 Osntoc int16
88 Osnloader int16
89 Osnbss int16
90 Oalgntext int16
91 Oalgndata int16
92 Omodtype [2]byte
93 Ocpuflag uint8
94 Ocputype uint8
95 Otextpsize uint8
96 Odatapsize uint8
97 Ostackpsize uint8
98 Oflags uint8
99 Otsize uint64
100 Odsize uint64
101 Obsize uint64
102 Oentry uint64
103 Omaxstack uint64
104 Omaxdata uint64
105 Osntdata int16
106 Osntbss int16
107 Ox64flags uint16
108 Oresv3a int16
109 Oresv3 [2]int32
110 }
111
112
113 type XcoffScnHdr64 struct {
114 Sname [8]byte
115 Spaddr uint64
116 Svaddr uint64
117 Ssize uint64
118 Sscnptr uint64
119 Srelptr uint64
120 Slnnoptr uint64
121 Snreloc uint32
122 Snlnno uint32
123 Sflags uint32
124 }
125
126
127 const (
128 STYP_DWARF = 0x0010
129 STYP_TEXT = 0x0020
130 STYP_DATA = 0x0040
131 STYP_BSS = 0x0080
132 STYP_EXCEPT = 0x0100
133 STYP_INFO = 0x0200
134 STYP_TDATA = 0x0400
135 STYP_TBSS = 0x0800
136 STYP_LOADER = 0x1000
137 STYP_DEBUG = 0x2000
138 STYP_TYPCHK = 0x4000
139 STYP_OVRFLO = 0x8000
140 )
141 const (
142 SSUBTYP_DWINFO = 0x10000
143 SSUBTYP_DWLINE = 0x20000
144 SSUBTYP_DWPBNMS = 0x30000
145 SSUBTYP_DWPBTYP = 0x40000
146 SSUBTYP_DWARNGE = 0x50000
147 SSUBTYP_DWABREV = 0x60000
148 SSUBTYP_DWSTR = 0x70000
149 SSUBTYP_DWRNGES = 0x80000
150 SSUBTYP_DWLOC = 0x90000
151 SSUBTYP_DWFRAME = 0xA0000
152 SSUBTYP_DWMAC = 0xB0000
153 )
154
155
156 const (
157 FILHSZ_32 = 20
158 FILHSZ_64 = 24
159 AOUTHSZ_EXEC32 = 72
160 AOUTHSZ_EXEC64 = 120
161 SCNHSZ_32 = 40
162 SCNHSZ_64 = 72
163 LDHDRSZ_32 = 32
164 LDHDRSZ_64 = 56
165 LDSYMSZ_64 = 24
166 RELSZ_64 = 14
167 )
168
169
170 type xcoffSym interface {
171 }
172
173
174 type XcoffSymEnt64 struct {
175 Nvalue uint64
176 Noffset uint32
177 Nscnum int16
178 Ntype uint16
179 Nsclass uint8
180 Nnumaux int8
181 }
182
183 const SYMESZ = 18
184
185 const (
186
187 N_DEBUG = -2
188 N_ABS = -1
189 N_UNDEF = 0
190
191
192 SYM_V_INTERNAL = 0x1000
193 SYM_V_HIDDEN = 0x2000
194 SYM_V_PROTECTED = 0x3000
195 SYM_V_EXPORTED = 0x4000
196 SYM_TYPE_FUNC = 0x0020
197 )
198
199
200 const (
201 C_NULL = 0
202 C_EXT = 2
203 C_STAT = 3
204 C_BLOCK = 100
205 C_FCN = 101
206 C_FILE = 103
207 C_HIDEXT = 107
208 C_BINCL = 108
209 C_EINCL = 109
210 C_WEAKEXT = 111
211 C_DWARF = 112
212 C_GSYM = 128
213 C_LSYM = 129
214 C_PSYM = 130
215 C_RSYM = 131
216 C_RPSYM = 132
217 C_STSYM = 133
218 C_BCOMM = 135
219 C_ECOML = 136
220 C_ECOMM = 137
221 C_DECL = 140
222 C_ENTRY = 141
223 C_FUN = 142
224 C_BSTAT = 143
225 C_ESTAT = 144
226 C_GTLS = 145
227 C_STTLS = 146
228 )
229
230
231 type XcoffAuxFile64 struct {
232 Xzeroes uint32
233 Xoffset uint32
234 X_pad1 [6]byte
235 Xftype uint8
236 X_pad2 [2]byte
237 Xauxtype uint8
238 }
239
240
241 type XcoffAuxFcn64 struct {
242 Xlnnoptr uint64
243 Xfsize uint32
244 Xendndx uint32
245 Xpad uint8
246 Xauxtype uint8
247 }
248
249
250 type XcoffAuxCSect64 struct {
251 Xscnlenlo uint32
252 Xparmhash uint32
253 Xsnhash uint16
254 Xsmtyp uint8
255 Xsmclas uint8
256 Xscnlenhi uint32
257 Xpad uint8
258 Xauxtype uint8
259 }
260
261
262 type XcoffAuxDWARF64 struct {
263 Xscnlen uint64
264 X_pad [9]byte
265 Xauxtype uint8
266 }
267
268
269 const (
270 _AUX_EXCEPT = 255
271 _AUX_FCN = 254
272 _AUX_SYM = 253
273 _AUX_FILE = 252
274 _AUX_CSECT = 251
275 _AUX_SECT = 250
276 )
277
278
279 const (
280 XFT_FN = 0
281 XFT_CT = 1
282 XFT_CV = 2
283 XFT_CD = 128
284
285 )
286
287
288 const (
289 XTY_ER = 0
290 XTY_SD = 1
291 XTY_LD = 2
292 XTY_CM = 3
293 XTY_WK = 0x8
294 XTY_EXP = 0x10
295 XTY_ENT = 0x20
296 XTY_IMP = 0x40
297 )
298
299
300 const (
301 XMC_PR = 0
302 XMC_RO = 1
303 XMC_DB = 2
304 XMC_TC = 3
305 XMC_UA = 4
306 XMC_RW = 5
307 XMC_GL = 6
308 XMC_XO = 7
309 XMC_SV = 8
310 XMC_BS = 9
311 XMC_DS = 10
312 XMC_UC = 11
313 XMC_TC0 = 15
314 XMC_TD = 16
315 XMC_SV64 = 17
316 XMC_SV3264 = 18
317 XMC_TL = 20
318 XMC_UL = 21
319 XMC_TE = 22
320 )
321
322
323 type XcoffLdHdr64 struct {
324 Lversion int32
325 Lnsyms int32
326 Lnreloc int32
327 Listlen uint32
328 Lnimpid int32
329 Lstlen uint32
330 Limpoff uint64
331 Lstoff uint64
332 Lsymoff uint64
333 Lrldoff uint64
334 }
335
336
337 type XcoffLdSym64 struct {
338 Lvalue uint64
339 Loffset uint32
340 Lscnum int16
341 Lsmtype int8
342 Lsmclas int8
343 Lifile int32
344 Lparm uint32
345 }
346
347 type xcoffLoaderSymbol struct {
348 sym loader.Sym
349 smtype int8
350 smclas int8
351 }
352
353 type XcoffLdImportFile64 struct {
354 Limpidpath string
355 Limpidbase string
356 Limpidmem string
357 }
358
359 type XcoffLdRel64 struct {
360 Lvaddr uint64
361 Lrtype uint16
362 Lrsecnm int16
363 Lsymndx int32
364 }
365
366
367 type xcoffLoaderReloc struct {
368 sym loader.Sym
369 roff int32
370 rtype uint16
371 symndx int32
372 }
373
374 const (
375 XCOFF_R_POS = 0x00
376 XCOFF_R_NEG = 0x01
377 XCOFF_R_REL = 0x02
378 XCOFF_R_TOC = 0x03
379 XCOFF_R_TRL = 0x12
380
381 XCOFF_R_TRLA = 0x13
382 XCOFF_R_GL = 0x05
383 XCOFF_R_TCL = 0x06
384 XCOFF_R_RL = 0x0C
385 XCOFF_R_RLA = 0x0D
386 XCOFF_R_REF = 0x0F
387 XCOFF_R_BA = 0x08
388 XCOFF_R_RBA = 0x18
389 XCOFF_R_BR = 0x0A
390 XCOFF_R_RBR = 0x1A
391
392 XCOFF_R_TLS = 0x20
393 XCOFF_R_TLS_IE = 0x21
394 XCOFF_R_TLS_LD = 0x22
395 XCOFF_R_TLS_LE = 0x23
396 XCOFF_R_TLSM = 0x24
397 XCOFF_R_TLSML = 0x25
398
399 XCOFF_R_TOCU = 0x30
400 XCOFF_R_TOCL = 0x31
401 )
402
403 type XcoffLdStr64 struct {
404 size uint16
405 name string
406 }
407
408
409 type xcoffFile struct {
410 xfhdr XcoffFileHdr64
411 xahdr XcoffAoutHdr64
412 sections []*XcoffScnHdr64
413 sectText *XcoffScnHdr64
414 sectData *XcoffScnHdr64
415 sectBss *XcoffScnHdr64
416 stringTable xcoffStringTable
417 sectNameToScnum map[string]int16
418 loaderSize uint64
419 symtabOffset int64
420 symbolCount uint32
421 symtabSym []xcoffSym
422 dynLibraries map[string]int
423 loaderSymbols []*xcoffLoaderSymbol
424 loaderReloc []*xcoffLoaderReloc
425 sync.Mutex
426 }
427
428
429 var (
430 xfile xcoffFile
431 )
432
433
434 type xcoffStringTable struct {
435 strings []string
436 stringsLen int
437 }
438
439
440 func (t *xcoffStringTable) size() int {
441
442 return t.stringsLen + 4
443 }
444
445
446 func (t *xcoffStringTable) add(str string) int {
447 off := t.size()
448 t.strings = append(t.strings, str)
449 t.stringsLen += len(str) + 1
450 return off
451 }
452
453
454 func (t *xcoffStringTable) write(out *OutBuf) {
455 out.Write32(uint32(t.size()))
456 for _, s := range t.strings {
457 out.WriteString(s)
458 out.Write8(0)
459 }
460 }
461
462
463 func (sect *XcoffScnHdr64) write(ctxt *Link) {
464 binary.Write(ctxt.Out, binary.BigEndian, sect)
465 ctxt.Out.Write32(0)
466 }
467
468
469 func (f *xcoffFile) addSection(name string, addr uint64, size uint64, fileoff uint64, flags uint32) *XcoffScnHdr64 {
470 sect := &XcoffScnHdr64{
471 Spaddr: addr,
472 Svaddr: addr,
473 Ssize: size,
474 Sscnptr: fileoff,
475 Sflags: flags,
476 }
477 copy(sect.Sname[:], name)
478 f.sections = append(f.sections, sect)
479 f.sectNameToScnum[name] = int16(len(f.sections))
480 return sect
481 }
482
483
484
485
486 func (f *xcoffFile) addDwarfSection(s *sym.Section) *XcoffScnHdr64 {
487 newName, subtype := xcoffGetDwarfSubtype(s.Name)
488 return f.addSection(newName, 0, s.Length, s.Seg.Fileoff+s.Vaddr-s.Seg.Vaddr, STYP_DWARF|subtype)
489 }
490
491
492
493 func xcoffGetDwarfSubtype(str string) (string, uint32) {
494 switch str {
495 default:
496 Exitf("unknown DWARF section name for XCOFF: %s", str)
497 case ".debug_abbrev":
498 return ".dwabrev", SSUBTYP_DWABREV
499 case ".debug_info":
500 return ".dwinfo", SSUBTYP_DWINFO
501 case ".debug_frame":
502 return ".dwframe", SSUBTYP_DWFRAME
503 case ".debug_line":
504 return ".dwline", SSUBTYP_DWLINE
505 case ".debug_loc":
506 return ".dwloc", SSUBTYP_DWLOC
507 case ".debug_pubnames":
508 return ".dwpbnms", SSUBTYP_DWPBNMS
509 case ".debug_pubtypes":
510 return ".dwpbtyp", SSUBTYP_DWPBTYP
511 case ".debug_ranges":
512 return ".dwrnges", SSUBTYP_DWRNGES
513 }
514
515 return "", 0
516 }
517
518
519 func (f *xcoffFile) getXCOFFscnum(sect *sym.Section) int16 {
520 switch sect.Seg {
521 case &Segtext:
522 return f.sectNameToScnum[".text"]
523 case &Segdata:
524 if sect.Name == ".noptrbss" || sect.Name == ".bss" {
525 return f.sectNameToScnum[".bss"]
526 }
527 if sect.Name == ".tbss" {
528 return f.sectNameToScnum[".tbss"]
529 }
530 return f.sectNameToScnum[".data"]
531 case &Segdwarf:
532 name, _ := xcoffGetDwarfSubtype(sect.Name)
533 return f.sectNameToScnum[name]
534 case &Segrelrodata:
535 return f.sectNameToScnum[".data"]
536 }
537 Errorf("getXCOFFscnum not implemented for section %s", sect.Name)
538 return -1
539 }
540
541
542
543 func Xcoffinit(ctxt *Link) {
544 xfile.dynLibraries = make(map[string]int)
545
546 HEADR = int32(Rnd(XCOFFHDRRESERVE, XCOFFSECTALIGN))
547 if *FlagRound != -1 {
548 Errorf("-R not available on AIX")
549 }
550 *FlagRound = XCOFFSECTALIGN
551 if *FlagTextAddr != -1 {
552 Errorf("-T not available on AIX")
553 }
554 *FlagTextAddr = Rnd(XCOFFTEXTBASE, *FlagRound) + int64(HEADR)
555 }
556
557
558
559
560 type xcoffSymSrcFile struct {
561 name string
562 file *XcoffSymEnt64
563 csectAux *XcoffAuxCSect64
564 csectSymNb uint64
565 csectVAStart int64
566 csectVAEnd int64
567 }
568
569 var (
570 currDwscnoff = make(map[string]uint64)
571 currSymSrcFile xcoffSymSrcFile
572 outerSymSize = make(map[string]int64)
573 )
574
575
576
577 func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
578 if size == 0 {
579 return
580 }
581
582
583 ldr := ctxt.loader
584 switch stype {
585 default:
586 Errorf("unknown XCOFF outer symbol for type %s", stype.String())
587 case sym.SRODATA, sym.SRODATARELRO, sym.SFUNCTAB, sym.SSTRING:
588
589 case sym.STYPERELRO:
590 if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
591
592 tsize := ldr.SymSize(ldr.Lookup("runtime.types", 0))
593 outerSymSize["typerel.*"] = size - tsize
594 return
595 }
596 fallthrough
597 case sym.STYPE:
598 if !ctxt.DynlinkingGo() {
599
600 tsize := ldr.SymSize(ldr.Lookup("runtime.types", 0))
601 outerSymSize["type:*"] = size - tsize
602 }
603 case sym.SGOSTRING:
604 outerSymSize["go:string.*"] = size
605 case sym.SGOFUNC:
606 if !ctxt.DynlinkingGo() {
607 outerSymSize["go:func.*"] = size
608 }
609 case sym.SGOFUNCRELRO:
610 outerSymSize["go:funcrel.*"] = size
611 case sym.SGCBITS:
612 outerSymSize["runtime.gcbits.*"] = size
613 case sym.SPCLNTAB:
614 outerSymSize["runtime.pclntab"] = size
615 }
616 }
617
618
619 func (f *xcoffFile) addSymbol(sym xcoffSym) {
620 f.symtabSym = append(f.symtabSym, sym)
621 f.symbolCount++
622 }
623
624
625 func xcoffAlign(ldr *loader.Loader, x loader.Sym, t SymbolType) uint8 {
626 align := ldr.SymAlign(x)
627 if align == 0 {
628 if t == TextSym {
629 align = int32(Funcalign)
630 } else {
631 align = symalign(ldr, x)
632 }
633 }
634 return logBase2(int(align))
635 }
636
637
638 func logBase2(a int) uint8 {
639 return uint8(bits.Len(uint(a)) - 1)
640 }
641
642
643
644
645
646
647
648
649
650 func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint64, extnum int16) {
651 ldr := ctxt.loader
652
653 s := &XcoffSymEnt64{
654 Noffset: uint32(f.stringTable.add(".file")),
655 Nsclass: C_FILE,
656 Nscnum: N_DEBUG,
657 Ntype: 0,
658 Nnumaux: 1,
659 }
660 f.addSymbol(s)
661 currSymSrcFile.file = s
662
663
664 auxf := &XcoffAuxFile64{
665 Xoffset: uint32(f.stringTable.add(name)),
666 Xftype: XFT_FN,
667 Xauxtype: _AUX_FILE,
668 }
669 f.addSymbol(auxf)
670
671
672 for _, sect := range Segdwarf.Sections {
673 var dwsize uint64
674 if ctxt.LinkMode == LinkInternal {
675
676
677 dwsize = getDwsectCUSize(sect.Name, name)
678
679 if sect.Name == ".debug_abbrev" {
680 dwsize = uint64(ldr.SymSize(loader.Sym(sect.Sym)))
681
682 }
683 } else {
684
685 dwsize = sect.Length
686 }
687
688
689 name, _ := xcoffGetDwarfSubtype(sect.Name)
690 s := &XcoffSymEnt64{
691 Nvalue: currDwscnoff[sect.Name],
692 Noffset: uint32(f.stringTable.add(name)),
693 Nsclass: C_DWARF,
694 Nscnum: f.getXCOFFscnum(sect),
695 Nnumaux: 1,
696 }
697
698 if currSymSrcFile.csectAux == nil {
699
700
701
702 ldr.SetSymDynid(loader.Sym(sect.Sym), int32(f.symbolCount))
703
704 if sect.Name == ".debug_frame" && ctxt.LinkMode != LinkExternal {
705
706 dwsize += 48
707 }
708 }
709
710 f.addSymbol(s)
711
712
713 if sect.Name != ".debug_abbrev" {
714 currDwscnoff[sect.Name] += dwsize
715 }
716
717
718 auxd := &XcoffAuxDWARF64{
719 Xscnlen: dwsize,
720 Xauxtype: _AUX_SECT,
721 }
722
723 f.addSymbol(auxd)
724 }
725
726
727
728
729 if extnum != 1 {
730 Exitf("XCOFF symtab: A new file was detected with its first symbol not in .text")
731 }
732
733 currSymSrcFile.csectSymNb = uint64(f.symbolCount)
734
735
736 s = &XcoffSymEnt64{
737 Nvalue: firstEntry,
738 Nscnum: extnum,
739 Nsclass: C_HIDEXT,
740 Ntype: 0,
741 Nnumaux: 1,
742 }
743 f.addSymbol(s)
744
745 aux := &XcoffAuxCSect64{
746 Xsmclas: XMC_PR,
747 Xsmtyp: XTY_SD | logBase2(Funcalign)<<3,
748 Xauxtype: _AUX_CSECT,
749 }
750 f.addSymbol(aux)
751
752 currSymSrcFile.csectAux = aux
753 currSymSrcFile.csectVAStart = int64(firstEntry)
754 currSymSrcFile.csectVAEnd = int64(firstEntry)
755 }
756
757
758
759
760 func (f *xcoffFile) updatePreviousFile(ctxt *Link, last bool) {
761
762 if currSymSrcFile.file == nil {
763 return
764 }
765
766
767 cfile := currSymSrcFile.file
768 if last {
769 cfile.Nvalue = 0xFFFFFFFFFFFFFFFF
770 } else {
771 cfile.Nvalue = uint64(f.symbolCount)
772 }
773
774
775 aux := currSymSrcFile.csectAux
776 csectSize := currSymSrcFile.csectVAEnd - currSymSrcFile.csectVAStart
777 aux.Xscnlenlo = uint32(csectSize & 0xFFFFFFFF)
778 aux.Xscnlenhi = uint32(csectSize >> 32)
779 }
780
781
782
783
784 func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x loader.Sym) []xcoffSym {
785
786 syms := []xcoffSym{}
787
788
789 ldr := ctxt.loader
790 name := ldr.SymName(x)
791 if strings.Contains(name, "-tramp") || strings.HasPrefix(name, "runtime.text.") {
792
793
794
795 } else if ldr.SymPkg(x) == "" {
796
797 if currSymSrcFile.name != "" {
798 Exitf("undefined global symbol found inside another file")
799 }
800 } else {
801
802 if currSymSrcFile.name != ldr.SymPkg(x) {
803 if ctxt.LinkMode == LinkInternal {
804
805 xfile.updatePreviousFile(ctxt, false)
806 currSymSrcFile.name = ldr.SymPkg(x)
807 f.writeSymbolNewFile(ctxt, ldr.SymPkg(x), uint64(ldr.SymValue(x)), xfile.getXCOFFscnum(ldr.SymSect(x)))
808 } else {
809
810
811
812
813
814
815
816 if currSymSrcFile.name == "" {
817 currSymSrcFile.name = ldr.SymPkg(x)
818 f.writeSymbolNewFile(ctxt, "go_functions", uint64(ldr.SymValue(x)), xfile.getXCOFFscnum(ldr.SymSect(x)))
819 }
820 }
821
822 }
823 }
824
825 name = ldr.SymExtname(x)
826 name = mangleABIName(ctxt, ldr, x, name)
827
828 s := &XcoffSymEnt64{
829 Nsclass: C_EXT,
830 Noffset: uint32(xfile.stringTable.add(name)),
831 Nvalue: uint64(ldr.SymValue(x)),
832 Nscnum: f.getXCOFFscnum(ldr.SymSect(x)),
833 Ntype: SYM_TYPE_FUNC,
834 Nnumaux: 2,
835 }
836
837 if ldr.IsFileLocal(x) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
838 s.Nsclass = C_HIDEXT
839 }
840
841 ldr.SetSymDynid(x, int32(xfile.symbolCount))
842 syms = append(syms, s)
843
844
845
846
847 sv := ldr.SymValue(x) + ldr.SymSize(x)
848 if currSymSrcFile.csectVAEnd < sv {
849 currSymSrcFile.csectVAEnd = sv
850 }
851
852
853 a2 := &XcoffAuxFcn64{
854 Xfsize: uint32(ldr.SymSize(x)),
855 Xlnnoptr: 0,
856 Xendndx: xfile.symbolCount + 3,
857 Xauxtype: _AUX_FCN,
858 }
859 syms = append(syms, a2)
860
861 a4 := &XcoffAuxCSect64{
862 Xscnlenlo: uint32(currSymSrcFile.csectSymNb & 0xFFFFFFFF),
863 Xscnlenhi: uint32(currSymSrcFile.csectSymNb >> 32),
864 Xsmclas: XMC_PR,
865 Xsmtyp: XTY_LD,
866 Xauxtype: _AUX_CSECT,
867 }
868 a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, TextSym) << 3)
869
870 syms = append(syms, a4)
871 return syms
872 }
873
874
875 func putaixsym(ctxt *Link, x loader.Sym, t SymbolType) {
876
877
878 syms := []xcoffSym{}
879
880 ldr := ctxt.loader
881 name := ldr.SymName(x)
882 if t == UndefinedSym {
883 name = ldr.SymExtname(x)
884 }
885
886 switch t {
887 default:
888 return
889
890 case TextSym:
891 if ldr.SymPkg(x) != "" || strings.Contains(name, "-tramp") || strings.HasPrefix(name, "runtime.text.") {
892
893 syms = xfile.writeSymbolFunc(ctxt, x)
894 } else {
895
896 if name != "runtime.text" && name != "runtime.etext" && name != "go:buildid" {
897 Exitf("putaixsym: unknown text symbol %s", name)
898 }
899 s := &XcoffSymEnt64{
900 Nsclass: C_HIDEXT,
901 Noffset: uint32(xfile.stringTable.add(name)),
902 Nvalue: uint64(ldr.SymValue(x)),
903 Nscnum: xfile.getXCOFFscnum(ldr.SymSect(x)),
904 Ntype: SYM_TYPE_FUNC,
905 Nnumaux: 1,
906 }
907 ldr.SetSymDynid(x, int32(xfile.symbolCount))
908 syms = append(syms, s)
909
910 size := uint64(ldr.SymSize(x))
911 a4 := &XcoffAuxCSect64{
912 Xauxtype: _AUX_CSECT,
913 Xscnlenlo: uint32(size & 0xFFFFFFFF),
914 Xscnlenhi: uint32(size >> 32),
915 Xsmclas: XMC_PR,
916 Xsmtyp: XTY_SD,
917 }
918 a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, TextSym) << 3)
919 syms = append(syms, a4)
920 }
921
922 case DataSym, BSSSym:
923 s := &XcoffSymEnt64{
924 Nsclass: C_EXT,
925 Noffset: uint32(xfile.stringTable.add(name)),
926 Nvalue: uint64(ldr.SymValue(x)),
927 Nscnum: xfile.getXCOFFscnum(ldr.SymSect(x)),
928 Nnumaux: 1,
929 }
930
931 if ldr.IsFileLocal(x) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
932
933
934
935
936
937
938 s.Nsclass = C_HIDEXT
939 }
940
941 ldr.SetSymDynid(x, int32(xfile.symbolCount))
942 syms = append(syms, s)
943
944
945
946
947
948
949
950 size := uint64(ldr.SymSize(x))
951 a4 := &XcoffAuxCSect64{
952 Xauxtype: _AUX_CSECT,
953 Xscnlenlo: uint32(size & 0xFFFFFFFF),
954 Xscnlenhi: uint32(size >> 32),
955 }
956
957 if ty := ldr.SymType(x); ty >= sym.STYPE && ty <= sym.SPCLNTAB {
958 if ctxt.IsExternal() && strings.HasPrefix(ldr.SymSect(x).Name, ".data.rel.ro") {
959
960
961 a4.Xsmclas = XMC_RW
962 } else {
963
964 a4.Xsmclas = XMC_RO
965 }
966 } else if strings.HasPrefix(ldr.SymName(x), "TOC.") && ctxt.IsExternal() {
967 a4.Xsmclas = XMC_TC
968 } else if ldr.SymName(x) == "TOC" {
969 a4.Xsmclas = XMC_TC0
970 } else {
971 a4.Xsmclas = XMC_RW
972 }
973 if t == DataSym {
974 a4.Xsmtyp |= XTY_SD
975 } else {
976 a4.Xsmtyp |= XTY_CM
977 }
978
979 a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, t) << 3)
980
981 syms = append(syms, a4)
982
983 case UndefinedSym:
984 if ty := ldr.SymType(x); ty != sym.SDYNIMPORT && ty != sym.SHOSTOBJ && ty != sym.SUNDEFEXT {
985 return
986 }
987 s := &XcoffSymEnt64{
988 Nsclass: C_EXT,
989 Noffset: uint32(xfile.stringTable.add(name)),
990 Nnumaux: 1,
991 }
992 ldr.SetSymDynid(x, int32(xfile.symbolCount))
993 syms = append(syms, s)
994
995 a4 := &XcoffAuxCSect64{
996 Xauxtype: _AUX_CSECT,
997 Xsmclas: XMC_DS,
998 Xsmtyp: XTY_ER | XTY_IMP,
999 }
1000
1001 if ldr.SymName(x) == "__n_pthreads" {
1002
1003
1004
1005 a4.Xsmclas = XMC_RW
1006 }
1007
1008 syms = append(syms, a4)
1009
1010 case TLSSym:
1011 s := &XcoffSymEnt64{
1012 Nsclass: C_EXT,
1013 Noffset: uint32(xfile.stringTable.add(name)),
1014 Nscnum: xfile.getXCOFFscnum(ldr.SymSect(x)),
1015 Nvalue: uint64(ldr.SymValue(x)),
1016 Nnumaux: 1,
1017 }
1018
1019 ldr.SetSymDynid(x, int32(xfile.symbolCount))
1020 syms = append(syms, s)
1021
1022 size := uint64(ldr.SymSize(x))
1023 a4 := &XcoffAuxCSect64{
1024 Xauxtype: _AUX_CSECT,
1025 Xsmclas: XMC_UL,
1026 Xsmtyp: XTY_CM,
1027 Xscnlenlo: uint32(size & 0xFFFFFFFF),
1028 Xscnlenhi: uint32(size >> 32),
1029 }
1030
1031 syms = append(syms, a4)
1032 }
1033
1034 for _, s := range syms {
1035 xfile.addSymbol(s)
1036 }
1037 }
1038
1039
1040
1041
1042 func (f *xcoffFile) asmaixsym(ctxt *Link) {
1043 ldr := ctxt.loader
1044
1045
1046 for name, size := range outerSymSize {
1047 sym := ldr.Lookup(name, 0)
1048 if sym == 0 {
1049 Errorf("unknown outer symbol with name %s", name)
1050 } else {
1051 s := ldr.MakeSymbolUpdater(sym)
1052 s.SetSize(size)
1053 }
1054 }
1055
1056
1057
1058 s := ldr.Lookup("runtime.text", 0)
1059 if ldr.SymType(s).IsText() {
1060
1061
1062 if !ctxt.IsExternal() {
1063 putaixsym(ctxt, s, TextSym)
1064 }
1065 }
1066
1067 n := 1
1068
1069 for _, sect := range Segtext.Sections[1:] {
1070 if sect.Name != ".text" || ctxt.IsExternal() {
1071
1072 break
1073 }
1074 s = ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
1075 if s == 0 {
1076 break
1077 }
1078 if ldr.SymType(s).IsText() {
1079 putaixsym(ctxt, s, TextSym)
1080 }
1081 n++
1082 }
1083
1084 s = ldr.Lookup("runtime.etext", 0)
1085 if ldr.SymType(s).IsText() {
1086
1087
1088
1089 if !ctxt.IsExternal() {
1090 putaixsym(ctxt, s, TextSym)
1091 }
1092 }
1093
1094 shouldBeInSymbolTable := func(s loader.Sym, name string) bool {
1095 if ldr.AttrNotInSymbolTable(s) {
1096 return false
1097 }
1098 if (name == "" || name[0] == '.') && !ldr.IsFileLocal(s) && name != ".TOC." {
1099 return false
1100 }
1101 return true
1102 }
1103
1104 for s, nsym := loader.Sym(1), loader.Sym(ldr.NSym()); s < nsym; s++ {
1105 if !shouldBeInSymbolTable(s, ldr.SymName(s)) {
1106 continue
1107 }
1108 st := ldr.SymType(s)
1109 switch {
1110 case st == sym.STLSBSS:
1111 if ctxt.IsExternal() {
1112 putaixsym(ctxt, s, TLSSym)
1113 }
1114
1115 case st == sym.SBSS, st == sym.SNOPTRBSS, st == sym.SLIBFUZZER_8BIT_COUNTER, st == sym.SCOVERAGE_COUNTER:
1116 if ldr.AttrReachable(s) {
1117 data := ldr.Data(s)
1118 if len(data) > 0 {
1119 ldr.Errorf(s, "should not be bss (size=%d type=%v special=%v)", len(data), ldr.SymType(s), ldr.AttrSpecial(s))
1120 }
1121 putaixsym(ctxt, s, BSSSym)
1122 }
1123
1124 case st >= sym.SELFRXSECT && st < sym.SXREF:
1125 if ldr.AttrReachable(s) {
1126 putaixsym(ctxt, s, DataSym)
1127 }
1128
1129 case st == sym.SUNDEFEXT:
1130 putaixsym(ctxt, s, UndefinedSym)
1131
1132 case st == sym.SDYNIMPORT:
1133 if ldr.AttrReachable(s) {
1134 putaixsym(ctxt, s, UndefinedSym)
1135 }
1136 }
1137 }
1138
1139 for _, s := range ctxt.Textp {
1140 putaixsym(ctxt, s, TextSym)
1141 }
1142
1143 if ctxt.Debugvlog != 0 {
1144 ctxt.Logf("symsize = %d\n", uint32(symSize))
1145 }
1146 xfile.updatePreviousFile(ctxt, true)
1147 }
1148
1149 func (f *xcoffFile) genDynSym(ctxt *Link) {
1150 ldr := ctxt.loader
1151 var dynsyms []loader.Sym
1152 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
1153 if !ldr.AttrReachable(s) {
1154 continue
1155 }
1156 if t := ldr.SymType(s); t != sym.SHOSTOBJ && t != sym.SDYNIMPORT {
1157 continue
1158 }
1159 dynsyms = append(dynsyms, s)
1160 }
1161
1162 for _, s := range dynsyms {
1163 f.adddynimpsym(ctxt, s)
1164
1165 if _, ok := f.dynLibraries[ldr.SymDynimplib(s)]; !ok {
1166 f.dynLibraries[ldr.SymDynimplib(s)] = len(f.dynLibraries)
1167 }
1168 }
1169 }
1170
1171
1172
1173
1174
1175
1176
1177
1178 func (f *xcoffFile) adddynimpsym(ctxt *Link, s loader.Sym) {
1179
1180
1181 ldr := ctxt.loader
1182 if ctxt.IsInternal() && ldr.SymDynimplib(s) == "" {
1183 ctxt.Errorf(s, "imported symbol must have a given library")
1184 }
1185
1186 sb := ldr.MakeSymbolUpdater(s)
1187 sb.SetReachable(true)
1188 sb.SetType(sym.SXCOFFTOC)
1189
1190
1191 extsym := ldr.CreateSymForUpdate(ldr.SymExtname(s), 0)
1192 extsym.SetType(sym.SDYNIMPORT)
1193 extsym.SetDynimplib(ldr.SymDynimplib(s))
1194 extsym.SetExtname(ldr.SymExtname(s))
1195 extsym.SetDynimpvers(ldr.SymDynimpvers(s))
1196
1197
1198 lds := &xcoffLoaderSymbol{
1199 sym: extsym.Sym(),
1200 smtype: XTY_IMP,
1201 smclas: XMC_DS,
1202 }
1203 if ldr.SymName(s) == "__n_pthreads" {
1204
1205
1206
1207 lds.smclas = XMC_RW
1208 }
1209 f.loaderSymbols = append(f.loaderSymbols, lds)
1210
1211
1212 sb.AddBytes(make([]byte, 8))
1213 r, _ := sb.AddRel(objabi.R_ADDR)
1214 r.SetSym(extsym.Sym())
1215 r.SetSiz(uint8(ctxt.Arch.PtrSize))
1216
1217
1218
1219
1220
1221
1222 }
1223
1224
1225
1226 func Xcoffadddynrel(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
1227 if target.IsExternal() {
1228 return true
1229 }
1230 if ldr.SymType(s) <= sym.SPCLNTAB {
1231 ldr.Errorf(s, "cannot have a relocation to %s in a text section symbol", ldr.SymName(r.Sym()))
1232 return false
1233 }
1234
1235 xldr := &xcoffLoaderReloc{
1236 sym: s,
1237 roff: r.Off(),
1238 }
1239 targ := r.Sym()
1240 var targType sym.SymKind
1241 if targ != 0 {
1242 targType = ldr.SymType(targ)
1243 }
1244
1245 switch r.Type() {
1246 default:
1247 ldr.Errorf(s, "unexpected .loader relocation to symbol: %s (type: %s)", ldr.SymName(targ), r.Type().String())
1248 return false
1249 case objabi.R_ADDR:
1250 if ldr.SymType(s) == sym.SXCOFFTOC && targType == sym.SDYNIMPORT {
1251
1252 for i, dynsym := range xfile.loaderSymbols {
1253 if ldr.SymName(dynsym.sym) == ldr.SymName(targ) {
1254 xldr.symndx = int32(i + 3)
1255 break
1256 }
1257 }
1258 } else if t := ldr.SymType(s); t.IsDATA() || t.IsNOPTRDATA() || t == sym.SBUILDINFO || t == sym.SXCOFFTOC {
1259 switch ldr.SymSect(targ).Seg {
1260 default:
1261 ldr.Errorf(s, "unknown segment for .loader relocation with symbol %s", ldr.SymName(targ))
1262 case &Segtext:
1263 case &Segrodata:
1264 xldr.symndx = 0
1265 case &Segdata:
1266 if targType == sym.SBSS || targType == sym.SNOPTRBSS {
1267 xldr.symndx = 2
1268 } else {
1269 xldr.symndx = 1
1270 }
1271 }
1272
1273 } else {
1274 ldr.Errorf(s, "unexpected type for .loader relocation R_ADDR for symbol %s: %s to %s", ldr.SymName(targ), ldr.SymType(s), ldr.SymType(targ))
1275 return false
1276 }
1277
1278 xldr.rtype = 0x3F<<8 + XCOFF_R_POS
1279 }
1280
1281 xfile.Lock()
1282 xfile.loaderReloc = append(xfile.loaderReloc, xldr)
1283 xfile.Unlock()
1284 return true
1285 }
1286
1287 func (ctxt *Link) doxcoff() {
1288 ldr := ctxt.loader
1289
1290
1291 toc := ldr.CreateSymForUpdate("TOC", 0)
1292 toc.SetType(sym.SXCOFFTOC)
1293 toc.SetVisibilityHidden(true)
1294
1295
1296 ep := ldr.Lookup(*flagEntrySymbol, 0)
1297 if ep == 0 || !ldr.AttrReachable(ep) {
1298 Exitf("wrong entry point")
1299 }
1300
1301 xfile.loaderSymbols = append(xfile.loaderSymbols, &xcoffLoaderSymbol{
1302 sym: ep,
1303 smtype: XTY_ENT | XTY_SD,
1304 smclas: XMC_DS,
1305 })
1306
1307 xfile.genDynSym(ctxt)
1308
1309 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
1310 if strings.HasPrefix(ldr.SymName(s), "TOC.") {
1311 sb := ldr.MakeSymbolUpdater(s)
1312 sb.SetType(sym.SXCOFFTOC)
1313 }
1314 }
1315
1316 if ctxt.IsExternal() {
1317
1318 rt0 := ldr.Lookup("runtime.rt0_go", 0)
1319 ldr.SetSymExtname(rt0, "runtime_rt0_go")
1320
1321 nsym := loader.Sym(ldr.NSym())
1322 for s := loader.Sym(1); s < nsym; s++ {
1323 if !ldr.AttrCgoExport(s) {
1324 continue
1325 }
1326 if ldr.IsFileLocal(s) {
1327 panic("cgo_export on static symbol")
1328 }
1329
1330 if ldr.SymType(s).IsText() {
1331
1332
1333
1334 name := ldr.SymExtname(s)
1335 ldr.SetSymExtname(s, "."+name)
1336
1337 desc := ldr.MakeSymbolUpdater(ldr.CreateExtSym(name, 0))
1338 desc.SetReachable(true)
1339 desc.SetType(sym.SNOPTRDATA)
1340 desc.AddAddr(ctxt.Arch, s)
1341 desc.AddAddr(ctxt.Arch, toc.Sym())
1342 desc.AddUint64(ctxt.Arch, 0)
1343 }
1344 }
1345 }
1346 }
1347
1348
1349
1350
1351
1352
1353 func Loaderblk(ctxt *Link, off uint64) {
1354 xfile.writeLdrScn(ctxt, off)
1355 }
1356
1357 func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) {
1358 var symtab []*XcoffLdSym64
1359 var strtab []*XcoffLdStr64
1360 var importtab []*XcoffLdImportFile64
1361 var reloctab []*XcoffLdRel64
1362 var dynimpreloc []*XcoffLdRel64
1363
1364
1365
1366 stlen := uint32(0)
1367
1368
1369 hdr := &XcoffLdHdr64{
1370 Lversion: 2,
1371 Lsymoff: LDHDRSZ_64,
1372 }
1373
1374 ldr := ctxt.loader
1375
1376 for _, s := range f.loaderSymbols {
1377 lds := &XcoffLdSym64{
1378 Loffset: uint32(stlen + 2),
1379 Lsmtype: s.smtype,
1380 Lsmclas: s.smclas,
1381 }
1382 sym := s.sym
1383 switch s.smtype {
1384 default:
1385 ldr.Errorf(sym, "unexpected loader symbol type: 0x%x", s.smtype)
1386 case XTY_ENT | XTY_SD:
1387 lds.Lvalue = uint64(ldr.SymValue(sym))
1388 lds.Lscnum = f.getXCOFFscnum(ldr.SymSect(sym))
1389 case XTY_IMP:
1390 lds.Lifile = int32(f.dynLibraries[ldr.SymDynimplib(sym)] + 1)
1391 }
1392 ldstr := &XcoffLdStr64{
1393 size: uint16(len(ldr.SymName(sym)) + 1),
1394 name: ldr.SymName(sym),
1395 }
1396 stlen += uint32(2 + ldstr.size)
1397 symtab = append(symtab, lds)
1398 strtab = append(strtab, ldstr)
1399
1400 }
1401
1402 hdr.Lnsyms = int32(len(symtab))
1403 hdr.Lrldoff = hdr.Lsymoff + uint64(24*hdr.Lnsyms)
1404 off := hdr.Lrldoff
1405
1406
1407
1408 sort.Slice(f.loaderReloc, func(i, j int) bool {
1409 r1, r2 := f.loaderReloc[i], f.loaderReloc[j]
1410 if r1.sym != r2.sym {
1411 return r1.sym < r2.sym
1412 }
1413 if r1.roff != r2.roff {
1414 return r1.roff < r2.roff
1415 }
1416 if r1.rtype != r2.rtype {
1417 return r1.rtype < r2.rtype
1418 }
1419 return r1.symndx < r2.symndx
1420 })
1421
1422 ep := ldr.Lookup(*flagEntrySymbol, 0)
1423 xldr := &XcoffLdRel64{
1424 Lvaddr: uint64(ldr.SymValue(ep)),
1425 Lrtype: 0x3F00,
1426 Lrsecnm: f.getXCOFFscnum(ldr.SymSect(ep)),
1427 Lsymndx: 0,
1428 }
1429 off += 16
1430 reloctab = append(reloctab, xldr)
1431
1432 off += uint64(16 * len(f.loaderReloc))
1433 for _, r := range f.loaderReloc {
1434 symp := r.sym
1435 if symp == 0 {
1436 panic("unexpected 0 sym value")
1437 }
1438 xldr = &XcoffLdRel64{
1439 Lvaddr: uint64(ldr.SymValue(symp) + int64(r.roff)),
1440 Lrtype: r.rtype,
1441 Lsymndx: r.symndx,
1442 }
1443
1444 if ldr.SymSect(symp) != nil {
1445 xldr.Lrsecnm = f.getXCOFFscnum(ldr.SymSect(symp))
1446 }
1447
1448 reloctab = append(reloctab, xldr)
1449 }
1450
1451 off += uint64(16 * len(dynimpreloc))
1452 reloctab = append(reloctab, dynimpreloc...)
1453
1454 hdr.Lnreloc = int32(len(reloctab))
1455 hdr.Limpoff = off
1456
1457
1458
1459 ldimpf := &XcoffLdImportFile64{
1460 Limpidpath: "/usr/lib:/lib",
1461 }
1462 off += uint64(len(ldimpf.Limpidpath) + len(ldimpf.Limpidbase) + len(ldimpf.Limpidmem) + 3)
1463 importtab = append(importtab, ldimpf)
1464
1465
1466
1467
1468 libsOrdered := make([]string, len(f.dynLibraries))
1469 for key, val := range f.dynLibraries {
1470 if libsOrdered[val] != "" {
1471 continue
1472 }
1473 libsOrdered[val] = key
1474 }
1475
1476 for _, lib := range libsOrdered {
1477
1478 n := strings.Split(lib, "/")
1479 path := ""
1480 base := n[len(n)-2]
1481 mem := n[len(n)-1]
1482 if len(n) > 2 {
1483 path = lib[:len(lib)-len(base)-len(mem)-2]
1484
1485 }
1486 ldimpf = &XcoffLdImportFile64{
1487 Limpidpath: path,
1488 Limpidbase: base,
1489 Limpidmem: mem,
1490 }
1491 off += uint64(len(ldimpf.Limpidpath) + len(ldimpf.Limpidbase) + len(ldimpf.Limpidmem) + 3)
1492 importtab = append(importtab, ldimpf)
1493 }
1494
1495 hdr.Lnimpid = int32(len(importtab))
1496 hdr.Listlen = uint32(off - hdr.Limpoff)
1497 hdr.Lstoff = off
1498 hdr.Lstlen = stlen
1499
1500
1501 ctxt.Out.SeekSet(int64(globalOff))
1502 binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, hdr)
1503
1504 for _, s := range symtab {
1505 binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, s)
1506
1507 }
1508 for _, r := range reloctab {
1509 binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, r)
1510 }
1511 for _, f := range importtab {
1512 ctxt.Out.WriteString(f.Limpidpath)
1513 ctxt.Out.Write8(0)
1514 ctxt.Out.WriteString(f.Limpidbase)
1515 ctxt.Out.Write8(0)
1516 ctxt.Out.WriteString(f.Limpidmem)
1517 ctxt.Out.Write8(0)
1518 }
1519 for _, s := range strtab {
1520 ctxt.Out.Write16(s.size)
1521 ctxt.Out.WriteString(s.name)
1522 ctxt.Out.Write8(0)
1523 }
1524
1525 f.loaderSize = off + uint64(stlen)
1526 }
1527
1528
1529
1530 func (f *xcoffFile) writeFileHeader(ctxt *Link) {
1531
1532 f.xfhdr.Fmagic = U64_TOCMAGIC
1533 f.xfhdr.Fnscns = uint16(len(f.sections))
1534 f.xfhdr.Ftimedat = 0
1535
1536 if !*FlagS {
1537 f.xfhdr.Fsymptr = uint64(f.symtabOffset)
1538 f.xfhdr.Fnsyms = int32(f.symbolCount)
1539 }
1540
1541 if ctxt.BuildMode == BuildModeExe && ctxt.LinkMode == LinkInternal {
1542 ldr := ctxt.loader
1543 f.xfhdr.Fopthdr = AOUTHSZ_EXEC64
1544 f.xfhdr.Fflags = F_EXEC
1545
1546
1547 f.xahdr.Ovstamp = 1
1548 f.xahdr.Omagic = 0x10b
1549 copy(f.xahdr.Omodtype[:], "1L")
1550 entry := ldr.Lookup(*flagEntrySymbol, 0)
1551 f.xahdr.Oentry = uint64(ldr.SymValue(entry))
1552 f.xahdr.Osnentry = f.getXCOFFscnum(ldr.SymSect(entry))
1553 toc := ldr.Lookup("TOC", 0)
1554 f.xahdr.Otoc = uint64(ldr.SymValue(toc))
1555 f.xahdr.Osntoc = f.getXCOFFscnum(ldr.SymSect(toc))
1556
1557 f.xahdr.Oalgntext = int16(logBase2(int(XCOFFSECTALIGN)))
1558 f.xahdr.Oalgndata = 0x5
1559
1560 binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr)
1561 binary.Write(ctxt.Out, binary.BigEndian, &f.xahdr)
1562 } else {
1563 f.xfhdr.Fopthdr = 0
1564 binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr)
1565 }
1566
1567 }
1568
1569 func xcoffwrite(ctxt *Link) {
1570 ctxt.Out.SeekSet(0)
1571
1572 xfile.writeFileHeader(ctxt)
1573
1574 for _, sect := range xfile.sections {
1575 sect.write(ctxt)
1576 }
1577 }
1578
1579
1580 func asmbXcoff(ctxt *Link) {
1581 ctxt.Out.SeekSet(0)
1582 fileoff := int64(Segdwarf.Fileoff + Segdwarf.Filelen)
1583 fileoff = int64(Rnd(int64(fileoff), *FlagRound))
1584
1585 xfile.sectNameToScnum = make(map[string]int16)
1586
1587
1588 s := xfile.addSection(".text", Segtext.Vaddr, Segtext.Length, Segtext.Fileoff, STYP_TEXT)
1589 xfile.xahdr.Otextstart = s.Svaddr
1590 xfile.xahdr.Osntext = xfile.sectNameToScnum[".text"]
1591 xfile.xahdr.Otsize = s.Ssize
1592 xfile.sectText = s
1593
1594 segdataVaddr := Segdata.Vaddr
1595 segdataFilelen := Segdata.Filelen
1596 segdataFileoff := Segdata.Fileoff
1597 segbssFilelen := Segdata.Length - Segdata.Filelen
1598 if len(Segrelrodata.Sections) > 0 {
1599
1600
1601 segdataVaddr = Segrelrodata.Vaddr
1602 segdataFileoff = Segrelrodata.Fileoff
1603 segdataFilelen = Segdata.Vaddr + Segdata.Filelen - Segrelrodata.Vaddr
1604 }
1605
1606 s = xfile.addSection(".data", segdataVaddr, segdataFilelen, segdataFileoff, STYP_DATA)
1607 xfile.xahdr.Odatastart = s.Svaddr
1608 xfile.xahdr.Osndata = xfile.sectNameToScnum[".data"]
1609 xfile.xahdr.Odsize = s.Ssize
1610 xfile.sectData = s
1611
1612 s = xfile.addSection(".bss", segdataVaddr+segdataFilelen, segbssFilelen, 0, STYP_BSS)
1613 xfile.xahdr.Osnbss = xfile.sectNameToScnum[".bss"]
1614 xfile.xahdr.Obsize = s.Ssize
1615 xfile.sectBss = s
1616
1617 if ctxt.LinkMode == LinkExternal {
1618 var tbss *sym.Section
1619 for _, s := range Segdata.Sections {
1620 if s.Name == ".tbss" {
1621 tbss = s
1622 break
1623 }
1624 }
1625 s = xfile.addSection(".tbss", tbss.Vaddr, tbss.Length, 0, STYP_TBSS)
1626 }
1627
1628
1629 for _, sect := range Segdwarf.Sections {
1630 xfile.addDwarfSection(sect)
1631 }
1632
1633
1634 if ctxt.LinkMode == LinkInternal {
1635
1636 if ctxt.BuildMode == BuildModeExe {
1637 Loaderblk(ctxt, uint64(fileoff))
1638 s = xfile.addSection(".loader", 0, xfile.loaderSize, uint64(fileoff), STYP_LOADER)
1639 xfile.xahdr.Osnloader = xfile.sectNameToScnum[".loader"]
1640
1641
1642 fileoff += int64(xfile.loaderSize)
1643 }
1644 }
1645
1646
1647 xfile.asmaixsym(ctxt)
1648
1649 if ctxt.LinkMode == LinkExternal {
1650 xfile.emitRelocations(ctxt, fileoff)
1651 }
1652
1653
1654 xfile.symtabOffset = ctxt.Out.Offset()
1655 for _, s := range xfile.symtabSym {
1656 binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, s)
1657 }
1658
1659 xfile.stringTable.write(ctxt.Out)
1660
1661
1662 xcoffwrite(ctxt)
1663 }
1664
1665
1666 func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
1667 ctxt.Out.SeekSet(fileoff)
1668 for ctxt.Out.Offset()&7 != 0 {
1669 ctxt.Out.Write8(0)
1670 }
1671
1672 ldr := ctxt.loader
1673
1674
1675 relocsect := func(sect *sym.Section, syms []loader.Sym, base uint64) uint32 {
1676
1677
1678 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
1679 return 0
1680 }
1681 sect.Reloff = uint64(ctxt.Out.Offset())
1682 for i, s := range syms {
1683 if !ldr.AttrReachable(s) {
1684 continue
1685 }
1686 if uint64(ldr.SymValue(s)) >= sect.Vaddr {
1687 syms = syms[i:]
1688 break
1689 }
1690 }
1691 eaddr := int64(sect.Vaddr + sect.Length)
1692 for _, s := range syms {
1693 if !ldr.AttrReachable(s) {
1694 continue
1695 }
1696 if ldr.SymValue(s) >= int64(eaddr) {
1697 break
1698 }
1699
1700
1701
1702 relocs := ldr.Relocs(s)
1703 sorted := make([]int, relocs.Count())
1704 for i := 0; i < relocs.Count(); i++ {
1705 sorted[i] = i
1706 }
1707 sort.Slice(sorted, func(i, j int) bool {
1708 return relocs.At(sorted[i]).Off() < relocs.At(sorted[j]).Off()
1709 })
1710
1711 for _, ri := range sorted {
1712 r := relocs.At(ri)
1713 rr, ok := extreloc(ctxt, ldr, s, r)
1714 if !ok {
1715 continue
1716 }
1717 if rr.Xsym == 0 {
1718 ldr.Errorf(s, "missing xsym in relocation")
1719 continue
1720 }
1721 if ldr.SymDynid(rr.Xsym) < 0 {
1722 ldr.Errorf(s, "reloc %s to non-coff symbol %s (outer=%s) %d %d", r.Type(), ldr.SymName(r.Sym()), ldr.SymName(rr.Xsym), ldr.SymType(r.Sym()), ldr.SymDynid(rr.Xsym))
1723 }
1724 if !thearch.Xcoffreloc1(ctxt.Arch, ctxt.Out, ldr, s, rr, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-base)) {
1725 ldr.Errorf(s, "unsupported obj reloc %d(%s)/%d to %s", r.Type(), r.Type(), r.Siz(), ldr.SymName(r.Sym()))
1726 }
1727 }
1728 }
1729 sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
1730 return uint32(sect.Rellen) / RELSZ_64
1731 }
1732 sects := []struct {
1733 xcoffSect *XcoffScnHdr64
1734 segs []*sym.Segment
1735 }{
1736 {f.sectText, []*sym.Segment{&Segtext}},
1737 {f.sectData, []*sym.Segment{&Segrelrodata, &Segdata}},
1738 }
1739 for _, s := range sects {
1740 s.xcoffSect.Srelptr = uint64(ctxt.Out.Offset())
1741 n := uint32(0)
1742 for _, seg := range s.segs {
1743 for _, sect := range seg.Sections {
1744 if sect.Name == ".text" {
1745 n += relocsect(sect, ctxt.Textp, 0)
1746 } else {
1747 n += relocsect(sect, ctxt.datap, 0)
1748 }
1749 }
1750 }
1751 s.xcoffSect.Snreloc += n
1752 }
1753
1754 dwarfLoop:
1755 for i := 0; i < len(Segdwarf.Sections); i++ {
1756 sect := Segdwarf.Sections[i]
1757 si := dwarfp[i]
1758 if si.secSym() != loader.Sym(sect.Sym) ||
1759 ldr.SymSect(si.secSym()) != sect {
1760 panic("inconsistency between dwarfp and Segdwarf")
1761 }
1762 for _, xcoffSect := range f.sections {
1763 _, subtyp := xcoffGetDwarfSubtype(sect.Name)
1764 if xcoffSect.Sflags&0xF0000 == subtyp {
1765 xcoffSect.Srelptr = uint64(ctxt.Out.Offset())
1766 xcoffSect.Snreloc = relocsect(sect, si.syms, sect.Vaddr)
1767 continue dwarfLoop
1768 }
1769 }
1770 Errorf("emitRelocations: could not find %q section", sect.Name)
1771 }
1772 }
1773
1774
1775
1776
1777 func xcoffCreateExportFile(ctxt *Link) (fname string) {
1778 fname = filepath.Join(*flagTmpdir, "export_file.exp")
1779 var buf bytes.Buffer
1780
1781 ldr := ctxt.loader
1782 for s, nsym := loader.Sym(1), loader.Sym(ldr.NSym()); s < nsym; s++ {
1783 if !ldr.AttrCgoExport(s) {
1784 continue
1785 }
1786 extname := ldr.SymExtname(s)
1787 if !strings.HasPrefix(extname, "._cgoexp_") {
1788 continue
1789 }
1790 if ldr.IsFileLocal(s) {
1791 continue
1792 }
1793
1794
1795
1796
1797
1798 name := strings.SplitN(extname, "_", 4)[3]
1799
1800 buf.Write([]byte(name + "\n"))
1801 }
1802
1803 err := os.WriteFile(fname, buf.Bytes(), 0666)
1804 if err != nil {
1805 Errorf("WriteFile %s failed: %v", fname, err)
1806 }
1807
1808 return fname
1809 }
1810
View as plain text