Index: debug/dwarf/buf.go |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/debug/dwarf/buf.go |
@@ -0,0 +1,181 @@ |
+// 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 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 |
+ Err string |
+} |
+ |
+func (e DecodeError) Error() string { |
+ return "decoding dwarf section " + e.Name + " at offset 0x" + strconv.FormatInt(int64(e.Offset), 16) + ": " + e.Err |
+} |