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