Source file src/pkg/cmd/link/internal/ld/decodesym.go
1
2
3
4
5 package ld
6
7 import (
8 "bytes"
9 "cmd/internal/objabi"
10 "cmd/internal/sys"
11 "cmd/link/internal/sym"
12 "debug/elf"
13 "fmt"
14 )
15
16
17
18
19
20
21
22
23
24
25
26
27 const (
28 tflagUncommon = 1 << 0
29 tflagExtraStar = 1 << 1
30 )
31
32 func decodeReloc(s *sym.Symbol, off int32) *sym.Reloc {
33 for i := range s.R {
34 if s.R[i].Off == off {
35 return &s.R[i]
36 }
37 }
38 return nil
39 }
40
41 func decodeRelocSym(s *sym.Symbol, off int32) *sym.Symbol {
42 r := decodeReloc(s, off)
43 if r == nil {
44 return nil
45 }
46 return r.Sym
47 }
48
49 func decodeInuxi(arch *sys.Arch, p []byte, sz int) uint64 {
50 switch sz {
51 case 2:
52 return uint64(arch.ByteOrder.Uint16(p))
53 case 4:
54 return uint64(arch.ByteOrder.Uint32(p))
55 case 8:
56 return arch.ByteOrder.Uint64(p)
57 default:
58 Exitf("dwarf: decode inuxi %d", sz)
59 panic("unreachable")
60 }
61 }
62
63 func commonsize(arch *sys.Arch) int { return 4*arch.PtrSize + 8 + 8 }
64 func structfieldSize(arch *sys.Arch) int { return 3 * arch.PtrSize }
65 func uncommonSize() int { return 4 + 2 + 2 + 4 + 4 }
66
67
68 func decodetypeKind(arch *sys.Arch, s *sym.Symbol) uint8 {
69 return s.P[2*arch.PtrSize+7] & objabi.KindMask
70 }
71
72
73 func decodetypeUsegcprog(arch *sys.Arch, s *sym.Symbol) uint8 {
74 return s.P[2*arch.PtrSize+7] & objabi.KindGCProg
75 }
76
77
78 func decodetypeSize(arch *sys.Arch, s *sym.Symbol) int64 {
79 return int64(decodeInuxi(arch, s.P, arch.PtrSize))
80 }
81
82
83 func decodetypePtrdata(arch *sys.Arch, s *sym.Symbol) int64 {
84 return int64(decodeInuxi(arch, s.P[arch.PtrSize:], arch.PtrSize))
85 }
86
87
88 func decodetypeHasUncommon(arch *sys.Arch, s *sym.Symbol) bool {
89 return s.P[2*arch.PtrSize+4]&tflagUncommon != 0
90 }
91
92
93 func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section {
94 for _, shlib := range ctxt.Shlibs {
95 if shlib.Path == path {
96 for _, sect := range shlib.File.Sections {
97 if sect.Addr <= addr && addr <= sect.Addr+sect.Size {
98 return sect
99 }
100 }
101 }
102 }
103 return nil
104 }
105
106
107 func decodetypeGcprog(ctxt *Link, s *sym.Symbol) []byte {
108 if s.Type == sym.SDYNIMPORT {
109 addr := decodetypeGcprogShlib(ctxt, s)
110 sect := findShlibSection(ctxt, s.File, addr)
111 if sect != nil {
112
113
114 progsize := make([]byte, 4)
115 sect.ReadAt(progsize, int64(addr-sect.Addr))
116 progbytes := make([]byte, ctxt.Arch.ByteOrder.Uint32(progsize))
117 sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
118 return append(progsize, progbytes...)
119 }
120 Exitf("cannot find gcprog for %s", s.Name)
121 return nil
122 }
123 return decodeRelocSym(s, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize)).P
124 }
125
126 func decodetypeGcprogShlib(ctxt *Link, s *sym.Symbol) uint64 {
127 if ctxt.Arch.Family == sys.ARM64 {
128 for _, shlib := range ctxt.Shlibs {
129 if shlib.Path == s.File {
130 return shlib.gcdataAddresses[s]
131 }
132 }
133 return 0
134 }
135 return decodeInuxi(ctxt.Arch, s.P[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize)
136 }
137
138 func decodetypeGcmask(ctxt *Link, s *sym.Symbol) []byte {
139 if s.Type == sym.SDYNIMPORT {
140 addr := decodetypeGcprogShlib(ctxt, s)
141 ptrdata := decodetypePtrdata(ctxt.Arch, s)
142 sect := findShlibSection(ctxt, s.File, addr)
143 if sect != nil {
144 r := make([]byte, ptrdata/int64(ctxt.Arch.PtrSize))
145 sect.ReadAt(r, int64(addr-sect.Addr))
146 return r
147 }
148 Exitf("cannot find gcmask for %s", s.Name)
149 return nil
150 }
151 mask := decodeRelocSym(s, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize))
152 return mask.P
153 }
154
155
156 func decodetypeArrayElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
157 return decodeRelocSym(s, int32(commonsize(arch)))
158 }
159
160 func decodetypeArrayLen(arch *sys.Arch, s *sym.Symbol) int64 {
161 return int64(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
162 }
163
164
165 func decodetypePtrElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
166 return decodeRelocSym(s, int32(commonsize(arch)))
167 }
168
169
170 func decodetypeMapKey(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
171 return decodeRelocSym(s, int32(commonsize(arch)))
172 }
173
174 func decodetypeMapValue(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
175 return decodeRelocSym(s, int32(commonsize(arch))+int32(arch.PtrSize))
176 }
177
178
179 func decodetypeChanElem(arch *sys.Arch, s *sym.Symbol) *sym.Symbol {
180 return decodeRelocSym(s, int32(commonsize(arch)))
181 }
182
183
184 func decodetypeFuncDotdotdot(arch *sys.Arch, s *sym.Symbol) bool {
185 return uint16(decodeInuxi(arch, s.P[commonsize(arch)+2:], 2))&(1<<15) != 0
186 }
187
188
189 func decodetypeFuncInCount(arch *sys.Arch, s *sym.Symbol) int {
190 return int(decodeInuxi(arch, s.P[commonsize(arch):], 2))
191 }
192
193 func decodetypeFuncOutCount(arch *sys.Arch, s *sym.Symbol) int {
194 return int(uint16(decodeInuxi(arch, s.P[commonsize(arch)+2:], 2)) & (1<<15 - 1))
195 }
196
197 func decodetypeFuncInType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
198 uadd := commonsize(arch) + 4
199 if arch.PtrSize == 8 {
200 uadd += 4
201 }
202 if decodetypeHasUncommon(arch, s) {
203 uadd += uncommonSize()
204 }
205 return decodeRelocSym(s, int32(uadd+i*arch.PtrSize))
206 }
207
208 func decodetypeFuncOutType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
209 return decodetypeFuncInType(arch, s, i+decodetypeFuncInCount(arch, s))
210 }
211
212
213 func decodetypeStructFieldCount(arch *sys.Arch, s *sym.Symbol) int {
214 return int(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
215 }
216
217 func decodetypeStructFieldArrayOff(arch *sys.Arch, s *sym.Symbol, i int) int {
218 off := commonsize(arch) + 4*arch.PtrSize
219 if decodetypeHasUncommon(arch, s) {
220 off += uncommonSize()
221 }
222 off += i * structfieldSize(arch)
223 return off
224 }
225
226
227 func decodetypeStr(arch *sys.Arch, s *sym.Symbol) string {
228 str := decodetypeName(s, 4*arch.PtrSize+8)
229 if s.P[2*arch.PtrSize+4]&tflagExtraStar != 0 {
230 return str[1:]
231 }
232 return str
233 }
234
235
236 func decodetypeName(s *sym.Symbol, off int) string {
237 r := decodeReloc(s, int32(off))
238 if r == nil {
239 return ""
240 }
241
242 data := r.Sym.P
243 namelen := int(uint16(data[1])<<8 | uint16(data[2]))
244 return string(data[3 : 3+namelen])
245 }
246
247 func decodetypeStructFieldName(arch *sys.Arch, s *sym.Symbol, i int) string {
248 off := decodetypeStructFieldArrayOff(arch, s, i)
249 return decodetypeName(s, off)
250 }
251
252 func decodetypeStructFieldType(arch *sys.Arch, s *sym.Symbol, i int) *sym.Symbol {
253 off := decodetypeStructFieldArrayOff(arch, s, i)
254 return decodeRelocSym(s, int32(off+arch.PtrSize))
255 }
256
257 func decodetypeStructFieldOffs(arch *sys.Arch, s *sym.Symbol, i int) int64 {
258 return decodetypeStructFieldOffsAnon(arch, s, i) >> 1
259 }
260
261 func decodetypeStructFieldOffsAnon(arch *sys.Arch, s *sym.Symbol, i int) int64 {
262 off := decodetypeStructFieldArrayOff(arch, s, i)
263 return int64(decodeInuxi(arch, s.P[off+2*arch.PtrSize:], arch.PtrSize))
264 }
265
266
267 func decodetypeIfaceMethodCount(arch *sys.Arch, s *sym.Symbol) int64 {
268 return int64(decodeInuxi(arch, s.P[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
269 }
270
271
272
273 type methodsig string
274
275
276 const (
277 kindArray = 17
278 kindChan = 18
279 kindFunc = 19
280 kindInterface = 20
281 kindMap = 21
282 kindPtr = 22
283 kindSlice = 23
284 kindStruct = 25
285 kindMask = (1 << 5) - 1
286 )
287
288
289
290
291
292
293
294 func decodeMethodSig(arch *sys.Arch, s *sym.Symbol, off, size, count int) []methodsig {
295 var buf bytes.Buffer
296 var methods []methodsig
297 for i := 0; i < count; i++ {
298 buf.WriteString(decodetypeName(s, off))
299 mtypSym := decodeRelocSym(s, int32(off+4))
300
301 buf.WriteRune('(')
302 inCount := decodetypeFuncInCount(arch, mtypSym)
303 for i := 0; i < inCount; i++ {
304 if i > 0 {
305 buf.WriteString(", ")
306 }
307 buf.WriteString(decodetypeFuncInType(arch, mtypSym, i).Name)
308 }
309 buf.WriteString(") (")
310 outCount := decodetypeFuncOutCount(arch, mtypSym)
311 for i := 0; i < outCount; i++ {
312 if i > 0 {
313 buf.WriteString(", ")
314 }
315 buf.WriteString(decodetypeFuncOutType(arch, mtypSym, i).Name)
316 }
317 buf.WriteRune(')')
318
319 off += size
320 methods = append(methods, methodsig(buf.String()))
321 buf.Reset()
322 }
323 return methods
324 }
325
326 func decodeIfaceMethods(arch *sys.Arch, s *sym.Symbol) []methodsig {
327 if decodetypeKind(arch, s)&kindMask != kindInterface {
328 panic(fmt.Sprintf("symbol %q is not an interface", s.Name))
329 }
330 r := decodeReloc(s, int32(commonsize(arch)+arch.PtrSize))
331 if r == nil {
332 return nil
333 }
334 if r.Sym != s {
335 panic(fmt.Sprintf("imethod slice pointer in %q leads to a different symbol", s.Name))
336 }
337 off := int(r.Add)
338 numMethods := int(decodetypeIfaceMethodCount(arch, s))
339 sizeofIMethod := 4 + 4
340 return decodeMethodSig(arch, s, off, sizeofIMethod, numMethods)
341 }
342
343 func decodetypeMethods(arch *sys.Arch, s *sym.Symbol) []methodsig {
344 if !decodetypeHasUncommon(arch, s) {
345 panic(fmt.Sprintf("no methods on %q", s.Name))
346 }
347 off := commonsize(arch)
348 switch decodetypeKind(arch, s) & kindMask {
349 case kindStruct:
350 off += 4 * arch.PtrSize
351 case kindPtr:
352 off += arch.PtrSize
353 case kindFunc:
354 off += arch.PtrSize
355 case kindSlice:
356 off += arch.PtrSize
357 case kindArray:
358 off += 3 * arch.PtrSize
359 case kindChan:
360 off += 2 * arch.PtrSize
361 case kindMap:
362 off += 3*arch.PtrSize + 8
363 case kindInterface:
364 off += 3 * arch.PtrSize
365 default:
366
367 }
368
369 mcount := int(decodeInuxi(arch, s.P[off+4:], 2))
370 moff := int(decodeInuxi(arch, s.P[off+4+2+2:], 4))
371 off += moff
372 const sizeofMethod = 4 * 4
373 return decodeMethodSig(arch, s, off, sizeofMethod, mcount)
374 }
375
View as plain text