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 }
609 }
610
611
612 func (f *xcoffFile) addSymbol(sym xcoffSym) {
613 f.symtabSym = append(f.symtabSym, sym)
614 f.symbolCount++
615 }
616
617
618 func xcoffAlign(ldr *loader.Loader, x loader.Sym, t SymbolType) uint8 {
619 align := ldr.SymAlign(x)
620 if align == 0 {
621 if t == TextSym {
622 align = int32(Funcalign)
623 } else {
624 align = symalign(ldr, x)
625 }
626 }
627 return logBase2(int(align))
628 }
629
630
631 func logBase2(a int) uint8 {
632 return uint8(bits.Len(uint(a)) - 1)
633 }
634
635
636
637
638
639
640
641
642
643 func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint64, extnum int16) {
644 ldr := ctxt.loader
645
646 s := &XcoffSymEnt64{
647 Noffset: uint32(f.stringTable.add(".file")),
648 Nsclass: C_FILE,
649 Nscnum: N_DEBUG,
650 Ntype: 0,
651 Nnumaux: 1,
652 }
653 f.addSymbol(s)
654 currSymSrcFile.file = s
655
656
657 auxf := &XcoffAuxFile64{
658 Xoffset: uint32(f.stringTable.add(name)),
659 Xftype: XFT_FN,
660 Xauxtype: _AUX_FILE,
661 }
662 f.addSymbol(auxf)
663
664
665 for _, sect := range Segdwarf.Sections {
666 var dwsize uint64
667 if ctxt.LinkMode == LinkInternal {
668
669
670 dwsize = getDwsectCUSize(sect.Name, name)
671
672 if sect.Name == ".debug_abbrev" {
673 dwsize = uint64(ldr.SymSize(sect.Sym))
674
675 }
676 } else {
677
678 dwsize = sect.Length
679 }
680
681
682 name, _ := xcoffGetDwarfSubtype(sect.Name)
683 s := &XcoffSymEnt64{
684 Nvalue: currDwscnoff[sect.Name],
685 Noffset: uint32(f.stringTable.add(name)),
686 Nsclass: C_DWARF,
687 Nscnum: f.getXCOFFscnum(sect),
688 Nnumaux: 1,
689 }
690
691 if currSymSrcFile.csectAux == nil {
692
693
694
695 ldr.SetSymDynid(sect.Sym, int32(f.symbolCount))
696
697 if sect.Name == ".debug_frame" && ctxt.LinkMode != LinkExternal {
698
699 dwsize += 48
700 }
701 }
702
703 f.addSymbol(s)
704
705
706 if sect.Name != ".debug_abbrev" {
707 currDwscnoff[sect.Name] += dwsize
708 }
709
710
711 auxd := &XcoffAuxDWARF64{
712 Xscnlen: dwsize,
713 Xauxtype: _AUX_SECT,
714 }
715
716 f.addSymbol(auxd)
717 }
718
719
720
721
722 if extnum != 1 {
723 Exitf("XCOFF symtab: A new file was detected with its first symbol not in .text")
724 }
725
726 currSymSrcFile.csectSymNb = uint64(f.symbolCount)
727
728
729 s = &XcoffSymEnt64{
730 Nvalue: firstEntry,
731 Nscnum: extnum,
732 Nsclass: C_HIDEXT,
733 Ntype: 0,
734 Nnumaux: 1,
735 }
736 f.addSymbol(s)
737
738 aux := &XcoffAuxCSect64{
739 Xsmclas: XMC_PR,
740 Xsmtyp: XTY_SD | logBase2(Funcalign)<<3,
741 Xauxtype: _AUX_CSECT,
742 }
743 f.addSymbol(aux)
744
745 currSymSrcFile.csectAux = aux
746 currSymSrcFile.csectVAStart = int64(firstEntry)
747 currSymSrcFile.csectVAEnd = int64(firstEntry)
748 }
749
750
751
752
753 func (f *xcoffFile) updatePreviousFile(ctxt *Link, last bool) {
754
755 if currSymSrcFile.file == nil {
756 return
757 }
758
759
760 cfile := currSymSrcFile.file
761 if last {
762 cfile.Nvalue = 0xFFFFFFFFFFFFFFFF
763 } else {
764 cfile.Nvalue = uint64(f.symbolCount)
765 }
766
767
768 aux := currSymSrcFile.csectAux
769 csectSize := currSymSrcFile.csectVAEnd - currSymSrcFile.csectVAStart
770 aux.Xscnlenlo = uint32(csectSize & 0xFFFFFFFF)
771 aux.Xscnlenhi = uint32(csectSize >> 32)
772 }
773
774
775
776
777 func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x loader.Sym) []xcoffSym {
778
779 syms := []xcoffSym{}
780
781
782 ldr := ctxt.loader
783 name := ldr.SymName(x)
784 if strings.Contains(name, "-tramp") || strings.HasPrefix(name, "runtime.text.") {
785
786
787
788 } else if ldr.SymPkg(x) == "" {
789
790 if currSymSrcFile.name != "" {
791 Exitf("undefined global symbol found inside another file")
792 }
793 } else {
794
795 if currSymSrcFile.name != ldr.SymPkg(x) {
796 if ctxt.LinkMode == LinkInternal {
797
798 xfile.updatePreviousFile(ctxt, false)
799 currSymSrcFile.name = ldr.SymPkg(x)
800 f.writeSymbolNewFile(ctxt, ldr.SymPkg(x), uint64(ldr.SymValue(x)), xfile.getXCOFFscnum(ldr.SymSect(x)))
801 } else {
802
803
804
805
806
807
808
809 if currSymSrcFile.name == "" {
810 currSymSrcFile.name = ldr.SymPkg(x)
811 f.writeSymbolNewFile(ctxt, "go_functions", uint64(ldr.SymValue(x)), xfile.getXCOFFscnum(ldr.SymSect(x)))
812 }
813 }
814
815 }
816 }
817
818 name = ldr.SymExtname(x)
819 name = mangleABIName(ctxt, ldr, x, name)
820
821 s := &XcoffSymEnt64{
822 Nsclass: C_EXT,
823 Noffset: uint32(xfile.stringTable.add(name)),
824 Nvalue: uint64(ldr.SymValue(x)),
825 Nscnum: f.getXCOFFscnum(ldr.SymSect(x)),
826 Ntype: SYM_TYPE_FUNC,
827 Nnumaux: 2,
828 }
829
830 if ldr.IsFileLocal(x) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
831 s.Nsclass = C_HIDEXT
832 }
833
834 ldr.SetSymDynid(x, int32(xfile.symbolCount))
835 syms = append(syms, s)
836
837
838
839
840 sv := ldr.SymValue(x) + ldr.SymSize(x)
841 if currSymSrcFile.csectVAEnd < sv {
842 currSymSrcFile.csectVAEnd = sv
843 }
844
845
846 a2 := &XcoffAuxFcn64{
847 Xfsize: uint32(ldr.SymSize(x)),
848 Xlnnoptr: 0,
849 Xendndx: xfile.symbolCount + 3,
850 Xauxtype: _AUX_FCN,
851 }
852 syms = append(syms, a2)
853
854 a4 := &XcoffAuxCSect64{
855 Xscnlenlo: uint32(currSymSrcFile.csectSymNb & 0xFFFFFFFF),
856 Xscnlenhi: uint32(currSymSrcFile.csectSymNb >> 32),
857 Xsmclas: XMC_PR,
858 Xsmtyp: XTY_LD,
859 Xauxtype: _AUX_CSECT,
860 }
861 a4.Xsmtyp |= xcoffAlign(ldr, x, TextSym) << 3
862
863 syms = append(syms, a4)
864 return syms
865 }
866
867
868 func putaixsym(ctxt *Link, x loader.Sym, t SymbolType) {
869
870
871 syms := []xcoffSym{}
872
873 ldr := ctxt.loader
874 name := ldr.SymName(x)
875 if t == UndefinedSym {
876 name = ldr.SymExtname(x)
877 }
878
879 switch t {
880 default:
881 return
882
883 case TextSym:
884 if ldr.SymPkg(x) != "" || strings.Contains(name, "-tramp") || strings.HasPrefix(name, "runtime.text.") {
885
886 syms = xfile.writeSymbolFunc(ctxt, x)
887 } else {
888
889 if name != "runtime.text" && name != "runtime.etext" && name != "go:buildid" {
890 Exitf("putaixsym: unknown text symbol %s", name)
891 }
892 s := &XcoffSymEnt64{
893 Nsclass: C_HIDEXT,
894 Noffset: uint32(xfile.stringTable.add(name)),
895 Nvalue: uint64(ldr.SymValue(x)),
896 Nscnum: xfile.getXCOFFscnum(ldr.SymSect(x)),
897 Ntype: SYM_TYPE_FUNC,
898 Nnumaux: 1,
899 }
900 ldr.SetSymDynid(x, int32(xfile.symbolCount))
901 syms = append(syms, s)
902
903 size := uint64(ldr.SymSize(x))
904 a4 := &XcoffAuxCSect64{
905 Xauxtype: _AUX_CSECT,
906 Xscnlenlo: uint32(size & 0xFFFFFFFF),
907 Xscnlenhi: uint32(size >> 32),
908 Xsmclas: XMC_PR,
909 Xsmtyp: XTY_SD,
910 }
911 a4.Xsmtyp |= xcoffAlign(ldr, x, TextSym) << 3
912 syms = append(syms, a4)
913 }
914
915 case DataSym, BSSSym:
916 s := &XcoffSymEnt64{
917 Nsclass: C_EXT,
918 Noffset: uint32(xfile.stringTable.add(name)),
919 Nvalue: uint64(ldr.SymValue(x)),
920 Nscnum: xfile.getXCOFFscnum(ldr.SymSect(x)),
921 Nnumaux: 1,
922 }
923
924 if ldr.IsFileLocal(x) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
925
926
927
928
929
930
931 s.Nsclass = C_HIDEXT
932 }
933
934 ldr.SetSymDynid(x, int32(xfile.symbolCount))
935 syms = append(syms, s)
936
937
938
939
940
941
942
943 size := uint64(ldr.SymSize(x))
944 a4 := &XcoffAuxCSect64{
945 Xauxtype: _AUX_CSECT,
946 Xscnlenlo: uint32(size & 0xFFFFFFFF),
947 Xscnlenhi: uint32(size >> 32),
948 }
949
950 if ty := ldr.SymType(x); ty >= sym.SSTRING && ty <= sym.SPCLNTAB {
951 if ctxt.IsExternal() && strings.HasPrefix(ldr.SymSect(x).Name, ".data.rel.ro") {
952
953
954 a4.Xsmclas = XMC_RW
955 } else {
956
957 a4.Xsmclas = XMC_RO
958 }
959 } else if strings.HasPrefix(ldr.SymName(x), "TOC.") && ctxt.IsExternal() {
960 a4.Xsmclas = XMC_TC
961 } else if ldr.SymName(x) == "TOC" {
962 a4.Xsmclas = XMC_TC0
963 } else {
964 a4.Xsmclas = XMC_RW
965 }
966 if t == DataSym {
967 a4.Xsmtyp |= XTY_SD
968 } else {
969 a4.Xsmtyp |= XTY_CM
970 }
971
972 a4.Xsmtyp |= xcoffAlign(ldr, x, t) << 3
973
974 syms = append(syms, a4)
975
976 case UndefinedSym:
977 if ty := ldr.SymType(x); ty != sym.SDYNIMPORT && ty != sym.SHOSTOBJ && ty != sym.SUNDEFEXT {
978 return
979 }
980 s := &XcoffSymEnt64{
981 Nsclass: C_EXT,
982 Noffset: uint32(xfile.stringTable.add(name)),
983 Nnumaux: 1,
984 }
985 ldr.SetSymDynid(x, int32(xfile.symbolCount))
986 syms = append(syms, s)
987
988 a4 := &XcoffAuxCSect64{
989 Xauxtype: _AUX_CSECT,
990 Xsmclas: XMC_DS,
991 Xsmtyp: XTY_ER | XTY_IMP,
992 }
993
994 if ldr.SymName(x) == "__n_pthreads" {
995
996
997
998 a4.Xsmclas = XMC_RW
999 }
1000
1001 syms = append(syms, a4)
1002
1003 case TLSSym:
1004 s := &XcoffSymEnt64{
1005 Nsclass: C_EXT,
1006 Noffset: uint32(xfile.stringTable.add(name)),
1007 Nscnum: xfile.getXCOFFscnum(ldr.SymSect(x)),
1008 Nvalue: uint64(ldr.SymValue(x)),
1009 Nnumaux: 1,
1010 }
1011
1012 ldr.SetSymDynid(x, int32(xfile.symbolCount))
1013 syms = append(syms, s)
1014
1015 size := uint64(ldr.SymSize(x))
1016 a4 := &XcoffAuxCSect64{
1017 Xauxtype: _AUX_CSECT,
1018 Xsmclas: XMC_UL,
1019 Xsmtyp: XTY_CM,
1020 Xscnlenlo: uint32(size & 0xFFFFFFFF),
1021 Xscnlenhi: uint32(size >> 32),
1022 }
1023
1024 syms = append(syms, a4)
1025 }
1026
1027 for _, s := range syms {
1028 xfile.addSymbol(s)
1029 }
1030 }
1031
1032
1033
1034
1035 func (f *xcoffFile) asmaixsym(ctxt *Link) {
1036 ldr := ctxt.loader
1037
1038
1039 for name, size := range outerSymSize {
1040 sym := ldr.Lookup(name, 0)
1041 if sym == 0 {
1042 Errorf("unknown outer symbol with name %s", name)
1043 } else {
1044 s := ldr.MakeSymbolUpdater(sym)
1045 s.SetSize(size)
1046 }
1047 }
1048
1049
1050
1051 s := ldr.Lookup("runtime.text", 0)
1052 if ldr.SymType(s).IsText() {
1053
1054
1055 if !ctxt.IsExternal() {
1056 putaixsym(ctxt, s, TextSym)
1057 }
1058 }
1059
1060 n := 1
1061
1062 for _, sect := range Segtext.Sections[1:] {
1063 if sect.Name != ".text" || ctxt.IsExternal() {
1064
1065 break
1066 }
1067 s = ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
1068 if s == 0 {
1069 break
1070 }
1071 if ldr.SymType(s).IsText() {
1072 putaixsym(ctxt, s, TextSym)
1073 }
1074 n++
1075 }
1076
1077 s = ldr.Lookup("runtime.etext", 0)
1078 if ldr.SymType(s).IsText() {
1079
1080
1081
1082 if !ctxt.IsExternal() {
1083 putaixsym(ctxt, s, TextSym)
1084 }
1085 }
1086
1087 shouldBeInSymbolTable := func(s loader.Sym, name string) bool {
1088 if ldr.AttrNotInSymbolTable(s) {
1089 return false
1090 }
1091 if (name == "" || name[0] == '.') && !ldr.IsFileLocal(s) && name != ".TOC." {
1092 return false
1093 }
1094 return true
1095 }
1096
1097 for s, nsym := loader.Sym(1), loader.Sym(ldr.NSym()); s < nsym; s++ {
1098 if !shouldBeInSymbolTable(s, ldr.SymName(s)) {
1099 continue
1100 }
1101 st := ldr.SymType(s)
1102 switch {
1103 case st == sym.STLSBSS:
1104 if ctxt.IsExternal() {
1105 putaixsym(ctxt, s, TLSSym)
1106 }
1107
1108 case st == sym.SBSS, st == sym.SNOPTRBSS, st == sym.SGCMASK, st == sym.SLIBFUZZER_8BIT_COUNTER, st == sym.SCOVERAGE_COUNTER:
1109 if ldr.AttrReachable(s) {
1110 data := ldr.Data(s)
1111 if len(data) > 0 {
1112 ldr.Errorf(s, "should not be bss (size=%d type=%v special=%v)", len(data), ldr.SymType(s), ldr.AttrSpecial(s))
1113 }
1114 putaixsym(ctxt, s, BSSSym)
1115 }
1116
1117 case st >= sym.SELFRXSECT && st < sym.SFirstUnallocated:
1118 if ldr.AttrReachable(s) {
1119 putaixsym(ctxt, s, DataSym)
1120 }
1121
1122 case st == sym.SUNDEFEXT:
1123 putaixsym(ctxt, s, UndefinedSym)
1124
1125 case st == sym.SDYNIMPORT:
1126 if ldr.AttrReachable(s) {
1127 putaixsym(ctxt, s, UndefinedSym)
1128 }
1129 }
1130 }
1131
1132 for _, s := range ctxt.Textp {
1133 putaixsym(ctxt, s, TextSym)
1134 }
1135
1136 if ctxt.Debugvlog != 0 {
1137 ctxt.Logf("symsize = %d\n", uint32(symSize))
1138 }
1139 xfile.updatePreviousFile(ctxt, true)
1140 }
1141
1142 func (f *xcoffFile) genDynSym(ctxt *Link) {
1143 ldr := ctxt.loader
1144 var dynsyms []loader.Sym
1145 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
1146 if !ldr.AttrReachable(s) {
1147 continue
1148 }
1149 if t := ldr.SymType(s); t != sym.SHOSTOBJ && t != sym.SDYNIMPORT {
1150 continue
1151 }
1152 dynsyms = append(dynsyms, s)
1153 }
1154
1155 for _, s := range dynsyms {
1156 f.adddynimpsym(ctxt, s)
1157
1158 if _, ok := f.dynLibraries[ldr.SymDynimplib(s)]; !ok {
1159 f.dynLibraries[ldr.SymDynimplib(s)] = len(f.dynLibraries)
1160 }
1161 }
1162 }
1163
1164
1165
1166
1167
1168
1169
1170
1171 func (f *xcoffFile) adddynimpsym(ctxt *Link, s loader.Sym) {
1172
1173
1174 ldr := ctxt.loader
1175 if ctxt.IsInternal() && ldr.SymDynimplib(s) == "" {
1176 ctxt.Errorf(s, "imported symbol must have a given library")
1177 }
1178
1179 sb := ldr.MakeSymbolUpdater(s)
1180 sb.SetReachable(true)
1181 sb.SetType(sym.SXCOFFTOC)
1182
1183
1184 extsym := ldr.CreateSymForUpdate(ldr.SymExtname(s), 0)
1185 extsym.SetType(sym.SDYNIMPORT)
1186 extsym.SetDynimplib(ldr.SymDynimplib(s))
1187 extsym.SetExtname(ldr.SymExtname(s))
1188 extsym.SetDynimpvers(ldr.SymDynimpvers(s))
1189
1190
1191 lds := &xcoffLoaderSymbol{
1192 sym: extsym.Sym(),
1193 smtype: XTY_IMP,
1194 smclas: XMC_DS,
1195 }
1196 if ldr.SymName(s) == "__n_pthreads" {
1197
1198
1199
1200 lds.smclas = XMC_RW
1201 }
1202 f.loaderSymbols = append(f.loaderSymbols, lds)
1203
1204
1205 sb.AddBytes(make([]byte, 8))
1206 r, _ := sb.AddRel(objabi.R_ADDR)
1207 r.SetSym(extsym.Sym())
1208 r.SetSiz(uint8(ctxt.Arch.PtrSize))
1209
1210
1211
1212
1213
1214
1215 }
1216
1217
1218
1219 func Xcoffadddynrel(target *Target, ldr *loader.Loader, syms *ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
1220 if target.IsExternal() {
1221 return true
1222 }
1223 if ldr.SymType(s) <= sym.SPCLNTAB {
1224 ldr.Errorf(s, "cannot have a relocation to %s in a text section symbol", ldr.SymName(r.Sym()))
1225 return false
1226 }
1227
1228 xldr := &xcoffLoaderReloc{
1229 sym: s,
1230 roff: r.Off(),
1231 }
1232 targ := r.Sym()
1233 var targType sym.SymKind
1234 if targ != 0 {
1235 targType = ldr.SymType(targ)
1236 }
1237
1238 switch r.Type() {
1239 default:
1240 ldr.Errorf(s, "unexpected .loader relocation to symbol: %s (type: %s)", ldr.SymName(targ), r.Type().String())
1241 return false
1242 case objabi.R_ADDR:
1243 if ldr.SymType(s) == sym.SXCOFFTOC && targType == sym.SDYNIMPORT {
1244
1245 for i, dynsym := range xfile.loaderSymbols {
1246 if ldr.SymName(dynsym.sym) == ldr.SymName(targ) {
1247 xldr.symndx = int32(i + 3)
1248 break
1249 }
1250 }
1251 } else if t := ldr.SymType(s); t.IsDATA() || t.IsNOPTRDATA() || t == sym.SBUILDINFO || t == sym.SXCOFFTOC || t == sym.SMODULEDATA {
1252 switch ldr.SymSect(targ).Seg {
1253 default:
1254 ldr.Errorf(s, "unknown segment for .loader relocation with symbol %s", ldr.SymName(targ))
1255 case &Segtext:
1256 case &Segrodata:
1257 xldr.symndx = 0
1258 case &Segdata:
1259 if targType == sym.SBSS || targType == sym.SNOPTRBSS || targType == sym.SGCMASK {
1260 xldr.symndx = 2
1261 } else {
1262 xldr.symndx = 1
1263 }
1264 }
1265
1266 } else {
1267 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))
1268 return false
1269 }
1270
1271 xldr.rtype = 0x3F<<8 + XCOFF_R_POS
1272 }
1273
1274 xfile.Lock()
1275 xfile.loaderReloc = append(xfile.loaderReloc, xldr)
1276 xfile.Unlock()
1277 return true
1278 }
1279
1280 func (ctxt *Link) doxcoff() {
1281 ldr := ctxt.loader
1282
1283
1284 toc := ldr.CreateSymForUpdate("TOC", 0)
1285 toc.SetType(sym.SXCOFFTOC)
1286 toc.SetVisibilityHidden(true)
1287
1288
1289 ep := ldr.Lookup(*flagEntrySymbol, 0)
1290 if ep == 0 || !ldr.AttrReachable(ep) {
1291 Exitf("wrong entry point")
1292 }
1293
1294 xfile.loaderSymbols = append(xfile.loaderSymbols, &xcoffLoaderSymbol{
1295 sym: ep,
1296 smtype: XTY_ENT | XTY_SD,
1297 smclas: XMC_DS,
1298 })
1299
1300 xfile.genDynSym(ctxt)
1301
1302 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
1303 if strings.HasPrefix(ldr.SymName(s), "TOC.") {
1304 sb := ldr.MakeSymbolUpdater(s)
1305 sb.SetType(sym.SXCOFFTOC)
1306 }
1307 }
1308
1309 if ctxt.IsExternal() {
1310
1311 rt0 := ldr.Lookup("runtime.rt0_go", 0)
1312 ldr.SetSymExtname(rt0, "runtime_rt0_go")
1313
1314 nsym := loader.Sym(ldr.NSym())
1315 for s := loader.Sym(1); s < nsym; s++ {
1316 if !ldr.AttrCgoExport(s) {
1317 continue
1318 }
1319 if ldr.IsFileLocal(s) {
1320 panic("cgo_export on static symbol")
1321 }
1322
1323 if ldr.SymType(s).IsText() {
1324
1325
1326
1327 name := ldr.SymExtname(s)
1328 ldr.SetSymExtname(s, "."+name)
1329
1330 desc := ldr.MakeSymbolUpdater(ldr.CreateExtSym(name, 0))
1331 desc.SetReachable(true)
1332 desc.SetType(sym.SNOPTRDATA)
1333 desc.AddAddr(ctxt.Arch, s)
1334 desc.AddAddr(ctxt.Arch, toc.Sym())
1335 desc.AddUint64(ctxt.Arch, 0)
1336 }
1337 }
1338 }
1339 }
1340
1341
1342
1343
1344
1345
1346 func Loaderblk(ctxt *Link, off uint64) {
1347 xfile.writeLdrScn(ctxt, off)
1348 }
1349
1350 func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) {
1351 var symtab []*XcoffLdSym64
1352 var strtab []*XcoffLdStr64
1353 var importtab []*XcoffLdImportFile64
1354 var reloctab []*XcoffLdRel64
1355 var dynimpreloc []*XcoffLdRel64
1356
1357
1358
1359 stlen := uint32(0)
1360
1361
1362 hdr := &XcoffLdHdr64{
1363 Lversion: 2,
1364 Lsymoff: LDHDRSZ_64,
1365 }
1366
1367 ldr := ctxt.loader
1368
1369 for _, s := range f.loaderSymbols {
1370 lds := &XcoffLdSym64{
1371 Loffset: stlen + 2,
1372 Lsmtype: s.smtype,
1373 Lsmclas: s.smclas,
1374 }
1375 sym := s.sym
1376 switch s.smtype {
1377 default:
1378 ldr.Errorf(sym, "unexpected loader symbol type: 0x%x", s.smtype)
1379 case XTY_ENT | XTY_SD:
1380 lds.Lvalue = uint64(ldr.SymValue(sym))
1381 lds.Lscnum = f.getXCOFFscnum(ldr.SymSect(sym))
1382 case XTY_IMP:
1383 lds.Lifile = int32(f.dynLibraries[ldr.SymDynimplib(sym)] + 1)
1384 }
1385 ldstr := &XcoffLdStr64{
1386 size: uint16(len(ldr.SymName(sym)) + 1),
1387 name: ldr.SymName(sym),
1388 }
1389 stlen += uint32(2 + ldstr.size)
1390 symtab = append(symtab, lds)
1391 strtab = append(strtab, ldstr)
1392
1393 }
1394
1395 hdr.Lnsyms = int32(len(symtab))
1396 hdr.Lrldoff = hdr.Lsymoff + uint64(24*hdr.Lnsyms)
1397 off := hdr.Lrldoff
1398
1399
1400
1401 sort.Slice(f.loaderReloc, func(i, j int) bool {
1402 r1, r2 := f.loaderReloc[i], f.loaderReloc[j]
1403 if r1.sym != r2.sym {
1404 return r1.sym < r2.sym
1405 }
1406 if r1.roff != r2.roff {
1407 return r1.roff < r2.roff
1408 }
1409 if r1.rtype != r2.rtype {
1410 return r1.rtype < r2.rtype
1411 }
1412 return r1.symndx < r2.symndx
1413 })
1414
1415 ep := ldr.Lookup(*flagEntrySymbol, 0)
1416 xldr := &XcoffLdRel64{
1417 Lvaddr: uint64(ldr.SymValue(ep)),
1418 Lrtype: 0x3F00,
1419 Lrsecnm: f.getXCOFFscnum(ldr.SymSect(ep)),
1420 Lsymndx: 0,
1421 }
1422 off += 16
1423 reloctab = append(reloctab, xldr)
1424
1425 off += uint64(16 * len(f.loaderReloc))
1426 for _, r := range f.loaderReloc {
1427 symp := r.sym
1428 if symp == 0 {
1429 panic("unexpected 0 sym value")
1430 }
1431 xldr = &XcoffLdRel64{
1432 Lvaddr: uint64(ldr.SymValue(symp) + int64(r.roff)),
1433 Lrtype: r.rtype,
1434 Lsymndx: r.symndx,
1435 }
1436
1437 if ldr.SymSect(symp) != nil {
1438 xldr.Lrsecnm = f.getXCOFFscnum(ldr.SymSect(symp))
1439 }
1440
1441 reloctab = append(reloctab, xldr)
1442 }
1443
1444 off += uint64(16 * len(dynimpreloc))
1445 reloctab = append(reloctab, dynimpreloc...)
1446
1447 hdr.Lnreloc = int32(len(reloctab))
1448 hdr.Limpoff = off
1449
1450
1451
1452 ldimpf := &XcoffLdImportFile64{
1453 Limpidpath: "/usr/lib:/lib",
1454 }
1455 off += uint64(len(ldimpf.Limpidpath) + len(ldimpf.Limpidbase) + len(ldimpf.Limpidmem) + 3)
1456 importtab = append(importtab, ldimpf)
1457
1458
1459
1460
1461 libsOrdered := make([]string, len(f.dynLibraries))
1462 for key, val := range f.dynLibraries {
1463 if libsOrdered[val] != "" {
1464 continue
1465 }
1466 libsOrdered[val] = key
1467 }
1468
1469 for _, lib := range libsOrdered {
1470
1471 n := strings.Split(lib, "/")
1472 path := ""
1473 base := n[len(n)-2]
1474 mem := n[len(n)-1]
1475 if len(n) > 2 {
1476 path = lib[:len(lib)-len(base)-len(mem)-2]
1477
1478 }
1479 ldimpf = &XcoffLdImportFile64{
1480 Limpidpath: path,
1481 Limpidbase: base,
1482 Limpidmem: mem,
1483 }
1484 off += uint64(len(ldimpf.Limpidpath) + len(ldimpf.Limpidbase) + len(ldimpf.Limpidmem) + 3)
1485 importtab = append(importtab, ldimpf)
1486 }
1487
1488 hdr.Lnimpid = int32(len(importtab))
1489 hdr.Listlen = uint32(off - hdr.Limpoff)
1490 hdr.Lstoff = off
1491 hdr.Lstlen = stlen
1492
1493
1494 ctxt.Out.SeekSet(int64(globalOff))
1495 binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, hdr)
1496
1497 for _, s := range symtab {
1498 binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, s)
1499
1500 }
1501 for _, r := range reloctab {
1502 binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, r)
1503 }
1504 for _, f := range importtab {
1505 ctxt.Out.WriteString(f.Limpidpath)
1506 ctxt.Out.Write8(0)
1507 ctxt.Out.WriteString(f.Limpidbase)
1508 ctxt.Out.Write8(0)
1509 ctxt.Out.WriteString(f.Limpidmem)
1510 ctxt.Out.Write8(0)
1511 }
1512 for _, s := range strtab {
1513 ctxt.Out.Write16(s.size)
1514 ctxt.Out.WriteString(s.name)
1515 ctxt.Out.Write8(0)
1516 }
1517
1518 f.loaderSize = off + uint64(stlen)
1519 }
1520
1521
1522
1523 func (f *xcoffFile) writeFileHeader(ctxt *Link) {
1524
1525 f.xfhdr.Fmagic = U64_TOCMAGIC
1526 f.xfhdr.Fnscns = uint16(len(f.sections))
1527 f.xfhdr.Ftimedat = 0
1528
1529 if !*FlagS {
1530 f.xfhdr.Fsymptr = uint64(f.symtabOffset)
1531 f.xfhdr.Fnsyms = int32(f.symbolCount)
1532 }
1533
1534 if ctxt.BuildMode == BuildModeExe && ctxt.LinkMode == LinkInternal {
1535 ldr := ctxt.loader
1536 f.xfhdr.Fopthdr = AOUTHSZ_EXEC64
1537 f.xfhdr.Fflags = F_EXEC
1538
1539
1540 f.xahdr.Ovstamp = 1
1541 f.xahdr.Omagic = 0x10b
1542 copy(f.xahdr.Omodtype[:], "1L")
1543 entry := ldr.Lookup(*flagEntrySymbol, 0)
1544 f.xahdr.Oentry = uint64(ldr.SymValue(entry))
1545 f.xahdr.Osnentry = f.getXCOFFscnum(ldr.SymSect(entry))
1546 toc := ldr.Lookup("TOC", 0)
1547 f.xahdr.Otoc = uint64(ldr.SymValue(toc))
1548 f.xahdr.Osntoc = f.getXCOFFscnum(ldr.SymSect(toc))
1549
1550 f.xahdr.Oalgntext = int16(logBase2(int(XCOFFSECTALIGN)))
1551 f.xahdr.Oalgndata = 0x5
1552
1553 binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr)
1554 binary.Write(ctxt.Out, binary.BigEndian, &f.xahdr)
1555 } else {
1556 f.xfhdr.Fopthdr = 0
1557 binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr)
1558 }
1559
1560 }
1561
1562 func xcoffwrite(ctxt *Link) {
1563 ctxt.Out.SeekSet(0)
1564
1565 xfile.writeFileHeader(ctxt)
1566
1567 for _, sect := range xfile.sections {
1568 sect.write(ctxt)
1569 }
1570 }
1571
1572
1573 func asmbXcoff(ctxt *Link) {
1574 ctxt.Out.SeekSet(0)
1575 fileoff := int64(Segdwarf.Fileoff + Segdwarf.Filelen)
1576 fileoff = Rnd(fileoff, *FlagRound)
1577
1578 xfile.sectNameToScnum = make(map[string]int16)
1579
1580
1581 s := xfile.addSection(".text", Segtext.Vaddr, Segtext.Length, Segtext.Fileoff, STYP_TEXT)
1582 xfile.xahdr.Otextstart = s.Svaddr
1583 xfile.xahdr.Osntext = xfile.sectNameToScnum[".text"]
1584 xfile.xahdr.Otsize = s.Ssize
1585 xfile.sectText = s
1586
1587 segdataVaddr := Segdata.Vaddr
1588 segdataFilelen := Segdata.Filelen
1589 segdataFileoff := Segdata.Fileoff
1590 segbssFilelen := Segdata.Length - Segdata.Filelen
1591 if len(Segrelrodata.Sections) > 0 {
1592
1593
1594 segdataVaddr = Segrelrodata.Vaddr
1595 segdataFileoff = Segrelrodata.Fileoff
1596 segdataFilelen = Segdata.Vaddr + Segdata.Filelen - Segrelrodata.Vaddr
1597 }
1598
1599 s = xfile.addSection(".data", segdataVaddr, segdataFilelen, segdataFileoff, STYP_DATA)
1600 xfile.xahdr.Odatastart = s.Svaddr
1601 xfile.xahdr.Osndata = xfile.sectNameToScnum[".data"]
1602 xfile.xahdr.Odsize = s.Ssize
1603 xfile.sectData = s
1604
1605 s = xfile.addSection(".bss", segdataVaddr+segdataFilelen, segbssFilelen, 0, STYP_BSS)
1606 xfile.xahdr.Osnbss = xfile.sectNameToScnum[".bss"]
1607 xfile.xahdr.Obsize = s.Ssize
1608 xfile.sectBss = s
1609
1610 if ctxt.LinkMode == LinkExternal {
1611 var tbss *sym.Section
1612 for _, s := range Segdata.Sections {
1613 if s.Name == ".tbss" {
1614 tbss = s
1615 break
1616 }
1617 }
1618 s = xfile.addSection(".tbss", tbss.Vaddr, tbss.Length, 0, STYP_TBSS)
1619 }
1620
1621
1622 for _, sect := range Segdwarf.Sections {
1623 xfile.addDwarfSection(sect)
1624 }
1625
1626
1627 if ctxt.LinkMode == LinkInternal {
1628
1629 if ctxt.BuildMode == BuildModeExe {
1630 Loaderblk(ctxt, uint64(fileoff))
1631 s = xfile.addSection(".loader", 0, xfile.loaderSize, uint64(fileoff), STYP_LOADER)
1632 xfile.xahdr.Osnloader = xfile.sectNameToScnum[".loader"]
1633
1634
1635 fileoff += int64(xfile.loaderSize)
1636 }
1637 }
1638
1639
1640 xfile.asmaixsym(ctxt)
1641
1642 if ctxt.LinkMode == LinkExternal {
1643 xfile.emitRelocations(ctxt, fileoff)
1644 }
1645
1646
1647 xfile.symtabOffset = ctxt.Out.Offset()
1648 for _, s := range xfile.symtabSym {
1649 binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, s)
1650 }
1651
1652 xfile.stringTable.write(ctxt.Out)
1653
1654
1655 xcoffwrite(ctxt)
1656 }
1657
1658
1659 func (f *xcoffFile) emitRelocations(ctxt *Link, fileoff int64) {
1660 ctxt.Out.SeekSet(fileoff)
1661 for ctxt.Out.Offset()&7 != 0 {
1662 ctxt.Out.Write8(0)
1663 }
1664
1665 ldr := ctxt.loader
1666
1667
1668 relocsect := func(sect *sym.Section, syms []loader.Sym, base uint64) uint32 {
1669
1670
1671 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
1672 return 0
1673 }
1674 sect.Reloff = uint64(ctxt.Out.Offset())
1675 for i, s := range syms {
1676 if !ldr.AttrReachable(s) {
1677 continue
1678 }
1679 if uint64(ldr.SymValue(s)) >= sect.Vaddr {
1680 syms = syms[i:]
1681 break
1682 }
1683 }
1684 eaddr := int64(sect.Vaddr + sect.Length)
1685 for _, s := range syms {
1686 if !ldr.AttrReachable(s) {
1687 continue
1688 }
1689 if ldr.SymValue(s) >= eaddr {
1690 break
1691 }
1692
1693
1694
1695 relocs := ldr.Relocs(s)
1696 sorted := make([]int, relocs.Count())
1697 for i := 0; i < relocs.Count(); i++ {
1698 sorted[i] = i
1699 }
1700 sort.Slice(sorted, func(i, j int) bool {
1701 return relocs.At(sorted[i]).Off() < relocs.At(sorted[j]).Off()
1702 })
1703
1704 for _, ri := range sorted {
1705 r := relocs.At(ri)
1706 rr, ok := extreloc(ctxt, ldr, s, r)
1707 if !ok {
1708 continue
1709 }
1710 if rr.Xsym == 0 {
1711 ldr.Errorf(s, "missing xsym in relocation")
1712 continue
1713 }
1714 if ldr.SymDynid(rr.Xsym) < 0 {
1715 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))
1716 }
1717 if !thearch.Xcoffreloc1(ctxt.Arch, ctxt.Out, ldr, s, rr, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-base)) {
1718 ldr.Errorf(s, "unsupported obj reloc %d(%s)/%d to %s", r.Type(), r.Type(), r.Siz(), ldr.SymName(r.Sym()))
1719 }
1720 }
1721 }
1722 sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
1723 return uint32(sect.Rellen) / RELSZ_64
1724 }
1725 sects := []struct {
1726 xcoffSect *XcoffScnHdr64
1727 segs []*sym.Segment
1728 }{
1729 {f.sectText, []*sym.Segment{&Segtext}},
1730 {f.sectData, []*sym.Segment{&Segrelrodata, &Segdata}},
1731 }
1732 for _, s := range sects {
1733 s.xcoffSect.Srelptr = uint64(ctxt.Out.Offset())
1734 n := uint32(0)
1735 for _, seg := range s.segs {
1736 for _, sect := range seg.Sections {
1737 if sect.Name == ".text" {
1738 n += relocsect(sect, ctxt.Textp, 0)
1739 } else {
1740 n += relocsect(sect, ctxt.datap, 0)
1741 }
1742 }
1743 }
1744 s.xcoffSect.Snreloc += n
1745 }
1746
1747 dwarfLoop:
1748 for i := 0; i < len(Segdwarf.Sections); i++ {
1749 sect := Segdwarf.Sections[i]
1750 si := dwarfp[i]
1751 if si.secSym() != sect.Sym ||
1752 ldr.SymSect(si.secSym()) != sect {
1753 panic("inconsistency between dwarfp and Segdwarf")
1754 }
1755 for _, xcoffSect := range f.sections {
1756 _, subtyp := xcoffGetDwarfSubtype(sect.Name)
1757 if xcoffSect.Sflags&0xF0000 == subtyp {
1758 xcoffSect.Srelptr = uint64(ctxt.Out.Offset())
1759 xcoffSect.Snreloc = relocsect(sect, si.syms, sect.Vaddr)
1760 continue dwarfLoop
1761 }
1762 }
1763 Errorf("emitRelocations: could not find %q section", sect.Name)
1764 }
1765 }
1766
1767
1768
1769
1770 func xcoffCreateExportFile(ctxt *Link) (fname string) {
1771 fname = filepath.Join(*flagTmpdir, "export_file.exp")
1772 var buf bytes.Buffer
1773
1774 ldr := ctxt.loader
1775 for s := range ldr.ForAllCgoExportStatic() {
1776 extname := ldr.SymExtname(s)
1777 if !strings.HasPrefix(extname, "._cgoexp_") {
1778 continue
1779 }
1780 if ldr.IsFileLocal(s) {
1781 continue
1782 }
1783
1784
1785
1786
1787
1788 name := strings.SplitN(extname, "_", 4)[3]
1789
1790 buf.Write([]byte(name + "\n"))
1791 }
1792
1793 err := os.WriteFile(fname, buf.Bytes(), 0666)
1794 if err != nil {
1795 Errorf("WriteFile %s failed: %v", fname, err)
1796 }
1797
1798 return fname
1799 }
1800
View as plain text