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