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 ls Symbols
260
261
262
263
264 for _, sect := range f.Sections {
265 if sect.Characteristics&pe.IMAGE_SCN_MEM_DISCARDABLE != 0 {
266 continue
267 }
268
269 if sect.Characteristics&(pe.IMAGE_SCN_CNT_CODE|pe.IMAGE_SCN_CNT_INITIALIZED_DATA|pe.IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 {
270
271
272 continue
273 }
274
275 name := fmt.Sprintf("%s(%s)", pkg, sect.Name)
276 s := state.l.LookupOrCreateCgoExport(name, localSymVersion)
277 bld := l.MakeSymbolUpdater(s)
278
279 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) {
280 case pe.IMAGE_SCN_CNT_INITIALIZED_DATA | pe.IMAGE_SCN_MEM_READ:
281 if issehsect(arch, sect) {
282 bld.SetType(sym.SSEHSECT)
283 bld.SetAlign(4)
284 } else {
285 bld.SetType(sym.SRODATA)
286 }
287
288 case pe.IMAGE_SCN_CNT_UNINITIALIZED_DATA | pe.IMAGE_SCN_MEM_READ | pe.IMAGE_SCN_MEM_WRITE:
289 bld.SetType(sym.SNOPTRBSS)
290
291 case pe.IMAGE_SCN_CNT_INITIALIZED_DATA | pe.IMAGE_SCN_MEM_READ | pe.IMAGE_SCN_MEM_WRITE:
292 bld.SetType(sym.SNOPTRDATA)
293
294 case pe.IMAGE_SCN_CNT_CODE | pe.IMAGE_SCN_MEM_EXECUTE | pe.IMAGE_SCN_MEM_READ:
295 bld.SetType(sym.STEXT)
296
297 default:
298 return nil, fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name)
299 }
300
301 if bld.Type() != sym.SNOPTRBSS {
302 data, err := sect.Data()
303 if err != nil {
304 return nil, err
305 }
306 state.sectdata[sect] = data
307 bld.SetData(data)
308 }
309 bld.SetSize(int64(sect.Size))
310 state.sectsyms[sect] = s
311 if sect.Name == ".rsrc" || strings.HasPrefix(sect.Name, ".rsrc$") {
312 ls.Resources = append(ls.Resources, s)
313 } else if bld.Type() == sym.SSEHSECT {
314 if sect.Name == ".pdata" {
315 ls.PData = s
316 } else if sect.Name == ".xdata" {
317 ls.XData = s
318 }
319 }
320 }
321
322
323 if err := state.preprocessSymbols(); err != nil {
324 return nil, err
325 }
326
327
328 for _, rsect := range f.Sections {
329 if _, found := state.sectsyms[rsect]; !found {
330 continue
331 }
332 if rsect.NumberOfRelocations == 0 {
333 continue
334 }
335 if rsect.Characteristics&pe.IMAGE_SCN_MEM_DISCARDABLE != 0 {
336 continue
337 }
338 if rsect.Characteristics&(pe.IMAGE_SCN_CNT_CODE|pe.IMAGE_SCN_CNT_INITIALIZED_DATA|pe.IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 {
339
340
341 continue
342 }
343
344 splitResources := strings.HasPrefix(rsect.Name, ".rsrc$")
345 issehsect := issehsect(arch, rsect)
346 sb := l.MakeSymbolUpdater(state.sectsyms[rsect])
347 for j, r := range rsect.Relocs {
348 if int(r.SymbolTableIndex) >= len(f.COFFSymbols) {
349 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))
350 }
351 pesym := &f.COFFSymbols[r.SymbolTableIndex]
352 _, rSym, err := state.readpesym(pesym)
353 if err != nil {
354 return nil, err
355 }
356 if rSym == 0 {
357 name, err := pesym.FullName(f.StringTable)
358 if err != nil {
359 name = string(pesym.Name[:])
360 }
361 return nil, fmt.Errorf("reloc of invalid sym %s idx=%d type=%d", name, r.SymbolTableIndex, pesym.Type)
362 }
363
364 rSize := uint8(4)
365 rOff := int32(r.VirtualAddress)
366 var rType objabi.RelocType
367 switch arch.Family {
368 default:
369 return nil, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family)
370 case sys.I386:
371 switch r.Type {
372 case IMAGE_REL_I386_REL32:
373 rType = objabi.R_PCREL
374 case IMAGE_REL_I386_DIR32:
375 rType = objabi.R_ADDR
376 case IMAGE_REL_I386_DIR32NB:
377 rType = objabi.R_PEIMAGEOFF
378 }
379 case sys.AMD64:
380 switch r.Type {
381 case IMAGE_REL_AMD64_REL32:
382 rType = objabi.R_PCREL
383 case IMAGE_REL_AMD64_ADDR32:
384 rType = objabi.R_ADDR
385 case IMAGE_REL_AMD64_ADDR64:
386 rType = objabi.R_ADDR
387 rSize = 8
388 case IMAGE_REL_AMD64_ADDR32NB:
389 rType = objabi.R_PEIMAGEOFF
390 }
391 case sys.ARM64:
392 switch r.Type {
393 case IMAGE_REL_ARM64_ADDR32:
394 rType = objabi.R_ADDR
395 case IMAGE_REL_ARM64_ADDR32NB:
396 rType = objabi.R_PEIMAGEOFF
397 }
398 }
399 if rType == 0 {
400 return nil, fmt.Errorf("%s: %v: unknown relocation type %v", pn, state.sectsyms[rsect], r.Type)
401 }
402 var rAdd int64
403 switch rSize {
404 default:
405 panic("unexpected relocation size " + strconv.Itoa(int(rSize)))
406 case 4:
407 rAdd = int64(int32(binary.LittleEndian.Uint32(state.sectdata[rsect][rOff:])))
408 case 8:
409 rAdd = int64(binary.LittleEndian.Uint64(state.sectdata[rsect][rOff:]))
410 }
411
412
413
414
415 if issect(pesym) || splitResources {
416 rAdd += int64(pesym.Value)
417 }
418 if issehsect {
419
420
421
422
423 rType |= objabi.R_WEAK
424 }
425
426 rel, _ := sb.AddRel(rType)
427 rel.SetOff(rOff)
428 rel.SetSiz(rSize)
429 rel.SetSym(rSym)
430 rel.SetAdd(rAdd)
431
432 }
433
434 sb.SortRelocs()
435 }
436
437
438 for i, numaux := 0, 0; i < len(f.COFFSymbols); i += numaux + 1 {
439 pesym := &f.COFFSymbols[i]
440
441 numaux = int(pesym.NumberOfAuxSymbols)
442
443 name, err := pesym.FullName(f.StringTable)
444 if err != nil {
445 return nil, err
446 }
447 if name == "" {
448 continue
449 }
450 if issect(pesym) {
451 continue
452 }
453 if int(pesym.SectionNumber) > len(f.Sections) {
454 continue
455 }
456 if pesym.SectionNumber == IMAGE_SYM_DEBUG {
457 continue
458 }
459 if pesym.SectionNumber == IMAGE_SYM_ABSOLUTE && bytes.Equal(pesym.Name[:], []byte("@feat.00")) {
460
461
462
463
464 continue
465 }
466 var sect *pe.Section
467 if pesym.SectionNumber > 0 {
468 sect = f.Sections[pesym.SectionNumber-1]
469 if _, found := state.sectsyms[sect]; !found {
470 continue
471 }
472 }
473
474 bld, s, err := state.readpesym(pesym)
475 if err != nil {
476 return nil, err
477 }
478
479 if pesym.SectionNumber == 0 {
480 if l.SymType(s) == sym.SXREF && pesym.Value > 0 {
481 bld = makeUpdater(l, bld, s)
482 bld.SetType(sym.SNOPTRDATA)
483 bld.SetSize(int64(pesym.Value))
484 }
485
486 continue
487 } else if pesym.SectionNumber > 0 && int(pesym.SectionNumber) <= len(f.Sections) {
488 sect = f.Sections[pesym.SectionNumber-1]
489 if _, found := state.sectsyms[sect]; !found {
490 return nil, fmt.Errorf("%s: %v: missing sect.sym", pn, s)
491 }
492 } else {
493 return nil, fmt.Errorf("%s: %v: sectnum < 0!", pn, s)
494 }
495
496 if sect == nil {
497 return nil, nil
498 }
499
500
501 if sz, ok1 := state.comdats[uint16(pesym.SectionNumber-1)]; ok1 {
502 if psz, ok2 := comdatDefinitions[l.SymName(s)]; ok2 {
503 if sz == psz {
504
505
506 continue
507 }
508 }
509 }
510 if l.OuterSym(s) != 0 {
511 if l.AttrDuplicateOK(s) {
512 continue
513 }
514 outerName := l.SymName(l.OuterSym(s))
515 sectName := l.SymName(state.sectsyms[sect])
516 return nil, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, l.SymName(s), outerName, sectName)
517 }
518
519 bld = makeUpdater(l, bld, s)
520 sectsym := state.sectsyms[sect]
521 bld.SetType(l.SymType(sectsym))
522 l.AddInteriorSym(sectsym, s)
523 bld.SetValue(int64(pesym.Value))
524 bld.SetSize(4)
525 if l.SymType(sectsym).IsText() {
526 if bld.External() && !bld.DuplicateOK() {
527 return nil, fmt.Errorf("%s: duplicate symbol definition", l.SymName(s))
528 }
529 bld.SetExternal(true)
530 }
531 if sz, ok := state.comdats[uint16(pesym.SectionNumber-1)]; ok {
532
533
534 if _, ok := comdatDefinitions[l.SymName(s)]; ok {
535 return nil, fmt.Errorf("internal error: preexisting COMDAT definition for %q", name)
536 }
537 comdatDefinitions[l.SymName(s)] = sz
538 }
539 }
540
541
542
543 for _, sect := range f.Sections {
544 s := state.sectsyms[sect]
545 if s == 0 {
546 continue
547 }
548 l.SortSub(s)
549 importSymsState.secSyms = append(importSymsState.secSyms, s)
550 if l.SymType(s).IsText() {
551 for ; s != 0; s = l.SubSym(s) {
552 if l.AttrOnList(s) {
553 return nil, fmt.Errorf("symbol %s listed multiple times", l.SymName(s))
554 }
555 l.SetAttrOnList(s, true)
556 ls.Textp = append(ls.Textp, s)
557 }
558 }
559 }
560
561 if ls.PData != 0 {
562 processSEH(l, arch, ls.PData, ls.XData)
563 }
564
565 return &ls, nil
566 }
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595 func PostProcessImports() error {
596 ldr := importSymsState.l
597 arch := importSymsState.arch
598 keeprelocneeded := make(map[loader.Sym]loader.Sym)
599 for _, s := range importSymsState.secSyms {
600 isText := ldr.SymType(s).IsText()
601 relocs := ldr.Relocs(s)
602 for i := 0; i < relocs.Count(); i++ {
603 r := relocs.At(i)
604 rs := r.Sym()
605 if ldr.SymType(rs) == sym.SDYNIMPORT {
606
607 ldr.SetPlt(rs, CreateImportStubPltToken)
608 continue
609 }
610 isym, err := LookupBaseFromImport(rs, ldr, arch)
611 if err != nil {
612 return err
613 }
614 if isym == 0 {
615 continue
616 }
617 if ldr.SymType(isym) != sym.SDYNIMPORT {
618 continue
619 }
620
621
622 if !isText {
623 r.SetSym(isym)
624 continue
625 }
626
627 ldr.SetGot(rs, RedirectToDynImportGotToken)
628
629 splt := ldr.SymPlt(rs)
630 if splt != -1 {
631 return fmt.Errorf("internal error: import symbol %q has invalid PLT setting %d", ldr.SymName(rs), splt)
632 }
633
634 keeprelocneeded[rs] = isym
635 }
636 }
637 for k, v := range keeprelocneeded {
638 sb := ldr.MakeSymbolUpdater(k)
639 r, _ := sb.AddRel(objabi.R_KEEP)
640 r.SetSym(v)
641 }
642 importSymsState = nil
643 return nil
644 }
645
646 func issehsect(arch *sys.Arch, s *pe.Section) bool {
647 return arch.Family == sys.AMD64 && (s.Name == ".pdata" || s.Name == ".xdata")
648 }
649
650 func issect(s *pe.COFFSymbol) bool {
651 return s.StorageClass == IMAGE_SYM_CLASS_STATIC && s.Type == 0 && s.Name[0] == '.'
652 }
653
654 func (state *peLoaderState) readpesym(pesym *pe.COFFSymbol) (*loader.SymbolBuilder, loader.Sym, error) {
655 symname, err := pesym.FullName(state.f.StringTable)
656 if err != nil {
657 return nil, 0, err
658 }
659 var name string
660 if issect(pesym) {
661 name = state.l.SymName(state.sectsyms[state.f.Sections[pesym.SectionNumber-1]])
662 } else {
663 name = symname
664
665
666
667
668
669
670 if state.arch.Family == sys.I386 && name[0] == '_' && name != "_main" && !strings.HasPrefix(name, "__imp_") {
671 name = name[1:]
672 }
673 }
674
675
676 if i := strings.LastIndex(name, "@"); i >= 0 {
677 name = name[:i]
678 }
679
680 var s loader.Sym
681 var bld *loader.SymbolBuilder
682
683
684
685 switch uint8(pesym.Type&0xf0) >> 4 {
686 default:
687 return nil, 0, fmt.Errorf("%s: invalid symbol type %d", symname, pesym.Type)
688
689 case IMAGE_SYM_DTYPE_FUNCTION, IMAGE_SYM_DTYPE_NULL:
690 switch pesym.StorageClass {
691 case IMAGE_SYM_CLASS_EXTERNAL:
692 s = state.l.LookupOrCreateCgoExport(name, 0)
693
694 case IMAGE_SYM_CLASS_NULL, IMAGE_SYM_CLASS_STATIC, IMAGE_SYM_CLASS_LABEL:
695 s = state.l.LookupOrCreateCgoExport(name, state.localSymVersion)
696 bld = makeUpdater(state.l, bld, s)
697 bld.SetDuplicateOK(true)
698
699 default:
700 return nil, 0, fmt.Errorf("%s: invalid symbol binding %d", symname, pesym.StorageClass)
701 }
702 }
703
704 if s != 0 && state.l.SymType(s) == 0 && (pesym.StorageClass != IMAGE_SYM_CLASS_STATIC || pesym.Value != 0) {
705 bld = makeUpdater(state.l, bld, s)
706 bld.SetType(sym.SXREF)
707 }
708
709 return bld, s, nil
710 }
711
712
713
714
715
716
717
718
719 func (state *peLoaderState) preprocessSymbols() error {
720
721
722 state.comdats = make(map[uint16]int64)
723 for i, s := range state.f.Sections {
724 if s.Characteristics&uint32(pe.IMAGE_SCN_LNK_COMDAT) != 0 {
725 state.comdats[uint16(i)] = int64(s.Size)
726 }
727 }
728
729
730 for i, numaux := 0, 0; i < len(state.f.COFFSymbols); i += numaux + 1 {
731 pesym := &state.f.COFFSymbols[i]
732 numaux = int(pesym.NumberOfAuxSymbols)
733 if pesym.SectionNumber == 0 {
734 continue
735 }
736 symname, err := pesym.FullName(state.f.StringTable)
737 if err != nil {
738 return err
739 }
740 if _, isc := state.comdats[uint16(pesym.SectionNumber-1)]; !isc {
741 continue
742 }
743 if pesym.StorageClass != uint8(IMAGE_SYM_CLASS_STATIC) {
744 continue
745 }
746
747
748 auxsymp, err := state.f.COFFSymbolReadSectionDefAux(i)
749 if err != nil {
750 return fmt.Errorf("unable to read aux info for section def symbol %d %s: pe.COFFSymbolReadComdatInfo returns %v", i, symname, err)
751 }
752 if auxsymp.Selection == pe.IMAGE_COMDAT_SELECT_SAME_SIZE {
753
754 } else if auxsymp.Selection == pe.IMAGE_COMDAT_SELECT_ANY {
755
756 state.comdats[uint16(pesym.SectionNumber-1)] = int64(-1)
757 } else {
758
759
760
761 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)
762 }
763 }
764 return nil
765 }
766
767
768
769
770
771
772 func LookupBaseFromImport(s loader.Sym, ldr *loader.Loader, arch *sys.Arch) (loader.Sym, error) {
773 sname := ldr.SymName(s)
774 if !strings.HasPrefix(sname, "__imp_") {
775 return 0, nil
776 }
777 basename := sname[len("__imp_"):]
778 if arch.Family == sys.I386 && basename[0] == '_' {
779 basename = basename[1:]
780 }
781 isym := ldr.Lookup(basename, 0)
782 if isym == 0 {
783 return 0, fmt.Errorf("internal error: import symbol %q with no underlying sym", sname)
784 }
785 return isym, nil
786 }
787
View as plain text