1
2
3
4
5 package dwarf
6
7 import (
8 "sort"
9 "strconv"
10 )
11
12
13
14
15 type unit struct {
16 base Offset
17 off Offset
18 data []byte
19 atable abbrevTable
20 asize int
21 vers int
22 utype uint8
23 is64 bool
24 }
25
26
27
28 func (u *unit) version() int {
29 return u.vers
30 }
31
32 func (u *unit) dwarf64() (bool, bool) {
33 return u.is64, true
34 }
35
36 func (u *unit) addrsize() int {
37 return u.asize
38 }
39
40 func (d *Data) parseUnits() ([]unit, error) {
41
42 nunit := 0
43 b := makeBuf(d, unknownFormat{}, "info", 0, d.info)
44 for len(b.data) > 0 {
45 len, _ := b.unitLength()
46 if len != Offset(uint32(len)) {
47 b.error("unit length overflow")
48 break
49 }
50 b.skip(int(len))
51 if len > 0 {
52 nunit++
53 }
54 }
55 if b.err != nil {
56 return nil, b.err
57 }
58
59
60 b = makeBuf(d, unknownFormat{}, "info", 0, d.info)
61 units := make([]unit, nunit)
62 for i := range units {
63 u := &units[i]
64 u.base = b.off
65 var n Offset
66 for n == 0 {
67 n, u.is64 = b.unitLength()
68 }
69 dataOff := b.off
70 vers := b.uint16()
71 if vers < 2 || vers > 5 {
72 b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
73 break
74 }
75 u.vers = int(vers)
76 if vers >= 5 {
77 u.utype = b.uint8()
78 u.asize = int(b.uint8())
79 }
80 var abbrevOff uint64
81 if u.is64 {
82 abbrevOff = b.uint64()
83 } else {
84 abbrevOff = uint64(b.uint32())
85 }
86 atable, err := d.parseAbbrev(abbrevOff, u.vers)
87 if err != nil {
88 if b.err == nil {
89 b.err = err
90 }
91 break
92 }
93 u.atable = atable
94 if vers < 5 {
95 u.asize = int(b.uint8())
96 }
97
98 switch u.utype {
99 case utSkeleton, utSplitCompile:
100 b.uint64()
101 case utType, utSplitType:
102 b.uint64()
103 if u.is64 {
104 b.uint64()
105 } else {
106 b.uint32()
107 }
108 }
109
110 u.off = b.off
111 u.data = b.bytes(int(n - (b.off - dataOff)))
112 }
113 if b.err != nil {
114 return nil, b.err
115 }
116 return units, nil
117 }
118
119
120
121 func (d *Data) offsetToUnit(off Offset) int {
122
123 next := sort.Search(len(d.unit), func(i int) bool {
124 return d.unit[i].off > off
125 })
126 if next == 0 {
127 return -1
128 }
129 u := &d.unit[next-1]
130 if u.off <= off && off < u.off+Offset(len(u.data)) {
131 return next - 1
132 }
133 return -1
134 }
135
View as plain text