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