]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/link/internal/ld/pe.go
cmd/internal/link: merge .pdata and .xdata sections from host object files
[gostls13.git] / src / cmd / link / internal / ld / pe.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // PE (Portable Executable) file writing
6 // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
7
8 package ld
9
10 import (
11         "cmd/internal/objabi"
12         "cmd/internal/sys"
13         "cmd/link/internal/loader"
14         "cmd/link/internal/sym"
15         "debug/pe"
16         "encoding/binary"
17         "fmt"
18         "internal/buildcfg"
19         "sort"
20         "strconv"
21         "strings"
22 )
23
24 type IMAGE_IMPORT_DESCRIPTOR struct {
25         OriginalFirstThunk uint32
26         TimeDateStamp      uint32
27         ForwarderChain     uint32
28         Name               uint32
29         FirstThunk         uint32
30 }
31
32 type IMAGE_EXPORT_DIRECTORY struct {
33         Characteristics       uint32
34         TimeDateStamp         uint32
35         MajorVersion          uint16
36         MinorVersion          uint16
37         Name                  uint32
38         Base                  uint32
39         NumberOfFunctions     uint32
40         NumberOfNames         uint32
41         AddressOfFunctions    uint32
42         AddressOfNames        uint32
43         AddressOfNameOrdinals uint32
44 }
45
46 var (
47         // PEBASE is the base address for the executable.
48         // It is small for 32-bit and large for 64-bit.
49         PEBASE int64
50
51         // SectionAlignment must be greater than or equal to FileAlignment.
52         // The default is the page size for the architecture.
53         PESECTALIGN int64 = 0x1000
54
55         // FileAlignment should be a power of 2 between 512 and 64 K, inclusive.
56         // The default is 512. If the SectionAlignment is less than
57         // the architecture's page size, then FileAlignment must match SectionAlignment.
58         PEFILEALIGN int64 = 2 << 8
59 )
60
61 const (
62         IMAGE_SCN_CNT_CODE               = 0x00000020
63         IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
64         IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
65         IMAGE_SCN_LNK_OTHER              = 0x00000100
66         IMAGE_SCN_LNK_INFO               = 0x00000200
67         IMAGE_SCN_LNK_REMOVE             = 0x00000800
68         IMAGE_SCN_LNK_COMDAT             = 0x00001000
69         IMAGE_SCN_GPREL                  = 0x00008000
70         IMAGE_SCN_MEM_PURGEABLE          = 0x00020000
71         IMAGE_SCN_MEM_16BIT              = 0x00020000
72         IMAGE_SCN_MEM_LOCKED             = 0x00040000
73         IMAGE_SCN_MEM_PRELOAD            = 0x00080000
74         IMAGE_SCN_ALIGN_1BYTES           = 0x00100000
75         IMAGE_SCN_ALIGN_2BYTES           = 0x00200000
76         IMAGE_SCN_ALIGN_4BYTES           = 0x00300000
77         IMAGE_SCN_ALIGN_8BYTES           = 0x00400000
78         IMAGE_SCN_ALIGN_16BYTES          = 0x00500000
79         IMAGE_SCN_ALIGN_32BYTES          = 0x00600000
80         IMAGE_SCN_ALIGN_64BYTES          = 0x00700000
81         IMAGE_SCN_ALIGN_128BYTES         = 0x00800000
82         IMAGE_SCN_ALIGN_256BYTES         = 0x00900000
83         IMAGE_SCN_ALIGN_512BYTES         = 0x00A00000
84         IMAGE_SCN_ALIGN_1024BYTES        = 0x00B00000
85         IMAGE_SCN_ALIGN_2048BYTES        = 0x00C00000
86         IMAGE_SCN_ALIGN_4096BYTES        = 0x00D00000
87         IMAGE_SCN_ALIGN_8192BYTES        = 0x00E00000
88         IMAGE_SCN_LNK_NRELOC_OVFL        = 0x01000000
89         IMAGE_SCN_MEM_DISCARDABLE        = 0x02000000
90         IMAGE_SCN_MEM_NOT_CACHED         = 0x04000000
91         IMAGE_SCN_MEM_NOT_PAGED          = 0x08000000
92         IMAGE_SCN_MEM_SHARED             = 0x10000000
93         IMAGE_SCN_MEM_EXECUTE            = 0x20000000
94         IMAGE_SCN_MEM_READ               = 0x40000000
95         IMAGE_SCN_MEM_WRITE              = 0x80000000
96 )
97
98 // See https://docs.microsoft.com/en-us/windows/win32/debug/pe-format.
99 // TODO(crawshaw): add these constants to debug/pe.
100 const (
101         IMAGE_SYM_TYPE_NULL      = 0
102         IMAGE_SYM_TYPE_STRUCT    = 8
103         IMAGE_SYM_DTYPE_FUNCTION = 2
104         IMAGE_SYM_DTYPE_ARRAY    = 3
105         IMAGE_SYM_CLASS_EXTERNAL = 2
106         IMAGE_SYM_CLASS_STATIC   = 3
107
108         IMAGE_REL_I386_DIR32   = 0x0006
109         IMAGE_REL_I386_DIR32NB = 0x0007
110         IMAGE_REL_I386_SECREL  = 0x000B
111         IMAGE_REL_I386_REL32   = 0x0014
112
113         IMAGE_REL_AMD64_ADDR64   = 0x0001
114         IMAGE_REL_AMD64_ADDR32   = 0x0002
115         IMAGE_REL_AMD64_ADDR32NB = 0x0003
116         IMAGE_REL_AMD64_REL32    = 0x0004
117         IMAGE_REL_AMD64_SECREL   = 0x000B
118
119         IMAGE_REL_ARM_ABSOLUTE = 0x0000
120         IMAGE_REL_ARM_ADDR32   = 0x0001
121         IMAGE_REL_ARM_ADDR32NB = 0x0002
122         IMAGE_REL_ARM_BRANCH24 = 0x0003
123         IMAGE_REL_ARM_BRANCH11 = 0x0004
124         IMAGE_REL_ARM_SECREL   = 0x000F
125
126         IMAGE_REL_ARM64_ABSOLUTE       = 0x0000
127         IMAGE_REL_ARM64_ADDR32         = 0x0001
128         IMAGE_REL_ARM64_ADDR32NB       = 0x0002
129         IMAGE_REL_ARM64_BRANCH26       = 0x0003
130         IMAGE_REL_ARM64_PAGEBASE_REL21 = 0x0004
131         IMAGE_REL_ARM64_REL21          = 0x0005
132         IMAGE_REL_ARM64_PAGEOFFSET_12A = 0x0006
133         IMAGE_REL_ARM64_PAGEOFFSET_12L = 0x0007
134         IMAGE_REL_ARM64_SECREL         = 0x0008
135         IMAGE_REL_ARM64_SECREL_LOW12A  = 0x0009
136         IMAGE_REL_ARM64_SECREL_HIGH12A = 0x000A
137         IMAGE_REL_ARM64_SECREL_LOW12L  = 0x000B
138         IMAGE_REL_ARM64_TOKEN          = 0x000C
139         IMAGE_REL_ARM64_SECTION        = 0x000D
140         IMAGE_REL_ARM64_ADDR64         = 0x000E
141         IMAGE_REL_ARM64_BRANCH19       = 0x000F
142         IMAGE_REL_ARM64_BRANCH14       = 0x0010
143         IMAGE_REL_ARM64_REL32          = 0x0011
144
145         IMAGE_REL_BASED_HIGHLOW = 3
146         IMAGE_REL_BASED_DIR64   = 10
147 )
148
149 const (
150         PeMinimumTargetMajorVersion = 6
151         PeMinimumTargetMinorVersion = 1
152 )
153
154 // DOS stub that prints out
155 // "This program cannot be run in DOS mode."
156 // See IMAGE_DOS_HEADER in the Windows SDK for the format of the header used here.
157 var dosstub = []uint8{
158         0x4d,
159         0x5a,
160         0x90,
161         0x00,
162         0x03,
163         0x00,
164         0x00,
165         0x00,
166         0x04,
167         0x00,
168         0x00,
169         0x00,
170         0xff,
171         0xff,
172         0x00,
173         0x00,
174         0x8b,
175         0x00,
176         0x00,
177         0x00,
178         0x00,
179         0x00,
180         0x00,
181         0x00,
182         0x40,
183         0x00,
184         0x00,
185         0x00,
186         0x00,
187         0x00,
188         0x00,
189         0x00,
190         0x00,
191         0x00,
192         0x00,
193         0x00,
194         0x00,
195         0x00,
196         0x00,
197         0x00,
198         0x00,
199         0x00,
200         0x00,
201         0x00,
202         0x00,
203         0x00,
204         0x00,
205         0x00,
206         0x00,
207         0x00,
208         0x00,
209         0x00,
210         0x00,
211         0x00,
212         0x00,
213         0x00,
214         0x00,
215         0x00,
216         0x00,
217         0x00,
218         0x80,
219         0x00,
220         0x00,
221         0x00,
222         0x0e,
223         0x1f,
224         0xba,
225         0x0e,
226         0x00,
227         0xb4,
228         0x09,
229         0xcd,
230         0x21,
231         0xb8,
232         0x01,
233         0x4c,
234         0xcd,
235         0x21,
236         0x54,
237         0x68,
238         0x69,
239         0x73,
240         0x20,
241         0x70,
242         0x72,
243         0x6f,
244         0x67,
245         0x72,
246         0x61,
247         0x6d,
248         0x20,
249         0x63,
250         0x61,
251         0x6e,
252         0x6e,
253         0x6f,
254         0x74,
255         0x20,
256         0x62,
257         0x65,
258         0x20,
259         0x72,
260         0x75,
261         0x6e,
262         0x20,
263         0x69,
264         0x6e,
265         0x20,
266         0x44,
267         0x4f,
268         0x53,
269         0x20,
270         0x6d,
271         0x6f,
272         0x64,
273         0x65,
274         0x2e,
275         0x0d,
276         0x0d,
277         0x0a,
278         0x24,
279         0x00,
280         0x00,
281         0x00,
282         0x00,
283         0x00,
284         0x00,
285         0x00,
286 }
287
288 type Imp struct {
289         s       loader.Sym
290         off     uint64
291         next    *Imp
292         argsize int
293 }
294
295 type Dll struct {
296         name     string
297         nameoff  uint64
298         thunkoff uint64
299         ms       *Imp
300         next     *Dll
301 }
302
303 var (
304         rsrcsyms    []loader.Sym
305         PESECTHEADR int32
306         PEFILEHEADR int32
307         pe64        int
308         dr          *Dll
309
310         dexport = make([]loader.Sym, 0, 1024)
311 )
312
313 // peStringTable is a COFF string table.
314 type peStringTable struct {
315         strings    []string
316         stringsLen int
317 }
318
319 // size returns size of string table t.
320 func (t *peStringTable) size() int {
321         // string table starts with 4-byte length at the beginning
322         return t.stringsLen + 4
323 }
324
325 // add adds string str to string table t.
326 func (t *peStringTable) add(str string) int {
327         off := t.size()
328         t.strings = append(t.strings, str)
329         t.stringsLen += len(str) + 1 // each string will have 0 appended to it
330         return off
331 }
332
333 // write writes string table t into the output file.
334 func (t *peStringTable) write(out *OutBuf) {
335         out.Write32(uint32(t.size()))
336         for _, s := range t.strings {
337                 out.WriteString(s)
338                 out.Write8(0)
339         }
340 }
341
342 // peSection represents section from COFF section table.
343 type peSection struct {
344         name                 string
345         shortName            string
346         index                int // one-based index into the Section Table
347         virtualSize          uint32
348         virtualAddress       uint32
349         sizeOfRawData        uint32
350         pointerToRawData     uint32
351         pointerToRelocations uint32
352         numberOfRelocations  uint16
353         characteristics      uint32
354 }
355
356 // checkOffset verifies COFF section sect offset in the file.
357 func (sect *peSection) checkOffset(off int64) {
358         if off != int64(sect.pointerToRawData) {
359                 Errorf(nil, "%s.PointerToRawData = %#x, want %#x", sect.name, uint64(int64(sect.pointerToRawData)), uint64(off))
360                 errorexit()
361         }
362 }
363
364 // checkSegment verifies COFF section sect matches address
365 // and file offset provided in segment seg.
366 func (sect *peSection) checkSegment(seg *sym.Segment) {
367         if seg.Vaddr-uint64(PEBASE) != uint64(sect.virtualAddress) {
368                 Errorf(nil, "%s.VirtualAddress = %#x, want %#x", sect.name, uint64(int64(sect.virtualAddress)), uint64(int64(seg.Vaddr-uint64(PEBASE))))
369                 errorexit()
370         }
371         if seg.Fileoff != uint64(sect.pointerToRawData) {
372                 Errorf(nil, "%s.PointerToRawData = %#x, want %#x", sect.name, uint64(int64(sect.pointerToRawData)), uint64(int64(seg.Fileoff)))
373                 errorexit()
374         }
375 }
376
377 // pad adds zeros to the section sect. It writes as many bytes
378 // as necessary to make section sect.SizeOfRawData bytes long.
379 // It assumes that n bytes are already written to the file.
380 func (sect *peSection) pad(out *OutBuf, n uint32) {
381         out.WriteStringN("", int(sect.sizeOfRawData-n))
382 }
383
384 // write writes COFF section sect into the output file.
385 func (sect *peSection) write(out *OutBuf, linkmode LinkMode) error {
386         h := pe.SectionHeader32{
387                 VirtualSize:          sect.virtualSize,
388                 SizeOfRawData:        sect.sizeOfRawData,
389                 PointerToRawData:     sect.pointerToRawData,
390                 PointerToRelocations: sect.pointerToRelocations,
391                 NumberOfRelocations:  sect.numberOfRelocations,
392                 Characteristics:      sect.characteristics,
393         }
394         if linkmode != LinkExternal {
395                 h.VirtualAddress = sect.virtualAddress
396         }
397         copy(h.Name[:], sect.shortName)
398         return binary.Write(out, binary.LittleEndian, h)
399 }
400
401 // emitRelocations emits the relocation entries for the sect.
402 // The actual relocations are emitted by relocfn.
403 // This updates the corresponding PE section table entry
404 // with the relocation offset and count.
405 func (sect *peSection) emitRelocations(out *OutBuf, relocfn func() int) {
406         sect.pointerToRelocations = uint32(out.Offset())
407         // first entry: extended relocs
408         out.Write32(0) // placeholder for number of relocation + 1
409         out.Write32(0)
410         out.Write16(0)
411
412         n := relocfn() + 1
413
414         cpos := out.Offset()
415         out.SeekSet(int64(sect.pointerToRelocations))
416         out.Write32(uint32(n))
417         out.SeekSet(cpos)
418         if n > 0x10000 {
419                 n = 0x10000
420                 sect.characteristics |= IMAGE_SCN_LNK_NRELOC_OVFL
421         } else {
422                 sect.pointerToRelocations += 10 // skip the extend reloc entry
423         }
424         sect.numberOfRelocations = uint16(n - 1)
425 }
426
427 // peFile is used to build COFF file.
428 type peFile struct {
429         sections       []*peSection
430         stringTable    peStringTable
431         textSect       *peSection
432         rdataSect      *peSection
433         dataSect       *peSection
434         bssSect        *peSection
435         ctorsSect      *peSection
436         pdataSect      *peSection
437         xdataSect      *peSection
438         nextSectOffset uint32
439         nextFileOffset uint32
440         symtabOffset   int64 // offset to the start of symbol table
441         symbolCount    int   // number of symbol table records written
442         dataDirectory  [16]pe.DataDirectory
443 }
444
445 // addSection adds section to the COFF file f.
446 func (f *peFile) addSection(name string, sectsize int, filesize int) *peSection {
447         sect := &peSection{
448                 name:             name,
449                 shortName:        name,
450                 index:            len(f.sections) + 1,
451                 virtualAddress:   f.nextSectOffset,
452                 pointerToRawData: f.nextFileOffset,
453         }
454         f.nextSectOffset = uint32(Rnd(int64(f.nextSectOffset)+int64(sectsize), PESECTALIGN))
455         if filesize > 0 {
456                 sect.virtualSize = uint32(sectsize)
457                 sect.sizeOfRawData = uint32(Rnd(int64(filesize), PEFILEALIGN))
458                 f.nextFileOffset += sect.sizeOfRawData
459         } else {
460                 sect.sizeOfRawData = uint32(sectsize)
461         }
462         f.sections = append(f.sections, sect)
463         return sect
464 }
465
466 // addDWARFSection adds DWARF section to the COFF file f.
467 // This function is similar to addSection, but DWARF section names are
468 // longer than 8 characters, so they need to be stored in the string table.
469 func (f *peFile) addDWARFSection(name string, size int) *peSection {
470         if size == 0 {
471                 Exitf("DWARF section %q is empty", name)
472         }
473         // DWARF section names are longer than 8 characters.
474         // PE format requires such names to be stored in string table,
475         // and section names replaced with slash (/) followed by
476         // correspondent string table index.
477         // see http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx
478         // for details
479         off := f.stringTable.add(name)
480         h := f.addSection(name, size, size)
481         h.shortName = fmt.Sprintf("/%d", off)
482         h.characteristics = IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_CNT_INITIALIZED_DATA
483         return h
484 }
485
486 // addDWARF adds DWARF information to the COFF file f.
487 func (f *peFile) addDWARF() {
488         if *FlagS { // disable symbol table
489                 return
490         }
491         if *FlagW { // disable dwarf
492                 return
493         }
494         for _, sect := range Segdwarf.Sections {
495                 h := f.addDWARFSection(sect.Name, int(sect.Length))
496                 fileoff := sect.Vaddr - Segdwarf.Vaddr + Segdwarf.Fileoff
497                 if uint64(h.pointerToRawData) != fileoff {
498                         Exitf("%s.PointerToRawData = %#x, want %#x", sect.Name, h.pointerToRawData, fileoff)
499                 }
500         }
501 }
502
503 // addSEH adds SEH information to the COFF file f.
504 func (f *peFile) addSEH(ctxt *Link) {
505         // .pdata section can exist without the .xdata section.
506         // .xdata section depends on the .pdata section.
507         if Segpdata.Length == 0 {
508                 return
509         }
510         d := pefile.addSection(".pdata", int(Segpdata.Length), int(Segpdata.Length))
511         d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
512         if ctxt.LinkMode == LinkExternal {
513                 // Some gcc versions don't honor the default alignment for the .pdata section.
514                 d.characteristics |= IMAGE_SCN_ALIGN_4BYTES
515         }
516         pefile.pdataSect = d
517         d.checkSegment(&Segpdata)
518         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = d.virtualAddress
519         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = d.virtualSize
520
521         if Segxdata.Length > 0 {
522                 d = pefile.addSection(".xdata", int(Segxdata.Length), int(Segxdata.Length))
523                 d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
524                 if ctxt.LinkMode == LinkExternal {
525                         // Some gcc versions don't honor the default alignment for the .xdata section.
526                         d.characteristics |= IMAGE_SCN_ALIGN_4BYTES
527                 }
528                 pefile.xdataSect = d
529                 d.checkSegment(&Segxdata)
530         }
531 }
532
533 // addInitArray adds .ctors COFF section to the file f.
534 func (f *peFile) addInitArray(ctxt *Link) *peSection {
535         // The size below was determined by the specification for array relocations,
536         // and by observing what GCC writes here. If the initarray section grows to
537         // contain more than one constructor entry, the size will need to be 8 * constructor_count.
538         // However, the entire Go runtime is initialized from just one function, so it is unlikely
539         // that this will need to grow in the future.
540         var size int
541         var alignment uint32
542         switch buildcfg.GOARCH {
543         default:
544                 Exitf("peFile.addInitArray: unsupported GOARCH=%q\n", buildcfg.GOARCH)
545         case "386", "arm":
546                 size = 4
547                 alignment = IMAGE_SCN_ALIGN_4BYTES
548         case "amd64", "arm64":
549                 size = 8
550                 alignment = IMAGE_SCN_ALIGN_8BYTES
551         }
552         sect := f.addSection(".ctors", size, size)
553         sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | alignment
554         sect.sizeOfRawData = uint32(size)
555         ctxt.Out.SeekSet(int64(sect.pointerToRawData))
556         sect.checkOffset(ctxt.Out.Offset())
557
558         init_entry := ctxt.loader.Lookup(*flagEntrySymbol, 0)
559         addr := uint64(ctxt.loader.SymValue(init_entry)) - ctxt.loader.SymSect(init_entry).Vaddr
560         switch buildcfg.GOARCH {
561         case "386", "arm":
562                 ctxt.Out.Write32(uint32(addr))
563         case "amd64", "arm64":
564                 ctxt.Out.Write64(addr)
565         }
566         return sect
567 }
568
569 // emitRelocations emits relocation entries for go.o in external linking.
570 func (f *peFile) emitRelocations(ctxt *Link) {
571         for ctxt.Out.Offset()&7 != 0 {
572                 ctxt.Out.Write8(0)
573         }
574
575         ldr := ctxt.loader
576
577         // relocsect relocates symbols from first in section sect, and returns
578         // the total number of relocations emitted.
579         relocsect := func(sect *sym.Section, syms []loader.Sym, base uint64) int {
580                 // If main section has no bits, nothing to relocate.
581                 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
582                         return 0
583                 }
584                 sect.Reloff = uint64(ctxt.Out.Offset())
585                 for i, s := range syms {
586                         if !ldr.AttrReachable(s) {
587                                 continue
588                         }
589                         if uint64(ldr.SymValue(s)) >= sect.Vaddr {
590                                 syms = syms[i:]
591                                 break
592                         }
593                 }
594                 eaddr := int64(sect.Vaddr + sect.Length)
595                 for _, s := range syms {
596                         if !ldr.AttrReachable(s) {
597                                 continue
598                         }
599                         if ldr.SymValue(s) >= eaddr {
600                                 break
601                         }
602                         // Compute external relocations on the go, and pass to PEreloc1
603                         // to stream out.
604                         relocs := ldr.Relocs(s)
605                         for ri := 0; ri < relocs.Count(); ri++ {
606                                 r := relocs.At(ri)
607                                 rr, ok := extreloc(ctxt, ldr, s, r)
608                                 if !ok {
609                                         continue
610                                 }
611                                 if rr.Xsym == 0 {
612                                         ctxt.Errorf(s, "missing xsym in relocation")
613                                         continue
614                                 }
615                                 if ldr.SymDynid(rr.Xsym) < 0 {
616                                         ctxt.Errorf(s, "reloc %d to non-coff symbol %s (outer=%s) %d", r.Type(), ldr.SymName(r.Sym()), ldr.SymName(rr.Xsym), ldr.SymType(r.Sym()))
617                                 }
618                                 if !thearch.PEreloc1(ctxt.Arch, ctxt.Out, ldr, s, rr, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-base)) {
619                                         ctxt.Errorf(s, "unsupported obj reloc %v/%d to %s", r.Type(), r.Siz(), ldr.SymName(r.Sym()))
620                                 }
621                         }
622                 }
623                 sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
624                 const relocLen = 4 + 4 + 2
625                 return int(sect.Rellen / relocLen)
626         }
627
628         type relsect struct {
629                 peSect *peSection
630                 seg    *sym.Segment
631                 syms   []loader.Sym
632         }
633         sects := []relsect{
634                 {f.textSect, &Segtext, ctxt.Textp},
635                 {f.rdataSect, &Segrodata, ctxt.datap},
636                 {f.dataSect, &Segdata, ctxt.datap},
637         }
638         if len(sehp.pdata) != 0 {
639                 sects = append(sects, relsect{f.pdataSect, &Segpdata, sehp.pdata})
640         }
641         if len(sehp.xdata) != 0 {
642                 sects = append(sects, relsect{f.xdataSect, &Segxdata, sehp.xdata})
643         }
644         for _, s := range sects {
645                 s.peSect.emitRelocations(ctxt.Out, func() int {
646                         var n int
647                         for _, sect := range s.seg.Sections {
648                                 n += relocsect(sect, s.syms, s.seg.Vaddr)
649                         }
650                         return n
651                 })
652         }
653
654 dwarfLoop:
655         for i := 0; i < len(Segdwarf.Sections); i++ {
656                 sect := Segdwarf.Sections[i]
657                 si := dwarfp[i]
658                 if si.secSym() != loader.Sym(sect.Sym) ||
659                         ldr.SymSect(si.secSym()) != sect {
660                         panic("inconsistency between dwarfp and Segdwarf")
661                 }
662                 for _, pesect := range f.sections {
663                         if sect.Name == pesect.name {
664                                 pesect.emitRelocations(ctxt.Out, func() int {
665                                         return relocsect(sect, si.syms, sect.Vaddr)
666                                 })
667                                 continue dwarfLoop
668                         }
669                 }
670                 Errorf(nil, "emitRelocations: could not find %q section", sect.Name)
671         }
672
673         if f.ctorsSect == nil {
674                 return
675         }
676
677         f.ctorsSect.emitRelocations(ctxt.Out, func() int {
678                 dottext := ldr.Lookup(".text", 0)
679                 ctxt.Out.Write32(0)
680                 ctxt.Out.Write32(uint32(ldr.SymDynid(dottext)))
681                 switch buildcfg.GOARCH {
682                 default:
683                         ctxt.Errorf(dottext, "unknown architecture for PE: %q\n", buildcfg.GOARCH)
684                 case "386":
685                         ctxt.Out.Write16(IMAGE_REL_I386_DIR32)
686                 case "amd64":
687                         ctxt.Out.Write16(IMAGE_REL_AMD64_ADDR64)
688                 case "arm":
689                         ctxt.Out.Write16(IMAGE_REL_ARM_ADDR32)
690                 case "arm64":
691                         ctxt.Out.Write16(IMAGE_REL_ARM64_ADDR64)
692                 }
693                 return 1
694         })
695 }
696
697 // writeSymbol appends symbol s to file f symbol table.
698 // It also sets s.Dynid to written symbol number.
699 func (f *peFile) writeSymbol(out *OutBuf, ldr *loader.Loader, s loader.Sym, name string, value int64, sectidx int, typ uint16, class uint8) {
700         if len(name) > 8 {
701                 out.Write32(0)
702                 out.Write32(uint32(f.stringTable.add(name)))
703         } else {
704                 out.WriteStringN(name, 8)
705         }
706         out.Write32(uint32(value))
707         out.Write16(uint16(sectidx))
708         out.Write16(typ)
709         out.Write8(class)
710         out.Write8(0) // no aux entries
711
712         ldr.SetSymDynid(s, int32(f.symbolCount))
713
714         f.symbolCount++
715 }
716
717 // mapToPESection searches peFile f for s symbol's location.
718 // It returns PE section index, and offset within that section.
719 func (f *peFile) mapToPESection(ldr *loader.Loader, s loader.Sym, linkmode LinkMode) (pesectidx int, offset int64, err error) {
720         sect := ldr.SymSect(s)
721         if sect == nil {
722                 return 0, 0, fmt.Errorf("could not map %s symbol with no section", ldr.SymName(s))
723         }
724         if sect.Seg == &Segtext {
725                 return f.textSect.index, int64(uint64(ldr.SymValue(s)) - Segtext.Vaddr), nil
726         }
727         if sect.Seg == &Segrodata {
728                 return f.rdataSect.index, int64(uint64(ldr.SymValue(s)) - Segrodata.Vaddr), nil
729         }
730         if sect.Seg != &Segdata {
731                 return 0, 0, fmt.Errorf("could not map %s symbol with non .text or .rdata or .data section", ldr.SymName(s))
732         }
733         v := uint64(ldr.SymValue(s)) - Segdata.Vaddr
734         if linkmode != LinkExternal {
735                 return f.dataSect.index, int64(v), nil
736         }
737         if ldr.SymType(s) == sym.SDATA {
738                 return f.dataSect.index, int64(v), nil
739         }
740         // Note: although address of runtime.edata (type sym.SDATA) is at the start of .bss section
741         // it still belongs to the .data section, not the .bss section.
742         if v < Segdata.Filelen {
743                 return f.dataSect.index, int64(v), nil
744         }
745         return f.bssSect.index, int64(v - Segdata.Filelen), nil
746 }
747
748 var isLabel = make(map[loader.Sym]bool)
749
750 func AddPELabelSym(ldr *loader.Loader, s loader.Sym) {
751         isLabel[s] = true
752 }
753
754 // writeSymbols writes all COFF symbol table records.
755 func (f *peFile) writeSymbols(ctxt *Link) {
756         ldr := ctxt.loader
757         addsym := func(s loader.Sym) {
758                 t := ldr.SymType(s)
759                 if ldr.SymSect(s) == nil && t != sym.SDYNIMPORT && t != sym.SHOSTOBJ && t != sym.SUNDEFEXT {
760                         return
761                 }
762
763                 name := ldr.SymName(s)
764
765                 // Only windows/386 requires underscore prefix on external symbols.
766                 if ctxt.Is386() && ctxt.IsExternal() &&
767                         (t == sym.SHOSTOBJ || t == sym.SUNDEFEXT || ldr.AttrCgoExport(s) ||
768                                 // TODO(cuonglm): remove this hack
769                                 //
770                                 // Previously, windows/386 requires underscore prefix on external symbols,
771                                 // but that's only applied for SHOSTOBJ/SUNDEFEXT or cgo export symbols.
772                                 // "go.buildid" is STEXT, "type.*" is STYPE, thus they are not prefixed
773                                 // with underscore.
774                                 //
775                                 // In external linking mode, the external linker can't resolve them as
776                                 // external symbols. But we are lucky that they have "." in their name,
777                                 // so the external linker see them as Forwarder RVA exports. See:
778                                 //
779                                 //  - https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#export-address-table
780                                 //  - https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=ld/pe-dll.c;h=e7b82ba6ffadf74dc1b9ee71dc13d48336941e51;hb=HEAD#l972
781                                 //
782                                 // CL 317917 changes "." to ":" in symbols name, so these symbols can not be
783                                 // found by external linker anymore. So a hacky way is adding the
784                                 // underscore prefix for these 2 symbols. I don't have enough knowledge to
785                                 // verify whether adding the underscore for all STEXT/STYPE symbols are
786                                 // fine, even if it could be, that would be done in future CL.
787                                 name == "go:buildid" || name == "type:*") {
788                         name = "_" + name
789                 }
790
791                 name = mangleABIName(ctxt, ldr, s, name)
792
793                 var peSymType uint16 = IMAGE_SYM_TYPE_NULL
794                 switch t {
795                 case sym.STEXT, sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
796                         // Microsoft's PE documentation is contradictory. It says that the symbol's complex type
797                         // is stored in the pesym.Type most significant byte, but MSVC, LLVM, and mingw store it
798                         // in the 4 high bits of the less significant byte. Also, the PE documentation says that
799                         // the basic type for a function should be IMAGE_SYM_TYPE_VOID,
800                         // but the reality is that it uses IMAGE_SYM_TYPE_NULL instead.
801                         peSymType = IMAGE_SYM_DTYPE_FUNCTION<<4 + IMAGE_SYM_TYPE_NULL
802                 }
803                 sect, value, err := f.mapToPESection(ldr, s, ctxt.LinkMode)
804                 if err != nil {
805                         switch t {
806                         case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
807                         default:
808                                 ctxt.Errorf(s, "addpesym: %v", err)
809                         }
810                 }
811                 class := IMAGE_SYM_CLASS_EXTERNAL
812                 if ldr.IsFileLocal(s) || ldr.AttrVisibilityHidden(s) || ldr.AttrLocal(s) {
813                         class = IMAGE_SYM_CLASS_STATIC
814                 }
815                 f.writeSymbol(ctxt.Out, ldr, s, name, value, sect, peSymType, uint8(class))
816         }
817
818         if ctxt.LinkMode == LinkExternal {
819                 // Include section symbols as external, because
820                 // .ctors and .debug_* section relocations refer to it.
821                 for _, pesect := range f.sections {
822                         s := ldr.LookupOrCreateSym(pesect.name, 0)
823                         f.writeSymbol(ctxt.Out, ldr, s, pesect.name, 0, pesect.index, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_STATIC)
824                 }
825         }
826
827         // Add special runtime.text and runtime.etext symbols.
828         s := ldr.Lookup("runtime.text", 0)
829         if ldr.SymType(s) == sym.STEXT {
830                 addsym(s)
831         }
832         s = ldr.Lookup("runtime.etext", 0)
833         if ldr.SymType(s) == sym.STEXT {
834                 addsym(s)
835         }
836
837         // Add text symbols.
838         for _, s := range ctxt.Textp {
839                 addsym(s)
840         }
841
842         shouldBeInSymbolTable := func(s loader.Sym) bool {
843                 if ldr.AttrNotInSymbolTable(s) {
844                         return false
845                 }
846                 name := ldr.SymName(s) // TODO: try not to read the name
847                 if name == "" || name[0] == '.' {
848                         return false
849                 }
850                 return true
851         }
852
853         // Add data symbols and external references.
854         for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
855                 if !ldr.AttrReachable(s) {
856                         continue
857                 }
858                 t := ldr.SymType(s)
859                 if t >= sym.SELFRXSECT && t < sym.SXREF { // data sections handled in dodata
860                         if t == sym.STLSBSS {
861                                 continue
862                         }
863                         if !shouldBeInSymbolTable(s) {
864                                 continue
865                         }
866                         addsym(s)
867                 }
868
869                 switch t {
870                 case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
871                         addsym(s)
872                 default:
873                         if len(isLabel) > 0 && isLabel[s] {
874                                 addsym(s)
875                         }
876                 }
877         }
878 }
879
880 // writeSymbolTableAndStringTable writes out symbol and string tables for peFile f.
881 func (f *peFile) writeSymbolTableAndStringTable(ctxt *Link) {
882         f.symtabOffset = ctxt.Out.Offset()
883
884         // write COFF symbol table
885         if !*FlagS || ctxt.LinkMode == LinkExternal {
886                 f.writeSymbols(ctxt)
887         }
888
889         // update COFF file header and section table
890         size := f.stringTable.size() + 18*f.symbolCount
891         var h *peSection
892         if ctxt.LinkMode != LinkExternal {
893                 // We do not really need .symtab for go.o, and if we have one, ld
894                 // will also include it in the exe, and that will confuse windows.
895                 h = f.addSection(".symtab", size, size)
896                 h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
897                 h.checkOffset(f.symtabOffset)
898         }
899
900         // write COFF string table
901         f.stringTable.write(ctxt.Out)
902         if ctxt.LinkMode != LinkExternal {
903                 h.pad(ctxt.Out, uint32(size))
904         }
905 }
906
907 // writeFileHeader writes COFF file header for peFile f.
908 func (f *peFile) writeFileHeader(ctxt *Link) {
909         var fh pe.FileHeader
910
911         switch ctxt.Arch.Family {
912         default:
913                 Exitf("unknown PE architecture: %v", ctxt.Arch.Family)
914         case sys.AMD64:
915                 fh.Machine = pe.IMAGE_FILE_MACHINE_AMD64
916         case sys.I386:
917                 fh.Machine = pe.IMAGE_FILE_MACHINE_I386
918         case sys.ARM:
919                 fh.Machine = pe.IMAGE_FILE_MACHINE_ARMNT
920         case sys.ARM64:
921                 fh.Machine = pe.IMAGE_FILE_MACHINE_ARM64
922         }
923
924         fh.NumberOfSections = uint16(len(f.sections))
925
926         // Being able to produce identical output for identical input is
927         // much more beneficial than having build timestamp in the header.
928         fh.TimeDateStamp = 0
929
930         if ctxt.LinkMode != LinkExternal {
931                 fh.Characteristics = pe.IMAGE_FILE_EXECUTABLE_IMAGE
932                 switch ctxt.Arch.Family {
933                 case sys.AMD64, sys.I386:
934                         if ctxt.BuildMode != BuildModePIE {
935                                 fh.Characteristics |= pe.IMAGE_FILE_RELOCS_STRIPPED
936                         }
937                 }
938         }
939         if pe64 != 0 {
940                 var oh64 pe.OptionalHeader64
941                 fh.SizeOfOptionalHeader = uint16(binary.Size(&oh64))
942                 fh.Characteristics |= pe.IMAGE_FILE_LARGE_ADDRESS_AWARE
943         } else {
944                 var oh pe.OptionalHeader32
945                 fh.SizeOfOptionalHeader = uint16(binary.Size(&oh))
946                 fh.Characteristics |= pe.IMAGE_FILE_32BIT_MACHINE
947         }
948
949         fh.PointerToSymbolTable = uint32(f.symtabOffset)
950         fh.NumberOfSymbols = uint32(f.symbolCount)
951
952         binary.Write(ctxt.Out, binary.LittleEndian, &fh)
953 }
954
955 // writeOptionalHeader writes COFF optional header for peFile f.
956 func (f *peFile) writeOptionalHeader(ctxt *Link) {
957         var oh pe.OptionalHeader32
958         var oh64 pe.OptionalHeader64
959
960         if pe64 != 0 {
961                 oh64.Magic = 0x20b // PE32+
962         } else {
963                 oh.Magic = 0x10b // PE32
964                 oh.BaseOfData = f.dataSect.virtualAddress
965         }
966
967         // Fill out both oh64 and oh. We only use one. Oh well.
968         oh64.MajorLinkerVersion = 3
969         oh.MajorLinkerVersion = 3
970         oh64.MinorLinkerVersion = 0
971         oh.MinorLinkerVersion = 0
972         oh64.SizeOfCode = f.textSect.sizeOfRawData
973         oh.SizeOfCode = f.textSect.sizeOfRawData
974         oh64.SizeOfInitializedData = f.dataSect.sizeOfRawData
975         oh.SizeOfInitializedData = f.dataSect.sizeOfRawData
976         oh64.SizeOfUninitializedData = 0
977         oh.SizeOfUninitializedData = 0
978         if ctxt.LinkMode != LinkExternal {
979                 oh64.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
980                 oh.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
981         }
982         oh64.BaseOfCode = f.textSect.virtualAddress
983         oh.BaseOfCode = f.textSect.virtualAddress
984         oh64.ImageBase = uint64(PEBASE)
985         oh.ImageBase = uint32(PEBASE)
986         oh64.SectionAlignment = uint32(PESECTALIGN)
987         oh.SectionAlignment = uint32(PESECTALIGN)
988         oh64.FileAlignment = uint32(PEFILEALIGN)
989         oh.FileAlignment = uint32(PEFILEALIGN)
990         oh64.MajorOperatingSystemVersion = PeMinimumTargetMajorVersion
991         oh.MajorOperatingSystemVersion = PeMinimumTargetMajorVersion
992         oh64.MinorOperatingSystemVersion = PeMinimumTargetMinorVersion
993         oh.MinorOperatingSystemVersion = PeMinimumTargetMinorVersion
994         oh64.MajorImageVersion = 1
995         oh.MajorImageVersion = 1
996         oh64.MinorImageVersion = 0
997         oh.MinorImageVersion = 0
998         oh64.MajorSubsystemVersion = PeMinimumTargetMajorVersion
999         oh.MajorSubsystemVersion = PeMinimumTargetMajorVersion
1000         oh64.MinorSubsystemVersion = PeMinimumTargetMinorVersion
1001         oh.MinorSubsystemVersion = PeMinimumTargetMinorVersion
1002         oh64.SizeOfImage = f.nextSectOffset
1003         oh.SizeOfImage = f.nextSectOffset
1004         oh64.SizeOfHeaders = uint32(PEFILEHEADR)
1005         oh.SizeOfHeaders = uint32(PEFILEHEADR)
1006         if windowsgui {
1007                 oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI
1008                 oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI
1009         } else {
1010                 oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI
1011                 oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI
1012         }
1013
1014         // Mark as having awareness of terminal services, to avoid ancient compatibility hacks.
1015         oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
1016         oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
1017
1018         // Enable DEP
1019         oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT
1020         oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT
1021
1022         // The DLL can be relocated at load time.
1023         if needPEBaseReloc(ctxt) {
1024                 oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
1025                 oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
1026         }
1027
1028         // Image can handle a high entropy 64-bit virtual address space.
1029         if ctxt.BuildMode == BuildModePIE {
1030                 oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
1031         }
1032
1033         // Disable stack growth as we don't want Windows to
1034         // fiddle with the thread stack limits, which we set
1035         // ourselves to circumvent the stack checks in the
1036         // Windows exception dispatcher.
1037         // Commit size must be strictly less than reserve
1038         // size otherwise reserve will be rounded up to a
1039         // larger size, as verified with VMMap.
1040
1041         // On 64-bit, we always reserve 2MB stacks. "Pure" Go code is
1042         // okay with much smaller stacks, but the syscall package
1043         // makes it easy to call into arbitrary C code without cgo,
1044         // and system calls even in "pure" Go code are actually C
1045         // calls that may need more stack than we think.
1046         //
1047         // The default stack reserve size directly affects only the main
1048         // thread.
1049         //
1050         // For other threads, the runtime explicitly asks the kernel
1051         // to use the default stack size so that all stacks are
1052         // consistent.
1053         //
1054         // At thread start, in minit, the runtime queries the OS for
1055         // the actual stack bounds so that the stack size doesn't need
1056         // to be hard-coded into the runtime.
1057         oh64.SizeOfStackReserve = 0x00200000
1058         if !iscgo {
1059                 oh64.SizeOfStackCommit = 0x00001000
1060         } else {
1061                 // TODO(brainman): Maybe remove optional header writing altogether for cgo.
1062                 // For cgo it is the external linker that is building final executable.
1063                 // And it probably does not use any information stored in optional header.
1064                 oh64.SizeOfStackCommit = 0x00200000 - 0x2000 // account for 2 guard pages
1065         }
1066
1067         oh.SizeOfStackReserve = 0x00100000
1068         if !iscgo {
1069                 oh.SizeOfStackCommit = 0x00001000
1070         } else {
1071                 oh.SizeOfStackCommit = 0x00100000 - 0x2000 // account for 2 guard pages
1072         }
1073
1074         oh64.SizeOfHeapReserve = 0x00100000
1075         oh.SizeOfHeapReserve = 0x00100000
1076         oh64.SizeOfHeapCommit = 0x00001000
1077         oh.SizeOfHeapCommit = 0x00001000
1078         oh64.NumberOfRvaAndSizes = 16
1079         oh.NumberOfRvaAndSizes = 16
1080
1081         if pe64 != 0 {
1082                 oh64.DataDirectory = f.dataDirectory
1083         } else {
1084                 oh.DataDirectory = f.dataDirectory
1085         }
1086
1087         if pe64 != 0 {
1088                 binary.Write(ctxt.Out, binary.LittleEndian, &oh64)
1089         } else {
1090                 binary.Write(ctxt.Out, binary.LittleEndian, &oh)
1091         }
1092 }
1093
1094 var pefile peFile
1095
1096 func Peinit(ctxt *Link) {
1097         var l int
1098
1099         if ctxt.Arch.PtrSize == 8 {
1100                 // 64-bit architectures
1101                 pe64 = 1
1102                 PEBASE = 1 << 32
1103                 if ctxt.Arch.Family == sys.AMD64 {
1104                         // TODO(rsc): For cgo we currently use 32-bit relocations
1105                         // that fail when PEBASE is too large.
1106                         // We need to fix this, but for now, use a smaller PEBASE.
1107                         PEBASE = 1 << 22
1108                 }
1109                 var oh64 pe.OptionalHeader64
1110                 l = binary.Size(&oh64)
1111         } else {
1112                 // 32-bit architectures
1113                 PEBASE = 1 << 22
1114                 var oh pe.OptionalHeader32
1115                 l = binary.Size(&oh)
1116         }
1117
1118         if ctxt.LinkMode == LinkExternal {
1119                 // .rdata section will contain "masks" and "shifts" symbols, and they
1120                 // need to be aligned to 16-bytes. So make all sections aligned
1121                 // to 32-byte and mark them all IMAGE_SCN_ALIGN_32BYTES so external
1122                 // linker will honour that requirement.
1123                 PESECTALIGN = 32
1124                 PEFILEALIGN = 0
1125                 // We are creating an object file. The absolute address is irrelevant.
1126                 PEBASE = 0
1127         }
1128
1129         var sh [16]pe.SectionHeader32
1130         var fh pe.FileHeader
1131         PEFILEHEADR = int32(Rnd(int64(len(dosstub)+binary.Size(&fh)+l+binary.Size(&sh)), PEFILEALIGN))
1132         if ctxt.LinkMode != LinkExternal {
1133                 PESECTHEADR = int32(Rnd(int64(PEFILEHEADR), PESECTALIGN))
1134         } else {
1135                 PESECTHEADR = 0
1136         }
1137         pefile.nextSectOffset = uint32(PESECTHEADR)
1138         pefile.nextFileOffset = uint32(PEFILEHEADR)
1139
1140         if ctxt.LinkMode == LinkInternal {
1141                 // some mingw libs depend on this symbol, for example, FindPESectionByName
1142                 for _, name := range [2]string{"__image_base__", "_image_base__"} {
1143                         sb := ctxt.loader.CreateSymForUpdate(name, 0)
1144                         sb.SetType(sym.SDATA)
1145                         sb.SetValue(PEBASE)
1146                         ctxt.loader.SetAttrSpecial(sb.Sym(), true)
1147                         ctxt.loader.SetAttrLocal(sb.Sym(), true)
1148                 }
1149         }
1150
1151         HEADR = PEFILEHEADR
1152         if *FlagRound == -1 {
1153                 *FlagRound = PESECTALIGN
1154         }
1155         if *FlagTextAddr == -1 {
1156                 *FlagTextAddr = Rnd(PEBASE, *FlagRound) + int64(PESECTHEADR)
1157         }
1158 }
1159
1160 func pewrite(ctxt *Link) {
1161         ctxt.Out.SeekSet(0)
1162         if ctxt.LinkMode != LinkExternal {
1163                 ctxt.Out.Write(dosstub)
1164                 ctxt.Out.WriteStringN("PE", 4)
1165         }
1166
1167         pefile.writeFileHeader(ctxt)
1168
1169         pefile.writeOptionalHeader(ctxt)
1170
1171         for _, sect := range pefile.sections {
1172                 sect.write(ctxt.Out, ctxt.LinkMode)
1173         }
1174 }
1175
1176 func strput(out *OutBuf, s string) {
1177         out.WriteString(s)
1178         out.Write8(0)
1179         // string must be padded to even size
1180         if (len(s)+1)%2 != 0 {
1181                 out.Write8(0)
1182         }
1183 }
1184
1185 func initdynimport(ctxt *Link) *Dll {
1186         ldr := ctxt.loader
1187         var d *Dll
1188
1189         dr = nil
1190         var m *Imp
1191         for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
1192                 if !ldr.AttrReachable(s) || ldr.SymType(s) != sym.SDYNIMPORT {
1193                         continue
1194                 }
1195                 dynlib := ldr.SymDynimplib(s)
1196                 for d = dr; d != nil; d = d.next {
1197                         if d.name == dynlib {
1198                                 m = new(Imp)
1199                                 break
1200                         }
1201                 }
1202
1203                 if d == nil {
1204                         d = new(Dll)
1205                         d.name = dynlib
1206                         d.next = dr
1207                         dr = d
1208                         m = new(Imp)
1209                 }
1210
1211                 // Because external link requires properly stdcall decorated name,
1212                 // all external symbols in runtime use %n to denote that the number
1213                 // of uinptrs this function consumes. Store the argsize and discard
1214                 // the %n suffix if any.
1215                 m.argsize = -1
1216                 extName := ldr.SymExtname(s)
1217                 if i := strings.IndexByte(extName, '%'); i >= 0 {
1218                         var err error
1219                         m.argsize, err = strconv.Atoi(extName[i+1:])
1220                         if err != nil {
1221                                 ctxt.Errorf(s, "failed to parse stdcall decoration: %v", err)
1222                         }
1223                         m.argsize *= ctxt.Arch.PtrSize
1224                         ldr.SetSymExtname(s, extName[:i])
1225                 }
1226
1227                 m.s = s
1228                 m.next = d.ms
1229                 d.ms = m
1230         }
1231
1232         if ctxt.IsExternal() {
1233                 // Add real symbol name
1234                 for d := dr; d != nil; d = d.next {
1235                         for m = d.ms; m != nil; m = m.next {
1236                                 sb := ldr.MakeSymbolUpdater(m.s)
1237                                 sb.SetType(sym.SDATA)
1238                                 sb.Grow(int64(ctxt.Arch.PtrSize))
1239                                 dynName := sb.Extname()
1240                                 // only windows/386 requires stdcall decoration
1241                                 if ctxt.Is386() && m.argsize >= 0 {
1242                                         dynName += fmt.Sprintf("@%d", m.argsize)
1243                                 }
1244                                 dynSym := ldr.CreateSymForUpdate(dynName, 0)
1245                                 dynSym.SetType(sym.SHOSTOBJ)
1246                                 r, _ := sb.AddRel(objabi.R_ADDR)
1247                                 r.SetSym(dynSym.Sym())
1248                                 r.SetSiz(uint8(ctxt.Arch.PtrSize))
1249                         }
1250                 }
1251         } else {
1252                 dynamic := ldr.CreateSymForUpdate(".windynamic", 0)
1253                 dynamic.SetType(sym.SWINDOWS)
1254                 for d := dr; d != nil; d = d.next {
1255                         for m = d.ms; m != nil; m = m.next {
1256                                 sb := ldr.MakeSymbolUpdater(m.s)
1257                                 sb.SetType(sym.SWINDOWS)
1258                                 sb.SetValue(dynamic.Size())
1259                                 dynamic.SetSize(dynamic.Size() + int64(ctxt.Arch.PtrSize))
1260                                 dynamic.AddInteriorSym(m.s)
1261                         }
1262
1263                         dynamic.SetSize(dynamic.Size() + int64(ctxt.Arch.PtrSize))
1264                 }
1265         }
1266
1267         return dr
1268 }
1269
1270 // peimporteddlls returns the gcc command line argument to link all imported
1271 // DLLs.
1272 func peimporteddlls() []string {
1273         var dlls []string
1274
1275         for d := dr; d != nil; d = d.next {
1276                 dlls = append(dlls, "-l"+strings.TrimSuffix(d.name, ".dll"))
1277         }
1278
1279         return dlls
1280 }
1281
1282 func addimports(ctxt *Link, datsect *peSection) {
1283         ldr := ctxt.loader
1284         startoff := ctxt.Out.Offset()
1285         dynamic := ldr.LookupOrCreateSym(".windynamic", 0)
1286
1287         // skip import descriptor table (will write it later)
1288         n := uint64(0)
1289
1290         for d := dr; d != nil; d = d.next {
1291                 n++
1292         }
1293         ctxt.Out.SeekSet(startoff + int64(binary.Size(&IMAGE_IMPORT_DESCRIPTOR{}))*int64(n+1))
1294
1295         // write dll names
1296         for d := dr; d != nil; d = d.next {
1297                 d.nameoff = uint64(ctxt.Out.Offset()) - uint64(startoff)
1298                 strput(ctxt.Out, d.name)
1299         }
1300
1301         // write function names
1302         for d := dr; d != nil; d = d.next {
1303                 for m := d.ms; m != nil; m = m.next {
1304                         m.off = uint64(pefile.nextSectOffset) + uint64(ctxt.Out.Offset()) - uint64(startoff)
1305                         ctxt.Out.Write16(0) // hint
1306                         strput(ctxt.Out, ldr.SymExtname(m.s))
1307                 }
1308         }
1309
1310         // write OriginalFirstThunks
1311         oftbase := uint64(ctxt.Out.Offset()) - uint64(startoff)
1312
1313         n = uint64(ctxt.Out.Offset())
1314         for d := dr; d != nil; d = d.next {
1315                 d.thunkoff = uint64(ctxt.Out.Offset()) - n
1316                 for m := d.ms; m != nil; m = m.next {
1317                         if pe64 != 0 {
1318                                 ctxt.Out.Write64(m.off)
1319                         } else {
1320                                 ctxt.Out.Write32(uint32(m.off))
1321                         }
1322                 }
1323
1324                 if pe64 != 0 {
1325                         ctxt.Out.Write64(0)
1326                 } else {
1327                         ctxt.Out.Write32(0)
1328                 }
1329         }
1330
1331         // add pe section and pad it at the end
1332         n = uint64(ctxt.Out.Offset()) - uint64(startoff)
1333
1334         isect := pefile.addSection(".idata", int(n), int(n))
1335         isect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
1336         isect.checkOffset(startoff)
1337         isect.pad(ctxt.Out, uint32(n))
1338         endoff := ctxt.Out.Offset()
1339
1340         // write FirstThunks (allocated in .data section)
1341         ftbase := uint64(ldr.SymValue(dynamic)) - uint64(datsect.virtualAddress) - uint64(PEBASE)
1342
1343         ctxt.Out.SeekSet(int64(uint64(datsect.pointerToRawData) + ftbase))
1344         for d := dr; d != nil; d = d.next {
1345                 for m := d.ms; m != nil; m = m.next {
1346                         if pe64 != 0 {
1347                                 ctxt.Out.Write64(m.off)
1348                         } else {
1349                                 ctxt.Out.Write32(uint32(m.off))
1350                         }
1351                 }
1352
1353                 if pe64 != 0 {
1354                         ctxt.Out.Write64(0)
1355                 } else {
1356                         ctxt.Out.Write32(0)
1357                 }
1358         }
1359
1360         // finally write import descriptor table
1361         out := ctxt.Out
1362         out.SeekSet(startoff)
1363
1364         for d := dr; d != nil; d = d.next {
1365                 out.Write32(uint32(uint64(isect.virtualAddress) + oftbase + d.thunkoff))
1366                 out.Write32(0)
1367                 out.Write32(0)
1368                 out.Write32(uint32(uint64(isect.virtualAddress) + d.nameoff))
1369                 out.Write32(uint32(uint64(datsect.virtualAddress) + ftbase + d.thunkoff))
1370         }
1371
1372         out.Write32(0) //end
1373         out.Write32(0)
1374         out.Write32(0)
1375         out.Write32(0)
1376         out.Write32(0)
1377
1378         // update data directory
1379         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.virtualAddress
1380         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.virtualSize
1381         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(ldr.SymValue(dynamic) - PEBASE)
1382         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(ldr.SymSize(dynamic))
1383
1384         out.SeekSet(endoff)
1385 }
1386
1387 func initdynexport(ctxt *Link) {
1388         ldr := ctxt.loader
1389         for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
1390                 if !ldr.AttrReachable(s) || !ldr.AttrCgoExportDynamic(s) {
1391                         continue
1392                 }
1393                 if len(dexport)+1 > cap(dexport) {
1394                         ctxt.Errorf(s, "pe dynexport table is full")
1395                         errorexit()
1396                 }
1397
1398                 dexport = append(dexport, s)
1399         }
1400
1401         sort.Slice(dexport, func(i, j int) bool { return ldr.SymExtname(dexport[i]) < ldr.SymExtname(dexport[j]) })
1402 }
1403
1404 func addexports(ctxt *Link) {
1405         ldr := ctxt.loader
1406         var e IMAGE_EXPORT_DIRECTORY
1407
1408         nexport := len(dexport)
1409         size := binary.Size(&e) + 10*nexport + len(*flagOutfile) + 1
1410         for _, s := range dexport {
1411                 size += len(ldr.SymExtname(s)) + 1
1412         }
1413
1414         if nexport == 0 {
1415                 return
1416         }
1417
1418         sect := pefile.addSection(".edata", size, size)
1419         sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
1420         sect.checkOffset(ctxt.Out.Offset())
1421         va := int(sect.virtualAddress)
1422         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = uint32(va)
1423         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect.virtualSize
1424
1425         vaName := va + binary.Size(&e) + nexport*4
1426         vaAddr := va + binary.Size(&e)
1427         vaNa := va + binary.Size(&e) + nexport*8
1428
1429         e.Characteristics = 0
1430         e.MajorVersion = 0
1431         e.MinorVersion = 0
1432         e.NumberOfFunctions = uint32(nexport)
1433         e.NumberOfNames = uint32(nexport)
1434         e.Name = uint32(va+binary.Size(&e)) + uint32(nexport)*10 // Program names.
1435         e.Base = 1
1436         e.AddressOfFunctions = uint32(vaAddr)
1437         e.AddressOfNames = uint32(vaName)
1438         e.AddressOfNameOrdinals = uint32(vaNa)
1439
1440         out := ctxt.Out
1441
1442         // put IMAGE_EXPORT_DIRECTORY
1443         binary.Write(out, binary.LittleEndian, &e)
1444
1445         // put EXPORT Address Table
1446         for _, s := range dexport {
1447                 out.Write32(uint32(ldr.SymValue(s) - PEBASE))
1448         }
1449
1450         // put EXPORT Name Pointer Table
1451         v := int(e.Name + uint32(len(*flagOutfile)) + 1)
1452
1453         for _, s := range dexport {
1454                 out.Write32(uint32(v))
1455                 v += len(ldr.SymExtname(s)) + 1
1456         }
1457
1458         // put EXPORT Ordinal Table
1459         for i := 0; i < nexport; i++ {
1460                 out.Write16(uint16(i))
1461         }
1462
1463         // put Names
1464         out.WriteStringN(*flagOutfile, len(*flagOutfile)+1)
1465
1466         for _, s := range dexport {
1467                 name := ldr.SymExtname(s)
1468                 out.WriteStringN(name, len(name)+1)
1469         }
1470         sect.pad(out, uint32(size))
1471 }
1472
1473 // peBaseRelocEntry represents a single relocation entry.
1474 type peBaseRelocEntry struct {
1475         typeOff uint16
1476 }
1477
1478 // peBaseRelocBlock represents a Base Relocation Block. A block
1479 // is a collection of relocation entries in a page, where each
1480 // entry describes a single relocation.
1481 // The block page RVA (Relative Virtual Address) is the index
1482 // into peBaseRelocTable.blocks.
1483 type peBaseRelocBlock struct {
1484         entries []peBaseRelocEntry
1485 }
1486
1487 // pePages is a type used to store the list of pages for which there
1488 // are base relocation blocks. This is defined as a type so that
1489 // it can be sorted.
1490 type pePages []uint32
1491
1492 func (p pePages) Len() int           { return len(p) }
1493 func (p pePages) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
1494 func (p pePages) Less(i, j int) bool { return p[i] < p[j] }
1495
1496 // A PE base relocation table is a list of blocks, where each block
1497 // contains relocation information for a single page. The blocks
1498 // must be emitted in order of page virtual address.
1499 // See https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-reloc-section-image-only
1500 type peBaseRelocTable struct {
1501         blocks map[uint32]peBaseRelocBlock
1502
1503         // pePages is a list of keys into blocks map.
1504         // It is stored separately for ease of sorting.
1505         pages pePages
1506 }
1507
1508 func (rt *peBaseRelocTable) init(ctxt *Link) {
1509         rt.blocks = make(map[uint32]peBaseRelocBlock)
1510 }
1511
1512 func (rt *peBaseRelocTable) addentry(ldr *loader.Loader, s loader.Sym, r *loader.Reloc) {
1513         // pageSize is the size in bytes of a page
1514         // described by a base relocation block.
1515         const pageSize = 0x1000
1516         const pageMask = pageSize - 1
1517
1518         addr := ldr.SymValue(s) + int64(r.Off()) - int64(PEBASE)
1519         page := uint32(addr &^ pageMask)
1520         off := uint32(addr & pageMask)
1521
1522         b, ok := rt.blocks[page]
1523         if !ok {
1524                 rt.pages = append(rt.pages, page)
1525         }
1526
1527         e := peBaseRelocEntry{
1528                 typeOff: uint16(off & 0xFFF),
1529         }
1530
1531         // Set entry type
1532         switch r.Siz() {
1533         default:
1534                 Exitf("unsupported relocation size %d\n", r.Siz)
1535         case 4:
1536                 e.typeOff |= uint16(IMAGE_REL_BASED_HIGHLOW << 12)
1537         case 8:
1538                 e.typeOff |= uint16(IMAGE_REL_BASED_DIR64 << 12)
1539         }
1540
1541         b.entries = append(b.entries, e)
1542         rt.blocks[page] = b
1543 }
1544
1545 func (rt *peBaseRelocTable) write(ctxt *Link) {
1546         out := ctxt.Out
1547
1548         // sort the pages array
1549         sort.Sort(rt.pages)
1550
1551         for _, p := range rt.pages {
1552                 b := rt.blocks[p]
1553                 const sizeOfPEbaseRelocBlock = 8 // 2 * sizeof(uint32)
1554                 blockSize := uint32(sizeOfPEbaseRelocBlock + len(b.entries)*2)
1555                 out.Write32(p)
1556                 out.Write32(blockSize)
1557
1558                 for _, e := range b.entries {
1559                         out.Write16(e.typeOff)
1560                 }
1561         }
1562 }
1563
1564 func addPEBaseRelocSym(ldr *loader.Loader, s loader.Sym, rt *peBaseRelocTable) {
1565         relocs := ldr.Relocs(s)
1566         for ri := 0; ri < relocs.Count(); ri++ {
1567                 r := relocs.At(ri)
1568                 if r.Type() >= objabi.ElfRelocOffset {
1569                         continue
1570                 }
1571                 if r.Siz() == 0 { // informational relocation
1572                         continue
1573                 }
1574                 if r.Type() == objabi.R_DWARFFILEREF {
1575                         continue
1576                 }
1577                 rs := r.Sym()
1578                 if rs == 0 {
1579                         continue
1580                 }
1581                 if !ldr.AttrReachable(s) {
1582                         continue
1583                 }
1584
1585                 switch r.Type() {
1586                 default:
1587                 case objabi.R_ADDR:
1588                         rt.addentry(ldr, s, &r)
1589                 }
1590         }
1591 }
1592
1593 func needPEBaseReloc(ctxt *Link) bool {
1594         // Non-PIE x86 binaries don't need the base relocation table.
1595         // Everyone else does.
1596         if (ctxt.Arch.Family == sys.I386 || ctxt.Arch.Family == sys.AMD64) && ctxt.BuildMode != BuildModePIE {
1597                 return false
1598         }
1599         return true
1600 }
1601
1602 func addPEBaseReloc(ctxt *Link) {
1603         if !needPEBaseReloc(ctxt) {
1604                 return
1605         }
1606
1607         var rt peBaseRelocTable
1608         rt.init(ctxt)
1609
1610         // Get relocation information
1611         ldr := ctxt.loader
1612         for _, s := range ctxt.Textp {
1613                 addPEBaseRelocSym(ldr, s, &rt)
1614         }
1615         for _, s := range ctxt.datap {
1616                 addPEBaseRelocSym(ldr, s, &rt)
1617         }
1618
1619         // Write relocation information
1620         startoff := ctxt.Out.Offset()
1621         rt.write(ctxt)
1622         size := ctxt.Out.Offset() - startoff
1623
1624         // Add a PE section and pad it at the end
1625         rsect := pefile.addSection(".reloc", int(size), int(size))
1626         rsect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
1627         rsect.checkOffset(startoff)
1628         rsect.pad(ctxt.Out, uint32(size))
1629
1630         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = rsect.virtualAddress
1631         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = rsect.virtualSize
1632 }
1633
1634 func (ctxt *Link) dope() {
1635         initdynimport(ctxt)
1636         initdynexport(ctxt)
1637         writeSEH(ctxt)
1638 }
1639
1640 func setpersrc(ctxt *Link, syms []loader.Sym) {
1641         if len(rsrcsyms) != 0 {
1642                 Errorf(nil, "too many .rsrc sections")
1643         }
1644         rsrcsyms = syms
1645 }
1646
1647 func addpersrc(ctxt *Link) {
1648         if len(rsrcsyms) == 0 {
1649                 return
1650         }
1651
1652         var size int64
1653         for _, rsrcsym := range rsrcsyms {
1654                 size += ctxt.loader.SymSize(rsrcsym)
1655         }
1656         h := pefile.addSection(".rsrc", int(size), int(size))
1657         h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA
1658         h.checkOffset(ctxt.Out.Offset())
1659
1660         for _, rsrcsym := range rsrcsyms {
1661                 // A split resource happens when the actual resource data and its relocations are
1662                 // split across multiple sections, denoted by a $01 or $02 at the end of the .rsrc
1663                 // section name.
1664                 splitResources := strings.Contains(ctxt.loader.SymName(rsrcsym), ".rsrc$")
1665                 relocs := ctxt.loader.Relocs(rsrcsym)
1666                 data := ctxt.loader.Data(rsrcsym)
1667                 for ri := 0; ri < relocs.Count(); ri++ {
1668                         r := relocs.At(ri)
1669                         p := data[r.Off():]
1670                         val := uint32(int64(h.virtualAddress) + r.Add())
1671                         if splitResources {
1672                                 // If we're a split resource section, and that section has relocation
1673                                 // symbols, then the data that it points to doesn't actually begin at
1674                                 // the virtual address listed in this current section, but rather
1675                                 // begins at the section immediately after this one. So, in order to
1676                                 // calculate the proper virtual address of the data it's pointing to,
1677                                 // we have to add the length of this section to the virtual address.
1678                                 // This works because .rsrc sections are divided into two (but not more)
1679                                 // of these sections.
1680                                 val += uint32(len(data))
1681                         }
1682                         binary.LittleEndian.PutUint32(p, val)
1683                 }
1684                 ctxt.Out.Write(data)
1685         }
1686         h.pad(ctxt.Out, uint32(size))
1687
1688         // update data directory
1689         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress
1690         pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize
1691 }
1692
1693 func asmbPe(ctxt *Link) {
1694         t := pefile.addSection(".text", int(Segtext.Length), int(Segtext.Length))
1695         t.characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
1696         if ctxt.LinkMode == LinkExternal {
1697                 // some data symbols (e.g. masks) end up in the .text section, and they normally
1698                 // expect larger alignment requirement than the default text section alignment.
1699                 t.characteristics |= IMAGE_SCN_ALIGN_32BYTES
1700         }
1701         t.checkSegment(&Segtext)
1702         pefile.textSect = t
1703
1704         ro := pefile.addSection(".rdata", int(Segrodata.Length), int(Segrodata.Length))
1705         ro.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
1706         if ctxt.LinkMode == LinkExternal {
1707                 // some data symbols (e.g. masks) end up in the .rdata section, and they normally
1708                 // expect larger alignment requirement than the default text section alignment.
1709                 ro.characteristics |= IMAGE_SCN_ALIGN_32BYTES
1710         }
1711         ro.checkSegment(&Segrodata)
1712         pefile.rdataSect = ro
1713
1714         var d *peSection
1715         if ctxt.LinkMode != LinkExternal {
1716                 d = pefile.addSection(".data", int(Segdata.Length), int(Segdata.Filelen))
1717                 d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
1718                 d.checkSegment(&Segdata)
1719                 pefile.dataSect = d
1720         } else {
1721                 d = pefile.addSection(".data", int(Segdata.Filelen), int(Segdata.Filelen))
1722                 d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
1723                 d.checkSegment(&Segdata)
1724                 pefile.dataSect = d
1725
1726                 b := pefile.addSection(".bss", int(Segdata.Length-Segdata.Filelen), 0)
1727                 b.characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
1728                 b.pointerToRawData = 0
1729                 pefile.bssSect = b
1730         }
1731
1732         pefile.addSEH(ctxt)
1733         pefile.addDWARF()
1734
1735         if ctxt.LinkMode == LinkExternal {
1736                 pefile.ctorsSect = pefile.addInitArray(ctxt)
1737         }
1738
1739         ctxt.Out.SeekSet(int64(pefile.nextFileOffset))
1740         if ctxt.LinkMode != LinkExternal {
1741                 addimports(ctxt, d)
1742                 addexports(ctxt)
1743                 addPEBaseReloc(ctxt)
1744         }
1745         pefile.writeSymbolTableAndStringTable(ctxt)
1746         addpersrc(ctxt)
1747         if ctxt.LinkMode == LinkExternal {
1748                 pefile.emitRelocations(ctxt)
1749         }
1750
1751         pewrite(ctxt)
1752 }