1
2
3
4
5 package ld
6
7 import (
8 "bytes"
9 "cmd/internal/objabi"
10 "cmd/link/internal/loader"
11 "cmd/link/internal/sym"
12 "encoding/binary"
13 "fmt"
14 "io/ioutil"
15 "math/bits"
16 "path/filepath"
17 "sort"
18 "strings"
19 "sync"
20 )
21
22
23
24
25
26
27 const (
28
29
30
31 XCOFFHDRRESERVE = FILHSZ_64 + AOUTHSZ_EXEC64 + SCNHSZ_64*23
32
33
34
35 XCOFFSECTALIGN int64 = 64
36
37
38
39
40
41
42 XCOFFTEXTBASE = 0x100000000
43 XCOFFDATABASE = 0x200000000
44 )
45
46
47 type XcoffFileHdr64 struct {
48 Fmagic uint16
49 Fnscns uint16
50 Ftimedat int32
51 Fsymptr uint64
52 Fopthdr uint16
53 Fflags uint16
54 Fnsyms int32
55 }
56
57 const (
58 U64_TOCMAGIC = 0767
59 )
60
61
62 const (
63 F_RELFLG = 0x0001
64 F_EXEC = 0x0002
65 F_LNNO = 0x0004
66 F_FDPR_PROF = 0x0010
67 F_FDPR_OPTI = 0x0020
68 F_DSA = 0x0040
69 F_VARPG = 0x0100
70 F_DYNLOAD = 0x1000
71 F_SHROBJ = 0x2000
72 F_LOADONLY = 0x4000
73 )
74
75
76 type XcoffAoutHdr64 struct {
77 Omagic int16
78 Ovstamp int16
79 Odebugger uint32
80 Otextstart uint64
81 Odatastart uint64
82 Otoc uint64
83 Osnentry int16
84 Osntext int16
85 Osndata int16
86 Osntoc int16
87 Osnloader int16
88 Osnbss int16
89 Oalgntext int16
90 Oalgndata int16
91 Omodtype [2]byte
92 Ocpuflag uint8
93 Ocputype uint8
94 Otextpsize uint8
95 Odatapsize uint8
96 Ostackpsize uint8
97 Oflags uint8
98 Otsize uint64
99 Odsize uint64
100 Obsize uint64
101 Oentry uint64
102 Omaxstack uint64
103 Omaxdata uint64
104 Osntdata int16
105 Osntbss int16
106 Ox64flags uint16
107 Oresv3a int16
108 Oresv3 [2]int32
109 }
110
111
112 type XcoffScnHdr64 struct {
113 Sname [8]byte
114 Spaddr uint64
115 Svaddr uint64
116 Ssize uint64
117 Sscnptr uint64
118 Srelptr uint64
119 Slnnoptr uint64
120 Snreloc uint32
121 Snlnno uint32
122 Sflags uint32
123 }
124
125
126 const (
127 STYP_DWARF = 0x0010
128 STYP_TEXT = 0x0020
129 STYP_DATA = 0x0040
130 STYP_BSS = 0x0080
131 STYP_EXCEPT = 0x0100
132 STYP_INFO = 0x0200
133 STYP_TDATA = 0x0400
134 STYP_TBSS = 0x0800
135 STYP_LOADER = 0x1000
136 STYP_DEBUG = 0x2000
137 STYP_TYPCHK = 0x4000
138 STYP_OVRFLO = 0x8000
139 )
140 const (
141 SSUBTYP_DWINFO = 0x10000
142 SSUBTYP_DWLINE = 0x20000
143 SSUBTYP_DWPBNMS = 0x30000
144 SSUBTYP_DWPBTYP = 0x40000
145 SSUBTYP_DWARNGE = 0x50000
146 SSUBTYP_DWABREV = 0x60000
147 SSUBTYP_DWSTR = 0x70000
148 SSUBTYP_DWRNGES = 0x80000
149 SSUBTYP_DWLOC = 0x90000
150 SSUBTYP_DWFRAME = 0xA0000
151 SSUBTYP_DWMAC = 0xB0000
152 )
153
154
155 const (
156 FILHSZ_32 = 20
157 FILHSZ_64 = 24
158 AOUTHSZ_EXEC32 = 72
159 AOUTHSZ_EXEC64 = 120
160 SCNHSZ_32 = 40
161 SCNHSZ_64 = 72
162 LDHDRSZ_32 = 32
163 LDHDRSZ_64 = 56
164 LDSYMSZ_64 = 24
165 RELSZ_64 = 14
166 )
167
168
169 type xcoffSym interface {
170 }
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(nil, "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 *FlagTextAddr != -1 {
547 Errorf(nil, "-T not available on AIX")
548 }
549 *FlagTextAddr = XCOFFTEXTBASE + int64(HEADR)
550 if *FlagRound != -1 {
551 Errorf(nil, "-R not available on AIX")
552 }
553 *FlagRound = int(XCOFFSECTALIGN)
554
555 }
556
557
558
559
560 type xcoffSymSrcFile struct {
561 name string
562 file *XcoffSymEnt64
563 csectAux *XcoffAuxCSect64
564 csectSymNb uint64
565 csectVAStart int64
566 csectVAEnd int64
567 }
568
569 var (
570 currDwscnoff = make(map[string]uint64)
571 currSymSrcFile xcoffSymSrcFile
572 outerSymSize = make(map[string]int64)
573 )
574
575
576
577 func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
578 if size == 0 {
579 return
580 }
581
582
583 ldr := ctxt.loader
584 switch stype {
585 default:
586 Errorf(nil, "unknown XCOFF outer symbol for type %s", stype.String())
587 case sym.SRODATA, sym.SRODATARELRO, sym.SFUNCTAB, sym.SSTRING:
588
589 case sym.STYPERELRO:
590 if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
591
592 tsize := ldr.SymSize(ldr.Lookup("runtime.types", 0))
593 outerSymSize["typerel.*"] = size - tsize
594 return
595 }
596 fallthrough
597 case sym.STYPE:
598 if !ctxt.DynlinkingGo() {
599
600 tsize := ldr.SymSize(ldr.Lookup("runtime.types", 0))
601 outerSymSize["type.*"] = size - tsize
602 }
603 case sym.SGOSTRING:
604 outerSymSize["go.string.*"] = size
605 case sym.SGOFUNC:
606 if !ctxt.DynlinkingGo() {
607 outerSymSize["go.func.*"] = size
608 }
609 case sym.SGOFUNCRELRO:
610 outerSymSize["go.funcrel.*"] = size
611 case sym.SGCBITS:
612 outerSymSize["runtime.gcbits.*"] = size
613 case sym.SPCLNTAB:
614 outerSymSize["runtime.pclntab"] = size
615 }
616 }
617
618
619 func (f *xcoffFile) addSymbol(sym xcoffSym) {
620 f.symtabSym = append(f.symtabSym, sym)
621 f.symbolCount++
622 }
623
624
625 func xcoffAlign(ldr *loader.Loader, x loader.Sym, t SymbolType) uint8 {
626 align := ldr.SymAlign(x)
627 if align == 0 {
628 if t == TextSym {
629 align = int32(Funcalign)
630 } else {
631 align = symalign(ldr, x)
632 }
633 }
634 return logBase2(int(align))
635 }
636
637
638 func logBase2(a int) uint8 {
639 return uint8(bits.Len(uint(a)) - 1)
640 }
641
642
643
644
645
646
647
648
649
650 func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint64, extnum int16) {
651 ldr := ctxt.loader
652
653 s := &XcoffSymEnt64{
654 Noffset: uint32(f.stringTable.add(".file")),
655 Nsclass: C_FILE,
656 Nscnum: N_DEBUG,
657 Ntype: 0,
658 Nnumaux: 1,
659 }
660 f.addSymbol(s)
661 currSymSrcFile.file = s
662
663
664 auxf := &XcoffAuxFile64{
665 Xoffset: uint32(f.stringTable.add(name)),
666 Xftype: XFT_FN,
667 Xauxtype: _AUX_FILE,
668 }
669 f.addSymbol(auxf)
670
671
672 for _, sect := range Segdwarf.Sections {
673 var dwsize uint64
674 if ctxt.LinkMode == LinkInternal {
675
676
677 dwsize = getDwsectCUSize(sect.Name, name)
678
679 if sect.Name == ".debug_abbrev" {
680 dwsize = uint64(ldr.SymSize(loader.Sym(sect.Sym)))
681
682 }
683 } else {
684
685 dwsize = sect.Length
686 }
687
688
689 name, _ := xcoffGetDwarfSubtype(sect.Name)
690 s := &XcoffSymEnt64{
691 Nvalue: currDwscnoff[sect.Name],
692 Noffset: uint32(f.stringTable.add(name)),
693 Nsclass: C_DWARF,
694 Nscnum: f.getXCOFFscnum(sect),
695 Nnumaux: 1,
696 }
697
698 if currSymSrcFile.csectAux == nil {
699
700
701
702 ldr.SetSymDynid(loader.Sym(sect.Sym), int32(f.symbolCount))
703
704 if sect.Name == ".debug_frame" && ctxt.LinkMode != LinkExternal {
705
706 dwsize += 48
707 }
708 }
709
710 f.addSymbol(s)
711
712
713 if sect.Name != ".debug_abbrev" {
714 currDwscnoff[sect.Name] += dwsize
715 }
716
717
718 auxd := &XcoffAuxDWARF64{
719 Xscnlen: dwsize,
720 Xauxtype: _AUX_SECT,
721 }
722
723 f.addSymbol(auxd)
724 }
725
726
727
728
729 if extnum != 1 {
730 Exitf("XCOFF symtab: A new file was detected with its first symbol not in .text")
731 }
732
733 currSymSrcFile.csectSymNb = uint64(f.symbolCount)
734
735
736 s = &XcoffSymEnt64{
737 Nvalue: firstEntry,
738 Nscnum: extnum,
739 Nsclass: C_HIDEXT,
740 Ntype: 0,
741 Nnumaux: 1,
742 }
743 f.addSymbol(s)
744
745 aux := &XcoffAuxCSect64{
746 Xsmclas: XMC_PR,
747 Xsmtyp: XTY_SD | logBase2(Funcalign)<<3,
748 Xauxtype: _AUX_CSECT,
749 }
750 f.addSymbol(aux)
751
752 currSymSrcFile.csectAux = aux
753 currSymSrcFile.csectVAStart = int64(firstEntry)
754 currSymSrcFile.csectVAEnd = int64(firstEntry)
755 }
756
757
758
759
760 func (f *xcoffFile) updatePreviousFile(ctxt *Link, last bool) {
761
762 if currSymSrcFile.file == nil {
763 return
764 }
765
766
767 cfile := currSymSrcFile.file
768 if last {
769 cfile.Nvalue = 0xFFFFFFFFFFFFFFFF
770 } else {
771 cfile.Nvalue = uint64(f.symbolCount)
772 }
773
774
775 aux := currSymSrcFile.csectAux
776 csectSize := currSymSrcFile.csectVAEnd - currSymSrcFile.csectVAStart
777 aux.Xscnlenlo = uint32(csectSize & 0xFFFFFFFF)
778 aux.Xscnlenhi = uint32(csectSize >> 32)
779 }
780
781
782
783
784 func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x loader.Sym) []xcoffSym {
785
786 syms := []xcoffSym{}
787
788
789 ldr := ctxt.loader
790 name := ldr.SymName(x)
791 if strings.Contains(name, "-tramp") || strings.HasPrefix(name, "runtime.text.") {
792
793
794
795 } else if ldr.SymPkg(x) == "" {
796
797 if currSymSrcFile.name != "" {
798 Exitf("undefined global symbol found inside another file")
799 }
800 } else {
801
802 if currSymSrcFile.name != ldr.SymPkg(x) {
803 if ctxt.LinkMode == LinkInternal {
804
805 xfile.updatePreviousFile(ctxt, false)
806 currSymSrcFile.name = ldr.SymPkg(x)
807 f.writeSymbolNewFile(ctxt, ldr.SymPkg(x), uint64(ldr.SymValue(x)), xfile.getXCOFFscnum(ldr.SymSect(x)))
808 } else {
809
810
811
812
813
814
815
816 if currSymSrcFile.name == "" {
817 currSymSrcFile.name = ldr.SymPkg(x)
818 f.writeSymbolNewFile(ctxt, "go_functions", uint64(ldr.SymValue(x)), xfile.getXCOFFscnum(ldr.SymSect(x)))
819 }
820 }
821
822 }
823 }
824
825 name = ldr.SymExtname(x)
826 name = mangleABIName(ctxt, ldr, x, name)
827
828 s := &XcoffSymEnt64{
829 Nsclass: C_EXT,
830 Noffset: uint32(xfile.stringTable.add(name)),
831 Nvalue: uint64(ldr.SymValue(x)),
832 Nscnum: f.getXCOFFscnum(ldr.SymSect(x)),
833 Ntype: SYM_TYPE_FUNC,
834 Nnumaux: 2,
835 }
836
837 if ldr.IsFileLocal(x) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
838 s.Nsclass = C_HIDEXT
839 }
840
841 ldr.SetSymDynid(x, int32(xfile.symbolCount))
842 syms = append(syms, s)
843
844
845
846
847 sv := ldr.SymValue(x) + ldr.SymSize(x)
848 if currSymSrcFile.csectVAEnd < sv {
849 currSymSrcFile.csectVAEnd = sv
850 }
851
852
853 a2 := &XcoffAuxFcn64{
854 Xfsize: uint32(ldr.SymSize(x)),
855 Xlnnoptr: 0,
856 Xendndx: xfile.symbolCount + 3,
857 Xauxtype: _AUX_FCN,
858 }
859 syms = append(syms, a2)
860
861 a4 := &XcoffAuxCSect64{
862 Xscnlenlo: uint32(currSymSrcFile.csectSymNb & 0xFFFFFFFF),
863 Xscnlenhi: uint32(currSymSrcFile.csectSymNb >> 32),
864 Xsmclas: XMC_PR,
865 Xsmtyp: XTY_LD,
866 Xauxtype: _AUX_CSECT,
867 }
868 a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, TextSym) << 3)
869
870 syms = append(syms, a4)
871 return syms
872 }
873
874
875 func putaixsym(ctxt *Link, x loader.Sym, t SymbolType) {
876
877
878 syms := []xcoffSym{}
879
880 ldr := ctxt.loader
881 name := ldr.SymName(x)
882 if t == UndefinedSym {
883 name = ldr.SymExtname(x)
884 }
885
886 switch t {
887 default:
888 return
889
890 case TextSym:
891 if ldr.SymPkg(x) != "" || strings.Contains(name, "-tramp") || strings.HasPrefix(name, "runtime.text.") {
892
893 syms = xfile.writeSymbolFunc(ctxt, x)
894 } else {
895
896 if name != "runtime.text" && name != "runtime.etext" && name != "go.buildid" {
897 Exitf("putaixsym: unknown text symbol %s", name)
898 }
899 s := &XcoffSymEnt64{
900 Nsclass: C_HIDEXT,
901 Noffset: uint32(xfile.stringTable.add(name)),
902 Nvalue: uint64(ldr.SymValue(x)),
903 Nscnum: xfile.getXCOFFscnum(ldr.SymSect(x)),
904 Ntype: SYM_TYPE_FUNC,
905 Nnumaux: 1,
906 }
907 ldr.SetSymDynid(x, int32(xfile.symbolCount))
908 syms = append(syms, s)
909
910 size := uint64(ldr.SymSize(x))
911 a4 := &XcoffAuxCSect64{
912 Xauxtype: _AUX_CSECT,
913 Xscnlenlo: uint32(size & 0xFFFFFFFF),
914 Xscnlenhi: uint32(size >> 32),
915 Xsmclas: XMC_PR,
916 Xsmtyp: XTY_SD,
917 }
918 a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, TextSym) << 3)
919 syms = append(syms, a4)
920 }
921
922 case DataSym, BSSSym:
923 s := &XcoffSymEnt64{
924 Nsclass: C_EXT,
925 Noffset: uint32(xfile.stringTable.add(name)),
926 Nvalue: uint64(ldr.SymValue(x)),
927 Nscnum: xfile.getXCOFFscnum(ldr.SymSect(x)),
928 Nnumaux: 1,
929 }
930
931 if ldr.IsFileLocal(x) || ldr.AttrVisibilityHidden(x) || ldr.AttrLocal(x) {
932
933
934
935
936
937
938 s.Nsclass = C_HIDEXT
939 }
940
941 ldr.SetSymDynid(x, int32(xfile.symbolCount))
942 syms = append(syms, s)
943
944
945
946
947
948
949
950 size := uint64(ldr.SymSize(x))
951 a4 := &XcoffAuxCSect64{
952 Xauxtype: _AUX_CSECT,
953 Xscnlenlo: uint32(size & 0xFFFFFFFF),
954 Xscnlenhi: uint32(size >> 32),
955 }
956
957 if ty := ldr.SymType(x); ty >= sym.STYPE && ty <= sym.SPCLNTAB {
958 if ctxt.IsExternal() && strings.HasPrefix(ldr.SymSect(x).Name, ".data.rel.ro") {
959
960
961 a4.Xsmclas = XMC_RW
962 } else {
963
964 a4.Xsmclas = XMC_RO
965 }
966 } else if strings.HasPrefix(ldr.SymName(x), "TOC.") && ctxt.IsExternal() {
967 a4.Xsmclas = XMC_TC
968 } else if ldr.SymName(x) == "TOC" {
969 a4.Xsmclas = XMC_TC0
970 } else {
971 a4.Xsmclas = XMC_RW
972 }
973 if t == DataSym {
974 a4.Xsmtyp |= XTY_SD
975 } else {
976 a4.Xsmtyp |= XTY_CM
977 }
978
979 a4.Xsmtyp |= uint8(xcoffAlign(ldr, x, t) << 3)
980
981 syms = append(syms, a4)
982
983 case UndefinedSym:
984 if ty := ldr.SymType(x); ty != sym.SDYNIMPORT && ty != sym.SHOSTOBJ && ty != sym.SUNDEFEXT {
985 return
986 }
987 s := &XcoffSymEnt64{
988 Nsclass: C_EXT,
989 Noffset: uint32(xfile.stringTable.add(name)),
990 Nnumaux: 1,
991 }
992 ldr.SetSymDynid(x, int32(xfile.symbolCount))
993 syms = append(syms, s)
994
995 a4 := &XcoffAuxCSect64{
996 Xauxtype: _AUX_CSECT,
997 Xsmclas: XMC_DS,
998 Xsmtyp: XTY_ER | XTY_IMP,
999 }
1000
1001 if ldr.SymName(x) == "__n_pthreads" {
1002
1003
1004
1005 a4.Xsmclas = XMC_RW
1006 }
1007
1008 syms = append(syms, a4)
1009
1010 case TLSSym:
1011 s := &XcoffSymEnt64{
1012 Nsclass: C_EXT,
1013 Noffset: uint32(xfile.stringTable.add(name)),
1014 Nscnum: xfile.getXCOFFscnum(ldr.SymSect(x)),
1015 Nvalue: uint64(ldr.SymValue(x)),
1016 Nnumaux: 1,
1017 }
1018
1019 ldr.SetSymDynid(x, int32(xfile.symbolCount))
1020 syms = append(syms, s)
1021
1022 size := uint64(ldr.SymSize(x))
1023 a4 := &XcoffAuxCSect64{
1024 Xauxtype: _AUX_CSECT,
1025 Xsmclas: XMC_UL,
1026 Xsmtyp: XTY_CM,
1027 Xscnlenlo: uint32(size & 0xFFFFFFFF),
1028 Xscnlenhi: uint32(size >> 32),
1029 }
1030
1031 syms = append(syms, a4)
1032 }
1033
1034 for _, s := range syms {
1035 xfile.addSymbol(s)
1036 }
1037 }
1038
1039
1040
1041
1042 func (f *xcoffFile) asmaixsym(ctxt *Link) {
1043 ldr := ctxt.loader
1044
1045
1046 for name, size := range outerSymSize {
1047 sym := ldr.Lookup(name, 0)
1048 if sym == 0 {
1049 Errorf(nil, "unknown outer symbol with name %s", name)
1050 } else {
1051 s := ldr.MakeSymbolUpdater(sym)
1052 s.SetSize(size)
1053 }
1054 }
1055
1056
1057
1058 s := ldr.Lookup("runtime.text", 0)
1059 if ldr.SymType(s) == sym.STEXT {
1060
1061
1062 if !ctxt.IsExternal() {
1063 putaixsym(ctxt, s, TextSym)
1064 }
1065 }
1066
1067 n := 1
1068
1069 for _, sect := range Segtext.Sections[1:] {
1070 if sect.Name != ".text" || ctxt.IsExternal() {
1071
1072 break
1073 }
1074 s = ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
1075 if s == 0 {
1076 break
1077 }
1078 if ldr.SymType(s) == sym.STEXT {
1079 putaixsym(ctxt, s, TextSym)
1080 }
1081 n++
1082 }
1083
1084 s = ldr.Lookup("runtime.etext", 0)
1085 if ldr.SymType(s) == sym.STEXT {
1086
1087
1088
1089 if !ctxt.IsExternal() {
1090 putaixsym(ctxt, s, TextSym)
1091 }
1092 }
1093
1094 shouldBeInSymbolTable := func(s loader.Sym, name string) bool {
1095 if name == ".go.buildinfo" {
1096
1097
1098 return true
1099 }
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_EXTRA_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.SXREF:
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 || *flagN {
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 == sym.SDATA || t == sym.SNOPTRDATA || t == sym.SBUILDINFO || t == sym.SXCOFFTOC {
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) == sym.STEXT {
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: uint32(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 = int64(Rnd(int64(fileoff), int64(*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) >= int64(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() != loader.Sym(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(nil, "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, nsym := loader.Sym(1), loader.Sym(ldr.NSym()); s < nsym; s++ {
1788 if !ldr.AttrCgoExport(s) {
1789 continue
1790 }
1791 extname := ldr.SymExtname(s)
1792 if !strings.HasPrefix(extname, "._cgoexp_") {
1793 continue
1794 }
1795 if ldr.IsFileLocal(s) {
1796 continue
1797 }
1798
1799
1800
1801
1802
1803 name := strings.SplitN(extname, "_", 4)[3]
1804
1805 buf.Write([]byte(name + "\n"))
1806 }
1807
1808 err := ioutil.WriteFile(fname, buf.Bytes(), 0666)
1809 if err != nil {
1810 Errorf(nil, "WriteFile %s failed: %v", fname, err)
1811 }
1812
1813 return fname
1814 }
1815
View as plain text