1
2
3
4
5 package ld
6
7 import (
8 "cmd/internal/objabi"
9 "cmd/internal/sys"
10 "cmd/link/internal/loader"
11 "cmd/link/internal/sym"
12 "debug/elf"
13 "encoding/binary"
14 "internal/abi"
15 "log"
16 )
17
18
19
20
21
22 func decodeInuxi(arch *sys.Arch, p []byte, sz int) uint64 {
23 switch sz {
24 case 2:
25 return uint64(arch.ByteOrder.Uint16(p))
26 case 4:
27 return uint64(arch.ByteOrder.Uint32(p))
28 case 8:
29 return arch.ByteOrder.Uint64(p)
30 default:
31 Exitf("dwarf: decode inuxi %d", sz)
32 panic("unreachable")
33 }
34 }
35
36 func commonsize(arch *sys.Arch) int { return abi.CommonSize(arch.PtrSize) }
37 func structfieldSize(arch *sys.Arch) int { return abi.StructFieldSize(arch.PtrSize) }
38 func uncommonSize(arch *sys.Arch) int { return int(abi.UncommonSize()) }
39
40
41 func decodetypeKind(arch *sys.Arch, p []byte) uint8 {
42 return p[2*arch.PtrSize+7] & objabi.KindMask
43 }
44
45
46 func decodetypeUsegcprog(arch *sys.Arch, p []byte) uint8 {
47 return p[2*arch.PtrSize+7] & objabi.KindGCProg
48 }
49
50
51 func decodetypeSize(arch *sys.Arch, p []byte) int64 {
52 return int64(decodeInuxi(arch, p, arch.PtrSize))
53 }
54
55
56 func decodetypePtrdata(arch *sys.Arch, p []byte) int64 {
57 return int64(decodeInuxi(arch, p[arch.PtrSize:], arch.PtrSize))
58 }
59
60
61 func decodetypeHasUncommon(arch *sys.Arch, p []byte) bool {
62 return abi.TFlag(p[abi.TFlagOff(arch.PtrSize)])&abi.TFlagUncommon != 0
63 }
64
65
66 func decodetypeFuncDotdotdot(arch *sys.Arch, p []byte) bool {
67 return uint16(decodeInuxi(arch, p[commonsize(arch)+2:], 2))&(1<<15) != 0
68 }
69
70
71 func decodetypeFuncInCount(arch *sys.Arch, p []byte) int {
72 return int(decodeInuxi(arch, p[commonsize(arch):], 2))
73 }
74
75 func decodetypeFuncOutCount(arch *sys.Arch, p []byte) int {
76 return int(uint16(decodeInuxi(arch, p[commonsize(arch)+2:], 2)) & (1<<15 - 1))
77 }
78
79
80 func decodetypeIfaceMethodCount(arch *sys.Arch, p []byte) int64 {
81 return int64(decodeInuxi(arch, p[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
82 }
83
84
85 const (
86 kindArray = 17
87 kindChan = 18
88 kindFunc = 19
89 kindInterface = 20
90 kindMap = 21
91 kindPtr = 22
92 kindSlice = 23
93 kindStruct = 25
94 kindMask = (1 << 5) - 1
95 )
96
97 func decodeReloc(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int32) loader.Reloc {
98 for j := 0; j < relocs.Count(); j++ {
99 rel := relocs.At(j)
100 if rel.Off() == off {
101 return rel
102 }
103 }
104 return loader.Reloc{}
105 }
106
107 func decodeRelocSym(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int32) loader.Sym {
108 return decodeReloc(ldr, symIdx, relocs, off).Sym()
109 }
110
111
112 func decodetypeName(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int) string {
113 r := decodeRelocSym(ldr, symIdx, relocs, int32(off))
114 if r == 0 {
115 return ""
116 }
117
118 data := ldr.DataString(r)
119 n := 1 + binary.MaxVarintLen64
120 if len(data) < n {
121 n = len(data)
122 }
123 nameLen, nameLenLen := binary.Uvarint([]byte(data[1:n]))
124 return data[1+nameLenLen : 1+nameLenLen+int(nameLen)]
125 }
126
127 func decodetypeNameEmbedded(ldr *loader.Loader, symIdx loader.Sym, relocs *loader.Relocs, off int) bool {
128 r := decodeRelocSym(ldr, symIdx, relocs, int32(off))
129 if r == 0 {
130 return false
131 }
132 data := ldr.Data(r)
133 return data[0]&(1<<3) != 0
134 }
135
136 func decodetypeFuncInType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym {
137 uadd := commonsize(arch) + 4
138 if arch.PtrSize == 8 {
139 uadd += 4
140 }
141 if decodetypeHasUncommon(arch, ldr.Data(symIdx)) {
142 uadd += uncommonSize(arch)
143 }
144 return decodeRelocSym(ldr, symIdx, relocs, int32(uadd+i*arch.PtrSize))
145 }
146
147 func decodetypeFuncOutType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym {
148 return decodetypeFuncInType(ldr, arch, symIdx, relocs, i+decodetypeFuncInCount(arch, ldr.Data(symIdx)))
149 }
150
151 func decodetypeArrayElem(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
152 relocs := ldr.Relocs(symIdx)
153 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch)))
154 }
155
156 func decodetypeArrayLen(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) int64 {
157 data := ldr.Data(symIdx)
158 return int64(decodeInuxi(arch, data[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
159 }
160
161 func decodetypeChanElem(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
162 relocs := ldr.Relocs(symIdx)
163 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch)))
164 }
165
166 func decodetypeMapKey(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
167 relocs := ldr.Relocs(symIdx)
168 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch)))
169 }
170
171 func decodetypeMapValue(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
172 relocs := ldr.Relocs(symIdx)
173 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch))+int32(arch.PtrSize))
174 }
175
176 func decodetypePtrElem(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
177 relocs := ldr.Relocs(symIdx)
178 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch)))
179 }
180
181 func decodetypeStructFieldCount(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) int {
182 data := ldr.Data(symIdx)
183 return int(decodeInuxi(arch, data[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
184 }
185
186 func decodetypeStructFieldArrayOff(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int {
187 data := ldr.Data(symIdx)
188 off := commonsize(arch) + 4*arch.PtrSize
189 if decodetypeHasUncommon(arch, data) {
190 off += uncommonSize(arch)
191 }
192 off += i * structfieldSize(arch)
193 return off
194 }
195
196 func decodetypeStructFieldName(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) string {
197 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
198 relocs := ldr.Relocs(symIdx)
199 return decodetypeName(ldr, symIdx, &relocs, off)
200 }
201
202 func decodetypeStructFieldType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) loader.Sym {
203 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
204 relocs := ldr.Relocs(symIdx)
205 return decodeRelocSym(ldr, symIdx, &relocs, int32(off+arch.PtrSize))
206 }
207
208 func decodetypeStructFieldOffset(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int64 {
209 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
210 data := ldr.Data(symIdx)
211 return int64(decodeInuxi(arch, data[off+2*arch.PtrSize:], arch.PtrSize))
212 }
213
214 func decodetypeStructFieldEmbedded(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) bool {
215 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
216 relocs := ldr.Relocs(symIdx)
217 return decodetypeNameEmbedded(ldr, symIdx, &relocs, off)
218 }
219
220
221 func decodetypeStr(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) string {
222 relocs := ldr.Relocs(symIdx)
223 str := decodetypeName(ldr, symIdx, &relocs, 4*arch.PtrSize+8)
224 data := ldr.Data(symIdx)
225 if data[abi.TFlagOff(arch.PtrSize)]&byte(abi.TFlagExtraStar) != 0 {
226 return str[1:]
227 }
228 return str
229 }
230
231 func decodetypeGcmask(ctxt *Link, s loader.Sym) []byte {
232 if ctxt.loader.SymType(s) == sym.SDYNIMPORT {
233 symData := ctxt.loader.Data(s)
234 addr := decodetypeGcprogShlib(ctxt, symData)
235 ptrdata := decodetypePtrdata(ctxt.Arch, symData)
236 sect := findShlibSection(ctxt, ctxt.loader.SymPkg(s), addr)
237 if sect != nil {
238 bits := ptrdata / int64(ctxt.Arch.PtrSize)
239 r := make([]byte, (bits+7)/8)
240
241
242
243 _, err := sect.ReadAt(r, int64(addr-sect.Addr))
244 if err != nil {
245 log.Fatal(err)
246 }
247 return r
248 }
249 Exitf("cannot find gcmask for %s", ctxt.loader.SymName(s))
250 return nil
251 }
252 relocs := ctxt.loader.Relocs(s)
253 mask := decodeRelocSym(ctxt.loader, s, &relocs, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize))
254 return ctxt.loader.Data(mask)
255 }
256
257
258 func decodetypeGcprog(ctxt *Link, s loader.Sym) []byte {
259 if ctxt.loader.SymType(s) == sym.SDYNIMPORT {
260 symData := ctxt.loader.Data(s)
261 addr := decodetypeGcprogShlib(ctxt, symData)
262 sect := findShlibSection(ctxt, ctxt.loader.SymPkg(s), addr)
263 if sect != nil {
264
265
266 progsize := make([]byte, 4)
267 _, err := sect.ReadAt(progsize, int64(addr-sect.Addr))
268 if err != nil {
269 log.Fatal(err)
270 }
271 progbytes := make([]byte, ctxt.Arch.ByteOrder.Uint32(progsize))
272 _, err = sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
273 if err != nil {
274 log.Fatal(err)
275 }
276 return append(progsize, progbytes...)
277 }
278 Exitf("cannot find gcmask for %s", ctxt.loader.SymName(s))
279 return nil
280 }
281 relocs := ctxt.loader.Relocs(s)
282 rs := decodeRelocSym(ctxt.loader, s, &relocs, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize))
283 return ctxt.loader.Data(rs)
284 }
285
286
287 func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section {
288 for _, shlib := range ctxt.Shlibs {
289 if shlib.Path == path {
290 for _, sect := range shlib.File.Sections[1:] {
291 if sect.Addr <= addr && addr < sect.Addr+sect.Size {
292 return sect
293 }
294 }
295 }
296 }
297 return nil
298 }
299
300 func decodetypeGcprogShlib(ctxt *Link, data []byte) uint64 {
301 return decodeInuxi(ctxt.Arch, data[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize)
302 }
303
304
305 func decodeItabType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
306 relocs := ldr.Relocs(symIdx)
307 return decodeRelocSym(ldr, symIdx, &relocs, int32(arch.PtrSize))
308 }
309
View as plain text