Source file src/pkg/debug/dwarf/entry.go
1
2
3
4
5
6
7
8
9
10
11 package dwarf
12
13 import (
14 "errors"
15 "strconv"
16 )
17
18
19 type abbrev struct {
20 tag Tag
21 children bool
22 field []afield
23 }
24
25 type afield struct {
26 attr Attr
27 fmt format
28 class Class
29 }
30
31
32 type abbrevTable map[uint32]abbrev
33
34
35
36 func (d *Data) parseAbbrev(off uint64, vers int) (abbrevTable, error) {
37 if m, ok := d.abbrevCache[off]; ok {
38 return m, nil
39 }
40
41 data := d.abbrev
42 if off > uint64(len(data)) {
43 data = nil
44 } else {
45 data = data[off:]
46 }
47 b := makeBuf(d, unknownFormat{}, "abbrev", 0, data)
48
49
50
51 m := make(abbrevTable)
52 for {
53
54 id := uint32(b.uint())
55 if id == 0 {
56 break
57 }
58
59
60 n := 0
61 b1 := b
62 b1.uint()
63 b1.uint8()
64 for {
65 tag := b1.uint()
66 fmt := b1.uint()
67 if tag == 0 && fmt == 0 {
68 break
69 }
70 n++
71 }
72 if b1.err != nil {
73 return nil, b1.err
74 }
75
76
77 var a abbrev
78 a.tag = Tag(b.uint())
79 a.children = b.uint8() != 0
80 a.field = make([]afield, n)
81 for i := range a.field {
82 a.field[i].attr = Attr(b.uint())
83 a.field[i].fmt = format(b.uint())
84 a.field[i].class = formToClass(a.field[i].fmt, a.field[i].attr, vers, &b)
85 }
86 b.uint()
87 b.uint()
88
89 m[id] = a
90 }
91 if b.err != nil {
92 return nil, b.err
93 }
94 d.abbrevCache[off] = m
95 return m, nil
96 }
97
98
99
100
101 var attrIsExprloc = map[Attr]bool{
102 AttrLocation: true,
103 AttrByteSize: true,
104 AttrBitOffset: true,
105 AttrBitSize: true,
106 AttrStringLength: true,
107 AttrLowerBound: true,
108 AttrReturnAddr: true,
109 AttrStrideSize: true,
110 AttrUpperBound: true,
111 AttrCount: true,
112 AttrDataMemberLoc: true,
113 AttrFrameBase: true,
114 AttrSegment: true,
115 AttrStaticLink: true,
116 AttrUseLocation: true,
117 AttrVtableElemLoc: true,
118 AttrAllocated: true,
119 AttrAssociated: true,
120 AttrDataLocation: true,
121 AttrStride: true,
122 }
123
124
125
126 var attrPtrClass = map[Attr]Class{
127 AttrLocation: ClassLocListPtr,
128 AttrStmtList: ClassLinePtr,
129 AttrStringLength: ClassLocListPtr,
130 AttrReturnAddr: ClassLocListPtr,
131 AttrStartScope: ClassRangeListPtr,
132 AttrDataMemberLoc: ClassLocListPtr,
133 AttrFrameBase: ClassLocListPtr,
134 AttrMacroInfo: ClassMacPtr,
135 AttrSegment: ClassLocListPtr,
136 AttrStaticLink: ClassLocListPtr,
137 AttrUseLocation: ClassLocListPtr,
138 AttrVtableElemLoc: ClassLocListPtr,
139 AttrRanges: ClassRangeListPtr,
140 }
141
142
143
144
145 func formToClass(form format, attr Attr, vers int, b *buf) Class {
146 switch form {
147 default:
148 b.error("cannot determine class of unknown attribute form")
149 return 0
150
151 case formAddr:
152 return ClassAddress
153
154 case formDwarfBlock1, formDwarfBlock2, formDwarfBlock4, formDwarfBlock:
155
156
157
158
159
160
161 if attrIsExprloc[attr] {
162 return ClassExprLoc
163 }
164 return ClassBlock
165
166 case formData1, formData2, formData4, formData8, formSdata, formUdata:
167
168
169
170
171
172 if class, ok := attrPtrClass[attr]; vers < 4 && ok {
173 return class
174 }
175 return ClassConstant
176
177 case formFlag, formFlagPresent:
178 return ClassFlag
179
180 case formRefAddr, formRef1, formRef2, formRef4, formRef8, formRefUdata:
181 return ClassReference
182
183 case formRefSig8:
184 return ClassReferenceSig
185
186 case formString, formStrp:
187 return ClassString
188
189 case formSecOffset:
190
191
192
193 if class, ok := attrPtrClass[attr]; ok {
194 return class
195 }
196 return ClassUnknown
197
198 case formExprloc:
199 return ClassExprLoc
200
201 case formGnuRefAlt:
202 return ClassReferenceAlt
203
204 case formGnuStrpAlt:
205 return ClassStringAlt
206 }
207 }
208
209
210 type Entry struct {
211 Offset Offset
212 Tag Tag
213 Children bool
214 Field []Field
215 }
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240 type Field struct {
241 Attr Attr
242 Val interface{}
243 Class Class
244 }
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 type Class int
261
262 const (
263
264 ClassUnknown Class = iota
265
266
267
268 ClassAddress
269
270
271
272 ClassBlock
273
274
275
276
277 ClassConstant
278
279
280
281 ClassExprLoc
282
283
284 ClassFlag
285
286
287
288 ClassLinePtr
289
290
291
292 ClassLocListPtr
293
294
295
296 ClassMacPtr
297
298
299
300 ClassRangeListPtr
301
302
303
304
305
306 ClassReference
307
308
309
310 ClassReferenceSig
311
312
313
314
315
316 ClassString
317
318
319
320
321 ClassReferenceAlt
322
323
324
325
326 ClassStringAlt
327 )
328
329
330
331 func (i Class) GoString() string {
332 return "dwarf." + i.String()
333 }
334
335
336
337
338
339
340
341
342 func (e *Entry) Val(a Attr) interface{} {
343 if f := e.AttrField(a); f != nil {
344 return f.Val
345 }
346 return nil
347 }
348
349
350
351 func (e *Entry) AttrField(a Attr) *Field {
352 for i, f := range e.Field {
353 if f.Attr == a {
354 return &e.Field[i]
355 }
356 }
357 return nil
358 }
359
360
361
362 type Offset uint32
363
364
365
366 func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
367 off := b.off
368 id := uint32(b.uint())
369 if id == 0 {
370 return &Entry{}
371 }
372 a, ok := atab[id]
373 if !ok {
374 b.error("unknown abbreviation table index")
375 return nil
376 }
377 e := &Entry{
378 Offset: off,
379 Tag: a.tag,
380 Children: a.children,
381 Field: make([]Field, len(a.field)),
382 }
383 for i := range e.Field {
384 e.Field[i].Attr = a.field[i].attr
385 e.Field[i].Class = a.field[i].class
386 fmt := a.field[i].fmt
387 if fmt == formIndirect {
388 fmt = format(b.uint())
389 }
390 var val interface{}
391 switch fmt {
392 default:
393 b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16))
394
395
396 case formAddr:
397 val = b.addr()
398
399
400 case formDwarfBlock1:
401 val = b.bytes(int(b.uint8()))
402 case formDwarfBlock2:
403 val = b.bytes(int(b.uint16()))
404 case formDwarfBlock4:
405 val = b.bytes(int(b.uint32()))
406 case formDwarfBlock:
407 val = b.bytes(int(b.uint()))
408
409
410 case formData1:
411 val = int64(b.uint8())
412 case formData2:
413 val = int64(b.uint16())
414 case formData4:
415 val = int64(b.uint32())
416 case formData8:
417 val = int64(b.uint64())
418 case formSdata:
419 val = int64(b.int())
420 case formUdata:
421 val = int64(b.uint())
422
423
424 case formFlag:
425 val = b.uint8() == 1
426
427 case formFlagPresent:
428
429
430 val = true
431
432
433 case formRefAddr:
434 vers := b.format.version()
435 if vers == 0 {
436 b.error("unknown version for DW_FORM_ref_addr")
437 } else if vers == 2 {
438 val = Offset(b.addr())
439 } else {
440 is64, known := b.format.dwarf64()
441 if !known {
442 b.error("unknown size for DW_FORM_ref_addr")
443 } else if is64 {
444 val = Offset(b.uint64())
445 } else {
446 val = Offset(b.uint32())
447 }
448 }
449 case formRef1:
450 val = Offset(b.uint8()) + ubase
451 case formRef2:
452 val = Offset(b.uint16()) + ubase
453 case formRef4:
454 val = Offset(b.uint32()) + ubase
455 case formRef8:
456 val = Offset(b.uint64()) + ubase
457 case formRefUdata:
458 val = Offset(b.uint()) + ubase
459
460
461 case formString:
462 val = b.string()
463 case formStrp:
464 var off uint64
465 is64, known := b.format.dwarf64()
466 if !known {
467 b.error("unknown size for DW_FORM_strp")
468 } else if is64 {
469 off = b.uint64()
470 } else {
471 off = uint64(b.uint32())
472 }
473 if uint64(int(off)) != off {
474 b.error("DW_FORM_strp offset out of range")
475 }
476 if b.err != nil {
477 return nil
478 }
479 b1 := makeBuf(b.dwarf, unknownFormat{}, "str", 0, b.dwarf.str)
480 b1.skip(int(off))
481 val = b1.string()
482 if b1.err != nil {
483 b.err = b1.err
484 return nil
485 }
486
487
488
489
490 case formSecOffset, formGnuRefAlt, formGnuStrpAlt:
491 is64, known := b.format.dwarf64()
492 if !known {
493 b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16))
494 } else if is64 {
495 val = int64(b.uint64())
496 } else {
497 val = int64(b.uint32())
498 }
499
500
501
502 case formExprloc:
503 val = b.bytes(int(b.uint()))
504
505
506
507 case formRefSig8:
508
509 val = b.uint64()
510 }
511 e.Field[i].Val = val
512 }
513 if b.err != nil {
514 return nil
515 }
516 return e
517 }
518
519
520
521
522
523
524 type Reader struct {
525 b buf
526 d *Data
527 err error
528 unit int
529 lastChildren bool
530 lastSibling Offset
531 }
532
533
534
535 func (d *Data) Reader() *Reader {
536 r := &Reader{d: d}
537 r.Seek(0)
538 return r
539 }
540
541
542
543 func (r *Reader) AddressSize() int {
544 return r.d.unit[r.unit].asize
545 }
546
547
548
549 func (r *Reader) Seek(off Offset) {
550 d := r.d
551 r.err = nil
552 r.lastChildren = false
553 if off == 0 {
554 if len(d.unit) == 0 {
555 return
556 }
557 u := &d.unit[0]
558 r.unit = 0
559 r.b = makeBuf(r.d, u, "info", u.off, u.data)
560 return
561 }
562
563 i := d.offsetToUnit(off)
564 if i == -1 {
565 r.err = errors.New("offset out of range")
566 return
567 }
568 u := &d.unit[i]
569 r.unit = i
570 r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:])
571 }
572
573
574 func (r *Reader) maybeNextUnit() {
575 for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
576 r.unit++
577 u := &r.d.unit[r.unit]
578 r.b = makeBuf(r.d, u, "info", u.off, u.data)
579 }
580 }
581
582
583
584
585
586 func (r *Reader) Next() (*Entry, error) {
587 if r.err != nil {
588 return nil, r.err
589 }
590 r.maybeNextUnit()
591 if len(r.b.data) == 0 {
592 return nil, nil
593 }
594 u := &r.d.unit[r.unit]
595 e := r.b.entry(u.atable, u.base)
596 if r.b.err != nil {
597 r.err = r.b.err
598 return nil, r.err
599 }
600 if e != nil {
601 r.lastChildren = e.Children
602 if r.lastChildren {
603 r.lastSibling, _ = e.Val(AttrSibling).(Offset)
604 }
605 } else {
606 r.lastChildren = false
607 }
608 return e, nil
609 }
610
611
612
613
614 func (r *Reader) SkipChildren() {
615 if r.err != nil || !r.lastChildren {
616 return
617 }
618
619
620
621
622
623 if r.lastSibling >= r.b.off {
624 r.Seek(r.lastSibling)
625 return
626 }
627
628 for {
629 e, err := r.Next()
630 if err != nil || e == nil || e.Tag == 0 {
631 break
632 }
633 if e.Children {
634 r.SkipChildren()
635 }
636 }
637 }
638
639
640
641 func (r *Reader) clone() typeReader {
642 return r.d.Reader()
643 }
644
645
646
647 func (r *Reader) offset() Offset {
648 return r.b.off
649 }
650
651
652
653
654
655
656
657
658
659
660
661
662
663 func (r *Reader) SeekPC(pc uint64) (*Entry, error) {
664 unit := r.unit
665 for i := 0; i < len(r.d.unit); i++ {
666 if unit >= len(r.d.unit) {
667 unit = 0
668 }
669 r.err = nil
670 r.lastChildren = false
671 r.unit = unit
672 u := &r.d.unit[unit]
673 r.b = makeBuf(r.d, u, "info", u.off, u.data)
674 e, err := r.Next()
675 if err != nil {
676 return nil, err
677 }
678 ranges, err := r.d.Ranges(e)
679 if err != nil {
680 return nil, err
681 }
682 for _, pcs := range ranges {
683 if pcs[0] <= pc && pc < pcs[1] {
684 return e, nil
685 }
686 }
687 unit++
688 }
689 return nil, ErrUnknownPC
690 }
691
692
693
694
695 func (d *Data) Ranges(e *Entry) ([][2]uint64, error) {
696 var ret [][2]uint64
697
698 low, lowOK := e.Val(AttrLowpc).(uint64)
699
700 var high uint64
701 var highOK bool
702 highField := e.AttrField(AttrHighpc)
703 if highField != nil {
704 switch highField.Class {
705 case ClassAddress:
706 high, highOK = highField.Val.(uint64)
707 case ClassConstant:
708 off, ok := highField.Val.(int64)
709 if ok {
710 high = low + uint64(off)
711 highOK = true
712 }
713 }
714 }
715
716 if lowOK && highOK {
717 ret = append(ret, [2]uint64{low, high})
718 }
719
720 ranges, rangesOK := e.Val(AttrRanges).(int64)
721 if rangesOK && d.ranges != nil {
722
723
724
725
726
727 var cu *Entry
728 if e.Tag == TagCompileUnit {
729 cu = e
730 } else {
731 i := d.offsetToUnit(e.Offset)
732 if i == -1 {
733 return nil, errors.New("no unit for entry")
734 }
735 u := &d.unit[i]
736 b := makeBuf(d, u, "info", u.off, u.data)
737 cu = b.entry(u.atable, u.base)
738 if b.err != nil {
739 return nil, b.err
740 }
741 }
742
743 var base uint64
744 if cuEntry, cuEntryOK := cu.Val(AttrEntrypc).(uint64); cuEntryOK {
745 base = cuEntry
746 } else if cuLow, cuLowOK := cu.Val(AttrLowpc).(uint64); cuLowOK {
747 base = cuLow
748 }
749
750 u := &d.unit[d.offsetToUnit(e.Offset)]
751 buf := makeBuf(d, u, "ranges", Offset(ranges), d.ranges[ranges:])
752 for len(buf.data) > 0 {
753 low = buf.addr()
754 high = buf.addr()
755
756 if low == 0 && high == 0 {
757 break
758 }
759
760 if low == ^uint64(0)>>uint((8-u.addrsize())*8) {
761 base = high
762 } else {
763 ret = append(ret, [2]uint64{base + low, base + high})
764 }
765 }
766 }
767
768 return ret, nil
769 }
770
View as plain text