...

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

View as plain text