github.com/karrick/go@v0.0.0-20170817181416-d5b0ec858b37/src/cmd/link/internal/ld/pe.go (about)

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