1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Buffered reading and decoding of DWARF data streams.
16
17package dwarf
18
19import (
20	"encoding/binary"
21	"fmt"
22	"strconv"
23)
24
25// Data buffer being decoded.
26type buf struct {
27	dwarf  *Data
28	order  binary.ByteOrder
29	format dataFormat
30	name   string
31	off    Offset
32	data   []byte
33	err    error
34}
35
36// Data format, other than byte order.  This affects the handling of
37// certain field formats.
38type dataFormat interface {
39	// DWARF version number.  Zero means unknown.
40	version() int
41
42	// 64-bit DWARF format?
43	dwarf64() (dwarf64 bool, isKnown bool)
44
45	// Size of an address, in bytes.  Zero means unknown.
46	addrsize() int
47}
48
49// Some parts of DWARF have no data format, e.g., abbrevs.
50type unknownFormat struct{}
51
52func (u unknownFormat) version() int {
53	return 0
54}
55
56func (u unknownFormat) dwarf64() (bool, bool) {
57	return false, false
58}
59
60func (u unknownFormat) addrsize() int {
61	return 0
62}
63
64func makeBuf(d *Data, format dataFormat, name string, off Offset, data []byte) buf {
65	return buf{d, d.order, format, name, off, data, nil}
66}
67
68func (b *buf) slice(length int) buf {
69	n := *b
70	data := b.data
71	b.skip(length) // Will validate length.
72	n.data = data[:length]
73	return n
74}
75
76func (b *buf) uint8() uint8 {
77	if len(b.data) < 1 {
78		b.error("underflow")
79		return 0
80	}
81	val := b.data[0]
82	b.data = b.data[1:]
83	b.off++
84	return val
85}
86
87func (b *buf) bytes(n int) []byte {
88	if len(b.data) < n {
89		b.error("underflow")
90		return nil
91	}
92	data := b.data[0:n]
93	b.data = b.data[n:]
94	b.off += Offset(n)
95	return data
96}
97
98func (b *buf) skip(n int) { b.bytes(n) }
99
100// string returns the NUL-terminated (C-like) string at the start of the buffer.
101// The terminal NUL is discarded.
102func (b *buf) string() string {
103	for i := 0; i < len(b.data); i++ {
104		if b.data[i] == 0 {
105			s := string(b.data[0:i])
106			b.data = b.data[i+1:]
107			b.off += Offset(i + 1)
108			return s
109		}
110	}
111	b.error("underflow")
112	return ""
113}
114
115func (b *buf) uint16() uint16 {
116	a := b.bytes(2)
117	if a == nil {
118		return 0
119	}
120	return b.order.Uint16(a)
121}
122
123func (b *buf) uint32() uint32 {
124	a := b.bytes(4)
125	if a == nil {
126		return 0
127	}
128	return b.order.Uint32(a)
129}
130
131func (b *buf) uint64() uint64 {
132	a := b.bytes(8)
133	if a == nil {
134		return 0
135	}
136	return b.order.Uint64(a)
137}
138
139// Read a varint, which is 7 bits per byte, little endian.
140// the 0x80 bit means read another byte.
141func (b *buf) varint() (c uint64, bits uint) {
142	for i := 0; i < len(b.data); i++ {
143		byte := b.data[i]
144		c |= uint64(byte&0x7F) << bits
145		bits += 7
146		if byte&0x80 == 0 {
147			b.off += Offset(i + 1)
148			b.data = b.data[i+1:]
149			return c, bits
150		}
151	}
152	return 0, 0
153}
154
155// Unsigned int is just a varint.
156func (b *buf) uint() uint64 {
157	x, _ := b.varint()
158	return x
159}
160
161// Signed int is a sign-extended varint.
162func (b *buf) int() int64 {
163	ux, bits := b.varint()
164	x := int64(ux)
165	if x&(1<<(bits-1)) != 0 {
166		x |= -1 << bits
167	}
168	return x
169}
170
171// Address-sized uint.
172func (b *buf) addr() uint64 {
173	switch b.format.addrsize() {
174	case 1:
175		return uint64(b.uint8())
176	case 2:
177		return uint64(b.uint16())
178	case 4:
179		return uint64(b.uint32())
180	case 8:
181		return uint64(b.uint64())
182	}
183	b.error("unknown address size")
184	return 0
185}
186
187// assertEmpty checks that everything has been read from b.
188func (b *buf) assertEmpty() {
189	if len(b.data) == 0 {
190		return
191	}
192	if len(b.data) > 5 {
193		b.error(fmt.Sprintf("unexpected extra data: %x...", b.data[0:5]))
194	}
195	b.error(fmt.Sprintf("unexpected extra data: %x", b.data))
196}
197
198func (b *buf) error(s string) {
199	if b.err == nil {
200		b.data = nil
201		b.err = DecodeError{b.name, b.off, s}
202	}
203}
204
205type DecodeError struct {
206	Name   string
207	Offset Offset
208	Err    string
209}
210
211func (e DecodeError) Error() string {
212	return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err
213}
214