github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/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  package ld
     6  
     7  import (
     8  	"cmd/internal/objabi"
     9  	"cmd/internal/sys"
    10  	"encoding/binary"
    11  	"fmt"
    12  	"os"
    13  	"sort"
    14  	"strconv"
    15  	"strings"
    16  )
    17  
    18  type IMAGE_FILE_HEADER struct {
    19  	Machine              uint16
    20  	NumberOfSections     uint16
    21  	TimeDateStamp        uint32
    22  	PointerToSymbolTable uint32
    23  	NumberOfSymbols      uint32
    24  	SizeOfOptionalHeader uint16
    25  	Characteristics      uint16
    26  }
    27  
    28  type IMAGE_DATA_DIRECTORY struct {
    29  	VirtualAddress uint32
    30  	Size           uint32
    31  }
    32  
    33  type IMAGE_OPTIONAL_HEADER struct {
    34  	Magic                       uint16
    35  	MajorLinkerVersion          uint8
    36  	MinorLinkerVersion          uint8
    37  	SizeOfCode                  uint32
    38  	SizeOfInitializedData       uint32
    39  	SizeOfUninitializedData     uint32
    40  	AddressOfEntryPoint         uint32
    41  	BaseOfCode                  uint32
    42  	BaseOfData                  uint32
    43  	ImageBase                   uint32
    44  	SectionAlignment            uint32
    45  	FileAlignment               uint32
    46  	MajorOperatingSystemVersion uint16
    47  	MinorOperatingSystemVersion uint16
    48  	MajorImageVersion           uint16
    49  	MinorImageVersion           uint16
    50  	MajorSubsystemVersion       uint16
    51  	MinorSubsystemVersion       uint16
    52  	Win32VersionValue           uint32
    53  	SizeOfImage                 uint32
    54  	SizeOfHeaders               uint32
    55  	CheckSum                    uint32
    56  	Subsystem                   uint16
    57  	DllCharacteristics          uint16
    58  	SizeOfStackReserve          uint32
    59  	SizeOfStackCommit           uint32
    60  	SizeOfHeapReserve           uint32
    61  	SizeOfHeapCommit            uint32
    62  	LoaderFlags                 uint32
    63  	NumberOfRvaAndSizes         uint32
    64  	DataDirectory               [16]IMAGE_DATA_DIRECTORY
    65  }
    66  
    67  type IMAGE_SECTION_HEADER struct {
    68  	Name                 [8]uint8
    69  	VirtualSize          uint32
    70  	VirtualAddress       uint32
    71  	SizeOfRawData        uint32
    72  	PointerToRawData     uint32
    73  	PointerToRelocations uint32
    74  	PointerToLineNumbers uint32
    75  	NumberOfRelocations  uint16
    76  	NumberOfLineNumbers  uint16
    77  	Characteristics      uint32
    78  }
    79  
    80  type IMAGE_IMPORT_DESCRIPTOR struct {
    81  	OriginalFirstThunk uint32
    82  	TimeDateStamp      uint32
    83  	ForwarderChain     uint32
    84  	Name               uint32
    85  	FirstThunk         uint32
    86  }
    87  
    88  type IMAGE_EXPORT_DIRECTORY struct {
    89  	Characteristics       uint32
    90  	TimeDateStamp         uint32
    91  	MajorVersion          uint16
    92  	MinorVersion          uint16
    93  	Name                  uint32
    94  	Base                  uint32
    95  	NumberOfFunctions     uint32
    96  	NumberOfNames         uint32
    97  	AddressOfFunctions    uint32
    98  	AddressOfNames        uint32
    99  	AddressOfNameOrdinals uint32
   100  }
   101  
   102  const (
   103  	PEBASE = 0x00400000
   104  )
   105  
   106  var (
   107  	// SectionAlignment must be greater than or equal to FileAlignment.
   108  	// The default is the page size for the architecture.
   109  	PESECTALIGN int64 = 0x1000
   110  
   111  	// FileAlignment should be a power of 2 between 512 and 64 K, inclusive.
   112  	// The default is 512. If the SectionAlignment is less than
   113  	// the architecture's page size, then FileAlignment must match SectionAlignment.
   114  	PEFILEALIGN int64 = 2 << 8
   115  )
   116  
   117  const (
   118  	IMAGE_FILE_MACHINE_I386              = 0x14c
   119  	IMAGE_FILE_MACHINE_AMD64             = 0x8664
   120  	IMAGE_FILE_RELOCS_STRIPPED           = 0x0001
   121  	IMAGE_FILE_EXECUTABLE_IMAGE          = 0x0002
   122  	IMAGE_FILE_LINE_NUMS_STRIPPED        = 0x0004
   123  	IMAGE_FILE_LARGE_ADDRESS_AWARE       = 0x0020
   124  	IMAGE_FILE_32BIT_MACHINE             = 0x0100
   125  	IMAGE_FILE_DEBUG_STRIPPED            = 0x0200
   126  	IMAGE_SCN_CNT_CODE                   = 0x00000020
   127  	IMAGE_SCN_CNT_INITIALIZED_DATA       = 0x00000040
   128  	IMAGE_SCN_CNT_UNINITIALIZED_DATA     = 0x00000080
   129  	IMAGE_SCN_MEM_EXECUTE                = 0x20000000
   130  	IMAGE_SCN_MEM_READ                   = 0x40000000
   131  	IMAGE_SCN_MEM_WRITE                  = 0x80000000
   132  	IMAGE_SCN_MEM_DISCARDABLE            = 0x2000000
   133  	IMAGE_SCN_LNK_NRELOC_OVFL            = 0x1000000
   134  	IMAGE_SCN_ALIGN_32BYTES              = 0x600000
   135  	IMAGE_DIRECTORY_ENTRY_EXPORT         = 0
   136  	IMAGE_DIRECTORY_ENTRY_IMPORT         = 1
   137  	IMAGE_DIRECTORY_ENTRY_RESOURCE       = 2
   138  	IMAGE_DIRECTORY_ENTRY_EXCEPTION      = 3
   139  	IMAGE_DIRECTORY_ENTRY_SECURITY       = 4
   140  	IMAGE_DIRECTORY_ENTRY_BASERELOC      = 5
   141  	IMAGE_DIRECTORY_ENTRY_DEBUG          = 6
   142  	IMAGE_DIRECTORY_ENTRY_COPYRIGHT      = 7
   143  	IMAGE_DIRECTORY_ENTRY_ARCHITECTURE   = 7
   144  	IMAGE_DIRECTORY_ENTRY_GLOBALPTR      = 8
   145  	IMAGE_DIRECTORY_ENTRY_TLS            = 9
   146  	IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    = 10
   147  	IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   = 11
   148  	IMAGE_DIRECTORY_ENTRY_IAT            = 12
   149  	IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   = 13
   150  	IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14
   151  	IMAGE_SUBSYSTEM_WINDOWS_GUI          = 2
   152  	IMAGE_SUBSYSTEM_WINDOWS_CUI          = 3
   153  )
   154  
   155  // X64
   156  type PE64_IMAGE_OPTIONAL_HEADER struct {
   157  	Magic                       uint16
   158  	MajorLinkerVersion          uint8
   159  	MinorLinkerVersion          uint8
   160  	SizeOfCode                  uint32
   161  	SizeOfInitializedData       uint32
   162  	SizeOfUninitializedData     uint32
   163  	AddressOfEntryPoint         uint32
   164  	BaseOfCode                  uint32
   165  	ImageBase                   uint64
   166  	SectionAlignment            uint32
   167  	FileAlignment               uint32
   168  	MajorOperatingSystemVersion uint16
   169  	MinorOperatingSystemVersion uint16
   170  	MajorImageVersion           uint16
   171  	MinorImageVersion           uint16
   172  	MajorSubsystemVersion       uint16
   173  	MinorSubsystemVersion       uint16
   174  	Win32VersionValue           uint32
   175  	SizeOfImage                 uint32
   176  	SizeOfHeaders               uint32
   177  	CheckSum                    uint32
   178  	Subsystem                   uint16
   179  	DllCharacteristics          uint16
   180  	SizeOfStackReserve          uint64
   181  	SizeOfStackCommit           uint64
   182  	SizeOfHeapReserve           uint64
   183  	SizeOfHeapCommit            uint64
   184  	LoaderFlags                 uint32
   185  	NumberOfRvaAndSizes         uint32
   186  	DataDirectory               [16]IMAGE_DATA_DIRECTORY
   187  }
   188  
   189  // Copyright 2009 The Go Authors. All rights reserved.
   190  // Use of this source code is governed by a BSD-style
   191  // license that can be found in the LICENSE file.
   192  
   193  // PE (Portable Executable) file writing
   194  // http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
   195  
   196  // DOS stub that prints out
   197  // "This program cannot be run in DOS mode."
   198  var dosstub = []uint8{
   199  	0x4d,
   200  	0x5a,
   201  	0x90,
   202  	0x00,
   203  	0x03,
   204  	0x00,
   205  	0x04,
   206  	0x00,
   207  	0x00,
   208  	0x00,
   209  	0x00,
   210  	0x00,
   211  	0xff,
   212  	0xff,
   213  	0x00,
   214  	0x00,
   215  	0x8b,
   216  	0x00,
   217  	0x00,
   218  	0x00,
   219  	0x00,
   220  	0x00,
   221  	0x00,
   222  	0x00,
   223  	0x40,
   224  	0x00,
   225  	0x00,
   226  	0x00,
   227  	0x00,
   228  	0x00,
   229  	0x00,
   230  	0x00,
   231  	0x00,
   232  	0x00,
   233  	0x00,
   234  	0x00,
   235  	0x00,
   236  	0x00,
   237  	0x00,
   238  	0x00,
   239  	0x00,
   240  	0x00,
   241  	0x00,
   242  	0x00,
   243  	0x00,
   244  	0x00,
   245  	0x00,
   246  	0x00,
   247  	0x00,
   248  	0x00,
   249  	0x00,
   250  	0x00,
   251  	0x00,
   252  	0x00,
   253  	0x00,
   254  	0x00,
   255  	0x00,
   256  	0x00,
   257  	0x00,
   258  	0x00,
   259  	0x80,
   260  	0x00,
   261  	0x00,
   262  	0x00,
   263  	0x0e,
   264  	0x1f,
   265  	0xba,
   266  	0x0e,
   267  	0x00,
   268  	0xb4,
   269  	0x09,
   270  	0xcd,
   271  	0x21,
   272  	0xb8,
   273  	0x01,
   274  	0x4c,
   275  	0xcd,
   276  	0x21,
   277  	0x54,
   278  	0x68,
   279  	0x69,
   280  	0x73,
   281  	0x20,
   282  	0x70,
   283  	0x72,
   284  	0x6f,
   285  	0x67,
   286  	0x72,
   287  	0x61,
   288  	0x6d,
   289  	0x20,
   290  	0x63,
   291  	0x61,
   292  	0x6e,
   293  	0x6e,
   294  	0x6f,
   295  	0x74,
   296  	0x20,
   297  	0x62,
   298  	0x65,
   299  	0x20,
   300  	0x72,
   301  	0x75,
   302  	0x6e,
   303  	0x20,
   304  	0x69,
   305  	0x6e,
   306  	0x20,
   307  	0x44,
   308  	0x4f,
   309  	0x53,
   310  	0x20,
   311  	0x6d,
   312  	0x6f,
   313  	0x64,
   314  	0x65,
   315  	0x2e,
   316  	0x0d,
   317  	0x0d,
   318  	0x0a,
   319  	0x24,
   320  	0x00,
   321  	0x00,
   322  	0x00,
   323  	0x00,
   324  	0x00,
   325  	0x00,
   326  	0x00,
   327  }
   328  
   329  var rsrcsym *Symbol
   330  
   331  var strtbl []byte
   332  
   333  var PESECTHEADR int32
   334  
   335  var PEFILEHEADR int32
   336  
   337  var pe64 int
   338  
   339  var pensect int
   340  
   341  var nextsectoff int
   342  
   343  var nextfileoff int
   344  
   345  var textsect int
   346  
   347  var datasect int
   348  
   349  var bsssect int
   350  
   351  var fh IMAGE_FILE_HEADER
   352  
   353  var oh IMAGE_OPTIONAL_HEADER
   354  
   355  var oh64 PE64_IMAGE_OPTIONAL_HEADER
   356  
   357  var sh [16]IMAGE_SECTION_HEADER
   358  
   359  // shNames stores full names of PE sections stored in sh.
   360  var shNames []string
   361  
   362  var dd []IMAGE_DATA_DIRECTORY
   363  
   364  type Imp struct {
   365  	s       *Symbol
   366  	off     uint64
   367  	next    *Imp
   368  	argsize int
   369  }
   370  
   371  type Dll struct {
   372  	name     string
   373  	nameoff  uint64
   374  	thunkoff uint64
   375  	ms       *Imp
   376  	next     *Dll
   377  }
   378  
   379  var dr *Dll
   380  
   381  var dexport [1024]*Symbol
   382  
   383  var nexport int
   384  
   385  func addpesectionWithLongName(ctxt *Link, shortname, longname string, sectsize int, filesize int) *IMAGE_SECTION_HEADER {
   386  	if pensect == 16 {
   387  		Errorf(nil, "too many sections")
   388  		errorexit()
   389  	}
   390  
   391  	h := &sh[pensect]
   392  	pensect++
   393  	copy(h.Name[:], shortname)
   394  	shNames = append(shNames, longname)
   395  	h.VirtualSize = uint32(sectsize)
   396  	h.VirtualAddress = uint32(nextsectoff)
   397  	nextsectoff = int(Rnd(int64(nextsectoff)+int64(sectsize), PESECTALIGN))
   398  	h.PointerToRawData = uint32(nextfileoff)
   399  	if filesize > 0 {
   400  		h.SizeOfRawData = uint32(Rnd(int64(filesize), PEFILEALIGN))
   401  		nextfileoff += int(h.SizeOfRawData)
   402  	}
   403  
   404  	return h
   405  }
   406  
   407  func addpesection(ctxt *Link, name string, sectsize int, filesize int) *IMAGE_SECTION_HEADER {
   408  	return addpesectionWithLongName(ctxt, name, name, sectsize, filesize)
   409  }
   410  func chksectoff(ctxt *Link, h *IMAGE_SECTION_HEADER, off int64) {
   411  	if off != int64(h.PointerToRawData) {
   412  		Errorf(nil, "%s.PointerToRawData = %#x, want %#x", cstring(h.Name[:]), uint64(int64(h.PointerToRawData)), uint64(off))
   413  		errorexit()
   414  	}
   415  }
   416  
   417  func chksectseg(ctxt *Link, h *IMAGE_SECTION_HEADER, s *Segment) {
   418  	if s.Vaddr-PEBASE != uint64(h.VirtualAddress) {
   419  		Errorf(nil, "%s.VirtualAddress = %#x, want %#x", cstring(h.Name[:]), uint64(int64(h.VirtualAddress)), uint64(int64(s.Vaddr-PEBASE)))
   420  		errorexit()
   421  	}
   422  
   423  	if s.Fileoff != uint64(h.PointerToRawData) {
   424  		Errorf(nil, "%s.PointerToRawData = %#x, want %#x", cstring(h.Name[:]), uint64(int64(h.PointerToRawData)), uint64(int64(s.Fileoff)))
   425  		errorexit()
   426  	}
   427  }
   428  
   429  func Peinit(ctxt *Link) {
   430  	var l int
   431  
   432  	switch SysArch.Family {
   433  	// 64-bit architectures
   434  	case sys.AMD64:
   435  		pe64 = 1
   436  
   437  		l = binary.Size(&oh64)
   438  		dd = oh64.DataDirectory[:]
   439  
   440  	// 32-bit architectures
   441  	default:
   442  		l = binary.Size(&oh)
   443  
   444  		dd = oh.DataDirectory[:]
   445  	}
   446  
   447  	if Linkmode == LinkExternal {
   448  		PESECTALIGN = 0
   449  		PEFILEALIGN = 0
   450  	}
   451  
   452  	PEFILEHEADR = int32(Rnd(int64(len(dosstub)+binary.Size(&fh)+l+binary.Size(&sh)), PEFILEALIGN))
   453  	if Linkmode != LinkExternal {
   454  		PESECTHEADR = int32(Rnd(int64(PEFILEHEADR), PESECTALIGN))
   455  	} else {
   456  		PESECTHEADR = 0
   457  	}
   458  	nextsectoff = int(PESECTHEADR)
   459  	nextfileoff = int(PEFILEHEADR)
   460  
   461  	if Linkmode == LinkInternal {
   462  		// some mingw libs depend on this symbol, for example, FindPESectionByName
   463  		ctxt.xdefine("__image_base__", SDATA, PEBASE)
   464  		ctxt.xdefine("_image_base__", SDATA, PEBASE)
   465  	}
   466  
   467  	HEADR = PEFILEHEADR
   468  	if *FlagTextAddr == -1 {
   469  		*FlagTextAddr = PEBASE + int64(PESECTHEADR)
   470  	}
   471  	if *FlagDataAddr == -1 {
   472  		*FlagDataAddr = 0
   473  	}
   474  	if *FlagRound == -1 {
   475  		*FlagRound = int(PESECTALIGN)
   476  	}
   477  	if *FlagDataAddr != 0 && *FlagRound != 0 {
   478  		fmt.Printf("warning: -D0x%x is ignored because of -R0x%x\n", uint64(*FlagDataAddr), uint32(*FlagRound))
   479  	}
   480  }
   481  
   482  func pewrite() {
   483  	Cseek(0)
   484  	if Linkmode != LinkExternal {
   485  		Cwrite(dosstub)
   486  		strnput("PE", 4)
   487  	}
   488  
   489  	binary.Write(&coutbuf, binary.LittleEndian, &fh)
   490  
   491  	if pe64 != 0 {
   492  		binary.Write(&coutbuf, binary.LittleEndian, &oh64)
   493  	} else {
   494  		binary.Write(&coutbuf, binary.LittleEndian, &oh)
   495  	}
   496  	if Linkmode == LinkExternal {
   497  		for i := range sh[:pensect] {
   498  			sh[i].VirtualAddress = 0
   499  		}
   500  	}
   501  	binary.Write(&coutbuf, binary.LittleEndian, sh[:pensect])
   502  }
   503  
   504  func strput(s string) {
   505  	coutbuf.WriteString(s)
   506  	Cput(0)
   507  	// string must be padded to even size
   508  	if (len(s)+1)%2 != 0 {
   509  		Cput(0)
   510  	}
   511  }
   512  
   513  func initdynimport(ctxt *Link) *Dll {
   514  	var d *Dll
   515  
   516  	dr = nil
   517  	var m *Imp
   518  	for _, s := range ctxt.Syms.Allsym {
   519  		if !s.Attr.Reachable() || s.Type != SDYNIMPORT {
   520  			continue
   521  		}
   522  		for d = dr; d != nil; d = d.next {
   523  			if d.name == s.Dynimplib {
   524  				m = new(Imp)
   525  				break
   526  			}
   527  		}
   528  
   529  		if d == nil {
   530  			d = new(Dll)
   531  			d.name = s.Dynimplib
   532  			d.next = dr
   533  			dr = d
   534  			m = new(Imp)
   535  		}
   536  
   537  		// Because external link requires properly stdcall decorated name,
   538  		// all external symbols in runtime use %n to denote that the number
   539  		// of uinptrs this function consumes. Store the argsize and discard
   540  		// the %n suffix if any.
   541  		m.argsize = -1
   542  		if i := strings.IndexByte(s.Extname, '%'); i >= 0 {
   543  			var err error
   544  			m.argsize, err = strconv.Atoi(s.Extname[i+1:])
   545  			if err != nil {
   546  				Errorf(s, "failed to parse stdcall decoration: %v", err)
   547  			}
   548  			m.argsize *= SysArch.PtrSize
   549  			s.Extname = s.Extname[:i]
   550  		}
   551  
   552  		m.s = s
   553  		m.next = d.ms
   554  		d.ms = m
   555  	}
   556  
   557  	if Linkmode == LinkExternal {
   558  		// Add real symbol name
   559  		for d := dr; d != nil; d = d.next {
   560  			for m = d.ms; m != nil; m = m.next {
   561  				m.s.Type = SDATA
   562  				Symgrow(m.s, int64(SysArch.PtrSize))
   563  				dynName := m.s.Extname
   564  				// only windows/386 requires stdcall decoration
   565  				if SysArch.Family == sys.I386 && m.argsize >= 0 {
   566  					dynName += fmt.Sprintf("@%d", m.argsize)
   567  				}
   568  				dynSym := ctxt.Syms.Lookup(dynName, 0)
   569  				dynSym.Attr |= AttrReachable
   570  				dynSym.Type = SHOSTOBJ
   571  				r := Addrel(m.s)
   572  				r.Sym = dynSym
   573  				r.Off = 0
   574  				r.Siz = uint8(SysArch.PtrSize)
   575  				r.Type = objabi.R_ADDR
   576  			}
   577  		}
   578  	} else {
   579  		dynamic := ctxt.Syms.Lookup(".windynamic", 0)
   580  		dynamic.Attr |= AttrReachable
   581  		dynamic.Type = SWINDOWS
   582  		for d := dr; d != nil; d = d.next {
   583  			for m = d.ms; m != nil; m = m.next {
   584  				m.s.Type = SWINDOWS | SSUB
   585  				m.s.Sub = dynamic.Sub
   586  				dynamic.Sub = m.s
   587  				m.s.Value = dynamic.Size
   588  				dynamic.Size += int64(SysArch.PtrSize)
   589  			}
   590  
   591  			dynamic.Size += int64(SysArch.PtrSize)
   592  		}
   593  	}
   594  
   595  	return dr
   596  }
   597  
   598  // peimporteddlls returns the gcc command line argument to link all imported
   599  // DLLs.
   600  func peimporteddlls() []string {
   601  	var dlls []string
   602  
   603  	for d := dr; d != nil; d = d.next {
   604  		dlls = append(dlls, "-l"+strings.TrimSuffix(d.name, ".dll"))
   605  	}
   606  
   607  	return dlls
   608  }
   609  
   610  func addimports(ctxt *Link, datsect *IMAGE_SECTION_HEADER) {
   611  	startoff := coutbuf.Offset()
   612  	dynamic := ctxt.Syms.Lookup(".windynamic", 0)
   613  
   614  	// skip import descriptor table (will write it later)
   615  	n := uint64(0)
   616  
   617  	for d := dr; d != nil; d = d.next {
   618  		n++
   619  	}
   620  	Cseek(startoff + int64(binary.Size(&IMAGE_IMPORT_DESCRIPTOR{}))*int64(n+1))
   621  
   622  	// write dll names
   623  	for d := dr; d != nil; d = d.next {
   624  		d.nameoff = uint64(coutbuf.Offset()) - uint64(startoff)
   625  		strput(d.name)
   626  	}
   627  
   628  	// write function names
   629  	var m *Imp
   630  	for d := dr; d != nil; d = d.next {
   631  		for m = d.ms; m != nil; m = m.next {
   632  			m.off = uint64(nextsectoff) + uint64(coutbuf.Offset()) - uint64(startoff)
   633  			Wputl(0) // hint
   634  			strput(m.s.Extname)
   635  		}
   636  	}
   637  
   638  	// write OriginalFirstThunks
   639  	oftbase := uint64(coutbuf.Offset()) - uint64(startoff)
   640  
   641  	n = uint64(coutbuf.Offset())
   642  	for d := dr; d != nil; d = d.next {
   643  		d.thunkoff = uint64(coutbuf.Offset()) - n
   644  		for m = d.ms; m != nil; m = m.next {
   645  			if pe64 != 0 {
   646  				Vputl(m.off)
   647  			} else {
   648  				Lputl(uint32(m.off))
   649  			}
   650  		}
   651  
   652  		if pe64 != 0 {
   653  			Vputl(0)
   654  		} else {
   655  			Lputl(0)
   656  		}
   657  	}
   658  
   659  	// add pe section and pad it at the end
   660  	n = uint64(coutbuf.Offset()) - uint64(startoff)
   661  
   662  	isect := addpesection(ctxt, ".idata", int(n), int(n))
   663  	isect.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
   664  	chksectoff(ctxt, isect, startoff)
   665  	strnput("", int(uint64(isect.SizeOfRawData)-n))
   666  	endoff := coutbuf.Offset()
   667  
   668  	// write FirstThunks (allocated in .data section)
   669  	ftbase := uint64(dynamic.Value) - uint64(datsect.VirtualAddress) - PEBASE
   670  
   671  	Cseek(int64(uint64(datsect.PointerToRawData) + ftbase))
   672  	for d := dr; d != nil; d = d.next {
   673  		for m = d.ms; m != nil; m = m.next {
   674  			if pe64 != 0 {
   675  				Vputl(m.off)
   676  			} else {
   677  				Lputl(uint32(m.off))
   678  			}
   679  		}
   680  
   681  		if pe64 != 0 {
   682  			Vputl(0)
   683  		} else {
   684  			Lputl(0)
   685  		}
   686  	}
   687  
   688  	// finally write import descriptor table
   689  	Cseek(startoff)
   690  
   691  	for d := dr; d != nil; d = d.next {
   692  		Lputl(uint32(uint64(isect.VirtualAddress) + oftbase + d.thunkoff))
   693  		Lputl(0)
   694  		Lputl(0)
   695  		Lputl(uint32(uint64(isect.VirtualAddress) + d.nameoff))
   696  		Lputl(uint32(uint64(datsect.VirtualAddress) + ftbase + d.thunkoff))
   697  	}
   698  
   699  	Lputl(0) //end
   700  	Lputl(0)
   701  	Lputl(0)
   702  	Lputl(0)
   703  	Lputl(0)
   704  
   705  	// update data directory
   706  	dd[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.VirtualAddress
   707  	dd[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.VirtualSize
   708  	dd[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(dynamic.Value - PEBASE)
   709  	dd[IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(dynamic.Size)
   710  
   711  	Cseek(endoff)
   712  }
   713  
   714  type byExtname []*Symbol
   715  
   716  func (s byExtname) Len() int           { return len(s) }
   717  func (s byExtname) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
   718  func (s byExtname) Less(i, j int) bool { return s[i].Extname < s[j].Extname }
   719  
   720  func initdynexport(ctxt *Link) {
   721  	nexport = 0
   722  	for _, s := range ctxt.Syms.Allsym {
   723  		if !s.Attr.Reachable() || !s.Attr.CgoExportDynamic() {
   724  			continue
   725  		}
   726  		if nexport+1 > len(dexport) {
   727  			Errorf(s, "pe dynexport table is full")
   728  			errorexit()
   729  		}
   730  
   731  		dexport[nexport] = s
   732  		nexport++
   733  	}
   734  
   735  	sort.Sort(byExtname(dexport[:nexport]))
   736  }
   737  
   738  func addexports(ctxt *Link) {
   739  	var e IMAGE_EXPORT_DIRECTORY
   740  
   741  	size := binary.Size(&e) + 10*nexport + len(*flagOutfile) + 1
   742  	for i := 0; i < nexport; i++ {
   743  		size += len(dexport[i].Extname) + 1
   744  	}
   745  
   746  	if nexport == 0 {
   747  		return
   748  	}
   749  
   750  	sect := addpesection(ctxt, ".edata", size, size)
   751  	sect.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
   752  	chksectoff(ctxt, sect, coutbuf.Offset())
   753  	va := int(sect.VirtualAddress)
   754  	dd[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = uint32(va)
   755  	dd[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect.VirtualSize
   756  
   757  	vaName := va + binary.Size(&e) + nexport*4
   758  	vaAddr := va + binary.Size(&e)
   759  	vaNa := va + binary.Size(&e) + nexport*8
   760  
   761  	e.Characteristics = 0
   762  	e.MajorVersion = 0
   763  	e.MinorVersion = 0
   764  	e.NumberOfFunctions = uint32(nexport)
   765  	e.NumberOfNames = uint32(nexport)
   766  	e.Name = uint32(va+binary.Size(&e)) + uint32(nexport)*10 // Program names.
   767  	e.Base = 1
   768  	e.AddressOfFunctions = uint32(vaAddr)
   769  	e.AddressOfNames = uint32(vaName)
   770  	e.AddressOfNameOrdinals = uint32(vaNa)
   771  
   772  	// put IMAGE_EXPORT_DIRECTORY
   773  	binary.Write(&coutbuf, binary.LittleEndian, &e)
   774  
   775  	// put EXPORT Address Table
   776  	for i := 0; i < nexport; i++ {
   777  		Lputl(uint32(dexport[i].Value - PEBASE))
   778  	}
   779  
   780  	// put EXPORT Name Pointer Table
   781  	v := int(e.Name + uint32(len(*flagOutfile)) + 1)
   782  
   783  	for i := 0; i < nexport; i++ {
   784  		Lputl(uint32(v))
   785  		v += len(dexport[i].Extname) + 1
   786  	}
   787  
   788  	// put EXPORT Ordinal Table
   789  	for i := 0; i < nexport; i++ {
   790  		Wputl(uint16(i))
   791  	}
   792  
   793  	// put Names
   794  	strnput(*flagOutfile, len(*flagOutfile)+1)
   795  
   796  	for i := 0; i < nexport; i++ {
   797  		strnput(dexport[i].Extname, len(dexport[i].Extname)+1)
   798  	}
   799  	strnput("", int(sect.SizeOfRawData-uint32(size)))
   800  }
   801  
   802  // perelocsect relocates symbols from first in section sect, and returns
   803  // the total number of relocations emitted.
   804  func perelocsect(ctxt *Link, sect *Section, syms []*Symbol, base uint64) int {
   805  	// If main section has no bits, nothing to relocate.
   806  	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
   807  		return 0
   808  	}
   809  
   810  	relocs := 0
   811  
   812  	sect.Reloff = uint64(coutbuf.Offset())
   813  	for i, s := range syms {
   814  		if !s.Attr.Reachable() {
   815  			continue
   816  		}
   817  		if uint64(s.Value) >= sect.Vaddr {
   818  			syms = syms[i:]
   819  			break
   820  		}
   821  	}
   822  
   823  	eaddr := int32(sect.Vaddr + sect.Length)
   824  	for _, sym := range syms {
   825  		if !sym.Attr.Reachable() {
   826  			continue
   827  		}
   828  		if sym.Value >= int64(eaddr) {
   829  			break
   830  		}
   831  		for ri := 0; ri < len(sym.R); ri++ {
   832  			r := &sym.R[ri]
   833  			if r.Done != 0 {
   834  				continue
   835  			}
   836  			if r.Xsym == nil {
   837  				Errorf(sym, "missing xsym in relocation")
   838  				continue
   839  			}
   840  
   841  			if r.Xsym.Dynid < 0 {
   842  				Errorf(sym, "reloc %d to non-coff symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type)
   843  			}
   844  			if !Thearch.PEreloc1(sym, r, int64(uint64(sym.Value+int64(r.Off))-base)) {
   845  				Errorf(sym, "unsupported obj reloc %d/%d to %s", r.Type, r.Siz, r.Sym.Name)
   846  			}
   847  
   848  			relocs++
   849  		}
   850  	}
   851  
   852  	sect.Rellen = uint64(coutbuf.Offset()) - sect.Reloff
   853  
   854  	return relocs
   855  }
   856  
   857  // peemitsectreloc emits the relocation entries for sect.
   858  // The actual relocations are emitted by relocfn.
   859  // This updates the corresponding PE section table entry
   860  // with the relocation offset and count.
   861  func peemitsectreloc(sect *IMAGE_SECTION_HEADER, relocfn func() int) {
   862  	sect.PointerToRelocations = uint32(coutbuf.Offset())
   863  	// first entry: extended relocs
   864  	Lputl(0) // placeholder for number of relocation + 1
   865  	Lputl(0)
   866  	Wputl(0)
   867  
   868  	n := relocfn() + 1
   869  
   870  	cpos := coutbuf.Offset()
   871  	Cseek(int64(sect.PointerToRelocations))
   872  	Lputl(uint32(n))
   873  	Cseek(cpos)
   874  	if n > 0x10000 {
   875  		n = 0x10000
   876  		sect.Characteristics |= IMAGE_SCN_LNK_NRELOC_OVFL
   877  	} else {
   878  		sect.PointerToRelocations += 10 // skip the extend reloc entry
   879  	}
   880  	sect.NumberOfRelocations = uint16(n - 1)
   881  }
   882  
   883  // peemitreloc emits relocation entries for go.o in external linking.
   884  func peemitreloc(ctxt *Link, text, data, ctors *IMAGE_SECTION_HEADER) {
   885  	for coutbuf.Offset()&7 != 0 {
   886  		Cput(0)
   887  	}
   888  
   889  	peemitsectreloc(text, func() int {
   890  		n := perelocsect(ctxt, Segtext.Sections[0], ctxt.Textp, Segtext.Vaddr)
   891  		for _, sect := range Segtext.Sections[1:] {
   892  			n += perelocsect(ctxt, sect, datap, Segtext.Vaddr)
   893  		}
   894  		return n
   895  	})
   896  
   897  	peemitsectreloc(data, func() int {
   898  		var n int
   899  		for _, sect := range Segdata.Sections {
   900  			n += perelocsect(ctxt, sect, datap, Segdata.Vaddr)
   901  		}
   902  		return n
   903  	})
   904  
   905  dwarfLoop:
   906  	for _, sect := range Segdwarf.Sections {
   907  		for i, name := range shNames {
   908  			if sect.Name == name {
   909  				peemitsectreloc(&sh[i], func() int {
   910  					return perelocsect(ctxt, sect, dwarfp, sect.Vaddr)
   911  				})
   912  				continue dwarfLoop
   913  			}
   914  		}
   915  		Errorf(nil, "peemitsectreloc: could not find %q section", sect.Name)
   916  	}
   917  
   918  	peemitsectreloc(ctors, func() int {
   919  		dottext := ctxt.Syms.Lookup(".text", 0)
   920  		Lputl(0)
   921  		Lputl(uint32(dottext.Dynid))
   922  		switch objabi.GOARCH {
   923  		default:
   924  			Errorf(dottext, "unknown architecture for PE: %q\n", objabi.GOARCH)
   925  		case "386":
   926  			Wputl(IMAGE_REL_I386_DIR32)
   927  		case "amd64":
   928  			Wputl(IMAGE_REL_AMD64_ADDR64)
   929  		}
   930  		return 1
   931  	})
   932  }
   933  
   934  func (ctxt *Link) dope() {
   935  	/* relocation table */
   936  	rel := ctxt.Syms.Lookup(".rel", 0)
   937  
   938  	rel.Attr |= AttrReachable
   939  	rel.Type = SELFROSECT
   940  
   941  	initdynimport(ctxt)
   942  	initdynexport(ctxt)
   943  }
   944  
   945  func strtbladd(name string) int {
   946  	off := len(strtbl) + 4 // offset includes 4-byte length at beginning of table
   947  	strtbl = append(strtbl, name...)
   948  	strtbl = append(strtbl, 0)
   949  	return off
   950  }
   951  
   952  /*
   953   * For more than 8 characters section names, name contains a slash (/) that is
   954   * followed by an ASCII representation of a decimal number that is an offset into
   955   * the string table.
   956   * reference: pecoff_v8.docx Page 24.
   957   * <http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx>
   958   */
   959  func newPEDWARFSection(ctxt *Link, name string, size int64) *IMAGE_SECTION_HEADER {
   960  	if size == 0 {
   961  		return nil
   962  	}
   963  
   964  	off := strtbladd(name)
   965  	s := fmt.Sprintf("/%d", off)
   966  	h := addpesectionWithLongName(ctxt, s, name, int(size), int(size))
   967  	h.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
   968  
   969  	return h
   970  }
   971  
   972  // writePESymTableRecords writes all COFF symbol table records.
   973  // It returns number of records written.
   974  func writePESymTableRecords(ctxt *Link) int {
   975  	var symcnt int
   976  
   977  	writeOneSymbol := func(s *Symbol, addr int64, sectidx int, typ uint16, class uint8) {
   978  		// write COFF symbol table record
   979  		if len(s.Name) > 8 {
   980  			Lputl(0)
   981  			Lputl(uint32(strtbladd(s.Name)))
   982  		} else {
   983  			strnput(s.Name, 8)
   984  		}
   985  		Lputl(uint32(addr))
   986  		Wputl(uint16(sectidx))
   987  		Wputl(typ)
   988  		Cput(class)
   989  		Cput(0) // no aux entries
   990  
   991  		s.Dynid = int32(symcnt)
   992  
   993  		symcnt++
   994  	}
   995  
   996  	put := func(ctxt *Link, s *Symbol, name string, type_ SymbolType, addr int64, gotype *Symbol) {
   997  		if s == nil {
   998  			return
   999  		}
  1000  		if s.Sect == nil && type_ != UndefinedSym {
  1001  			return
  1002  		}
  1003  		switch type_ {
  1004  		default:
  1005  			return
  1006  		case DataSym, BSSSym, TextSym, UndefinedSym:
  1007  		}
  1008  
  1009  		// Only windows/386 requires underscore prefix on external symbols.
  1010  		if SysArch.Family == sys.I386 &&
  1011  			Linkmode == LinkExternal &&
  1012  			(s.Type == SHOSTOBJ || s.Attr.CgoExport()) {
  1013  			s.Name = "_" + s.Name
  1014  		}
  1015  
  1016  		typ := uint16(IMAGE_SYM_TYPE_NULL)
  1017  		var sect int
  1018  		var value int64
  1019  		if s.Sect != nil && s.Sect.Seg == &Segdata {
  1020  			// Note: although address of runtime.edata (type SDATA) is at the start of .bss section
  1021  			// it still belongs to the .data section, not the .bss section.
  1022  			if uint64(s.Value) >= Segdata.Vaddr+Segdata.Filelen && s.Type != SDATA && Linkmode == LinkExternal {
  1023  				value = int64(uint64(s.Value) - Segdata.Vaddr - Segdata.Filelen)
  1024  				sect = bsssect
  1025  			} else {
  1026  				value = int64(uint64(s.Value) - Segdata.Vaddr)
  1027  				sect = datasect
  1028  			}
  1029  		} else if s.Sect != nil && s.Sect.Seg == &Segtext {
  1030  			value = int64(uint64(s.Value) - Segtext.Vaddr)
  1031  			sect = textsect
  1032  		} else if type_ == UndefinedSym {
  1033  			typ = IMAGE_SYM_DTYPE_FUNCTION
  1034  		} else {
  1035  			Errorf(s, "addpesym %#x", addr)
  1036  		}
  1037  		if typ != IMAGE_SYM_TYPE_NULL {
  1038  		} else if Linkmode != LinkExternal {
  1039  			// TODO: fix IMAGE_SYM_DTYPE_ARRAY value and use following expression, instead of 0x0308
  1040  			typ = IMAGE_SYM_DTYPE_ARRAY<<8 + IMAGE_SYM_TYPE_STRUCT
  1041  			typ = 0x0308 // "array of structs"
  1042  		}
  1043  		class := IMAGE_SYM_CLASS_EXTERNAL
  1044  		if s.Version != 0 || (s.Type&SHIDDEN != 0) || s.Attr.Local() {
  1045  			class = IMAGE_SYM_CLASS_STATIC
  1046  		}
  1047  		writeOneSymbol(s, value, sect, typ, uint8(class))
  1048  	}
  1049  
  1050  	if Linkmode == LinkExternal {
  1051  		// Include section symbols as external, because
  1052  		// .ctors and .debug_* section relocations refer to it.
  1053  		for idx, name := range shNames {
  1054  			sym := ctxt.Syms.Lookup(name, 0)
  1055  			writeOneSymbol(sym, 0, idx+1, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_STATIC)
  1056  		}
  1057  	}
  1058  
  1059  	genasmsym(ctxt, put)
  1060  
  1061  	return symcnt
  1062  }
  1063  
  1064  func addpesymtable(ctxt *Link) {
  1065  	symtabStartPos := coutbuf.Offset()
  1066  
  1067  	// write COFF symbol table
  1068  	var symcnt int
  1069  	if !*FlagS || Linkmode == LinkExternal {
  1070  		symcnt = writePESymTableRecords(ctxt)
  1071  	}
  1072  
  1073  	// update COFF file header and section table
  1074  	size := len(strtbl) + 4 + 18*symcnt
  1075  	var h *IMAGE_SECTION_HEADER
  1076  	if Linkmode != LinkExternal {
  1077  		// We do not really need .symtab for go.o, and if we have one, ld
  1078  		// will also include it in the exe, and that will confuse windows.
  1079  		h = addpesection(ctxt, ".symtab", size, size)
  1080  		h.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
  1081  		chksectoff(ctxt, h, symtabStartPos)
  1082  	}
  1083  	fh.PointerToSymbolTable = uint32(symtabStartPos)
  1084  	fh.NumberOfSymbols = uint32(symcnt)
  1085  
  1086  	// write COFF string table
  1087  	Lputl(uint32(len(strtbl)) + 4)
  1088  	for i := 0; i < len(strtbl); i++ {
  1089  		Cput(strtbl[i])
  1090  	}
  1091  	if Linkmode != LinkExternal {
  1092  		strnput("", int(h.SizeOfRawData-uint32(size)))
  1093  	}
  1094  }
  1095  
  1096  func setpersrc(ctxt *Link, sym *Symbol) {
  1097  	if rsrcsym != nil {
  1098  		Errorf(sym, "too many .rsrc sections")
  1099  	}
  1100  
  1101  	rsrcsym = sym
  1102  }
  1103  
  1104  func addpersrc(ctxt *Link) {
  1105  	if rsrcsym == nil {
  1106  		return
  1107  	}
  1108  
  1109  	h := addpesection(ctxt, ".rsrc", int(rsrcsym.Size), int(rsrcsym.Size))
  1110  	h.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA
  1111  	chksectoff(ctxt, h, coutbuf.Offset())
  1112  
  1113  	// relocation
  1114  	var p []byte
  1115  	var r *Reloc
  1116  	var val uint32
  1117  	for ri := 0; ri < len(rsrcsym.R); ri++ {
  1118  		r = &rsrcsym.R[ri]
  1119  		p = rsrcsym.P[r.Off:]
  1120  		val = uint32(int64(h.VirtualAddress) + r.Add)
  1121  
  1122  		// 32-bit little-endian
  1123  		p[0] = byte(val)
  1124  
  1125  		p[1] = byte(val >> 8)
  1126  		p[2] = byte(val >> 16)
  1127  		p[3] = byte(val >> 24)
  1128  	}
  1129  
  1130  	Cwrite(rsrcsym.P)
  1131  	strnput("", int(int64(h.SizeOfRawData)-rsrcsym.Size))
  1132  
  1133  	// update data directory
  1134  	dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.VirtualAddress
  1135  
  1136  	dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.VirtualSize
  1137  }
  1138  
  1139  func addinitarray(ctxt *Link) (c *IMAGE_SECTION_HEADER) {
  1140  	// The size below was determined by the specification for array relocations,
  1141  	// and by observing what GCC writes here. If the initarray section grows to
  1142  	// contain more than one constructor entry, the size will need to be 8 * constructor_count.
  1143  	// However, the entire Go runtime is initialized from just one function, so it is unlikely
  1144  	// that this will need to grow in the future.
  1145  	var size int
  1146  	switch objabi.GOARCH {
  1147  	default:
  1148  		fmt.Fprintf(os.Stderr, "link: unknown architecture for PE: %q\n", objabi.GOARCH)
  1149  		os.Exit(2)
  1150  	case "386":
  1151  		size = 4
  1152  	case "amd64":
  1153  		size = 8
  1154  	}
  1155  
  1156  	c = addpesection(ctxt, ".ctors", size, size)
  1157  	c.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
  1158  	c.SizeOfRawData = uint32(size)
  1159  
  1160  	Cseek(int64(c.PointerToRawData))
  1161  	chksectoff(ctxt, c, coutbuf.Offset())
  1162  	init_entry := ctxt.Syms.Lookup(*flagEntrySymbol, 0)
  1163  	addr := uint64(init_entry.Value) - init_entry.Sect.Vaddr
  1164  
  1165  	switch objabi.GOARCH {
  1166  	case "386":
  1167  		Lputl(uint32(addr))
  1168  	case "amd64":
  1169  		Vputl(addr)
  1170  	}
  1171  
  1172  	return c
  1173  }
  1174  
  1175  func Asmbpe(ctxt *Link) {
  1176  	switch SysArch.Family {
  1177  	default:
  1178  		Exitf("unknown PE architecture: %v", SysArch.Family)
  1179  	case sys.AMD64:
  1180  		fh.Machine = IMAGE_FILE_MACHINE_AMD64
  1181  	case sys.I386:
  1182  		fh.Machine = IMAGE_FILE_MACHINE_I386
  1183  	}
  1184  
  1185  	t := addpesection(ctxt, ".text", int(Segtext.Length), int(Segtext.Length))
  1186  	t.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
  1187  	if Linkmode == LinkExternal {
  1188  		// some data symbols (e.g. masks) end up in the .text section, and they normally
  1189  		// expect larger alignment requirement than the default text section alignment.
  1190  		t.Characteristics |= IMAGE_SCN_ALIGN_32BYTES
  1191  	}
  1192  	chksectseg(ctxt, t, &Segtext)
  1193  	textsect = pensect
  1194  
  1195  	var d *IMAGE_SECTION_HEADER
  1196  	var c *IMAGE_SECTION_HEADER
  1197  	if Linkmode != LinkExternal {
  1198  		d = addpesection(ctxt, ".data", int(Segdata.Length), int(Segdata.Filelen))
  1199  		d.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
  1200  		chksectseg(ctxt, d, &Segdata)
  1201  		datasect = pensect
  1202  	} else {
  1203  		d = addpesection(ctxt, ".data", int(Segdata.Filelen), int(Segdata.Filelen))
  1204  		d.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
  1205  		chksectseg(ctxt, d, &Segdata)
  1206  		datasect = pensect
  1207  
  1208  		b := addpesection(ctxt, ".bss", int(Segdata.Length-Segdata.Filelen), 0)
  1209  		b.Characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
  1210  		b.PointerToRawData = 0
  1211  		bsssect = pensect
  1212  	}
  1213  
  1214  	if !*FlagS {
  1215  		dwarfaddpeheaders(ctxt)
  1216  	}
  1217  
  1218  	if Linkmode == LinkExternal {
  1219  		c = addinitarray(ctxt)
  1220  	}
  1221  
  1222  	Cseek(int64(nextfileoff))
  1223  	if Linkmode != LinkExternal {
  1224  		addimports(ctxt, d)
  1225  		addexports(ctxt)
  1226  	}
  1227  	addpesymtable(ctxt)
  1228  	addpersrc(ctxt)
  1229  	if Linkmode == LinkExternal {
  1230  		peemitreloc(ctxt, t, d, c)
  1231  	}
  1232  
  1233  	fh.NumberOfSections = uint16(pensect)
  1234  
  1235  	// Being able to produce identical output for identical input is
  1236  	// much more beneficial than having build timestamp in the header.
  1237  	fh.TimeDateStamp = 0
  1238  
  1239  	if Linkmode == LinkExternal {
  1240  		fh.Characteristics = IMAGE_FILE_LINE_NUMS_STRIPPED
  1241  	} else {
  1242  		fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DEBUG_STRIPPED
  1243  	}
  1244  	if pe64 != 0 {
  1245  		fh.SizeOfOptionalHeader = uint16(binary.Size(&oh64))
  1246  		fh.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE
  1247  		oh64.Magic = 0x20b // PE32+
  1248  	} else {
  1249  		fh.SizeOfOptionalHeader = uint16(binary.Size(&oh))
  1250  		fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE
  1251  		oh.Magic = 0x10b // PE32
  1252  		oh.BaseOfData = d.VirtualAddress
  1253  	}
  1254  
  1255  	// Fill out both oh64 and oh. We only use one. Oh well.
  1256  	oh64.MajorLinkerVersion = 3
  1257  
  1258  	oh.MajorLinkerVersion = 3
  1259  	oh64.MinorLinkerVersion = 0
  1260  	oh.MinorLinkerVersion = 0
  1261  	oh64.SizeOfCode = t.SizeOfRawData
  1262  	oh.SizeOfCode = t.SizeOfRawData
  1263  	oh64.SizeOfInitializedData = d.SizeOfRawData
  1264  	oh.SizeOfInitializedData = d.SizeOfRawData
  1265  	oh64.SizeOfUninitializedData = 0
  1266  	oh.SizeOfUninitializedData = 0
  1267  	if Linkmode != LinkExternal {
  1268  		oh64.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
  1269  		oh.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
  1270  	}
  1271  	oh64.BaseOfCode = t.VirtualAddress
  1272  	oh.BaseOfCode = t.VirtualAddress
  1273  	oh64.ImageBase = PEBASE
  1274  	oh.ImageBase = PEBASE
  1275  	oh64.SectionAlignment = uint32(PESECTALIGN)
  1276  	oh.SectionAlignment = uint32(PESECTALIGN)
  1277  	oh64.FileAlignment = uint32(PEFILEALIGN)
  1278  	oh.FileAlignment = uint32(PEFILEALIGN)
  1279  	oh64.MajorOperatingSystemVersion = 4
  1280  	oh.MajorOperatingSystemVersion = 4
  1281  	oh64.MinorOperatingSystemVersion = 0
  1282  	oh.MinorOperatingSystemVersion = 0
  1283  	oh64.MajorImageVersion = 1
  1284  	oh.MajorImageVersion = 1
  1285  	oh64.MinorImageVersion = 0
  1286  	oh.MinorImageVersion = 0
  1287  	oh64.MajorSubsystemVersion = 4
  1288  	oh.MajorSubsystemVersion = 4
  1289  	oh64.MinorSubsystemVersion = 0
  1290  	oh.MinorSubsystemVersion = 0
  1291  	oh64.SizeOfImage = uint32(nextsectoff)
  1292  	oh.SizeOfImage = uint32(nextsectoff)
  1293  	oh64.SizeOfHeaders = uint32(PEFILEHEADR)
  1294  	oh.SizeOfHeaders = uint32(PEFILEHEADR)
  1295  	if windowsgui {
  1296  		oh64.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
  1297  		oh.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
  1298  	} else {
  1299  		oh64.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
  1300  		oh.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
  1301  	}
  1302  
  1303  	// Disable stack growth as we don't want Windows to
  1304  	// fiddle with the thread stack limits, which we set
  1305  	// ourselves to circumvent the stack checks in the
  1306  	// Windows exception dispatcher.
  1307  	// Commit size must be strictly less than reserve
  1308  	// size otherwise reserve will be rounded up to a
  1309  	// larger size, as verified with VMMap.
  1310  
  1311  	// Go code would be OK with 64k stacks, but we need larger stacks for cgo.
  1312  	//
  1313  	// The default stack reserve size affects only the main
  1314  	// thread, ctrlhandler thread, and profileloop thread. For
  1315  	// these, it must be greater than the stack size assumed by
  1316  	// externalthreadhandler.
  1317  	//
  1318  	// For other threads we specify stack size in runtime explicitly
  1319  	// (runtime knows whether cgo is enabled or not).
  1320  	// For these, the reserve must match STACKSIZE in
  1321  	// runtime/cgo/gcc_windows_{386,amd64}.c and the correspondent
  1322  	// CreateThread parameter in runtime.newosproc.
  1323  	if !iscgo {
  1324  		oh64.SizeOfStackReserve = 0x00020000
  1325  		oh.SizeOfStackReserve = 0x00020000
  1326  		oh64.SizeOfStackCommit = 0x00001000
  1327  		oh.SizeOfStackCommit = 0x00001000
  1328  	} else {
  1329  		oh64.SizeOfStackReserve = 0x00200000
  1330  		oh.SizeOfStackReserve = 0x00100000
  1331  
  1332  		// account for 2 guard pages
  1333  		oh64.SizeOfStackCommit = 0x00200000 - 0x2000
  1334  
  1335  		oh.SizeOfStackCommit = 0x00100000 - 0x2000
  1336  	}
  1337  
  1338  	oh64.SizeOfHeapReserve = 0x00100000
  1339  	oh.SizeOfHeapReserve = 0x00100000
  1340  	oh64.SizeOfHeapCommit = 0x00001000
  1341  	oh.SizeOfHeapCommit = 0x00001000
  1342  	oh64.NumberOfRvaAndSizes = 16
  1343  	oh.NumberOfRvaAndSizes = 16
  1344  
  1345  	pewrite()
  1346  }