Source file
src/debug/pe/symbol.go
1
2
3
4
5 package pe
6
7 import (
8 "encoding/binary"
9 "errors"
10 "fmt"
11 "internal/saferio"
12 "io"
13 "unsafe"
14 )
15
16 const COFFSymbolSize = 18
17
18
19 type COFFSymbol struct {
20 Name [8]uint8
21 Value uint32
22 SectionNumber int16
23 Type uint16
24 StorageClass uint8
25 NumberOfAuxSymbols uint8
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 func readCOFFSymbols(fh *FileHeader, r io.ReadSeeker) ([]COFFSymbol, error) {
52 if fh.PointerToSymbolTable == 0 {
53 return nil, nil
54 }
55 if fh.NumberOfSymbols <= 0 {
56 return nil, nil
57 }
58 _, err := r.Seek(int64(fh.PointerToSymbolTable), io.SeekStart)
59 if err != nil {
60 return nil, fmt.Errorf("fail to seek to symbol table: %v", err)
61 }
62 c := saferio.SliceCap[COFFSymbol](uint64(fh.NumberOfSymbols))
63 if c < 0 {
64 return nil, errors.New("too many symbols; file may be corrupt")
65 }
66 syms := make([]COFFSymbol, 0, c)
67 naux := 0
68 for k := uint32(0); k < fh.NumberOfSymbols; k++ {
69 var sym COFFSymbol
70 if naux == 0 {
71
72 err = binary.Read(r, binary.LittleEndian, &sym)
73 if err != nil {
74 return nil, fmt.Errorf("fail to read symbol table: %v", err)
75 }
76
77 naux = int(sym.NumberOfAuxSymbols)
78 } else {
79
80
81
82
83 naux--
84 aux := (*COFFSymbolAuxFormat5)(unsafe.Pointer(&sym))
85 err = binary.Read(r, binary.LittleEndian, aux)
86 if err != nil {
87 return nil, fmt.Errorf("fail to read symbol table: %v", err)
88 }
89 }
90 syms = append(syms, sym)
91 }
92 if naux != 0 {
93 return nil, fmt.Errorf("fail to read symbol table: %d aux symbols unread", naux)
94 }
95 return syms, nil
96 }
97
98
99 func isSymNameOffset(name [8]byte) (bool, uint32) {
100 if name[0] == 0 && name[1] == 0 && name[2] == 0 && name[3] == 0 {
101 offset := binary.LittleEndian.Uint32(name[4:])
102 if offset == 0 {
103
104 return false, 0
105 }
106 return true, offset
107 }
108 return false, 0
109 }
110
111
112
113
114 func (sym *COFFSymbol) FullName(st StringTable) (string, error) {
115 if ok, offset := isSymNameOffset(sym.Name); ok {
116 return st.String(offset)
117 }
118 return cstring(sym.Name[:]), nil
119 }
120
121 func removeAuxSymbols(allsyms []COFFSymbol, st StringTable) ([]*Symbol, error) {
122 if len(allsyms) == 0 {
123 return nil, nil
124 }
125 syms := make([]*Symbol, 0)
126 aux := uint8(0)
127 for _, sym := range allsyms {
128 if aux > 0 {
129 aux--
130 continue
131 }
132 name, err := sym.FullName(st)
133 if err != nil {
134 return nil, err
135 }
136 aux = sym.NumberOfAuxSymbols
137 s := &Symbol{
138 Name: name,
139 Value: sym.Value,
140 SectionNumber: sym.SectionNumber,
141 Type: sym.Type,
142 StorageClass: sym.StorageClass,
143 }
144 syms = append(syms, s)
145 }
146 return syms, nil
147 }
148
149
150
151 type Symbol struct {
152 Name string
153 Value uint32
154 SectionNumber int16
155 Type uint16
156 StorageClass uint8
157 }
158
159
160
161
162
163
164
165
166
167 type COFFSymbolAuxFormat5 struct {
168 Size uint32
169 NumRelocs uint16
170 NumLineNumbers uint16
171 Checksum uint32
172 SecNum uint16
173 Selection uint8
174 _ [3]uint8
175 }
176
177
178
179 const (
180 IMAGE_COMDAT_SELECT_NODUPLICATES = 1
181 IMAGE_COMDAT_SELECT_ANY = 2
182 IMAGE_COMDAT_SELECT_SAME_SIZE = 3
183 IMAGE_COMDAT_SELECT_EXACT_MATCH = 4
184 IMAGE_COMDAT_SELECT_ASSOCIATIVE = 5
185 IMAGE_COMDAT_SELECT_LARGEST = 6
186 )
187
188
189
190
191
192
193
194
195
196
197 func (f *File) COFFSymbolReadSectionDefAux(idx int) (*COFFSymbolAuxFormat5, error) {
198 var rv *COFFSymbolAuxFormat5
199 if idx < 0 || idx >= len(f.COFFSymbols) {
200 return rv, fmt.Errorf("invalid symbol index")
201 }
202 pesym := &f.COFFSymbols[idx]
203 const IMAGE_SYM_CLASS_STATIC = 3
204 if pesym.StorageClass != uint8(IMAGE_SYM_CLASS_STATIC) {
205 return rv, fmt.Errorf("incorrect symbol storage class")
206 }
207 if pesym.NumberOfAuxSymbols == 0 || idx+1 >= len(f.COFFSymbols) {
208 return rv, fmt.Errorf("aux symbol unavailable")
209 }
210
211 pesymn := &f.COFFSymbols[idx+1]
212 rv = (*COFFSymbolAuxFormat5)(unsafe.Pointer(pesymn))
213 return rv, nil
214 }
215
View as plain text