summaryrefslogtreecommitdiff
path: root/usr/austin/sym/binary.go
diff options
context:
space:
mode:
authorAustin Clements <aclements@csail.mit.edu>2009-08-19 10:05:11 -0700
committerAustin Clements <aclements@csail.mit.edu>2009-08-19 10:05:11 -0700
commit68c5968a7dc814a3f0ddd0af4235a47857981983 (patch)
tree213b3794503aab8d5e52cf0799fb309d995470c8 /usr/austin/sym/binary.go
parentc96a8d488643318109f2e6f418cbc6d7d29b67e1 (diff)
downloadgolang-68c5968a7dc814a3f0ddd0af4235a47857981983.tar.gz
ELF reader and Go symbol table and PC/line table decoder.
R=rsc APPROVED=rsc DELTA=1425 (1425 added, 0 deleted, 0 changed) OCL=33432 CL=33517
Diffstat (limited to 'usr/austin/sym/binary.go')
-rw-r--r--usr/austin/sym/binary.go190
1 files changed, 190 insertions, 0 deletions
diff --git a/usr/austin/sym/binary.go b/usr/austin/sym/binary.go
new file mode 100644
index 000000000..d06179cec
--- /dev/null
+++ b/usr/austin/sym/binary.go
@@ -0,0 +1,190 @@
+// 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.
+
+package sym
+
+import (
+ "bufio";
+ "io";
+ "log";
+ "os";
+ "reflect";
+)
+
+type byteOrder interface {
+ Uint16(b []byte) uint16;
+ Uint32(b []byte) uint32;
+ Uint64(b []byte) uint64;
+ String() string;
+}
+
+type olsb struct {}
+
+func (olsb) Uint16(b []byte) uint16 {
+ return uint16(b[0]) | uint16(b[1]) << 8;
+}
+
+func (olsb) Uint32(b []byte) uint32 {
+ return uint32(b[0]) | uint32(b[1]) << 8 | uint32(b[2]) << 16 | uint32(b[3]) << 24;
+}
+
+func (olsb) Uint64(b []byte) uint64 {
+ return uint64(b[0]) | uint64(b[1]) << 8 | uint64(b[2]) << 16 | uint64(b[3]) << 24 | uint64(b[4]) << 32 | uint64(b[5]) << 40 | uint64(b[6]) << 48 | uint64(b[7]) << 56;
+}
+
+func (olsb) String() string {
+ return "LSB";
+}
+
+type omsb struct {}
+
+func (omsb) Uint16(b []byte) uint16 {
+ return uint16(b[1]) | uint16(b[0]) << 8;
+}
+
+func (omsb) Uint32(b []byte) uint32 {
+ return uint32(b[3]) | uint32(b[2]) << 8 | uint32(b[1]) << 16 | uint32(b[0]) << 24;
+}
+
+func (omsb) Uint64(b []byte) uint64 {
+ return uint64(b[7]) | uint64(b[6]) << 8 | uint64(b[5]) << 16 | uint64(b[4]) << 24 | uint64(b[3]) << 32 | uint64(b[2]) << 40 | uint64(b[1]) << 48 | uint64(b[0]) << 56;
+}
+
+func (omsb) String() string {
+ return "MSB";
+}
+
+var (
+ lsb = olsb{};
+ msb = omsb{};
+)
+
+// A binaryReader decodes binary data from another reader. On an
+// error, the Read methods simply return 0 and record the error, to
+// make it more convenient to decode long sequences of binary data.
+// The caller should use the Error method when convenient to check
+// for errors.
+type binaryReader struct {
+ *bufio.Reader;
+ err os.Error;
+ order byteOrder;
+}
+
+// newBinaryReader creates a new binary data reader backed by the
+// given reader and using the given byte order for decoding.
+func newBinaryReader(r io.Reader, o byteOrder) *binaryReader {
+ return &binaryReader{bufio.NewReader(r), nil, o};
+}
+
+// Error returns the recorded error, or nil if no error has occurred.
+func (r *binaryReader) Error() os.Error {
+ return r.err;
+}
+
+func (r *binaryReader) ReadUint8() uint8 {
+ var buf [1]byte;
+ n, err := io.ReadFull(r.Reader, &buf);
+ if r.err == nil && err != nil {
+ r.err = err;
+ }
+ return buf[0];
+}
+
+func (r *binaryReader) ReadUint16() uint16 {
+ var buf [2]byte;
+ n, err := io.ReadFull(r.Reader, &buf);
+ if r.err == nil && err != nil {
+ r.err = err;
+ }
+ return r.order.Uint16(&buf);
+}
+
+func (r *binaryReader) ReadUint32() uint32 {
+ var buf [4]byte;
+ n, err := io.ReadFull(r.Reader, &buf);
+ if r.err == nil && err != nil {
+ r.err = err;
+ }
+ return r.order.Uint32(&buf);
+}
+
+func (r *binaryReader) ReadUint64() uint64 {
+ var buf [8]byte;
+ n, err := io.ReadFull(r.Reader, &buf);
+ if r.err == nil && err != nil {
+ r.err = err;
+ }
+ return r.order.Uint64(&buf);
+}
+
+func (r *binaryReader) ReadInt8() int8 {
+ return int8(r.ReadUint8());
+}
+
+func (r *binaryReader) ReadInt16() int16 {
+ return int16(r.ReadUint16());
+}
+
+func (r *binaryReader) ReadInt32() int32 {
+ return int32(r.ReadUint32());
+}
+
+func (r *binaryReader) ReadInt64() int64 {
+ return int64(r.ReadUint64());
+}
+
+// ReadCString reads a NULL-terminated string.
+func (r *binaryReader) ReadCString() string {
+ str, err := r.Reader.ReadLineString('\x00', false);
+ if r.err == nil && err != nil {
+ r.err = err;
+ }
+ return str;
+}
+
+// ReadValue reads a value according to its reflected type. This can
+// read any of the types for which there is a regular Read method,
+// plus structs and arrays. It assumes structs contain no padding.
+func (r *binaryReader) ReadValue(v reflect.Value) {
+ switch v := v.(type) {
+ case *reflect.ArrayValue:
+ l := v.Len();
+ for i := 0; i < l; i++ {
+ r.ReadValue(v.Elem(i));
+ }
+ case *reflect.StructValue:
+ l := v.NumField();
+ for i := 0; i < l; i++ {
+ r.ReadValue(v.Field(i));
+ }
+
+ case *reflect.Uint8Value:
+ v.Set(r.ReadUint8());
+ case *reflect.Uint16Value:
+ v.Set(r.ReadUint16());
+ case *reflect.Uint32Value:
+ v.Set(r.ReadUint32());
+ case *reflect.Uint64Value:
+ v.Set(r.ReadUint64());
+ case *reflect.Int8Value:
+ v.Set(r.ReadInt8());
+ case *reflect.Int16Value:
+ v.Set(r.ReadInt16());
+ case *reflect.Int32Value:
+ v.Set(r.ReadInt32());
+ case *reflect.Int64Value:
+ v.Set(r.ReadInt64());
+ case *reflect.StringValue:
+ v.Set(r.ReadCString());
+
+ default:
+ log.Crashf("Value of unexpected type %T", v);
+ }
+}
+
+// ReadAny is a convenience wrapper for ReadValue. It can be passed a
+// pointer any type that can be decoded by ReadValue.
+func (r *binaryReader) ReadAny(out interface {}) {
+ r.ReadValue(reflect.Indirect(reflect.NewValue(out)));
+}