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 if b.err != nil {
67 return nil, b.err
68 }
69 for n == 0 {
70 n, u.is64 = b.unitLength()
71 }
72 dataOff := b.off
73 vers := b.uint16()
74 if vers < 2 || vers > 5 {
75 b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
76 break
77 }
78 u.vers = int(vers)
79 if vers >= 5 {
80 u.utype = b.uint8()
81 u.asize = int(b.uint8())
82 }
83 var abbrevOff uint64
84 if u.is64 {
85 abbrevOff = b.uint64()
86 } else {
87 abbrevOff = uint64(b.uint32())
88 }
89 atable, err := d.parseAbbrev(abbrevOff, u.vers)
90 if err != nil {
91 if b.err == nil {
92 b.err = err
93 }
94 break
95 }
96 u.atable = atable
97 if vers < 5 {
98 u.asize = int(b.uint8())
99 }
100
101 switch u.utype {
102 case utSkeleton, utSplitCompile:
103 b.uint64()
104 case utType, utSplitType:
105 b.uint64()
106 if u.is64 {
107 b.uint64()
108 } else {
109 b.uint32()
110 }
111 }
112
113 u.off = b.off
114 u.data = b.bytes(int(n - (b.off - dataOff)))
115 }
116 if b.err != nil {
117 return nil, b.err
118 }
119 return units, nil
120 }
121
122
123
124 func (d *Data) offsetToUnit(off Offset) int {
125
126 next := sort.Search(len(d.unit), func(i int) bool {
127 return d.unit[i].off > off
128 })
129 if next == 0 {
130 return -1
131 }
132 u := &d.unit[next-1]
133 if u.off <= off && off < u.off+Offset(len(u.data)) {
134 return next - 1
135 }
136 return -1
137 }
138
View as plain text