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  			class = IMAGE_SYM_CLASS_STATIC
   942  		}
   943  		f.writeSymbol(ctxt.Out, ldr, s, name, value, sect, peSymType, uint8(class))
   944  	}
   945  
   946  	if ctxt.LinkMode == LinkExternal {
   947  		// Include section symbols as external, because
   948  		// .ctors and .debug_* section relocations refer to it.
   949  		for _, pesect := range f.sections {
   950  			s := ldr.LookupOrCreateSym(pesect.name, 0)
   951  			f.writeSymbol(ctxt.Out, ldr, s, pesect.name, 0, pesect.index, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_STATIC)
   952  		}
   953  	}
   954  
   955  	// Add special runtime.text and runtime.etext symbols.
   956  	s := ldr.Lookup("runtime.text", 0)
   957  	if ldr.SymType(s).IsText() {
   958  		addsym(s)
   959  	}
   960  	s = ldr.Lookup("runtime.etext", 0)
   961  	if ldr.SymType(s).IsText() {
   962  		addsym(s)
   963  	}
   964  
   965  	// Add text symbols.
   966  	for _, s := range ctxt.Textp {
   967  		addsym(s)
   968  	}
   969  
   970  	shouldBeInSymbolTable := func(s loader.Sym) bool {
   971  		if ldr.AttrNotInSymbolTable(s) {
   972  			return false
   973  		}
   974  		name := ldr.SymName(s) // TODO: try not to read the name
   975  		if name == "" || name[0] == '.' {
   976  			return false
   977  		}
   978  		return true
   979  	}
   980  
   981  	// Add data symbols and external references.
   982  	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
   983  		if !ldr.AttrReachable(s) {
   984  			continue
   985  		}
   986  		t := ldr.SymType(s)
   987  		if t >= sym.SELFRXSECT && t < sym.SFirstUnallocated { // data sections handled in dodata
   988  			if t == sym.STLSBSS {
   989  				continue
   990  			}
   991  			if !shouldBeInSymbolTable(s) {
   992  				continue
   993  			}
   994  			addsym(s)
   995  		}
   996  
   997  		switch t {
   998  		case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
   999  			addsym(s)
  1000  		default:
  1001  			if len(isLabel) > 0 && isLabel[s] {
  1002  				addsym(s)
  1003  			}
  1004  		}
  1005  	}
  1006  }
  1007  
  1008  // writeSymbolTableAndStringTable writes out symbol and string tables for peFile f.
  1009  func (f *peFile) writeSymbolTableAndStringTable(ctxt *Link) {
  1010  	f.symtabOffset = ctxt.Out.Offset()
  1011  
  1012  	// write COFF symbol table
  1013  	if !*FlagS || ctxt.LinkMode == LinkExternal {
  1014  		f.writeSymbols(ctxt)
  1015  	}
  1016  
  1017  	// update COFF file header and section table
  1018  	size := f.stringTable.size() + 18*f.symbolCount
  1019  	var h *peSection
  1020  	if ctxt.LinkMode != LinkExternal {
  1021  		// We do not really need .symtab for go.o, and if we have one, ld
  1022  		// will also include it in the exe, and that will confuse windows.
  1023  		h = f.addSection(".symtab", size, size)
  1024  		h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
  1025  		h.checkOffset(f.symtabOffset)
  1026  	}
  1027  
  1028  	// write COFF string table
  1029  	f.stringTable.write(ctxt.Out)
  1030  	if ctxt.LinkMode != LinkExternal {
  1031  		h.pad(ctxt.Out, uint32(size))
  1032  	}
  1033  }
  1034  
  1035  // writeFileHeader writes COFF file header for peFile f.
  1036  func (f *peFile) writeFileHeader(ctxt *Link) {
  1037  	var fh pe.FileHeader
  1038  
  1039  	switch ctxt.Arch.Family {
  1040  	default:
  1041  		Exitf("unknown PE architecture: %v", ctxt.Arch.Family)
  1042  	case sys.AMD64:
  1043  		fh.Machine = pe.IMAGE_FILE_MACHINE_AMD64
  1044  	case sys.I386:
  1045  		fh.Machine = pe.IMAGE_FILE_MACHINE_I386
  1046  	case sys.ARM64:
  1047  		fh.Machine = pe.IMAGE_FILE_MACHINE_ARM64
  1048  	}
  1049  
  1050  	fh.NumberOfSections = uint16(len(f.sections))
  1051  
  1052  	// Being able to produce identical output for identical input is
  1053  	// much more beneficial than having build timestamp in the header.
  1054  	fh.TimeDateStamp = 0
  1055  
  1056  	if ctxt.LinkMode != LinkExternal {
  1057  		fh.Characteristics = pe.IMAGE_FILE_EXECUTABLE_IMAGE
  1058  		switch ctxt.Arch.Family {
  1059  		case sys.AMD64, sys.I386:
  1060  			if ctxt.BuildMode != BuildModePIE {
  1061  				fh.Characteristics |= pe.IMAGE_FILE_RELOCS_STRIPPED
  1062  			}
  1063  		}
  1064  	}
  1065  	if pe64 {
  1066  		var oh64 pe.OptionalHeader64
  1067  		fh.SizeOfOptionalHeader = uint16(binary.Size(&oh64))
  1068  		fh.Characteristics |= pe.IMAGE_FILE_LARGE_ADDRESS_AWARE
  1069  	} else {
  1070  		var oh pe.OptionalHeader32
  1071  		fh.SizeOfOptionalHeader = uint16(binary.Size(&oh))
  1072  		fh.Characteristics |= pe.IMAGE_FILE_32BIT_MACHINE
  1073  	}
  1074  
  1075  	fh.PointerToSymbolTable = uint32(f.symtabOffset)
  1076  	fh.NumberOfSymbols = uint32(f.symbolCount)
  1077  
  1078  	binary.Write(ctxt.Out, binary.LittleEndian, &fh)
  1079  }
  1080  
  1081  // writeOptionalHeader writes COFF optional header for peFile f.
  1082  func (f *peFile) writeOptionalHeader(ctxt *Link) {
  1083  	var oh pe.OptionalHeader32
  1084  	var oh64 pe.OptionalHeader64
  1085  
  1086  	if pe64 {
  1087  		oh64.Magic = 0x20b // PE32+
  1088  	} else {
  1089  		oh.Magic = 0x10b // PE32
  1090  		oh.BaseOfData = f.dataSect.virtualAddress
  1091  	}
  1092  
  1093  	// Fill out both oh64 and oh. We only use one. Oh well.
  1094  	oh64.MajorLinkerVersion = 3
  1095  	oh.MajorLinkerVersion = 3
  1096  	oh64.MinorLinkerVersion = 0
  1097  	oh.MinorLinkerVersion = 0
  1098  	oh64.SizeOfCode = f.textSect.sizeOfRawData
  1099  	oh.SizeOfCode = f.textSect.sizeOfRawData
  1100  	oh64.SizeOfInitializedData = f.dataSect.sizeOfRawData
  1101  	oh.SizeOfInitializedData = f.dataSect.sizeOfRawData
  1102  	oh64.SizeOfUninitializedData = 0
  1103  	oh.SizeOfUninitializedData = 0
  1104  	if ctxt.LinkMode != LinkExternal {
  1105  		oh64.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
  1106  		oh.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
  1107  	}
  1108  	oh64.BaseOfCode = f.textSect.virtualAddress
  1109  	oh.BaseOfCode = f.textSect.virtualAddress
  1110  	oh64.ImageBase = uint64(PEBASE)
  1111  	oh.ImageBase = uint32(PEBASE)
  1112  	oh64.SectionAlignment = uint32(PESECTALIGN)
  1113  	oh.SectionAlignment = uint32(PESECTALIGN)
  1114  	oh64.FileAlignment = uint32(PEFILEALIGN)
  1115  	oh.FileAlignment = uint32(PEFILEALIGN)
  1116  	oh64.MajorOperatingSystemVersion = PeMinimumTargetMajorVersion
  1117  	oh.MajorOperatingSystemVersion = PeMinimumTargetMajorVersion
  1118  	oh64.MinorOperatingSystemVersion = PeMinimumTargetMinorVersion
  1119  	oh.MinorOperatingSystemVersion = PeMinimumTargetMinorVersion
  1120  	oh64.MajorImageVersion = 1
  1121  	oh.MajorImageVersion = 1
  1122  	oh64.MinorImageVersion = 0
  1123  	oh.MinorImageVersion = 0
  1124  	oh64.MajorSubsystemVersion = PeMinimumTargetMajorVersion
  1125  	oh.MajorSubsystemVersion = PeMinimumTargetMajorVersion
  1126  	oh64.MinorSubsystemVersion = PeMinimumTargetMinorVersion
  1127  	oh.MinorSubsystemVersion = PeMinimumTargetMinorVersion
  1128  	oh64.SizeOfImage = f.nextSectOffset
  1129  	oh.SizeOfImage = f.nextSectOffset
  1130  	oh64.SizeOfHeaders = uint32(PEFILEHEADR)
  1131  	oh.SizeOfHeaders = uint32(PEFILEHEADR)
  1132  	if windowsgui {
  1133  		oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI
  1134  		oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI
  1135  	} else {
  1136  		oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI
  1137  		oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI
  1138  	}
  1139  
  1140  	// Mark as having awareness of terminal services, to avoid ancient compatibility hacks.
  1141  	oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
  1142  	oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
  1143  
  1144  	// Enable DEP
  1145  	oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT
  1146  	oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT
  1147  
  1148  	// The DLL can be relocated at load time.
  1149  	if needPEBaseReloc(ctxt) {
  1150  		oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
  1151  		oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
  1152  	}
  1153  
  1154  	// Image can handle a high entropy 64-bit virtual address space.
  1155  	if ctxt.BuildMode == BuildModePIE {
  1156  		oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
  1157  	}
  1158  
  1159  	// Disable stack growth as we don't want Windows to
  1160  	// fiddle with the thread stack limits, which we set
  1161  	// ourselves to circumvent the stack checks in the
  1162  	// Windows exception dispatcher.
  1163  	// Commit size must be strictly less than reserve
  1164  	// size otherwise reserve will be rounded up to a
  1165  	// larger size, as verified with VMMap.
  1166  
  1167  	// On 64-bit, we always reserve 2MB stacks. "Pure" Go code is
  1168  	// okay with much smaller stacks, but the syscall package
  1169  	// makes it easy to call into arbitrary C code without cgo,
  1170  	// and system calls even in "pure" Go code are actually C
  1171  	// calls that may need more stack than we think.
  1172  	//
  1173  	// The default stack reserve size directly affects only the main
  1174  	// thread.
  1175  	//
  1176  	// For other threads, the runtime explicitly asks the kernel
  1177  	// to use the default stack size so that all stacks are
  1178  	// consistent.
  1179  	//
  1180  	// At thread start, in minit, the runtime queries the OS for
  1181  	// the actual stack bounds so that the stack size doesn't need
  1182  	// to be hard-coded into the runtime.
  1183  	oh64.SizeOfStackReserve = 0x00200000
  1184  	if !iscgo {
  1185  		oh64.SizeOfStackCommit = 0x00001000
  1186  	} else {
  1187  		// TODO(brainman): Maybe remove optional header writing altogether for cgo.
  1188  		// For cgo it is the external linker that is building final executable.
  1189  		// And it probably does not use any information stored in optional header.
  1190  		oh64.SizeOfStackCommit = 0x00200000 - 0x2000 // account for 2 guard pages
  1191  	}
  1192  
  1193  	oh.SizeOfStackReserve = 0x00100000
  1194  	if !iscgo {
  1195  		oh.SizeOfStackCommit = 0x00001000
  1196  	} else {
  1197  		oh.SizeOfStackCommit = 0x00100000 - 0x2000 // account for 2 guard pages
  1198  	}
  1199  
  1200  	oh64.SizeOfHeapReserve = 0x00100000
  1201  	oh.SizeOfHeapReserve = 0x00100000
  1202  	oh64.SizeOfHeapCommit = 0x00001000
  1203  	oh.SizeOfHeapCommit = 0x00001000
  1204  	oh64.NumberOfRvaAndSizes = 16
  1205  	oh.NumberOfRvaAndSizes = 16
  1206  
  1207  	if pe64 {
  1208  		oh64.DataDirectory = f.dataDirectory
  1209  	} else {
  1210  		oh.DataDirectory = f.dataDirectory
  1211  	}
  1212  
  1213  	if pe64 {
  1214  		binary.Write(ctxt.Out, binary.LittleEndian, &oh64)
  1215  	} else {
  1216  		binary.Write(ctxt.Out, binary.LittleEndian, &oh)
  1217  	}
  1218  }
  1219  
  1220  var pefile peFile
  1221  
  1222  func Peinit(ctxt *Link) {
  1223  	var l int
  1224  
  1225  	if ctxt.Arch.PtrSize == 8 {
  1226  		// 64-bit architectures
  1227  		pe64 = true
  1228  		var oh64 pe.OptionalHeader64
  1229  		l = binary.Size(&oh64)
  1230  	} else {
  1231  		// 32-bit architectures
  1232  		var oh pe.OptionalHeader32
  1233  		l = binary.Size(&oh)
  1234  	}
  1235  
  1236  	if ctxt.LinkMode == LinkExternal {
  1237  		// .rdata section will contain "masks" and "shifts" symbols, and they
  1238  		// need to be aligned to 16-bytes. So make all sections aligned
  1239  		// to 32-byte and mark them all IMAGE_SCN_ALIGN_32BYTES so external
  1240  		// linker will honour that requirement.
  1241  		PESECTALIGN = 32
  1242  		PEFILEALIGN = 0
  1243  		// We are creating an object file. The absolute address is irrelevant.
  1244  		PEBASE = 0
  1245  	} else {
  1246  		// Use the same base image address as MSVC and LLVM.
  1247  		if pe64 {
  1248  			PEBASE = 0x140000000
  1249  		} else {
  1250  			PEBASE = 0x400000
  1251  		}
  1252  	}
  1253  
  1254  	var sh [16]pe.SectionHeader32
  1255  	var fh pe.FileHeader
  1256  	PEFILEHEADR = int32(Rnd(int64(len(dosstub)+binary.Size(&fh)+l+binary.Size(&sh)), PEFILEALIGN))
  1257  	if ctxt.LinkMode != LinkExternal {
  1258  		PESECTHEADR = int32(Rnd(int64(PEFILEHEADR), PESECTALIGN))
  1259  	} else {
  1260  		PESECTHEADR = 0
  1261  	}
  1262  	pefile.nextSectOffset = uint32(PESECTHEADR)
  1263  	pefile.nextFileOffset = uint32(PEFILEHEADR)
  1264  
  1265  	if ctxt.LinkMode == LinkInternal {
  1266  		// some mingw libs depend on this symbol, for example, FindPESectionByName
  1267  		for _, name := range [2]string{"__image_base__", "_image_base__"} {
  1268  			sb := ctxt.loader.CreateSymForUpdate(name, 0)
  1269  			sb.SetType(sym.SDATA)
  1270  			sb.SetValue(PEBASE)
  1271  			ctxt.loader.SetAttrSpecial(sb.Sym(), true)
  1272  			ctxt.loader.SetAttrLocal(sb.Sym(), true)
  1273  		}
  1274  
  1275  		// The _load_config_used symbol is required to be present on modern
  1276  		// Windows. We later wire this up to the PE data directory.
  1277  		sb := ctxt.loader.CreateSymForUpdate("_load_config_used", 0)
  1278  		sb.SetType(sym.SRODATA)
  1279  		sb.SetAlign(int32(ctxt.Arch.PtrSize))
  1280  		var buf bytes.Buffer
  1281  		if pe64 {
  1282  			lc := IMAGE_LOAD_CONFIG_DIRECTORY64{
  1283  				Size:       uint32(binary.Size(&IMAGE_LOAD_CONFIG_DIRECTORY64{})),
  1284  				GuardFlags: IMAGE_GUARD_SECURITY_COOKIE_UNUSED,
  1285  			}
  1286  			binary.Write(&buf, binary.LittleEndian, &lc)
  1287  		} else {
  1288  			lc := IMAGE_LOAD_CONFIG_DIRECTORY32{
  1289  				Size:       uint32(binary.Size(&IMAGE_LOAD_CONFIG_DIRECTORY32{})),
  1290  				GuardFlags: IMAGE_GUARD_SECURITY_COOKIE_UNUSED,
  1291  			}
  1292  			binary.Write(&buf, binary.LittleEndian, &lc)
  1293  		}
  1294  		sb.SetData(buf.Bytes())
  1295  		sb.SetSize(int64(buf.Len()))
  1296  		ctxt.loader.SetAttrReachable(sb.Sym(), true)
  1297  	}
  1298  
  1299  	HEADR = PEFILEHEADR
  1300  	if *FlagRound == -1 {
  1301  		*FlagRound = PESECTALIGN
  1302  	}
  1303  	if *FlagTextAddr == -1 {
  1304  		*FlagTextAddr = Rnd(PEBASE, *FlagRound) + int64(PESECTHEADR)
  1305  	}
  1306  }
  1307  
  1308  func pewrite(ctxt *Link) {
  1309  	ctxt.Out.SeekSet(0)
  1310  	if ctxt.LinkMode != LinkExternal {
  1311  		ctxt.Out.Write(dosstub)
  1312  		ctxt.Out.WriteStringN("PE", 4)
  1313  	}
  1314  
  1315  	pefile.writeFileHeader(ctxt)
  1316  
  1317  	pefile.writeOptionalHeader(ctxt)
  1318  
  1319  	for _, sect := range pefile.sections {
  1320  		sect.write(ctxt.Out, ctxt.LinkMode)
  1321  	}
  1322  }
  1323  
  1324  func strput(out *OutBuf, s string) {
  1325  	out.WriteString(s)
  1326  	out.Write8(0)
  1327  	// string must be padded to even size
  1328  	if (len(s)+1)%2 != 0 {
  1329  		out.Write8(0)
  1330  	}
  1331  }
  1332  
  1333  func initdynimport(ctxt *Link) *Dll {
  1334  	ldr := ctxt.loader
  1335  	var d *Dll
  1336  
  1337  	dr = nil
  1338  	var m *Imp
  1339  	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
  1340  		if !ldr.AttrReachable(s) || ldr.SymType(s) != sym.SDYNIMPORT {
  1341  			continue
  1342  		}
  1343  		dynlib := ldr.SymDynimplib(s)
  1344  		for d = dr; d != nil; d = d.next {
  1345  			if d.name == dynlib {
  1346  				m = new(Imp)
  1347  				break
  1348  			}
  1349  		}
  1350  
  1351  		if d == nil {
  1352  			d = new(Dll)
  1353  			d.name = dynlib
  1354  			d.next = dr
  1355  			dr = d
  1356  			m = new(Imp)
  1357  		}
  1358  
  1359  		// Because external link requires properly stdcall decorated name,
  1360  		// all external symbols in runtime use %n to denote that the number
  1361  		// of uinptrs this function consumes. Store the argsize and discard
  1362  		// the %n suffix if any.
  1363  		m.argsize = -1
  1364  		extName := ldr.SymExtname(s)
  1365  		if i := strings.IndexByte(extName, '%'); i >= 0 {
  1366  			var err error
  1367  			m.argsize, err = strconv.Atoi(extName[i+1:])
  1368  			if err != nil {
  1369  				ctxt.Errorf(s, "failed to parse stdcall decoration: %v", err)
  1370  			}
  1371  			m.argsize *= ctxt.Arch.PtrSize
  1372  			ldr.SetSymExtname(s, extName[:i])
  1373  		}
  1374  
  1375  		m.s = s
  1376  		m.next = d.ms
  1377  		d.ms = m
  1378  	}
  1379  
  1380  	if ctxt.IsExternal() {
  1381  		// Add real symbol name
  1382  		for d := dr; d != nil; d = d.next {
  1383  			for m = d.ms; m != nil; m = m.next {
  1384  				sb := ldr.MakeSymbolUpdater(m.s)
  1385  				sb.SetType(sym.SDATA)
  1386  				sb.Grow(int64(ctxt.Arch.PtrSize))
  1387  				dynName := sb.Extname()
  1388  				// only windows/386 requires stdcall decoration
  1389  				if ctxt.Is386() && m.argsize >= 0 {
  1390  					dynName += fmt.Sprintf("@%d", m.argsize)
  1391  				}
  1392  				dynSym := ldr.CreateSymForUpdate(dynName, 0)
  1393  				dynSym.SetType(sym.SHOSTOBJ)
  1394  				r, _ := sb.AddRel(objabi.R_ADDR)
  1395  				r.SetSym(dynSym.Sym())
  1396  				r.SetSiz(uint8(ctxt.Arch.PtrSize))
  1397  			}
  1398  		}
  1399  	} else {
  1400  		dynamic := ldr.CreateSymForUpdate(".windynamic", 0)
  1401  		dynamic.SetType(sym.SWINDOWS)
  1402  		for d := dr; d != nil; d = d.next {
  1403  			for m = d.ms; m != nil; m = m.next {
  1404  				sb := ldr.MakeSymbolUpdater(m.s)
  1405  				sb.SetType(sym.SWINDOWS)
  1406  				sb.SetValue(dynamic.Size())
  1407  				dynamic.SetSize(dynamic.Size() + int64(ctxt.Arch.PtrSize))
  1408  				dynamic.AddInteriorSym(m.s)
  1409  			}
  1410  
  1411  			dynamic.SetSize(dynamic.Size() + int64(ctxt.Arch.PtrSize))
  1412  		}
  1413  	}
  1414  
  1415  	return dr
  1416  }
  1417  
  1418  // peimporteddlls returns the gcc command line argument to link all imported
  1419  // DLLs.
  1420  func peimporteddlls() []string {
  1421  	var dlls []string
  1422  
  1423  	for d := dr; d != nil; d = d.next {
  1424  		dlls = append(dlls, "-l"+strings.TrimSuffix(d.name, ".dll"))
  1425  	}
  1426  
  1427  	return dlls
  1428  }
  1429  
  1430  func addimports(ctxt *Link, datsect *peSection) {
  1431  	ldr := ctxt.loader
  1432  	startoff := ctxt.Out.Offset()
  1433  	dynamic := ldr.LookupOrCreateSym(".windynamic", 0)
  1434  
  1435  	// skip import descriptor table (will write it later)
  1436  	n := uint64(0)
  1437  
  1438  	for d := dr; d != nil; d = d.next {
  1439  		n++
  1440  	}
  1441  	ctxt.Out.SeekSet(startoff + int64(binary.Size(&IMAGE_IMPORT_DESCRIPTOR{}))*int64(n+1))
  1442  
  1443  	// write dll names
  1444  	for d := dr; d != nil; d = d.next {
  1445  		d.nameoff = uint64(ctxt.Out.Offset()) - uint64(startoff)
  1446  		strput(ctxt.Out, d.name)
  1447  	}
  1448  
  1449  	// write function names
  1450  	for d := dr; d != nil; d = d.next {
  1451  		for m := d.ms; m != nil; m = m.next {
  1452  			m.off = uint64(pefile.nextSectOffset) + uint64(ctxt.Out.Offset()) - uint64(startoff)
  1453  			ctxt.Out.Write16(0) // hint
  1454  			strput(ctxt.Out, ldr.SymExtname(m.s))
  1455  		}
  1456  	}
  1457  
  1458  	// write OriginalFirstThunks
  1459  	oftbase := uint64(ctxt.Out.Offset()) - uint64(startoff)
  1460  
  1461  	n = uint64(ctxt.Out.Offset())
  1462  	for d := dr; d != nil; d = d.next {
  1463  		d.thunkoff = uint64(ctxt.Out.Offset()) - n
  1464  		for m := d.ms; m != nil; m = m.next {
  1465  			if pe64 {
  1466  				ctxt.Out.Write64(m.off)
  1467  			} else {
  1468  				ctxt.Out.Write32(uint32(m.off))
  1469  			}
  1470  		}
  1471  
  1472  		if pe64 {
  1473  			ctxt.Out.Write64(0)
  1474  		} else {
  1475  			ctxt.Out.Write32(0)
  1476  		}
  1477  	}
  1478  
  1479  	// add pe section and pad it at the end
  1480  	n = uint64(ctxt.Out.Offset()) - uint64(startoff)
  1481  
  1482  	isect := pefile.addSection(".idata", int(n), int(n))
  1483  	isect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
  1484  	isect.checkOffset(startoff)
  1485  	isect.pad(ctxt.Out, uint32(n))
  1486  	endoff := ctxt.Out.Offset()
  1487  
  1488  	// write FirstThunks (allocated in .data section)
  1489  	ftbase := uint64(ldr.SymValue(dynamic)) - uint64(datsect.virtualAddress) - uint64(PEBASE)
  1490  
  1491  	ctxt.Out.SeekSet(int64(uint64(datsect.pointerToRawData) + ftbase))
  1492  	for d := dr; d != nil; d = d.next {
  1493  		for m := d.ms; m != nil; m = m.next {
  1494  			if pe64 {
  1495  				ctxt.Out.Write64(m.off)
  1496  			} else {
  1497  				ctxt.Out.Write32(uint32(m.off))
  1498  			}
  1499  		}
  1500  
  1501  		if pe64 {
  1502  			ctxt.Out.Write64(0)
  1503  		} else {
  1504  			ctxt.Out.Write32(0)
  1505  		}
  1506  	}
  1507  
  1508  	// finally write import descriptor table
  1509  	out := ctxt.Out
  1510  	out.SeekSet(startoff)
  1511  
  1512  	for d := dr; d != nil; d = d.next {
  1513  		out.Write32(uint32(uint64(isect.virtualAddress) + oftbase + d.thunkoff))
  1514  		out.Write32(0)
  1515  		out.Write32(0)
  1516  		out.Write32(uint32(uint64(isect.virtualAddress) + d.nameoff))
  1517  		out.Write32(uint32(uint64(datsect.virtualAddress) + ftbase + d.thunkoff))
  1518  	}
  1519  
  1520  	out.Write32(0) //end
  1521  	out.Write32(0)
  1522  	out.Write32(0)
  1523  	out.Write32(0)
  1524  	out.Write32(0)
  1525  
  1526  	// update data directory
  1527  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.virtualAddress
  1528  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.virtualSize
  1529  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(ldr.SymValue(dynamic) - PEBASE)
  1530  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(ldr.SymSize(dynamic))
  1531  
  1532  	out.SeekSet(endoff)
  1533  }
  1534  
  1535  func initdynexport(ctxt *Link) {
  1536  	ldr := ctxt.loader
  1537  	for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
  1538  		if !ldr.AttrReachable(s) || !ldr.AttrCgoExportDynamic(s) {
  1539  			continue
  1540  		}
  1541  		if len(dexport) >= math.MaxUint16 {
  1542  			ctxt.Errorf(s, "pe dynexport table is full")
  1543  			errorexit()
  1544  		}
  1545  
  1546  		dexport = append(dexport, s)
  1547  	}
  1548  
  1549  	sort.Slice(dexport, func(i, j int) bool { return ldr.SymExtname(dexport[i]) < ldr.SymExtname(dexport[j]) })
  1550  }
  1551  
  1552  func addexports(ctxt *Link) {
  1553  	ldr := ctxt.loader
  1554  	var e IMAGE_EXPORT_DIRECTORY
  1555  
  1556  	nexport := len(dexport)
  1557  	size := binary.Size(&e) + 10*nexport + len(*flagOutfile) + 1
  1558  	for _, s := range dexport {
  1559  		size += len(ldr.SymExtname(s)) + 1
  1560  	}
  1561  
  1562  	if nexport == 0 {
  1563  		return
  1564  	}
  1565  
  1566  	sect := pefile.addSection(".edata", size, size)
  1567  	sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
  1568  	sect.checkOffset(ctxt.Out.Offset())
  1569  	va := int(sect.virtualAddress)
  1570  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = uint32(va)
  1571  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect.virtualSize
  1572  
  1573  	vaName := va + binary.Size(&e) + nexport*4
  1574  	vaAddr := va + binary.Size(&e)
  1575  	vaNa := va + binary.Size(&e) + nexport*8
  1576  
  1577  	e.Characteristics = 0
  1578  	e.MajorVersion = 0
  1579  	e.MinorVersion = 0
  1580  	e.NumberOfFunctions = uint32(nexport)
  1581  	e.NumberOfNames = uint32(nexport)
  1582  	e.Name = uint32(va+binary.Size(&e)) + uint32(nexport)*10 // Program names.
  1583  	e.Base = 1
  1584  	e.AddressOfFunctions = uint32(vaAddr)
  1585  	e.AddressOfNames = uint32(vaName)
  1586  	e.AddressOfNameOrdinals = uint32(vaNa)
  1587  
  1588  	out := ctxt.Out
  1589  
  1590  	// put IMAGE_EXPORT_DIRECTORY
  1591  	binary.Write(out, binary.LittleEndian, &e)
  1592  
  1593  	// put EXPORT Address Table
  1594  	for _, s := range dexport {
  1595  		out.Write32(uint32(ldr.SymValue(s) - PEBASE))
  1596  	}
  1597  
  1598  	// put EXPORT Name Pointer Table
  1599  	v := int(e.Name + uint32(len(*flagOutfile)) + 1)
  1600  
  1601  	for _, s := range dexport {
  1602  		out.Write32(uint32(v))
  1603  		v += len(ldr.SymExtname(s)) + 1
  1604  	}
  1605  
  1606  	// put EXPORT Ordinal Table
  1607  	for i := 0; i < nexport; i++ {
  1608  		out.Write16(uint16(i))
  1609  	}
  1610  
  1611  	// put Names
  1612  	out.WriteStringN(*flagOutfile, len(*flagOutfile)+1)
  1613  
  1614  	for _, s := range dexport {
  1615  		name := ldr.SymExtname(s)
  1616  		out.WriteStringN(name, len(name)+1)
  1617  	}
  1618  	sect.pad(out, uint32(size))
  1619  }
  1620  
  1621  // peBaseRelocEntry represents a single relocation entry.
  1622  type peBaseRelocEntry struct {
  1623  	typeOff uint16
  1624  }
  1625  
  1626  // peBaseRelocBlock represents a Base Relocation Block. A block
  1627  // is a collection of relocation entries in a page, where each
  1628  // entry describes a single relocation.
  1629  // The block page RVA (Relative Virtual Address) is the index
  1630  // into peBaseRelocTable.blocks.
  1631  type peBaseRelocBlock struct {
  1632  	entries []peBaseRelocEntry
  1633  }
  1634  
  1635  // pePages is a type used to store the list of pages for which there
  1636  // are base relocation blocks. This is defined as a type so that
  1637  // it can be sorted.
  1638  type pePages []uint32
  1639  
  1640  // A PE base relocation table is a list of blocks, where each block
  1641  // contains relocation information for a single page. The blocks
  1642  // must be emitted in order of page virtual address.
  1643  // See https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-reloc-section-image-only
  1644  type peBaseRelocTable struct {
  1645  	blocks map[uint32]peBaseRelocBlock
  1646  
  1647  	// pePages is a list of keys into blocks map.
  1648  	// It is stored separately for ease of sorting.
  1649  	pages pePages
  1650  }
  1651  
  1652  func (rt *peBaseRelocTable) init(ctxt *Link) {
  1653  	rt.blocks = make(map[uint32]peBaseRelocBlock)
  1654  }
  1655  
  1656  func (rt *peBaseRelocTable) addentry(ldr *loader.Loader, s loader.Sym, r *loader.Reloc) {
  1657  	// pageSize is the size in bytes of a page
  1658  	// described by a base relocation block.
  1659  	const pageSize = 0x1000
  1660  	const pageMask = pageSize - 1
  1661  
  1662  	addr := ldr.SymValue(s) + int64(r.Off()) - PEBASE
  1663  	page := uint32(addr &^ pageMask)
  1664  	off := uint32(addr & pageMask)
  1665  
  1666  	b, ok := rt.blocks[page]
  1667  	if !ok {
  1668  		rt.pages = append(rt.pages, page)
  1669  	}
  1670  
  1671  	e := peBaseRelocEntry{
  1672  		typeOff: uint16(off & 0xFFF),
  1673  	}
  1674  
  1675  	// Set entry type
  1676  	switch r.Siz() {
  1677  	default:
  1678  		Exitf("unsupported relocation size %d\n", r.Siz)
  1679  	case 4:
  1680  		e.typeOff |= uint16(IMAGE_REL_BASED_HIGHLOW << 12)
  1681  	case 8:
  1682  		e.typeOff |= uint16(IMAGE_REL_BASED_DIR64 << 12)
  1683  	}
  1684  
  1685  	b.entries = append(b.entries, e)
  1686  	rt.blocks[page] = b
  1687  }
  1688  
  1689  func (rt *peBaseRelocTable) write(ctxt *Link) {
  1690  	out := ctxt.Out
  1691  
  1692  	// sort the pages array
  1693  	slices.Sort(rt.pages)
  1694  
  1695  	// .reloc section must be 32-bit aligned
  1696  	if out.Offset()&3 != 0 {
  1697  		Errorf("internal error, start of .reloc not 32-bit aligned")
  1698  	}
  1699  
  1700  	for _, p := range rt.pages {
  1701  		b := rt.blocks[p]
  1702  
  1703  		// Add a dummy entry at the end of the list if we have an
  1704  		// odd number of entries, so as to ensure that the next
  1705  		// block starts on a 32-bit boundary (see issue 68260).
  1706  		if len(b.entries)&1 != 0 {
  1707  			b.entries = append(b.entries, peBaseRelocEntry{})
  1708  		}
  1709  
  1710  		const sizeOfPEbaseRelocBlock = 8 // 2 * sizeof(uint32)
  1711  		blockSize := uint32(sizeOfPEbaseRelocBlock + len(b.entries)*2)
  1712  		out.Write32(p)
  1713  		out.Write32(blockSize)
  1714  
  1715  		for _, e := range b.entries {
  1716  			out.Write16(e.typeOff)
  1717  		}
  1718  	}
  1719  }
  1720  
  1721  func addPEBaseRelocSym(ldr *loader.Loader, s loader.Sym, rt *peBaseRelocTable) {
  1722  	relocs := ldr.Relocs(s)
  1723  	for ri := 0; ri < relocs.Count(); ri++ {
  1724  		r := relocs.At(ri)
  1725  		if r.Type() >= objabi.ElfRelocOffset {
  1726  			continue
  1727  		}
  1728  		if r.Siz() == 0 { // informational relocation
  1729  			continue
  1730  		}
  1731  		rs := r.Sym()
  1732  		if rs == 0 {
  1733  			continue
  1734  		}
  1735  		if !ldr.AttrReachable(s) {
  1736  			continue
  1737  		}
  1738  
  1739  		switch r.Type() {
  1740  		default:
  1741  		case objabi.R_ADDR:
  1742  			rt.addentry(ldr, s, &r)
  1743  		}
  1744  	}
  1745  }
  1746  
  1747  func needPEBaseReloc(ctxt *Link) bool {
  1748  	// Non-PIE x86 binaries don't need the base relocation table.
  1749  	// Everyone else does.
  1750  	if (ctxt.Arch.Family == sys.I386 || ctxt.Arch.Family == sys.AMD64) && ctxt.BuildMode != BuildModePIE {
  1751  		return false
  1752  	}
  1753  	return true
  1754  }
  1755  
  1756  func addPEBaseReloc(ctxt *Link) {
  1757  	if !needPEBaseReloc(ctxt) {
  1758  		return
  1759  	}
  1760  
  1761  	var rt peBaseRelocTable
  1762  	rt.init(ctxt)
  1763  
  1764  	// Get relocation information
  1765  	ldr := ctxt.loader
  1766  	for _, s := range ctxt.Textp {
  1767  		addPEBaseRelocSym(ldr, s, &rt)
  1768  	}
  1769  	for _, s := range ctxt.datap {
  1770  		addPEBaseRelocSym(ldr, s, &rt)
  1771  	}
  1772  
  1773  	// Write relocation information
  1774  	startoff := ctxt.Out.Offset()
  1775  	rt.write(ctxt)
  1776  	size := ctxt.Out.Offset() - startoff
  1777  
  1778  	// Add a PE section and pad it at the end
  1779  	rsect := pefile.addSection(".reloc", int(size), int(size))
  1780  	rsect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
  1781  	rsect.checkOffset(startoff)
  1782  	rsect.pad(ctxt.Out, uint32(size))
  1783  
  1784  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = rsect.virtualAddress
  1785  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = rsect.virtualSize
  1786  }
  1787  
  1788  func (ctxt *Link) dope() {
  1789  	initdynimport(ctxt)
  1790  	initdynexport(ctxt)
  1791  }
  1792  
  1793  func setpersrc(ctxt *Link, syms []loader.Sym) {
  1794  	if len(rsrcsyms) != 0 {
  1795  		Errorf("too many .rsrc sections")
  1796  	}
  1797  	rsrcsyms = syms
  1798  }
  1799  
  1800  func addpersrc(ctxt *Link) {
  1801  	if len(rsrcsyms) == 0 {
  1802  		return
  1803  	}
  1804  
  1805  	var size int64
  1806  	for _, rsrcsym := range rsrcsyms {
  1807  		size += ctxt.loader.SymSize(rsrcsym)
  1808  	}
  1809  	h := pefile.addSection(".rsrc", int(size), int(size))
  1810  	h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA
  1811  	h.checkOffset(ctxt.Out.Offset())
  1812  
  1813  	for _, rsrcsym := range rsrcsyms {
  1814  		// A split resource happens when the actual resource data and its relocations are
  1815  		// split across multiple sections, denoted by a $01 or $02 at the end of the .rsrc
  1816  		// section name.
  1817  		splitResources := strings.Contains(ctxt.loader.SymName(rsrcsym), ".rsrc$")
  1818  		relocs := ctxt.loader.Relocs(rsrcsym)
  1819  		data := ctxt.loader.Data(rsrcsym)
  1820  		for ri := 0; ri < relocs.Count(); ri++ {
  1821  			r := relocs.At(ri)
  1822  			p := data[r.Off():]
  1823  			val := uint32(int64(h.virtualAddress) + r.Add())
  1824  			if splitResources {
  1825  				// If we're a split resource section, and that section has relocation
  1826  				// symbols, then the data that it points to doesn't actually begin at
  1827  				// the virtual address listed in this current section, but rather
  1828  				// begins at the section immediately after this one. So, in order to
  1829  				// calculate the proper virtual address of the data it's pointing to,
  1830  				// we have to add the length of this section to the virtual address.
  1831  				// This works because .rsrc sections are divided into two (but not more)
  1832  				// of these sections.
  1833  				val += uint32(len(data))
  1834  			}
  1835  			binary.LittleEndian.PutUint32(p, val)
  1836  		}
  1837  		ctxt.Out.Write(data)
  1838  	}
  1839  	h.pad(ctxt.Out, uint32(size))
  1840  
  1841  	// update data directory
  1842  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress
  1843  	pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize
  1844  }
  1845  
  1846  func asmbPe(ctxt *Link) {
  1847  	t := pefile.addSection(".text", int(Segtext.Length), int(Segtext.Length))
  1848  	t.characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
  1849  	if ctxt.LinkMode == LinkExternal {
  1850  		// some data symbols (e.g. masks) end up in the .text section, and they normally
  1851  		// expect larger alignment requirement than the default text section alignment.
  1852  		t.characteristics |= IMAGE_SCN_ALIGN_32BYTES
  1853  	}
  1854  	t.checkSegment(&Segtext)
  1855  	pefile.textSect = t
  1856  
  1857  	ro := pefile.addSection(".rdata", int(Segrodata.Length), int(Segrodata.Length))
  1858  	ro.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
  1859  	if ctxt.LinkMode == LinkExternal {
  1860  		// some data symbols (e.g. masks) end up in the .rdata section, and they normally
  1861  		// expect larger alignment requirement than the default text section alignment.
  1862  		ro.characteristics |= IMAGE_SCN_ALIGN_32BYTES
  1863  	}
  1864  	ro.checkSegment(&Segrodata)
  1865  	pefile.rdataSect = ro
  1866  
  1867  	// This should have been added in Peinit and by now is part of the
  1868  	// just-written .rdata section.
  1869  	s := ctxt.loader.Lookup("_load_config_used", 0)
  1870  	if s != 0 {
  1871  		pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].VirtualAddress = uint32(ctxt.loader.SymValue(s) - PEBASE)
  1872  		pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG].Size = uint32(ctxt.loader.SymSize(s))
  1873  	}
  1874  
  1875  	var d *peSection
  1876  	if ctxt.LinkMode != LinkExternal {
  1877  		d = pefile.addSection(".data", int(Segdata.Length), int(Segdata.Filelen))
  1878  		d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
  1879  		d.checkSegment(&Segdata)
  1880  		pefile.dataSect = d
  1881  	} else {
  1882  		d = pefile.addSection(".data", int(Segdata.Filelen), int(Segdata.Filelen))
  1883  		d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
  1884  		d.checkSegment(&Segdata)
  1885  		pefile.dataSect = d
  1886  
  1887  		b := pefile.addSection(".bss", int(Segdata.Length-Segdata.Filelen), 0)
  1888  		b.characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
  1889  		b.pointerToRawData = 0
  1890  		pefile.bssSect = b
  1891  	}
  1892  
  1893  	pefile.addSEH(ctxt)
  1894  	pefile.addDWARF()
  1895  
  1896  	if ctxt.LinkMode == LinkExternal {
  1897  		pefile.ctorsSect = pefile.addInitArray(ctxt)
  1898  	}
  1899  
  1900  	ctxt.Out.SeekSet(int64(pefile.nextFileOffset))
  1901  	if ctxt.LinkMode != LinkExternal {
  1902  		addimports(ctxt, d)
  1903  		addexports(ctxt)
  1904  		addPEBaseReloc(ctxt)
  1905  	}
  1906  	pefile.writeSymbolTableAndStringTable(ctxt)
  1907  	addpersrc(ctxt)
  1908  	if ctxt.LinkMode == LinkExternal {
  1909  		pefile.emitRelocations(ctxt)
  1910  	}
  1911  
  1912  	pewrite(ctxt)
  1913  }
  1914  
  1915  // peCreateExportFile creates a file with exported symbols for Windows .def files.
  1916  // ld will export all symbols, even those not marked for export, unless a .def file is provided.
  1917  func peCreateExportFile(ctxt *Link, libName string) (fname string) {
  1918  	fname = filepath.Join(*flagTmpdir, "export_file.def")
  1919  	var buf bytes.Buffer
  1920  
  1921  	if ctxt.BuildMode == BuildModeCShared {
  1922  		fmt.Fprintf(&buf, "LIBRARY %s\n", libName)
  1923  	}
  1924  	buf.WriteString("EXPORTS\n")
  1925  
  1926  	ldr := ctxt.loader
  1927  	var exports []string
  1928  	for s := range ldr.ForAllCgoExportStatic() {
  1929  		extname := ldr.SymExtname(s)
  1930  		if !strings.HasPrefix(extname, "_cgoexp_") {
  1931  			continue
  1932  		}
  1933  		if ldr.IsFileLocal(s) {
  1934  			continue // Only export non-static symbols
  1935  		}
  1936  		// Retrieve the name of the initial symbol
  1937  		// exported by cgo.
  1938  		// The corresponding Go symbol is:
  1939  		// _cgoexp_hashcode_symname.
  1940  		name := strings.SplitN(extname, "_", 4)[3]
  1941  		exports = append(exports, name)
  1942  	}
  1943  	if len(exports) == 0 {
  1944  		// See runtime/cgo/windows.go for details.
  1945  		exports = append(exports, "_cgo_stub_export")
  1946  	}
  1947  	sort.Strings(exports)
  1948  	buf.WriteString(strings.Join(exports, "\n"))
  1949  
  1950  	err := os.WriteFile(fname, buf.Bytes(), 0666)
  1951  	if err != nil {
  1952  		Errorf("WriteFile %s failed: %v", fname, err)
  1953  	}
  1954  
  1955  	return fname
  1956  }
  1957  

View as plain text