1
2
3
4
5
6
7
8 package ld
9
10 import (
11 "cmd/internal/objabi"
12 "cmd/internal/sys"
13 "cmd/link/internal/loader"
14 "cmd/link/internal/sym"
15 "debug/pe"
16 "encoding/binary"
17 "fmt"
18 "internal/buildcfg"
19 "sort"
20 "strconv"
21 "strings"
22 )
23
24 type IMAGE_IMPORT_DESCRIPTOR struct {
25 OriginalFirstThunk uint32
26 TimeDateStamp uint32
27 ForwarderChain uint32
28 Name uint32
29 FirstThunk uint32
30 }
31
32 type IMAGE_EXPORT_DIRECTORY struct {
33 Characteristics uint32
34 TimeDateStamp uint32
35 MajorVersion uint16
36 MinorVersion uint16
37 Name uint32
38 Base uint32
39 NumberOfFunctions uint32
40 NumberOfNames uint32
41 AddressOfFunctions uint32
42 AddressOfNames uint32
43 AddressOfNameOrdinals uint32
44 }
45
46 var (
47
48
49 PEBASE int64
50
51
52
53 PESECTALIGN int64 = 0x1000
54
55
56
57
58 PEFILEALIGN int64 = 2 << 8
59 )
60
61 const (
62 IMAGE_SCN_CNT_CODE = 0x00000020
63 IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040
64 IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
65 IMAGE_SCN_LNK_OTHER = 0x00000100
66 IMAGE_SCN_LNK_INFO = 0x00000200
67 IMAGE_SCN_LNK_REMOVE = 0x00000800
68 IMAGE_SCN_LNK_COMDAT = 0x00001000
69 IMAGE_SCN_GPREL = 0x00008000
70 IMAGE_SCN_MEM_PURGEABLE = 0x00020000
71 IMAGE_SCN_MEM_16BIT = 0x00020000
72 IMAGE_SCN_MEM_LOCKED = 0x00040000
73 IMAGE_SCN_MEM_PRELOAD = 0x00080000
74 IMAGE_SCN_ALIGN_1BYTES = 0x00100000
75 IMAGE_SCN_ALIGN_2BYTES = 0x00200000
76 IMAGE_SCN_ALIGN_4BYTES = 0x00300000
77 IMAGE_SCN_ALIGN_8BYTES = 0x00400000
78 IMAGE_SCN_ALIGN_16BYTES = 0x00500000
79 IMAGE_SCN_ALIGN_32BYTES = 0x00600000
80 IMAGE_SCN_ALIGN_64BYTES = 0x00700000
81 IMAGE_SCN_ALIGN_128BYTES = 0x00800000
82 IMAGE_SCN_ALIGN_256BYTES = 0x00900000
83 IMAGE_SCN_ALIGN_512BYTES = 0x00A00000
84 IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000
85 IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000
86 IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000
87 IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000
88 IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000
89 IMAGE_SCN_MEM_DISCARDABLE = 0x02000000
90 IMAGE_SCN_MEM_NOT_CACHED = 0x04000000
91 IMAGE_SCN_MEM_NOT_PAGED = 0x08000000
92 IMAGE_SCN_MEM_SHARED = 0x10000000
93 IMAGE_SCN_MEM_EXECUTE = 0x20000000
94 IMAGE_SCN_MEM_READ = 0x40000000
95 IMAGE_SCN_MEM_WRITE = 0x80000000
96 )
97
98
99
100 const (
101 IMAGE_SYM_TYPE_NULL = 0
102 IMAGE_SYM_TYPE_STRUCT = 8
103 IMAGE_SYM_DTYPE_FUNCTION = 2
104 IMAGE_SYM_DTYPE_ARRAY = 3
105 IMAGE_SYM_CLASS_EXTERNAL = 2
106 IMAGE_SYM_CLASS_STATIC = 3
107
108 IMAGE_REL_I386_DIR32 = 0x0006
109 IMAGE_REL_I386_DIR32NB = 0x0007
110 IMAGE_REL_I386_SECREL = 0x000B
111 IMAGE_REL_I386_REL32 = 0x0014
112
113 IMAGE_REL_AMD64_ADDR64 = 0x0001
114 IMAGE_REL_AMD64_ADDR32 = 0x0002
115 IMAGE_REL_AMD64_ADDR32NB = 0x0003
116 IMAGE_REL_AMD64_REL32 = 0x0004
117 IMAGE_REL_AMD64_SECREL = 0x000B
118
119 IMAGE_REL_ARM_ABSOLUTE = 0x0000
120 IMAGE_REL_ARM_ADDR32 = 0x0001
121 IMAGE_REL_ARM_ADDR32NB = 0x0002
122 IMAGE_REL_ARM_BRANCH24 = 0x0003
123 IMAGE_REL_ARM_BRANCH11 = 0x0004
124 IMAGE_REL_ARM_SECREL = 0x000F
125
126 IMAGE_REL_ARM64_ABSOLUTE = 0x0000
127 IMAGE_REL_ARM64_ADDR32 = 0x0001
128 IMAGE_REL_ARM64_ADDR32NB = 0x0002
129 IMAGE_REL_ARM64_BRANCH26 = 0x0003
130 IMAGE_REL_ARM64_PAGEBASE_REL21 = 0x0004
131 IMAGE_REL_ARM64_REL21 = 0x0005
132 IMAGE_REL_ARM64_PAGEOFFSET_12A = 0x0006
133 IMAGE_REL_ARM64_PAGEOFFSET_12L = 0x0007
134 IMAGE_REL_ARM64_SECREL = 0x0008
135 IMAGE_REL_ARM64_SECREL_LOW12A = 0x0009
136 IMAGE_REL_ARM64_SECREL_HIGH12A = 0x000A
137 IMAGE_REL_ARM64_SECREL_LOW12L = 0x000B
138 IMAGE_REL_ARM64_TOKEN = 0x000C
139 IMAGE_REL_ARM64_SECTION = 0x000D
140 IMAGE_REL_ARM64_ADDR64 = 0x000E
141 IMAGE_REL_ARM64_BRANCH19 = 0x000F
142 IMAGE_REL_ARM64_BRANCH14 = 0x0010
143 IMAGE_REL_ARM64_REL32 = 0x0011
144
145 IMAGE_REL_BASED_HIGHLOW = 3
146 IMAGE_REL_BASED_DIR64 = 10
147 )
148
149 const (
150 PeMinimumTargetMajorVersion = 6
151 PeMinimumTargetMinorVersion = 1
152 )
153
154
155
156
157 var dosstub = []uint8{
158 0x4d,
159 0x5a,
160 0x90,
161 0x00,
162 0x03,
163 0x00,
164 0x00,
165 0x00,
166 0x04,
167 0x00,
168 0x00,
169 0x00,
170 0xff,
171 0xff,
172 0x00,
173 0x00,
174 0x8b,
175 0x00,
176 0x00,
177 0x00,
178 0x00,
179 0x00,
180 0x00,
181 0x00,
182 0x40,
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 0x00,
198 0x00,
199 0x00,
200 0x00,
201 0x00,
202 0x00,
203 0x00,
204 0x00,
205 0x00,
206 0x00,
207 0x00,
208 0x00,
209 0x00,
210 0x00,
211 0x00,
212 0x00,
213 0x00,
214 0x00,
215 0x00,
216 0x00,
217 0x00,
218 0x80,
219 0x00,
220 0x00,
221 0x00,
222 0x0e,
223 0x1f,
224 0xba,
225 0x0e,
226 0x00,
227 0xb4,
228 0x09,
229 0xcd,
230 0x21,
231 0xb8,
232 0x01,
233 0x4c,
234 0xcd,
235 0x21,
236 0x54,
237 0x68,
238 0x69,
239 0x73,
240 0x20,
241 0x70,
242 0x72,
243 0x6f,
244 0x67,
245 0x72,
246 0x61,
247 0x6d,
248 0x20,
249 0x63,
250 0x61,
251 0x6e,
252 0x6e,
253 0x6f,
254 0x74,
255 0x20,
256 0x62,
257 0x65,
258 0x20,
259 0x72,
260 0x75,
261 0x6e,
262 0x20,
263 0x69,
264 0x6e,
265 0x20,
266 0x44,
267 0x4f,
268 0x53,
269 0x20,
270 0x6d,
271 0x6f,
272 0x64,
273 0x65,
274 0x2e,
275 0x0d,
276 0x0d,
277 0x0a,
278 0x24,
279 0x00,
280 0x00,
281 0x00,
282 0x00,
283 0x00,
284 0x00,
285 0x00,
286 }
287
288 type Imp struct {
289 s loader.Sym
290 off uint64
291 next *Imp
292 argsize int
293 }
294
295 type Dll struct {
296 name string
297 nameoff uint64
298 thunkoff uint64
299 ms *Imp
300 next *Dll
301 }
302
303 var (
304 rsrcsyms []loader.Sym
305 PESECTHEADR int32
306 PEFILEHEADR int32
307 pe64 int
308 dr *Dll
309
310 dexport = make([]loader.Sym, 0, 1024)
311 )
312
313
314 type peStringTable struct {
315 strings []string
316 stringsLen int
317 }
318
319
320 func (t *peStringTable) size() int {
321
322 return t.stringsLen + 4
323 }
324
325
326 func (t *peStringTable) add(str string) int {
327 off := t.size()
328 t.strings = append(t.strings, str)
329 t.stringsLen += len(str) + 1
330 return off
331 }
332
333
334 func (t *peStringTable) write(out *OutBuf) {
335 out.Write32(uint32(t.size()))
336 for _, s := range t.strings {
337 out.WriteString(s)
338 out.Write8(0)
339 }
340 }
341
342
343 type peSection struct {
344 name string
345 shortName string
346 index int
347 virtualSize uint32
348 virtualAddress uint32
349 sizeOfRawData uint32
350 pointerToRawData uint32
351 pointerToRelocations uint32
352 numberOfRelocations uint16
353 characteristics uint32
354 }
355
356
357 func (sect *peSection) checkOffset(off int64) {
358 if off != int64(sect.pointerToRawData) {
359 Errorf(nil, "%s.PointerToRawData = %#x, want %#x", sect.name, uint64(int64(sect.pointerToRawData)), uint64(off))
360 errorexit()
361 }
362 }
363
364
365
366 func (sect *peSection) checkSegment(seg *sym.Segment) {
367 if seg.Vaddr-uint64(PEBASE) != uint64(sect.virtualAddress) {
368 Errorf(nil, "%s.VirtualAddress = %#x, want %#x", sect.name, uint64(int64(sect.virtualAddress)), uint64(int64(seg.Vaddr-uint64(PEBASE))))
369 errorexit()
370 }
371 if seg.Fileoff != uint64(sect.pointerToRawData) {
372 Errorf(nil, "%s.PointerToRawData = %#x, want %#x", sect.name, uint64(int64(sect.pointerToRawData)), uint64(int64(seg.Fileoff)))
373 errorexit()
374 }
375 }
376
377
378
379
380 func (sect *peSection) pad(out *OutBuf, n uint32) {
381 out.WriteStringN("", int(sect.sizeOfRawData-n))
382 }
383
384
385 func (sect *peSection) write(out *OutBuf, linkmode LinkMode) error {
386 h := pe.SectionHeader32{
387 VirtualSize: sect.virtualSize,
388 SizeOfRawData: sect.sizeOfRawData,
389 PointerToRawData: sect.pointerToRawData,
390 PointerToRelocations: sect.pointerToRelocations,
391 NumberOfRelocations: sect.numberOfRelocations,
392 Characteristics: sect.characteristics,
393 }
394 if linkmode != LinkExternal {
395 h.VirtualAddress = sect.virtualAddress
396 }
397 copy(h.Name[:], sect.shortName)
398 return binary.Write(out, binary.LittleEndian, h)
399 }
400
401
402
403
404
405 func (sect *peSection) emitRelocations(out *OutBuf, relocfn func() int) {
406 sect.pointerToRelocations = uint32(out.Offset())
407
408 out.Write32(0)
409 out.Write32(0)
410 out.Write16(0)
411
412 n := relocfn() + 1
413
414 cpos := out.Offset()
415 out.SeekSet(int64(sect.pointerToRelocations))
416 out.Write32(uint32(n))
417 out.SeekSet(cpos)
418 if n > 0x10000 {
419 n = 0x10000
420 sect.characteristics |= IMAGE_SCN_LNK_NRELOC_OVFL
421 } else {
422 sect.pointerToRelocations += 10
423 }
424 sect.numberOfRelocations = uint16(n - 1)
425 }
426
427
428 type peFile struct {
429 sections []*peSection
430 stringTable peStringTable
431 textSect *peSection
432 rdataSect *peSection
433 dataSect *peSection
434 bssSect *peSection
435 ctorsSect *peSection
436 pdataSect *peSection
437 xdataSect *peSection
438 nextSectOffset uint32
439 nextFileOffset uint32
440 symtabOffset int64
441 symbolCount int
442 dataDirectory [16]pe.DataDirectory
443 }
444
445
446 func (f *peFile) addSection(name string, sectsize int, filesize int) *peSection {
447 sect := &peSection{
448 name: name,
449 shortName: name,
450 index: len(f.sections) + 1,
451 virtualAddress: f.nextSectOffset,
452 pointerToRawData: f.nextFileOffset,
453 }
454 f.nextSectOffset = uint32(Rnd(int64(f.nextSectOffset)+int64(sectsize), PESECTALIGN))
455 if filesize > 0 {
456 sect.virtualSize = uint32(sectsize)
457 sect.sizeOfRawData = uint32(Rnd(int64(filesize), PEFILEALIGN))
458 f.nextFileOffset += sect.sizeOfRawData
459 } else {
460 sect.sizeOfRawData = uint32(sectsize)
461 }
462 f.sections = append(f.sections, sect)
463 return sect
464 }
465
466
467
468
469 func (f *peFile) addDWARFSection(name string, size int) *peSection {
470 if size == 0 {
471 Exitf("DWARF section %q is empty", name)
472 }
473
474
475
476
477
478
479 off := f.stringTable.add(name)
480 h := f.addSection(name, size, size)
481 h.shortName = fmt.Sprintf("/%d", off)
482 h.characteristics = IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_CNT_INITIALIZED_DATA
483 return h
484 }
485
486
487 func (f *peFile) addDWARF() {
488 if *FlagS {
489 return
490 }
491 if *FlagW {
492 return
493 }
494 for _, sect := range Segdwarf.Sections {
495 h := f.addDWARFSection(sect.Name, int(sect.Length))
496 fileoff := sect.Vaddr - Segdwarf.Vaddr + Segdwarf.Fileoff
497 if uint64(h.pointerToRawData) != fileoff {
498 Exitf("%s.PointerToRawData = %#x, want %#x", sect.Name, h.pointerToRawData, fileoff)
499 }
500 }
501 }
502
503
504 func (f *peFile) addSEH(ctxt *Link) {
505
506
507 if Segpdata.Length == 0 {
508 return
509 }
510 d := pefile.addSection(".pdata", int(Segpdata.Length), int(Segpdata.Length))
511 d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
512 if ctxt.LinkMode == LinkExternal {
513
514 d.characteristics |= IMAGE_SCN_ALIGN_4BYTES
515 }
516 pefile.pdataSect = d
517 d.checkSegment(&Segpdata)
518 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = d.virtualAddress
519 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = d.virtualSize
520
521 if Segxdata.Length > 0 {
522 d = pefile.addSection(".xdata", int(Segxdata.Length), int(Segxdata.Length))
523 d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
524 if ctxt.LinkMode == LinkExternal {
525
526 d.characteristics |= IMAGE_SCN_ALIGN_4BYTES
527 }
528 pefile.xdataSect = d
529 d.checkSegment(&Segxdata)
530 }
531 }
532
533
534 func (f *peFile) addInitArray(ctxt *Link) *peSection {
535
536
537
538
539
540 var size int
541 var alignment uint32
542 switch buildcfg.GOARCH {
543 default:
544 Exitf("peFile.addInitArray: unsupported GOARCH=%q\n", buildcfg.GOARCH)
545 case "386", "arm":
546 size = 4
547 alignment = IMAGE_SCN_ALIGN_4BYTES
548 case "amd64", "arm64":
549 size = 8
550 alignment = IMAGE_SCN_ALIGN_8BYTES
551 }
552 sect := f.addSection(".ctors", size, size)
553 sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | alignment
554 sect.sizeOfRawData = uint32(size)
555 ctxt.Out.SeekSet(int64(sect.pointerToRawData))
556 sect.checkOffset(ctxt.Out.Offset())
557
558 init_entry := ctxt.loader.Lookup(*flagEntrySymbol, 0)
559 addr := uint64(ctxt.loader.SymValue(init_entry)) - ctxt.loader.SymSect(init_entry).Vaddr
560 switch buildcfg.GOARCH {
561 case "386", "arm":
562 ctxt.Out.Write32(uint32(addr))
563 case "amd64", "arm64":
564 ctxt.Out.Write64(addr)
565 }
566 return sect
567 }
568
569
570 func (f *peFile) emitRelocations(ctxt *Link) {
571 for ctxt.Out.Offset()&7 != 0 {
572 ctxt.Out.Write8(0)
573 }
574
575 ldr := ctxt.loader
576
577
578
579 relocsect := func(sect *sym.Section, syms []loader.Sym, base uint64) int {
580
581 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen {
582 return 0
583 }
584 sect.Reloff = uint64(ctxt.Out.Offset())
585 for i, s := range syms {
586 if !ldr.AttrReachable(s) {
587 continue
588 }
589 if uint64(ldr.SymValue(s)) >= sect.Vaddr {
590 syms = syms[i:]
591 break
592 }
593 }
594 eaddr := int64(sect.Vaddr + sect.Length)
595 for _, s := range syms {
596 if !ldr.AttrReachable(s) {
597 continue
598 }
599 if ldr.SymValue(s) >= eaddr {
600 break
601 }
602
603
604 relocs := ldr.Relocs(s)
605 for ri := 0; ri < relocs.Count(); ri++ {
606 r := relocs.At(ri)
607 rr, ok := extreloc(ctxt, ldr, s, r)
608 if !ok {
609 continue
610 }
611 if rr.Xsym == 0 {
612 ctxt.Errorf(s, "missing xsym in relocation")
613 continue
614 }
615 if ldr.SymDynid(rr.Xsym) < 0 {
616 ctxt.Errorf(s, "reloc %d to non-coff symbol %s (outer=%s) %d", r.Type(), ldr.SymName(r.Sym()), ldr.SymName(rr.Xsym), ldr.SymType(r.Sym()))
617 }
618 if !thearch.PEreloc1(ctxt.Arch, ctxt.Out, ldr, s, rr, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-base)) {
619 ctxt.Errorf(s, "unsupported obj reloc %v/%d to %s", r.Type(), r.Siz(), ldr.SymName(r.Sym()))
620 }
621 }
622 }
623 sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff
624 const relocLen = 4 + 4 + 2
625 return int(sect.Rellen / relocLen)
626 }
627
628 type relsect struct {
629 peSect *peSection
630 seg *sym.Segment
631 syms []loader.Sym
632 }
633 sects := []relsect{
634 {f.textSect, &Segtext, ctxt.Textp},
635 {f.rdataSect, &Segrodata, ctxt.datap},
636 {f.dataSect, &Segdata, ctxt.datap},
637 }
638 if len(sehp.pdata) != 0 {
639 sects = append(sects, relsect{f.pdataSect, &Segpdata, sehp.pdata})
640 }
641 if len(sehp.xdata) != 0 {
642 sects = append(sects, relsect{f.xdataSect, &Segxdata, sehp.xdata})
643 }
644 for _, s := range sects {
645 s.peSect.emitRelocations(ctxt.Out, func() int {
646 var n int
647 for _, sect := range s.seg.Sections {
648 n += relocsect(sect, s.syms, s.seg.Vaddr)
649 }
650 return n
651 })
652 }
653
654 dwarfLoop:
655 for i := 0; i < len(Segdwarf.Sections); i++ {
656 sect := Segdwarf.Sections[i]
657 si := dwarfp[i]
658 if si.secSym() != loader.Sym(sect.Sym) ||
659 ldr.SymSect(si.secSym()) != sect {
660 panic("inconsistency between dwarfp and Segdwarf")
661 }
662 for _, pesect := range f.sections {
663 if sect.Name == pesect.name {
664 pesect.emitRelocations(ctxt.Out, func() int {
665 return relocsect(sect, si.syms, sect.Vaddr)
666 })
667 continue dwarfLoop
668 }
669 }
670 Errorf(nil, "emitRelocations: could not find %q section", sect.Name)
671 }
672
673 if f.ctorsSect == nil {
674 return
675 }
676
677 f.ctorsSect.emitRelocations(ctxt.Out, func() int {
678 dottext := ldr.Lookup(".text", 0)
679 ctxt.Out.Write32(0)
680 ctxt.Out.Write32(uint32(ldr.SymDynid(dottext)))
681 switch buildcfg.GOARCH {
682 default:
683 ctxt.Errorf(dottext, "unknown architecture for PE: %q\n", buildcfg.GOARCH)
684 case "386":
685 ctxt.Out.Write16(IMAGE_REL_I386_DIR32)
686 case "amd64":
687 ctxt.Out.Write16(IMAGE_REL_AMD64_ADDR64)
688 case "arm":
689 ctxt.Out.Write16(IMAGE_REL_ARM_ADDR32)
690 case "arm64":
691 ctxt.Out.Write16(IMAGE_REL_ARM64_ADDR64)
692 }
693 return 1
694 })
695 }
696
697
698
699 func (f *peFile) writeSymbol(out *OutBuf, ldr *loader.Loader, s loader.Sym, name string, value int64, sectidx int, typ uint16, class uint8) {
700 if len(name) > 8 {
701 out.Write32(0)
702 out.Write32(uint32(f.stringTable.add(name)))
703 } else {
704 out.WriteStringN(name, 8)
705 }
706 out.Write32(uint32(value))
707 out.Write16(uint16(sectidx))
708 out.Write16(typ)
709 out.Write8(class)
710 out.Write8(0)
711
712 ldr.SetSymDynid(s, int32(f.symbolCount))
713
714 f.symbolCount++
715 }
716
717
718
719 func (f *peFile) mapToPESection(ldr *loader.Loader, s loader.Sym, linkmode LinkMode) (pesectidx int, offset int64, err error) {
720 sect := ldr.SymSect(s)
721 if sect == nil {
722 return 0, 0, fmt.Errorf("could not map %s symbol with no section", ldr.SymName(s))
723 }
724 if sect.Seg == &Segtext {
725 return f.textSect.index, int64(uint64(ldr.SymValue(s)) - Segtext.Vaddr), nil
726 }
727 if sect.Seg == &Segrodata {
728 return f.rdataSect.index, int64(uint64(ldr.SymValue(s)) - Segrodata.Vaddr), nil
729 }
730 if sect.Seg != &Segdata {
731 return 0, 0, fmt.Errorf("could not map %s symbol with non .text or .rdata or .data section", ldr.SymName(s))
732 }
733 v := uint64(ldr.SymValue(s)) - Segdata.Vaddr
734 if linkmode != LinkExternal {
735 return f.dataSect.index, int64(v), nil
736 }
737 if ldr.SymType(s) == sym.SDATA {
738 return f.dataSect.index, int64(v), nil
739 }
740
741
742 if v < Segdata.Filelen {
743 return f.dataSect.index, int64(v), nil
744 }
745 return f.bssSect.index, int64(v - Segdata.Filelen), nil
746 }
747
748 var isLabel = make(map[loader.Sym]bool)
749
750 func AddPELabelSym(ldr *loader.Loader, s loader.Sym) {
751 isLabel[s] = true
752 }
753
754
755 func (f *peFile) writeSymbols(ctxt *Link) {
756 ldr := ctxt.loader
757 addsym := func(s loader.Sym) {
758 t := ldr.SymType(s)
759 if ldr.SymSect(s) == nil && t != sym.SDYNIMPORT && t != sym.SHOSTOBJ && t != sym.SUNDEFEXT {
760 return
761 }
762
763 name := ldr.SymName(s)
764
765
766 if ctxt.Is386() && ctxt.IsExternal() &&
767 (t == sym.SHOSTOBJ || t == sym.SUNDEFEXT || ldr.AttrCgoExport(s) ||
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787 name == "go:buildid" || name == "type:*") {
788 name = "_" + name
789 }
790
791 name = mangleABIName(ctxt, ldr, s, name)
792
793 var peSymType uint16 = IMAGE_SYM_TYPE_NULL
794 switch t {
795 case sym.STEXT, sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
796
797
798
799
800
801 peSymType = IMAGE_SYM_DTYPE_FUNCTION<<4 + IMAGE_SYM_TYPE_NULL
802 }
803 sect, value, err := f.mapToPESection(ldr, s, ctxt.LinkMode)
804 if err != nil {
805 switch t {
806 case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
807 default:
808 ctxt.Errorf(s, "addpesym: %v", err)
809 }
810 }
811 class := IMAGE_SYM_CLASS_EXTERNAL
812 if ldr.IsFileLocal(s) || ldr.AttrVisibilityHidden(s) || ldr.AttrLocal(s) {
813 class = IMAGE_SYM_CLASS_STATIC
814 }
815 f.writeSymbol(ctxt.Out, ldr, s, name, value, sect, peSymType, uint8(class))
816 }
817
818 if ctxt.LinkMode == LinkExternal {
819
820
821 for _, pesect := range f.sections {
822 s := ldr.LookupOrCreateSym(pesect.name, 0)
823 f.writeSymbol(ctxt.Out, ldr, s, pesect.name, 0, pesect.index, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_STATIC)
824 }
825 }
826
827
828 s := ldr.Lookup("runtime.text", 0)
829 if ldr.SymType(s) == sym.STEXT {
830 addsym(s)
831 }
832 s = ldr.Lookup("runtime.etext", 0)
833 if ldr.SymType(s) == sym.STEXT {
834 addsym(s)
835 }
836
837
838 for _, s := range ctxt.Textp {
839 addsym(s)
840 }
841
842 shouldBeInSymbolTable := func(s loader.Sym) bool {
843 if ldr.AttrNotInSymbolTable(s) {
844 return false
845 }
846 name := ldr.SymName(s)
847 if name == "" || name[0] == '.' {
848 return false
849 }
850 return true
851 }
852
853
854 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
855 if !ldr.AttrReachable(s) {
856 continue
857 }
858 t := ldr.SymType(s)
859 if t >= sym.SELFRXSECT && t < sym.SXREF {
860 if t == sym.STLSBSS {
861 continue
862 }
863 if !shouldBeInSymbolTable(s) {
864 continue
865 }
866 addsym(s)
867 }
868
869 switch t {
870 case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
871 addsym(s)
872 default:
873 if len(isLabel) > 0 && isLabel[s] {
874 addsym(s)
875 }
876 }
877 }
878 }
879
880
881 func (f *peFile) writeSymbolTableAndStringTable(ctxt *Link) {
882 f.symtabOffset = ctxt.Out.Offset()
883
884
885 if !*FlagS || ctxt.LinkMode == LinkExternal {
886 f.writeSymbols(ctxt)
887 }
888
889
890 size := f.stringTable.size() + 18*f.symbolCount
891 var h *peSection
892 if ctxt.LinkMode != LinkExternal {
893
894
895 h = f.addSection(".symtab", size, size)
896 h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
897 h.checkOffset(f.symtabOffset)
898 }
899
900
901 f.stringTable.write(ctxt.Out)
902 if ctxt.LinkMode != LinkExternal {
903 h.pad(ctxt.Out, uint32(size))
904 }
905 }
906
907
908 func (f *peFile) writeFileHeader(ctxt *Link) {
909 var fh pe.FileHeader
910
911 switch ctxt.Arch.Family {
912 default:
913 Exitf("unknown PE architecture: %v", ctxt.Arch.Family)
914 case sys.AMD64:
915 fh.Machine = pe.IMAGE_FILE_MACHINE_AMD64
916 case sys.I386:
917 fh.Machine = pe.IMAGE_FILE_MACHINE_I386
918 case sys.ARM:
919 fh.Machine = pe.IMAGE_FILE_MACHINE_ARMNT
920 case sys.ARM64:
921 fh.Machine = pe.IMAGE_FILE_MACHINE_ARM64
922 }
923
924 fh.NumberOfSections = uint16(len(f.sections))
925
926
927
928 fh.TimeDateStamp = 0
929
930 if ctxt.LinkMode != LinkExternal {
931 fh.Characteristics = pe.IMAGE_FILE_EXECUTABLE_IMAGE
932 switch ctxt.Arch.Family {
933 case sys.AMD64, sys.I386:
934 if ctxt.BuildMode != BuildModePIE {
935 fh.Characteristics |= pe.IMAGE_FILE_RELOCS_STRIPPED
936 }
937 }
938 }
939 if pe64 != 0 {
940 var oh64 pe.OptionalHeader64
941 fh.SizeOfOptionalHeader = uint16(binary.Size(&oh64))
942 fh.Characteristics |= pe.IMAGE_FILE_LARGE_ADDRESS_AWARE
943 } else {
944 var oh pe.OptionalHeader32
945 fh.SizeOfOptionalHeader = uint16(binary.Size(&oh))
946 fh.Characteristics |= pe.IMAGE_FILE_32BIT_MACHINE
947 }
948
949 fh.PointerToSymbolTable = uint32(f.symtabOffset)
950 fh.NumberOfSymbols = uint32(f.symbolCount)
951
952 binary.Write(ctxt.Out, binary.LittleEndian, &fh)
953 }
954
955
956 func (f *peFile) writeOptionalHeader(ctxt *Link) {
957 var oh pe.OptionalHeader32
958 var oh64 pe.OptionalHeader64
959
960 if pe64 != 0 {
961 oh64.Magic = 0x20b
962 } else {
963 oh.Magic = 0x10b
964 oh.BaseOfData = f.dataSect.virtualAddress
965 }
966
967
968 oh64.MajorLinkerVersion = 3
969 oh.MajorLinkerVersion = 3
970 oh64.MinorLinkerVersion = 0
971 oh.MinorLinkerVersion = 0
972 oh64.SizeOfCode = f.textSect.sizeOfRawData
973 oh.SizeOfCode = f.textSect.sizeOfRawData
974 oh64.SizeOfInitializedData = f.dataSect.sizeOfRawData
975 oh.SizeOfInitializedData = f.dataSect.sizeOfRawData
976 oh64.SizeOfUninitializedData = 0
977 oh.SizeOfUninitializedData = 0
978 if ctxt.LinkMode != LinkExternal {
979 oh64.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
980 oh.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE)
981 }
982 oh64.BaseOfCode = f.textSect.virtualAddress
983 oh.BaseOfCode = f.textSect.virtualAddress
984 oh64.ImageBase = uint64(PEBASE)
985 oh.ImageBase = uint32(PEBASE)
986 oh64.SectionAlignment = uint32(PESECTALIGN)
987 oh.SectionAlignment = uint32(PESECTALIGN)
988 oh64.FileAlignment = uint32(PEFILEALIGN)
989 oh.FileAlignment = uint32(PEFILEALIGN)
990 oh64.MajorOperatingSystemVersion = PeMinimumTargetMajorVersion
991 oh.MajorOperatingSystemVersion = PeMinimumTargetMajorVersion
992 oh64.MinorOperatingSystemVersion = PeMinimumTargetMinorVersion
993 oh.MinorOperatingSystemVersion = PeMinimumTargetMinorVersion
994 oh64.MajorImageVersion = 1
995 oh.MajorImageVersion = 1
996 oh64.MinorImageVersion = 0
997 oh.MinorImageVersion = 0
998 oh64.MajorSubsystemVersion = PeMinimumTargetMajorVersion
999 oh.MajorSubsystemVersion = PeMinimumTargetMajorVersion
1000 oh64.MinorSubsystemVersion = PeMinimumTargetMinorVersion
1001 oh.MinorSubsystemVersion = PeMinimumTargetMinorVersion
1002 oh64.SizeOfImage = f.nextSectOffset
1003 oh.SizeOfImage = f.nextSectOffset
1004 oh64.SizeOfHeaders = uint32(PEFILEHEADR)
1005 oh.SizeOfHeaders = uint32(PEFILEHEADR)
1006 if windowsgui {
1007 oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI
1008 oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_GUI
1009 } else {
1010 oh64.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI
1011 oh.Subsystem = pe.IMAGE_SUBSYSTEM_WINDOWS_CUI
1012 }
1013
1014
1015 oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
1016 oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE
1017
1018
1019 oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT
1020 oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_NX_COMPAT
1021
1022
1023 if needPEBaseReloc(ctxt) {
1024 oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
1025 oh.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
1026 }
1027
1028
1029 if ctxt.BuildMode == BuildModePIE {
1030 oh64.DllCharacteristics |= pe.IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
1031 }
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057 oh64.SizeOfStackReserve = 0x00200000
1058 if !iscgo {
1059 oh64.SizeOfStackCommit = 0x00001000
1060 } else {
1061
1062
1063
1064 oh64.SizeOfStackCommit = 0x00200000 - 0x2000
1065 }
1066
1067 oh.SizeOfStackReserve = 0x00100000
1068 if !iscgo {
1069 oh.SizeOfStackCommit = 0x00001000
1070 } else {
1071 oh.SizeOfStackCommit = 0x00100000 - 0x2000
1072 }
1073
1074 oh64.SizeOfHeapReserve = 0x00100000
1075 oh.SizeOfHeapReserve = 0x00100000
1076 oh64.SizeOfHeapCommit = 0x00001000
1077 oh.SizeOfHeapCommit = 0x00001000
1078 oh64.NumberOfRvaAndSizes = 16
1079 oh.NumberOfRvaAndSizes = 16
1080
1081 if pe64 != 0 {
1082 oh64.DataDirectory = f.dataDirectory
1083 } else {
1084 oh.DataDirectory = f.dataDirectory
1085 }
1086
1087 if pe64 != 0 {
1088 binary.Write(ctxt.Out, binary.LittleEndian, &oh64)
1089 } else {
1090 binary.Write(ctxt.Out, binary.LittleEndian, &oh)
1091 }
1092 }
1093
1094 var pefile peFile
1095
1096 func Peinit(ctxt *Link) {
1097 var l int
1098
1099 if ctxt.Arch.PtrSize == 8 {
1100
1101 pe64 = 1
1102 PEBASE = 1 << 32
1103 if ctxt.Arch.Family == sys.AMD64 {
1104
1105
1106
1107 PEBASE = 1 << 22
1108 }
1109 var oh64 pe.OptionalHeader64
1110 l = binary.Size(&oh64)
1111 } else {
1112
1113 PEBASE = 1 << 22
1114 var oh pe.OptionalHeader32
1115 l = binary.Size(&oh)
1116 }
1117
1118 if ctxt.LinkMode == LinkExternal {
1119
1120
1121
1122
1123 PESECTALIGN = 32
1124 PEFILEALIGN = 0
1125
1126 PEBASE = 0
1127 }
1128
1129 var sh [16]pe.SectionHeader32
1130 var fh pe.FileHeader
1131 PEFILEHEADR = int32(Rnd(int64(len(dosstub)+binary.Size(&fh)+l+binary.Size(&sh)), PEFILEALIGN))
1132 if ctxt.LinkMode != LinkExternal {
1133 PESECTHEADR = int32(Rnd(int64(PEFILEHEADR), PESECTALIGN))
1134 } else {
1135 PESECTHEADR = 0
1136 }
1137 pefile.nextSectOffset = uint32(PESECTHEADR)
1138 pefile.nextFileOffset = uint32(PEFILEHEADR)
1139
1140 if ctxt.LinkMode == LinkInternal {
1141
1142 for _, name := range [2]string{"__image_base__", "_image_base__"} {
1143 sb := ctxt.loader.CreateSymForUpdate(name, 0)
1144 sb.SetType(sym.SDATA)
1145 sb.SetValue(PEBASE)
1146 ctxt.loader.SetAttrSpecial(sb.Sym(), true)
1147 ctxt.loader.SetAttrLocal(sb.Sym(), true)
1148 }
1149 }
1150
1151 HEADR = PEFILEHEADR
1152 if *FlagRound == -1 {
1153 *FlagRound = PESECTALIGN
1154 }
1155 if *FlagTextAddr == -1 {
1156 *FlagTextAddr = Rnd(PEBASE, *FlagRound) + int64(PESECTHEADR)
1157 }
1158 }
1159
1160 func pewrite(ctxt *Link) {
1161 ctxt.Out.SeekSet(0)
1162 if ctxt.LinkMode != LinkExternal {
1163 ctxt.Out.Write(dosstub)
1164 ctxt.Out.WriteStringN("PE", 4)
1165 }
1166
1167 pefile.writeFileHeader(ctxt)
1168
1169 pefile.writeOptionalHeader(ctxt)
1170
1171 for _, sect := range pefile.sections {
1172 sect.write(ctxt.Out, ctxt.LinkMode)
1173 }
1174 }
1175
1176 func strput(out *OutBuf, s string) {
1177 out.WriteString(s)
1178 out.Write8(0)
1179
1180 if (len(s)+1)%2 != 0 {
1181 out.Write8(0)
1182 }
1183 }
1184
1185 func initdynimport(ctxt *Link) *Dll {
1186 ldr := ctxt.loader
1187 var d *Dll
1188
1189 dr = nil
1190 var m *Imp
1191 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
1192 if !ldr.AttrReachable(s) || ldr.SymType(s) != sym.SDYNIMPORT {
1193 continue
1194 }
1195 dynlib := ldr.SymDynimplib(s)
1196 for d = dr; d != nil; d = d.next {
1197 if d.name == dynlib {
1198 m = new(Imp)
1199 break
1200 }
1201 }
1202
1203 if d == nil {
1204 d = new(Dll)
1205 d.name = dynlib
1206 d.next = dr
1207 dr = d
1208 m = new(Imp)
1209 }
1210
1211
1212
1213
1214
1215 m.argsize = -1
1216 extName := ldr.SymExtname(s)
1217 if i := strings.IndexByte(extName, '%'); i >= 0 {
1218 var err error
1219 m.argsize, err = strconv.Atoi(extName[i+1:])
1220 if err != nil {
1221 ctxt.Errorf(s, "failed to parse stdcall decoration: %v", err)
1222 }
1223 m.argsize *= ctxt.Arch.PtrSize
1224 ldr.SetSymExtname(s, extName[:i])
1225 }
1226
1227 m.s = s
1228 m.next = d.ms
1229 d.ms = m
1230 }
1231
1232 if ctxt.IsExternal() {
1233
1234 for d := dr; d != nil; d = d.next {
1235 for m = d.ms; m != nil; m = m.next {
1236 sb := ldr.MakeSymbolUpdater(m.s)
1237 sb.SetType(sym.SDATA)
1238 sb.Grow(int64(ctxt.Arch.PtrSize))
1239 dynName := sb.Extname()
1240
1241 if ctxt.Is386() && m.argsize >= 0 {
1242 dynName += fmt.Sprintf("@%d", m.argsize)
1243 }
1244 dynSym := ldr.CreateSymForUpdate(dynName, 0)
1245 dynSym.SetType(sym.SHOSTOBJ)
1246 r, _ := sb.AddRel(objabi.R_ADDR)
1247 r.SetSym(dynSym.Sym())
1248 r.SetSiz(uint8(ctxt.Arch.PtrSize))
1249 }
1250 }
1251 } else {
1252 dynamic := ldr.CreateSymForUpdate(".windynamic", 0)
1253 dynamic.SetType(sym.SWINDOWS)
1254 for d := dr; d != nil; d = d.next {
1255 for m = d.ms; m != nil; m = m.next {
1256 sb := ldr.MakeSymbolUpdater(m.s)
1257 sb.SetType(sym.SWINDOWS)
1258 sb.SetValue(dynamic.Size())
1259 dynamic.SetSize(dynamic.Size() + int64(ctxt.Arch.PtrSize))
1260 dynamic.AddInteriorSym(m.s)
1261 }
1262
1263 dynamic.SetSize(dynamic.Size() + int64(ctxt.Arch.PtrSize))
1264 }
1265 }
1266
1267 return dr
1268 }
1269
1270
1271
1272 func peimporteddlls() []string {
1273 var dlls []string
1274
1275 for d := dr; d != nil; d = d.next {
1276 dlls = append(dlls, "-l"+strings.TrimSuffix(d.name, ".dll"))
1277 }
1278
1279 return dlls
1280 }
1281
1282 func addimports(ctxt *Link, datsect *peSection) {
1283 ldr := ctxt.loader
1284 startoff := ctxt.Out.Offset()
1285 dynamic := ldr.LookupOrCreateSym(".windynamic", 0)
1286
1287
1288 n := uint64(0)
1289
1290 for d := dr; d != nil; d = d.next {
1291 n++
1292 }
1293 ctxt.Out.SeekSet(startoff + int64(binary.Size(&IMAGE_IMPORT_DESCRIPTOR{}))*int64(n+1))
1294
1295
1296 for d := dr; d != nil; d = d.next {
1297 d.nameoff = uint64(ctxt.Out.Offset()) - uint64(startoff)
1298 strput(ctxt.Out, d.name)
1299 }
1300
1301
1302 for d := dr; d != nil; d = d.next {
1303 for m := d.ms; m != nil; m = m.next {
1304 m.off = uint64(pefile.nextSectOffset) + uint64(ctxt.Out.Offset()) - uint64(startoff)
1305 ctxt.Out.Write16(0)
1306 strput(ctxt.Out, ldr.SymExtname(m.s))
1307 }
1308 }
1309
1310
1311 oftbase := uint64(ctxt.Out.Offset()) - uint64(startoff)
1312
1313 n = uint64(ctxt.Out.Offset())
1314 for d := dr; d != nil; d = d.next {
1315 d.thunkoff = uint64(ctxt.Out.Offset()) - n
1316 for m := d.ms; m != nil; m = m.next {
1317 if pe64 != 0 {
1318 ctxt.Out.Write64(m.off)
1319 } else {
1320 ctxt.Out.Write32(uint32(m.off))
1321 }
1322 }
1323
1324 if pe64 != 0 {
1325 ctxt.Out.Write64(0)
1326 } else {
1327 ctxt.Out.Write32(0)
1328 }
1329 }
1330
1331
1332 n = uint64(ctxt.Out.Offset()) - uint64(startoff)
1333
1334 isect := pefile.addSection(".idata", int(n), int(n))
1335 isect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
1336 isect.checkOffset(startoff)
1337 isect.pad(ctxt.Out, uint32(n))
1338 endoff := ctxt.Out.Offset()
1339
1340
1341 ftbase := uint64(ldr.SymValue(dynamic)) - uint64(datsect.virtualAddress) - uint64(PEBASE)
1342
1343 ctxt.Out.SeekSet(int64(uint64(datsect.pointerToRawData) + ftbase))
1344 for d := dr; d != nil; d = d.next {
1345 for m := d.ms; m != nil; m = m.next {
1346 if pe64 != 0 {
1347 ctxt.Out.Write64(m.off)
1348 } else {
1349 ctxt.Out.Write32(uint32(m.off))
1350 }
1351 }
1352
1353 if pe64 != 0 {
1354 ctxt.Out.Write64(0)
1355 } else {
1356 ctxt.Out.Write32(0)
1357 }
1358 }
1359
1360
1361 out := ctxt.Out
1362 out.SeekSet(startoff)
1363
1364 for d := dr; d != nil; d = d.next {
1365 out.Write32(uint32(uint64(isect.virtualAddress) + oftbase + d.thunkoff))
1366 out.Write32(0)
1367 out.Write32(0)
1368 out.Write32(uint32(uint64(isect.virtualAddress) + d.nameoff))
1369 out.Write32(uint32(uint64(datsect.virtualAddress) + ftbase + d.thunkoff))
1370 }
1371
1372 out.Write32(0)
1373 out.Write32(0)
1374 out.Write32(0)
1375 out.Write32(0)
1376 out.Write32(0)
1377
1378
1379 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.virtualAddress
1380 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.virtualSize
1381 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(ldr.SymValue(dynamic) - PEBASE)
1382 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(ldr.SymSize(dynamic))
1383
1384 out.SeekSet(endoff)
1385 }
1386
1387 func initdynexport(ctxt *Link) {
1388 ldr := ctxt.loader
1389 for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
1390 if !ldr.AttrReachable(s) || !ldr.AttrCgoExportDynamic(s) {
1391 continue
1392 }
1393 if len(dexport)+1 > cap(dexport) {
1394 ctxt.Errorf(s, "pe dynexport table is full")
1395 errorexit()
1396 }
1397
1398 dexport = append(dexport, s)
1399 }
1400
1401 sort.Slice(dexport, func(i, j int) bool { return ldr.SymExtname(dexport[i]) < ldr.SymExtname(dexport[j]) })
1402 }
1403
1404 func addexports(ctxt *Link) {
1405 ldr := ctxt.loader
1406 var e IMAGE_EXPORT_DIRECTORY
1407
1408 nexport := len(dexport)
1409 size := binary.Size(&e) + 10*nexport + len(*flagOutfile) + 1
1410 for _, s := range dexport {
1411 size += len(ldr.SymExtname(s)) + 1
1412 }
1413
1414 if nexport == 0 {
1415 return
1416 }
1417
1418 sect := pefile.addSection(".edata", size, size)
1419 sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
1420 sect.checkOffset(ctxt.Out.Offset())
1421 va := int(sect.virtualAddress)
1422 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = uint32(va)
1423 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect.virtualSize
1424
1425 vaName := va + binary.Size(&e) + nexport*4
1426 vaAddr := va + binary.Size(&e)
1427 vaNa := va + binary.Size(&e) + nexport*8
1428
1429 e.Characteristics = 0
1430 e.MajorVersion = 0
1431 e.MinorVersion = 0
1432 e.NumberOfFunctions = uint32(nexport)
1433 e.NumberOfNames = uint32(nexport)
1434 e.Name = uint32(va+binary.Size(&e)) + uint32(nexport)*10
1435 e.Base = 1
1436 e.AddressOfFunctions = uint32(vaAddr)
1437 e.AddressOfNames = uint32(vaName)
1438 e.AddressOfNameOrdinals = uint32(vaNa)
1439
1440 out := ctxt.Out
1441
1442
1443 binary.Write(out, binary.LittleEndian, &e)
1444
1445
1446 for _, s := range dexport {
1447 out.Write32(uint32(ldr.SymValue(s) - PEBASE))
1448 }
1449
1450
1451 v := int(e.Name + uint32(len(*flagOutfile)) + 1)
1452
1453 for _, s := range dexport {
1454 out.Write32(uint32(v))
1455 v += len(ldr.SymExtname(s)) + 1
1456 }
1457
1458
1459 for i := 0; i < nexport; i++ {
1460 out.Write16(uint16(i))
1461 }
1462
1463
1464 out.WriteStringN(*flagOutfile, len(*flagOutfile)+1)
1465
1466 for _, s := range dexport {
1467 name := ldr.SymExtname(s)
1468 out.WriteStringN(name, len(name)+1)
1469 }
1470 sect.pad(out, uint32(size))
1471 }
1472
1473
1474 type peBaseRelocEntry struct {
1475 typeOff uint16
1476 }
1477
1478
1479
1480
1481
1482
1483 type peBaseRelocBlock struct {
1484 entries []peBaseRelocEntry
1485 }
1486
1487
1488
1489
1490 type pePages []uint32
1491
1492 func (p pePages) Len() int { return len(p) }
1493 func (p pePages) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
1494 func (p pePages) Less(i, j int) bool { return p[i] < p[j] }
1495
1496
1497
1498
1499
1500 type peBaseRelocTable struct {
1501 blocks map[uint32]peBaseRelocBlock
1502
1503
1504
1505 pages pePages
1506 }
1507
1508 func (rt *peBaseRelocTable) init(ctxt *Link) {
1509 rt.blocks = make(map[uint32]peBaseRelocBlock)
1510 }
1511
1512 func (rt *peBaseRelocTable) addentry(ldr *loader.Loader, s loader.Sym, r *loader.Reloc) {
1513
1514
1515 const pageSize = 0x1000
1516 const pageMask = pageSize - 1
1517
1518 addr := ldr.SymValue(s) + int64(r.Off()) - int64(PEBASE)
1519 page := uint32(addr &^ pageMask)
1520 off := uint32(addr & pageMask)
1521
1522 b, ok := rt.blocks[page]
1523 if !ok {
1524 rt.pages = append(rt.pages, page)
1525 }
1526
1527 e := peBaseRelocEntry{
1528 typeOff: uint16(off & 0xFFF),
1529 }
1530
1531
1532 switch r.Siz() {
1533 default:
1534 Exitf("unsupported relocation size %d\n", r.Siz)
1535 case 4:
1536 e.typeOff |= uint16(IMAGE_REL_BASED_HIGHLOW << 12)
1537 case 8:
1538 e.typeOff |= uint16(IMAGE_REL_BASED_DIR64 << 12)
1539 }
1540
1541 b.entries = append(b.entries, e)
1542 rt.blocks[page] = b
1543 }
1544
1545 func (rt *peBaseRelocTable) write(ctxt *Link) {
1546 out := ctxt.Out
1547
1548
1549 sort.Sort(rt.pages)
1550
1551
1552 if out.Offset()&3 != 0 {
1553 Errorf(nil, "internal error, start of .reloc not 32-bit aligned")
1554 }
1555
1556 for _, p := range rt.pages {
1557 b := rt.blocks[p]
1558
1559
1560
1561
1562 if len(b.entries)&1 != 0 {
1563 b.entries = append(b.entries, peBaseRelocEntry{})
1564 }
1565
1566 const sizeOfPEbaseRelocBlock = 8
1567 blockSize := uint32(sizeOfPEbaseRelocBlock + len(b.entries)*2)
1568 out.Write32(p)
1569 out.Write32(blockSize)
1570
1571 for _, e := range b.entries {
1572 out.Write16(e.typeOff)
1573 }
1574 }
1575 }
1576
1577 func addPEBaseRelocSym(ldr *loader.Loader, s loader.Sym, rt *peBaseRelocTable) {
1578 relocs := ldr.Relocs(s)
1579 for ri := 0; ri < relocs.Count(); ri++ {
1580 r := relocs.At(ri)
1581 if r.Type() >= objabi.ElfRelocOffset {
1582 continue
1583 }
1584 if r.Siz() == 0 {
1585 continue
1586 }
1587 if r.Type() == objabi.R_DWARFFILEREF {
1588 continue
1589 }
1590 rs := r.Sym()
1591 if rs == 0 {
1592 continue
1593 }
1594 if !ldr.AttrReachable(s) {
1595 continue
1596 }
1597
1598 switch r.Type() {
1599 default:
1600 case objabi.R_ADDR:
1601 rt.addentry(ldr, s, &r)
1602 }
1603 }
1604 }
1605
1606 func needPEBaseReloc(ctxt *Link) bool {
1607
1608
1609 if (ctxt.Arch.Family == sys.I386 || ctxt.Arch.Family == sys.AMD64) && ctxt.BuildMode != BuildModePIE {
1610 return false
1611 }
1612 return true
1613 }
1614
1615 func addPEBaseReloc(ctxt *Link) {
1616 if !needPEBaseReloc(ctxt) {
1617 return
1618 }
1619
1620 var rt peBaseRelocTable
1621 rt.init(ctxt)
1622
1623
1624 ldr := ctxt.loader
1625 for _, s := range ctxt.Textp {
1626 addPEBaseRelocSym(ldr, s, &rt)
1627 }
1628 for _, s := range ctxt.datap {
1629 addPEBaseRelocSym(ldr, s, &rt)
1630 }
1631
1632
1633 startoff := ctxt.Out.Offset()
1634 rt.write(ctxt)
1635 size := ctxt.Out.Offset() - startoff
1636
1637
1638 rsect := pefile.addSection(".reloc", int(size), int(size))
1639 rsect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
1640 rsect.checkOffset(startoff)
1641 rsect.pad(ctxt.Out, uint32(size))
1642
1643 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = rsect.virtualAddress
1644 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = rsect.virtualSize
1645 }
1646
1647 func (ctxt *Link) dope() {
1648 initdynimport(ctxt)
1649 initdynexport(ctxt)
1650 writeSEH(ctxt)
1651 }
1652
1653 func setpersrc(ctxt *Link, syms []loader.Sym) {
1654 if len(rsrcsyms) != 0 {
1655 Errorf(nil, "too many .rsrc sections")
1656 }
1657 rsrcsyms = syms
1658 }
1659
1660 func addpersrc(ctxt *Link) {
1661 if len(rsrcsyms) == 0 {
1662 return
1663 }
1664
1665 var size int64
1666 for _, rsrcsym := range rsrcsyms {
1667 size += ctxt.loader.SymSize(rsrcsym)
1668 }
1669 h := pefile.addSection(".rsrc", int(size), int(size))
1670 h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA
1671 h.checkOffset(ctxt.Out.Offset())
1672
1673 for _, rsrcsym := range rsrcsyms {
1674
1675
1676
1677 splitResources := strings.Contains(ctxt.loader.SymName(rsrcsym), ".rsrc$")
1678 relocs := ctxt.loader.Relocs(rsrcsym)
1679 data := ctxt.loader.Data(rsrcsym)
1680 for ri := 0; ri < relocs.Count(); ri++ {
1681 r := relocs.At(ri)
1682 p := data[r.Off():]
1683 val := uint32(int64(h.virtualAddress) + r.Add())
1684 if splitResources {
1685
1686
1687
1688
1689
1690
1691
1692
1693 val += uint32(len(data))
1694 }
1695 binary.LittleEndian.PutUint32(p, val)
1696 }
1697 ctxt.Out.Write(data)
1698 }
1699 h.pad(ctxt.Out, uint32(size))
1700
1701
1702 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress
1703 pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize
1704 }
1705
1706 func asmbPe(ctxt *Link) {
1707 t := pefile.addSection(".text", int(Segtext.Length), int(Segtext.Length))
1708 t.characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
1709 if ctxt.LinkMode == LinkExternal {
1710
1711
1712 t.characteristics |= IMAGE_SCN_ALIGN_32BYTES
1713 }
1714 t.checkSegment(&Segtext)
1715 pefile.textSect = t
1716
1717 ro := pefile.addSection(".rdata", int(Segrodata.Length), int(Segrodata.Length))
1718 ro.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
1719 if ctxt.LinkMode == LinkExternal {
1720
1721
1722 ro.characteristics |= IMAGE_SCN_ALIGN_32BYTES
1723 }
1724 ro.checkSegment(&Segrodata)
1725 pefile.rdataSect = ro
1726
1727 var d *peSection
1728 if ctxt.LinkMode != LinkExternal {
1729 d = pefile.addSection(".data", int(Segdata.Length), int(Segdata.Filelen))
1730 d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
1731 d.checkSegment(&Segdata)
1732 pefile.dataSect = d
1733 } else {
1734 d = pefile.addSection(".data", int(Segdata.Filelen), int(Segdata.Filelen))
1735 d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
1736 d.checkSegment(&Segdata)
1737 pefile.dataSect = d
1738
1739 b := pefile.addSection(".bss", int(Segdata.Length-Segdata.Filelen), 0)
1740 b.characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES
1741 b.pointerToRawData = 0
1742 pefile.bssSect = b
1743 }
1744
1745 pefile.addSEH(ctxt)
1746 pefile.addDWARF()
1747
1748 if ctxt.LinkMode == LinkExternal {
1749 pefile.ctorsSect = pefile.addInitArray(ctxt)
1750 }
1751
1752 ctxt.Out.SeekSet(int64(pefile.nextFileOffset))
1753 if ctxt.LinkMode != LinkExternal {
1754 addimports(ctxt, d)
1755 addexports(ctxt)
1756 addPEBaseReloc(ctxt)
1757 }
1758 pefile.writeSymbolTableAndStringTable(ctxt)
1759 addpersrc(ctxt)
1760 if ctxt.LinkMode == LinkExternal {
1761 pefile.emitRelocations(ctxt)
1762 }
1763
1764 pewrite(ctxt)
1765 }
1766
View as plain text