]>
Commit | Line | Data |
---|---|---|
22b955cc | 1 | // Copyright 2009 The Go Authors. All rights reserved. |
7a938933 ILT |
2 | // Use of this source code is governed by a BSD-style |
3 | // license that can be found in the LICENSE file. | |
4 | ||
5 | // Buffered reading and decoding of DWARF data streams. | |
6 | ||
7 | package dwarf | |
8 | ||
9 | import ( | |
5a8ea165 | 10 | "bytes" |
7a938933 | 11 | "encoding/binary" |
7a938933 ILT |
12 | "strconv" |
13 | ) | |
14 | ||
15 | // Data buffer being decoded. | |
16 | type buf struct { | |
be47d6ec ILT |
17 | dwarf *Data |
18 | order binary.ByteOrder | |
19 | format dataFormat | |
20 | name string | |
21 | off Offset | |
22 | data []byte | |
23 | err error | |
7a938933 ILT |
24 | } |
25 | ||
22b955cc | 26 | // Data format, other than byte order. This affects the handling of |
be47d6ec ILT |
27 | // certain field formats. |
28 | type dataFormat interface { | |
22b955cc | 29 | // DWARF version number. Zero means unknown. |
be47d6ec ILT |
30 | version() int |
31 | ||
32 | // 64-bit DWARF format? | |
33 | dwarf64() (dwarf64 bool, isKnown bool) | |
34 | ||
22b955cc | 35 | // Size of an address, in bytes. Zero means unknown. |
be47d6ec ILT |
36 | addrsize() int |
37 | } | |
38 | ||
39 | // Some parts of DWARF have no data format, e.g., abbrevs. | |
40 | type unknownFormat struct{} | |
41 | ||
42 | func (u unknownFormat) version() int { | |
43 | return 0 | |
44 | } | |
45 | ||
46 | func (u unknownFormat) dwarf64() (bool, bool) { | |
47 | return false, false | |
48 | } | |
49 | ||
50 | func (u unknownFormat) addrsize() int { | |
51 | return 0 | |
52 | } | |
53 | ||
54 | func makeBuf(d *Data, format dataFormat, name string, off Offset, data []byte) buf { | |
55 | return buf{d, d.order, format, name, off, data, nil} | |
7a938933 ILT |
56 | } |
57 | ||
58 | func (b *buf) uint8() uint8 { | |
59 | if len(b.data) < 1 { | |
60 | b.error("underflow") | |
61 | return 0 | |
62 | } | |
63 | val := b.data[0] | |
64 | b.data = b.data[1:] | |
65 | b.off++ | |
66 | return val | |
67 | } | |
68 | ||
69 | func (b *buf) bytes(n int) []byte { | |
70 | if len(b.data) < n { | |
71 | b.error("underflow") | |
72 | return nil | |
73 | } | |
74 | data := b.data[0:n] | |
75 | b.data = b.data[n:] | |
76 | b.off += Offset(n) | |
77 | return data | |
78 | } | |
79 | ||
80 | func (b *buf) skip(n int) { b.bytes(n) } | |
81 | ||
82 | func (b *buf) string() string { | |
5a8ea165 ILT |
83 | i := bytes.IndexByte(b.data, 0) |
84 | if i < 0 { | |
85 | b.error("underflow") | |
86 | return "" | |
7a938933 | 87 | } |
5a8ea165 ILT |
88 | |
89 | s := string(b.data[0:i]) | |
90 | b.data = b.data[i+1:] | |
91 | b.off += Offset(i + 1) | |
92 | return s | |
7a938933 ILT |
93 | } |
94 | ||
95 | func (b *buf) uint16() uint16 { | |
96 | a := b.bytes(2) | |
97 | if a == nil { | |
98 | return 0 | |
99 | } | |
100 | return b.order.Uint16(a) | |
101 | } | |
102 | ||
5a8ea165 ILT |
103 | func (b *buf) uint24() uint32 { |
104 | a := b.bytes(3) | |
105 | if a == nil { | |
106 | return 0 | |
107 | } | |
108 | if b.dwarf.bigEndian { | |
109 | return uint32(a[2]) | uint32(a[1])<<8 | uint32(a[0])<<16 | |
110 | } else { | |
111 | return uint32(a[0]) | uint32(a[1])<<8 | uint32(a[2])<<16 | |
112 | } | |
113 | } | |
114 | ||
7a938933 ILT |
115 | func (b *buf) uint32() uint32 { |
116 | a := b.bytes(4) | |
117 | if a == nil { | |
118 | return 0 | |
119 | } | |
120 | return b.order.Uint32(a) | |
121 | } | |
122 | ||
123 | func (b *buf) uint64() uint64 { | |
124 | a := b.bytes(8) | |
125 | if a == nil { | |
126 | return 0 | |
127 | } | |
128 | return b.order.Uint64(a) | |
129 | } | |
130 | ||
131 | // Read a varint, which is 7 bits per byte, little endian. | |
132 | // the 0x80 bit means read another byte. | |
133 | func (b *buf) varint() (c uint64, bits uint) { | |
134 | for i := 0; i < len(b.data); i++ { | |
135 | byte := b.data[i] | |
136 | c |= uint64(byte&0x7F) << bits | |
137 | bits += 7 | |
138 | if byte&0x80 == 0 { | |
139 | b.off += Offset(i + 1) | |
140 | b.data = b.data[i+1:] | |
141 | return c, bits | |
142 | } | |
143 | } | |
144 | return 0, 0 | |
145 | } | |
146 | ||
147 | // Unsigned int is just a varint. | |
148 | func (b *buf) uint() uint64 { | |
149 | x, _ := b.varint() | |
150 | return x | |
151 | } | |
152 | ||
153 | // Signed int is a sign-extended varint. | |
154 | func (b *buf) int() int64 { | |
155 | ux, bits := b.varint() | |
156 | x := int64(ux) | |
157 | if x&(1<<(bits-1)) != 0 { | |
158 | x |= -1 << bits | |
159 | } | |
160 | return x | |
161 | } | |
162 | ||
163 | // Address-sized uint. | |
164 | func (b *buf) addr() uint64 { | |
be47d6ec ILT |
165 | switch b.format.addrsize() { |
166 | case 1: | |
167 | return uint64(b.uint8()) | |
168 | case 2: | |
169 | return uint64(b.uint16()) | |
170 | case 4: | |
171 | return uint64(b.uint32()) | |
172 | case 8: | |
22b955cc | 173 | return b.uint64() |
7a938933 ILT |
174 | } |
175 | b.error("unknown address size") | |
176 | return 0 | |
177 | } | |
178 | ||
af146490 ILT |
179 | func (b *buf) unitLength() (length Offset, dwarf64 bool) { |
180 | length = Offset(b.uint32()) | |
181 | if length == 0xffffffff { | |
182 | dwarf64 = true | |
183 | length = Offset(b.uint64()) | |
184 | } else if length >= 0xfffffff0 { | |
185 | b.error("unit length has reserved value") | |
186 | } | |
187 | return | |
188 | } | |
189 | ||
7a938933 ILT |
190 | func (b *buf) error(s string) { |
191 | if b.err == nil { | |
192 | b.data = nil | |
193 | b.err = DecodeError{b.name, b.off, s} | |
194 | } | |
195 | } | |
196 | ||
197 | type DecodeError struct { | |
198 | Name string | |
199 | Offset Offset | |
2fd401c8 | 200 | Err string |
7a938933 ILT |
201 | } |
202 | ||
2fd401c8 | 203 | func (e DecodeError) Error() string { |
d5363590 | 204 | return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err |
7a938933 | 205 | } |