Source file src/cmd/link/internal/ld/pe.go

     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  // PE (Portable Executable) file writing
     6  // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
     7  
     8  package ld
     9  
    10  import (
    11  	"bytes"
    12  	"cmd/internal/objabi"
    13  	"cmd/internal/sys"
    14  	"cmd/link/internal/loader"
    15  	"cmd/link/internal/sym"
    16  	"debug/pe"
    17  	"encoding/binary"
    18  	"fmt"
    19  	"internal/buildcfg"
    20  	"math"
    21  	"os"
    22  	"path/filepath"
    23  	"slices"
    24  	"sort"
    25  	"strconv"
    26  	"strings"
    27  )
    28  
    29  type IMAGE_IMPORT_DESCRIPTOR struct {
    30  	OriginalFirstThunk uint32
    31  	TimeDateStamp      uint32
    32  	ForwarderChain     uint32
    33  	Name               uint32
    34  	FirstThunk         uint32
    35  }
    36  
    37  type IMAGE_EXPORT_DIRECTORY struct {
    38  	Characteristics       uint32
    39  	TimeDateStamp         uint32
    40  	MajorVersion          uint16
    41  	MinorVersion          uint16
    42  	Name                  uint32
    43  	Base                  uint32
    44  	NumberOfFunctions     uint32
    45  	NumberOfNames         uint32
    46  	AddressOfFunctions    uint32
    47  	AddressOfNames        uint32
    48  	AddressOfNameOrdinals uint32
    49  }
    50  
    51  var (
    52  	// PEBASE is the base address for the executable.
    53  	// It is small for 32-bit and large for 64-bit.
    54  	PEBASE int64
    55  
    56  	// SectionAlignment must be greater than or equal to FileAlignment.
    57  	// The default is the page size for the architecture.
    58  	PESECTALIGN int64 = 0x1000
    59  
    60  	// FileAlignment should be a power of 2 between 512 and 64 K, inclusive.
    61  	// The default is 512. If the SectionAlignment is less than
    62  	// the architecture's page size, then FileAlignment must match SectionAlignment.
    63  	PEFILEALIGN int64 = 2 << 8
    64  )
    65  
    66  const (
    67  	IMAGE_SCN_CNT_CODE               = 0x00000020
    68  	IMAGE_SCN_CNT_INITIALIZED_DATA   = 0x00000040
    69  	IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
    70  	IMAGE_SCN_LNK_OTHER              = 0x00000100
    71  	IMAGE_SCN_LNK_INFO               = 0x00000200
    72  	IMAGE_SCN_LNK_REMOVE             = 0x00000800
    73  	IMAGE_SCN_LNK_COMDAT             = 0x00001000
    74  	IMAGE_SCN_GPREL                  = 0x00008000
    75  	IMAGE_SCN_MEM_PURGEABLE          = 0x00020000
    76  	IMAGE_SCN_MEM_16BIT              = 0x00020000
    77  	IMAGE_SCN_MEM_LOCKED             = 0x00040000
    78  	IMAGE_SCN_MEM_PRELOAD            = 0x00080000
    79  	IMAGE_SCN_ALIGN_1BYTES           = 0x00100000
    80  	IMAGE_SCN_ALIGN_2BYTES           = 0x00200000
    81  	IMAGE_SCN_ALIGN_4BYTES           = 0x00300000
    82  	IMAGE_SCN_ALIGN_8BYTES           = 0x00400000
    83  	IMAGE_SCN_ALIGN_16BYTES          = 0x00500000
    84  	IMAGE_SCN_ALIGN_32BYTES          = 0x00600000
    85  	IMAGE_SCN_ALIGN_64BYTES          = 0x00700000
    86  	IMAGE_SCN_ALIGN_128BYTES         = 0x00800000
    87  	IMAGE_SCN_ALIGN_256BYTES         = 0x00900000
    88  	IMAGE_SCN_ALIGN_512BYTES         = 0x00A00000
    89  	IMAGE_SCN_ALIGN_1024BYTES        = 0x00B00000
    90  	IMAGE_SCN_ALIGN_2048BYTES        = 0x00C00000
    91  	IMAGE_SCN_ALIGN_4096BYTES        = 0x00D00000
    92  	IMAGE_SCN_ALIGN_8192BYTES        = 0x00E00000
    93  	IMAGE_SCN_LNK_NRELOC_OVFL        = 0x01000000
    94  	IMAGE_SCN_MEM_DISCARDABLE        = 0x02000000
    95  	IMAGE_SCN_MEM_NOT_CACHED         = 0x04000000
    96  	IMAGE_SCN_MEM_NOT_PAGED          = 0x08000000
    97  	IMAGE_SCN_MEM_SHARED             = 0x10000000
    98  	IMAGE_SCN_MEM_EXECUTE            = 0x20000000
    99  	IMAGE_SCN_MEM_READ               = 0x40000000
   100  	IMAGE_SCN_MEM_WRITE              = 0x80000000
   101  )
   102  
   103  // See https://docs.microsoft.com/en-us/windows/win32/debug/pe-format.
   104  // TODO(crawshaw): add these constants to debug/pe.
   105  const (
   106  	IMAGE_SYM_TYPE_NULL      = 0
   107  	IMAGE_SYM_TYPE_STRUCT    = 8
   108  	IMAGE_SYM_DTYPE_FUNCTION = 2
   109  	IMAGE_SYM_DTYPE_ARRAY    = 3
   110  	IMAGE_SYM_CLASS_EXTERNAL = 2
   111  	IMAGE_SYM_CLASS_STATIC   = 3
   112  
   113  	IMAGE_REL_I386_DIR32   = 0x0006
   114  	IMAGE_REL_I386_DIR32NB = 0x0007
   115  	IMAGE_REL_I386_SECREL  = 0x000B
   116  	IMAGE_REL_I386_REL32   = 0x0014
   117  
   118  	IMAGE_REL_AMD64_ADDR64   = 0x0001
   119  	IMAGE_REL_AMD64_ADDR32   = 0x0002
   120  	IMAGE_REL_AMD64_ADDR32NB = 0x0003
   121  	IMAGE_REL_AMD64_REL32    = 0x0004
   122  	IMAGE_REL_AMD64_SECREL   = 0x000B
   123  
   124  	IMAGE_REL_ARM_ABSOLUTE = 0x0000
   125  	IMAGE_REL_ARM_ADDR32   = 0x0001
   126  	IMAGE_REL_ARM_ADDR32NB = 0x0002
   127  	IMAGE_REL_ARM_BRANCH24 = 0x0003
   128  	IMAGE_REL_ARM_BRANCH11 = 0x0004
   129  	IMAGE_REL_ARM_SECREL   = 0x000F
   130  
   131  	IMAGE_REL_ARM64_ABSOLUTE       = 0x0000
   132  	IMAGE_REL_ARM64_ADDR32         = 0x0001
   133  	IMAGE_REL_ARM64_ADDR32NB       = 0x0002
   134  	IMAGE_REL_ARM64_BRANCH26       = 0x0003
   135  	IMAGE_REL_ARM64_PAGEBASE_REL21 = 0x0004
   136  	IMAGE_REL_ARM64_REL21          = 0x0005
   137  	IMAGE_REL_ARM64_PAGEOFFSET_12A = 0x0006
   138  	IMAGE_REL_ARM64_PAGEOFFSET_12L = 0x0007
   139  	IMAGE_REL_ARM64_SECREL         = 0x0008
   140  	IMAGE_REL_ARM64_SECREL_LOW12A  = 0x0009
   141  	IMAGE_REL_ARM64_SECREL_HIGH12A = 0x000A
   142  	IMAGE_REL_ARM64_SECREL_LOW12L  = 0x000B
   143  	IMAGE_REL_ARM64_TOKEN          = 0x000C
   144  	IMAGE_REL_ARM64_SECTION        = 0x000D
   145  	IMAGE_REL_ARM64_ADDR64         = 0x000E
   146  	IMAGE_REL_ARM64_BRANCH19       = 0x000F
   147  	IMAGE_REL_ARM64_BRANCH14       = 0x0010
   148  	IMAGE_REL_ARM64_REL32          = 0x0011
   149  
   150  	IMAGE_REL_BASED_HIGHLOW = 3
   151  	IMAGE_REL_BASED_DIR64   = 10
   152  )
   153  
   154  // IMAGE_LOAD_CONFIG_DIRECTORY64.GuardFlags and IMAGE_LOAD_CONFIG_DIRECTORY32.GuardFlags
   155  // values. These can be combined together.
   156  const (
   157  	IMAGE_GUARD_CF_INSTRUMENTED                    = 0x00000100 // Module performs control flow integrity checks using system-supplied support
   158  	IMAGE_GUARD_CFW_INSTRUMENTED                   = 0x00000200 // Module performs control flow and write integrity checks
   159  	IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT          = 0x00000400 // Module contains valid control flow target metadata
   160  	IMAGE_GUARD_SECURITY_COOKIE_UNUSED             = 0x00000800 // Module does not make use of the /GS security cookie
   161  	IMAGE_GUARD_PROTECT_DELAYLOAD_IAT              = 0x00001000 // Module supports read only delay load IAT
   162  	IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION   = 0x00002000 // Delayload import table in its own .didat section (with nothing else in it) that can be freely reprotected
   163  	IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT = 0x00004000 // Module contains suppressed export information
   164  	IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION       = 0x00008000 // Module enables suppression of exports
   165  	IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT          = 0x00010000 // Module contains longjmp target information
   166  	IMAGE_GUARD_RF_INSTRUMENTED                    = 0x00020000 // Module contains return flow instrumentation and metadata
   167  	IMAGE_GUARD_RF_ENABLE                          = 0x00040000 // Module requests that the OS enable return flow protection
   168  	IMAGE_GUARD_RF_STRICT                          = 0x00080000 // Module requests that the OS enable return flow protection in strict mode
   169  	IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK        = 0xF0000000 // Stride of Guard CF function table encoded in these bits (additional count of bytes per element)
   170  	IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT       = 28         // Shift to right-justify Guard CF function table stride
   171  )
   172  
   173  type IMAGE_LOAD_CONFIG_CODE_INTEGRITY struct {
   174  	Flags         uint16
   175  	Catalog       uint16
   176  	CatalogOffset uint32
   177  	Reserved      uint32
   178  }
   179  
   180  type IMAGE_LOAD_CONFIG_DIRECTORY32 struct {
   181  	Size                                     uint32
   182  	TimeDateStamp                            uint32
   183  	MajorVersion                             uint16
   184  	MinorVersion                             uint16
   185  	GlobalFlagsClear                         uint32
   186  	GlobalFlagsSet                           uint32
   187  	CriticalSectionDefaultTimeout            uint32
   188  	DeCommitFreeBlockThreshold               uint32
   189  	DeCommitTotalFreeThreshold               uint32
   190  	LockPrefixTable                          uint32
   191  	MaximumAllocationSize                    uint32
   192  	VirtualMemoryThreshold                   uint32
   193  	ProcessHeapFlags                         uint32
   194  	ProcessAffinityMask                      uint32
   195  	CSDVersion                               uint16
   196  	DependentLoadFlags                       uint16
   197  	EditList                                 uint32
   198  	SecurityCookie                           uint32
   199  	SEHandlerTable                           uint32
   200  	SEHandlerCount                           uint32
   201  	GuardCFCheckFunctionPointer              uint32
   202  	GuardCFDispatchFunctionPointer           uint32
   203  	GuardCFFunctionTable                     uint32
   204  	GuardCFFunctionCount                     uint32
   205  	GuardFlags                               uint32
   206  	CodeIntegrity                            IMAGE_LOAD_CONFIG_CODE_INTEGRITY
   207  	GuardAddressTakenIatEntryTable           uint32
   208  	GuardAddressTakenIatEntryCount           uint32
   209  	GuardLongJumpTargetTable                 uint32
   210  	GuardLongJumpTargetCount                 uint32
   211  	DynamicValueRelocTable                   uint32
   212  	CHPEMetadataPointer                      uint32
   213  	GuardRFFailureRoutine                    uint32
   214  	GuardRFFailureRoutineFunctionPointer     uint32
   215  	DynamicValueRelocTableOffset             uint32
   216  	DynamicValueRelocTableSection            uint16
   217  	Reserved2                                uint16
   218  	GuardRFVerifyStackPointerFunctionPointer uint32
   219  	HotPatchTableOffset                      uint32
   220  	Reserved3                                uint32
   221  	EnclaveConfigurationPointer              uint32
   222  	VolatileMetadataPointer                  uint32
   223  	GuardEHContinuationTable                 uint32
   224  	GuardEHContinuationCount                 uint32
   225  	GuardXFGCheckFunctionPointer             uint32
   226  	GuardXFGDispatchFunctionPointer          uint32
   227  	GuardXFGTableDispatchFunctionPointer     uint32
   228  	CastGuardOsDeterminedFailureMode         uint32
   229  	GuardMemcpyFunctionPointer               uint32
   230  }
   231  
   232  type IMAGE_LOAD_CONFIG_DIRECTORY64 struct {
   233  	Size                                     uint32
   234  	TimeDateStamp                            uint32
   235  	MajorVersion                             uint16
   236  	MinorVersion                             uint16
   237  	GlobalFlagsClear                         uint32
   238  	GlobalFlagsSet                           uint32
   239  	CriticalSectionDefaultTimeout            uint32
   240  	DeCommitFreeBlockThreshold               uint64
   241  	DeCommitTotalFreeThreshold               uint64
   242  	LockPrefixTable                          uint64
   243  	MaximumAllocationSize                    uint64
   244  	VirtualMemoryThreshold                   uint64
   245  	ProcessAffinityMask                      uint64
   246  	ProcessHeapFlags                         uint32
   247  	CSDVersion                               uint16
   248  	DependentLoadFlags                       uint16
   249  	EditList                                 uint64
   250  	SecurityCookie                           uint64
   251  	SEHandlerTable                           uint64
   252  	SEHandlerCount                           uint64
   253  	GuardCFCheckFunctionPointer              uint64
   254  	GuardCFDispatchFunctionPointer           uint64
   255  	GuardCFFunctionTable                     uint64
   256  	GuardCFFunctionCount                     uint64
   257  	GuardFlags                               uint32
   258  	CodeIntegrity                            IMAGE_LOAD_CONFIG_CODE_INTEGRITY
   259  	GuardAddressTakenIatEntryTable           uint64
   260  	GuardAddressTakenIatEntryCount           uint64
   261  	GuardLongJumpTargetTable                 uint64
   262  	GuardLongJumpTargetCount                 uint64
   263  	DynamicValueRelocTable                   uint64
   264  	CHPEMetadataPointer                      uint64
   265  	GuardRFFailureRoutine                    uint64
   266  	GuardRFFailureRoutineFunctionPointer     uint64
   267  	DynamicValueRelocTableOffset             uint32
   268  	DynamicValueRelocTableSection            uint16
   269  	Reserved2                                uint16
   270  	GuardRFVerifyStackPointerFunctionPointer uint64
   271  	HotPatchTableOffset                      uint32
   272  	Reserved3                                uint32
   273  	EnclaveConfigurationPointer              uint64
   274  	VolatileMetadataPointer                  uint64
   275  	GuardEHContinuationTable                 uint64
   276  	GuardEHContinuationCount                 uint64
   277  	GuardXFGCheckFunctionPointer             uint64
   278  	GuardXFGDispatchFunctionPointer          uint64
   279  	GuardXFGTableDispatchFunctionPointer     uint64
   280  	CastGuardOsDeterminedFailureMode         uint64
   281  	GuardMemcpyFunctionPointer               uint64
   282  }
   283  
   284  const (
   285  	PeMinimumTargetMajorVersion = 10
   286  	PeMinimumTargetMinorVersion = 0
   287  )
   288  
   289  // DOS stub that prints out
   290  // "This program cannot be run in DOS mode."
   291  // See IMAGE_DOS_HEADER in the Windows SDK for the format of the header used here.
   292  var dosstub = []uint8{
   293  	0x4d,
   294  	0x5a,
   295  	0x90,
   296  	0x00,
   297  	0x03,
   298  	0x00,
   299  	0x00,
   300  	0x00,
   301  	0x04,
   302  	0x00,
   303  	0x00,
   304  	0x00,
   305  	0xff,
   306  	0xff,
   307  	0x00,
   308  	0x00,
   309  	0x8b,
   310  	0x00,
   311  	0x00,
   312  	0x00,
   313  	0x00,
   314  	0x00,
   315  	0x00,
   316  	0x00,
   317  	0x40,
   318  	0x00,
   319  	0x00,
   320  	0x00,
   321  	0x00,
   322  	0x00,
   323  	0x00,
   324  	0x00,
   325  	0x00,
   326  	0x00,
   327  	0x00,
   328  	0x00,
   329  	0x00,
   330  	0x00,
   331  	0x00,
   332  	0x00,
   333  	0x00,
   334  	0x00,
   335  	0x00,
   336  	0x00,
   337  	0x00,
   338  	0x00,
   339  	0x00,
   340  	0x00,
   341  	0x00,
   342  	0x00,
   343  	0x00,
   344  	0x00,
   345  	0x00,
   346  	0x00,
   347  	0x00,
   348  	0x00,
   349  	0x00,
   350  	0x00,
   351  	0x00,
   352  	0x00,
   353  	0x80,
   354  	0x00,
   355  	0x00,
   356  	0x00,
   357  	0x0e,
   358  	0x1f,
   359  	0xba,
   360  	0x0e,
   361  	0x00,
   362  	0xb4,
   363  	0x09,
   364  	0xcd,
   365  	0x21,
   366  	0xb8,
   367  	0x01,
   368  	0x4c,
   369  	0xcd,
   370  	0x21,
   371  	0x54,
   372  	0x68,
   373  	0x69,
   374  	0x73,
   375  	0x20,
   376  	0x70,
   377  	0x72,
   378  	0x6f,
   379  	0x67,
   380  	0x72,
   381  	0x61,
   382  	0x6d,
   383  	0x20,
   384  	0x63,
   385  	0x61,
   386  	0x6e,
   387  	0x6e,
   388  	0x6f,
   389  	0x74,
   390  	0x20,
   391  	0x62,
   392  	0x65,
   393  	0x20,
   394  	0x72,
   395  	0x75,
   396  	0x6e,
   397  	0x20,
   398  	0x69,
   399  	0x6e,
   400  	0x20,
   401  	0x44,
   402  	0x4f,
   403  	0x53,
   404  	0x20,
   405  	0x6d,
   406  	0x6f,
   407  	0x64,
   408  	0x65,
   409  	0x2e,
   410  	0x0d,
   411  	0x0d,
   412  	0x0a,
   413  	0x24,
   414  	0x00,
   415  	0x00,
   416  	0x00,
   417  	0x00,
   418  	0x00,
   419  	0x00,
   420  	0x00,
   421  }
   422  
   423  type Imp struct {
   424  	s       loader.Sym
   425  	off     uint64
   426  	next    *Imp
   427  	argsize int
   428  }
   429  
   430  type Dll struct {
   431  	name     string
   432  	nameoff  uint64
   433  	thunkoff uint64
   434  	ms       *Imp
   435  	next     *Dll
   436  }
   437  
   438  var (
   439  	rsrcsyms    []loader.Sym
   440  	PESECTHEADR int32
   441  	PEFILEHEADR int32
   442  	pe64        bool
   443  	dr          *Dll
   444  
   445  	dexport []loader.Sym
   446  )
   447  
   448  // peStringTable is a COFF string table.
   449  type peStringTable struct {
   450  	strings    []string
   451  	stringsLen int
   452  }
   453  
   454  // size returns size of string table t.
   455  func (t *peStringTable) size() int {
   456  	// string table starts with 4-byte length at the beginning
   457  	return t.stringsLen + 4
   458  }
   459  
   460  // add adds string str to string table t.
   461  func (t *peStringTable) add(str string) int {
   462  	off := t.size()
   463  	t.strings = append(t.strings, str)
   464  	t.stringsLen += len(str) + 1 // each string will have 0 appended to it
   465  	return off
   466  }
   467  
   468  // write writes string table t into the output file.
   469  func (t *peStringTable) write(out *OutBuf) {
   470  	out.Write32(uint32(t.size()))
   471  	for _, s := range t.strings {
   472  		out.WriteString(s)
   473  		out.Write8(0)
   474  	}
   475  }
   476  
   477  // peSection represents section from COFF section table.
   478  type peSection struct {
   479  	name                 string
   480  	shortName            string
   481  	index                int // one-based index into the Section Table
   482  	virtualSize          uint32
   483  	virtualAddress       uint32
   484  	sizeOfRawData        uint32
   485  	pointerToRawData     uint32
   486  	pointerToRelocations uint32
   487  	numberOfRelocations  uint16
   488  	characteristics      uint32
   489  }
   490  
   491  // checkOffset verifies COFF section sect offset in the file.
   492  func (sect *peSection) checkOffset(off int64) {
   493  	if off != int64(sect.pointerToRawData) {
   494  		Errorf("%s.PointerToRawData = %#x, want %#x", sect.name, uint64(int64(sect.pointerToRawData)), uint64(off))
   495  		errorexit()
   496  	}
   497  }
   498  
   499  // checkSegment verifies COFF section sect matches address
   500  // and file offset provided in segment seg.
   501  func (sect *peSection) checkSegment(seg *sym.Segment) {
   502  	if seg.Vaddr-uint64(PEBASE) != uint64(sect.virtualAddress) {
   503  		Errorf("%s.VirtualAddress = %#x, want %#x", sect.name, uint64(int64(sect.virtualAddress)), uint64(int64(seg.Vaddr-uint64(PEBASE))))
   504  		errorexit()
   505  	}
   506  	if seg.Fileoff != uint64(sect.pointerToRawData) {
   507  		Errorf("%s.PointerToRawData = %#x, want %#x", sect.name, uint64(int64(sect.pointerToRawData)), uint64(int64(seg.Fileoff)))
   508  		errorexit()
   509  	}
   510  }
   511  
   512  // pad adds zeros to the section sect. It writes as many bytes
   513  // as necessary to make section sect.SizeOfRawData bytes long.
   514  // It assumes that n bytes are already written to the file.
   515  func (sect *peSection) pad(out *OutBuf, n uint32) {
   516  	out.WriteStringN("", int(sect.sizeOfRawData-n))
   517  }
   518  
   519  // write writes COFF section sect into the output file.
   520  func (sect *peSection) write(out *OutBuf, linkmode LinkMode) error {
   521  	h := pe.SectionHeader32{
   522  		VirtualSize:          sect.virtualSize,
   523  		SizeOfRawData:        sect.sizeOfRawData,
   524  		PointerToRawData:     sect.pointerToRawData,
   525  		PointerToRelocations: sect.pointerToRelocations,
   526  		NumberOfRelocations:  sect.numberOfRelocations,
   527  		Characteristics:      sect.characteristics,
   528  	}
   529  	if linkmode != LinkExternal {
   530  		h.VirtualAddress = sect.virtualAddress
   531  	}
   532  	copy(h.Name[:], sect.shortName)
   533  	return binary.Write(out, binary.LittleEndian, h)
   534  }
   535  
   536  // emitRelocations emits the relocation entries for the sect.
   537  // The actual relocations are emitted by relocfn.
   538  // This updates the corresponding PE section table entry
   539  // with the relocation offset and count.
   540  func (sect *peSection) emitRelocations(out *OutBuf, relocfn func() int) {
   541  	sect.pointerToRelocations = uint32(out.Offset())
   542  	// first entry: extended relocs
   543  	out.Write32(0) // placeholder for number of relocation + 1
   544  	out.Write32(0)
   545  	out.Write16(0)
   546  
   547  	n := relocfn() + 1
   548  
   549  	cpos := out.Offset()
   550  	out.SeekSet(int64(sect.pointerToRelocations))
   551  	out.Write32(uint32(n))
   552  	out.SeekSet(cpos)
   553  	if n > 0x10000 {
   554  		n = 0x10000
   555  		sect.characteristics |= IMAGE_SCN_LNK_NRELOC_OVFL
   556  	} else {
   557  		sect.pointerToRelocations += 10 // skip the extend reloc entry
   558  	}
   559  	sect.numberOfRelocations = uint16(n - 1)
   560  }
   561  
   562  // peFile is used to build COFF file.
   563  type peFile struct {
   564  	sections       []*peSection
   565  	stringTable    peStringTable
   566  	textSect       *peSection
   567  	rdataSect      *peSection
   568  	dataSect       *peSection
   569  	bssSect        *peSection
   570  	ctorsSect      *peSection
   571  	pdataSect      *peSection
   572  	xdataSect      *peSection
   573  	nextSectOffset uint32
   574  	nextFileOffset uint32
   575  	symtabOffset   int64 // offset to the start of symbol table
   576  	symbolCount    int   // number of symbol table records written
   577  	dataDirectory  [16]pe.DataDirectory
   578  }
   579  
   580  // addSection adds section to the COFF file f.
   581  func (f *peFile) addSection(name string, sectsize int, filesize int) *peSection {
   582  	sect := &peSection{
   583  		name:             name,
   584  		shortName:        name,
   585  		index:            len(f.sections) + 1,
   586  		virtualAddress:   f.nextSectOffset,
   587  		pointerToRawData: f.nextFileOffset,
   588  	}
   589  	f.nextSectOffset = uint32(Rnd(int64(f.nextSectOffset)+int64(sectsize), PESECTALIGN))
   590  	if filesize > 0 {
   591  		sect.virtualSize = uint32(sectsize)
   592  		sect.sizeOfRawData = uint32(Rnd(int64(filesize), PEFILEALIGN))
   593  		f.nextFileOffset += sect.sizeOfRawData
   594  	} else {
   595  		sect.sizeOfRawData = uint32(sectsize)
   596  	}
   597  	f.sections = append(f.sections, sect)
   598  	return sect
   599  }
   600  
   601  // addDWARFSection adds DWARF section to the COFF file f.
   602  // This function is similar to addSection, but DWARF section names are
   603  // longer than 8 characters, so they need to be stored in the string table.
   604  func (f *peFile) addDWARFSection(name string, size int) *peSection {
   605  	if size == 0 {
   606  		Exitf("DWARF section %q is empty", name)
   607  	}
   608  	// DWARF section names are longer than 8 characters.
   609  	// PE format requires such names to be stored in string table,
   610  	// and section names replaced with slash (/) followed by
   611  	// correspondent string table index.
   612  	// see http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx
   613  	// for details
   614  	off := f.stringTable.add(name)
   615  	h := f.addSection(name, size, size)
   616  	h.shortName = fmt.Sprintf("/%d", off)
   617  	h.characteristics = IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_CNT_INITIALIZED_DATA
   618  	return h
   619  }
   620  
   621  // addDWARF adds DWARF information to the COFF file f.
   622  func (f *peFile) addDWARF() {
   623  	if *FlagW { // disable dwarf
   624  		return
   625  	}
   626  	for _, sect := range Segdwarf.Sections {
   627  		h := f.addDWARFSection(sect.Name, int(sect.Length))
   628  		fileoff := sect.Vaddr - Segdwarf.Vaddr + Segdwarf.Fileoff
   629  		if uint64(h.pointerToRawData) != fileoff {
   630  			Exitf("%s.PointerToRawData = %#x, want %#x", sect.Name, h.pointerToRawData, fileoff)
   631  		}
   632  	}
   633  }
   634  
   635  // addSEH adds SEH information to the COFF file f.
   636  func (f *peFile) addSEH(ctxt *Link) {
   637  	// .pdata section can exist without the .xdata section.
   638  	// .xdata section depends on the .pdata section.
   639  	if Segpdata.Length == 0 {
   640  		return
   641  	}
   642  	d := pefile.addSection(".pdata", int(Segpdata.Length), int(Segpdata.Length))
   643  	d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
   644  	if ctxt.LinkMode == LinkExternal {
   645  		// Some gcc versions don't honor the default alignment for the .pdata section.
   646  		d.characteristics |= IMAGE_SCN_ALIGN_4BYTES
   647  	}
   648  	pefile.pdataSect = d
   649  	d.checkSegment(&Segpdata)
   650  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = d.virtualAddress
   651  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = d.virtualSize
   652  
   653  	if Segxdata.Length > 0 {
   654  		d = pefile.addSection(".xdata", int(Segxdata.Length), int(Segxdata.Length))
   655  		d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
   656  		if ctxt.LinkMode == LinkExternal {
   657  			// Some gcc versions don't honor the default alignment for the .xdata section.
   658  			d.characteristics |= IMAGE_SCN_ALIGN_4BYTES
   659  		}
   660  		pefile.xdataSect = d
   661  		d.checkSegment(&Segxdata)
   662  	}
   663  }
   664  
   665  // addInitArray adds .ctors COFF section to the file f.
   666  func (f *peFile) addInitArray(ctxt *Link) *peSection {
   667  	// The size below was determined by the specification for array relocations,
   668  	// and by observing what GCC writes here. If the initarray section grows to
   669  	// contain more than one constructor entry, the size will need to be 8 * constructor_count.
   670  	// However, the entire Go runtime is initialized from just one function, so it is unlikely
   671  	// that this will need to grow in the future.
   672  	var size int
   673  	var alignment uint32
   674  	if pe64 {
   675  		size = 8
   676  		alignment = IMAGE_SCN_ALIGN_8BYTES
   677  	} else {
   678  		size = 4
   679  		alignment = IMAGE_SCN_ALIGN_4BYTES
   680  	}
   681  	sect := f.addSection(".ctors", size, size)
   682  	sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | alignment
   683  	sect.sizeOfRawData = uint32(size)
   684  	ctxt.Out.SeekSet(int64(sect.pointerToRawData))
   685  	sect.checkOffset(ctxt.Out.Offset())
   686  
   687  	init_entry := ctxt.loader.Lookup(*flagEntrySymbol, 0)
   688  	addr := uint64(ctxt.loader.SymValue(init_entry)) - ctxt.loader.SymSect(init_entry).Vaddr
   689  	if pe64 {
   690  		ctxt.Out.Write64(addr)
   691  	} else {
   692  		ctxt.Out.Write32(uint32(addr))
   693  	}
   694  	return sect
   695  }
   696  
   697  // emitRelocations emits relocation entries for go.o in external linking.
   698  func (f *peFile) emitRelocations(ctxt *Link) {
   699  	for ctxt.Out.Offset()&7 != 0 {
   700  		ctxt.Out.Write8(0)
   701  	}
   702  
   703  	ldr := ctxt.loader
   704  
   705  	// relocsect relocates symbols from first in section sect, and returns
   706  	// the total number of relocations emitted.
   707  	relocsect := func(sect *sym.Section, syms []loader.Sym, base uint64) int {
   708  		// If main section has no bits, nothing to relocate.
   709  		if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
   710  			return 0
   711  		}
   712  		sect.Reloff = uint64(ctxt.Out.Offset())
   713  		for i, s := range syms {
   714  			if !ldr.AttrReachable(s) {
   715  				continue
   716  			}
   717  			if uint64(ldr.SymValue(s)) >= sect.Vaddr {
   718  				syms = syms[i:]
   719  				break
   720  			}
   721  		}
   722  		eaddr := int64(sect.Vaddr + sect.Length)
   723  		for _, s := range syms {
   724  			if !ldr.AttrReachable(s) {
   725  				continue
   726  			}
   727  			if ldr.SymValue(s) >= eaddr {
   728  				break
   729  			}
   730  			// Compute external relocations on the go, and pass to PEreloc1
   731  			// to stream out.
   732  			relocs := ldr.Relocs(s)
   733  			for ri := 0; ri < relocs.Count(); ri++ {
   734  				r := relocs.At(ri)
   735  				rr, ok := extreloc(ctxt, ldr, s, r)
   736  				if !ok {
   737  					continue
   738  				}
   739  				if rr.Xsym == 0 {
   740  					ctxt.Errorf(s, "missing xsym in relocation")
   741  					continue
   742  				}
   743  				if ldr.SymDynid(rr.Xsym) < 0 {
   744  					ctxt.Errorf(s, "reloc %d to non-coff symbol %s (outer=%s) %d", r.Type(), ldr.SymName(r.Sym()), ldr.SymName(rr.Xsym), ldr.SymType(r.Sym()))
   745  				}
   746  				if !thearch.PEreloc1(ctxt.Arch, ctxt.Out, ldr, s, rr, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-base)) {
   747  					ctxt.Errorf(s, "unsupported obj reloc %v/%d to %s", r.Type(), r.Siz(), ldr.SymName(r.Sym()))
   748  				}
   749  			}
   750  		}
   751  		sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
   752  		const relocLen = 4 + 4 + 2
   753  		return int(sect.Rellen / relocLen)
   754  	}
   755  
   756  	type relsect struct {
   757  		peSect *peSection
   758  		seg    *sym.Segment
   759  		syms   []loader.Sym
   760  	}
   761  	sects := []relsect{
   762  		{f.textSect, &Segtext, ctxt.Textp},
   763  		{f.rdataSect, &Segrodata, ctxt.datap},
   764  		{f.dataSect, &Segdata, ctxt.datap},
   765  	}
   766  	if len(sehp.pdata) != 0 {
   767  		sects = append(sects, relsect{f.pdataSect, &Segpdata, sehp.pdata})
   768  	}
   769  	if len(sehp.xdata) != 0 {
   770  		sects = append(sects, relsect{f.xdataSect, &Segxdata, sehp.xdata})
   771  	}
   772  	for _, s := range sects {
   773  		s.peSect.emitRelocations(ctxt.Out, func() int {
   774  			var n int
   775  			for _, sect := range s.seg.Sections {
   776  				n += relocsect(sect, s.syms, s.seg.Vaddr)
   777  			}
   778  			return n
   779  		})
   780  	}
   781  
   782  dwarfLoop:
   783  	for i := 0; i < len(Segdwarf.Sections); i++ {
   784  		sect := Segdwarf.Sections[i]
   785  		si := dwarfp[i]
   786  		if si.secSym() != sect.Sym ||
   787  			ldr.SymSect(si.secSym()) != sect {
   788  			panic("inconsistency between dwarfp and Segdwarf")
   789  		}
   790  		for _, pesect := range f.sections {
   791  			if sect.Name == pesect.name {
   792  				pesect.emitRelocations(ctxt.Out, func() int {
   793  					return relocsect(sect, si.syms, sect.Vaddr)
   794  				})
   795  				continue dwarfLoop
   796  			}
   797  		}
   798  		Errorf("emitRelocations: could not find %q section", sect.Name)
   799  	}
   800  
   801  	if f.ctorsSect == nil {
   802  		return
   803  	}
   804  
   805  	f.ctorsSect.emitRelocations(ctxt.Out, func() int {
   806  		dottext := ldr.Lookup(".text", 0)
   807  		ctxt.Out.Write32(0)
   808  		ctxt.Out.Write32(uint32(ldr.SymDynid(dottext)))
   809  		switch buildcfg.GOARCH {
   810  		default:
   811  			ctxt.Errorf(dottext, "unknown architecture for PE: %q\n", buildcfg.GOARCH)
   812  		case "386":
   813  			ctxt.Out.Write16(IMAGE_REL_I386_DIR32)
   814  		case "amd64":
   815  			ctxt.Out.Write16(IMAGE_REL_AMD64_ADDR64)
   816  		case "arm":
   817  			ctxt.Out.Write16(IMAGE_REL_ARM_ADDR32)
   818  		case "arm64":
   819  			ctxt.Out.Write16(IMAGE_REL_ARM64_ADDR64)
   820  		}
   821  		return 1
   822  	})
   823  }
   824  
   825  // writeSymbol appends symbol s to file f symbol table.
   826  // It also sets s.Dynid to written symbol number.
   827  func (f *peFile) writeSymbol(out *OutBuf, ldr *loader.Loader, s loader.Sym, name string, value int64, sectidx int, typ uint16, class uint8) {
   828  	if len(name) > 8 {
   829  		out.Write32(0)
   830  		out.Write32(uint32(f.stringTable.add(name)))
   831  	} else {
   832  		out.WriteStringN(name, 8)
   833  	}
   834  	out.Write32(uint32(value))
   835  	out.Write16(uint16(sectidx))
   836  	out.Write16(typ)
   837  	out.Write8(class)
   838  	out.Write8(0) // no aux entries
   839  
   840  	ldr.SetSymDynid(s, int32(f.symbolCount))
   841  
   842  	f.symbolCount++
   843  }
   844  
   845  // mapToPESection searches peFile f for s symbol's location.
   846  // It returns PE section index, and offset within that section.
   847  func (f *peFile) mapToPESection(ldr *loader.Loader, s loader.Sym, linkmode LinkMode) (pesectidx int, offset int64, err error) {
   848  	sect := ldr.SymSect(s)
   849  	if sect == nil {
   850  		return 0, 0, fmt.Errorf("could not map %s symbol with no section", ldr.SymName(s))
   851  	}
   852  	if sect.Seg == &Segtext {
   853  		return f.textSect.index, int64(uint64(ldr.SymValue(s)) - Segtext.Vaddr), nil
   854  	}
   855  	if sect.Seg == &Segrodata {
   856  		return f.rdataSect.index, int64(uint64(ldr.SymValue(s)) - Segrodata.Vaddr), nil
   857  	}
   858  	if sect.Seg != &Segdata {
   859  		return 0, 0, fmt.Errorf("could not map %s symbol with non .text or .rdata or .data section", ldr.SymName(s))
   860  	}
   861  	v := uint64(ldr.SymValue(s)) - Segdata.Vaddr
   862  	if linkmode != LinkExternal {
   863  		return f.dataSect.index, int64(v), nil
   864  	}
   865  	if ldr.SymType(s).IsDATA() {
   866  		return f.dataSect.index, int64(v), nil
   867  	}
   868  	// Note: although address of runtime.edata (type sym.SDATA) is at the start of .bss section
   869  	// it still belongs to the .data section, not the .bss section.
   870  	if v < Segdata.Filelen {
   871  		return f.dataSect.index, int64(v), nil
   872  	}
   873  	return f.bssSect.index, int64(v - Segdata.Filelen), nil
   874  }
   875  
   876  var isLabel = make(map[loader.Sym]bool)
   877  
   878  func AddPELabelSym(ldr *loader.Loader, s loader.Sym) {
   879  	isLabel[s] = true
   880  }
   881  
   882  // writeSymbols writes all COFF symbol table records.
   883  func (f *peFile) writeSymbols(ctxt *Link) {
   884  	ldr := ctxt.loader
   885  	addsym := func(s loader.Sym) {
   886  		t := ldr.SymType(s)
   887  		if ldr.SymSect(s) == nil && t != sym.SDYNIMPORT && t != sym.SHOSTOBJ && t != sym.SUNDEFEXT {
   888  			return
   889  		}
   890  
   891  		name := ldr.SymName(s)
   892  
   893  		// Only windows/386 requires underscore prefix on external symbols.
   894  		if ctxt.Is386() && ctxt.IsExternal() &&
   895  			(t == sym.SHOSTOBJ || t == sym.SUNDEFEXT || ldr.AttrCgoExport(s) ||
   896  				// TODO(cuonglm): remove this hack
   897  				//
   898  				// Previously, windows/386 requires underscore prefix on external symbols,
   899  				// but that's only applied for SHOSTOBJ/SUNDEFEXT or cgo export symbols.
   900  				// "go.buildid" is STEXT, "type.*" is STYPE, thus they are not prefixed
   901  				// with underscore.
   902  				//
   903  				// In external linking mode, the external linker can't resolve them as
   904  				// external symbols. But we are lucky that they have "." in their name,
   905  				// so the external linker see them as Forwarder RVA exports. See:
   906  				//
   907  				//  - https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#export-address-table
   908  				//  - https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=ld/pe-dll.c;h=e7b82ba6ffadf74dc1b9ee71dc13d48336941e51;hb=HEAD#l972
   909  				//
   910  				// CL 317917 changes "." to ":" in symbols name, so these symbols can not be
   911  				// found by external linker anymore. So a hacky way is adding the
   912  				// underscore prefix for these 2 symbols. I don't have enough knowledge to
   913  				// verify whether adding the underscore for all STEXT/STYPE symbols are
   914  				// fine, even if it could be, that would be done in future CL.
   915  				name == "go:buildid" || name == "type:*") {
   916  			name = "_" + name
   917  		}
   918  
   919  		name = mangleABIName(ctxt, ldr, s, name)
   920  
   921  		var peSymType uint16 = IMAGE_SYM_TYPE_NULL
   922  		switch {
   923  		case t.IsText(), t == sym.SDYNIMPORT, t == sym.SHOSTOBJ, t == sym.SUNDEFEXT:
   924  			// Microsoft's PE documentation is contradictory. It says that the symbol's complex type
   925  			// is stored in the pesym.Type most significant byte, but MSVC, LLVM, and mingw store it
   926  			// in the 4 high bits of the less significant byte. Also, the PE documentation says that
   927  			// the basic type for a function should be IMAGE_SYM_TYPE_VOID,
   928  			// but the reality is that it uses IMAGE_SYM_TYPE_NULL instead.
   929  			peSymType = IMAGE_SYM_DTYPE_FUNCTION<<4 + IMAGE_SYM_TYPE_NULL
   930  		}
   931  		sect, value, err := f.mapToPESection(ldr, s, ctxt.LinkMode)
   932  		if err != nil {
   933  			switch t {
   934  			case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
   935  			default:
   936  				ctxt.Errorf(s, "addpesym: %v", err)
   937  			}
   938  		}
   939  		class := IMAGE_SYM_CLASS_EXTERNAL
   940  		if ldr.IsFileLocal(s) || ldr.AttrVisibilityHidden(s) || ldr.AttrLocal(s) ||
   941  			(ldr.IsContentHashed(s) && ldr.SymType(s).IsText()) {
   942  			class = IMAGE_SYM_CLASS_STATIC
   943  		}
   944  		f.writeSymbol(ctxt.Out, ldr, s, name, value, sect, peSymType, uint8(class))
   945  	}
   946  
   947  	if ctxt.LinkMode == LinkExternal {
   948  		// Include section symbols as external, because
   949  		// .ctors and .debug_* section relocations refer to it.
   950  		for _, pesect := range f.sections {
   951  			s := ldr.LookupOrCreateSym(pesect.name, 0)
   952  			f.writeSymbol(ctxt.Out, ldr, s, pesect.name, 0, pesect.index, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_STATIC)
   953  		}
   954  	}
   955  
   956  	// Add special runtime.text and runtime.etext symbols.
   957  	s := ldr.Lookup("runtime.text", 0)
   958  	if ldr.SymType(s).IsText() {
   959  		addsym(s)
   960  	}
   961  	s = ldr.Lookup("runtime.etext", 0)
   962  	if ldr.SymType(s).IsText() {
   963  		addsym(s)
   964  	}
   965  
   966  	// Add text symbols.
   967  	for _, s := range ctxt.Textp {
   968  		addsym(s)
   969  	}
   970  
   971  	shouldBeInSymbolTable := func(s loader.Sym) bool {
   972  		if ldr.AttrNotInSymbolTable(s) {
   973  			return false
   974  		}
   975  		name := ldr.SymName(s) // TODO: try not to read the name
   976  		if name == "" || name[0] == '.' {
   977  			return false
   978  		}
   979  		return true
   980  	}
   981  
   982  	// Add data symbols and external references.
   983  	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
   984  		if !ldr.AttrReachable(s) {
   985  			continue
   986  		}
   987  		t := ldr.SymType(s)
   988  		if t >= sym.SELFRXSECT && t < sym.SFirstUnallocated { // data sections handled in dodata
   989  			if t == sym.STLSBSS {
   990  				continue
   991  			}
   992  			if !shouldBeInSymbolTable(s) {
   993  				continue
   994  			}
   995  			addsym(s)
   996  		}
   997  
   998  		switch t {
   999  		case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
  1000  			addsym(s)
  1001  		default:
  1002  			if len(isLabel) > 0 && isLabel[s] {
  1003  				addsym(s)
  1004  			}
  1005  		}
  1006  	}
  1007  }
  1008  
  1009  // writeSymbolTableAndStringTable writes out symbol and string tables for peFile f.
  1010  func (f *peFile) writeSymbolTableAndStringTable(ctxt *Link) {
  1011  	f.symtabOffset = ctxt.Out.Offset()
  1012  
  1013  	// write COFF symbol table
  1014  	if !*FlagS || ctxt.LinkMode == LinkExternal {
  1015  		f.writeSymbols(ctxt)
  1016  	}
  1017  
  1018  	// update COFF file header and section table
  1019  	size := f.stringTable.size() + 18*f.symbolCount
  1020  	var h *peSection
  1021  	if ctxt.LinkMode != LinkExternal {
  1022  		// We do not really need .symtab for go.o, and if we have one, ld
  1023  		// will also include it in the exe, and that will confuse windows.
  1024  		h = f.addSection(".symtab", size, size)
  1025  		h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
  1026  		h.checkOffset(f.symtabOffset)
  1027  	}
  1028  
  1029  	// write COFF string table
  1030  	f.stringTable.write(ctxt.Out)
  1031  	if ctxt.LinkMode != LinkExternal {
  1032  		h.pad(ctxt.Out, uint32(size))
  1033  	}
  1034  }
  1035  
  1036  // writeFileHeader writes COFF file header for peFile f.
  1037  func (f *peFile) writeFileHeader(ctxt *Link) {
  1038  	var fh pe.FileHeader
  1039  
  1040  	switch ctxt.Arch.Family {
  1041  	default:
  1042  		Exitf("unknown PE architecture: %v", ctxt.Arch.Family)
  1043  	case sys.AMD64:
  1044  		fh.Machine = pe.IMAGE_FILE_MACHINE_AMD64
  1045  	case sys.I386:
  1046  		fh.Machine = pe.IMAGE_FILE_MACHINE_I386
  1047  	case sys.ARM64:
  1048  		fh.Machine = pe.IMAGE_FILE_MACHINE_ARM64
  1049  	}
  1050  
  1051  	fh.NumberOfSections = uint16(len(f.sections))
  1052  
  1053  	// Being able to produce identical output for identical input is
  1054  	// much more beneficial than having build timestamp in the header.
  1055  	fh.TimeDateStamp = 0
  1056  
  1057  	if ctxt.LinkMode != LinkExternal {
  1058  		fh.Characteristics = pe.IMAGE_FILE_EXECUTABLE_IMAGE
  1059  		switch ctxt.Arch.Family {
  1060  		case sys.AMD64, sys.I386:
  1061  			if ctxt.BuildMode != BuildModePIE {
  1062  				fh.Characteristics |= pe.IMAGE_FILE_RELOCS_STRIPPED
  1063  			}
  1064  		}
  1065  	}
  1066  	if pe64 {
  1067  		var oh64 pe.OptionalHeader64
  1068  		fh.SizeOfOptionalHeader = uint16(binary.Size(&oh64))
  1069  		fh.Characteristics |= pe.IMAGE_FILE_LARGE_ADDRESS_AWARE
  1070  	} else {
  1071  		var oh pe.OptionalHeader32
  1072  		fh.SizeOfOptionalHeader = uint16(binary.Size(&oh))
  1073  		fh.Characteristics |= pe.IMAGE_FILE_32BIT_MACHINE
  1074  	}
  1075  
  1076  	fh.PointerToSymbolTable = uint32(f.symtabOffset)
  1077  	fh.NumberOfSymbols = uint32(f.symbolCount)
  1078  
  1079  	binary.Write(ctxt.Out, binary.LittleEndian, &fh)
  1080  }
  1081  
  1082  // writeOptionalHeader writes COFF optional header for peFile f.
  1083  func (f *peFile) writeOptionalHeader(ctxt *Link) {
  1084  	var oh pe.OptionalHeader32
  1085  	var oh64 pe.OptionalHeader64
  1086  
  1087  	if pe64 {
  1088  		oh64.Magic = 0x20b // PE32+
  1089  	} else {
  1090  		oh.Magic = 0x10b // PE32
  1091  		oh.BaseOfData = f.dataSect.virtualAddress
  1092  	}
  1093  
  1094  	// Fill out both oh64 and oh. We only use one. Oh well.
  1095  	oh64.MajorLinkerVersion = 3
  1096  	oh.MajorLinkerVersion = 3
  1097  	oh64.MinorLinkerVersion = 0
  1098  	oh.MinorLinkerVersion = 0
  1099  	oh64.SizeOfCode = f.textSect.sizeOfRawData
  1100  	oh.SizeOfCode = f.textSect.sizeOfRawData
  1101  	oh64.SizeOfInitializedData = f.dataSect.sizeOfRawData
  1102  	oh.SizeOfInitializedData = f.dataSect.sizeOfRawData
  1103  	oh64.SizeOfUninitializedData = 0
  1104  	oh.SizeOfUninitializedData = 0
  1105  	if ctxt.LinkMode != LinkExternal {
  1106  		oh64.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
  1107  		oh.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
  1108  	}
  1109  	oh64.BaseOfCode = f.textSect.virtualAddress
  1110  	oh.BaseOfCode = f.textSect.virtualAddress
  1111  	oh64.ImageBase = uint64(PEBASE)
  1112  	oh.ImageBase = uint32(PEBASE)
  1113  	oh64.SectionAlignment = uint32(PESECTALIGN)
  1114  	oh.SectionAlignment = uint32(PESECTALIGN)
  1115  	oh64.FileAlignment = uint32(PEFILEALIGN)
  1116  	oh.FileAlignment = uint32(PEFILEALIGN)
  1117  	oh64.MajorOperatingSystemVersion = PeMinimumTargetMajorVersion
  1118  	oh.MajorOperatingSystemVersion = PeMinimumTargetMajorVersion
  1119  	oh64.MinorOperatingSystemVersion = PeMinimumTargetMinorVersion
  1120  	oh.MinorOperatingSystemVersion = PeMinimumTargetMinorVersion
  1121  	oh64.MajorImageVersion = 1
  1122  	oh.MajorImageVersion = 1
  1123  	oh64.MinorImageVersion = 0
  1124  	oh.MinorImageVersion = 0
  1125  	oh64.MajorSubsystemVersion = PeMinimumTargetMajorVersion
  1126  	oh.MajorSubsystemVersion = PeMinimumTargetMajorVersion
  1127  	oh64.MinorSubsystemVersion = PeMinimumTargetMinorVersion
  1128  	oh.MinorSubsystemVersion = PeMinimumTargetMinorVersion
  1129  	oh64.SizeOfImage = f.nextSectOffset
  1130  	oh.SizeOfImage = f.nextSectOffset
  1131  	oh64.SizeOfHeaders = uint32(PEFILEHEADR)
  1132  	oh.SizeOfHeaders = uint32(PEFILEHEADR)
  1133  	if windowsgui {
  1134  		oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI
  1135  		oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI
  1136  	} else {
  1137  		oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI
  1138  		oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI
  1139  	}
  1140  
  1141  	// Mark as having awareness of terminal services, to avoid ancient compatibility hacks.
  1142  	oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
  1143  	oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
  1144  
  1145  	// Enable DEP
  1146  	oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT
  1147  	oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT
  1148  
  1149  	// The DLL can be relocated at load time.
  1150  	if needPEBaseReloc(ctxt) {
  1151  		oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
  1152  		oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
  1153  	}
  1154  
  1155  	// Image can handle a high entropy 64-bit virtual address space.
  1156  	if ctxt.BuildMode == BuildModePIE {
  1157  		oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
  1158  	}
  1159  
  1160  	// Disable stack growth as we don't want Windows to
  1161  	// fiddle with the thread stack limits, which we set
  1162  	// ourselves to circumvent the stack checks in the
  1163  	// Windows exception dispatcher.
  1164  	// Commit size must be strictly less than reserve
  1165  	// size otherwise reserve will be rounded up to a
  1166  	// larger size, as verified with VMMap.
  1167  
  1168  	// On 64-bit, we always reserve 2MB stacks. "Pure" Go code is
  1169  	// okay with much smaller stacks, but the syscall package
  1170  	// makes it easy to call into arbitrary C code without cgo,
  1171  	// and system calls even in "pure" Go code are actually C
  1172  	// calls that may need more stack than we think.
  1173  	//
  1174  	// The default stack reserve size directly affects only the main
  1175  	// thread.
  1176  	//
  1177  	// For other threads, the runtime explicitly asks the kernel
  1178  	// to use the default stack size so that all stacks are
  1179  	// consistent.
  1180  	//
  1181  	// At thread start, in minit, the runtime queries the OS for
  1182  	// the actual stack bounds so that the stack size doesn't need
  1183  	// to be hard-coded into the runtime.
  1184  	oh64.SizeOfStackReserve = 0x00200000
  1185  	if !iscgo {
  1186  		oh64.SizeOfStackCommit = 0x00001000
  1187  	} else {
  1188  		// TODO(brainman): Maybe remove optional header writing altogether for cgo.
  1189  		// For cgo it is the external linker that is building final executable.
  1190  		// And it probably does not use any information stored in optional header.
  1191  		oh64.SizeOfStackCommit = 0x00200000 - 0x2000 // account for 2 guard pages
  1192  	}
  1193  
  1194  	oh.SizeOfStackReserve = 0x00100000
  1195  	if !iscgo {
  1196  		oh.SizeOfStackCommit = 0x00001000
  1197  	} else {
  1198  		oh.SizeOfStackCommit = 0x00100000 - 0x2000 // account for 2 guard pages
  1199  	}
  1200  
  1201  	oh64.SizeOfHeapReserve = 0x00100000
  1202  	oh.SizeOfHeapReserve = 0x00100000
  1203  	oh64.SizeOfHeapCommit = 0x00001000
  1204  	oh.SizeOfHeapCommit = 0x00001000
  1205  	oh64.NumberOfRvaAndSizes = 16
  1206  	oh.NumberOfRvaAndSizes = 16
  1207  
  1208  	if pe64 {
  1209  		oh64.DataDirectory = f.dataDirectory
  1210  	} else {
  1211  		oh.DataDirectory = f.dataDirectory
  1212  	}
  1213  
  1214  	if pe64 {
  1215  		binary.Write(ctxt.Out, binary.LittleEndian, &oh64)
  1216  	} else {
  1217  		binary.Write(ctxt.Out, binary.LittleEndian, &oh)
  1218  	}
  1219  }
  1220  
  1221  var pefile peFile
  1222  
  1223  func Peinit(ctxt *Link) {
  1224  	var l int
  1225  
  1226  	if ctxt.Arch.PtrSize == 8 {
  1227  		// 64-bit architectures
  1228  		pe64 = true
  1229  		var oh64 pe.OptionalHeader64
  1230  		l = binary.Size(&oh64)
  1231  	} else {
  1232  		// 32-bit architectures
  1233  		var oh pe.OptionalHeader32
  1234  		l = binary.Size(&oh)
  1235  	}
  1236  
  1237  	if ctxt.LinkMode == LinkExternal {
  1238  		// .rdata section will contain "masks" and "shifts" symbols, and they
  1239  		// need to be aligned to 16-bytes. So make all sections aligned
  1240  		// to 32-byte and mark them all IMAGE_SCN_ALIGN_32BYTES so external
  1241  		// linker will honour that requirement.
  1242  		PESECTALIGN = 32
  1243  		PEFILEALIGN = 0
  1244  		// We are creating an object file. The absolute address is irrelevant.
  1245  		PEBASE = 0
  1246  	} else {
  1247  		// Use the same base image address as MSVC and LLVM.
  1248  		if pe64 {
  1249  			PEBASE = 0x140000000
  1250  		} else {
  1251  			PEBASE = 0x400000
  1252  		}
  1253  	}
  1254  
  1255  	var sh [16]pe.SectionHeader32
  1256  	var fh pe.FileHeader
  1257  	PEFILEHEADR = int32(Rnd(int64(len(dosstub)+binary.Size(&fh)+l+binary.Size(&sh)), PEFILEALIGN))
  1258  	if ctxt.LinkMode != LinkExternal {
  1259  		PESECTHEADR = int32(Rnd(int64(PEFILEHEADR), PESECTALIGN))
  1260  	} else {
  1261  		PESECTHEADR = 0
  1262  	}
  1263  	pefile.nextSectOffset = uint32(PESECTHEADR)
  1264  	pefile.nextFileOffset = uint32(PEFILEHEADR)
  1265  
  1266  	if ctxt.LinkMode == LinkInternal {
  1267  		// some mingw libs depend on this symbol, for example, FindPESectionByName
  1268  		for _, name := range [2]string{"__image_base__", "_image_base__"} {
  1269  			sb := ctxt.loader.CreateSymForUpdate(name, 0)
  1270  			sb.SetType(sym.SDATA)
  1271  			sb.SetValue(PEBASE)
  1272  			ctxt.loader.SetAttrSpecial(sb.Sym(), true)
  1273  			ctxt.loader.SetAttrLocal(sb.Sym(), true)
  1274  		}
  1275  
  1276  		// The _load_config_used symbol is required to be present on modern
  1277  		// Windows. We later wire this up to the PE data directory.
  1278  		sb := ctxt.loader.CreateSymForUpdate("_load_config_used", 0)
  1279  		sb.SetType(sym.SRODATA)
  1280  		sb.SetAlign(int32(ctxt.Arch.PtrSize))
  1281  		var buf bytes.Buffer
  1282  		if pe64 {
  1283  			lc := IMAGE_LOAD_CONFIG_DIRECTORY64{
  1284  				Size:       uint32(binary.Size(&IMAGE_LOAD_CONFIG_DIRECTORY64{})),
  1285  				GuardFlags: IMAGE_GUARD_SECURITY_COOKIE_UNUSED,
  1286  			}
  1287  			binary.Write(&buf, binary.LittleEndian, &lc)
  1288  		} else {
  1289  			lc := IMAGE_LOAD_CONFIG_DIRECTORY32{
  1290  				Size:       uint32(binary.Size(&IMAGE_LOAD_CONFIG_DIRECTORY32{})),
  1291  				GuardFlags: IMAGE_GUARD_SECURITY_COOKIE_UNUSED,
  1292  			}
  1293  			binary.Write(&buf, binary.LittleEndian, &lc)
  1294  		}
  1295  		sb.SetData(buf.Bytes())
  1296  		sb.SetSize(int64(buf.Len()))
  1297  		ctxt.loader.SetAttrReachable(sb.Sym(), true)
  1298  	}
  1299  
  1300  	HEADR = PEFILEHEADR
  1301  	if *FlagRound == -1 {
  1302  		*FlagRound = PESECTALIGN
  1303  	}
  1304  	if *FlagTextAddr == -1 {
  1305  		*FlagTextAddr = Rnd(PEBASE, *FlagRound) + int64(PESECTHEADR)
  1306  	}
  1307  }
  1308  
  1309  func pewrite(ctxt *Link) {
  1310  	ctxt.Out.SeekSet(0)
  1311  	if ctxt.LinkMode != LinkExternal {
  1312  		ctxt.Out.Write(dosstub)
  1313  		ctxt.Out.WriteStringN("PE", 4)
  1314  	}
  1315  
  1316  	pefile.writeFileHeader(ctxt)
  1317  
  1318  	pefile.writeOptionalHeader(ctxt)
  1319  
  1320  	for _, sect := range pefile.sections {
  1321  		sect.write(ctxt.Out, ctxt.LinkMode)
  1322  	}
  1323  }
  1324  
  1325  func strput(out *OutBuf, s string) {
  1326  	out.WriteString(s)
  1327  	out.Write8(0)
  1328  	// string must be padded to even size
  1329  	if (len(s)+1)%2 != 0 {
  1330  		out.Write8(0)
  1331  	}
  1332  }
  1333  
  1334  func initdynimport(ctxt *Link) *Dll {
  1335  	ldr := ctxt.loader
  1336  	var d *Dll
  1337  
  1338  	dr = nil
  1339  	var m *Imp
  1340  	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
  1341  		if !ldr.AttrReachable(s) || ldr.SymType(s) != sym.SDYNIMPORT {
  1342  			continue
  1343  		}
  1344  		dynlib := ldr.SymDynimplib(s)
  1345  		for d = dr; d != nil; d = d.next {
  1346  			if d.name == dynlib {
  1347  				m = new(Imp)
  1348  				break
  1349  			}
  1350  		}
  1351  
  1352  		if d == nil {
  1353  			d = new(Dll)
  1354  			d.name = dynlib
  1355  			d.next = dr
  1356  			dr = d
  1357  			m = new(Imp)
  1358  		}
  1359  
  1360  		// Because external link requires properly stdcall decorated name,
  1361  		// all external symbols in runtime use %n to denote that the number
  1362  		// of uinptrs this function consumes. Store the argsize and discard
  1363  		// the %n suffix if any.
  1364  		m.argsize = -1
  1365  		extName := ldr.SymExtname(s)
  1366  		if i := strings.IndexByte(extName, '%'); i >= 0 {
  1367  			var err error
  1368  			m.argsize, err = strconv.Atoi(extName[i+1:])
  1369  			if err != nil {
  1370  				ctxt.Errorf(s, "failed to parse stdcall decoration: %v", err)
  1371  			}
  1372  			m.argsize *= ctxt.Arch.PtrSize
  1373  			ldr.SetSymExtname(s, extName[:i])
  1374  		}
  1375  
  1376  		m.s = s
  1377  		m.next = d.ms
  1378  		d.ms = m
  1379  	}
  1380  
  1381  	if ctxt.IsExternal() {
  1382  		// Add real symbol name
  1383  		for d := dr; d != nil; d = d.next {
  1384  			for m = d.ms; m != nil; m = m.next {
  1385  				sb := ldr.MakeSymbolUpdater(m.s)
  1386  				sb.SetType(sym.SDATA)
  1387  				sb.Grow(int64(ctxt.Arch.PtrSize))
  1388  				dynName := sb.Extname()
  1389  				// only windows/386 requires stdcall decoration
  1390  				if ctxt.Is386() && m.argsize >= 0 {
  1391  					dynName += fmt.Sprintf("@%d", m.argsize)
  1392  				}
  1393  				dynSym := ldr.CreateSymForUpdate(dynName, 0)
  1394  				dynSym.SetType(sym.SHOSTOBJ)
  1395  				r, _ := sb.AddRel(objabi.R_ADDR)
  1396  				r.SetSym(dynSym.Sym())
  1397  				r.SetSiz(uint8(ctxt.Arch.PtrSize))
  1398  			}
  1399  		}
  1400  	} else {
  1401  		dynamic := ldr.CreateSymForUpdate(".windynamic", 0)
  1402  		dynamic.SetType(sym.SWINDOWS)
  1403  		for d := dr; d != nil; d = d.next {
  1404  			for m = d.ms; m != nil; m = m.next {
  1405  				sb := ldr.MakeSymbolUpdater(m.s)
  1406  				sb.SetType(sym.SWINDOWS)
  1407  				sb.SetValue(dynamic.Size())
  1408  				dynamic.SetSize(dynamic.Size() + int64(ctxt.Arch.PtrSize))
  1409  				dynamic.AddInteriorSym(m.s)
  1410  			}
  1411  
  1412  			dynamic.SetSize(dynamic.Size() + int64(ctxt.Arch.PtrSize))
  1413  		}
  1414  	}
  1415  
  1416  	return dr
  1417  }
  1418  
  1419  // peimporteddlls returns the gcc command line argument to link all imported
  1420  // DLLs.
  1421  func peimporteddlls() []string {
  1422  	var dlls []string
  1423  
  1424  	for d := dr; d != nil; d = d.next {
  1425  		dlls = append(dlls, "-l"+strings.TrimSuffix(d.name, ".dll"))
  1426  	}
  1427  
  1428  	return dlls
  1429  }
  1430  
  1431  func addimports(ctxt *Link, datsect *peSection) {
  1432  	ldr := ctxt.loader
  1433  	startoff := ctxt.Out.Offset()
  1434  	dynamic := ldr.LookupOrCreateSym(".windynamic", 0)
  1435  
  1436  	// skip import descriptor table (will write it later)
  1437  	n := uint64(0)
  1438  
  1439  	for d := dr; d != nil; d = d.next {
  1440  		n++
  1441  	}
  1442  	ctxt.Out.SeekSet(startoff + int64(binary.Size(&IMAGE_IMPORT_DESCRIPTOR{}))*int64(n+1))
  1443  
  1444  	// write dll names
  1445  	for d := dr; d != nil; d = d.next {
  1446  		d.nameoff = uint64(ctxt.Out.Offset()) - uint64(startoff)
  1447  		strput(ctxt.Out, d.name)
  1448  	}
  1449  
  1450  	// write function names
  1451  	for d := dr; d != nil; d = d.next {
  1452  		for m := d.ms; m != nil; m = m.next {
  1453  			m.off = uint64(pefile.nextSectOffset) + uint64(ctxt.Out.Offset()) - uint64(startoff)
  1454  			ctxt.Out.Write16(0) // hint
  1455  			strput(ctxt.Out, ldr.SymExtname(m.s))
  1456  		}
  1457  	}
  1458  
  1459  	// write OriginalFirstThunks
  1460  	oftbase := uint64(ctxt.Out.Offset()) - uint64(startoff)
  1461  
  1462  	n = uint64(ctxt.Out.Offset())
  1463  	for d := dr; d != nil; d = d.next {
  1464  		d.thunkoff = uint64(ctxt.Out.Offset()) - n
  1465  		for m := d.ms; m != nil; m = m.next {
  1466  			if pe64 {
  1467  				ctxt.Out.Write64(m.off)
  1468  			} else {
  1469  				ctxt.Out.Write32(uint32(m.off))
  1470  			}
  1471  		}
  1472  
  1473  		if pe64 {
  1474  			ctxt.Out.Write64(0)
  1475  		} else {
  1476  			ctxt.Out.Write32(0)
  1477  		}
  1478  	}
  1479  
  1480  	// add pe section and pad it at the end
  1481  	n = uint64(ctxt.Out.Offset()) - uint64(startoff)
  1482  
  1483  	isect := pefile.addSection(".idata", int(n), int(n))
  1484  	isect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
  1485  	isect.checkOffset(startoff)
  1486  	isect.pad(ctxt.Out, uint32(n))
  1487  	endoff := ctxt.Out.Offset()
  1488  
  1489  	// write FirstThunks (allocated in .data section)
  1490  	ftbase := uint64(ldr.SymValue(dynamic)) - uint64(datsect.virtualAddress) - uint64(PEBASE)
  1491  
  1492  	ctxt.Out.SeekSet(int64(uint64(datsect.pointerToRawData) + ftbase))
  1493  	for d := dr; d != nil; d = d.next {
  1494  		for m := d.ms; m != nil; m = m.next {
  1495  			if pe64 {
  1496  				ctxt.Out.Write64(m.off)
  1497  			} else {
  1498  				ctxt.Out.Write32(uint32(m.off))
  1499  			}
  1500  		}
  1501  
  1502  		if pe64 {
  1503  			ctxt.Out.Write64(0)
  1504  		} else {
  1505  			ctxt.Out.Write32(0)
  1506  		}
  1507  	}
  1508  
  1509  	// finally write import descriptor table
  1510  	out := ctxt.Out
  1511  	out.SeekSet(startoff)
  1512  
  1513  	for d := dr; d != nil; d = d.next {
  1514  		out.Write32(uint32(uint64(isect.virtualAddress) + oftbase + d.thunkoff))
  1515  		out.Write32(0)
  1516  		out.Write32(0)
  1517  		out.Write32(uint32(uint64(isect.virtualAddress) + d.nameoff))
  1518  		out.Write32(uint32(uint64(datsect.virtualAddress) + ftbase + d.thunkoff))
  1519  	}
  1520  
  1521  	out.Write32(0) //end
  1522  	out.Write32(0)
  1523  	out.Write32(0)
  1524  	out.Write32(0)
  1525  	out.Write32(0)
  1526  
  1527  	// update data directory
  1528  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.virtualAddress
  1529  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.virtualSize
  1530  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(ldr.SymValue(dynamic) - PEBASE)
  1531  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(ldr.SymSize(dynamic))
  1532  
  1533  	out.SeekSet(endoff)
  1534  }
  1535  
  1536  func initdynexport(ctxt *Link) {
  1537  	ldr := ctxt.loader
  1538  	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
  1539  		if !ldr.AttrReachable(s) || !ldr.AttrCgoExportDynamic(s) {
  1540  			continue
  1541  		}
  1542  		if len(dexport) >= math.MaxUint16 {
  1543  			ctxt.Errorf(s, "pe dynexport table is full")
  1544  			errorexit()
  1545  		}
  1546  
  1547  		dexport = append(dexport, s)
  1548  	}
  1549  
  1550  	sort.Slice(dexport, func(i, j int) bool { return ldr.SymExtname(dexport[i]) < ldr.SymExtname(dexport[j]) })
  1551  }
  1552  
  1553  func addexports(ctxt *Link) {
  1554  	ldr := ctxt.loader
  1555  	var e IMAGE_EXPORT_DIRECTORY
  1556  
  1557  	nexport := len(dexport)
  1558  	size := binary.Size(&e) + 10*nexport + len(*flagOutfile) + 1
  1559  	for _, s := range dexport {
  1560  		size += len(ldr.SymExtname(s)) + 1
  1561  	}
  1562  
  1563  	if nexport == 0 {
  1564  		return
  1565  	}
  1566  
  1567  	sect := pefile.addSection(".edata", size, size)
  1568  	sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
  1569  	sect.checkOffset(ctxt.Out.Offset())
  1570  	va := int(sect.virtualAddress)
  1571  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = uint32(va)
  1572  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect.virtualSize
  1573  
  1574  	vaName := va + binary.Size(&e) + nexport*4
  1575  	vaAddr := va + binary.Size(&e)
  1576  	vaNa := va + binary.Size(&e) + nexport*8
  1577  
  1578  	e.Characteristics = 0
  1579  	e.MajorVersion = 0
  1580  	e.MinorVersion = 0
  1581  	e.NumberOfFunctions = uint32(nexport)
  1582  	e.NumberOfNames = uint32(nexport)
  1583  	e.Name = uint32(va+binary.Size(&e)) + uint32(nexport)*10 // Program names.
  1584  	e.Base = 1
  1585  	e.AddressOfFunctions = uint32(vaAddr)
  1586  	e.AddressOfNames = uint32(vaName)
  1587  	e.AddressOfNameOrdinals = uint32(vaNa)
  1588  
  1589  	out := ctxt.Out
  1590  
  1591  	// put IMAGE_EXPORT_DIRECTORY
  1592  	binary.Write(out, binary.LittleEndian, &e)
  1593  
  1594  	// put EXPORT Address Table
  1595  	for _, s := range dexport {
  1596  		out.Write32(uint32(ldr.SymValue(s) - PEBASE))
  1597  	}
  1598  
  1599  	// put EXPORT Name Pointer Table
  1600  	v := int(e.Name + uint32(len(*flagOutfile)) + 1)
  1601  
  1602  	for _, s := range dexport {
  1603  		out.Write32(uint32(v))
  1604  		v += len(ldr.SymExtname(s)) + 1
  1605  	}
  1606  
  1607  	// put EXPORT Ordinal Table
  1608  	for i := 0; i < nexport; i++ {
  1609  		out.Write16(uint16(i))
  1610  	}
  1611  
  1612  	// put Names
  1613  	out.WriteStringN(*flagOutfile, len(*flagOutfile)+1)
  1614  
  1615  	for _, s := range dexport {
  1616  		name := ldr.SymExtname(s)
  1617  		out.WriteStringN(name, len(name)+1)
  1618  	}
  1619  	sect.pad(out, uint32(size))
  1620  }
  1621  
  1622  // peBaseRelocEntry represents a single relocation entry.
  1623  type peBaseRelocEntry struct {
  1624  	typeOff uint16
  1625  }
  1626  
  1627  // peBaseRelocBlock represents a Base Relocation Block. A block
  1628  // is a collection of relocation entries in a page, where each
  1629  // entry describes a single relocation.
  1630  // The block page RVA (Relative Virtual Address) is the index
  1631  // into peBaseRelocTable.blocks.
  1632  type peBaseRelocBlock struct {
  1633  	entries []peBaseRelocEntry
  1634  }
  1635  
  1636  // pePages is a type used to store the list of pages for which there
  1637  // are base relocation blocks. This is defined as a type so that
  1638  // it can be sorted.
  1639  type pePages []uint32
  1640  
  1641  // A PE base relocation table is a list of blocks, where each block
  1642  // contains relocation information for a single page. The blocks
  1643  // must be emitted in order of page virtual address.
  1644  // See https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-reloc-section-image-only
  1645  type peBaseRelocTable struct {
  1646  	blocks map[uint32]peBaseRelocBlock
  1647  
  1648  	// pePages is a list of keys into blocks map.
  1649  	// It is stored separately for ease of sorting.
  1650  	pages pePages
  1651  }
  1652  
  1653  func (rt *peBaseRelocTable) init(ctxt *Link) {
  1654  	rt.blocks = make(map[uint32]peBaseRelocBlock)
  1655  }
  1656  
  1657  func (rt *peBaseRelocTable) addentry(ldr *loader.Loader, s loader.Sym, r *loader.Reloc) {
  1658  	// pageSize is the size in bytes of a page
  1659  	// described by a base relocation block.
  1660  	const pageSize = 0x1000
  1661  	const pageMask = pageSize - 1
  1662  
  1663  	addr := ldr.SymValue(s) + int64(r.Off()) - PEBASE
  1664  	page := uint32(addr &^ pageMask)
  1665  	off := uint32(addr & pageMask)
  1666  
  1667  	b, ok := rt.blocks[page]
  1668  	if !ok {
  1669  		rt.pages = append(rt.pages, page)
  1670  	}
  1671  
  1672  	e := peBaseRelocEntry{
  1673  		typeOff: uint16(off & 0xFFF),
  1674  	}
  1675  
  1676  	// Set entry type
  1677  	switch r.Siz() {
  1678  	default:
  1679  		Exitf("unsupported relocation size %d\n", r.Siz)
  1680  	case 4:
  1681  		e.typeOff |= uint16(IMAGE_REL_BASED_HIGHLOW << 12)
  1682  	case 8:
  1683  		e.typeOff |= uint16(IMAGE_REL_BASED_DIR64 << 12)
  1684  	}
  1685  
  1686  	b.entries = append(b.entries, e)
  1687  	rt.blocks[page] = b
  1688  }
  1689  
  1690  func (rt *peBaseRelocTable) write(ctxt *Link) {
  1691  	out := ctxt.Out
  1692  
  1693  	// sort the pages array
  1694  	slices.Sort(rt.pages)
  1695  
  1696  	// .reloc section must be 32-bit aligned
  1697  	if out.Offset()&3 != 0 {
  1698  		Errorf("internal error, start of .reloc not 32-bit aligned")
  1699  	}
  1700  
  1701  	for _, p := range rt.pages {
  1702  		b := rt.blocks[p]
  1703  
  1704  		// Add a dummy entry at the end of the list if we have an
  1705  		// odd number of entries, so as to ensure that the next
  1706  		// block starts on a 32-bit boundary (see issue 68260).
  1707  		if len(b.entries)&1 != 0 {
  1708  			b.entries = append(b.entries, peBaseRelocEntry{})
  1709  		}
  1710  
  1711  		const sizeOfPEbaseRelocBlock = 8 // 2 * sizeof(uint32)
  1712  		blockSize := uint32(sizeOfPEbaseRelocBlock + len(b.entries)*2)
  1713  		out.Write32(p)
  1714  		out.Write32(blockSize)
  1715  
  1716  		for _, e := range b.entries {
  1717  			out.Write16(e.typeOff)
  1718  		}
  1719  	}
  1720  }
  1721  
  1722  func addPEBaseRelocSym(ldr *loader.Loader, s loader.Sym, rt *peBaseRelocTable) {
  1723  	relocs := ldr.Relocs(s)
  1724  	for ri := 0; ri < relocs.Count(); ri++ {
  1725  		r := relocs.At(ri)
  1726  		if r.Type() >= objabi.ElfRelocOffset {
  1727  			continue
  1728  		}
  1729  		if r.Siz() == 0 { // informational relocation
  1730  			continue
  1731  		}
  1732  		rs := r.Sym()
  1733  		if rs == 0 {
  1734  			continue
  1735  		}
  1736  		if !ldr.AttrReachable(s) {
  1737  			continue
  1738  		}
  1739  
  1740  		switch r.Type() {
  1741  		default:
  1742  		case objabi.R_ADDR:
  1743  			rt.addentry(ldr, s, &r)
  1744  		}
  1745  	}
  1746  }
  1747  
  1748  func needPEBaseReloc(ctxt *Link) bool {
  1749  	// Non-PIE x86 binaries don't need the base relocation table.
  1750  	// Everyone else does.
  1751  	if (ctxt.Arch.Family == sys.I386 || ctxt.Arch.Family == sys.AMD64) && ctxt.BuildMode != BuildModePIE {
  1752  		return false
  1753  	}
  1754  	return true
  1755  }
  1756  
  1757  func addPEBaseReloc(ctxt *Link) {
  1758  	if !needPEBaseReloc(ctxt) {
  1759  		return
  1760  	}
  1761  
  1762  	var rt peBaseRelocTable
  1763  	rt.init(ctxt)
  1764  
  1765  	// Get relocation information
  1766  	ldr := ctxt.loader
  1767  	for _, s := range ctxt.Textp {
  1768  		addPEBaseRelocSym(ldr, s, &rt)
  1769  	}
  1770  	for _, s := range ctxt.datap {
  1771  		addPEBaseRelocSym(ldr, s, &rt)
  1772  	}
  1773  
  1774  	// Write relocation information
  1775  	startoff := ctxt.Out.Offset()
  1776  	rt.write(ctxt)
  1777  	size := ctxt.Out.Offset() - startoff
  1778  
  1779  	// Add a PE section and pad it at the end
  1780  	rsect := pefile.addSection(".reloc", int(size), int(size))
  1781  	rsect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
  1782  	rsect.checkOffset(startoff)
  1783  	rsect.pad(ctxt.Out, uint32(size))
  1784  
  1785  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = rsect.virtualAddress
  1786  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = rsect.virtualSize
  1787  }
  1788  
  1789  func (ctxt *Link) dope() {
  1790  	initdynimport(ctxt)
  1791  	initdynexport(ctxt)
  1792  }
  1793  
  1794  func setpersrc(ctxt *Link, syms []loader.Sym) {
  1795  	if len(rsrcsyms) != 0 {
  1796  		Errorf("too many .rsrc sections")
  1797  	}
  1798  	rsrcsyms = syms
  1799  }
  1800  
  1801  func addpersrc(ctxt *Link) {
  1802  	if len(rsrcsyms) == 0 {
  1803  		return
  1804  	}
  1805  
  1806  	var size int64
  1807  	for _, rsrcsym := range rsrcsyms {
  1808  		size += ctxt.loader.SymSize(rsrcsym)
  1809  	}
  1810  	h := pefile.addSection(".rsrc", int(size), int(size))
  1811  	h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA
  1812  	h.checkOffset(ctxt.Out.Offset())
  1813  
  1814  	for _, rsrcsym := range rsrcsyms {
  1815  		// A split resource happens when the actual resource data and its relocations are
  1816  		// split across multiple sections, denoted by a $01 or $02 at the end of the .rsrc
  1817  		// section name.
  1818  		splitResources := strings.Contains(ctxt.loader.SymName(rsrcsym), ".rsrc$")
  1819  		relocs := ctxt.loader.Relocs(rsrcsym)
  1820  		data := ctxt.loader.Data(rsrcsym)
  1821  		for ri := 0; ri < relocs.Count(); ri++ {
  1822  			r := relocs.At(ri)
  1823  			p := data[r.Off():]
  1824  			val := uint32(int64(h.virtualAddress) + r.Add())
  1825  			if splitResources {
  1826  				// If we're a split resource section, and that section has relocation
  1827  				// symbols, then the data that it points to doesn't actually begin at
  1828  				// the virtual address listed in this current section, but rather
  1829  				// begins at the section immediately after this one. So, in order to
  1830  				// calculate the proper virtual address of the data it's pointing to,
  1831  				// we have to add the length of this section to the virtual address.
  1832  				// This works because .rsrc sections are divided into two (but not more)
  1833  				// of these sections.
  1834  				val += uint32(len(data))
  1835  			}
  1836  			binary.LittleEndian.PutUint32(p, val)
  1837  		}
  1838  		ctxt.Out.Write(data)
  1839  	}
  1840  	h.pad(ctxt.Out, uint32(size))
  1841  
  1842  	// update data directory
  1843  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress
  1844  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize
  1845  }
  1846  
  1847  func asmbPe(ctxt *Link) {
  1848  	t := pefile.addSection(".text", int(Segtext.Length), int(Segtext.Length))
  1849  	t.characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
  1850  	if ctxt.LinkMode == LinkExternal {
  1851  		// some data symbols (e.g. masks) end up in the .text section, and they normally
  1852  		// expect larger alignment requirement than the default text section alignment.
  1853  		t.characteristics |= IMAGE_SCN_ALIGN_32BYTES
  1854  	}
  1855  	t.checkSegment(&Segtext)
  1856  	pefile.textSect = t
  1857  
  1858  	ro := pefile.addSection(".rdata", int(Segrodata.Length), int(Segrodata.Length))
  1859  	ro.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
  1860  	if ctxt.LinkMode == LinkExternal {
  1861  		// some data symbols (e.g. masks) end up in the .rdata section, and they normally
  1862  		// expect larger alignment requirement than the default text section alignment.
  1863  		ro.characteristics |= IMAGE_SCN_ALIGN_32BYTES
  1864  	}
  1865  	ro.checkSegment(&Segrodata)
  1866  	pefile.rdataSect = ro
  1867  
  1868  	// This should have been added in Peinit and by now is part of the
  1869  	// just-written .rdata section.
  1870  	s := ctxt.loader.Lookup("_load_config_used", 0)
  1871  	if s != 0 {
  1872  		pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = uint32(ctxt.loader.SymValue(s) - PEBASE)
  1873  		pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = uint32(ctxt.loader.SymSize(s))
  1874  	}
  1875  
  1876  	var d *peSection
  1877  	if ctxt.LinkMode != LinkExternal {
  1878  		d = pefile.addSection(".data", int(Segdata.Length), int(Segdata.Filelen))
  1879  		d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
  1880  		d.checkSegment(&Segdata)
  1881  		pefile.dataSect = d
  1882  	} else {
  1883  		d = pefile.addSection(".data", int(Segdata.Filelen), int(Segdata.Filelen))
  1884  		d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
  1885  		d.checkSegment(&Segdata)
  1886  		pefile.dataSect = d
  1887  
  1888  		b := pefile.addSection(".bss", int(Segdata.Length-Segdata.Filelen), 0)
  1889  		b.characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
  1890  		b.pointerToRawData = 0
  1891  		pefile.bssSect = b
  1892  	}
  1893  
  1894  	pefile.addSEH(ctxt)
  1895  	pefile.addDWARF()
  1896  
  1897  	if ctxt.LinkMode == LinkExternal {
  1898  		pefile.ctorsSect = pefile.addInitArray(ctxt)
  1899  	}
  1900  
  1901  	ctxt.Out.SeekSet(int64(pefile.nextFileOffset))
  1902  	if ctxt.LinkMode != LinkExternal {
  1903  		addimports(ctxt, d)
  1904  		addexports(ctxt)
  1905  		addPEBaseReloc(ctxt)
  1906  	}
  1907  	pefile.writeSymbolTableAndStringTable(ctxt)
  1908  	addpersrc(ctxt)
  1909  	if ctxt.LinkMode == LinkExternal {
  1910  		pefile.emitRelocations(ctxt)
  1911  	}
  1912  
  1913  	pewrite(ctxt)
  1914  }
  1915  
  1916  // peCreateExportFile creates a file with exported symbols for Windows .def files.
  1917  // ld will export all symbols, even those not marked for export, unless a .def file is provided.
  1918  func peCreateExportFile(ctxt *Link, libName string) (fname string) {
  1919  	fname = filepath.Join(*flagTmpdir, "export_file.def")
  1920  	var buf bytes.Buffer
  1921  
  1922  	if ctxt.BuildMode == BuildModeCShared {
  1923  		fmt.Fprintf(&buf, "LIBRARY %s\n", libName)
  1924  	}
  1925  	buf.WriteString("EXPORTS\n")
  1926  
  1927  	ldr := ctxt.loader
  1928  	var exports []string
  1929  	for s := range ldr.ForAllCgoExportStatic() {
  1930  		extname := ldr.SymExtname(s)
  1931  		if !strings.HasPrefix(extname, "_cgoexp_") {
  1932  			continue
  1933  		}
  1934  		if ldr.IsFileLocal(s) {
  1935  			continue // Only export non-static symbols
  1936  		}
  1937  		// Retrieve the name of the initial symbol
  1938  		// exported by cgo.
  1939  		// The corresponding Go symbol is:
  1940  		// _cgoexp_hashcode_symname.
  1941  		name := strings.SplitN(extname, "_", 4)[3]
  1942  		exports = append(exports, name)
  1943  	}
  1944  	if len(exports) == 0 {
  1945  		// See runtime/cgo/windows.go for details.
  1946  		exports = append(exports, "_cgo_stub_export")
  1947  	}
  1948  	sort.Strings(exports)
  1949  	buf.WriteString(strings.Join(exports, "\n"))
  1950  
  1951  	err := os.WriteFile(fname, buf.Bytes(), 0666)
  1952  	if err != nil {
  1953  		Errorf("WriteFile %s failed: %v", fname, err)
  1954  	}
  1955  
  1956  	return fname
  1957  }
  1958  

View as plain text