src/pkg/debug/dwarf/type.go - The Go Programming Language

Golang

Source file src/pkg/debug/dwarf/type.go

     1	// Copyright 2009 The Go Authors.  All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// DWARF type information structures.
     6	// The format is heavily biased toward C, but for simplicity
     7	// the String methods use a pseudo-Go syntax.
     8	
     9	package dwarf
    10	
    11	import "strconv"
    12	
    13	// A Type conventionally represents a pointer to any of the
    14	// specific Type structures (CharType, StructType, etc.).
    15	type Type interface {
    16		Common() *CommonType
    17		String() string
    18		Size() int64
    19	}
    20	
    21	// A CommonType holds fields common to multiple types.
    22	// If a field is not known or not applicable for a given type,
    23	// the zero value is used.
    24	type CommonType struct {
    25		ByteSize int64  // size of value of this type, in bytes
    26		Name     string // name that can be used to refer to type
    27	}
    28	
    29	func (c *CommonType) Common() *CommonType { return c }
    30	
    31	func (c *CommonType) Size() int64 { return c.ByteSize }
    32	
    33	// Basic types
    34	
    35	// A BasicType holds fields common to all basic types.
    36	type BasicType struct {
    37		CommonType
    38		BitSize   int64
    39		BitOffset int64
    40	}
    41	
    42	func (b *BasicType) Basic() *BasicType { return b }
    43	
    44	func (t *BasicType) String() string {
    45		if t.Name != "" {
    46			return t.Name
    47		}
    48		return "?"
    49	}
    50	
    51	// A CharType represents a signed character type.
    52	type CharType struct {
    53		BasicType
    54	}
    55	
    56	// A UcharType represents an unsigned character type.
    57	type UcharType struct {
    58		BasicType
    59	}
    60	
    61	// An IntType represents a signed integer type.
    62	type IntType struct {
    63		BasicType
    64	}
    65	
    66	// A UintType represents an unsigned integer type.
    67	type UintType struct {
    68		BasicType
    69	}
    70	
    71	// A FloatType represents a floating point type.
    72	type FloatType struct {
    73		BasicType
    74	}
    75	
    76	// A ComplexType represents a complex floating point type.
    77	type ComplexType struct {
    78		BasicType
    79	}
    80	
    81	// A BoolType represents a boolean type.
    82	type BoolType struct {
    83		BasicType
    84	}
    85	
    86	// An AddrType represents a machine address type.
    87	type AddrType struct {
    88		BasicType
    89	}
    90	
    91	// qualifiers
    92	
    93	// A QualType represents a type that has the C/C++ "const", "restrict", or "volatile" qualifier.
    94	type QualType struct {
    95		CommonType
    96		Qual string
    97		Type Type
    98	}
    99	
   100	func (t *QualType) String() string { return t.Qual + " " + t.Type.String() }
   101	
   102	func (t *QualType) Size() int64 { return t.Type.Size() }
   103	
   104	// An ArrayType represents a fixed size array type.
   105	type ArrayType struct {
   106		CommonType
   107		Type          Type
   108		StrideBitSize int64 // if > 0, number of bits to hold each element
   109		Count         int64 // if == -1, an incomplete array, like char x[].
   110	}
   111	
   112	func (t *ArrayType) String() string {
   113		return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.String()
   114	}
   115	
   116	func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() }
   117	
   118	// A VoidType represents the C void type.
   119	type VoidType struct {
   120		CommonType
   121	}
   122	
   123	func (t *VoidType) String() string { return "void" }
   124	
   125	// A PtrType represents a pointer type.
   126	type PtrType struct {
   127		CommonType
   128		Type Type
   129	}
   130	
   131	func (t *PtrType) String() string { return "*" + t.Type.String() }
   132	
   133	// A StructType represents a struct, union, or C++ class type.
   134	type StructType struct {
   135		CommonType
   136		StructName string
   137		Kind       string // "struct", "union", or "class".
   138		Field      []*StructField
   139		Incomplete bool // if true, struct, union, class is declared but not defined
   140	}
   141	
   142	// A StructField represents a field in a struct, union, or C++ class type.
   143	type StructField struct {
   144		Name       string
   145		Type       Type
   146		ByteOffset int64
   147		ByteSize   int64
   148		BitOffset  int64 // within the ByteSize bytes at ByteOffset
   149		BitSize    int64 // zero if not a bit field
   150	}
   151	
   152	func (t *StructType) String() string {
   153		if t.StructName != "" {
   154			return t.Kind + " " + t.StructName
   155		}
   156		return t.Defn()
   157	}
   158	
   159	func (t *StructType) Defn() string {
   160		s := t.Kind
   161		if t.StructName != "" {
   162			s += " " + t.StructName
   163		}
   164		if t.Incomplete {
   165			s += " /*incomplete*/"
   166			return s
   167		}
   168		s += " {"
   169		for i, f := range t.Field {
   170			if i > 0 {
   171				s += "; "
   172			}
   173			s += f.Name + " " + f.Type.String()
   174			s += "@" + strconv.FormatInt(f.ByteOffset, 10)
   175			if f.BitSize > 0 {
   176				s += " : " + strconv.FormatInt(f.BitSize, 10)
   177				s += "@" + strconv.FormatInt(f.BitOffset, 10)
   178			}
   179		}
   180		s += "}"
   181		return s
   182	}
   183	
   184	// An EnumType represents an enumerated type.
   185	// The only indication of its native integer type is its ByteSize
   186	// (inside CommonType).
   187	type EnumType struct {
   188		CommonType
   189		EnumName string
   190		Val      []*EnumValue
   191	}
   192	
   193	// An EnumValue represents a single enumeration value.
   194	type EnumValue struct {
   195		Name string
   196		Val  int64
   197	}
   198	
   199	func (t *EnumType) String() string {
   200		s := "enum"
   201		if t.EnumName != "" {
   202			s += " " + t.EnumName
   203		}
   204		s += " {"
   205		for i, v := range t.Val {
   206			if i > 0 {
   207				s += "; "
   208			}
   209			s += v.Name + "=" + strconv.FormatInt(v.Val, 10)
   210		}
   211		s += "}"
   212		return s
   213	}
   214	
   215	// A FuncType represents a function type.
   216	type FuncType struct {
   217		CommonType
   218		ReturnType Type
   219		ParamType  []Type
   220	}
   221	
   222	func (t *FuncType) String() string {
   223		s := "func("
   224		for i, t := range t.ParamType {
   225			if i > 0 {
   226				s += ", "
   227			}
   228			s += t.String()
   229		}
   230		s += ")"
   231		if t.ReturnType != nil {
   232			s += " " + t.ReturnType.String()
   233		}
   234		return s
   235	}
   236	
   237	// A DotDotDotType represents the variadic ... function parameter.
   238	type DotDotDotType struct {
   239		CommonType
   240	}
   241	
   242	func (t *DotDotDotType) String() string { return "..." }
   243	
   244	// A TypedefType represents a named type.
   245	type TypedefType struct {
   246		CommonType
   247		Type Type
   248	}
   249	
   250	func (t *TypedefType) String() string { return t.Name }
   251	
   252	func (t *TypedefType) Size() int64 { return t.Type.Size() }
   253	
   254	func (d *Data) Type(off Offset) (Type, error) {
   255		if t, ok := d.typeCache[off]; ok {
   256			return t, nil
   257		}
   258	
   259		r := d.Reader()
   260		r.Seek(off)
   261		e, err := r.Next()
   262		if err != nil {
   263			return nil, err
   264		}
   265		if e == nil || e.Offset != off {
   266			return nil, DecodeError{"info", off, "no type at offset"}
   267		}
   268	
   269		// Parse type from Entry.
   270		// Must always set d.typeCache[off] before calling
   271		// d.Type recursively, to handle circular types correctly.
   272		var typ Type
   273	
   274		// Get next child; set err if error happens.
   275		next := func() *Entry {
   276			if !e.Children {
   277				return nil
   278			}
   279			kid, err1 := r.Next()
   280			if err1 != nil {
   281				err = err1
   282				return nil
   283			}
   284			if kid == nil {
   285				err = DecodeError{"info", r.b.off, "unexpected end of DWARF entries"}
   286				return nil
   287			}
   288			if kid.Tag == 0 {
   289				return nil
   290			}
   291			return kid
   292		}
   293	
   294		// Get Type referred to by Entry's AttrType field.
   295		// Set err if error happens.  Not having a type is an error.
   296		typeOf := func(e *Entry) Type {
   297			toff, ok := e.Val(AttrType).(Offset)
   298			if !ok {
   299				// It appears that no Type means "void".
   300				return new(VoidType)
   301			}
   302			var t Type
   303			if t, err = d.Type(toff); err != nil {
   304				return nil
   305			}
   306			return t
   307		}
   308	
   309		switch e.Tag {
   310		case TagArrayType:
   311			// Multi-dimensional array.  (DWARF v2 §5.4)
   312			// Attributes:
   313			//	AttrType:subtype [required]
   314			//	AttrStrideSize: size in bits of each element of the array
   315			//	AttrByteSize: size of entire array
   316			// Children:
   317			//	TagSubrangeType or TagEnumerationType giving one dimension.
   318			//	dimensions are in left to right order.
   319			t := new(ArrayType)
   320			typ = t
   321			d.typeCache[off] = t
   322			if t.Type = typeOf(e); err != nil {
   323				goto Error
   324			}
   325			t.StrideBitSize, _ = e.Val(AttrStrideSize).(int64)
   326	
   327			// Accumulate dimensions,
   328			ndim := 0
   329			for kid := next(); kid != nil; kid = next() {
   330				// TODO(rsc): Can also be TagEnumerationType
   331				// but haven't seen that in the wild yet.
   332				switch kid.Tag {
   333				case TagSubrangeType:
   334					max, ok := kid.Val(AttrUpperBound).(int64)
   335					if !ok {
   336						max = -2 // Count == -1, as in x[].
   337					}
   338					if ndim == 0 {
   339						t.Count = max + 1
   340					} else {
   341						// Multidimensional array.
   342						// Create new array type underneath this one.
   343						t.Type = &ArrayType{Type: t.Type, Count: max + 1}
   344					}
   345					ndim++
   346				case TagEnumerationType:
   347					err = DecodeError{"info", kid.Offset, "cannot handle enumeration type as array bound"}
   348					goto Error
   349				}
   350			}
   351			if ndim == 0 {
   352				// LLVM generates this for x[].
   353				t.Count = -1
   354			}
   355	
   356		case TagBaseType:
   357			// Basic type.  (DWARF v2 §5.1)
   358			// Attributes:
   359			//	AttrName: name of base type in programming language of the compilation unit [required]
   360			//	AttrEncoding: encoding value for type (encFloat etc) [required]
   361			//	AttrByteSize: size of type in bytes [required]
   362			//	AttrBitOffset: for sub-byte types, size in bits
   363			//	AttrBitSize: for sub-byte types, bit offset of high order bit in the AttrByteSize bytes
   364			name, _ := e.Val(AttrName).(string)
   365			enc, ok := e.Val(AttrEncoding).(int64)
   366			if !ok {
   367				err = DecodeError{"info", e.Offset, "missing encoding attribute for " + name}
   368				goto Error
   369			}
   370			switch enc {
   371			default:
   372				err = DecodeError{"info", e.Offset, "unrecognized encoding attribute value"}
   373				goto Error
   374	
   375			case encAddress:
   376				typ = new(AddrType)
   377			case encBoolean:
   378				typ = new(BoolType)
   379			case encComplexFloat:
   380				typ = new(ComplexType)
   381			case encFloat:
   382				typ = new(FloatType)
   383			case encSigned:
   384				typ = new(IntType)
   385			case encUnsigned:
   386				typ = new(UintType)
   387			case encSignedChar:
   388				typ = new(CharType)
   389			case encUnsignedChar:
   390				typ = new(UcharType)
   391			}
   392			d.typeCache[off] = typ
   393			t := typ.(interface {
   394				Basic() *BasicType
   395			}).Basic()
   396			t.Name = name
   397			t.BitSize, _ = e.Val(AttrBitSize).(int64)
   398			t.BitOffset, _ = e.Val(AttrBitOffset).(int64)
   399	
   400		case TagClassType, TagStructType, TagUnionType:
   401			// Structure, union, or class type.  (DWARF v2 §5.5)
   402			// Attributes:
   403			//	AttrName: name of struct, union, or class
   404			//	AttrByteSize: byte size [required]
   405			//	AttrDeclaration: if true, struct/union/class is incomplete
   406			// Children:
   407			//	TagMember to describe one member.
   408			//		AttrName: name of member [required]
   409			//		AttrType: type of member [required]
   410			//		AttrByteSize: size in bytes
   411			//		AttrBitOffset: bit offset within bytes for bit fields
   412			//		AttrBitSize: bit size for bit fields
   413			//		AttrDataMemberLoc: location within struct [required for struct, class]
   414			// There is much more to handle C++, all ignored for now.
   415			t := new(StructType)
   416			typ = t
   417			d.typeCache[off] = t
   418			switch e.Tag {
   419			case TagClassType:
   420				t.Kind = "class"
   421			case TagStructType:
   422				t.Kind = "struct"
   423			case TagUnionType:
   424				t.Kind = "union"
   425			}
   426			t.StructName, _ = e.Val(AttrName).(string)
   427			t.Incomplete = e.Val(AttrDeclaration) != nil
   428			t.Field = make([]*StructField, 0, 8)
   429			var lastFieldType Type
   430			var lastFieldBitOffset int64
   431			for kid := next(); kid != nil; kid = next() {
   432				if kid.Tag == TagMember {
   433					f := new(StructField)
   434					if f.Type = typeOf(kid); err != nil {
   435						goto Error
   436					}
   437					if loc, ok := kid.Val(AttrDataMemberLoc).([]byte); ok {
   438						b := makeBuf(d, "location", 0, loc, d.addrsize)
   439						if b.uint8() != opPlusUconst {
   440							err = DecodeError{"info", kid.Offset, "unexpected opcode"}
   441							goto Error
   442						}
   443						f.ByteOffset = int64(b.uint())
   444						if b.err != nil {
   445							err = b.err
   446							goto Error
   447						}
   448					}
   449	
   450					haveBitOffset := false
   451					f.Name, _ = kid.Val(AttrName).(string)
   452					f.ByteSize, _ = kid.Val(AttrByteSize).(int64)
   453					f.BitOffset, haveBitOffset = kid.Val(AttrBitOffset).(int64)
   454					f.BitSize, _ = kid.Val(AttrBitSize).(int64)
   455					t.Field = append(t.Field, f)
   456	
   457					bito := f.BitOffset
   458					if !haveBitOffset {
   459						bito = f.ByteOffset * 8
   460					}
   461					if bito == lastFieldBitOffset && t.Kind != "union" {
   462						// Last field was zero width.  Fix array length.
   463						// (DWARF writes out 0-length arrays as if they were 1-length arrays.)
   464						zeroArray(lastFieldType)
   465					}
   466					lastFieldType = f.Type
   467					lastFieldBitOffset = bito
   468				}
   469			}
   470			if t.Kind != "union" {
   471				b, ok := e.Val(AttrByteSize).(int64)
   472				if ok && b*8 == lastFieldBitOffset {
   473					// Final field must be zero width.  Fix array length.
   474					zeroArray(lastFieldType)
   475				}
   476			}
   477	
   478		case TagConstType, TagVolatileType, TagRestrictType:
   479			// Type modifier (DWARF v2 §5.2)
   480			// Attributes:
   481			//	AttrType: subtype
   482			t := new(QualType)
   483			typ = t
   484			d.typeCache[off] = t
   485			if t.Type = typeOf(e); err != nil {
   486				goto Error
   487			}
   488			switch e.Tag {
   489			case TagConstType:
   490				t.Qual = "const"
   491			case TagRestrictType:
   492				t.Qual = "restrict"
   493			case TagVolatileType:
   494				t.Qual = "volatile"
   495			}
   496	
   497		case TagEnumerationType:
   498			// Enumeration type (DWARF v2 §5.6)
   499			// Attributes:
   500			//	AttrName: enum name if any
   501			//	AttrByteSize: bytes required to represent largest value
   502			// Children:
   503			//	TagEnumerator:
   504			//		AttrName: name of constant
   505			//		AttrConstValue: value of constant
   506			t := new(EnumType)
   507			typ = t
   508			d.typeCache[off] = t
   509			t.EnumName, _ = e.Val(AttrName).(string)
   510			t.Val = make([]*EnumValue, 0, 8)
   511			for kid := next(); kid != nil; kid = next() {
   512				if kid.Tag == TagEnumerator {
   513					f := new(EnumValue)
   514					f.Name, _ = kid.Val(AttrName).(string)
   515					f.Val, _ = kid.Val(AttrConstValue).(int64)
   516					n := len(t.Val)
   517					if n >= cap(t.Val) {
   518						val := make([]*EnumValue, n, n*2)
   519						copy(val, t.Val)
   520						t.Val = val
   521					}
   522					t.Val = t.Val[0 : n+1]
   523					t.Val[n] = f
   524				}
   525			}
   526	
   527		case TagPointerType:
   528			// Type modifier (DWARF v2 §5.2)
   529			// Attributes:
   530			//	AttrType: subtype [not required!  void* has no AttrType]
   531			//	AttrAddrClass: address class [ignored]
   532			t := new(PtrType)
   533			typ = t
   534			d.typeCache[off] = t
   535			if e.Val(AttrType) == nil {
   536				t.Type = &VoidType{}
   537				break
   538			}
   539			t.Type = typeOf(e)
   540	
   541		case TagSubroutineType:
   542			// Subroutine type.  (DWARF v2 §5.7)
   543			// Attributes:
   544			//	AttrType: type of return value if any
   545			//	AttrName: possible name of type [ignored]
   546			//	AttrPrototyped: whether used ANSI C prototype [ignored]
   547			// Children:
   548			//	TagFormalParameter: typed parameter
   549			//		AttrType: type of parameter
   550			//	TagUnspecifiedParameter: final ...
   551			t := new(FuncType)
   552			typ = t
   553			d.typeCache[off] = t
   554			if t.ReturnType = typeOf(e); err != nil {
   555				goto Error
   556			}
   557			t.ParamType = make([]Type, 0, 8)
   558			for kid := next(); kid != nil; kid = next() {
   559				var tkid Type
   560				switch kid.Tag {
   561				default:
   562					continue
   563				case TagFormalParameter:
   564					if tkid = typeOf(kid); err != nil {
   565						goto Error
   566					}
   567				case TagUnspecifiedParameters:
   568					tkid = &DotDotDotType{}
   569				}
   570				t.ParamType = append(t.ParamType, tkid)
   571			}
   572	
   573		case TagTypedef:
   574			// Typedef (DWARF v2 §5.3)
   575			// Attributes:
   576			//	AttrName: name [required]
   577			//	AttrType: type definition [required]
   578			t := new(TypedefType)
   579			typ = t
   580			d.typeCache[off] = t
   581			t.Name, _ = e.Val(AttrName).(string)
   582			t.Type = typeOf(e)
   583		}
   584	
   585		if err != nil {
   586			goto Error
   587		}
   588	
   589		{
   590			b, ok := e.Val(AttrByteSize).(int64)
   591			if !ok {
   592				b = -1
   593			}
   594			typ.Common().ByteSize = b
   595		}
   596		return typ, nil
   597	
   598	Error:
   599		// If the parse fails, take the type out of the cache
   600		// so that the next call with this offset doesn't hit
   601		// the cache and return success.
   602		delete(d.typeCache, off)
   603		return nil, err
   604	}
   605	
   606	func zeroArray(t Type) {
   607		for {
   608			at, ok := t.(*ArrayType)
   609			if !ok {
   610				break
   611			}
   612			at.Count = 0
   613			t = at.Type
   614		}
   615	}