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