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 decodetypeUsegcprog(arch *sys.Arch, p []byte) bool {
46 return abi.Kind(p[2*arch.PtrSize+7])&abi.KindGCProg != 0
47 }
48
49
50 func decodetypeSize(arch *sys.Arch, p []byte) int64 {
51 return int64(decodeInuxi(arch, p, arch.PtrSize))
52 }
53
54
55 func decodetypePtrdata(arch *sys.Arch, p []byte) int64 {
56 return int64(decodeInuxi(arch, p[arch.PtrSize:], arch.PtrSize))
57 }
58
59
60 func decodetypeHasUncommon(arch *sys.Arch, p []byte) bool {
61 return abi.TFlag(p[abi.TFlagOff(arch.PtrSize)])&abi.TFlagUncommon != 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(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
138 relocs := ldr.Relocs(symIdx)
139 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch)))
140 }
141
142 func decodetypeArrayLen(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) int64 {
143 data := ldr.Data(symIdx)
144 return int64(decodeInuxi(arch, data[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
145 }
146
147 func decodetypeChanElem(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
148 relocs := ldr.Relocs(symIdx)
149 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch)))
150 }
151
152 func decodetypeMapKey(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
153 relocs := ldr.Relocs(symIdx)
154 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch)))
155 }
156
157 func decodetypeMapValue(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
158 relocs := ldr.Relocs(symIdx)
159 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch))+int32(arch.PtrSize))
160 }
161
162 func decodetypeMapSwissGroup(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
163 relocs := ldr.Relocs(symIdx)
164 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch))+2*int32(arch.PtrSize))
165 }
166
167 func decodetypePtrElem(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
168 relocs := ldr.Relocs(symIdx)
169 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch)))
170 }
171
172 func decodetypeStructFieldCount(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) int {
173 data := ldr.Data(symIdx)
174 return int(decodeInuxi(arch, data[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
175 }
176
177 func decodetypeStructFieldArrayOff(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int {
178 data := ldr.Data(symIdx)
179 off := commonsize(arch) + 4*arch.PtrSize
180 if decodetypeHasUncommon(arch, data) {
181 off += uncommonSize(arch)
182 }
183 off += i * structfieldSize(arch)
184 return off
185 }
186
187 func decodetypeStructFieldName(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) string {
188 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
189 relocs := ldr.Relocs(symIdx)
190 return decodetypeName(ldr, symIdx, &relocs, off)
191 }
192
193 func decodetypeStructFieldType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) loader.Sym {
194 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
195 relocs := ldr.Relocs(symIdx)
196 return decodeRelocSym(ldr, symIdx, &relocs, int32(off+arch.PtrSize))
197 }
198
199 func decodetypeStructFieldOffset(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int64 {
200 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
201 data := ldr.Data(symIdx)
202 return int64(decodeInuxi(arch, data[off+2*arch.PtrSize:], arch.PtrSize))
203 }
204
205 func decodetypeStructFieldEmbedded(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) bool {
206 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
207 relocs := ldr.Relocs(symIdx)
208 return decodetypeNameEmbedded(ldr, symIdx, &relocs, off)
209 }
210
211
212 func decodetypeStr(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) string {
213 relocs := ldr.Relocs(symIdx)
214 str := decodetypeName(ldr, symIdx, &relocs, 4*arch.PtrSize+8)
215 data := ldr.Data(symIdx)
216 if data[abi.TFlagOff(arch.PtrSize)]&byte(abi.TFlagExtraStar) != 0 {
217 return str[1:]
218 }
219 return str
220 }
221
222 func decodetypeGcmask(ctxt *Link, s loader.Sym) []byte {
223 if ctxt.loader.SymType(s) == sym.SDYNIMPORT {
224 symData := ctxt.loader.Data(s)
225 addr := decodetypeGcprogShlib(ctxt, symData)
226 ptrdata := decodetypePtrdata(ctxt.Arch, symData)
227 sect := findShlibSection(ctxt, ctxt.loader.SymPkg(s), addr)
228 if sect != nil {
229 bits := ptrdata / int64(ctxt.Arch.PtrSize)
230 r := make([]byte, (bits+7)/8)
231
232
233
234 _, err := sect.ReadAt(r, int64(addr-sect.Addr))
235 if err != nil {
236 log.Fatal(err)
237 }
238 return r
239 }
240 Exitf("cannot find gcmask for %s", ctxt.loader.SymName(s))
241 return nil
242 }
243 relocs := ctxt.loader.Relocs(s)
244 mask := decodeRelocSym(ctxt.loader, s, &relocs, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize))
245 return ctxt.loader.Data(mask)
246 }
247
248
249 func decodetypeGcprog(ctxt *Link, s loader.Sym) []byte {
250 if ctxt.loader.SymType(s) == sym.SDYNIMPORT {
251 symData := ctxt.loader.Data(s)
252 addr := decodetypeGcprogShlib(ctxt, symData)
253 sect := findShlibSection(ctxt, ctxt.loader.SymPkg(s), addr)
254 if sect != nil {
255
256
257 progsize := make([]byte, 4)
258 _, err := sect.ReadAt(progsize, int64(addr-sect.Addr))
259 if err != nil {
260 log.Fatal(err)
261 }
262 progbytes := make([]byte, ctxt.Arch.ByteOrder.Uint32(progsize))
263 _, err = sect.ReadAt(progbytes, int64(addr-sect.Addr+4))
264 if err != nil {
265 log.Fatal(err)
266 }
267 return append(progsize, progbytes...)
268 }
269 Exitf("cannot find gcprog for %s", ctxt.loader.SymName(s))
270 return nil
271 }
272 relocs := ctxt.loader.Relocs(s)
273 rs := decodeRelocSym(ctxt.loader, s, &relocs, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize))
274 return ctxt.loader.Data(rs)
275 }
276
277
278 func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section {
279 for _, shlib := range ctxt.Shlibs {
280 if shlib.Path == path {
281 for _, sect := range shlib.File.Sections[1:] {
282 if sect.Addr <= addr && addr < sect.Addr+sect.Size {
283 return sect
284 }
285 }
286 }
287 }
288 return nil
289 }
290
291 func decodetypeGcprogShlib(ctxt *Link, data []byte) uint64 {
292 return decodeInuxi(ctxt.Arch, data[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize)
293 }
294
295
296 func decodeItabType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
297 relocs := ldr.Relocs(symIdx)
298 return decodeRelocSym(ldr, symIdx, &relocs, int32(abi.ITabTypeOff(arch.PtrSize)))
299 }
300
View as plain text