...
Run Format

Source file src/debug/dwarf/buf.go

Documentation: debug/dwarf

  // 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"
  	"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 {
  	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.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
  }
  

View as plain text