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])
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 := abi.RTypeSize(abi.Func, arch.PtrSize)
124 if decodetypeHasUncommon(arch, ldr.Data(symIdx)) {
125 uadd += uncommonSize(arch)
126 }
127 return decodeRelocSym(ldr, symIdx, relocs, int32(uadd+i*arch.PtrSize))
128 }
129
130 func decodetypeFuncOutType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, relocs *loader.Relocs, i int) loader.Sym {
131 return decodetypeFuncInType(ldr, arch, symIdx, relocs, i+decodetypeFuncInCount(arch, ldr.Data(symIdx)))
132 }
133
134 func decodetypeArrayElem(ctxt *Link, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
135 return decodeTargetSym(ctxt, arch, symIdx, int64(commonsize(arch)))
136 }
137
138 func decodetypeArrayLen(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) int64 {
139 data := ldr.Data(symIdx)
140 return int64(decodeInuxi(arch, data[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
141 }
142
143 func decodetypeChanElem(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
144 relocs := ldr.Relocs(symIdx)
145 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch)))
146 }
147
148 func decodetypeMapKey(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
149 relocs := ldr.Relocs(symIdx)
150 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch)))
151 }
152
153 func decodetypeMapValue(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
154 relocs := ldr.Relocs(symIdx)
155 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch))+int32(arch.PtrSize))
156 }
157
158 func decodetypeMapGroup(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
159 relocs := ldr.Relocs(symIdx)
160 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch))+2*int32(arch.PtrSize))
161 }
162
163 func decodetypePtrElem(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
164 relocs := ldr.Relocs(symIdx)
165 return decodeRelocSym(ldr, symIdx, &relocs, int32(commonsize(arch)))
166 }
167
168 func decodetypeStructFieldCount(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) int {
169 data := ldr.Data(symIdx)
170 return int(decodeInuxi(arch, data[commonsize(arch)+2*arch.PtrSize:], arch.PtrSize))
171 }
172
173 func decodetypeStructFieldArrayOff(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int {
174 data := ldr.Data(symIdx)
175 off := abi.RTypeSize(abi.Struct, arch.PtrSize)
176 if decodetypeHasUncommon(arch, data) {
177 off += uncommonSize(arch)
178 }
179 off += i * structfieldSize(arch)
180 return off
181 }
182
183 func decodetypeStructFieldName(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) string {
184 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
185 relocs := ldr.Relocs(symIdx)
186 return decodetypeName(ldr, symIdx, &relocs, off)
187 }
188
189 func decodetypeStructFieldType(ctxt *Link, arch *sys.Arch, symIdx loader.Sym, i int) loader.Sym {
190 ldr := ctxt.loader
191 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
192 return decodeTargetSym(ctxt, arch, symIdx, int64(off+arch.PtrSize))
193 }
194
195 func decodetypeStructFieldOffset(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) int64 {
196 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
197 data := ldr.Data(symIdx)
198 return int64(decodeInuxi(arch, data[off+2*arch.PtrSize:], arch.PtrSize))
199 }
200
201 func decodetypeStructFieldEmbedded(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym, i int) bool {
202 off := decodetypeStructFieldArrayOff(ldr, arch, symIdx, i)
203 relocs := ldr.Relocs(symIdx)
204 return decodetypeNameEmbedded(ldr, symIdx, &relocs, off)
205 }
206
207
208 func decodetypeStr(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) string {
209 relocs := ldr.Relocs(symIdx)
210 str := decodetypeName(ldr, symIdx, &relocs, 4*arch.PtrSize+8)
211 data := ldr.Data(symIdx)
212 if data[abi.TFlagOff(arch.PtrSize)]&byte(abi.TFlagExtraStar) != 0 {
213 return str[1:]
214 }
215 return str
216 }
217
218 func decodetypeGcmask(ctxt *Link, s loader.Sym) []byte {
219 if ctxt.loader.SymType(s) == sym.SDYNIMPORT {
220 symData := ctxt.loader.Data(s)
221 addr := decodetypeGcprogShlib(ctxt, symData)
222 ptrdata := decodetypePtrdata(ctxt.Arch, symData)
223 sect := findShlibSection(ctxt, ctxt.loader.SymPkg(s), addr)
224 if sect != nil {
225 bits := ptrdata / int64(ctxt.Arch.PtrSize)
226 r := make([]byte, (bits+7)/8)
227
228
229
230 _, err := sect.ReadAt(r, int64(addr-sect.Addr))
231 if err != nil {
232 log.Fatal(err)
233 }
234 return r
235 }
236 Exitf("cannot find gcmask for %s", ctxt.loader.SymName(s))
237 return nil
238 }
239 relocs := ctxt.loader.Relocs(s)
240 mask := decodeRelocSym(ctxt.loader, s, &relocs, 2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize))
241 return ctxt.loader.Data(mask)
242 }
243
244
245 func findShlibSection(ctxt *Link, path string, addr uint64) *elf.Section {
246 for _, shlib := range ctxt.Shlibs {
247 if shlib.Path == path {
248 for _, sect := range shlib.File.Sections[1:] {
249 if sect.Addr <= addr && addr < sect.Addr+sect.Size {
250 return sect
251 }
252 }
253 }
254 }
255 return nil
256 }
257
258 func decodetypeGcprogShlib(ctxt *Link, data []byte) uint64 {
259 return decodeInuxi(ctxt.Arch, data[2*int32(ctxt.Arch.PtrSize)+8+1*int32(ctxt.Arch.PtrSize):], ctxt.Arch.PtrSize)
260 }
261
262
263 func decodeItabType(ldr *loader.Loader, arch *sys.Arch, symIdx loader.Sym) loader.Sym {
264 relocs := ldr.Relocs(symIdx)
265 return decodeRelocSym(ldr, symIdx, &relocs, int32(abi.ITabTypeOff(arch.PtrSize)))
266 }
267
268
269 func decodeTargetSym(ctxt *Link, arch *sys.Arch, s loader.Sym, off int64) loader.Sym {
270 ldr := ctxt.loader
271 if ldr.SymType(s) == sym.SDYNIMPORT {
272
273
274
275
276 name := ldr.SymName(s)
277 for _, sh := range ctxt.Shlibs {
278 addr, ok := sh.symAddr[name]
279 if !ok {
280 continue
281 }
282 addr += uint64(off)
283 target := sh.relocTarget[addr]
284 if target == "" {
285 Exitf("can't find relocation in %s at offset %d", name, off)
286 }
287 t := ldr.Lookup(target, 0)
288 if t == 0 {
289 Exitf("can't find target of relocation in %s at offset %d: %s", name, off, target)
290 }
291 return t
292 }
293 }
294
295
296
297 relocs := ldr.Relocs(s)
298 return decodeRelocSym(ldr, s, &relocs, int32(off))
299 }
300
View as plain text