liyujie
2025-08-28 d9927380ed7c8366f762049be9f3fee225860833
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
 
package pe
 
import (
   "encoding/binary"
   "fmt"
   "io"
)
 
const COFFSymbolSize = 18
 
// COFFSymbol represents single COFF symbol table record.
type COFFSymbol struct {
   Name               [8]uint8
   Value              uint32
   SectionNumber      int16
   Type               uint16
   StorageClass       uint8
   NumberOfAuxSymbols uint8
}
 
func readCOFFSymbols(fh *FileHeader, r io.ReadSeeker) ([]COFFSymbol, error) {
   if fh.PointerToSymbolTable == 0 {
       return nil, nil
   }
   if fh.NumberOfSymbols <= 0 {
       return nil, nil
   }
   _, err := r.Seek(int64(fh.PointerToSymbolTable), seekStart)
   if err != nil {
       return nil, fmt.Errorf("fail to seek to symbol table: %v", err)
   }
   syms := make([]COFFSymbol, fh.NumberOfSymbols)
   err = binary.Read(r, binary.LittleEndian, syms)
   if err != nil {
       return nil, fmt.Errorf("fail to read symbol table: %v", err)
   }
   return syms, nil
}
 
// isSymNameOffset checks symbol name if it is encoded as offset into string table.
func isSymNameOffset(name [8]byte) (bool, uint32) {
   if name[0] == 0 && name[1] == 0 && name[2] == 0 && name[3] == 0 {
       return true, binary.LittleEndian.Uint32(name[4:])
   }
   return false, 0
}
 
// FullName finds real name of symbol sym. Normally name is stored
// in sym.Name, but if it is longer then 8 characters, it is stored
// in COFF string table st instead.
func (sym *COFFSymbol) FullName(st StringTable) (string, error) {
   if ok, offset := isSymNameOffset(sym.Name); ok {
       return st.String(offset)
   }
   return cstring(sym.Name[:]), nil
}
 
func removeAuxSymbols(allsyms []COFFSymbol, st StringTable) ([]*Symbol, error) {
   if len(allsyms) == 0 {
       return nil, nil
   }
   syms := make([]*Symbol, 0)
   aux := uint8(0)
   for _, sym := range allsyms {
       if aux > 0 {
           aux--
           continue
       }
       name, err := sym.FullName(st)
       if err != nil {
           return nil, err
       }
       aux = sym.NumberOfAuxSymbols
       s := &Symbol{
           Name:          name,
           Value:         sym.Value,
           SectionNumber: sym.SectionNumber,
           Type:          sym.Type,
           StorageClass:  sym.StorageClass,
       }
       syms = append(syms, s)
   }
   return syms, nil
}
 
// Symbol is similar to COFFSymbol with Name field replaced
// by Go string. Symbol also does not have NumberOfAuxSymbols.
type Symbol struct {
   Name          string
   Value         uint32
   SectionNumber int16
   Type          uint16
   StorageClass  uint8
}