func (p *Process) readDWARFTypes() {
	d, _ := p.proc.DWARF()

	// Make one of our own Types for each dwarf type.
	r := d.Reader()
	var types []*Type
	for e, err := r.Next(); e != nil && err == nil; e, err = r.Next() {
		if isNonGoCU(e) {
			r.SkipChildren()
			continue
		}
		switch e.Tag {
		case dwarf.TagArrayType, dwarf.TagPointerType, dwarf.TagStructType, dwarf.TagBaseType, dwarf.TagSubroutineType, dwarf.TagTypedef:
			dt, err := d.Type(e.Offset)
			if err != nil {
				continue
			}
			t := &Type{Name: gocoreName(dt), Size: dwarfSize(dt, p.proc.PtrSize())}
			p.dwarfMap[dt] = t
			types = append(types, t)
		}
	}

	p.runtimeNameMap = map[string][]*Type{}

	// Fill in fields of types. Postponed until now so we're sure
	// we have all the Types allocated and available.
	for dt, t := range p.dwarfMap {
		switch x := dt.(type) {
		case *dwarf.ArrayType:
			t.Kind = KindArray
			t.Elem = p.dwarfMap[x.Type]
			t.Count = x.Count
		case *dwarf.PtrType:
			t.Kind = KindPtr
			// unsafe.Pointer has a void base type.
			if _, ok := x.Type.(*dwarf.VoidType); !ok {
				t.Elem = p.dwarfMap[x.Type]
			}
		case *dwarf.StructType:
			t.Kind = KindStruct
			for _, f := range x.Field {
				fType := p.dwarfMap[f.Type]

				// Work around issue 21094. There's no guarantee that the
				// pointer type is in the DWARF, so just invent a Type.
				if strings.HasPrefix(t.Name, "sudog<") && f.Name == "elem" &&
					strings.Count(t.Name, "*")+1 != strings.Count(gocoreName(f.Type), "*") {
					ptrName := "*" + gocoreName(f.Type)
					fType = &Type{Name: ptrName, Kind: KindPtr, Size: p.proc.PtrSize(), Elem: fType}
					p.runtimeNameMap[ptrName] = []*Type{fType}
				}

				t.Fields = append(t.Fields, Field{Name: f.Name, Type: fType, Off: f.ByteOffset})
			}
		case *dwarf.BoolType:
			t.Kind = KindBool
		case *dwarf.IntType:
			t.Kind = KindInt
		case *dwarf.UintType:
			t.Kind = KindUint
		case *dwarf.FloatType:
			t.Kind = KindFloat
		case *dwarf.ComplexType:
			t.Kind = KindComplex
		case *dwarf.FuncType:
			t.Kind = KindFunc
		case *dwarf.TypedefType:
			// handle these types in the loop below
		default:
			panic(fmt.Sprintf("unknown type %s %T", dt, dt))
		}
	}

	// Detect strings & slices
	for _, t := range types {
		if t.Kind != KindStruct {
			continue
		}
		if t.Name == "string" { // TODO: also "struct runtime.stringStructDWARF" ?
			t.Kind = KindString
			t.Elem = t.Fields[0].Type.Elem // TODO: check that it is always uint8.
			t.Fields = nil
		}
		if len(t.Name) >= 9 && t.Name[:9] == "struct []" ||
			len(t.Name) >= 2 && t.Name[:2] == "[]" {
			t.Kind = KindSlice
			t.Elem = t.Fields[0].Type.Elem
			t.Fields = nil
		}
	}

	// Copy info from base types into typedefs.
	for dt, t := range p.dwarfMap {
		tt, ok := dt.(*dwarf.TypedefType)
		if !ok {
			continue
		}
		base := tt.Type
		// Walk typedef chain until we reach a non-typedef type.
		for {
			if x, ok := base.(*dwarf.TypedefType); ok {
				base = x.Type
				continue
			}
			break
		}
		bt := p.dwarfMap[base]

		// Copy type info from base. Everything except the name.
		name := t.Name
		*t = *bt
		t.Name = name

		// Detect some special types. If the base is some particular type,
		// then the alias gets marked as special.
		// We have aliases like:
		//   interface {}              -> struct runtime.eface
		//   error                     -> struct runtime.iface
		// Note: the base itself does not get marked as special.
		// (Unlike strings and slices, where they do.)
		if bt.Name == "runtime.eface" {
			t.Kind = KindEface
			t.Fields = nil
		}
		if bt.Name == "runtime.iface" {
			t.Kind = KindIface
			t.Fields = nil
		}
	}

	// Make a runtime name -> Type map for existing DWARF types.
	for dt, t := range p.dwarfMap {
		name := runtimeName(dt)
		p.runtimeNameMap[name] = append(p.runtimeNameMap[name], t)
	}

	// Construct the runtime.specialfinalizer type.  It won't be found
	// in DWARF before 1.10 because it does not appear in the type of any variable.
	// type specialfinalizer struct {
	//      special special
	//      fn      *funcval
	//      nret    uintptr
	//      fint    *_type
	//      ot      *ptrtype
	// }
	if p.runtimeNameMap["runtime.specialfinalizer"] == nil {
		special := p.findType("runtime.special")
		p.runtimeNameMap["runtime.specialfinalizer"] = []*Type{
			&Type{
				Name: "runtime.specialfinalizer",
				Size: special.Size + 4*p.proc.PtrSize(),
				Kind: KindStruct,
				Fields: []Field{
					Field{
						Name: "special",
						Off:  0,
						Type: special,
					},
					Field{
						Name: "fn",
						Off:  special.Size,
						Type: p.findType("*runtime.funcval"),
					},
					Field{
						Name: "nret",
						Off:  special.Size + p.proc.PtrSize(),
						Type: p.findType("uintptr"),
					},
					Field{
						Name: "fint",
						Off:  special.Size + 2*p.proc.PtrSize(),
						Type: p.findType("*runtime._type"),
					},
					Field{
						Name: "fn",
						Off:  special.Size + 3*p.proc.PtrSize(),
						Type: p.findType("*runtime.ptrtype"),
					},
				},
			},
		}
	}
}
func (p *Process) readDWARFTypes() {
	d, _ := p.proc.DWARF()

	
	r := d.Reader()
	var types []*Type
	for e, err := r.Next(); e != nil && err == nil; e, err = r.Next() {
		if isNonGoCU(e) {
			r.SkipChildren()
			continue
		}
		switch e.Tag {
		case dwarf.TagArrayType, dwarf.TagPointerType, dwarf.TagStructType, dwarf.TagBaseType, dwarf.TagSubroutineType, dwarf.TagTypedef:
			dt, err := d.Type(e.Offset)
			if err != nil {
				continue
			}
			t := &Type{Name: gocoreName(dt), Size: dwarfSize(dt, p.proc.PtrSize())}
			p.dwarfMap[dt] = t
			types = append(types, t)
		}
	}

	p.runtimeNameMap = map[string][]*Type{}

	
	
	for dt, t := range p.dwarfMap {
		switch x := dt.(type) {
		case *dwarf.ArrayType:
			t.Kind = KindArray
			t.Elem = p.dwarfMap[x.Type]
			t.Count = x.Count
		case *dwarf.PtrType:
			t.Kind = KindPtr
			
			if _, ok := x.Type.(*dwarf.VoidType); !ok {
				t.Elem = p.dwarfMap[x.Type]
			}
		case *dwarf.StructType:
			t.Kind = KindStruct
			for _, f := range x.Field {
				fType := p.dwarfMap[f.Type]

				
				
				if strings.HasPrefix(t.Name, "sudog<") && f.Name == "elem" &&
					strings.Count(t.Name, "*")+1 != strings.Count(gocoreName(f.Type), "*") {
					ptrName := "*" + gocoreName(f.Type)
					fType = &Type{Name: ptrName, Kind: KindPtr, Size: p.proc.PtrSize(), Elem: fType}
					p.runtimeNameMap[ptrName] = []*Type{fType}
				}

				t.Fields = append(t.Fields, Field{Name: f.Name, Type: fType, Off: f.ByteOffset})
			}
		case *dwarf.BoolType:
			t.Kind = KindBool
		case *dwarf.IntType:
			t.Kind = KindInt
		case *dwarf.UintType:
			t.Kind = KindUint
		case *dwarf.FloatType:
			t.Kind = KindFloat
		case *dwarf.ComplexType:
			t.Kind = KindComplex
		case *dwarf.FuncType:
			t.Kind = KindFunc
		case *dwarf.TypedefType:
			
		default:
			panic(fmt.Sprintf("unknown type %s %T", dt, dt))
		}
	}

	
	for _, t := range types {
		if t.Kind != KindStruct {
			continue
		}
		if t.Name == "string" { 
			t.Kind = KindString
			t.Elem = t.Fields[0].Type.Elem 
			t.Fields = nil
		}
		if len(t.Name) >= 9 && t.Name[:9] == "struct []" ||
			len(t.Name) >= 2 && t.Name[:2] == "[]" {
			t.Kind = KindSlice
			t.Elem = t.Fields[0].Type.Elem
			t.Fields = nil
		}
	}

	
	for dt, t := range p.dwarfMap {
		tt, ok := dt.(*dwarf.TypedefType)
		if !ok {
			continue
		}
		base := tt.Type
		
		for {
			if x, ok := base.(*dwarf.TypedefType); ok {
				base = x.Type
				continue
			}
			break
		}
		bt := p.dwarfMap[base]

		
		name := t.Name
		*t = *bt
		t.Name = name

		
		
		
		
		
		
		
		if bt.Name == "runtime.eface" {
			t.Kind = KindEface
			t.Fields = nil
		}
		if bt.Name == "runtime.iface" {
			t.Kind = KindIface
			t.Fields = nil
		}
	}

	
	for dt, t := range p.dwarfMap {
		name := runtimeName(dt)
		p.runtimeNameMap[name] = append(p.runtimeNameMap[name], t)
	}

	
	
	
	
	
	
	
	
	
	if p.runtimeNameMap["runtime.specialfinalizer"] == nil {
		special := p.findType("runtime.special")
		p.runtimeNameMap["runtime.specialfinalizer"] = []*Type{
			&Type{
				Name: "runtime.specialfinalizer",
				Size: special.Size + 4*p.proc.PtrSize(),
				Kind: KindStruct,
				Fields: []Field{
					Field{
						Name: "special",
						Off:  0,
						Type: special,
					},
					Field{
						Name: "fn",
						Off:  special.Size,
						Type: p.findType("*runtime.funcval"),
					},
					Field{
						Name: "nret",
						Off:  special.Size + p.proc.PtrSize(),
						Type: p.findType("uintptr"),
					},
					Field{
						Name: "fint",
						Off:  special.Size + 2*p.proc.PtrSize(),
						Type: p.findType("*runtime._type"),
					},
					Field{
						Name: "fn",
						Off:  special.Size + 3*p.proc.PtrSize(),
						Type: p.findType("*runtime.ptrtype"),
					},
				},
			},
		}
	}
}
func ( p * Process ) readDWARFTypes ( ) { d , _ := p . proc . DWARF ( ) // Make one of our own Types for each dwarf type. r := d . Reader ( ) var types [ ] * Type for e , err := r . Next ( ) ; e != nil && err == nil ; e , err = r . Next ( ) { if isNonGoCU ( e ) { r . SkipChildren ( ) continue } switch e . Tag { case dwarf . TagArrayType , dwarf . TagPointerType , dwarf . TagStructType , dwarf . TagBaseType , dwarf . TagSubroutineType , dwarf . TagTypedef : dt , err := d . Type ( e . Offset ) if err != nil { continue } t := & Type { Name : gocoreName ( dt ) , Size : dwarfSize ( dt , p . proc . PtrSize ( ) ) } p . dwarfMap [ dt ] = t types = append ( types , t ) } } p . runtimeNameMap = map [ string ] [ ] * Type { } // Fill in fields of types. Postponed until now so we're sure // we have all the Types allocated and available. for dt , t := range p . dwarfMap { switch x := dt . ( type ) { case * dwarf . ArrayType : t . Kind = KindArray t . Elem = p . dwarfMap [ x . Type ] t . Count = x . Count case * dwarf . PtrType : t . Kind = KindPtr // unsafe.Pointer has a void base type. if _ , ok := x . Type . ( * dwarf . VoidType ) ; ! ok { t . Elem = p . dwarfMap [ x . Type ] } case * dwarf . StructType : t . Kind = KindStruct for _ , f := range x . Field { fType := p . dwarfMap [ f . Type ] // Work around issue 21094. There's no guarantee that the // pointer type is in the DWARF, so just invent a Type. if strings . HasPrefix ( t . Name , " " ) && f . Name == " " && strings . Count ( t . Name , " " ) + 1 != strings . Count ( gocoreName ( f . Type ) , " " ) { ptrName := " " + gocoreName ( f . Type ) fType = & Type { Name : ptrName , Kind : KindPtr , Size : p . proc . PtrSize ( ) , Elem : fType } p . runtimeNameMap [ ptrName ] = [ ] * Type { fType } } t . Fields = append ( t . Fields , Field { Name : f . Name , Type : fType , Off : f . ByteOffset } ) } case * dwarf . BoolType : t . Kind = KindBool case * dwarf . IntType : t . Kind = KindInt case * dwarf . UintType : t . Kind = KindUint case * dwarf . FloatType : t . Kind = KindFloat case * dwarf . ComplexType : t . Kind = KindComplex case * dwarf . FuncType : t . Kind = KindFunc case * dwarf . TypedefType : // handle these types in the loop below default : panic ( fmt . Sprintf ( " " , dt , dt ) ) } } // Detect strings & slices for _ , t := range types { if t . Kind != KindStruct { continue } if t . Name == " " { // TODO: also "struct runtime.stringStructDWARF" ? t . Kind = KindString t . Elem = t . Fields [ 0 ] . Type . Elem // TODO: check that it is always uint8. t . Fields = nil } if len ( t . Name ) >= 9 && t . Name [ : 9 ] == " " || len ( t . Name ) >= 2 && t . Name [ : 2 ] == " " { t . Kind = KindSlice t . Elem = t . Fields [ 0 ] . Type . Elem t . Fields = nil } } // Copy info from base types into typedefs. for dt , t := range p . dwarfMap { tt , ok := dt . ( * dwarf . TypedefType ) if ! ok { continue } base := tt . Type // Walk typedef chain until we reach a non-typedef type. for { if x , ok := base . ( * dwarf . TypedefType ) ; ok { base = x . Type continue } break } bt := p . dwarfMap [ base ] // Copy type info from base. Everything except the name. name := t . Name * t = * bt t . Name = name // Detect some special types. If the base is some particular type, // then the alias gets marked as special. // We have aliases like: //   interface {}              -> struct runtime.eface //   error                     -> struct runtime.iface // Note: the base itself does not get marked as special. // (Unlike strings and slices, where they do.) if bt . Name == " " { t . Kind = KindEface t . Fields = nil } if bt . Name == " " { t . Kind = KindIface t . Fields = nil } } // Make a runtime name -> Type map for existing DWARF types. for dt , t := range p . dwarfMap { name := runtimeName ( dt ) p . runtimeNameMap [ name ] = append ( p . runtimeNameMap [ name ] , t ) } // Construct the runtime.specialfinalizer type.  It won't be found // in DWARF before 1.10 because it does not appear in the type of any variable. // type specialfinalizer struct { //      special special //      fn      *funcval //      nret    uintptr //      fint    *_type //      ot      *ptrtype // } if p . runtimeNameMap [ " " ] == nil { special := p . findType ( " " ) p . runtimeNameMap [ " " ] = [ ] * Type { & Type { Name : " " , Size : special . Size + 4 * p . proc . PtrSize ( ) , Kind : KindStruct , Fields : [ ] Field { Field { Name : " " , Off : 0 , Type : special , } , Field { Name : " " , Off : special . Size , Type : p . findType ( " " ) , } , Field { Name : " " , Off : special . Size + p . proc . PtrSize ( ) , Type : p . findType ( " " ) , } , Field { Name : " " , Off : special . Size + 2 * p . proc . PtrSize ( ) , Type : p . findType ( " " ) , } , Field { Name : " " , Off : special . Size + 3 * p . proc . PtrSize ( ) , Type : p . findType ( " " ) , } , } , } , } } }
// read DWARF types from core dump.
read DWARF types from core dump .