github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/ld/pe.go (about)

     1  // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/ld/pe.go
     2  
     3  // Copyright 2009 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  package ld
     8  
     9  import (
    10  	"rsc.io/tmp/bootstrap/internal/obj"
    11  	"encoding/binary"
    12  	"fmt"
    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 *LSym
   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       *LSym
   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]*LSym
   377  
   378  var nexport int
   379  
   380  type COFFSym struct {
   381  	sym       *LSym
   382  	strtbloff int
   383  	sect      int
   384  	value     int64
   385  	typ       uint16
   386  }
   387  
   388  var coffsym []COFFSym
   389  
   390  var ncoffsym int
   391  
   392  func addpesection(name string, sectsize int, filesize int) *IMAGE_SECTION_HEADER {
   393  	if pensect == 16 {
   394  		Diag("too many sections")
   395  		errorexit()
   396  	}
   397  
   398  	h := &sh[pensect]
   399  	pensect++
   400  	copy(h.Name[:], name)
   401  	h.VirtualSize = uint32(sectsize)
   402  	h.VirtualAddress = uint32(nextsectoff)
   403  	nextsectoff = int(Rnd(int64(nextsectoff)+int64(sectsize), PESECTALIGN))
   404  	h.PointerToRawData = uint32(nextfileoff)
   405  	if filesize > 0 {
   406  		h.SizeOfRawData = uint32(Rnd(int64(filesize), PEFILEALIGN))
   407  		nextfileoff += int(h.SizeOfRawData)
   408  	}
   409  
   410  	return h
   411  }
   412  
   413  func chksectoff(h *IMAGE_SECTION_HEADER, off int64) {
   414  	if off != int64(h.PointerToRawData) {
   415  		Diag("%s.PointerToRawData = %#x, want %#x", cstring(h.Name[:]), uint64(int64(h.PointerToRawData)), uint64(off))
   416  		errorexit()
   417  	}
   418  }
   419  
   420  func chksectseg(h *IMAGE_SECTION_HEADER, s *Segment) {
   421  	if s.Vaddr-PEBASE != uint64(h.VirtualAddress) {
   422  		Diag("%s.VirtualAddress = %#x, want %#x", cstring(h.Name[:]), uint64(int64(h.VirtualAddress)), uint64(int64(s.Vaddr-PEBASE)))
   423  		errorexit()
   424  	}
   425  
   426  	if s.Fileoff != uint64(h.PointerToRawData) {
   427  		Diag("%s.PointerToRawData = %#x, want %#x", cstring(h.Name[:]), uint64(int64(h.PointerToRawData)), uint64(int64(s.Fileoff)))
   428  		errorexit()
   429  	}
   430  }
   431  
   432  func Peinit() {
   433  	var l int
   434  
   435  	switch Thearch.Thechar {
   436  	// 64-bit architectures
   437  	case '6':
   438  		pe64 = 1
   439  
   440  		l = binary.Size(&oh64)
   441  		dd = oh64.DataDirectory[:]
   442  
   443  	// 32-bit architectures
   444  	default:
   445  		l = binary.Size(&oh)
   446  
   447  		dd = oh.DataDirectory[:]
   448  	}
   449  
   450  	PEFILEHEADR = int32(Rnd(int64(len(dosstub)+binary.Size(&fh)+l+binary.Size(&sh)), PEFILEALIGN))
   451  	PESECTHEADR = int32(Rnd(int64(PEFILEHEADR), PESECTALIGN))
   452  	nextsectoff = int(PESECTHEADR)
   453  	nextfileoff = int(PEFILEHEADR)
   454  
   455  	// some mingw libs depend on this symbol, for example, FindPESectionByName
   456  	xdefine("__image_base__", obj.SDATA, PEBASE)
   457  
   458  	xdefine("_image_base__", obj.SDATA, PEBASE)
   459  }
   460  
   461  func pewrite() {
   462  	Cseek(0)
   463  	if Linkmode != LinkExternal {
   464  		Cwrite(dosstub)
   465  		strnput("PE", 4)
   466  	}
   467  
   468  	binary.Write(&coutbuf, binary.LittleEndian, &fh)
   469  
   470  	if pe64 != 0 {
   471  		binary.Write(&coutbuf, binary.LittleEndian, &oh64)
   472  	} else {
   473  		binary.Write(&coutbuf, binary.LittleEndian, &oh)
   474  	}
   475  	binary.Write(&coutbuf, binary.LittleEndian, sh[:pensect])
   476  }
   477  
   478  func strput(s string) {
   479  	coutbuf.w.WriteString(s)
   480  	Cput(0)
   481  	// string must be padded to even size
   482  	if (len(s)+1)%2 != 0 {
   483  		Cput(0)
   484  	}
   485  }
   486  
   487  func initdynimport() *Dll {
   488  	var d *Dll
   489  
   490  	dr = nil
   491  	var m *Imp
   492  	for s := Ctxt.Allsym; s != nil; s = s.Allsym {
   493  		if !s.Reachable || s.Type != obj.SDYNIMPORT {
   494  			continue
   495  		}
   496  		for d = dr; d != nil; d = d.next {
   497  			if d.name == s.Dynimplib {
   498  				m = new(Imp)
   499  				break
   500  			}
   501  		}
   502  
   503  		if d == nil {
   504  			d = new(Dll)
   505  			d.name = s.Dynimplib
   506  			d.next = dr
   507  			dr = d
   508  			m = new(Imp)
   509  		}
   510  
   511  		// Because external link requires properly stdcall decorated name,
   512  		// all external symbols in runtime use %n to denote that the number
   513  		// of uinptrs this function consumes. Store the argsize and discard
   514  		// the %n suffix if any.
   515  		m.argsize = -1
   516  		if i := strings.IndexByte(s.Extname, '%'); i >= 0 {
   517  			var err error
   518  			m.argsize, err = strconv.Atoi(s.Extname[i+1:])
   519  			if err != nil {
   520  				Diag("failed to parse stdcall decoration: %v", err)
   521  			}
   522  			m.argsize *= Thearch.Ptrsize
   523  			s.Extname = s.Extname[:i]
   524  		}
   525  
   526  		m.s = s
   527  		m.next = d.ms
   528  		d.ms = m
   529  	}
   530  
   531  	if Linkmode == LinkExternal {
   532  		// Add real symbol name
   533  		for d := dr; d != nil; d = d.next {
   534  			for m = d.ms; m != nil; m = m.next {
   535  				m.s.Type = obj.SDATA
   536  				Symgrow(Ctxt, m.s, int64(Thearch.Ptrsize))
   537  				dynName := m.s.Extname
   538  				// only windows/386 requires stdcall decoration
   539  				if Thearch.Thechar == '8' && m.argsize >= 0 {
   540  					dynName += fmt.Sprintf("@%d", m.argsize)
   541  				}
   542  				dynSym := Linklookup(Ctxt, dynName, 0)
   543  				dynSym.Reachable = true
   544  				dynSym.Type = obj.SHOSTOBJ
   545  				r := Addrel(m.s)
   546  				r.Sym = dynSym
   547  				r.Off = 0
   548  				r.Siz = uint8(Thearch.Ptrsize)
   549  				r.Type = obj.R_ADDR
   550  
   551  				// pre-allocate symtab entries for those symbols
   552  				dynSym.Dynid = int32(ncoffsym)
   553  				ncoffsym++
   554  			}
   555  		}
   556  	} else {
   557  		dynamic := Linklookup(Ctxt, ".windynamic", 0)
   558  		dynamic.Reachable = true
   559  		dynamic.Type = obj.SWINDOWS
   560  		for d := dr; d != nil; d = d.next {
   561  			for m = d.ms; m != nil; m = m.next {
   562  				m.s.Type = obj.SWINDOWS | obj.SSUB
   563  				m.s.Sub = dynamic.Sub
   564  				dynamic.Sub = m.s
   565  				m.s.Value = dynamic.Size
   566  				dynamic.Size += int64(Thearch.Ptrsize)
   567  			}
   568  
   569  			dynamic.Size += int64(Thearch.Ptrsize)
   570  		}
   571  	}
   572  
   573  	return dr
   574  }
   575  
   576  // peimporteddlls returns the gcc command line argument to link all imported
   577  // DLLs.
   578  func peimporteddlls() []string {
   579  	var dlls []string
   580  
   581  	for d := dr; d != nil; d = d.next {
   582  		dlls = append(dlls, "-l"+strings.TrimSuffix(d.name, ".dll"))
   583  	}
   584  
   585  	return dlls
   586  }
   587  
   588  func addimports(datsect *IMAGE_SECTION_HEADER) {
   589  	startoff := Cpos()
   590  	dynamic := Linklookup(Ctxt, ".windynamic", 0)
   591  
   592  	// skip import descriptor table (will write it later)
   593  	n := uint64(0)
   594  
   595  	for d := dr; d != nil; d = d.next {
   596  		n++
   597  	}
   598  	Cseek(startoff + int64(binary.Size(&IMAGE_IMPORT_DESCRIPTOR{}))*int64(n+1))
   599  
   600  	// write dll names
   601  	for d := dr; d != nil; d = d.next {
   602  		d.nameoff = uint64(Cpos()) - uint64(startoff)
   603  		strput(d.name)
   604  	}
   605  
   606  	// write function names
   607  	var m *Imp
   608  	for d := dr; d != nil; d = d.next {
   609  		for m = d.ms; m != nil; m = m.next {
   610  			m.off = uint64(nextsectoff) + uint64(Cpos()) - uint64(startoff)
   611  			Wputl(0) // hint
   612  			strput(m.s.Extname)
   613  		}
   614  	}
   615  
   616  	// write OriginalFirstThunks
   617  	oftbase := uint64(Cpos()) - uint64(startoff)
   618  
   619  	n = uint64(Cpos())
   620  	for d := dr; d != nil; d = d.next {
   621  		d.thunkoff = uint64(Cpos()) - n
   622  		for m = d.ms; m != nil; m = m.next {
   623  			if pe64 != 0 {
   624  				Vputl(m.off)
   625  			} else {
   626  				Lputl(uint32(m.off))
   627  			}
   628  		}
   629  
   630  		if pe64 != 0 {
   631  			Vputl(0)
   632  		} else {
   633  			Lputl(0)
   634  		}
   635  	}
   636  
   637  	// add pe section and pad it at the end
   638  	n = uint64(Cpos()) - uint64(startoff)
   639  
   640  	isect := addpesection(".idata", int(n), int(n))
   641  	isect.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
   642  	chksectoff(isect, startoff)
   643  	strnput("", int(uint64(isect.SizeOfRawData)-n))
   644  	endoff := Cpos()
   645  
   646  	// write FirstThunks (allocated in .data section)
   647  	ftbase := uint64(dynamic.Value) - uint64(datsect.VirtualAddress) - PEBASE
   648  
   649  	Cseek(int64(uint64(datsect.PointerToRawData) + ftbase))
   650  	for d := dr; d != nil; d = d.next {
   651  		for m = d.ms; m != nil; m = m.next {
   652  			if pe64 != 0 {
   653  				Vputl(m.off)
   654  			} else {
   655  				Lputl(uint32(m.off))
   656  			}
   657  		}
   658  
   659  		if pe64 != 0 {
   660  			Vputl(0)
   661  		} else {
   662  			Lputl(0)
   663  		}
   664  	}
   665  
   666  	// finally write import descriptor table
   667  	Cseek(startoff)
   668  
   669  	for d := dr; d != nil; d = d.next {
   670  		Lputl(uint32(uint64(isect.VirtualAddress) + oftbase + d.thunkoff))
   671  		Lputl(0)
   672  		Lputl(0)
   673  		Lputl(uint32(uint64(isect.VirtualAddress) + d.nameoff))
   674  		Lputl(uint32(uint64(datsect.VirtualAddress) + ftbase + d.thunkoff))
   675  	}
   676  
   677  	Lputl(0) //end
   678  	Lputl(0)
   679  	Lputl(0)
   680  	Lputl(0)
   681  	Lputl(0)
   682  
   683  	// update data directory
   684  	dd[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.VirtualAddress
   685  
   686  	dd[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.VirtualSize
   687  	dd[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(dynamic.Value - PEBASE)
   688  	dd[IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(dynamic.Size)
   689  
   690  	Cseek(endoff)
   691  }
   692  
   693  type pescmp []*LSym
   694  
   695  func (x pescmp) Len() int {
   696  	return len(x)
   697  }
   698  
   699  func (x pescmp) Swap(i, j int) {
   700  	x[i], x[j] = x[j], x[i]
   701  }
   702  
   703  func (x pescmp) Less(i, j int) bool {
   704  	s1 := x[i]
   705  	s2 := x[j]
   706  	return stringsCompare(s1.Extname, s2.Extname) < 0
   707  }
   708  
   709  func initdynexport() {
   710  	nexport = 0
   711  	for s := Ctxt.Allsym; s != nil; s = s.Allsym {
   712  		if !s.Reachable || s.Cgoexport&CgoExportDynamic == 0 {
   713  			continue
   714  		}
   715  		if nexport+1 > len(dexport) {
   716  			Diag("pe dynexport table is full")
   717  			errorexit()
   718  		}
   719  
   720  		dexport[nexport] = s
   721  		nexport++
   722  	}
   723  
   724  	sort.Sort(pescmp(dexport[:nexport]))
   725  }
   726  
   727  func addexports() {
   728  	var e IMAGE_EXPORT_DIRECTORY
   729  
   730  	size := binary.Size(&e) + 10*nexport + len(outfile) + 1
   731  	for i := 0; i < nexport; i++ {
   732  		size += len(dexport[i].Extname) + 1
   733  	}
   734  
   735  	if nexport == 0 {
   736  		return
   737  	}
   738  
   739  	sect := addpesection(".edata", size, size)
   740  	sect.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
   741  	chksectoff(sect, Cpos())
   742  	va := int(sect.VirtualAddress)
   743  	dd[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = uint32(va)
   744  	dd[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect.VirtualSize
   745  
   746  	va_name := va + binary.Size(&e) + nexport*4
   747  	va_addr := va + binary.Size(&e)
   748  	va_na := va + binary.Size(&e) + nexport*8
   749  
   750  	e.Characteristics = 0
   751  	e.MajorVersion = 0
   752  	e.MinorVersion = 0
   753  	e.NumberOfFunctions = uint32(nexport)
   754  	e.NumberOfNames = uint32(nexport)
   755  	e.Name = uint32(va+binary.Size(&e)) + uint32(nexport)*10 // Program names.
   756  	e.Base = 1
   757  	e.AddressOfFunctions = uint32(va_addr)
   758  	e.AddressOfNames = uint32(va_name)
   759  	e.AddressOfNameOrdinals = uint32(va_na)
   760  
   761  	// put IMAGE_EXPORT_DIRECTORY
   762  	binary.Write(&coutbuf, binary.LittleEndian, &e)
   763  
   764  	// put EXPORT Address Table
   765  	for i := 0; i < nexport; i++ {
   766  		Lputl(uint32(dexport[i].Value - PEBASE))
   767  	}
   768  
   769  	// put EXPORT Name Pointer Table
   770  	v := int(e.Name + uint32(len(outfile)) + 1)
   771  
   772  	for i := 0; i < nexport; i++ {
   773  		Lputl(uint32(v))
   774  		v += len(dexport[i].Extname) + 1
   775  	}
   776  
   777  	// put EXPORT Ordinal Table
   778  	for i := 0; i < nexport; i++ {
   779  		Wputl(uint16(i))
   780  	}
   781  
   782  	// put Names
   783  	strnput(outfile, len(outfile)+1)
   784  
   785  	for i := 0; i < nexport; i++ {
   786  		strnput(dexport[i].Extname, len(dexport[i].Extname)+1)
   787  	}
   788  	strnput("", int(sect.SizeOfRawData-uint32(size)))
   789  }
   790  
   791  // perelocsect relocates symbols from first in section sect, and returns
   792  // the total number of relocations emitted.
   793  func perelocsect(sect *Section, first *LSym) int {
   794  	// If main section has no bits, nothing to relocate.
   795  	if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
   796  		return 0
   797  	}
   798  
   799  	relocs := 0
   800  
   801  	sect.Reloff = uint64(Cpos())
   802  	var sym *LSym
   803  	for sym = first; sym != nil; sym = sym.Next {
   804  		if !sym.Reachable {
   805  			continue
   806  		}
   807  		if uint64(sym.Value) >= sect.Vaddr {
   808  			break
   809  		}
   810  	}
   811  
   812  	eaddr := int32(sect.Vaddr + sect.Length)
   813  	var r *Reloc
   814  	var ri int
   815  	for ; sym != nil; sym = sym.Next {
   816  		if !sym.Reachable {
   817  			continue
   818  		}
   819  		if sym.Value >= int64(eaddr) {
   820  			break
   821  		}
   822  		Ctxt.Cursym = sym
   823  
   824  		for ri = 0; ri < len(sym.R); ri++ {
   825  			r = &sym.R[ri]
   826  			if r.Done != 0 {
   827  				continue
   828  			}
   829  			if r.Xsym == nil {
   830  				Diag("missing xsym in relocation")
   831  				continue
   832  			}
   833  
   834  			if r.Xsym.Dynid < 0 {
   835  				Diag("reloc %d to non-coff symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type)
   836  			}
   837  			if !Thearch.PEreloc1(r, int64(uint64(sym.Value+int64(r.Off))-PEBASE)) {
   838  				Diag("unsupported obj reloc %d/%d to %s", r.Type, r.Siz, r.Sym.Name)
   839  			}
   840  
   841  			relocs++
   842  		}
   843  	}
   844  
   845  	sect.Rellen = uint64(Cpos()) - sect.Reloff
   846  
   847  	return relocs
   848  }
   849  
   850  // peemitreloc emits relocation entries for go.o in external linking.
   851  func peemitreloc(text, data *IMAGE_SECTION_HEADER) {
   852  	for Cpos()&7 != 0 {
   853  		Cput(0)
   854  	}
   855  
   856  	text.PointerToRelocations = uint32(Cpos())
   857  	// first entry: extended relocs
   858  	Lputl(0) // placeholder for number of relocation + 1
   859  	Lputl(0)
   860  	Wputl(0)
   861  
   862  	n := perelocsect(Segtext.Sect, Ctxt.Textp) + 1
   863  	for sect := Segtext.Sect.Next; sect != nil; sect = sect.Next {
   864  		n += perelocsect(sect, datap)
   865  	}
   866  
   867  	cpos := Cpos()
   868  	Cseek(int64(text.PointerToRelocations))
   869  	Lputl(uint32(n))
   870  	Cseek(cpos)
   871  	if n > 0x10000 {
   872  		n = 0x10000
   873  		text.Characteristics |= IMAGE_SCN_LNK_NRELOC_OVFL
   874  	} else {
   875  		text.PointerToRelocations += 10 // skip the extend reloc entry
   876  	}
   877  	text.NumberOfRelocations = uint16(n - 1)
   878  
   879  	data.PointerToRelocations = uint32(cpos)
   880  	// first entry: extended relocs
   881  	Lputl(0) // placeholder for number of relocation + 1
   882  	Lputl(0)
   883  	Wputl(0)
   884  
   885  	n = 1
   886  	for sect := Segdata.Sect; sect != nil; sect = sect.Next {
   887  		n += perelocsect(sect, datap)
   888  	}
   889  
   890  	cpos = Cpos()
   891  	Cseek(int64(data.PointerToRelocations))
   892  	Lputl(uint32(n))
   893  	Cseek(cpos)
   894  	if n > 0x10000 {
   895  		n = 0x10000
   896  		data.Characteristics |= IMAGE_SCN_LNK_NRELOC_OVFL
   897  	} else {
   898  		data.PointerToRelocations += 10 // skip the extend reloc entry
   899  	}
   900  	data.NumberOfRelocations = uint16(n - 1)
   901  }
   902  
   903  func dope() {
   904  	/* relocation table */
   905  	rel := Linklookup(Ctxt, ".rel", 0)
   906  
   907  	rel.Reachable = true
   908  	rel.Type = obj.SELFROSECT
   909  
   910  	initdynimport()
   911  	initdynexport()
   912  }
   913  
   914  func strtbladd(name string) int {
   915  	off := len(strtbl) + 4 // offset includes 4-byte length at beginning of table
   916  	strtbl = append(strtbl, name...)
   917  	strtbl = append(strtbl, 0)
   918  	return off
   919  }
   920  
   921  /*
   922   * For more than 8 characters section names, name contains a slash (/) that is
   923   * followed by an ASCII representation of a decimal number that is an offset into
   924   * the string table.
   925   * reference: pecoff_v8.docx Page 24.
   926   * <http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx>
   927   */
   928  func newPEDWARFSection(name string, size int64) *IMAGE_SECTION_HEADER {
   929  	if size == 0 {
   930  		return nil
   931  	}
   932  
   933  	off := strtbladd(name)
   934  	s := fmt.Sprintf("/%d", off)
   935  	h := addpesection(s, int(size), int(size))
   936  	h.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
   937  
   938  	return h
   939  }
   940  
   941  func addpesym(s *LSym, name string, type_ int, addr int64, size int64, ver int, gotype *LSym) {
   942  	if s == nil {
   943  		return
   944  	}
   945  
   946  	if s.Sect == nil && type_ != 'U' {
   947  		return
   948  	}
   949  
   950  	switch type_ {
   951  	default:
   952  		return
   953  
   954  	case 'D', 'B', 'T', 'U':
   955  		break
   956  	}
   957  
   958  	if coffsym != nil {
   959  		// only windows/386 requires underscore prefix on external symbols
   960  		if Thearch.Thechar == '8' && Linkmode == LinkExternal && (s.Type == obj.SHOSTOBJ || s.Cgoexport != 0) && s.Name == s.Extname {
   961  			s.Name = "_" + s.Name
   962  		}
   963  		cs := &coffsym[ncoffsym]
   964  		cs.sym = s
   965  		if len(s.Name) > 8 {
   966  			cs.strtbloff = strtbladd(s.Name)
   967  		}
   968  		// Note: although address of runtime.edata (type SDATA) is at the start of .bss section
   969  		// it still belongs to the .data section, not the .bss section.
   970  		if uint64(s.Value) >= Segdata.Vaddr+Segdata.Filelen && s.Type != obj.SDATA && Linkmode == LinkExternal {
   971  			cs.value = int64(uint64(s.Value) - Segdata.Vaddr - Segdata.Filelen)
   972  			cs.sect = bsssect
   973  		} else if uint64(s.Value) >= Segdata.Vaddr {
   974  			cs.value = int64(uint64(s.Value) - Segdata.Vaddr)
   975  			cs.sect = datasect
   976  		} else if uint64(s.Value) >= Segtext.Vaddr {
   977  			cs.value = int64(uint64(s.Value) - Segtext.Vaddr)
   978  			cs.sect = textsect
   979  		} else if type_ == 'U' {
   980  			cs.value = 0
   981  			cs.typ = IMAGE_SYM_DTYPE_FUNCTION
   982  		} else {
   983  			cs.value = 0
   984  			cs.sect = 0
   985  			Diag("addpesym %#x", addr)
   986  		}
   987  	}
   988  
   989  	s.Dynid = int32(ncoffsym)
   990  	ncoffsym++
   991  }
   992  
   993  func addpesymtable() {
   994  	if Debug['s'] == 0 {
   995  		genasmsym(addpesym)
   996  		coffsym = make([]COFFSym, ncoffsym)
   997  		ncoffsym = 0
   998  		if Linkmode == LinkExternal {
   999  			for d := dr; d != nil; d = d.next {
  1000  				for m := d.ms; m != nil; m = m.next {
  1001  					s := m.s.R[0].Xsym
  1002  					addpesym(s, s.Name, 'U', 0, int64(Thearch.Ptrsize), 0, nil)
  1003  				}
  1004  			}
  1005  		}
  1006  		genasmsym(addpesym)
  1007  	}
  1008  	size := len(strtbl) + 4 + 18*ncoffsym
  1009  
  1010  	var h *IMAGE_SECTION_HEADER
  1011  	if Linkmode != LinkExternal {
  1012  		// We do not really need .symtab for go.o, and if we have one, ld
  1013  		// will also include it in the exe, and that will confuse windows.
  1014  		h = addpesection(".symtab", size, size)
  1015  		h.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
  1016  		chksectoff(h, Cpos())
  1017  	}
  1018  	fh.PointerToSymbolTable = uint32(Cpos())
  1019  	fh.NumberOfSymbols = uint32(ncoffsym)
  1020  
  1021  	// put COFF symbol table
  1022  	var s *COFFSym
  1023  	for i := 0; i < ncoffsym; i++ {
  1024  		s = &coffsym[i]
  1025  		if s.strtbloff == 0 {
  1026  			strnput(s.sym.Name, 8)
  1027  		} else {
  1028  			Lputl(0)
  1029  			Lputl(uint32(s.strtbloff))
  1030  		}
  1031  
  1032  		Lputl(uint32(s.value))
  1033  		Wputl(uint16(s.sect))
  1034  		if s.typ != 0 {
  1035  			Wputl(s.typ)
  1036  		} else if Linkmode == LinkExternal {
  1037  			Wputl(0)
  1038  		} else {
  1039  			Wputl(0x0308) // "array of structs"
  1040  		}
  1041  		Cput(2) // storage class: external
  1042  		Cput(0) // no aux entries
  1043  	}
  1044  
  1045  	// put COFF string table
  1046  	Lputl(uint32(len(strtbl)) + 4)
  1047  
  1048  	for i := 0; i < len(strtbl); i++ {
  1049  		Cput(uint8(strtbl[i]))
  1050  	}
  1051  	if Linkmode != LinkExternal {
  1052  		strnput("", int(h.SizeOfRawData-uint32(size)))
  1053  	}
  1054  }
  1055  
  1056  func setpersrc(sym *LSym) {
  1057  	if rsrcsym != nil {
  1058  		Diag("too many .rsrc sections")
  1059  	}
  1060  
  1061  	rsrcsym = sym
  1062  }
  1063  
  1064  func addpersrc() {
  1065  	if rsrcsym == nil {
  1066  		return
  1067  	}
  1068  
  1069  	h := addpesection(".rsrc", int(rsrcsym.Size), int(rsrcsym.Size))
  1070  	h.Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA
  1071  	chksectoff(h, Cpos())
  1072  
  1073  	// relocation
  1074  	var p []byte
  1075  	var r *Reloc
  1076  	var val uint32
  1077  	for ri := 0; ri < len(rsrcsym.R); ri++ {
  1078  		r = &rsrcsym.R[ri]
  1079  		p = rsrcsym.P[r.Off:]
  1080  		val = uint32(int64(h.VirtualAddress) + r.Add)
  1081  
  1082  		// 32-bit little-endian
  1083  		p[0] = byte(val)
  1084  
  1085  		p[1] = byte(val >> 8)
  1086  		p[2] = byte(val >> 16)
  1087  		p[3] = byte(val >> 24)
  1088  	}
  1089  
  1090  	Cwrite(rsrcsym.P)
  1091  	strnput("", int(int64(h.SizeOfRawData)-rsrcsym.Size))
  1092  
  1093  	// update data directory
  1094  	dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.VirtualAddress
  1095  
  1096  	dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.VirtualSize
  1097  }
  1098  
  1099  func Asmbpe() {
  1100  	switch Thearch.Thechar {
  1101  	default:
  1102  		Exitf("unknown PE architecture: %v", Thearch.Thechar)
  1103  	case '6':
  1104  		fh.Machine = IMAGE_FILE_MACHINE_AMD64
  1105  	case '8':
  1106  		fh.Machine = IMAGE_FILE_MACHINE_I386
  1107  	}
  1108  
  1109  	t := addpesection(".text", int(Segtext.Length), int(Segtext.Length))
  1110  	t.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
  1111  	chksectseg(t, &Segtext)
  1112  	textsect = pensect
  1113  
  1114  	var d *IMAGE_SECTION_HEADER
  1115  	if Linkmode != LinkExternal {
  1116  		d = addpesection(".data", int(Segdata.Length), int(Segdata.Filelen))
  1117  		d.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
  1118  		chksectseg(d, &Segdata)
  1119  		datasect = pensect
  1120  	} else {
  1121  		d = addpesection(".data", int(Segdata.Filelen), int(Segdata.Filelen))
  1122  		d.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
  1123  		chksectseg(d, &Segdata)
  1124  		datasect = pensect
  1125  
  1126  		b := addpesection(".bss", int(Segdata.Length-Segdata.Filelen), 0)
  1127  		b.Characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
  1128  		b.PointerToRawData = 0
  1129  		bsssect = pensect
  1130  	}
  1131  
  1132  	if Debug['s'] == 0 {
  1133  		dwarfaddpeheaders()
  1134  	}
  1135  
  1136  	Cseek(int64(nextfileoff))
  1137  	if Linkmode != LinkExternal {
  1138  		addimports(d)
  1139  		addexports()
  1140  	}
  1141  	addpesymtable()
  1142  	addpersrc()
  1143  	if Linkmode == LinkExternal {
  1144  		peemitreloc(t, d)
  1145  	}
  1146  
  1147  	fh.NumberOfSections = uint16(pensect)
  1148  
  1149  	// Being able to produce identical output for identical input is
  1150  	// much more beneficial than having build timestamp in the header.
  1151  	fh.TimeDateStamp = 0
  1152  
  1153  	if Linkmode == LinkExternal {
  1154  		fh.Characteristics = IMAGE_FILE_LINE_NUMS_STRIPPED
  1155  	} else {
  1156  		fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DEBUG_STRIPPED
  1157  	}
  1158  	if pe64 != 0 {
  1159  		fh.SizeOfOptionalHeader = uint16(binary.Size(&oh64))
  1160  		fh.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE
  1161  		oh64.Magic = 0x20b // PE32+
  1162  	} else {
  1163  		fh.SizeOfOptionalHeader = uint16(binary.Size(&oh))
  1164  		fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE
  1165  		oh.Magic = 0x10b // PE32
  1166  		oh.BaseOfData = d.VirtualAddress
  1167  	}
  1168  
  1169  	// Fill out both oh64 and oh. We only use one. Oh well.
  1170  	oh64.MajorLinkerVersion = 3
  1171  
  1172  	oh.MajorLinkerVersion = 3
  1173  	oh64.MinorLinkerVersion = 0
  1174  	oh.MinorLinkerVersion = 0
  1175  	oh64.SizeOfCode = t.SizeOfRawData
  1176  	oh.SizeOfCode = t.SizeOfRawData
  1177  	oh64.SizeOfInitializedData = d.SizeOfRawData
  1178  	oh.SizeOfInitializedData = d.SizeOfRawData
  1179  	oh64.SizeOfUninitializedData = 0
  1180  	oh.SizeOfUninitializedData = 0
  1181  	if Linkmode != LinkExternal {
  1182  		oh64.AddressOfEntryPoint = uint32(Entryvalue() - PEBASE)
  1183  		oh.AddressOfEntryPoint = uint32(Entryvalue() - PEBASE)
  1184  	}
  1185  	oh64.BaseOfCode = t.VirtualAddress
  1186  	oh.BaseOfCode = t.VirtualAddress
  1187  	oh64.ImageBase = PEBASE
  1188  	oh.ImageBase = PEBASE
  1189  	oh64.SectionAlignment = PESECTALIGN
  1190  	oh.SectionAlignment = PESECTALIGN
  1191  	oh64.FileAlignment = PEFILEALIGN
  1192  	oh.FileAlignment = PEFILEALIGN
  1193  	oh64.MajorOperatingSystemVersion = 4
  1194  	oh.MajorOperatingSystemVersion = 4
  1195  	oh64.MinorOperatingSystemVersion = 0
  1196  	oh.MinorOperatingSystemVersion = 0
  1197  	oh64.MajorImageVersion = 1
  1198  	oh.MajorImageVersion = 1
  1199  	oh64.MinorImageVersion = 0
  1200  	oh.MinorImageVersion = 0
  1201  	oh64.MajorSubsystemVersion = 4
  1202  	oh.MajorSubsystemVersion = 4
  1203  	oh64.MinorSubsystemVersion = 0
  1204  	oh.MinorSubsystemVersion = 0
  1205  	oh64.SizeOfImage = uint32(nextsectoff)
  1206  	oh.SizeOfImage = uint32(nextsectoff)
  1207  	oh64.SizeOfHeaders = uint32(PEFILEHEADR)
  1208  	oh.SizeOfHeaders = uint32(PEFILEHEADR)
  1209  	if headstring == "windowsgui" {
  1210  		oh64.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
  1211  		oh.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI
  1212  	} else {
  1213  		oh64.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
  1214  		oh.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
  1215  	}
  1216  
  1217  	// Disable stack growth as we don't want Windows to
  1218  	// fiddle with the thread stack limits, which we set
  1219  	// ourselves to circumvent the stack checks in the
  1220  	// Windows exception dispatcher.
  1221  	// Commit size must be strictly less than reserve
  1222  	// size otherwise reserve will be rounded up to a
  1223  	// larger size, as verified with VMMap.
  1224  
  1225  	// Go code would be OK with 64k stacks, but we need larger stacks for cgo.
  1226  	// That default stack reserve size affects only the main thread,
  1227  	// for other threads we specify stack size in runtime explicitly
  1228  	// (runtime knows whether cgo is enabled or not).
  1229  	// If you change stack reserve sizes here,
  1230  	// change STACKSIZE in runtime/cgo/gcc_windows_{386,amd64}.c as well.
  1231  	if !iscgo {
  1232  		oh64.SizeOfStackReserve = 0x00010000
  1233  		oh.SizeOfStackReserve = 0x00010000
  1234  		oh64.SizeOfStackCommit = 0x0000ffff
  1235  		oh.SizeOfStackCommit = 0x0000ffff
  1236  	} else {
  1237  		oh64.SizeOfStackReserve = 0x00200000
  1238  		oh.SizeOfStackReserve = 0x00100000
  1239  
  1240  		// account for 2 guard pages
  1241  		oh64.SizeOfStackCommit = 0x00200000 - 0x2000
  1242  
  1243  		oh.SizeOfStackCommit = 0x00100000 - 0x2000
  1244  	}
  1245  
  1246  	oh64.SizeOfHeapReserve = 0x00100000
  1247  	oh.SizeOfHeapReserve = 0x00100000
  1248  	oh64.SizeOfHeapCommit = 0x00001000
  1249  	oh.SizeOfHeapCommit = 0x00001000
  1250  	oh64.NumberOfRvaAndSizes = 16
  1251  	oh.NumberOfRvaAndSizes = 16
  1252  
  1253  	pewrite()
  1254  }