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