github.com/bir3/gocompiler@v0.3.205/src/cmd/link/internal/ld/pe.go (about)

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