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