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
8package ld
9
10import (
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
24type IMAGE_IMPORT_DESCRIPTOR struct {
25	OriginalFirstThunk uint32
26	TimeDateStamp      uint32
27	ForwarderChain     uint32
28	Name               uint32
29	FirstThunk         uint32
30}
31
32type 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
46var (
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
61const (
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.
100const (
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
149const (
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.
157var 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
288type Imp struct {
289	s       loader.Sym
290	off     uint64
291	next    *Imp
292	argsize int
293}
294
295type Dll struct {
296	name     string
297	nameoff  uint64
298	thunkoff uint64
299	ms       *Imp
300	next     *Dll
301}
302
303var (
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.
314type peStringTable struct {
315	strings    []string
316	stringsLen int
317}
318
319// size returns size of string table t.
320func (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.
326func (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.
334func (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.
343type 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.
357func (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.
366func (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.
380func (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.
385func (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.
405func (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.
428type 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.
446func (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.
469func (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.
487func (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.
504func (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.
534func (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.
570func (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
654dwarfLoop:
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.
699func (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.
719func (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
748var isLabel = make(map[loader.Sym]bool)
749
750func AddPELabelSym(ldr *loader.Loader, s loader.Sym) {
751	isLabel[s] = true
752}
753
754// writeSymbols writes all COFF symbol table records.
755func (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.
881func (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.
908func (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.
956func (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
1094var pefile peFile
1095
1096func 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
1160func 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
1176func 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
1185func 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.
1272func 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
1282func 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
1387func 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
1404func 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.
1474type 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.
1483type 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.
1490type pePages []uint32
1491
1492func (p pePages) Len() int           { return len(p) }
1493func (p pePages) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
1494func (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
1500type 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
1508func (rt *peBaseRelocTable) init(ctxt *Link) {
1509	rt.blocks = make(map[uint32]peBaseRelocBlock)
1510}
1511
1512func (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
1545func (rt *peBaseRelocTable) write(ctxt *Link) {
1546	out := ctxt.Out
1547
1548	// sort the pages array
1549	sort.Sort(rt.pages)
1550
1551	// .reloc section must be 32-bit aligned
1552	if out.Offset()&3 != 0 {
1553		Errorf(nil, "internal error, start of .reloc not 32-bit aligned")
1554	}
1555
1556	for _, p := range rt.pages {
1557		b := rt.blocks[p]
1558
1559		// Add a dummy entry at the end of the list if we have an
1560		// odd number of entries, so as to ensure that the next
1561		// block starts on a 32-bit boundary (see issue 68260).
1562		if len(b.entries)&1 != 0 {
1563			b.entries = append(b.entries, peBaseRelocEntry{})
1564		}
1565
1566		const sizeOfPEbaseRelocBlock = 8 // 2 * sizeof(uint32)
1567		blockSize := uint32(sizeOfPEbaseRelocBlock + len(b.entries)*2)
1568		out.Write32(p)
1569		out.Write32(blockSize)
1570
1571		for _, e := range b.entries {
1572			out.Write16(e.typeOff)
1573		}
1574	}
1575}
1576
1577func addPEBaseRelocSym(ldr *loader.Loader, s loader.Sym, rt *peBaseRelocTable) {
1578	relocs := ldr.Relocs(s)
1579	for ri := 0; ri < relocs.Count(); ri++ {
1580		r := relocs.At(ri)
1581		if r.Type() >= objabi.ElfRelocOffset {
1582			continue
1583		}
1584		if r.Siz() == 0 { // informational relocation
1585			continue
1586		}
1587		if r.Type() == objabi.R_DWARFFILEREF {
1588			continue
1589		}
1590		rs := r.Sym()
1591		if rs == 0 {
1592			continue
1593		}
1594		if !ldr.AttrReachable(s) {
1595			continue
1596		}
1597
1598		switch r.Type() {
1599		default:
1600		case objabi.R_ADDR:
1601			rt.addentry(ldr, s, &r)
1602		}
1603	}
1604}
1605
1606func needPEBaseReloc(ctxt *Link) bool {
1607	// Non-PIE x86 binaries don't need the base relocation table.
1608	// Everyone else does.
1609	if (ctxt.Arch.Family == sys.I386 || ctxt.Arch.Family == sys.AMD64) && ctxt.BuildMode != BuildModePIE {
1610		return false
1611	}
1612	return true
1613}
1614
1615func addPEBaseReloc(ctxt *Link) {
1616	if !needPEBaseReloc(ctxt) {
1617		return
1618	}
1619
1620	var rt peBaseRelocTable
1621	rt.init(ctxt)
1622
1623	// Get relocation information
1624	ldr := ctxt.loader
1625	for _, s := range ctxt.Textp {
1626		addPEBaseRelocSym(ldr, s, &rt)
1627	}
1628	for _, s := range ctxt.datap {
1629		addPEBaseRelocSym(ldr, s, &rt)
1630	}
1631
1632	// Write relocation information
1633	startoff := ctxt.Out.Offset()
1634	rt.write(ctxt)
1635	size := ctxt.Out.Offset() - startoff
1636
1637	// Add a PE section and pad it at the end
1638	rsect := pefile.addSection(".reloc", int(size), int(size))
1639	rsect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
1640	rsect.checkOffset(startoff)
1641	rsect.pad(ctxt.Out, uint32(size))
1642
1643	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = rsect.virtualAddress
1644	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = rsect.virtualSize
1645}
1646
1647func (ctxt *Link) dope() {
1648	initdynimport(ctxt)
1649	initdynexport(ctxt)
1650	writeSEH(ctxt)
1651}
1652
1653func setpersrc(ctxt *Link, syms []loader.Sym) {
1654	if len(rsrcsyms) != 0 {
1655		Errorf(nil, "too many .rsrc sections")
1656	}
1657	rsrcsyms = syms
1658}
1659
1660func addpersrc(ctxt *Link) {
1661	if len(rsrcsyms) == 0 {
1662		return
1663	}
1664
1665	var size int64
1666	for _, rsrcsym := range rsrcsyms {
1667		size += ctxt.loader.SymSize(rsrcsym)
1668	}
1669	h := pefile.addSection(".rsrc", int(size), int(size))
1670	h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA
1671	h.checkOffset(ctxt.Out.Offset())
1672
1673	for _, rsrcsym := range rsrcsyms {
1674		// A split resource happens when the actual resource data and its relocations are
1675		// split across multiple sections, denoted by a $01 or $02 at the end of the .rsrc
1676		// section name.
1677		splitResources := strings.Contains(ctxt.loader.SymName(rsrcsym), ".rsrc$")
1678		relocs := ctxt.loader.Relocs(rsrcsym)
1679		data := ctxt.loader.Data(rsrcsym)
1680		for ri := 0; ri < relocs.Count(); ri++ {
1681			r := relocs.At(ri)
1682			p := data[r.Off():]
1683			val := uint32(int64(h.virtualAddress) + r.Add())
1684			if splitResources {
1685				// If we're a split resource section, and that section has relocation
1686				// symbols, then the data that it points to doesn't actually begin at
1687				// the virtual address listed in this current section, but rather
1688				// begins at the section immediately after this one. So, in order to
1689				// calculate the proper virtual address of the data it's pointing to,
1690				// we have to add the length of this section to the virtual address.
1691				// This works because .rsrc sections are divided into two (but not more)
1692				// of these sections.
1693				val += uint32(len(data))
1694			}
1695			binary.LittleEndian.PutUint32(p, val)
1696		}
1697		ctxt.Out.Write(data)
1698	}
1699	h.pad(ctxt.Out, uint32(size))
1700
1701	// update data directory
1702	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress
1703	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize
1704}
1705
1706func asmbPe(ctxt *Link) {
1707	t := pefile.addSection(".text", int(Segtext.Length), int(Segtext.Length))
1708	t.characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
1709	if ctxt.LinkMode == LinkExternal {
1710		// some data symbols (e.g. masks) end up in the .text section, and they normally
1711		// expect larger alignment requirement than the default text section alignment.
1712		t.characteristics |= IMAGE_SCN_ALIGN_32BYTES
1713	}
1714	t.checkSegment(&Segtext)
1715	pefile.textSect = t
1716
1717	ro := pefile.addSection(".rdata", int(Segrodata.Length), int(Segrodata.Length))
1718	ro.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
1719	if ctxt.LinkMode == LinkExternal {
1720		// some data symbols (e.g. masks) end up in the .rdata section, and they normally
1721		// expect larger alignment requirement than the default text section alignment.
1722		ro.characteristics |= IMAGE_SCN_ALIGN_32BYTES
1723	}
1724	ro.checkSegment(&Segrodata)
1725	pefile.rdataSect = ro
1726
1727	var d *peSection
1728	if ctxt.LinkMode != LinkExternal {
1729		d = pefile.addSection(".data", int(Segdata.Length), int(Segdata.Filelen))
1730		d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
1731		d.checkSegment(&Segdata)
1732		pefile.dataSect = d
1733	} else {
1734		d = pefile.addSection(".data", int(Segdata.Filelen), int(Segdata.Filelen))
1735		d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
1736		d.checkSegment(&Segdata)
1737		pefile.dataSect = d
1738
1739		b := pefile.addSection(".bss", int(Segdata.Length-Segdata.Filelen), 0)
1740		b.characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
1741		b.pointerToRawData = 0
1742		pefile.bssSect = b
1743	}
1744
1745	pefile.addSEH(ctxt)
1746	pefile.addDWARF()
1747
1748	if ctxt.LinkMode == LinkExternal {
1749		pefile.ctorsSect = pefile.addInitArray(ctxt)
1750	}
1751
1752	ctxt.Out.SeekSet(int64(pefile.nextFileOffset))
1753	if ctxt.LinkMode != LinkExternal {
1754		addimports(ctxt, d)
1755		addexports(ctxt)
1756		addPEBaseReloc(ctxt)
1757	}
1758	pefile.writeSymbolTableAndStringTable(ctxt)
1759	addpersrc(ctxt)
1760	if ctxt.LinkMode == LinkExternal {
1761		pefile.emitRelocations(ctxt)
1762	}
1763
1764	pewrite(ctxt)
1765}
1766