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_ADDR64:
396 rType = objabi.R_ADDR
397 rSize = 8
398 case IMAGE_REL_ARM64_ADDR32NB:
399 rType = objabi.R_PEIMAGEOFF
400 case IMAGE_REL_ARM64_BRANCH26:
401 rType = objabi.R_CALLARM64
402 case IMAGE_REL_ARM64_PAGEBASE_REL21,
403 IMAGE_REL_ARM64_PAGEOFFSET_12A,
404 IMAGE_REL_ARM64_PAGEOFFSET_12L:
405 rType = objabi.R_ARM64_PCREL
406 }
407 }
408 if rType == 0 {
409 return nil, fmt.Errorf("%s: %v: unknown relocation type %v", pn, state.sectsyms[rsect], r.Type)
410 }
411 var val int64
412 switch rSize {
413 default:
414 panic("unexpected relocation size " + strconv.Itoa(int(rSize)))
415 case 4:
416 val = int64(int32(binary.LittleEndian.Uint32(state.sectdata[rsect][rOff:])))
417 case 8:
418 val = int64(binary.LittleEndian.Uint64(state.sectdata[rsect][rOff:]))
419 }
420 var rAdd int64
421 if arch.Family == sys.ARM64 {
422 switch r.Type {
423 case IMAGE_REL_ARM64_BRANCH26:
424
425 case IMAGE_REL_ARM64_PAGEOFFSET_12A:
426
427
428 rAdd = (val >> 10) & 0xfff
429 case IMAGE_REL_ARM64_PAGEOFFSET_12L:
430
431 shift := uint32(val) >> 30
432 if shift == 0 && (val>>20)&0x048 == 0x048 {
433 shift = 4
434 }
435 rAdd = ((val >> 10) & 0xfff) << shift
436 case IMAGE_REL_ARM64_PAGEBASE_REL21:
437
438
439
440 immlo := (val >> 29) & 3
441 immhi := (val >> 5) & 0x7ffff
442 rAdd = (immhi << 2) | immlo
443 default:
444 rAdd = val
445 }
446 } else {
447 rAdd = val
448 }
449
450
451
452
453 if issect(pesym) || splitResources {
454 rAdd += int64(pesym.Value)
455 }
456 if issehsect {
457
458
459
460
461 rType |= objabi.R_WEAK
462 }
463
464 rel, _ := sb.AddRel(rType)
465 rel.SetOff(rOff)
466 rel.SetSiz(rSize)
467 rel.SetSym(rSym)
468 rel.SetAdd(rAdd)
469
470 }
471
472 sb.SortRelocs()
473 }
474
475
476 for i, numaux := 0, 0; i < len(f.COFFSymbols); i += numaux + 1 {
477 pesym := &f.COFFSymbols[i]
478
479 numaux = int(pesym.NumberOfAuxSymbols)
480
481 name, err := pesym.FullName(f.StringTable)
482 if err != nil {
483 return nil, err
484 }
485 if name == "" {
486 continue
487 }
488 if issect(pesym) {
489 continue
490 }
491 if int(pesym.SectionNumber) > len(f.Sections) {
492 continue
493 }
494 if pesym.SectionNumber == IMAGE_SYM_DEBUG {
495 continue
496 }
497 if pesym.SectionNumber == IMAGE_SYM_ABSOLUTE && bytes.Equal(pesym.Name[:], []byte("@feat.00")) {
498
499
500
501
502 continue
503 }
504 var sect *pe.Section
505 if pesym.SectionNumber > 0 {
506 sect = f.Sections[pesym.SectionNumber-1]
507 if _, found := state.sectsyms[sect]; !found {
508 continue
509 }
510 }
511
512 bld, s, err := state.readpesym(pesym)
513 if err != nil {
514 return nil, err
515 }
516
517 if pesym.SectionNumber == 0 {
518 if l.SymType(s) == sym.SXREF && pesym.Value > 0 {
519 bld = makeUpdater(l, bld, s)
520 bld.SetType(sym.SNOPTRDATA)
521 bld.SetSize(int64(pesym.Value))
522 }
523
524 continue
525 } else if pesym.SectionNumber > 0 && int(pesym.SectionNumber) <= len(f.Sections) {
526 sect = f.Sections[pesym.SectionNumber-1]
527 if _, found := state.sectsyms[sect]; !found {
528 return nil, fmt.Errorf("%s: %v: missing sect.sym", pn, s)
529 }
530 } else {
531 return nil, fmt.Errorf("%s: %v: sectnum < 0!", pn, s)
532 }
533
534 if sect == nil {
535 return nil, nil
536 }
537
538
539 if sz, ok1 := state.comdats[uint16(pesym.SectionNumber-1)]; ok1 {
540 if psz, ok2 := comdatDefinitions[l.SymName(s)]; ok2 {
541 if sz == psz {
542
543
544 continue
545 }
546 }
547 }
548 if l.OuterSym(s) != 0 {
549 if l.AttrDuplicateOK(s) {
550 continue
551 }
552 outerName := l.SymName(l.OuterSym(s))
553 sectName := l.SymName(state.sectsyms[sect])
554 return nil, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, l.SymName(s), outerName, sectName)
555 }
556
557 bld = makeUpdater(l, bld, s)
558 sectsym := state.sectsyms[sect]
559 bld.SetType(l.SymType(sectsym))
560 l.AddInteriorSym(sectsym, s)
561 bld.SetValue(int64(pesym.Value))
562 bld.SetSize(4)
563 if l.SymType(sectsym).IsText() {
564 if bld.External() && !bld.DuplicateOK() {
565 return nil, fmt.Errorf("%s: duplicate symbol definition", l.SymName(s))
566 }
567 bld.SetExternal(true)
568 }
569 if sz, ok := state.comdats[uint16(pesym.SectionNumber-1)]; ok {
570
571
572 if _, ok := comdatDefinitions[l.SymName(s)]; ok {
573 return nil, fmt.Errorf("internal error: preexisting COMDAT definition for %q", name)
574 }
575 comdatDefinitions[l.SymName(s)] = sz
576 }
577 }
578
579
580
581 for _, sect := range f.Sections {
582 s := state.sectsyms[sect]
583 if s == 0 {
584 continue
585 }
586 l.SortSub(s)
587 importSymsState.secSyms = append(importSymsState.secSyms, s)
588 if l.SymType(s).IsText() {
589 for ; s != 0; s = l.SubSym(s) {
590 if l.AttrOnList(s) {
591 return nil, fmt.Errorf("symbol %s listed multiple times", l.SymName(s))
592 }
593 l.SetAttrOnList(s, true)
594 ls.Textp = append(ls.Textp, s)
595 }
596 }
597 }
598
599 if ls.PData != 0 {
600 processSEH(l, arch, ls.PData, ls.XData)
601 }
602
603 return &ls, nil
604 }
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633 func PostProcessImports() error {
634 ldr := importSymsState.l
635 arch := importSymsState.arch
636 keeprelocneeded := make(map[loader.Sym]loader.Sym)
637 for _, s := range importSymsState.secSyms {
638 isText := ldr.SymType(s).IsText()
639 relocs := ldr.Relocs(s)
640 for i := 0; i < relocs.Count(); i++ {
641 r := relocs.At(i)
642 rs := r.Sym()
643 if ldr.SymType(rs) == sym.SDYNIMPORT {
644
645 ldr.SetPlt(rs, CreateImportStubPltToken)
646 continue
647 }
648 isym, err := LookupBaseFromImport(rs, ldr, arch)
649 if err != nil {
650 return err
651 }
652 if isym == 0 {
653 continue
654 }
655 if ldr.SymType(isym) != sym.SDYNIMPORT {
656 continue
657 }
658
659
660 if !isText {
661 r.SetSym(isym)
662 continue
663 }
664
665 ldr.SetGot(rs, RedirectToDynImportGotToken)
666
667 splt := ldr.SymPlt(rs)
668 if splt != -1 {
669 return fmt.Errorf("internal error: import symbol %q has invalid PLT setting %d", ldr.SymName(rs), splt)
670 }
671
672 keeprelocneeded[rs] = isym
673 }
674 }
675 for k, v := range keeprelocneeded {
676 sb := ldr.MakeSymbolUpdater(k)
677 r, _ := sb.AddRel(objabi.R_KEEP)
678 r.SetSym(v)
679 }
680 importSymsState = nil
681 return nil
682 }
683
684 func issehsect(arch *sys.Arch, s *pe.Section) bool {
685 return arch.Family == sys.AMD64 && (s.Name == ".pdata" || s.Name == ".xdata")
686 }
687
688 func issect(s *pe.COFFSymbol) bool {
689 return s.StorageClass == IMAGE_SYM_CLASS_STATIC && s.Type == 0 && s.Name[0] == '.'
690 }
691
692 func (state *peLoaderState) readpesym(pesym *pe.COFFSymbol) (*loader.SymbolBuilder, loader.Sym, error) {
693 symname, err := pesym.FullName(state.f.StringTable)
694 if err != nil {
695 return nil, 0, err
696 }
697 var name string
698 if issect(pesym) {
699 name = state.l.SymName(state.sectsyms[state.f.Sections[pesym.SectionNumber-1]])
700 } else {
701 name = symname
702
703
704
705
706
707
708 if state.arch.Family == sys.I386 && name[0] == '_' && name != "_main" && !strings.HasPrefix(name, "__imp_") {
709 name = name[1:]
710 }
711 }
712
713
714 if i := strings.LastIndex(name, "@"); i >= 0 {
715 name = name[:i]
716 }
717
718 var s loader.Sym
719 var bld *loader.SymbolBuilder
720
721
722
723 switch uint8(pesym.Type&0xf0) >> 4 {
724 default:
725 return nil, 0, fmt.Errorf("%s: invalid symbol type %d", symname, pesym.Type)
726
727 case IMAGE_SYM_DTYPE_FUNCTION, IMAGE_SYM_DTYPE_NULL:
728 switch pesym.StorageClass {
729 case IMAGE_SYM_CLASS_EXTERNAL:
730 s = state.l.LookupOrCreateCgoExport(name, 0)
731
732 case IMAGE_SYM_CLASS_NULL, IMAGE_SYM_CLASS_STATIC, IMAGE_SYM_CLASS_LABEL:
733 s = state.l.LookupOrCreateCgoExport(name, state.localSymVersion)
734 bld = makeUpdater(state.l, bld, s)
735 bld.SetDuplicateOK(true)
736
737 default:
738 return nil, 0, fmt.Errorf("%s: invalid symbol binding %d", symname, pesym.StorageClass)
739 }
740 }
741
742 if s != 0 && state.l.SymType(s) == 0 && (pesym.StorageClass != IMAGE_SYM_CLASS_STATIC || pesym.Value != 0) {
743 bld = makeUpdater(state.l, bld, s)
744 bld.SetType(sym.SXREF)
745 }
746
747 return bld, s, nil
748 }
749
750
751
752
753
754
755
756
757 func (state *peLoaderState) preprocessSymbols() error {
758
759
760 state.comdats = make(map[uint16]int64)
761 for i, s := range state.f.Sections {
762 if s.Characteristics&uint32(pe.IMAGE_SCN_LNK_COMDAT) != 0 {
763 state.comdats[uint16(i)] = int64(s.Size)
764 }
765 }
766
767
768 for i, numaux := 0, 0; i < len(state.f.COFFSymbols); i += numaux + 1 {
769 pesym := &state.f.COFFSymbols[i]
770 numaux = int(pesym.NumberOfAuxSymbols)
771 if pesym.SectionNumber == 0 {
772 continue
773 }
774 symname, err := pesym.FullName(state.f.StringTable)
775 if err != nil {
776 return err
777 }
778 if _, isc := state.comdats[uint16(pesym.SectionNumber-1)]; !isc {
779 continue
780 }
781 if pesym.StorageClass != uint8(IMAGE_SYM_CLASS_STATIC) {
782 continue
783 }
784
785
786 auxsymp, err := state.f.COFFSymbolReadSectionDefAux(i)
787 if err != nil {
788 return fmt.Errorf("unable to read aux info for section def symbol %d %s: pe.COFFSymbolReadComdatInfo returns %v", i, symname, err)
789 }
790 if auxsymp.Selection == pe.IMAGE_COMDAT_SELECT_SAME_SIZE {
791
792 } else if auxsymp.Selection == pe.IMAGE_COMDAT_SELECT_ANY {
793
794 state.comdats[uint16(pesym.SectionNumber-1)] = int64(-1)
795 } else {
796
797
798
799 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)
800 }
801 }
802 return nil
803 }
804
805
806
807
808
809
810 func LookupBaseFromImport(s loader.Sym, ldr *loader.Loader, arch *sys.Arch) (loader.Sym, error) {
811 sname := ldr.SymName(s)
812 if !strings.HasPrefix(sname, "__imp_") {
813 return 0, nil
814 }
815 basename := sname[len("__imp_"):]
816 if arch.Family == sys.I386 && basename[0] == '_' {
817 basename = basename[1:]
818 }
819 isym := ldr.Lookup(basename, 0)
820 if isym == 0 {
821 return 0, fmt.Errorf("internal error: import symbol %q with no underlying sym", sname)
822 }
823 return isym, nil
824 }
825
View as plain text