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