206 lines
3.7 KiB
Go
206 lines
3.7 KiB
Go
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
// Buffered reading and decoding of DWARF data streams.
|
||
|
|
||
|
package dwarf
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/binary"
|
||
|
"strconv"
|
||
|
)
|
||
|
|
||
|
// Data buffer being decoded.
|
||
|
type buf struct {
|
||
|
dwarf *Data
|
||
|
order binary.ByteOrder
|
||
|
format dataFormat
|
||
|
name string
|
||
|
off Offset
|
||
|
data []byte
|
||
|
err error
|
||
|
}
|
||
|
|
||
|
// Data format, other than byte order. This affects the handling of
|
||
|
// certain field formats.
|
||
|
type dataFormat interface {
|
||
|
// DWARF version number. Zero means unknown.
|
||
|
version() int
|
||
|
|
||
|
// 64-bit DWARF format?
|
||
|
dwarf64() (dwarf64 bool, isKnown bool)
|
||
|
|
||
|
// Size of an address, in bytes. Zero means unknown.
|
||
|
addrsize() int
|
||
|
}
|
||
|
|
||
|
// Some parts of DWARF have no data format, e.g., abbrevs.
|
||
|
type unknownFormat struct{}
|
||
|
|
||
|
func (u unknownFormat) version() int {
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
func (u unknownFormat) dwarf64() (bool, bool) {
|
||
|
return false, false
|
||
|
}
|
||
|
|
||
|
func (u unknownFormat) addrsize() int {
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
func makeBuf(d *Data, format dataFormat, name string, off Offset, data []byte) buf {
|
||
|
return buf{d, d.order, format, name, off, data, nil}
|
||
|
}
|
||
|
|
||
|
func (b *buf) uint8() uint8 {
|
||
|
if len(b.data) < 1 {
|
||
|
b.error("underflow")
|
||
|
return 0
|
||
|
}
|
||
|
val := b.data[0]
|
||
|
b.data = b.data[1:]
|
||
|
b.off++
|
||
|
return val
|
||
|
}
|
||
|
|
||
|
func (b *buf) bytes(n int) []byte {
|
||
|
if len(b.data) < n {
|
||
|
b.error("underflow")
|
||
|
return nil
|
||
|
}
|
||
|
data := b.data[0:n]
|
||
|
b.data = b.data[n:]
|
||
|
b.off += Offset(n)
|
||
|
return data
|
||
|
}
|
||
|
|
||
|
func (b *buf) skip(n int) { b.bytes(n) }
|
||
|
|
||
|
func (b *buf) string() string {
|
||
|
i := bytes.IndexByte(b.data, 0)
|
||
|
if i < 0 {
|
||
|
b.error("underflow")
|
||
|
return ""
|
||
|
}
|
||
|
|
||
|
s := string(b.data[0:i])
|
||
|
b.data = b.data[i+1:]
|
||
|
b.off += Offset(i + 1)
|
||
|
return s
|
||
|
}
|
||
|
|
||
|
func (b *buf) uint16() uint16 {
|
||
|
a := b.bytes(2)
|
||
|
if a == nil {
|
||
|
return 0
|
||
|
}
|
||
|
return b.order.Uint16(a)
|
||
|
}
|
||
|
|
||
|
func (b *buf) uint24() uint32 {
|
||
|
a := b.bytes(3)
|
||
|
if a == nil {
|
||
|
return 0
|
||
|
}
|
||
|
if b.dwarf.bigEndian {
|
||
|
return uint32(a[2]) | uint32(a[1])<<8 | uint32(a[0])<<16
|
||
|
} else {
|
||
|
return uint32(a[0]) | uint32(a[1])<<8 | uint32(a[2])<<16
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (b *buf) uint32() uint32 {
|
||
|
a := b.bytes(4)
|
||
|
if a == nil {
|
||
|
return 0
|
||
|
}
|
||
|
return b.order.Uint32(a)
|
||
|
}
|
||
|
|
||
|
func (b *buf) uint64() uint64 {
|
||
|
a := b.bytes(8)
|
||
|
if a == nil {
|
||
|
return 0
|
||
|
}
|
||
|
return b.order.Uint64(a)
|
||
|
}
|
||
|
|
||
|
// Read a varint, which is 7 bits per byte, little endian.
|
||
|
// the 0x80 bit means read another byte.
|
||
|
func (b *buf) varint() (c uint64, bits uint) {
|
||
|
for i := 0; i < len(b.data); i++ {
|
||
|
byte := b.data[i]
|
||
|
c |= uint64(byte&0x7F) << bits
|
||
|
bits += 7
|
||
|
if byte&0x80 == 0 {
|
||
|
b.off += Offset(i + 1)
|
||
|
b.data = b.data[i+1:]
|
||
|
return c, bits
|
||
|
}
|
||
|
}
|
||
|
return 0, 0
|
||
|
}
|
||
|
|
||
|
// Unsigned int is just a varint.
|
||
|
func (b *buf) uint() uint64 {
|
||
|
x, _ := b.varint()
|
||
|
return x
|
||
|
}
|
||
|
|
||
|
// Signed int is a sign-extended varint.
|
||
|
func (b *buf) int() int64 {
|
||
|
ux, bits := b.varint()
|
||
|
x := int64(ux)
|
||
|
if x&(1<<(bits-1)) != 0 {
|
||
|
x |= -1 << bits
|
||
|
}
|
||
|
return x
|
||
|
}
|
||
|
|
||
|
// Address-sized uint.
|
||
|
func (b *buf) addr() uint64 {
|
||
|
switch b.format.addrsize() {
|
||
|
case 1:
|
||
|
return uint64(b.uint8())
|
||
|
case 2:
|
||
|
return uint64(b.uint16())
|
||
|
case 4:
|
||
|
return uint64(b.uint32())
|
||
|
case 8:
|
||
|
return b.uint64()
|
||
|
}
|
||
|
b.error("unknown address size")
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
func (b *buf) unitLength() (length Offset, dwarf64 bool) {
|
||
|
length = Offset(b.uint32())
|
||
|
if length == 0xffffffff {
|
||
|
dwarf64 = true
|
||
|
length = Offset(b.uint64())
|
||
|
} else if length >= 0xfffffff0 {
|
||
|
b.error("unit length has reserved value")
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func (b *buf) error(s string) {
|
||
|
if b.err == nil {
|
||
|
b.data = nil
|
||
|
b.err = DecodeError{b.name, b.off, s}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type DecodeError struct {
|
||
|
Name string
|
||
|
Offset Offset
|
||
|
Err string
|
||
|
}
|
||
|
|
||
|
func (e DecodeError) Error() string {
|
||
|
return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err
|
||
|
}
|