func (v Value) WriteScalar(x interface{}) {
	a := v.Type.Program().RuntimeLibrary.Arch
	switch t := v.Type.(type) {
	case *NumericType:
		switch t.Kind {
		case NumericBool:
			if x.(bool) {
				v.Bytes[0] = 1
			} else {
				v.Bytes[0] = 0
			}
		case NumericUint8, NumericInt8:
			v.Bytes[0] = byte(uint8(reflect.ValueOf(x).Uint()))
		case NumericUint16, NumericInt16:
			a.ByteOrder.PutUint16(v.Bytes, uint16(reflect.ValueOf(x).Uint()))
		case NumericUint32, NumericInt32:
			a.ByteOrder.PutUint32(v.Bytes, uint32(reflect.ValueOf(x).Uint()))
		case NumericUint64, NumericInt64:
			a.ByteOrder.PutUint64(v.Bytes, uint64(reflect.ValueOf(x).Uint()))
		case NumericFloat32:
			a.FloatByteOrder.PutUint32(v.Bytes, math.Float32bits(float32(reflect.ValueOf(x).Float())))
		case NumericFloat64:
			a.FloatByteOrder.PutUint64(v.Bytes, math.Float64bits(float64(reflect.ValueOf(x).Float())))
		case NumericComplex64:
			c := reflect.ValueOf(x).Complex()
			a.FloatByteOrder.PutUint32(v.Bytes[0:4], math.Float32bits(float32(real(c))))
			a.FloatByteOrder.PutUint32(v.Bytes[4:8], math.Float32bits(float32(imag(c))))
		case NumericComplex128:
			c := reflect.ValueOf(x).Complex()
			a.FloatByteOrder.PutUint64(v.Bytes[0:8], math.Float64bits(float64(real(c))))
			a.FloatByteOrder.PutUint64(v.Bytes[8:16], math.Float64bits(float64(imag(c))))
		}
	case *PtrType, *UnsafePtrType:
		switch a.PointerSize {
		case 4:
			a.ByteOrder.PutUint32(v.Bytes, uint32(reflect.ValueOf(x).Uint()))
		case 8:
			a.ByteOrder.PutUint64(v.Bytes, uint64(reflect.ValueOf(x).Uint()))
		default:
			panic(fmt.Sprintf("unexpected PointerSize %v", a.PointerSize))
		}
	default:
		panic(fmt.Sprintf("bad type for Value.WriteScalar(): %s (%T)", t, t))
	}
}
WriteScalar overwrites v. WriteScalar is the inverse of ReadScalar.
If the core file was opened in writable mode, then this write will be reflected
in the core file. Otherwise, this write may segfault. WriteScalar panics if v
has a non-scalar type or if the type of x is not compatible with v.Type.
package corefile
import (
	"errors"
	"fmt"
	"math"
	"reflect"
)
var (
	ErrNil         = errors.New("nil pointer")
	ErrOutOfBounds = errors.New("access is out-of-bounds")
)
type Value struct {
	Type  Type
	Addr  uint64  
	Bytes []byte  
}
func (v Value) IsZero() bool {
	for _, b := range v.Bytes {
		if b != 0 {
			return false
		}
	}
	return true
}
func (v Value) Size() uint64 {
	return v.Type.Size()
}
func (v Value) ContainsAddress(addr uint64) bool {
	return v.Addr <= addr && addr < v.Addr+v.Type.Size()
}
func (v Value) Deref() (Value, error) {
	switch t := v.Type.(type) {
	case *PtrType:
		return v.Type.Program().Value(v.ReadScalar().(uint64), t.Elem)
	case *InterfaceType:
		if v.IsZero() {
			return Value{}, ErrNil
		}
		elemType, err := v.DynamicType()
		if err != nil {
			return Value{}, err
		}
		datafield := ifaceDataField
		if t.EFace {
			datafield = efaceDataField
		}
		v.Type = t.Rep
		if elemType.directIface() {
			data, err := v.Field(t.Rep.Fields[datafield])
			if err != nil {
				return Value{}, err
			}
			data.Type = elemType
			return data, nil
		} else {
			dataptr, err := v.Field(t.Rep.Fields[datafield])
			if err != nil {
				return Value{}, err
			}
			dataptr.Type = v.Type.Program().MakePtrType(elemType)
			return dataptr.Deref()
		}
	default:
		panic(fmt.Sprintf("bad type for Value.Deref(): %s (%T)", v.Type, v.Type))
	}
}
func (v Value) DynamicType() (Type, error) {
	t, ok := v.Type.(*InterfaceType)
	if !ok {
		return v.Type, nil
	}
	rep := t.Rep
	if t.EFace {
		v.Type = rep
		rtypePtr, err := v.Field(rep.Fields[efaceTypeField])
		if err != nil {
			return nil, err
		}
		return rep.Program().typeCache.convertRuntimeType(rtypePtr)
	} else {
		v.Type = rep
		itabPtr, err := v.Field(rep.Fields[ifaceTabField])
		if err != nil {
			return nil, err
		}
		return rep.Program().typeCache.convertRuntimeItab(itabPtr)
	}
}
func (v Value) typedSlice(offset uint64, t Type) (Value, error) {
	end := offset + t.Size()
	if end > v.Type.Size() {
		return Value{}, ErrOutOfBounds
	}
	return Value{
		Addr:  v.Addr + offset,
		Type:  t,
		Bytes: v.Bytes[offset:end:end],
	}, nil
}
func (v Value) Field(f StructField) (Value, error) {
	if _, ok := v.Type.(*StructType); !ok {
		panic(fmt.Sprintf("bad type for Value.Field(): %s (%T)", v.Type, v.Type))
	}
	v, err := v.typedSlice(f.Offset, f.Type)
	if err != nil {
		return Value{}, fmt.Errorf("error reading field %s.%s, type %s: %v", v.Type, f.Name, f.Type, err)
	}
	return v, nil
}
func (v Value) FieldByName(name string) (Value, error) {
	st, ok := v.Type.(*StructType)
	if !ok {
		panic(fmt.Sprintf("bad type for Value.FieldByName(): %s (%T)", v.Type, v.Type))
	}
	f, ok := st.FieldByName(name)
	if !ok {
		return Value{}, fmt.Errorf("cannot find field %s in %s", name, st)
	}
	return v.Field(f)
}
func (v Value) DerefArray() (Value, error) {
	vcap, err := v.Cap()
	if err != nil {
		return Value{}, err
	}
	p := v.Type.Program()
	var f StructField
	switch t := v.Type.(type) {
	case *SliceType:
		f = t.Rep.Fields[sliceArrayField]
		f.Type = p.MakePtrType(p.MakeArrayType(t.Elem, vcap))
		v.Type = t.Rep
	case *StringType:
		f = t.Rep.Fields[stringArrayField]
		f.Type = p.MakePtrType(p.MakeArrayType(p.MakeNumericType(NumericUint8), vcap))
		v.Type = t.Rep
	case *ChanType:
		v.Type = t.Rep
		v, err = v.Deref()
		if err != nil {
			return Value{}, err
		}
		f = v.Type.(*StructType).Fields[chanBufferField]
		f.Type = p.MakePtrType(p.MakeArrayType(t.Elem, vcap))
	default:
		panic(fmt.Sprintf("bad type for Value.DerefArray(): %s (%T)", v.Type, v.Type))
	}
	fv, err := v.Field(f)
	if err != nil {
		return Value{}, err
	}
	return fv.Deref()
}
func (v Value) Index(n uint64) (Value, error) {
	vcap, err := v.Cap()
	if err != nil {
		return Value{}, err
	}
	if n >= vcap {
		return Value{}, ErrOutOfBounds
	}
	var addrf StructField
	var elem Type
	switch t := v.Type.(type) {
	case *ArrayType:
		return v.typedSlice(n*t.Elem.Size(), t.Elem)
	case *SliceType:
		v.Type = t.Rep
		addrf = t.Rep.Fields[sliceArrayField]
		elem = t.Elem
	case *StringType:
		v.Type = t.Rep
		addrf = t.Rep.Fields[stringArrayField]
		elem = t.Program().MakeNumericType(NumericUint8)
	case *ChanType:
		v.Type = t.Rep
		v, err := v.Deref()
		if err != nil {
			return Value{}, err
		}
		addrf = v.Type.(*StructType).Fields[chanBufferField]
		elem = t.Elem
	default:
		panic(fmt.Sprintf("bad type for Value.Len(): %s (%T)", v.Type, v.Type))
	}
	addr, err := v.ReadUintField(addrf)
	if err != nil {
		return Value{}, err
	}
	if addr == 0 {
		return Value{}, ErrNil
	}
	return v.Type.Program().Value(addr+n*elem.Size(), elem)
}
func (v Value) Len() (uint64, error) {
	switch t := v.Type.(type) {
	case *ArrayType:
		return t.Len, nil
	case *SliceType:
		v.Type = t.Rep
		return v.ReadUintField(t.Rep.Fields[sliceLenField])
	case *StringType:
		v.Type = t.Rep
		return v.ReadUintField(t.Rep.Fields[stringLenField])
	case *ChanType:
		v.Type = t.Rep
		v, err := v.Deref()
		if err != nil {
			return 0, err
		}
		return v.ReadUintField(v.Type.(*StructType).Fields[chanLenField])
	case *MapType:
		v.Type = t.Rep
		v, err := v.Deref()
		if err != nil {
			return 0, err
		}
		return v.ReadUintField(v.Type.(*StructType).Fields[mapLenField])
	default:
		panic(fmt.Sprintf("bad type for Value.Len(): %s (%T)", v.Type, v.Type))
	}
}
func (v Value) Cap() (uint64, error) {
	switch t := v.Type.(type) {
	case *ArrayType:
		return t.Len, nil
	case *SliceType:
		v.Type = t.Rep
		return v.ReadUintField(t.Rep.Fields[sliceCapField])
	case *StringType:
		v.Type = t.Rep
		return v.ReadUintField(t.Rep.Fields[stringLenField])
	case *ChanType:
		v.Type = t.Rep
		v, err := v.Deref()
		if err != nil {
			return 0, err
		}
		return v.ReadUintField(v.Type.(*StructType).Fields[chanCapField])
	default:
		panic(fmt.Sprintf("bad type for Value.Cap(): %s (%T)", v.Type, v.Type))
	}
}
func (v Value) ReadScalar() interface{} {
	a := v.Type.Program().RuntimeLibrary.Arch
	switch t := v.Type.(type) {
	case *NumericType:
		switch t.Kind {
		case NumericBool:
			return v.Bytes[0] != 0
		case NumericUint8:
			return uint8(v.Bytes[0])
		case NumericUint16:
			return a.Uint16(v.Bytes)
		case NumericUint32:
			return a.Uint32(v.Bytes)
		case NumericUint64:
			return a.Uint64(v.Bytes)
		case NumericInt8:
			return int8(v.Bytes[0])
		case NumericInt16:
			return a.Int16(v.Bytes)
		case NumericInt32:
			return a.Int32(v.Bytes)
		case NumericInt64:
			return a.Int64(v.Bytes)
		case NumericFloat32:
			return a.Float32(v.Bytes)
		case NumericFloat64:
			return a.Float64(v.Bytes)
		case NumericComplex64:
			return a.Complex64(v.Bytes)
		case NumericComplex128:
			return a.Complex128(v.Bytes)
		}
		panic(fmt.Sprintf("bad numeric type for Value.ReadScalar(): %s (%T)", t, t))
	case *PtrType, *UnsafePtrType:
		return a.Uintptr(v.Bytes)
	default:
		panic(fmt.Sprintf("bad type for Value.ReadScalar(): %s (%T)", t, t))
	}
}
func (v Value) ReadUint() uint64 {
	a := v.Type.Program().RuntimeLibrary.Arch
	switch t := v.Type.(type) {
	case *NumericType:
		switch t.Kind {
		case NumericUint8:
			return uint64(v.Bytes[0])
		case NumericUint16, NumericInt16:
			return uint64(a.Uint16(v.Bytes))
		case NumericUint32, NumericInt32:
			return uint64(a.Uint32(v.Bytes))
		case NumericUint64, NumericInt64:
			return uint64(a.Uint64(v.Bytes))
		}
	case *PtrType, *UnsafePtrType:
		return a.Uintptr(v.Bytes)
	}
	panic(fmt.Sprintf("bad type for Value.ReadUint(): %s (%T)", v.Type, v.Type))
}
func (v Value) ReadScalarField(f StructField) (interface{}, error) {
	fv, err := v.Field(f)
	if err != nil {
		return nil, err
	}
	return fv.ReadScalar(), nil
}
func (v Value) ReadUintField(f StructField) (uint64, error) {
	fv, err := v.Field(f)
	if err != nil {
		return 0, err
	}
	return fv.ReadUint(), nil
}
func (v Value) ReadScalarFieldByName(name string) (interface{}, error) {
	fv, err := v.FieldByName(name)
	if err != nil {
		return nil, err
	}
	return fv.ReadScalar(), nil
}
func (v Value) ReadUintFieldByName(name string) (uint64, error) {
	fv, err := v.FieldByName(name)
	if err != nil {
		return 0, err
	}
	return fv.ReadUint(), nil
}