The Go Programming Language

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

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.