Created
February 19, 2025 06:56
-
-
Save mikeschinkel/07d211bcc54949a9b55bfc7bbb737fa6 to your computer and use it in GitHub Desktop.
A refactoring of https://github.com/golang/go/blob/279da965329a74cd75320f15cb9672a282690ab7/src/debug/dwarf/type.go#L407-L859, take 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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