Source file src/pkg/cmd/link/internal/ld/pe.go
1
2
3
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
47
48 PESECTALIGN int64 = 0x1000
49
50
51
52
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
99 const (
100
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
128
129
130
131
132
133
134
135
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
293 type peStringTable struct {
294 strings []string
295 stringsLen int
296 }
297
298
299 func (t *peStringTable) size() int {
300
301 return t.stringsLen + 4
302 }
303
304
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
309 return off
310 }
311
312
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
322 type peSection struct {
323 name string
324 shortName string
325 index int
326 virtualSize uint32
327 virtualAddress uint32
328 sizeOfRawData uint32
329 pointerToRawData uint32
330 pointerToRelocations uint32
331 numberOfRelocations uint16
332 characteristics uint32
333 }
334
335
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
344
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
357
358
359 func (sect *peSection) pad(out *OutBuf, n uint32) {
360 out.WriteStringN("", int(sect.sizeOfRawData-n))
361 }
362
363
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
381
382
383
384 func (sect *peSection) emitRelocations(out *OutBuf, relocfn func() int) {
385 sect.pointerToRelocations = uint32(out.Offset())
386
387 out.Write32(0)
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
402 }
403 sect.numberOfRelocations = uint16(n - 1)
404 }
405
406
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
418 symbolCount int
419 dataDirectory [16]pe.DataDirectory
420 }
421
422
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
442
443
444 func (f *peFile) addDWARFSection(name string, size int) *peSection {
445 if size == 0 {
446 Exitf("DWARF section %q is empty", name)
447 }
448
449
450
451
452
453
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
462 func (f *peFile) addDWARF() {
463 if *FlagS {
464 return
465 }
466 if *FlagW {
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
479 func (f *peFile) addInitArray(ctxt *Link) *peSection {
480
481
482
483
484
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
514 func (f *peFile) emitRelocations(ctxt *Link) {
515 for ctxt.Out.Offset()&7 != 0 {
516 ctxt.Out.Write8(0)
517 }
518
519
520
521 relocsect := func(sect *sym.Section, syms []*sym.Symbol, base uint64) int {
522
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
618
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)
631
632 s.Dynid = int32(f.symbolCount)
633
634 f.symbolCount++
635 }
636
637
638
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
660
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
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
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
695 typ = IMAGE_SYM_DTYPE_ARRAY<<8 + IMAGE_SYM_TYPE_STRUCT
696 typ = 0x0308
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
715
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
726 func (f *peFile) writeSymbolTableAndStringTable(ctxt *Link) {
727 f.symtabOffset = ctxt.Out.Offset()
728
729
730 if !*FlagS || ctxt.LinkMode == LinkExternal {
731 f.writeSymbols(ctxt)
732 }
733
734
735 size := f.stringTable.size() + 18*f.symbolCount
736 var h *peSection
737 if ctxt.LinkMode != LinkExternal {
738
739
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
746 f.stringTable.write(ctxt.Out)
747 if ctxt.LinkMode != LinkExternal {
748 h.pad(ctxt.Out, uint32(size))
749 }
750 }
751
752
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
770
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
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
808 } else {
809 oh.Magic = 0x10b
810 oh.BaseOfData = f.dataSect.virtualAddress
811 }
812
813
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
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892 oh64.SizeOfStackReserve = 0x00200000
893 if !iscgo {
894 oh64.SizeOfStackCommit = 0x00001000
895 } else {
896
897
898
899 oh64.SizeOfStackCommit = 0x00200000 - 0x2000
900 }
901
902 oh.SizeOfStackReserve = 0x00100000
903 if !iscgo {
904 oh.SizeOfStackCommit = 0x00001000
905 } else {
906 oh.SizeOfStackCommit = 0x00100000 - 0x2000
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
936 case sys.AMD64:
937 pe64 = 1
938 var oh64 pe.OptionalHeader64
939 l = binary.Size(&oh64)
940
941
942 default:
943 var oh pe.OptionalHeader32
944 l = binary.Size(&oh)
945
946 }
947
948 if ctxt.LinkMode == LinkExternal {
949
950
951
952
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
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
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
1033
1034
1035
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
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
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
1096
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
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
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
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)
1130 strput(ctxt.Out, m.s.Extname())
1131 }
1132 }
1133
1134
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
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
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
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)
1197 out.Write32(0)
1198 out.Write32(0)
1199 out.Write32(0)
1200 out.Write32(0)
1201
1202
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
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
1272 binary.Write(out, binary.LittleEndian, &e)
1273
1274
1275 for i := 0; i < nexport; i++ {
1276 out.Write32(uint32(dexport[i].Value - PEBASE))
1277 }
1278
1279
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
1288 for i := 0; i < nexport; i++ {
1289 out.Write16(uint16(i))
1290 }
1291
1292
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
1302 type peBaseRelocEntry struct {
1303 typeOff uint16
1304 rel *sym.Reloc
1305 sym *sym.Symbol
1306 }
1307
1308
1309
1310
1311
1312
1313 type peBaseRelocBlock struct {
1314 entries []peBaseRelocEntry
1315 }
1316
1317
1318
1319
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
1327
1328
1329
1330 type peBaseRelocTable struct {
1331 blocks map[uint32]peBaseRelocBlock
1332
1333
1334
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
1344
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
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
1379 sort.Sort(rt.pages)
1380
1381 for _, p := range rt.pages {
1382 b := rt.blocks[p]
1383 const sizeOfPEbaseRelocBlock = 8
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 {
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
1424
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
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
1443 startoff := ctxt.Out.Offset()
1444 rt.write(ctxt)
1445 size := ctxt.Out.Offset() - startoff
1446
1447
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
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
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
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
1513
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
1523
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