1
2
3
4
5
6
7
8
9 package gob
10
11
12
13
14
15
16
17 import (
18 "bytes"
19 "fmt"
20 "io"
21 "os"
22 "strings"
23 "sync"
24 )
25
26 var dumpBytes = false
27
28
29
30 func init() {
31 debugFunc = Debug
32 }
33
34 var (
35 blanks = bytes.Repeat([]byte{' '}, 3*10)
36 empty = []byte(": <empty>\n")
37 tabs = strings.Repeat("\t", 100)
38 )
39
40
41 type tab int
42
43 func (t tab) String() string {
44 n := int(t)
45 if n > len(tabs) {
46 n = len(tabs)
47 }
48 return tabs[0:n]
49 }
50
51 func (t tab) print() {
52 fmt.Fprint(os.Stderr, t)
53 }
54
55
56
57 type peekReader struct {
58 r io.Reader
59 data []byte
60 }
61
62
63 func newPeekReader(r io.Reader) *peekReader {
64 return &peekReader{r: r}
65 }
66
67
68 func (p *peekReader) Read(b []byte) (n int, err error) {
69 if len(p.data) == 0 {
70 return p.r.Read(b)
71 }
72
73 n = copy(b, p.data)
74
75 copy(p.data, p.data[n:])
76 p.data = p.data[:len(p.data)-n]
77 return
78 }
79
80
81
82 func (p *peekReader) peek(b []byte) (n int, err error) {
83 if len(p.data) > 0 {
84 n = copy(b, p.data)
85 if n == len(b) {
86 return
87 }
88 b = b[n:]
89 }
90 if len(b) == 0 {
91 return
92 }
93 m, e := io.ReadFull(p.r, b)
94 if m > 0 {
95 p.data = append(p.data, b[:m]...)
96 }
97 n += m
98 if e == io.ErrUnexpectedEOF {
99
100
101 if n > 0 {
102 e = nil
103 } else {
104 e = io.EOF
105 }
106 }
107 return n, e
108 }
109
110 type debugger struct {
111 mutex sync.Mutex
112 remain int
113 remainingKnown bool
114 r *peekReader
115 wireType map[typeId]*wireType
116 tmp []byte
117 }
118
119
120
121
122 func (deb *debugger) dump(format string, args ...any) {
123 if !dumpBytes {
124 return
125 }
126 fmt.Fprintf(os.Stderr, format+" ", args...)
127 if !deb.remainingKnown {
128 return
129 }
130 if deb.remain < 0 {
131 fmt.Fprintf(os.Stderr, "remaining byte count is negative! %d\n", deb.remain)
132 return
133 }
134 data := make([]byte, deb.remain)
135 n, _ := deb.r.peek(data)
136 if n == 0 {
137 os.Stderr.Write(empty)
138 return
139 }
140 b := new(bytes.Buffer)
141 fmt.Fprintf(b, "[%d]{\n", deb.remain)
142
143 lineLength := 0
144 if n := len(data); n%10 != 0 {
145 lineLength = 10 - n%10
146 fmt.Fprintf(b, "\t%s", blanks[:lineLength*3])
147 }
148
149 for len(data) > 0 {
150 if lineLength == 0 {
151 fmt.Fprint(b, "\t")
152 }
153 m := 10 - lineLength
154 lineLength = 0
155 if m > len(data) {
156 m = len(data)
157 }
158 fmt.Fprintf(b, "% x\n", data[:m])
159 data = data[m:]
160 }
161 fmt.Fprint(b, "}\n")
162 os.Stderr.Write(b.Bytes())
163 }
164
165
166
167 func Debug(r io.Reader) {
168 err := debug(r)
169 if err != nil {
170 fmt.Fprintf(os.Stderr, "gob debug: %s\n", err)
171 }
172 }
173
174
175
176 func debug(r io.Reader) (err error) {
177 defer catchError(&err)
178 fmt.Fprintln(os.Stderr, "Start of debugging")
179 deb := &debugger{
180 r: newPeekReader(r),
181 wireType: make(map[typeId]*wireType),
182 tmp: make([]byte, 16),
183 }
184 if b, ok := r.(*bytes.Buffer); ok {
185 deb.remain = b.Len()
186 deb.remainingKnown = true
187 }
188 deb.gobStream()
189 return
190 }
191
192
193 func (deb *debugger) consumed(n int) {
194 if deb.remainingKnown {
195 deb.remain -= n
196 }
197 }
198
199
200
201 func (deb *debugger) int64() int64 {
202 return toInt(deb.uint64())
203 }
204
205
206
207
208 func (deb *debugger) uint64() uint64 {
209 n, w, err := decodeUintReader(deb.r, deb.tmp)
210 if err != nil {
211 errorf("debug: read error: %s", err)
212 }
213 deb.consumed(w)
214 return n
215 }
216
217
218
219
220 func (deb *debugger) gobStream() {
221
222 deb.mutex.Lock()
223 defer deb.mutex.Unlock()
224
225 for deb.delimitedMessage(0) {
226 }
227 }
228
229
230
231
232 func (deb *debugger) delimitedMessage(indent tab) bool {
233 for {
234 n := deb.loadBlock(true)
235 if n < 0 {
236 return false
237 }
238 deb.dump("Delimited message of length %d", n)
239 deb.message(indent)
240 }
241 return true
242 }
243
244
245
246
247
248
249 func (deb *debugger) loadBlock(eofOK bool) int {
250 n64, w, err := decodeUintReader(deb.r, deb.tmp)
251 if err != nil {
252 if eofOK && err == io.EOF {
253 return -1
254 }
255 errorf("debug: unexpected error: %s", err)
256 }
257 deb.consumed(w)
258 n := int(n64)
259 if n < 0 {
260 errorf("huge value for message length: %d", n64)
261 }
262 return int(n)
263 }
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280 func (deb *debugger) message(indent tab) bool {
281 for {
282
283 uid := deb.int64()
284 id := typeId(uid)
285 deb.dump("type id=%d", id)
286 if id < 0 {
287 deb.typeDefinition(indent, -id)
288 n := deb.loadBlock(false)
289 deb.dump("Message of length %d", n)
290 continue
291 } else {
292 deb.value(indent, id)
293 break
294 }
295 }
296 return true
297 }
298
299
300
301
302 func (deb *debugger) common() CommonType {
303 fieldNum := -1
304 name := ""
305 id := typeId(0)
306 for {
307 delta := deb.delta(-1)
308 if delta == 0 {
309 break
310 }
311 fieldNum += delta
312 switch fieldNum {
313 case 0:
314 name = deb.string()
315 case 1:
316
317 id = deb.typeId()
318 default:
319 errorf("corrupted CommonType, delta is %d fieldNum is %d", delta, fieldNum)
320 }
321 }
322 return CommonType{name, id}
323 }
324
325
326 func (deb *debugger) uint() uint {
327 return uint(deb.uint64())
328 }
329
330
331 func (deb *debugger) int() int {
332 return int(deb.int64())
333 }
334
335
336 func (deb *debugger) typeId() typeId {
337 return typeId(deb.int64())
338 }
339
340
341 func (deb *debugger) string() string {
342 x := int(deb.uint64())
343 b := make([]byte, x)
344 nb, _ := deb.r.Read(b)
345 if nb != x {
346 errorf("corrupted type")
347 }
348 deb.consumed(nb)
349 return string(b)
350 }
351
352
353
354 func (deb *debugger) delta(expect int) int {
355 delta := int(deb.uint64())
356 if delta < 0 || (expect >= 0 && delta != expect) {
357 errorf("decode: corrupted type: delta %d expected %d", delta, expect)
358 }
359 return delta
360 }
361
362
363
364
365 func (deb *debugger) typeDefinition(indent tab, id typeId) {
366 deb.dump("type definition for id %d", id)
367
368 fieldNum := -1
369 wire := new(wireType)
370
371 delta := deb.delta(-1)
372 fieldNum += delta
373 switch fieldNum {
374 case 0:
375
376 deb.delta(1)
377 com := deb.common()
378
379 deb.delta(1)
380 id := deb.typeId()
381
382 deb.delta(1)
383 length := deb.int()
384 wire.ArrayT = &arrayType{com, id, length}
385
386 case 1:
387
388 deb.delta(1)
389 com := deb.common()
390
391 deb.delta(1)
392 id := deb.typeId()
393 wire.SliceT = &sliceType{com, id}
394
395 case 2:
396
397 deb.delta(1)
398 com := deb.common()
399
400 deb.delta(1)
401 numField := int(deb.uint())
402 field := make([]*fieldType, numField)
403 for i := 0; i < numField; i++ {
404 field[i] = new(fieldType)
405 deb.delta(1)
406 field[i].Name = deb.string()
407 deb.delta(1)
408 field[i].Id = deb.typeId()
409 deb.delta(0)
410 }
411 wire.StructT = &structType{com, field}
412
413 case 3:
414
415 deb.delta(1)
416 com := deb.common()
417
418 deb.delta(1)
419 keyId := deb.typeId()
420
421 deb.delta(1)
422 elemId := deb.typeId()
423 wire.MapT = &mapType{com, keyId, elemId}
424 case 4:
425
426 deb.delta(1)
427 com := deb.common()
428 wire.GobEncoderT = &gobEncoderType{com}
429 case 5:
430
431 deb.delta(1)
432 com := deb.common()
433 wire.BinaryMarshalerT = &gobEncoderType{com}
434 case 6:
435
436 deb.delta(1)
437 com := deb.common()
438 wire.TextMarshalerT = &gobEncoderType{com}
439 default:
440 errorf("bad field in type %d", fieldNum)
441 }
442 deb.printWireType(indent, wire)
443 deb.delta(0)
444 deb.delta(0)
445
446 deb.wireType[id] = wire
447 }
448
449
450
451
452 func (deb *debugger) value(indent tab, id typeId) {
453 wire, ok := deb.wireType[id]
454 if ok && wire.StructT != nil {
455 deb.structValue(indent, id)
456 } else {
457 deb.singletonValue(indent, id)
458 }
459 }
460
461
462
463
464 func (deb *debugger) singletonValue(indent tab, id typeId) {
465 deb.dump("Singleton value")
466
467 wire := deb.wireType[id]
468 if builtinIdToType(id) == nil && wire == nil {
469 errorf("type id %d not defined", id)
470 }
471 m := deb.uint64()
472 if m != 0 {
473 errorf("expected zero; got %d", m)
474 }
475 deb.fieldValue(indent, id)
476 }
477
478
479
480
481 func (deb *debugger) interfaceValue(indent tab) {
482 deb.dump("Start of interface value")
483 if nameLen := deb.uint64(); nameLen == 0 {
484 deb.nilInterfaceValue(indent)
485 } else {
486 deb.nonNilInterfaceValue(indent, int(nameLen))
487 }
488 }
489
490
491
492
493 func (deb *debugger) nilInterfaceValue(indent tab) int {
494 fmt.Fprintf(os.Stderr, "%snil interface\n", indent)
495 return 0
496 }
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513 func (deb *debugger) nonNilInterfaceValue(indent tab, nameLen int) {
514
515 b := make([]byte, nameLen)
516 deb.r.Read(b)
517 deb.consumed(nameLen)
518 name := string(b)
519
520 for {
521 id := deb.typeId()
522 if id < 0 {
523 deb.typeDefinition(indent, -id)
524 n := deb.loadBlock(false)
525 deb.dump("Nested message of length %d", n)
526 } else {
527
528 x := deb.uint64()
529 fmt.Fprintf(os.Stderr, "%sinterface value, type %q id=%d; valueLength %d\n", indent, name, id, x)
530 deb.value(indent, id)
531 break
532 }
533 }
534 }
535
536
537 func (deb *debugger) printCommonType(indent tab, kind string, common *CommonType) {
538 indent.print()
539 fmt.Fprintf(os.Stderr, "%s %q id=%d\n", kind, common.Name, common.Id)
540 }
541
542
543 func (deb *debugger) printWireType(indent tab, wire *wireType) {
544 fmt.Fprintf(os.Stderr, "%stype definition {\n", indent)
545 indent++
546 switch {
547 case wire.ArrayT != nil:
548 deb.printCommonType(indent, "array", &wire.ArrayT.CommonType)
549 fmt.Fprintf(os.Stderr, "%slen %d\n", indent+1, wire.ArrayT.Len)
550 fmt.Fprintf(os.Stderr, "%selemid %d\n", indent+1, wire.ArrayT.Elem)
551 case wire.MapT != nil:
552 deb.printCommonType(indent, "map", &wire.MapT.CommonType)
553 fmt.Fprintf(os.Stderr, "%skey id=%d\n", indent+1, wire.MapT.Key)
554 fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.MapT.Elem)
555 case wire.SliceT != nil:
556 deb.printCommonType(indent, "slice", &wire.SliceT.CommonType)
557 fmt.Fprintf(os.Stderr, "%selem id=%d\n", indent+1, wire.SliceT.Elem)
558 case wire.StructT != nil:
559 deb.printCommonType(indent, "struct", &wire.StructT.CommonType)
560 for i, field := range wire.StructT.Field {
561 fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\tid=%d\n", indent+1, i, field.Name, field.Id)
562 }
563 case wire.GobEncoderT != nil:
564 deb.printCommonType(indent, "GobEncoder", &wire.GobEncoderT.CommonType)
565 }
566 indent--
567 fmt.Fprintf(os.Stderr, "%s}\n", indent)
568 }
569
570
571
572
573
574 func (deb *debugger) fieldValue(indent tab, id typeId) {
575 if builtinIdToType(id) != nil {
576 if id == tInterface {
577 deb.interfaceValue(indent)
578 } else {
579 deb.printBuiltin(indent, id)
580 }
581 return
582 }
583 wire, ok := deb.wireType[id]
584 if !ok {
585 errorf("type id %d not defined", id)
586 }
587 switch {
588 case wire.ArrayT != nil:
589 deb.arrayValue(indent, wire)
590 case wire.MapT != nil:
591 deb.mapValue(indent, wire)
592 case wire.SliceT != nil:
593 deb.sliceValue(indent, wire)
594 case wire.StructT != nil:
595 deb.structValue(indent, id)
596 case wire.GobEncoderT != nil:
597 deb.gobEncoderValue(indent, id)
598 default:
599 panic("bad wire type for field")
600 }
601 }
602
603
604
605 func (deb *debugger) printBuiltin(indent tab, id typeId) {
606 switch id {
607 case tBool:
608 x := deb.int64()
609 if x == 0 {
610 fmt.Fprintf(os.Stderr, "%sfalse\n", indent)
611 } else {
612 fmt.Fprintf(os.Stderr, "%strue\n", indent)
613 }
614 case tInt:
615 x := deb.int64()
616 fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
617 case tUint:
618 x := deb.uint64()
619 fmt.Fprintf(os.Stderr, "%s%d\n", indent, x)
620 case tFloat:
621 x := deb.uint64()
622 fmt.Fprintf(os.Stderr, "%s%g\n", indent, float64FromBits(x))
623 case tComplex:
624 r := deb.uint64()
625 i := deb.uint64()
626 fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, float64FromBits(r), float64FromBits(i))
627 case tBytes:
628 x := int(deb.uint64())
629 b := make([]byte, x)
630 deb.r.Read(b)
631 deb.consumed(x)
632 fmt.Fprintf(os.Stderr, "%s{% x}=%q\n", indent, b, b)
633 case tString:
634 x := int(deb.uint64())
635 b := make([]byte, x)
636 deb.r.Read(b)
637 deb.consumed(x)
638 fmt.Fprintf(os.Stderr, "%s%q\n", indent, b)
639 default:
640 panic("unknown builtin")
641 }
642 }
643
644
645
646
647 func (deb *debugger) arrayValue(indent tab, wire *wireType) {
648 elemId := wire.ArrayT.Elem
649 u := deb.uint64()
650 length := int(u)
651 for i := 0; i < length; i++ {
652 deb.fieldValue(indent, elemId)
653 }
654 if length != wire.ArrayT.Len {
655 fmt.Fprintf(os.Stderr, "%s(wrong length for array: %d should be %d)\n", indent, length, wire.ArrayT.Len)
656 }
657 }
658
659
660
661
662 func (deb *debugger) mapValue(indent tab, wire *wireType) {
663 keyId := wire.MapT.Key
664 elemId := wire.MapT.Elem
665 u := deb.uint64()
666 length := int(u)
667 for i := 0; i < length; i++ {
668 deb.fieldValue(indent+1, keyId)
669 deb.fieldValue(indent+1, elemId)
670 }
671 }
672
673
674
675
676 func (deb *debugger) sliceValue(indent tab, wire *wireType) {
677 elemId := wire.SliceT.Elem
678 u := deb.uint64()
679 length := int(u)
680 deb.dump("Start of slice of length %d", length)
681
682 for i := 0; i < length; i++ {
683 deb.fieldValue(indent, elemId)
684 }
685 }
686
687
688
689
690 func (deb *debugger) structValue(indent tab, id typeId) {
691 deb.dump("Start of struct value of %q id=%d\n<<\n", id.name(), id)
692 fmt.Fprintf(os.Stderr, "%s%s struct {\n", indent, id.name())
693 wire, ok := deb.wireType[id]
694 if !ok {
695 errorf("type id %d not defined", id)
696 }
697 strct := wire.StructT
698 fieldNum := -1
699 indent++
700 for {
701 delta := deb.uint64()
702 if delta == 0 {
703 break
704 }
705 fieldNum += int(delta)
706 if fieldNum < 0 || fieldNum >= len(strct.Field) {
707 deb.dump("field number out of range: prevField=%d delta=%d", fieldNum-int(delta), delta)
708 break
709 }
710 fmt.Fprintf(os.Stderr, "%sfield %d:\t%s\n", indent, fieldNum, wire.StructT.Field[fieldNum].Name)
711 deb.fieldValue(indent+1, strct.Field[fieldNum].Id)
712 }
713 indent--
714 fmt.Fprintf(os.Stderr, "%s} // end %s struct\n", indent, id.name())
715 deb.dump(">> End of struct value of type %d %q", id, id.name())
716 }
717
718
719
720
721 func (deb *debugger) gobEncoderValue(indent tab, id typeId) {
722 len := deb.uint64()
723 deb.dump("GobEncoder value of %q id=%d, length %d\n", id.name(), id, len)
724 fmt.Fprintf(os.Stderr, "%s%s (implements GobEncoder)\n", indent, id.name())
725 data := make([]byte, len)
726 _, err := deb.r.Read(data)
727 if err != nil {
728 errorf("gobEncoder data read: %s", err)
729 }
730 fmt.Fprintf(os.Stderr, "%s[% .2x]\n", indent+1, data)
731 }
732
View as plain text