Skip to content

Instantly share code, notes, and snippets.

@mikeschinkel
Created February 19, 2025 06:56
Show Gist options
  • Save mikeschinkel/07d211bcc54949a9b55bfc7bbb737fa6 to your computer and use it in GitHub Desktop.
Save mikeschinkel/07d211bcc54949a9b55bfc7bbb737fa6 to your computer and use it in GitHub Desktop.
// 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, fixups *typeFixer) (t Type, err error) {
var e *Entry
var ok bool
var addressSize int
var typ Type
var nextDepth int
var next entryChildFunc
var typeOf entryTypeFunc
if t, ok = typeCache[off]; ok {
goto end
}
r.Seek(off)
e = r.Next() ?
addressSize = r.AddressSize()
if e == nil || e.Offset != off {
DecodeError{name, off, "no type at offset"} ?
}
// If this is the root of the recursion, prepare to resolve
// 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() {
fixer.apply()
}()
fixups = &fixer
}
// Parse type from Entry.
// Must always set typeCache[off] before calling
// d.readType recursively, to handle circular types correctly.
// Get next child; set err if error happens.
next = func() *Entry {
return e.getChild(name, r, &nextDepth)
}
// Get Type referred to by Entry's AttrType field.
// Set err if error happens. Not having a type is an error.
typeOf = func(e *Entry) (Type, error) {
return e.getType(d, name, r, typeCache, fixups)
}
switch e.Tag {
case TagArrayType:
// Multi-dimensional array. (DWARF v2 §5.4)
typ = e.readArrayTag(name, off, typeCache, next, typeOf) ?
case TagBaseType:
// Basic type. (DWARF v2 §5.1)
typ = e.readBaseTag(name, off, typeCache) ?
case TagClassType, TagStructType, TagUnionType:
// Structure, union, or class type. (DWARF v2 §5.5)
typ = e.readClassStructUnionTag(d, name, off, typeCache, fixups, next, typeOf) ?
case TagConstType, TagVolatileType, TagRestrictType:
// Type modifier (DWARF v2 §5.2)
typ = e.readConstVolatileRestrictTag(d, name, off, typeCache, fixups, next, typeOf) ?
case TagEnumerationType:
// Enumeration type (DWARF v2 §5.6)
typ = e.readEnumerationTag(off, typeCache, next) ?
case TagPointerType:
// Type modifier (DWARF v2 §5.2)
typ = e.readPointerTag(off, typeCache, typeOf) ?
case TagSubroutineType:
// Subroutine type. (DWARF v2 §5.7)
typ = e.readSubroutineTag(off, typeCache, next, typeOf) ?
case TagTypedef:
// Typedef (DWARF v2 §5.3)
typ = e.readTypedefTag(off, typeCache, typeOf) ?
case TagUnspecifiedType:
// Unspecified type (DWARF v3 §5.2)
typ = e.readUnspecifiedTypeTag(off, typeCache) ?
default:
// This is some other type DIE that we're currently not
// equipped to handle.
typ = e.readUnsupportedTypeTag(off, typeCache) ?
}
typ, fixups = e.fixupByteSize(typ, fixups, addressSize)
error {
// If the parse fails, take the type out of the cache
// so that the next call with this offset doesn't hit
// the cache and return success.
delete(typeCache, off)
}
end:
return typ, error()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment