1
2
3
4
5 package pkgbits
6
7 import (
8 "encoding/binary"
9 "errors"
10 "fmt"
11 "go/constant"
12 "go/token"
13 "io"
14 "math/big"
15 "os"
16 "runtime"
17 "strings"
18 )
19
20
21
22 type PkgDecoder struct {
23
24 version Version
25
26
27 sync bool
28
29
30
31
32 pkgPath string
33
34
35
36
37
38 elemData string
39
40
41
42
43
44
45
46
47
48 elemEnds []uint32
49
50
51
52
53
54
55 elemEndsEnds [numRelocs]uint32
56
57 scratchRelocEnt []RelocEnt
58 }
59
60
61
62
63 func (pr *PkgDecoder) PkgPath() string { return pr.pkgPath }
64
65
66 func (pr *PkgDecoder) SyncMarkers() bool { return pr.sync }
67
68
69
70
71 func NewPkgDecoder(pkgPath, input string) PkgDecoder {
72 pr := PkgDecoder{
73 pkgPath: pkgPath,
74 }
75
76
77
78
79 r := strings.NewReader(input)
80
81 var ver uint32
82 assert(binary.Read(r, binary.LittleEndian, &ver) == nil)
83 pr.version = Version(ver)
84
85 if pr.version >= numVersions {
86 panic(fmt.Errorf("cannot decode %q, export data version %d is greater than maximum supported version %d", pkgPath, pr.version, numVersions-1))
87 }
88
89 if pr.version.Has(Flags) {
90 var flags uint32
91 assert(binary.Read(r, binary.LittleEndian, &flags) == nil)
92 pr.sync = flags&flagSyncMarkers != 0
93 }
94
95 assert(binary.Read(r, binary.LittleEndian, pr.elemEndsEnds[:]) == nil)
96
97 pr.elemEnds = make([]uint32, pr.elemEndsEnds[len(pr.elemEndsEnds)-1])
98 assert(binary.Read(r, binary.LittleEndian, pr.elemEnds[:]) == nil)
99
100 pos, err := r.Seek(0, io.SeekCurrent)
101 assert(err == nil)
102
103 pr.elemData = input[pos:]
104
105 const fingerprintSize = 8
106 assert(len(pr.elemData)-fingerprintSize == int(pr.elemEnds[len(pr.elemEnds)-1]))
107
108 return pr
109 }
110
111
112 func (pr *PkgDecoder) NumElems(k RelocKind) int {
113 count := int(pr.elemEndsEnds[k])
114 if k > 0 {
115 count -= int(pr.elemEndsEnds[k-1])
116 }
117 return count
118 }
119
120
121 func (pr *PkgDecoder) TotalElems() int {
122 return len(pr.elemEnds)
123 }
124
125
126 func (pr *PkgDecoder) Fingerprint() [8]byte {
127 var fp [8]byte
128 copy(fp[:], pr.elemData[len(pr.elemData)-8:])
129 return fp
130 }
131
132
133
134 func (pr *PkgDecoder) AbsIdx(k RelocKind, idx Index) int {
135 absIdx := int(idx)
136 if k > 0 {
137 absIdx += int(pr.elemEndsEnds[k-1])
138 }
139 if absIdx >= int(pr.elemEndsEnds[k]) {
140 panicf("%v:%v is out of bounds; %v", k, idx, pr.elemEndsEnds)
141 }
142 return absIdx
143 }
144
145
146
147 func (pr *PkgDecoder) DataIdx(k RelocKind, idx Index) string {
148 absIdx := pr.AbsIdx(k, idx)
149
150 var start uint32
151 if absIdx > 0 {
152 start = pr.elemEnds[absIdx-1]
153 }
154 end := pr.elemEnds[absIdx]
155
156 return pr.elemData[start:end]
157 }
158
159
160 func (pr *PkgDecoder) StringIdx(idx Index) string {
161 return pr.DataIdx(RelocString, idx)
162 }
163
164
165
166 func (pr *PkgDecoder) NewDecoder(k RelocKind, idx Index, marker SyncMarker) Decoder {
167 r := pr.NewDecoderRaw(k, idx)
168 r.Sync(marker)
169 return r
170 }
171
172
173
174
175
176 func (pr *PkgDecoder) TempDecoder(k RelocKind, idx Index, marker SyncMarker) Decoder {
177 r := pr.TempDecoderRaw(k, idx)
178 r.Sync(marker)
179 return r
180 }
181
182 func (pr *PkgDecoder) RetireDecoder(d *Decoder) {
183 pr.scratchRelocEnt = d.Relocs
184 d.Relocs = nil
185 }
186
187
188
189
190 func (pr *PkgDecoder) NewDecoderRaw(k RelocKind, idx Index) Decoder {
191 r := Decoder{
192 common: pr,
193 k: k,
194 Idx: idx,
195 }
196
197 r.Data.Reset(pr.DataIdx(k, idx))
198 r.Sync(SyncRelocs)
199 r.Relocs = make([]RelocEnt, r.Len())
200 for i := range r.Relocs {
201 r.Sync(SyncReloc)
202 r.Relocs[i] = RelocEnt{RelocKind(r.Len()), Index(r.Len())}
203 }
204
205 return r
206 }
207
208 func (pr *PkgDecoder) TempDecoderRaw(k RelocKind, idx Index) Decoder {
209 r := Decoder{
210 common: pr,
211 k: k,
212 Idx: idx,
213 }
214
215 r.Data.Reset(pr.DataIdx(k, idx))
216 r.Sync(SyncRelocs)
217 l := r.Len()
218 if cap(pr.scratchRelocEnt) >= l {
219 r.Relocs = pr.scratchRelocEnt[:l]
220 pr.scratchRelocEnt = nil
221 } else {
222 r.Relocs = make([]RelocEnt, l)
223 }
224 for i := range r.Relocs {
225 r.Sync(SyncReloc)
226 r.Relocs[i] = RelocEnt{RelocKind(r.Len()), Index(r.Len())}
227 }
228
229 return r
230 }
231
232
233
234 type Decoder struct {
235 common *PkgDecoder
236
237 Relocs []RelocEnt
238 Data strings.Reader
239
240 k RelocKind
241 Idx Index
242 }
243
244 func (r *Decoder) checkErr(err error) {
245 if err != nil {
246 panicf("unexpected decoding error: %w", err)
247 }
248 }
249
250 func (r *Decoder) rawUvarint() uint64 {
251 x, err := readUvarint(&r.Data)
252 r.checkErr(err)
253 return x
254 }
255
256
257
258
259 func readUvarint(r *strings.Reader) (uint64, error) {
260 var x uint64
261 var s uint
262 for i := 0; i < binary.MaxVarintLen64; i++ {
263 b, err := r.ReadByte()
264 if err != nil {
265 if i > 0 && err == io.EOF {
266 err = io.ErrUnexpectedEOF
267 }
268 return x, err
269 }
270 if b < 0x80 {
271 if i == binary.MaxVarintLen64-1 && b > 1 {
272 return x, overflow
273 }
274 return x | uint64(b)<<s, nil
275 }
276 x |= uint64(b&0x7f) << s
277 s += 7
278 }
279 return x, overflow
280 }
281
282 var overflow = errors.New("pkgbits: readUvarint overflows a 64-bit integer")
283
284 func (r *Decoder) rawVarint() int64 {
285 ux := r.rawUvarint()
286
287
288 x := int64(ux >> 1)
289 if ux&1 != 0 {
290 x = ^x
291 }
292 return x
293 }
294
295 func (r *Decoder) rawReloc(k RelocKind, idx int) Index {
296 e := r.Relocs[idx]
297 assert(e.Kind == k)
298 return e.Idx
299 }
300
301
302
303
304
305 func (r *Decoder) Sync(mWant SyncMarker) {
306 if !r.common.sync {
307 return
308 }
309
310 pos, _ := r.Data.Seek(0, io.SeekCurrent)
311 mHave := SyncMarker(r.rawUvarint())
312 writerPCs := make([]int, r.rawUvarint())
313 for i := range writerPCs {
314 writerPCs[i] = int(r.rawUvarint())
315 }
316
317 if mHave == mWant {
318 return
319 }
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337 fmt.Printf("export data desync: package %q, section %v, index %v, offset %v\n", r.common.pkgPath, r.k, r.Idx, pos)
338
339 fmt.Printf("\nfound %v, written at:\n", mHave)
340 if len(writerPCs) == 0 {
341 fmt.Printf("\t[stack trace unavailable; recompile package %q with -d=syncframes]\n", r.common.pkgPath)
342 }
343 for _, pc := range writerPCs {
344 fmt.Printf("\t%s\n", r.common.StringIdx(r.rawReloc(RelocString, pc)))
345 }
346
347 fmt.Printf("\nexpected %v, reading at:\n", mWant)
348 var readerPCs [32]uintptr
349 n := runtime.Callers(2, readerPCs[:])
350 for _, pc := range fmtFrames(readerPCs[:n]...) {
351 fmt.Printf("\t%s\n", pc)
352 }
353
354
355
356
357 os.Exit(1)
358 }
359
360
361 func (r *Decoder) Bool() bool {
362 r.Sync(SyncBool)
363 x, err := r.Data.ReadByte()
364 r.checkErr(err)
365 assert(x < 2)
366 return x != 0
367 }
368
369
370 func (r *Decoder) Int64() int64 {
371 r.Sync(SyncInt64)
372 return r.rawVarint()
373 }
374
375
376 func (r *Decoder) Uint64() uint64 {
377 r.Sync(SyncUint64)
378 return r.rawUvarint()
379 }
380
381
382 func (r *Decoder) Len() int { x := r.Uint64(); v := int(x); assert(uint64(v) == x); return v }
383
384
385 func (r *Decoder) Int() int { x := r.Int64(); v := int(x); assert(int64(v) == x); return v }
386
387
388 func (r *Decoder) Uint() uint { x := r.Uint64(); v := uint(x); assert(uint64(v) == x); return v }
389
390
391
392
393
394
395
396
397 func (r *Decoder) Code(mark SyncMarker) int {
398 r.Sync(mark)
399 return r.Len()
400 }
401
402
403
404 func (r *Decoder) Reloc(k RelocKind) Index {
405 r.Sync(SyncUseReloc)
406 return r.rawReloc(k, r.Len())
407 }
408
409
410
411 func (r *Decoder) String() string {
412 r.Sync(SyncString)
413 return r.common.StringIdx(r.Reloc(RelocString))
414 }
415
416
417
418 func (r *Decoder) Strings() []string {
419 res := make([]string, r.Len())
420 for i := range res {
421 res[i] = r.String()
422 }
423 return res
424 }
425
426
427
428 func (r *Decoder) Value() constant.Value {
429 r.Sync(SyncValue)
430 isComplex := r.Bool()
431 val := r.scalar()
432 if isComplex {
433 val = constant.BinaryOp(val, token.ADD, constant.MakeImag(r.scalar()))
434 }
435 return val
436 }
437
438 func (r *Decoder) scalar() constant.Value {
439 switch tag := CodeVal(r.Code(SyncVal)); tag {
440 default:
441 panic(fmt.Errorf("unexpected scalar tag: %v", tag))
442
443 case ValBool:
444 return constant.MakeBool(r.Bool())
445 case ValString:
446 return constant.MakeString(r.String())
447 case ValInt64:
448 return constant.MakeInt64(r.Int64())
449 case ValBigInt:
450 return constant.Make(r.bigInt())
451 case ValBigRat:
452 num := r.bigInt()
453 denom := r.bigInt()
454 return constant.Make(new(big.Rat).SetFrac(num, denom))
455 case ValBigFloat:
456 return constant.Make(r.bigFloat())
457 }
458 }
459
460 func (r *Decoder) bigInt() *big.Int {
461 v := new(big.Int).SetBytes([]byte(r.String()))
462 if r.Bool() {
463 v.Neg(v)
464 }
465 return v
466 }
467
468 func (r *Decoder) bigFloat() *big.Float {
469 v := new(big.Float).SetPrec(512)
470 assert(v.UnmarshalText([]byte(r.String())) == nil)
471 return v
472 }
473
474
475
476
477
478
479
480
481 func (pr *PkgDecoder) PeekPkgPath(idx Index) string {
482 var path string
483 {
484 r := pr.TempDecoder(RelocPkg, idx, SyncPkgDef)
485 path = r.String()
486 pr.RetireDecoder(&r)
487 }
488 if path == "" {
489 path = pr.pkgPath
490 }
491 return path
492 }
493
494
495
496 func (pr *PkgDecoder) PeekObj(idx Index) (string, string, CodeObj) {
497 var ridx Index
498 var name string
499 var rcode int
500 {
501 r := pr.TempDecoder(RelocName, idx, SyncObject1)
502 r.Sync(SyncSym)
503 r.Sync(SyncPkg)
504 ridx = r.Reloc(RelocPkg)
505 name = r.String()
506 rcode = r.Code(SyncCodeObj)
507 pr.RetireDecoder(&r)
508 }
509
510 path := pr.PeekPkgPath(ridx)
511 assert(name != "")
512
513 tag := CodeObj(rcode)
514
515 return path, name, tag
516 }
517
518
519 func (w *Decoder) Version() Version { return w.common.version }
520
View as plain text