1
2
3
4
5
6
7
8
9
10
11 package dwarf
12
13 import (
14 "encoding/binary"
15 "errors"
16 "strconv"
17 )
18
19
20 type abbrev struct {
21 tag Tag
22 children bool
23 field []afield
24 }
25
26 type afield struct {
27 attr Attr
28 fmt format
29 class Class
30 val int64
31 }
32
33
34 type abbrevTable map[uint32]abbrev
35
36
37
38 func (d *Data) parseAbbrev(off uint64, vers int) (abbrevTable, error) {
39 if m, ok := d.abbrevCache[off]; ok {
40 return m, nil
41 }
42
43 data := d.abbrev
44 if off > uint64(len(data)) {
45 data = nil
46 } else {
47 data = data[off:]
48 }
49 b := makeBuf(d, unknownFormat{}, "abbrev", 0, data)
50
51
52
53 m := make(abbrevTable)
54 for {
55
56 id := uint32(b.uint())
57 if id == 0 {
58 break
59 }
60
61
62 n := 0
63 b1 := b
64 b1.uint()
65 b1.uint8()
66 for {
67 tag := b1.uint()
68 fmt := b1.uint()
69 if tag == 0 && fmt == 0 {
70 break
71 }
72 if format(fmt) == formImplicitConst {
73 b1.int()
74 }
75 n++
76 }
77 if b1.err != nil {
78 return nil, b1.err
79 }
80
81
82 var a abbrev
83 a.tag = Tag(b.uint())
84 a.children = b.uint8() != 0
85 a.field = make([]afield, n)
86 for i := range a.field {
87 a.field[i].attr = Attr(b.uint())
88 a.field[i].fmt = format(b.uint())
89 a.field[i].class = formToClass(a.field[i].fmt, a.field[i].attr, vers, &b)
90 if a.field[i].fmt == formImplicitConst {
91 a.field[i].val = b.int()
92 }
93 }
94 b.uint()
95 b.uint()
96
97 m[id] = a
98 }
99 if b.err != nil {
100 return nil, b.err
101 }
102 d.abbrevCache[off] = m
103 return m, nil
104 }
105
106
107
108
109 var attrIsExprloc = map[Attr]bool{
110 AttrLocation: true,
111 AttrByteSize: true,
112 AttrBitOffset: true,
113 AttrBitSize: true,
114 AttrStringLength: true,
115 AttrLowerBound: true,
116 AttrReturnAddr: true,
117 AttrStrideSize: true,
118 AttrUpperBound: true,
119 AttrCount: true,
120 AttrDataMemberLoc: true,
121 AttrFrameBase: true,
122 AttrSegment: true,
123 AttrStaticLink: true,
124 AttrUseLocation: true,
125 AttrVtableElemLoc: true,
126 AttrAllocated: true,
127 AttrAssociated: true,
128 AttrDataLocation: true,
129 AttrStride: true,
130 }
131
132
133
134 var attrPtrClass = map[Attr]Class{
135 AttrLocation: ClassLocListPtr,
136 AttrStmtList: ClassLinePtr,
137 AttrStringLength: ClassLocListPtr,
138 AttrReturnAddr: ClassLocListPtr,
139 AttrStartScope: ClassRangeListPtr,
140 AttrDataMemberLoc: ClassLocListPtr,
141 AttrFrameBase: ClassLocListPtr,
142 AttrMacroInfo: ClassMacPtr,
143 AttrSegment: ClassLocListPtr,
144 AttrStaticLink: ClassLocListPtr,
145 AttrUseLocation: ClassLocListPtr,
146 AttrVtableElemLoc: ClassLocListPtr,
147 AttrRanges: ClassRangeListPtr,
148
149 AttrStrOffsetsBase: ClassStrOffsetsPtr,
150 AttrAddrBase: ClassAddrPtr,
151 AttrRnglistsBase: ClassRngListsPtr,
152 AttrLoclistsBase: ClassLocListPtr,
153 }
154
155
156
157
158 func formToClass(form format, attr Attr, vers int, b *buf) Class {
159 switch form {
160 default:
161 b.error("cannot determine class of unknown attribute form")
162 return 0
163
164 case formIndirect:
165 return ClassUnknown
166
167 case formAddr, formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4:
168 return ClassAddress
169
170 case formDwarfBlock1, formDwarfBlock2, formDwarfBlock4, formDwarfBlock:
171
172
173
174
175
176
177 if attrIsExprloc[attr] {
178 return ClassExprLoc
179 }
180 return ClassBlock
181
182 case formData1, formData2, formData4, formData8, formSdata, formUdata, formData16, formImplicitConst:
183
184
185
186
187
188 if class, ok := attrPtrClass[attr]; vers < 4 && ok {
189 return class
190 }
191 return ClassConstant
192
193 case formFlag, formFlagPresent:
194 return ClassFlag
195
196 case formRefAddr, formRef1, formRef2, formRef4, formRef8, formRefUdata, formRefSup4, formRefSup8:
197 return ClassReference
198
199 case formRefSig8:
200 return ClassReferenceSig
201
202 case formString, formStrp, formStrx, formStrpSup, formLineStrp, formStrx1, formStrx2, formStrx3, formStrx4:
203 return ClassString
204
205 case formSecOffset:
206
207
208
209 if class, ok := attrPtrClass[attr]; ok {
210 return class
211 }
212 return ClassUnknown
213
214 case formExprloc:
215 return ClassExprLoc
216
217 case formGnuRefAlt:
218 return ClassReferenceAlt
219
220 case formGnuStrpAlt:
221 return ClassStringAlt
222
223 case formLoclistx:
224 return ClassLocList
225
226 case formRnglistx:
227 return ClassRngList
228 }
229 }
230
231
232 type Entry struct {
233 Offset Offset
234 Tag Tag
235 Children bool
236 Field []Field
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262 type Field struct {
263 Attr Attr
264 Val any
265 Class Class
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282 type Class int
283
284 const (
285
286 ClassUnknown Class = iota
287
288
289
290 ClassAddress
291
292
293
294 ClassBlock
295
296
297
298
299 ClassConstant
300
301
302
303 ClassExprLoc
304
305
306 ClassFlag
307
308
309
310 ClassLinePtr
311
312
313
314 ClassLocListPtr
315
316
317
318 ClassMacPtr
319
320
321
322 ClassRangeListPtr
323
324
325
326
327
328 ClassReference
329
330
331
332 ClassReferenceSig
333
334
335
336
337
338 ClassString
339
340
341
342
343 ClassReferenceAlt
344
345
346
347
348 ClassStringAlt
349
350
351
352 ClassAddrPtr
353
354
355
356 ClassLocList
357
358
359
360 ClassRngList
361
362
363
364
365 ClassRngListsPtr
366
367
368
369 ClassStrOffsetsPtr
370 )
371
372
373
374 func (i Class) GoString() string {
375 return "dwarf." + i.String()
376 }
377
378
379
380
381
382
383
384
385 func (e *Entry) Val(a Attr) any {
386 if f := e.AttrField(a); f != nil {
387 return f.Val
388 }
389 return nil
390 }
391
392
393
394 func (e *Entry) AttrField(a Attr) *Field {
395 for i, f := range e.Field {
396 if f.Attr == a {
397 return &e.Field[i]
398 }
399 }
400 return nil
401 }
402
403
404
405 type Offset uint32
406
407
408
409 func (b *buf) entry(cu *Entry, atab abbrevTable, ubase Offset, vers int) *Entry {
410 off := b.off
411 id := uint32(b.uint())
412 if id == 0 {
413 return &Entry{}
414 }
415 a, ok := atab[id]
416 if !ok {
417 b.error("unknown abbreviation table index")
418 return nil
419 }
420 e := &Entry{
421 Offset: off,
422 Tag: a.tag,
423 Children: a.children,
424 Field: make([]Field, len(a.field)),
425 }
426
427
428
429
430 type delayed struct {
431 idx int
432 off uint64
433 fmt format
434 }
435 var delay []delayed
436
437 resolveStrx := func(strBase, off uint64) string {
438 off += strBase
439 if uint64(int(off)) != off {
440 b.error("DW_FORM_strx offset out of range")
441 }
442
443 b1 := makeBuf(b.dwarf, b.format, "str_offsets", 0, b.dwarf.strOffsets)
444 b1.skip(int(off))
445 is64, _ := b.format.dwarf64()
446 if is64 {
447 off = b1.uint64()
448 } else {
449 off = uint64(b1.uint32())
450 }
451 if b1.err != nil {
452 b.err = b1.err
453 return ""
454 }
455 if uint64(int(off)) != off {
456 b.error("DW_FORM_strx indirect offset out of range")
457 }
458 b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
459 b1.skip(int(off))
460 val := b1.string()
461 if b1.err != nil {
462 b.err = b1.err
463 }
464 return val
465 }
466
467 resolveRnglistx := func(rnglistsBase, off uint64) uint64 {
468 is64, _ := b.format.dwarf64()
469 if is64 {
470 off *= 8
471 } else {
472 off *= 4
473 }
474 off += rnglistsBase
475 if uint64(int(off)) != off {
476 b.error("DW_FORM_rnglistx offset out of range")
477 }
478
479 b1 := makeBuf(b.dwarf, b.format, "rnglists", 0, b.dwarf.rngLists)
480 b1.skip(int(off))
481 if is64 {
482 off = b1.uint64()
483 } else {
484 off = uint64(b1.uint32())
485 }
486 if b1.err != nil {
487 b.err = b1.err
488 return 0
489 }
490 if uint64(int(off)) != off {
491 b.error("DW_FORM_rnglistx indirect offset out of range")
492 }
493 return rnglistsBase + off
494 }
495
496 for i := range e.Field {
497 e.Field[i].Attr = a.field[i].attr
498 e.Field[i].Class = a.field[i].class
499 fmt := a.field[i].fmt
500 if fmt == formIndirect {
501 fmt = format(b.uint())
502 e.Field[i].Class = formToClass(fmt, a.field[i].attr, vers, b)
503 }
504 var val any
505 switch fmt {
506 default:
507 b.error("unknown entry attr format 0x" + strconv.FormatInt(int64(fmt), 16))
508
509
510 case formAddr:
511 val = b.addr()
512 case formAddrx, formAddrx1, formAddrx2, formAddrx3, formAddrx4:
513 var off uint64
514 switch fmt {
515 case formAddrx:
516 off = b.uint()
517 case formAddrx1:
518 off = uint64(b.uint8())
519 case formAddrx2:
520 off = uint64(b.uint16())
521 case formAddrx3:
522 off = uint64(b.uint24())
523 case formAddrx4:
524 off = uint64(b.uint32())
525 }
526 if b.dwarf.addr == nil {
527 b.error("DW_FORM_addrx with no .debug_addr section")
528 }
529 if b.err != nil {
530 return nil
531 }
532
533
534
535
536
537 var addrBase int64
538 if cu != nil {
539 addrBase, _ = cu.Val(AttrAddrBase).(int64)
540 } else if a.tag == TagCompileUnit {
541 delay = append(delay, delayed{i, off, formAddrx})
542 break
543 }
544
545 var err error
546 val, err = b.dwarf.debugAddr(b.format, uint64(addrBase), off)
547 if err != nil {
548 if b.err == nil {
549 b.err = err
550 }
551 return nil
552 }
553
554
555 case formDwarfBlock1:
556 val = b.bytes(int(b.uint8()))
557 case formDwarfBlock2:
558 val = b.bytes(int(b.uint16()))
559 case formDwarfBlock4:
560 val = b.bytes(int(b.uint32()))
561 case formDwarfBlock:
562 val = b.bytes(int(b.uint()))
563
564
565 case formData1:
566 val = int64(b.uint8())
567 case formData2:
568 val = int64(b.uint16())
569 case formData4:
570 val = int64(b.uint32())
571 case formData8:
572 val = int64(b.uint64())
573 case formData16:
574 val = b.bytes(16)
575 case formSdata:
576 val = int64(b.int())
577 case formUdata:
578 val = int64(b.uint())
579 case formImplicitConst:
580 val = a.field[i].val
581
582
583 case formFlag:
584 val = b.uint8() == 1
585
586 case formFlagPresent:
587
588
589 val = true
590
591
592 case formRefAddr:
593 vers := b.format.version()
594 if vers == 0 {
595 b.error("unknown version for DW_FORM_ref_addr")
596 } else if vers == 2 {
597 val = Offset(b.addr())
598 } else {
599 is64, known := b.format.dwarf64()
600 if !known {
601 b.error("unknown size for DW_FORM_ref_addr")
602 } else if is64 {
603 val = Offset(b.uint64())
604 } else {
605 val = Offset(b.uint32())
606 }
607 }
608 case formRef1:
609 val = Offset(b.uint8()) + ubase
610 case formRef2:
611 val = Offset(b.uint16()) + ubase
612 case formRef4:
613 val = Offset(b.uint32()) + ubase
614 case formRef8:
615 val = Offset(b.uint64()) + ubase
616 case formRefUdata:
617 val = Offset(b.uint()) + ubase
618
619
620 case formString:
621 val = b.string()
622 case formStrp, formLineStrp:
623 var off uint64
624 is64, known := b.format.dwarf64()
625 if !known {
626 b.error("unknown size for DW_FORM_strp/line_strp")
627 } else if is64 {
628 off = b.uint64()
629 } else {
630 off = uint64(b.uint32())
631 }
632 if uint64(int(off)) != off {
633 b.error("DW_FORM_strp/line_strp offset out of range")
634 }
635 if b.err != nil {
636 return nil
637 }
638 var b1 buf
639 if fmt == formStrp {
640 b1 = makeBuf(b.dwarf, b.format, "str", 0, b.dwarf.str)
641 } else {
642 if len(b.dwarf.lineStr) == 0 {
643 b.error("DW_FORM_line_strp with no .debug_line_str section")
644 return nil
645 }
646 b1 = makeBuf(b.dwarf, b.format, "line_str", 0, b.dwarf.lineStr)
647 }
648 b1.skip(int(off))
649 val = b1.string()
650 if b1.err != nil {
651 b.err = b1.err
652 return nil
653 }
654 case formStrx, formStrx1, formStrx2, formStrx3, formStrx4:
655 var off uint64
656 switch fmt {
657 case formStrx:
658 off = b.uint()
659 case formStrx1:
660 off = uint64(b.uint8())
661 case formStrx2:
662 off = uint64(b.uint16())
663 case formStrx3:
664 off = uint64(b.uint24())
665 case formStrx4:
666 off = uint64(b.uint32())
667 }
668 if len(b.dwarf.strOffsets) == 0 {
669 b.error("DW_FORM_strx with no .debug_str_offsets section")
670 }
671 is64, known := b.format.dwarf64()
672 if !known {
673 b.error("unknown offset size for DW_FORM_strx")
674 }
675 if b.err != nil {
676 return nil
677 }
678 if is64 {
679 off *= 8
680 } else {
681 off *= 4
682 }
683
684
685
686
687
688 var strBase int64
689 if cu != nil {
690 strBase, _ = cu.Val(AttrStrOffsetsBase).(int64)
691 } else if a.tag == TagCompileUnit {
692 delay = append(delay, delayed{i, off, formStrx})
693 break
694 }
695
696 val = resolveStrx(uint64(strBase), off)
697
698 case formStrpSup:
699 is64, known := b.format.dwarf64()
700 if !known {
701 b.error("unknown size for DW_FORM_strp_sup")
702 } else if is64 {
703 val = b.uint64()
704 } else {
705 val = b.uint32()
706 }
707
708
709
710
711 case formSecOffset, formGnuRefAlt, formGnuStrpAlt:
712 is64, known := b.format.dwarf64()
713 if !known {
714 b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16))
715 } else if is64 {
716 val = int64(b.uint64())
717 } else {
718 val = int64(b.uint32())
719 }
720
721
722
723 case formExprloc:
724 val = b.bytes(int(b.uint()))
725
726
727
728 case formRefSig8:
729
730 val = b.uint64()
731 case formRefSup4:
732 val = b.uint32()
733 case formRefSup8:
734 val = b.uint64()
735
736
737 case formLoclistx:
738 val = b.uint()
739
740
741 case formRnglistx:
742 off := b.uint()
743
744
745
746
747
748 var rnglistsBase int64
749 if cu != nil {
750 rnglistsBase, _ = cu.Val(AttrRnglistsBase).(int64)
751 } else if a.tag == TagCompileUnit {
752 delay = append(delay, delayed{i, off, formRnglistx})
753 break
754 }
755
756 val = resolveRnglistx(uint64(rnglistsBase), off)
757 }
758
759 e.Field[i].Val = val
760 }
761 if b.err != nil {
762 return nil
763 }
764
765 for _, del := range delay {
766 switch del.fmt {
767 case formAddrx:
768 addrBase, _ := e.Val(AttrAddrBase).(int64)
769 val, err := b.dwarf.debugAddr(b.format, uint64(addrBase), del.off)
770 if err != nil {
771 b.err = err
772 return nil
773 }
774 e.Field[del.idx].Val = val
775 case formStrx:
776 strBase, _ := e.Val(AttrStrOffsetsBase).(int64)
777 e.Field[del.idx].Val = resolveStrx(uint64(strBase), del.off)
778 if b.err != nil {
779 return nil
780 }
781 case formRnglistx:
782 rnglistsBase, _ := e.Val(AttrRnglistsBase).(int64)
783 e.Field[del.idx].Val = resolveRnglistx(uint64(rnglistsBase), del.off)
784 if b.err != nil {
785 return nil
786 }
787 }
788 }
789
790 return e
791 }
792
793
794
795
796
797
798 type Reader struct {
799 b buf
800 d *Data
801 err error
802 unit int
803 lastUnit bool
804 lastChildren bool
805 lastSibling Offset
806 cu *Entry
807 }
808
809
810
811 func (d *Data) Reader() *Reader {
812 r := &Reader{d: d}
813 r.Seek(0)
814 return r
815 }
816
817
818
819 func (r *Reader) AddressSize() int {
820 return r.d.unit[r.unit].asize
821 }
822
823
824 func (r *Reader) ByteOrder() binary.ByteOrder {
825 return r.b.order
826 }
827
828
829
830 func (r *Reader) Seek(off Offset) {
831 d := r.d
832 r.err = nil
833 r.lastChildren = false
834 if off == 0 {
835 if len(d.unit) == 0 {
836 return
837 }
838 u := &d.unit[0]
839 r.unit = 0
840 r.b = makeBuf(r.d, u, "info", u.off, u.data)
841 r.cu = nil
842 return
843 }
844
845 i := d.offsetToUnit(off)
846 if i == -1 {
847 r.err = errors.New("offset out of range")
848 return
849 }
850 if i != r.unit {
851 r.cu = nil
852 }
853 u := &d.unit[i]
854 r.unit = i
855 r.b = makeBuf(r.d, u, "info", off, u.data[off-u.off:])
856 }
857
858
859 func (r *Reader) maybeNextUnit() {
860 for len(r.b.data) == 0 && r.unit+1 < len(r.d.unit) {
861 r.nextUnit()
862 }
863 }
864
865
866 func (r *Reader) nextUnit() {
867 r.unit++
868 u := &r.d.unit[r.unit]
869 r.b = makeBuf(r.d, u, "info", u.off, u.data)
870 r.cu = nil
871 }
872
873
874
875
876
877 func (r *Reader) Next() (*Entry, error) {
878 if r.err != nil {
879 return nil, r.err
880 }
881 r.maybeNextUnit()
882 if len(r.b.data) == 0 {
883 return nil, nil
884 }
885 u := &r.d.unit[r.unit]
886 e := r.b.entry(r.cu, u.atable, u.base, u.vers)
887 if r.b.err != nil {
888 r.err = r.b.err
889 return nil, r.err
890 }
891 r.lastUnit = false
892 if e != nil {
893 r.lastChildren = e.Children
894 if r.lastChildren {
895 r.lastSibling, _ = e.Val(AttrSibling).(Offset)
896 }
897 if e.Tag == TagCompileUnit || e.Tag == TagPartialUnit {
898 r.lastUnit = true
899 r.cu = e
900 }
901 } else {
902 r.lastChildren = false
903 }
904 return e, nil
905 }
906
907
908
909
910 func (r *Reader) SkipChildren() {
911 if r.err != nil || !r.lastChildren {
912 return
913 }
914
915
916
917
918
919 if r.lastSibling >= r.b.off {
920 r.Seek(r.lastSibling)
921 return
922 }
923
924 if r.lastUnit && r.unit+1 < len(r.d.unit) {
925 r.nextUnit()
926 return
927 }
928
929 for {
930 e, err := r.Next()
931 if err != nil || e == nil || e.Tag == 0 {
932 break
933 }
934 if e.Children {
935 r.SkipChildren()
936 }
937 }
938 }
939
940
941
942 func (r *Reader) clone() typeReader {
943 return r.d.Reader()
944 }
945
946
947
948 func (r *Reader) offset() Offset {
949 return r.b.off
950 }
951
952
953
954
955
956
957
958
959
960
961
962
963
964 func (r *Reader) SeekPC(pc uint64) (*Entry, error) {
965 unit := r.unit
966 for i := 0; i < len(r.d.unit); i++ {
967 if unit >= len(r.d.unit) {
968 unit = 0
969 }
970 r.err = nil
971 r.lastChildren = false
972 r.unit = unit
973 r.cu = nil
974 u := &r.d.unit[unit]
975 r.b = makeBuf(r.d, u, "info", u.off, u.data)
976 e, err := r.Next()
977 if err != nil {
978 return nil, err
979 }
980 ranges, err := r.d.Ranges(e)
981 if err != nil {
982 return nil, err
983 }
984 for _, pcs := range ranges {
985 if pcs[0] <= pc && pc < pcs[1] {
986 return e, nil
987 }
988 }
989 unit++
990 }
991 return nil, ErrUnknownPC
992 }
993
994
995
996
997 func (d *Data) Ranges(e *Entry) ([][2]uint64, error) {
998 var ret [][2]uint64
999
1000 low, lowOK := e.Val(AttrLowpc).(uint64)
1001
1002 var high uint64
1003 var highOK bool
1004 highField := e.AttrField(AttrHighpc)
1005 if highField != nil {
1006 switch highField.Class {
1007 case ClassAddress:
1008 high, highOK = highField.Val.(uint64)
1009 case ClassConstant:
1010 off, ok := highField.Val.(int64)
1011 if ok {
1012 high = low + uint64(off)
1013 highOK = true
1014 }
1015 }
1016 }
1017
1018 if lowOK && highOK {
1019 ret = append(ret, [2]uint64{low, high})
1020 }
1021
1022 var u *unit
1023 if uidx := d.offsetToUnit(e.Offset); uidx >= 0 && uidx < len(d.unit) {
1024 u = &d.unit[uidx]
1025 }
1026
1027 if u != nil && u.vers >= 5 && d.rngLists != nil {
1028
1029 field := e.AttrField(AttrRanges)
1030 if field == nil {
1031 return ret, nil
1032 }
1033 switch field.Class {
1034 case ClassRangeListPtr:
1035 ranges, rangesOK := field.Val.(int64)
1036 if !rangesOK {
1037 return ret, nil
1038 }
1039 cu, base, err := d.baseAddressForEntry(e)
1040 if err != nil {
1041 return nil, err
1042 }
1043 return d.dwarf5Ranges(u, cu, base, ranges, ret)
1044
1045 case ClassRngList:
1046 rnglist, ok := field.Val.(uint64)
1047 if !ok {
1048 return ret, nil
1049 }
1050 cu, base, err := d.baseAddressForEntry(e)
1051 if err != nil {
1052 return nil, err
1053 }
1054 return d.dwarf5Ranges(u, cu, base, int64(rnglist), ret)
1055
1056 default:
1057 return ret, nil
1058 }
1059 }
1060
1061
1062 ranges, rangesOK := e.Val(AttrRanges).(int64)
1063 if rangesOK && d.ranges != nil {
1064 _, base, err := d.baseAddressForEntry(e)
1065 if err != nil {
1066 return nil, err
1067 }
1068 return d.dwarf2Ranges(u, base, ranges, ret)
1069 }
1070
1071 return ret, nil
1072 }
1073
1074
1075
1076
1077
1078
1079 func (d *Data) baseAddressForEntry(e *Entry) (*Entry, uint64, error) {
1080 var cu *Entry
1081 if e.Tag == TagCompileUnit {
1082 cu = e
1083 } else {
1084 i := d.offsetToUnit(e.Offset)
1085 if i == -1 {
1086 return nil, 0, errors.New("no unit for entry")
1087 }
1088 u := &d.unit[i]
1089 b := makeBuf(d, u, "info", u.off, u.data)
1090 cu = b.entry(nil, u.atable, u.base, u.vers)
1091 if b.err != nil {
1092 return nil, 0, b.err
1093 }
1094 }
1095
1096 if cuEntry, cuEntryOK := cu.Val(AttrEntrypc).(uint64); cuEntryOK {
1097 return cu, cuEntry, nil
1098 } else if cuLow, cuLowOK := cu.Val(AttrLowpc).(uint64); cuLowOK {
1099 return cu, cuLow, nil
1100 }
1101
1102 return cu, 0, nil
1103 }
1104
1105 func (d *Data) dwarf2Ranges(u *unit, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) {
1106 buf := makeBuf(d, u, "ranges", Offset(ranges), d.ranges[ranges:])
1107 for len(buf.data) > 0 {
1108 low := buf.addr()
1109 high := buf.addr()
1110
1111 if low == 0 && high == 0 {
1112 break
1113 }
1114
1115 if low == ^uint64(0)>>uint((8-u.addrsize())*8) {
1116 base = high
1117 } else {
1118 ret = append(ret, [2]uint64{base + low, base + high})
1119 }
1120 }
1121
1122 return ret, nil
1123 }
1124
1125
1126
1127 func (d *Data) dwarf5Ranges(u *unit, cu *Entry, base uint64, ranges int64, ret [][2]uint64) ([][2]uint64, error) {
1128 var addrBase int64
1129 if cu != nil {
1130 addrBase, _ = cu.Val(AttrAddrBase).(int64)
1131 }
1132
1133 buf := makeBuf(d, u, "rnglists", 0, d.rngLists)
1134 buf.skip(int(ranges))
1135 for {
1136 opcode := buf.uint8()
1137 switch opcode {
1138 case rleEndOfList:
1139 if buf.err != nil {
1140 return nil, buf.err
1141 }
1142 return ret, nil
1143
1144 case rleBaseAddressx:
1145 baseIdx := buf.uint()
1146 var err error
1147 base, err = d.debugAddr(u, uint64(addrBase), baseIdx)
1148 if err != nil {
1149 return nil, err
1150 }
1151
1152 case rleStartxEndx:
1153 startIdx := buf.uint()
1154 endIdx := buf.uint()
1155
1156 start, err := d.debugAddr(u, uint64(addrBase), startIdx)
1157 if err != nil {
1158 return nil, err
1159 }
1160 end, err := d.debugAddr(u, uint64(addrBase), endIdx)
1161 if err != nil {
1162 return nil, err
1163 }
1164 ret = append(ret, [2]uint64{start, end})
1165
1166 case rleStartxLength:
1167 startIdx := buf.uint()
1168 len := buf.uint()
1169 start, err := d.debugAddr(u, uint64(addrBase), startIdx)
1170 if err != nil {
1171 return nil, err
1172 }
1173 ret = append(ret, [2]uint64{start, start + len})
1174
1175 case rleOffsetPair:
1176 off1 := buf.uint()
1177 off2 := buf.uint()
1178 ret = append(ret, [2]uint64{base + off1, base + off2})
1179
1180 case rleBaseAddress:
1181 base = buf.addr()
1182
1183 case rleStartEnd:
1184 start := buf.addr()
1185 end := buf.addr()
1186 ret = append(ret, [2]uint64{start, end})
1187
1188 case rleStartLength:
1189 start := buf.addr()
1190 len := buf.uint()
1191 ret = append(ret, [2]uint64{start, start + len})
1192 }
1193 }
1194 }
1195
1196
1197 func (d *Data) debugAddr(format dataFormat, addrBase, idx uint64) (uint64, error) {
1198 off := idx*uint64(format.addrsize()) + addrBase
1199
1200 if uint64(int(off)) != off {
1201 return 0, errors.New("offset out of range")
1202 }
1203
1204 b := makeBuf(d, format, "addr", 0, d.addr)
1205 b.skip(int(off))
1206 val := b.addr()
1207 if b.err != nil {
1208 return 0, b.err
1209 }
1210 return val, nil
1211 }
1212
View as plain text