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