x/debug: Add types for representing Func and Interface values, and add an address field to Channel.

Func just contains an address for the function struct, and Interface holds no
information for now.

Fixes some comments in program.go.

For Channels, store the address of the channel struct as well as the
address of the queue buffer.

Change-Id: I5b103f0d3b049270c3a04a700f52ec3afdb47734
Reviewed-on: https://go-review.googlesource.com/15521
Reviewed-by: Dave Day <djd@golang.org>
diff --git a/ogle/demo/ogler/ogler_test.go b/ogle/demo/ogler/ogler_test.go
index baba743..7a69445 100644
--- a/ogle/demo/ogler/ogler_test.go
+++ b/ogle/demo/ogler/ogler_test.go
@@ -53,6 +53,7 @@
 	`main.Z_func_int8_r_int8`:    `func(int8, *int8) void @0xX `,
 	`main.Z_func_int8_r_pint8`:   `func(int8, **int8) void @0xX `,
 	`main.Z_func_bar`:            `func(*main.FooStruct) void @0xX `,
+	`main.Z_func_nil`:            `func(int8, *int8) void @0xX `,
 	`main.Z_int`:                 `-21`,
 	`main.Z_int16`:               `-32321`,
 	`main.Z_int32`:               `-1987654321`,
@@ -600,4 +601,26 @@
 		}
 		return nil
 	})
+
+	checkValue("main.Z_func_bar", func(val program.Value) error {
+		f, ok := val.(program.Func)
+		if !ok {
+			return fmt.Errorf("got %T(%v) expected Func", val, val)
+		}
+		if f.Address == 0 {
+			return fmt.Errorf("got func address %d expected nonzero", f.Address)
+		}
+		return nil
+	})
+
+	checkValue("main.Z_func_nil", func(val program.Value) error {
+		f, ok := val.(program.Func)
+		if !ok {
+			return fmt.Errorf("got %T(%v) expected Func", val, val)
+		}
+		if f.Address != 0 {
+			return fmt.Errorf("got func address %d expected zero", f.Address)
+		}
+		return nil
+	})
 }
diff --git a/ogle/demo/tracee/main.go b/ogle/demo/tracee/main.go
index 1ac8a8b..1293ba2 100644
--- a/ogle/demo/tracee/main.go
+++ b/ogle/demo/tracee/main.go
@@ -50,11 +50,12 @@
 	Z_channel_2           chan int16  = make(chan int16)
 	Z_channel_buffered    chan int16  = make(chan int16, 10)
 	Z_channel_nil         chan int16
-	Z_func_bar                         = (*FooStruct).Bar
-	Z_func_int8_r_int8                 = func(x int8) int8 { return x + 1 }
-	Z_func_int8_r_pint8                = func(x int8) *int8 { y := x + 1; return &y }
-	Z_interface           FooInterface = &Z_struct
-	Z_interface_typed_nil FooInterface = Z_pointer_nil
+	Z_func_bar                              = (*FooStruct).Bar
+	Z_func_int8_r_int8                      = func(x int8) int8 { return x + 1 }
+	Z_func_int8_r_pint8                     = func(x int8) *int8 { y := x + 1; return &y }
+	Z_func_nil            func(x int8) int8 = nil
+	Z_interface           FooInterface      = &Z_struct
+	Z_interface_typed_nil FooInterface      = Z_pointer_nil
 	Z_interface_nil       FooInterface
 	Z_map                 map[int8]float32 = map[int8]float32{-21: 3.54321}
 	Z_map_2               map[int16]int8   = map[int16]int8{1024: 1}
@@ -79,7 +80,7 @@
 	fmt.Println(Z_float32, Z_float64, Z_complex64, Z_complex128)
 	fmt.Println(Z_array, Z_array_empty, Z_array_of_empties)
 	fmt.Println(Z_channel, Z_channel_buffered, Z_channel_nil)
-	fmt.Println(Z_func_bar, Z_func_int8_r_int8, Z_func_int8_r_pint8)
+	fmt.Println(Z_func_bar, Z_func_int8_r_int8, Z_func_int8_r_pint8, Z_func_nil)
 	fmt.Println(Z_interface, Z_interface_nil, Z_interface_typed_nil)
 	fmt.Println(Z_map, Z_map_2, Z_map_3, Z_map_empty, Z_map_nil)
 	fmt.Println(Z_pointer, Z_pointer_nil)
diff --git a/ogle/program/program.go b/ogle/program/program.go
index b48c055..4409781 100644
--- a/ogle/program/program.go
+++ b/ogle/program/program.go
@@ -103,10 +103,15 @@
 // A value read from a remote program.
 type Value interface{}
 
