// 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 ( "encoding/binary" "os" "strconv" ) // Data buffer being decoded. type buf struct { dwarf *Data order binary.ByteOrder name string off Offset data []byte addrsize int err os.Error } func makeBuf(d *Data, name string, off Offset, data []byte, addrsize int) buf { return buf{d, d.order, name, off, data, addrsize, 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 { for i := 0; i < len(b.data); i++ { if b.data[i] == 0 { s := string(b.data[0:i]) b.data = b.data[i+1:] b.off += Offset(i + 1) return s } } b.error("underflow") return "" } func (b *buf) uint16() uint16 { a := b.bytes(2) if a == nil { return 0 } return b.order.Uint16(a) } 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.addrsize { case 1: return uint64(b.uint8()) case 2: return uint64(b.uint16()) case 4: return uint64(b.uint32()) case 8: return uint64(b.uint64()) } b.error("unknown address size") return 0 } 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 Error string } func (e DecodeError) String() string { return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.Itob64(int64(e.Offset), 16) + ": " + e.Error }