1
2
3
4
5
6 package loadpe
7
8 import (
9 "bytes"
10 "cmd/internal/bio"
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 "errors"
18 "fmt"
19 "io"
20 "strconv"
21 "strings"
22 )
23
24 const (
25 IMAGE_SYM_UNDEFINED = 0
26 IMAGE_SYM_ABSOLUTE = -1
27 IMAGE_SYM_DEBUG = -2
28 IMAGE_SYM_TYPE_NULL = 0
29 IMAGE_SYM_TYPE_VOID = 1
30 IMAGE_SYM_TYPE_CHAR = 2
31 IMAGE_SYM_TYPE_SHORT = 3
32 IMAGE_SYM_TYPE_INT = 4
33 IMAGE_SYM_TYPE_LONG = 5
34 IMAGE_SYM_TYPE_FLOAT = 6
35 IMAGE_SYM_TYPE_DOUBLE = 7
36 IMAGE_SYM_TYPE_STRUCT = 8
37 IMAGE_SYM_TYPE_UNION = 9
38 IMAGE_SYM_TYPE_ENUM = 10
39 IMAGE_SYM_TYPE_MOE = 11
40 IMAGE_SYM_TYPE_BYTE = 12
41 IMAGE_SYM_TYPE_WORD = 13
42 IMAGE_SYM_TYPE_UINT = 14
43 IMAGE_SYM_TYPE_DWORD = 15
44 IMAGE_SYM_TYPE_PCODE = 32768
45 IMAGE_SYM_DTYPE_NULL = 0
46 IMAGE_SYM_DTYPE_POINTER = 1
47 IMAGE_SYM_DTYPE_FUNCTION = 2
48 IMAGE_SYM_DTYPE_ARRAY = 3
49 IMAGE_SYM_CLASS_END_OF_FUNCTION = -1
50 IMAGE_SYM_CLASS_NULL = 0
51 IMAGE_SYM_CLASS_AUTOMATIC = 1
52 IMAGE_SYM_CLASS_EXTERNAL = 2
53 IMAGE_SYM_CLASS_STATIC = 3
54 IMAGE_SYM_CLASS_REGISTER = 4
55 IMAGE_SYM_CLASS_EXTERNAL_DEF = 5
56 IMAGE_SYM_CLASS_LABEL = 6
57 IMAGE_SYM_CLASS_UNDEFINED_LABEL = 7
58 IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8
59 IMAGE_SYM_CLASS_ARGUMENT = 9
60 IMAGE_SYM_CLASS_STRUCT_TAG = 10
61 IMAGE_SYM_CLASS_MEMBER_OF_UNION = 11
62 IMAGE_SYM_CLASS_UNION_TAG = 12
63 IMAGE_SYM_CLASS_TYPE_DEFINITION = 13
64 IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14
65 IMAGE_SYM_CLASS_ENUM_TAG = 15
66 IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16
67 IMAGE_SYM_CLASS_REGISTER_PARAM = 17
68 IMAGE_SYM_CLASS_BIT_FIELD = 18
69 IMAGE_SYM_CLASS_FAR_EXTERNAL = 68
70 IMAGE_SYM_CLASS_BLOCK = 100
71 IMAGE_SYM_CLASS_FUNCTION = 101
72 IMAGE_SYM_CLASS_END_OF_STRUCT = 102
73 IMAGE_SYM_CLASS_FILE = 103
74 IMAGE_SYM_CLASS_SECTION = 104
75 IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105
76 IMAGE_SYM_CLASS_CLR_TOKEN = 107
77 IMAGE_REL_I386_ABSOLUTE = 0x0000
78 IMAGE_REL_I386_DIR16 = 0x0001
79 IMAGE_REL_I386_REL16 = 0x0002
80 IMAGE_REL_I386_DIR32 = 0x0006
81 IMAGE_REL_I386_DIR32NB = 0x0007
82 IMAGE_REL_I386_SEG12 = 0x0009
83 IMAGE_REL_I386_SECTION = 0x000A
84 IMAGE_REL_I386_SECREL = 0x000B
85 IMAGE_REL_I386_TOKEN = 0x000C
86 IMAGE_REL_I386_SECREL7 = 0x000D
87 IMAGE_REL_I386_REL32 = 0x0014
88 IMAGE_REL_AMD64_ABSOLUTE = 0x0000
89 IMAGE_REL_AMD64_ADDR64 = 0x0001
90 IMAGE_REL_AMD64_ADDR32 = 0x0002
91 IMAGE_REL_AMD64_ADDR32NB = 0x0003
92 IMAGE_REL_AMD64_REL32 = 0x0004
93 IMAGE_REL_AMD64_REL32_1 = 0x0005
94 IMAGE_REL_AMD64_REL32_2 = 0x0006
95 IMAGE_REL_AMD64_REL32_3 = 0x0007
96 IMAGE_REL_AMD64_REL32_4 = 0x0008
97 IMAGE_REL_AMD64_REL32_5 = 0x0009
98 IMAGE_REL_AMD64_SECTION = 0x000A
99 IMAGE_REL_AMD64_SECREL = 0x000B
100 IMAGE_REL_AMD64_SECREL7 = 0x000C
101 IMAGE_REL_AMD64_TOKEN = 0x000D
102 IMAGE_REL_AMD64_SREL32 = 0x000E
103 IMAGE_REL_AMD64_PAIR = 0x000F
104 IMAGE_REL_AMD64_SSPAN32 = 0x0010
105 IMAGE_REL_ARM_ABSOLUTE = 0x0000
106 IMAGE_REL_ARM_ADDR32 = 0x0001
107 IMAGE_REL_ARM_ADDR32NB = 0x0002
108 IMAGE_REL_ARM_BRANCH24 = 0x0003
109 IMAGE_REL_ARM_BRANCH11 = 0x0004
110 IMAGE_REL_ARM_SECTION = 0x000E
111 IMAGE_REL_ARM_SECREL = 0x000F
112 IMAGE_REL_ARM_MOV32 = 0x0010
113 IMAGE_REL_THUMB_MOV32 = 0x0011
114 IMAGE_REL_THUMB_BRANCH20 = 0x0012
115 IMAGE_REL_THUMB_BRANCH24 = 0x0014
116 IMAGE_REL_THUMB_BLX23 = 0x0015
117 IMAGE_REL_ARM_PAIR = 0x0016
118 IMAGE_REL_ARM64_ABSOLUTE = 0x0000
119 IMAGE_REL_ARM64_ADDR32 = 0x0001
120 IMAGE_REL_ARM64_ADDR32NB = 0x0002
121 IMAGE_REL_ARM64_BRANCH26 = 0x0003
122 IMAGE_REL_ARM64_PAGEBASE_REL21 = 0x0004
123 IMAGE_REL_ARM64_REL21 = 0x0005
124 IMAGE_REL_ARM64_PAGEOFFSET_12A = 0x0006
125 IMAGE_REL_ARM64_PAGEOFFSET_12L = 0x0007
126 IMAGE_REL_ARM64_SECREL = 0x0008
127 IMAGE_REL_ARM64_SECREL_LOW12A = 0x0009
128 IMAGE_REL_ARM64_SECREL_HIGH12A = 0x000A
129 IMAGE_REL_ARM64_SECREL_LOW12L = 0x000B
130 IMAGE_REL_ARM64_TOKEN = 0x000C
131 IMAGE_REL_ARM64_SECTION = 0x000D
132 IMAGE_REL_ARM64_ADDR64 = 0x000E
133 IMAGE_REL_ARM64_BRANCH19 = 0x000F
134 IMAGE_REL_ARM64_BRANCH14 = 0x0010
135 IMAGE_REL_ARM64_REL32 = 0x0011
136 )
137
138 const (
139
140
141
142
143 CreateImportStubPltToken = -2
144
145
146
147
148 RedirectToDynImportGotToken = -2
149 )
150
151
152
153
154 type peBiobuf bio.Reader
155
156 func (f *peBiobuf) ReadAt(p []byte, off int64) (int, error) {
157 ret := ((*bio.Reader)(f)).MustSeek(off, 0)
158 if ret < 0 {
159 return 0, errors.New("fail to seek")
160 }
161 n, err := f.Read(p)
162 if err != nil {
163 return 0, err
164 }
165 return n, nil
166 }
167
168
169
170 func makeUpdater(l *loader.Loader, bld *loader.SymbolBuilder, s loader.Sym) *loader.SymbolBuilder {
171 if bld != nil {
172 return bld
173 }
174 bld = l.MakeSymbolUpdater(s)
175 return bld
176 }
177
178
179
180
181 type peImportSymsState struct {
182
183
184 secSyms []loader.Sym
185
186
187 l *loader.Loader
188 arch *sys.Arch
189 }
190
191 var importSymsState *peImportSymsState
192
193 func createImportSymsState(l *loader.Loader, arch *sys.Arch) {
194 if importSymsState != nil {
195 return
196 }
197 importSymsState = &peImportSymsState{
198 l: l,
199 arch: arch,
200 }
201 }
202
203
204
205 type peLoaderState struct {
206 l *loader.Loader
207 arch *sys.Arch
208 f *pe.File
209 pn string
210 sectsyms map[*pe.Section]loader.Sym
211 comdats map[uint16]int64
212 sectdata map[*pe.Section][]byte
213 localSymVersion int
214 }
215
216
217
218
219 var comdatDefinitions map[string]int64
220
221
222 type Symbols struct {
223 Textp []loader.Sym
224 Resources []loader.Sym
225 PData []loader.Sym
226 XData loader.Sym
227 }
228
229
230
231 func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (*Symbols, error) {
232 state := &peLoaderState{
233 l: l,
234 arch: arch,
235 sectsyms: make(map[*pe.Section]loader.Sym),
236 sectdata: make(map[*pe.Section][]byte),
237 localSymVersion: localSymVersion,
238 pn: pn,
239 }
240 createImportSymsState(state.l, state.arch)
241 if comdatDefinitions == nil {
242 comdatDefinitions = make(map[string]int64)
243 }
244
245
246
247
248
249 sr := io.NewSectionReader((*peBiobuf)(input), input.Offset(), 1<<63-1)
250
251
252 f, err := pe.NewFile(sr)
253 if err != nil {
254 return nil, err
255 }
256 defer f.Close()
257 state.f = f
258
259 var (
260 ls Symbols
261 pdata loader.Sym
262 )
263
264
265
266
267 for _, sect := range f.Sections {
268 if sect.Characteristics&pe.IMAGE_SCN_MEM_DISCARDABLE != 0 {
269 continue
270 }
271
272 if sect.Characteristics&(pe.IMAGE_SCN_CNT_CODE|pe.IMAGE_SCN_CNT_INITIALIZED_DATA|pe.IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 {
273
274
275 continue
276 }
277
278 name := fmt.Sprintf("%s(%s)", pkg, sect.Name)
279 s := state.l.LookupOrCreateCgoExport(name, localSymVersion)
280 bld := l.MakeSymbolUpdater(s)
281
282 switch sect.Characteristics & (pe.IMAGE_SCN_CNT_UNINITIALIZED_DATA | pe.IMAGE_SCN_CNT_INITIALIZED_DATA | pe.IMAGE_SCN_MEM_READ | pe.IMAGE_SCN_MEM_WRITE | pe.IMAGE_SCN_CNT_CODE | pe.IMAGE_SCN_MEM_EXECUTE) {
283 case pe.IMAGE_SCN_CNT_INITIALIZED_DATA | pe.IMAGE_SCN_MEM_READ:
284 if issehsect(arch, sect) {
285 bld.SetType(sym.SSEHSECT)
286 bld.SetAlign(4)
287 } else {
288 bld.SetType(sym.SRODATA)
289 }
290
291 case pe.IMAGE_SCN_CNT_UNINITIALIZED_DATA | pe.IMAGE_SCN_MEM_READ | pe.IMAGE_SCN_MEM_WRITE:
292 bld.SetType(sym.SNOPTRBSS)
293
294 case pe.IMAGE_SCN_CNT_INITIALIZED_DATA | pe.IMAGE_SCN_MEM_READ | pe.IMAGE_SCN_MEM_WRITE:
295 bld.SetType(sym.SNOPTRDATA)
296
297 case pe.IMAGE_SCN_CNT_CODE | pe.IMAGE_SCN_MEM_EXECUTE | pe.IMAGE_SCN_MEM_READ:
298 bld.SetType(sym.STEXT)
299
300 default:
301 return nil, fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name)
302 }
303
304 if bld.Type() != sym.SNOPTRBSS {
305 data, err := sect.Data()
306 if err != nil {
307 return nil, err
308 }
309 state.sectdata[sect] = data
310 bld.SetData(data)
311 }
312 bld.SetSize(int64(sect.Size))
313 state.sectsyms[sect] = s
314 if sect.Name == ".rsrc" || strings.HasPrefix(sect.Name, ".rsrc$") {
315 ls.Resources = append(ls.Resources, s)
316 } else if bld.Type() == sym.SSEHSECT {
317 if sect.Name == ".pdata" {
318 pdata = s
319 } else if sect.Name == ".xdata" {
320 ls.XData = s
321 }
322 }
323 }
324
325
326 if err := state.preprocessSymbols(); err != nil {
327 return nil, err
328 }
329
330
331 for _, rsect := range f.Sections {
332 if _, found := state.sectsyms[rsect]; !found {
333 continue
334 }
335 if rsect.NumberOfRelocations == 0 {
336 continue
337 }
338 if rsect.Characteristics&pe.IMAGE_SCN_MEM_DISCARDABLE != 0 {
339 continue
340 }
341 if rsect.Characteristics&(pe.IMAGE_SCN_CNT_CODE|pe.IMAGE_SCN_CNT_INITIALIZED_DATA|pe.IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 {
342
343
344 continue
345 }
346
347 splitResources := strings.HasPrefix(rsect.Name, ".rsrc$")
348 issehsect := issehsect(arch, rsect)
349 sb := l.MakeSymbolUpdater(state.sectsyms[rsect])
350 for j, r := range rsect.Relocs {
351 if int(r.SymbolTableIndex) >= len(f.COFFSymbols) {
352 return nil, fmt.Errorf("relocation number %d symbol index idx=%d cannot be large then number of symbols %d", j, r.SymbolTableIndex, len(f.COFFSymbols))
353 }
354 pesym := &f.COFFSymbols[r.SymbolTableIndex]
355 _, rSym, err := state.readpesym(pesym)
356 if err != nil {
357 return nil, err
358 }
359 if rSym == 0 {
360 name, err := pesym.FullName(f.StringTable)
361 if err != nil {
362 name = string(pesym.Name[:])
363 }
364 return nil, fmt.Errorf("reloc of invalid sym %s idx=%d type=%d", name, r.SymbolTableIndex, pesym.Type)
365 }
366
367 rSize := uint8(4)
368 rOff := int32(r.VirtualAddress)
369 var rType objabi.RelocType
370 switch arch.Family {
371 default:
372 return nil, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family)
373 case sys.I386:
374 switch r.Type {
375 case IMAGE_REL_I386_REL32:
376 rType = objabi.R_PCREL
377 case IMAGE_REL_I386_DIR32:
378 rType = objabi.R_ADDR
379 case IMAGE_REL_I386_DIR32NB:
380 rType = objabi.R_PEIMAGEOFF
381 }
382 case sys.AMD64:
383 switch r.Type {
384 case IMAGE_REL_AMD64_REL32:
385 rType = objabi.R_PCREL
386 case IMAGE_REL_AMD64_ADDR32:
387 rType = objabi.R_ADDR
388 case IMAGE_REL_AMD64_ADDR64:
389 rType = objabi.R_ADDR
390 rSize = 8
391 case IMAGE_REL_AMD64_ADDR32NB:
392 rType = objabi.R_PEIMAGEOFF
393 }
394 case sys.ARM64:
395 switch r.Type {
396 case IMAGE_REL_ARM64_ADDR32:
397 rType = objabi.R_ADDR
398 case IMAGE_REL_ARM64_ADDR64:
399 rType = objabi.R_ADDR
400 rSize = 8
401 case IMAGE_REL_ARM64_ADDR32NB:
402 rType = objabi.R_PEIMAGEOFF
403 case IMAGE_REL_ARM64_BRANCH26:
404 rType = objabi.R_CALLARM64
405 case IMAGE_REL_ARM64_PAGEBASE_REL21,
406 IMAGE_REL_ARM64_PAGEOFFSET_12A,
407 IMAGE_REL_ARM64_PAGEOFFSET_12L:
408 rType = objabi.R_ARM64_PCREL
409 }
410 }
411 if rType == 0 {
412 return nil, fmt.Errorf("%s: %v: unknown relocation type %v", pn, state.sectsyms[rsect], r.Type)
413 }
414 var val int64
415 switch rSize {
416 default:
417 panic("unexpected relocation size " + strconv.Itoa(int(rSize)))
418 case 4:
419 val = int64(int32(binary.LittleEndian.Uint32(state.sectdata[rsect][rOff:])))
420 case 8:
421 val = int64(binary.LittleEndian.Uint64(state.sectdata[rsect][rOff:]))
422 }
423 var rAdd int64
424 if arch.Family == sys.ARM64 {
425 switch r.Type {
426 case IMAGE_REL_ARM64_BRANCH26:
427
428 case IMAGE_REL_ARM64_PAGEOFFSET_12A:
429
430
431 rAdd = (val >> 10) & 0xfff
432 case IMAGE_REL_ARM64_PAGEOFFSET_12L:
433
434 shift := uint32(val) >> 30
435 if shift == 0 && (val>>20)&0x048 == 0x048 {
436 shift = 4
437 }
438 rAdd = ((val >> 10) & 0xfff) << shift
439 case IMAGE_REL_ARM64_PAGEBASE_REL21:
440
441
442
443 immlo := (val >> 29) & 3
444 immhi := (val >> 5) & 0x7ffff
445 rAdd = (immhi << 2) | immlo
446 default:
447 rAdd = val
448 }
449 } else {
450 rAdd = val
451 }
452
453
454
455
456 if issect(pesym) || splitResources {
457 rAdd += int64(pesym.Value)
458 }
459 if issehsect {
460
461
462
463
464 rType |= objabi.R_WEAK
465 }
466
467 rel, _ := sb.AddRel(rType)
468 rel.SetOff(rOff)
469 rel.SetSiz(rSize)
470 rel.SetSym(rSym)
471 rel.SetAdd(rAdd)
472
473 }
474
475 sb.SortRelocs()
476 }
477
478
479 for i, numaux := 0, 0; i < len(f.COFFSymbols); i += numaux + 1 {
480 pesym := &f.COFFSymbols[i]
481
482 numaux = int(pesym.NumberOfAuxSymbols)
483
484 name, err := pesym.FullName(f.StringTable)
485 if err != nil {
486 return nil, err
487 }
488 if name == "" {
489 continue
490 }
491 if issect(pesym) {
492 continue
493 }
494 if int(pesym.SectionNumber) > len(f.Sections) {
495 continue
496 }
497 if pesym.SectionNumber == IMAGE_SYM_DEBUG {
498 continue
499 }
500 if pesym.SectionNumber == IMAGE_SYM_ABSOLUTE && bytes.Equal(pesym.Name[:], []byte("@feat.00")) {
501
502
503
504
505 continue
506 }
507 var sect *pe.Section
508 if pesym.SectionNumber > 0 {
509 sect = f.Sections[pesym.SectionNumber-1]
510 if _, found := state.sectsyms[sect]; !found {
511 continue
512 }
513 }
514
515 bld, s, err := state.readpesym(pesym)
516 if err != nil {
517 return nil, err
518 }
519
520 if pesym.SectionNumber == 0 {
521 if l.SymType(s) == sym.SXREF && pesym.Value > 0 {
522 bld = makeUpdater(l, bld, s)
523 bld.SetType(sym.SNOPTRDATA)
524 bld.SetSize(int64(pesym.Value))
525 }
526
527 continue
528 } else if pesym.SectionNumber > 0 && int(pesym.SectionNumber) <= len(f.Sections) {
529 sect = f.Sections[pesym.SectionNumber-1]
530 if _, found := state.sectsyms[sect]; !found {
531 return nil, fmt.Errorf("%s: %v: missing sect.sym", pn, s)
532 }
533 } else {
534 return nil, fmt.Errorf("%s: %v: sectnum < 0!", pn, s)
535 }
536
537 if sect == nil {
538 return nil, nil
539 }
540
541
542 if sz, ok1 := state.comdats[uint16(pesym.SectionNumber-1)]; ok1 {
543 if psz, ok2 := comdatDefinitions[l.SymName(s)]; ok2 {
544 if sz == psz {
545
546
547 continue
548 }
549 }
550 }
551 if l.OuterSym(s) != 0 {
552 if l.AttrDuplicateOK(s) {
553 continue
554 }
555 outerName := l.SymName(l.OuterSym(s))
556 sectName := l.SymName(state.sectsyms[sect])
557 return nil, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, l.SymName(s), outerName, sectName)
558 }
559
560 bld = makeUpdater(l, bld, s)
561 sectsym := state.sectsyms[sect]
562 bld.SetType(l.SymType(sectsym))
563 l.AddInteriorSym(sectsym, s)
564 bld.SetValue(int64(pesym.Value))
565 bld.SetSize(4)
566 if l.SymType(sectsym).IsText() {
567 if bld.External() && !bld.DuplicateOK() {
568 return nil, fmt.Errorf("%s: duplicate symbol definition", l.SymName(s))
569 }
570 bld.SetExternal(true)
571 }
572 if sz, ok := state.comdats[uint16(pesym.SectionNumber-1)]; ok {
573
574
575 if _, ok := comdatDefinitions[l.SymName(s)]; ok {
576 return nil, fmt.Errorf("internal error: preexisting COMDAT definition for %q", name)
577 }
578 comdatDefinitions[l.SymName(s)] = sz
579 }
580 }
581
582
583
584 for _, sect := range f.Sections {
585 s := state.sectsyms[sect]
586 if s == 0 {
587 continue
588 }
589 l.SortSub(s)
590 importSymsState.secSyms = append(importSymsState.secSyms, s)
591 if l.SymType(s).IsText() {
592 for ; s != 0; s = l.SubSym(s) {
593 if l.AttrOnList(s) {
594 return nil, fmt.Errorf("symbol %s listed multiple times", l.SymName(s))
595 }
596 l.SetAttrOnList(s, true)
597 ls.Textp = append(ls.Textp, s)
598 }
599 }
600 }
601
602 if pdata != 0 {
603 subs, err := processSEH(l, arch, pdata)
604 if err != nil {
605 return nil, err
606 }
607 ls.PData = subs
608 }
609
610 return &ls, nil
611 }
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640 func PostProcessImports() error {
641 ldr := importSymsState.l
642 arch := importSymsState.arch
643 keeprelocneeded := make(map[loader.Sym]loader.Sym)
644 for _, s := range importSymsState.secSyms {
645 isText := ldr.SymType(s).IsText()
646 relocs := ldr.Relocs(s)
647 for i := 0; i < relocs.Count(); i++ {
648 r := relocs.At(i)
649 rs := r.Sym()
650 if ldr.SymType(rs) == sym.SDYNIMPORT {
651
652 ldr.SetPlt(rs, CreateImportStubPltToken)
653 continue
654 }
655 isym, err := LookupBaseFromImport(rs, ldr, arch)
656 if err != nil {
657 return err
658 }
659 if isym == 0 {
660 continue
661 }
662 if ldr.SymType(isym) != sym.SDYNIMPORT {
663 continue
664 }
665
666
667 if !isText {
668 r.SetSym(isym)
669 continue
670 }
671
672 ldr.SetGot(rs, RedirectToDynImportGotToken)
673
674 splt := ldr.SymPlt(rs)
675 if splt != -1 {
676 return fmt.Errorf("internal error: import symbol %q has invalid PLT setting %d", ldr.SymName(rs), splt)
677 }
678
679 keeprelocneeded[rs] = isym
680 }
681 }
682 for k, v := range keeprelocneeded {
683 sb := ldr.MakeSymbolUpdater(k)
684 r, _ := sb.AddRel(objabi.R_KEEP)
685 r.SetSym(v)
686 }
687 importSymsState = nil
688 return nil
689 }
690
691 func issehsect(arch *sys.Arch, s *pe.Section) bool {
692 return arch.Family == sys.AMD64 && (s.Name == ".pdata" || s.Name == ".xdata")
693 }
694
695 func issect(s *pe.COFFSymbol) bool {
696 return s.StorageClass == IMAGE_SYM_CLASS_STATIC && s.Type == 0 && s.Name[0] == '.'
697 }
698
699 func (state *peLoaderState) readpesym(pesym *pe.COFFSymbol) (*loader.SymbolBuilder, loader.Sym, error) {
700 symname, err := pesym.FullName(state.f.StringTable)
701 if err != nil {
702 return nil, 0, err
703 }
704 var name string
705 if issect(pesym) {
706 name = state.l.SymName(state.sectsyms[state.f.Sections[pesym.SectionNumber-1]])
707 } else {
708 name = symname
709
710
711
712
713
714
715 if state.arch.Family == sys.I386 && name[0] == '_' && name != "_main" && !strings.HasPrefix(name, "__imp_") {
716 name = name[1:]
717 }
718 }
719
720
721 if i := strings.LastIndex(name, "@"); i >= 0 {
722 name = name[:i]
723 }
724
725 var s loader.Sym
726 var bld *loader.SymbolBuilder
727
728
729
730 switch uint8(pesym.Type&0xf0) >> 4 {
731 default:
732 return nil, 0, fmt.Errorf("%s: invalid symbol type %d", symname, pesym.Type)
733
734 case IMAGE_SYM_DTYPE_FUNCTION, IMAGE_SYM_DTYPE_NULL:
735 switch pesym.StorageClass {
736 case IMAGE_SYM_CLASS_EXTERNAL:
737 s = state.l.LookupOrCreateCgoExport(name, 0)
738
739 case IMAGE_SYM_CLASS_NULL, IMAGE_SYM_CLASS_STATIC, IMAGE_SYM_CLASS_LABEL:
740 s = state.l.LookupOrCreateCgoExport(name, state.localSymVersion)
741 bld = makeUpdater(state.l, bld, s)
742 bld.SetDuplicateOK(true)
743
744 default:
745 return nil, 0, fmt.Errorf("%s: invalid symbol binding %d", symname, pesym.StorageClass)
746 }
747 }
748
749 if s != 0 && state.l.SymType(s) == 0 && (pesym.StorageClass != IMAGE_SYM_CLASS_STATIC || pesym.Value != 0) {
750 bld = makeUpdater(state.l, bld, s)
751 bld.SetType(sym.SXREF)
752 }
753
754 return bld, s, nil
755 }
756
757
758
759
760
761
762
763
764 func (state *peLoaderState) preprocessSymbols() error {
765
766
767 state.comdats = make(map[uint16]int64)
768 for i, s := range state.f.Sections {
769 if s.Characteristics&uint32(pe.IMAGE_SCN_LNK_COMDAT) != 0 {
770 state.comdats[uint16(i)] = int64(s.Size)
771 }
772 }
773
774
775 for i, numaux := 0, 0; i < len(state.f.COFFSymbols); i += numaux + 1 {
776 pesym := &state.f.COFFSymbols[i]
777 numaux = int(pesym.NumberOfAuxSymbols)
778 if pesym.SectionNumber == 0 {
779 continue
780 }
781 symname, err := pesym.FullName(state.f.StringTable)
782 if err != nil {
783 return err
784 }
785 if _, isc := state.comdats[uint16(pesym.SectionNumber-1)]; !isc {
786 continue
787 }
788 if pesym.StorageClass != uint8(IMAGE_SYM_CLASS_STATIC) {
789 continue
790 }
791
792
793 auxsymp, err := state.f.COFFSymbolReadSectionDefAux(i)
794 if err != nil {
795 return fmt.Errorf("unable to read aux info for section def symbol %d %s: pe.COFFSymbolReadComdatInfo returns %v", i, symname, err)
796 }
797 if auxsymp.Selection == pe.IMAGE_COMDAT_SELECT_SAME_SIZE {
798
799 } else if auxsymp.Selection == pe.IMAGE_COMDAT_SELECT_ANY {
800
801 state.comdats[uint16(pesym.SectionNumber-1)] = int64(-1)
802 } else {
803
804
805
806 return fmt.Errorf("internal error: unsupported COMDAT selection strategy found in path=%s sec=%d strategy=%d idx=%d, please file a bug", state.pn, auxsymp.SecNum, auxsymp.Selection, i)
807 }
808 }
809 return nil
810 }
811
812
813
814
815
816
817 func LookupBaseFromImport(s loader.Sym, ldr *loader.Loader, arch *sys.Arch) (loader.Sym, error) {
818 sname := ldr.SymName(s)
819 if !strings.HasPrefix(sname, "__imp_") {
820 return 0, nil
821 }
822 basename := sname[len("__imp_"):]
823 if arch.Family == sys.I386 && basename[0] == '_' {
824 basename = basename[1:]
825 }
826 isym := ldr.Lookup(basename, 0)
827 if isym == 0 {
828 return 0, fmt.Errorf("internal error: import symbol %q with no underlying sym", sname)
829 }
830 return isym, nil
831 }
832
View as plain text