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