x/debug: support changes to the internal representation of interfaces' types.

There are now typedefs in different places in the DWARF type data, and
the type name is now stored as a string instead of a *string.  This
supports both.

Change-Id: I6f963d34a0157f76a8b3d92ef998712066806c3f
Reviewed-on: https://go-review.googlesource.com/20720
Reviewed-by: Dave Day <djd@golang.org>
diff --git a/server/print.go b/server/print.go
index 927988a..e370498 100644
--- a/server/print.go
+++ b/server/print.go
@@ -274,15 +274,11 @@
 }
 
 func (p *Printer) printInterfaceAt(t *dwarf.InterfaceType, a uint64) {
-	// t should be a typedef binding a typedef binding a struct.
-	tt, ok := t.TypedefType.Type.(*dwarf.TypedefType)
+	// t embeds a TypedefType, which may point to another typedef.
+	// The underlying type should be a struct.
+	st, ok := followTypedefs(&t.TypedefType).(*dwarf.StructType)
 	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")
+		p.errorf("bad interface type: not a struct")
 		return
 	}
 	p.printf("(")
@@ -315,70 +311,71 @@
 		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)
+	// t should be a pointer to a struct containing _type, which is a pointer to a
+	// struct containing _string, which is the name of the type.
+	// Depending on the compiler version, some of these types can be typedefs, and
+	// _string may be a string or a *string.
+	t1, ok := followTypedefs(t).(*dwarf.PtrType)
 	if !ok {
-		p.errorf("bad type")
+		p.errorf("interface's tab is not a pointer")
 		return
 	}
-	t2, ok := t1.Type.(*dwarf.TypedefType)
+	t2, ok := followTypedefs(t1.Type).(*dwarf.StructType)
 	if !ok {
-		p.errorf("bad type")
+		p.errorf("interface's tab is not a pointer to struct")
 		return
 	}
-	t3, ok := t2.Type.(*dwarf.StructType)
-	if !ok {
-		p.errorf("bad type")
-		return
-	}
-	typeField, err := getField(t3, "_type")
+	typeField, err := getField(t2, "_type")
 	if err != nil {
 		p.errorf("%s", err)
 		return
 	}
-	t4, ok := typeField.Type.(*dwarf.PtrType)
+	t3, ok := followTypedefs(typeField.Type).(*dwarf.PtrType)
 	if !ok {
-		p.errorf("bad type")
+		p.errorf("interface's _type is not a pointer")
 		return
 	}
-	t5, ok := t4.Type.(*dwarf.TypedefType)
+	t4, ok := followTypedefs(t3.Type).(*dwarf.StructType)
 	if !ok {
-		p.errorf("bad type")
+		p.errorf("interface's _type is not a pointer to struct")
 		return
 	}
-	t6, ok := t5.Type.(*dwarf.StructType)
-	if !ok {
-		p.errorf("bad type")
-		return
-	}
-	stringField, err := getField(t6, "_string")
+	stringField, err := getField(t4, "_string")
 	if err != nil {
 		p.errorf("%s", err)
 		return
 	}
-	t7, ok := stringField.Type.(*dwarf.PtrType)
-	if !ok {
-		p.errorf("bad type")
-		return
+	if t5, ok := stringField.Type.(*dwarf.PtrType); ok {
+		stringType, ok := t5.Type.(*dwarf.StringType)
+		if !ok {
+			p.errorf("interface _string is a pointer to %T, want string or *string", t5.Type)
+			return
+		}
+		typeAddr, err := p.server.peekPtrStructField(t2, a, "_type")
+		if err != nil {
+			p.errorf("reading interface type: %s", err)
+			return
+		}
+		stringAddr, err := p.server.peekPtrStructField(t4, typeAddr, "_string")
+		if err != nil {
+			p.errorf("reading interface type: %s", err)
+			return
+		}
+		p.printStringAt(stringType, stringAddr)
+	} else {
+		stringType, ok := stringField.Type.(*dwarf.StringType)
+		if !ok {
+			p.errorf("interface _string is a %T, want string or *string", stringField.Type)
+			return
+		}
+		typeAddr, err := p.server.peekPtrStructField(t2, a, "_type")
+		if err != nil {
+			p.errorf("reading interface type: %s", err)
+			return
+		}
+		stringAddr := typeAddr + uint64(stringField.ByteOffset)
+		p.printStringAt(stringType, stringAddr)
 	}
-	stringType, ok := t7.Type.(*dwarf.StringType)
-	if !ok {
-		p.errorf("bad type")
-		return
-	}
-	typeAddr, err := p.server.peekPtrStructField(t3, a, "_type")
-	if err != nil {
-		p.errorf("reading interface type: %s", err)
-		return
-	}
-	stringAddr, err := p.server.peekPtrStructField(t6, typeAddr, "_string")
-	if err != nil {
-		p.errorf("reading interface type: %s", err)
-		return
-	}
-	p.printStringAt(stringType, stringAddr)
 }
 
 // maxMapValuesToPrint values are printed for each map; any remaining values are