1// Copyright 2009 The Go Authors. All rights reserved.
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
7package dwarf
8
9import (
10	"bytes"
11	"encoding/binary"
12	"strconv"
13)
14
15// Data buffer being decoded.
16type buf struct {
17	dwarf  *Data
18	order  binary.ByteOrder
19	format dataFormat
20	name   string
21	off    Offset
22	data   []byte
23	err    error
24}
25
26// Data format, other than byte order. This affects the handling of
27// certain field formats.
28type dataFormat interface {
29	// DWARF version number. Zero means unknown.
30	version() int
31
32	// 64-bit DWARF format?
33	dwarf64() (dwarf64 bool, isKnown bool)
34
35	// Size of an address, in bytes. Zero means unknown.
36	addrsize() int
37}
38
39// Some parts of DWARF have no data format, e.g., abbrevs.
40type unknownFormat struct{}
41
42func (u unknownFormat) version() int {
43	return 0
44}
45
46func (u unknownFormat) dwarf64() (bool, bool) {
47	return false, false
48}
49
50func (u unknownFormat) addrsize() int {
51	return 0
52}
53
54func makeBuf(d *Data, format dataFormat, name string, off Offset, data []byte) buf {
55	return buf{d, d.order, format, name, off, data, nil}
56}
57
58func (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
69func (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
80func (b *buf) skip(n int) { b.bytes(n) }
81
82func (b *buf) string() string {
83	i := bytes.IndexByte(b.data, 0)
84	if i < 0 {
85		b.error("underflow")
86		return ""
87	}
88
89	s := string(b.data[0:i])
90	b.data = b.data[i+1:]
91	b.off += Offset(i + 1)
92	return s
93}
94
95func (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
103func (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
115func (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
123func (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.
133func (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.
148func (b *buf) uint() uint64 {
149	x, _ := b.varint()
150	return x
151}
152
153// Signed int is a sign-extended varint.
154func (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.
164func (b *buf) addr() uint64 {
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:
173		return b.uint64()
174	}
175	b.error("unknown address size")
176	return 0
177}
178
179func (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
190func (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
197type DecodeError struct {
198	Name   string
199	Offset Offset
200	Err    string
201}
202
203func (e DecodeError) Error() string {
204	return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err
205}
206