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