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