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 *unit5
21 asize int
22 vers int
23 is64 bool
24 utype uint8
25 }
26
27 type unit5 struct {
28 addrBase uint64
29 strOffsetsBase uint64
30 rngListsBase uint64
31 locListsBase uint64
32 }
33
34
35
36 func (u *unit) version() int {
37 return u.vers
38 }
39
40 func (u *unit) dwarf64() (bool, bool) {
41 return u.is64, true
42 }
43
44 func (u *unit) addrsize() int {
45 return u.asize
46 }
47
48 func (u *unit) addrBase() uint64 {
49 if u.unit5 != nil {
50 return u.unit5.addrBase
51 }
52 return 0
53 }
54
55 func (u *unit) strOffsetsBase() uint64 {
56 if u.unit5 != nil {
57 return u.unit5.strOffsetsBase
58 }
59 return 0
60 }
61
62 func (u *unit) rngListsBase() uint64 {
63 if u.unit5 != nil {
64 return u.unit5.rngListsBase
65 }
66 return 0
67 }
68
69 func (u *unit) locListsBase() uint64 {
70 if u.unit5 != nil {
71 return u.unit5.locListsBase
72 }
73 return 0
74 }
75
76 func (d *Data) parseUnits() ([]unit, error) {
77
78 nunit := 0
79 b := makeBuf(d, unknownFormat{}, "info", 0, d.info)
80 for len(b.data) > 0 {
81 len, _ := b.unitLength()
82 if len != Offset(uint32(len)) {
83 b.error("unit length overflow")
84 break
85 }
86 b.skip(int(len))
87 if len > 0 {
88 nunit++
89 }
90 }
91 if b.err != nil {
92 return nil, b.err
93 }
94
95
96 b = makeBuf(d, unknownFormat{}, "info", 0, d.info)
97 units := make([]unit, nunit)
98 for i := range units {
99 u := &units[i]
100 u.base = b.off
101 var n Offset
102 if b.err != nil {
103 return nil, b.err
104 }
105 for n == 0 {
106 n, u.is64 = b.unitLength()
107 }
108 dataOff := b.off
109 vers := b.uint16()
110 if vers < 2 || vers > 5 {
111 b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
112 break
113 }
114 u.vers = int(vers)
115 if vers >= 5 {
116 u.utype = b.uint8()
117 u.asize = int(b.uint8())
118 }
119 var abbrevOff uint64
120 if u.is64 {
121 abbrevOff = b.uint64()
122 } else {
123 abbrevOff = uint64(b.uint32())
124 }
125 atable, err := d.parseAbbrev(abbrevOff, u.vers)
126 if err != nil {
127 if b.err == nil {
128 b.err = err
129 }
130 break
131 }
132 u.atable = atable
133 if vers < 5 {
134 u.asize = int(b.uint8())
135 }
136
137 switch u.utype {
138 case utSkeleton, utSplitCompile:
139 b.uint64()
140 case utType, utSplitType:
141 b.uint64()
142 if u.is64 {
143 b.uint64()
144 } else {
145 b.uint32()
146 }
147 }
148
149 u.off = b.off
150 u.data = b.bytes(int(n - (b.off - dataOff)))
151 }
152 if b.err != nil {
153 return nil, b.err
154 }
155 return units, nil
156 }
157
158
159
160 func (d *Data) offsetToUnit(off Offset) int {
161
162 next := sort.Search(len(d.unit), func(i int) bool {
163 return d.unit[i].off > off
164 })
165 if next == 0 {
166 return -1
167 }
168 u := &d.unit[next-1]
169 if u.off <= off && off < u.off+Offset(len(u.data)) {
170 return next - 1
171 }
172 return -1
173 }
174
175 func (d *Data) collectDwarf5BaseOffsets(u *unit) error {
176 if u.unit5 == nil {
177 panic("expected unit5 to be set up already")
178 }
179 b := makeBuf(d, u, "info", u.off, u.data)
180 cu := b.entry(nil, u)
181 if cu == nil {
182
183
184
185 return b.err
186 }
187 if iAddrBase, ok := cu.Val(AttrAddrBase).(int64); ok {
188 u.unit5.addrBase = uint64(iAddrBase)
189 }
190 if iStrOffsetsBase, ok := cu.Val(AttrStrOffsetsBase).(int64); ok {
191 u.unit5.strOffsetsBase = uint64(iStrOffsetsBase)
192 }
193 if iRngListsBase, ok := cu.Val(AttrRnglistsBase).(int64); ok {
194 u.unit5.rngListsBase = uint64(iRngListsBase)
195 }
196 if iLocListsBase, ok := cu.Val(AttrLoclistsBase).(int64); ok {
197 u.unit5.locListsBase = uint64(iLocListsBase)
198 }
199 return nil
200 }
201
View as plain text