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