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