github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/debug/dwarf/type.go (about)

     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  					// TODO: Should have original compilation
   439  					// unit here, not unknownFormat.
   440  					b := makeBuf(d, unknownFormat{}, "location", 0, loc)
   441  					if b.uint8() != opPlusUconst {
   442  						err = DecodeError{"info", kid.Offset, "unexpected opcode"}
   443  						goto Error
   444  					}
   445  					f.ByteOffset = int64(b.uint())
   446  					if b.err != nil {
   447  						err = b.err
   448  						goto Error
   449  					}
   450  				}
   451  
   452  				haveBitOffset := false
   453  				f.Name, _ = kid.Val(AttrName).(string)
   454  				f.ByteSize, _ = kid.Val(AttrByteSize).(int64)
   455  				f.BitOffset, haveBitOffset = kid.Val(AttrBitOffset).(int64)
   456  				f.BitSize, _ = kid.Val(AttrBitSize).(int64)
   457  				t.Field = append(t.Field, f)
   458  
   459  				bito := f.BitOffset
   460  				if !haveBitOffset {
   461  					bito = f.ByteOffset * 8
   462  				}
   463  				if bito == lastFieldBitOffset && t.Kind != "union" {
   464  					// Last field was zero width.  Fix array length.
   465  					// (DWARF writes out 0-length arrays as if they were 1-length arrays.)
   466  					zeroArray(lastFieldType)
   467  				}
   468  				lastFieldType = f.Type
   469  				lastFieldBitOffset = bito
   470  			}
   471  		}
   472  		if t.Kind != "union" {
   473  			b, ok := e.Val(AttrByteSize).(int64)
   474  			if ok && b*8 == lastFieldBitOffset {
   475  				// Final field must be zero width.  Fix array length.
   476  				zeroArray(lastFieldType)
   477  			}
   478  		}
   479  
   480  	case TagConstType, TagVolatileType, TagRestrictType:
   481  		// Type modifier (DWARF v2 §5.2)
   482  		// Attributes:
   483  		//	AttrType: subtype
   484  		t := new(QualType)
   485  		typ = t
   486  		d.typeCache[off] = t
   487  		if t.Type = typeOf(e); err != nil {
   488  			goto Error
   489  		}
   490  		switch e.Tag {
   491  		case TagConstType:
   492  			t.Qual = "const"
   493  		case TagRestrictType:
   494  			t.Qual = "restrict"
   495  		case TagVolatileType:
   496  			t.Qual = "volatile"
   497  		}
   498  
   499  	case TagEnumerationType:
   500  		// Enumeration type (DWARF v2 §5.6)
   501  		// Attributes:
   502  		//	AttrName: enum name if any
   503  		//	AttrByteSize: bytes required to represent largest value
   504  		// Children:
   505  		//	TagEnumerator:
   506  		//		AttrName: name of constant
   507  		//		AttrConstValue: value of constant
   508  		t := new(EnumType)
   509  		typ = t
   510  		d.typeCache[off] = t
   511  		t.EnumName, _ = e.Val(AttrName).(string)
   512  		t.Val = make([]*EnumValue, 0, 8)
   513  		for kid := next(); kid != nil; kid = next() {
   514  			if kid.Tag == TagEnumerator {
   515  				f := new(EnumValue)
   516  				f.Name, _ = kid.Val(AttrName).(string)
   517  				f.Val, _ = kid.Val(AttrConstValue).(int64)
   518  				n := len(t.Val)
   519  				if n >= cap(t.Val) {
   520  					val := make([]*EnumValue, n, n*2)
   521  					copy(val, t.Val)
   522  					t.Val = val
   523  				}
   524  				t.Val = t.Val[0 : n+1]
   525  				t.Val[n] = f
   526  			}
   527  		}
   528  
   529  	case TagPointerType:
   530  		// Type modifier (DWARF v2 §5.2)
   531  		// Attributes:
   532  		//	AttrType: subtype [not required!  void* has no AttrType]
   533  		//	AttrAddrClass: address class [ignored]
   534  		t := new(PtrType)
   535  		typ = t
   536  		d.typeCache[off] = t
   537  		if e.Val(AttrType) == nil {
   538  			t.Type = &VoidType{}
   539  			break
   540  		}
   541  		t.Type = typeOf(e)
   542  
   543  	case TagSubroutineType:
   544  		// Subroutine type.  (DWARF v2 §5.7)
   545  		// Attributes:
   546  		//	AttrType: type of return value if any
   547  		//	AttrName: possible name of type [ignored]
   548  		//	AttrPrototyped: whether used ANSI C prototype [ignored]
   549  		// Children:
   550  		//	TagFormalParameter: typed parameter
   551  		//		AttrType: type of parameter
   552  		//	TagUnspecifiedParameter: final ...
   553  		t := new(FuncType)
   554  		typ = t
   555  		d.typeCache[off] = t
   556  		if t.ReturnType = typeOf(e); err != nil {
   557  			goto Error
   558  		}
   559  		t.ParamType = make([]Type, 0, 8)
   560  		for kid := next(); kid != nil; kid = next() {
   561  			var tkid Type
   562  			switch kid.Tag {
   563  			default:
   564  				continue
   565  			case TagFormalParameter:
   566  				if tkid = typeOf(kid); err != nil {
   567  					goto Error
   568  				}
   569  			case TagUnspecifiedParameters:
   570  				tkid = &DotDotDotType{}
   571  			}
   572  			t.ParamType = append(t.ParamType, tkid)
   573  		}
   574  
   575  	case TagTypedef:
   576  		// Typedef (DWARF v2 §5.3)
   577  		// Attributes:
   578  		//	AttrName: name [required]
   579  		//	AttrType: type definition [required]
   580  		t := new(TypedefType)
   581  		typ = t
   582  		d.typeCache[off] = t
   583  		t.Name, _ = e.Val(AttrName).(string)
   584  		t.Type = typeOf(e)
   585  	}
   586  
   587  	if err != nil {
   588  		goto Error
   589  	}
   590  
   591  	{
   592  		b, ok := e.Val(AttrByteSize).(int64)
   593  		if !ok {
   594  			b = -1
   595  		}
   596  		typ.Common().ByteSize = b
   597  	}
   598  	return typ, nil
   599  
   600  Error:
   601  	// If the parse fails, take the type out of the cache
   602  	// so that the next call with this offset doesn't hit
   603  	// the cache and return success.
   604  	delete(d.typeCache, off)
   605  	return nil, err
   606  }
   607  
   608  func zeroArray(t Type) {
   609  	for {
   610  		at, ok := t.(*ArrayType)
   611  		if !ok {
   612  			break
   613  		}
   614  		at.Count = 0
   615  		t = at.Type
   616  	}
   617  }