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