-// Pointer is a Var representing a pointer.
-type Pointer Var
+// Pointer is a Value representing a pointer.
+// Note that the TypeID field will be the type of the variable being pointed to,
+// not the type of this pointer.
+type Pointer struct {
+	TypeID  uint64 // A type identifier, opaque to the user.
+	Address uint64 // The address of the variable.
+}
 
-// Array is a Var representing an array.
+// Array is a Value representing an array.
 type Array struct {
 	ElementTypeID uint64
 	Address       uint64
@@ -127,13 +132,13 @@
 	}
 }
 
-// Slice is a Var representing a slice.
+// Slice is a Value representing a slice.
 type Slice struct {
 	Array
 	Capacity uint64
 }
 
-// String is a Var representing a string.
+// String is a Value representing a string.
 // TODO: a method to access more of a truncated string.
 type String struct {
 	// Length contains the length of the remote string, in bytes.
@@ -142,14 +147,14 @@
 	String string
 }
 
-// Map is a Var representing a map.
+// Map is a Value representing a map.
 type Map struct {
 	TypeID  uint64
 	Address uint64
 	Length  uint64 // Number of elements in the map.
 }
 
-// Struct is a Var representing a struct.
+// Struct is a Value representing a struct.
 type Struct struct {
 	Fields []StructField
 }
@@ -160,10 +165,11 @@
 	Var  Var
 }
 
-// Channel is a Var representing a channel.
+// Channel is a Value representing a channel.
 type Channel struct {
 	ElementTypeID uint64
-	Buffer        uint64 // Location of the buffer; zero for nil and unbuffered channels.
+	Address       uint64 // Location of the channel struct in memory.
+	Buffer        uint64 // Location of the buffer; zero for nil channels.
 	Length        uint64 // Number of elements stored in the channel buffer.
 	Capacity      uint64 // Capacity of the buffer; zero for unbuffered channels.
 	Stride        uint64 // Number of bytes between buffer entries.
@@ -195,6 +201,14 @@
 	}
 }
 
+// Func is a Value representing a func.
+type Func struct {
+	Address uint64
+}
+
+// Interface is a Value representing an interface.
+type Interface struct{}
+
 // The File interface provides access to file-like resources in the program.
 // It implements only ReaderAt and WriterAt, not Reader and Writer, because
 // random access is a far more common pattern for things like symbol tables,
diff --git a/ogle/program/proxyrpc/proxyrpc.go b/ogle/program/proxyrpc/proxyrpc.go
index c3fac48..80031c3 100644
--- a/ogle/program/proxyrpc/proxyrpc.go
+++ b/ogle/program/proxyrpc/proxyrpc.go
@@ -13,7 +13,7 @@
 )
 
 func init() {
-	// Register implementations of program.Var with gob.
+	// Register implementations of program.Value with gob.
 	gob.Register(program.Pointer{})
 	gob.Register(program.Array{})
 	gob.Register(program.Struct{})
@@ -21,6 +21,8 @@
 	gob.Register(program.Map{})
 	gob.Register(program.String{})
 	gob.Register(program.Channel{})
+	gob.Register(program.Func{})
+	gob.Register(program.Interface{})
 }
 
 // For regularity, each method has a unique Request and a Response type even
diff --git a/ogle/program/server/value.go b/ogle/program/server/value.go
index 3532620..2b5c1c6 100644
--- a/ogle/program/server/value.go
+++ b/ogle/program/server/value.go
@@ -219,6 +219,7 @@
 			// This channel is nil.
 			return program.Channel{
 				ElementTypeID: uint64(t.ElemType.Common().Offset),
+				Address:       0,
 				Buffer:        0,
 				Length:        0,
 				Capacity:      0,
@@ -245,12 +246,21 @@
 		}
 		return program.Channel{
 			ElementTypeID: uint64(t.ElemType.Common().Offset),
+			Address:       a,
 			Buffer:        buf,
 			Length:        qcount,
 			Capacity:      capacity,
 			Stride:        uint64(t.ElemType.Common().ByteSize),
 			BufferStart:   recvx,
 		}, nil
+	case *dwarf.FuncType:
+		a, err := s.peekPtr(addr)
+		if err != nil {
+			return nil, fmt.Errorf("reading func: %s", err)
+		}
+		return program.Func{Address: a}, nil
+	case *dwarf.InterfaceType:
+		return program.Interface{}, nil
 		// TODO: more types
 	}
 	return nil, fmt.Errorf("Unsupported type %T", t)