debug: print interfaces.  Add InterfaceType to DWARF parser.

Change-Id: I9d5943463bea905c7ce11e5d91acd9f74b3b031f
Reviewed-on: https://go-review.googlesource.com/2791
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/dwarf/type.go b/dwarf/type.go
index 4f58b74..d61cfa9 100644
--- a/dwarf/type.go
+++ b/dwarf/type.go
@@ -217,6 +217,18 @@
 	return "string"
 }
 
+// An InterfaceType represents a Go interface.
+type InterfaceType struct {
+	TypedefType
+}
+
+func (t *InterfaceType) String() string {
+	if t.Name != "" {
+		return t.Name
+	}
+	return "Interface"
+}
+
 // An EnumType represents an enumerated type.
 // The only indication of its native integer type is its ByteSize
 // (inside CommonType).
@@ -743,6 +755,10 @@
 			c.ElemType = typeOf(e, AttrGoElem)
 			t = &c.TypedefType
 			typ = c
+		case reflect.Interface:
+			it := new(InterfaceType)
+			t = &it.TypedefType
+			typ = it
 		default:
 			typ = t
 		}
diff --git a/ogle/demo/ogler/ogler_test.go b/ogle/demo/ogler/ogler_test.go
index 9b02f96..65483ee 100644
--- a/ogle/demo/ogler/ogler_test.go
+++ b/ogle/demo/ogler/ogler_test.go
@@ -38,9 +38,9 @@
 	`main.Z_int32`:               `-1987654321`,
 	`main.Z_int64`:               `-9012345678987654321`,
 	`main.Z_int8`:                `-121`,
-	`main.Z_interface`:           `struct runtime.iface {0xX, 0xX}`,
-	`main.Z_interface_nil`:       `struct runtime.iface {0x0, 0x0}`,
-	`main.Z_interface_typed_nil`: `struct runtime.iface {0xX, 0x0}`,
+	`main.Z_interface`:           `("*main.FooStruct", 0xX)`,
+	`main.Z_interface_nil`:       `(<nil>, <nil>)`,
+	`main.Z_interface_typed_nil`: `("*main.FooStruct", <nil>)`,
 	`main.Z_map`:                 `{-21:3.54321}`,
 	`main.Z_map_2`:               `{1024:1}`,
 	`main.Z_map_empty`:           `{}`,
diff --git a/ogle/program/server/print.go b/ogle/program/server/print.go
index 8d93b3a..4b9c3c7 100644
--- a/ogle/program/server/print.go
+++ b/ogle/program/server/print.go
@@ -327,6 +327,8 @@
 		p.printf("}")
 	case *dwarf.ArrayType:
 		p.printArrayAt(typ, a)
+	case *dwarf.InterfaceType:
+		p.printInterfaceAt(typ, a)
 	case *dwarf.MapType:
 		p.printMapAt(typ, a)
 	case *dwarf.ChanType:
@@ -342,7 +344,6 @@
 	case *dwarf.VoidType:
 		p.printf("void")
 	default:
-		// TODO: interface
 		p.errorf("unimplemented type %v", typ)
 	}
 }
@@ -372,6 +373,114 @@
 	p.printf("}")
 }
 
+func (p *Printer) printInterfaceAt(t *dwarf.InterfaceType, a address) {
+	// t should be a typedef binding a typedef binding a struct.
+	tt, ok := t.TypedefType.Type.(*dwarf.TypedefType)
+	if !ok {
+		p.errorf("bad interface type: not a typedef")
+		return
+	}
+	st, ok := tt.Type.(*dwarf.StructType)
+	if !ok {
+		p.errorf("bad interface type: not a typedef of a struct")
+		return
+	}
+	p.printf("(")
+	tab, ok := p.peekPtrStructField(st, a, "tab")
+	if ok {
+		f, err := getField(st, "tab")
+		if err != nil {
+			p.errorf("%s", err)
+		} else {
+			p.printTypeOfInterface(f.Type, tab)
+		}
+	} else {
+		p.errorf("couldn't read interface type")
+	}
+	p.printf(", ")
+	data, ok := p.peekPtrStructField(st, a, "data")
+	if !ok {
+		p.errorf("couldn't read interface value")
+	} else if data == 0 {
+		p.printf("<nil>")
+	} else {
+		p.printf("%#x", data)
+	}
+	p.printf(")")
+}
+
+// printTypeOfInterface prints the type of the given tab pointer.
+func (p *Printer) printTypeOfInterface(t dwarf.Type, a address) {
+	if a == 0 {
+		p.printf("<nil>")
+		return
+	}
+	// t should be a pointer to a typedef binding a struct which contains a field _type.
+	// _type should be a pointer to a typedef binding a struct which contains a field _string.
+	// _string is the name of the type.
+	t1, ok := t.(*dwarf.PtrType)
+	if !ok {
+		p.errorf("bad type")
+		return
+	}
+	t2, ok := t1.Type.(*dwarf.TypedefType)
+	if !ok {
+		p.errorf("bad type")
+		return
+	}
+	t3, ok := t2.Type.(*dwarf.StructType)
+	if !ok {
+		p.errorf("bad type")
+		return
+	}
+	typeField, err := getField(t3, "_type")
+	if err != nil {
+		p.errorf("%s", err)
+		return
+	}
+	t4, ok := typeField.Type.(*dwarf.PtrType)
+	if !ok {
+		p.errorf("bad type")
+		return
+	}
+	t5, ok := t4.Type.(*dwarf.TypedefType)
+	if !ok {
+		p.errorf("bad type")
+		return
+	}
+	t6, ok := t5.Type.(*dwarf.StructType)
+	if !ok {
+		p.errorf("bad type")
+		return
+	}
+	stringField, err := getField(t6, "_string")
+	if err != nil {
+		p.errorf("%s", err)
+		return
+	}
+	t7, ok := stringField.Type.(*dwarf.PtrType)
+	if !ok {
+		p.errorf("bad type")
+		return
+	}
+	stringType, ok := t7.Type.(*dwarf.StringType)
+	if !ok {
+		p.errorf("bad type")
+		return
+	}
+	typeAddr, ok := p.peekPtrStructField(t3, a, "_type")
+	if !ok {
+		p.errorf("couldn't read type structure pointer")
+		return
+	}
+	stringAddr, ok := p.peekPtrStructField(t6, typeAddr, "_string")
+	if !ok {
+		p.errorf("couldn't read type name")
+		return
+	}
+	p.printStringAt(stringType, stringAddr)
+}
+
 // maxMapValuesToPrint values are printed for each map; any remaining values are
 // truncated to "...".
 const maxMapValuesToPrint = 8