Help us shape the future of Go! Take the 2026 Go Developer Survey

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

View as plain text