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