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