return d.readType("info", d.Reader(), off, d.typeCache, nil)
}
+type typeFixer struct {
+ typedefs []*TypedefType
+ arraytypes []*Type
+}
+
+func (tf *typeFixer) recordArrayType(t *Type) {
+ if t == nil {
+ return
+ }
+ _, ok := (*t).(*ArrayType)
+ if ok {
+ tf.arraytypes = append(tf.arraytypes, t)
+ }
+}
+
+func (tf *typeFixer) apply() {
+ for _, t := range tf.typedefs {
+ t.Common().ByteSize = t.Type.Size()
+ }
+ for _, t := range tf.arraytypes {
+ zeroArray(t)
+ }
+}
+
// readType reads a type from r at off of name. It adds types to the
// type cache, appends new typedef types to typedefs, and computes the
// sizes of types. Callers should pass nil for typedefs; this is used
// for internal recursion.
-func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type, typedefs *[]*TypedefType) (Type, error) {
+func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type, fixups *typeFixer) (Type, error) {
if t, ok := typeCache[off]; ok {
return t, nil
}
}
// If this is the root of the recursion, prepare to resolve
- // typedef sizes once the recursion is done. This must be done
- // after the type graph is constructed because it may need to
- // resolve cycles in a different order than readType
- // encounters them.
- if typedefs == nil {
- var typedefList []*TypedefType
+ // typedef sizes and perform other fixups once the recursion is
+ // done. This must be done after the type graph is constructed
+ // because it may need to resolve cycles in a different order than
+ // readType encounters them.
+ if fixups == nil {
+ var fixer typeFixer
defer func() {
- for _, t := range typedefList {
- t.Common().ByteSize = t.Type.Size()
- }
+ fixer.apply()
}()
- typedefs = &typedefList
+ fixups = &fixer
}
// Parse type from Entry.
var t Type
switch toff := tval.(type) {
case Offset:
- if t, err = d.readType(name, r.clone(), toff, typeCache, typedefs); err != nil {
+ if t, err = d.readType(name, r.clone(), toff, typeCache, fixups); err != nil {
return nil
}
case uint64:
if bito == lastFieldBitOffset && t.Kind != "union" {
// Last field was zero width. Fix array length.
// (DWARF writes out 0-length arrays as if they were 1-length arrays.)
- zeroArray(lastFieldType)
+ fixups.recordArrayType(lastFieldType)
}
lastFieldType = &f.Type
lastFieldBitOffset = bito
b, ok := e.Val(AttrByteSize).(int64)
if ok && b*8 == lastFieldBitOffset {
// Final field must be zero width. Fix array length.
- zeroArray(lastFieldType)
+ fixups.recordArrayType(lastFieldType)
}
}
// Record that we need to resolve this
// type's size once the type graph is
// constructed.
- *typedefs = append(*typedefs, t)
+ fixups.typedefs = append(fixups.typedefs, t)
case *PtrType:
b = int64(addressSize)
}
}
func zeroArray(t *Type) {
- if t == nil {
- return
- }
- at, ok := (*t).(*ArrayType)
- if !ok || at.Type.Size() == 0 {
+ at := (*t).(*ArrayType)
+ if at.Type.Size() == 0 {
return
}
// Make a copy to avoid invalidating typeCache.