diff --git a/reccmp/compare/ingest.py b/reccmp/compare/ingest.py index 25923825..1c1a3bf2 100644 --- a/reccmp/compare/ingest.py +++ b/reccmp/compare/ingest.py @@ -29,6 +29,7 @@ def load_cvdump_types(cvdump_analysis: CvdumpAnalysis, types: CvdumpTypesParser) # TODO: Populate the universal type database here when this exists. (#106) # For now, just copy the keys into another CvdumpTypesParser so we can use its API. types.keys.update(cvdump_analysis.types.keys) + types.alerted_types = cvdump_analysis.types.alerted_types def load_cvdump(cvdump_analysis: CvdumpAnalysis, db: EntityDb, recomp_bin: PEImage): @@ -111,6 +112,7 @@ def load_cvdump(cvdump_analysis: CvdumpAnalysis, db: EntityDb, recomp_bin: PEIma # Set the cvdump type key so it can be referenced later. if sym.node_type == EntityType.DATA and sym.data_type is not None: + assert isinstance(sym.data_type.key, int) batch.set_recomp(addr, data_type=sym.data_type.key) diff --git a/reccmp/compare/mutate.py b/reccmp/compare/mutate.py index b6c033d3..4426f987 100644 --- a/reccmp/compare/mutate.py +++ b/reccmp/compare/mutate.py @@ -8,6 +8,7 @@ get_function_arg_string, ) from reccmp.cvdump import CvdumpTypesParser +from reccmp.cvdump.types import CvdumpTypeKey from reccmp.types import EntityType from .db import EntityDb from .queries import get_overloaded_functions, get_named_thunks @@ -27,7 +28,7 @@ def match_array_elements(db: EntityDb, types: CvdumpTypesParser): batch = db.batch() @cache - def get_type_size(type_key: str) -> int: + def get_type_size(type_key: CvdumpTypeKey) -> int: type_ = types.get(type_key) assert type_.size is not None return type_.size @@ -57,15 +58,16 @@ def _add_match_in_array( for match in db.get_matches_by_type(EntityType.DATA): # TODO: The type information we need is in multiple places. (See #106) - type_key = match.get("data_type") - if type_key is None: + type_key_raw = match.get("data_type") + if type_key_raw is None: continue - if not type_key.startswith("0x"): + type_key = CvdumpTypeKey(type_key_raw) + if type_key.is_scalar(): # scalar type, so clearly not an array continue - type_dict = types.keys.get(type_key.lower()) + type_dict = types.keys.get(type_key) if type_dict is None: continue @@ -76,7 +78,7 @@ def _add_match_in_array( if array_type_key is None: continue - data_type = types.get(type_key.lower()) + data_type = types.get(type_key) # Check whether another orig variable appears before the end of the array in recomp. # If this happens we can still add all the recomp offsets, but do not attach the orig address diff --git a/reccmp/cvdump/analysis.py b/reccmp/cvdump/analysis.py index 0aedbcbc..1afb72d0 100644 --- a/reccmp/cvdump/analysis.py +++ b/reccmp/cvdump/analysis.py @@ -6,7 +6,12 @@ from .demangler import demangle_vtable from .parser import CvdumpParser, LineValue, NodeKey from .symbols import SymbolsEntry -from .types import CvdumpKeyError, CvdumpIntegrityError, CvdumpTypesParser, TypeInfo +from .types import ( + CvdumpKeyError, + CvdumpIntegrityError, + CvdumpTypesParser, + TypeInfo, +) @dataclass diff --git a/reccmp/cvdump/cvinfo.py b/reccmp/cvdump/cvinfo.py new file mode 100644 index 00000000..52d74da1 --- /dev/null +++ b/reccmp/cvdump/cvinfo.py @@ -0,0 +1,761 @@ +"""Type enum modified from cvinfo.h released under MIT license. +https://github.com/microsoft/microsoft-pdb/blob/master/include/cvinfo.h +See `LICENSE.cvdump.txt` for details. +""" + +from enum import Enum +from types import MappingProxyType +from typing import NamedTuple + + +class CvdumpTypeKey(int): + def is_scalar(self) -> bool: + return self < 0x1000 + + @classmethod + def from_str(cls, key: str) -> "CvdumpTypeKey": + """The patterns we expect are: + 1. Hex number, either 4 or 8 digits. + 2. Primitive type name with hex digits in parens. + a. T_INT4(0074) + b. ???(007C) + """ + if key.startswith("0x"): + return cls(int(key, 16)) + + return cls(int(key[-5:-1], 16)) + + +class CvInfoType(NamedTuple): + key: CvdumpTypeKey + """The integer type key.""" + name: str + """The name of this type as given in cvinfo.h.""" + fmt: str + """The struct.unpack format char(s) for this type.""" + size: int + """The type's footprint in bytes.""" + pointer: CvdumpTypeKey | None + """If set, this type is a pointer to another CVinfo type.""" + verified: bool + """Is this a type we have seen in the field?""" + + +# This listing of types is taken from cvinfo.h. +# We have modified the order for clarity. +# The original description for each type is on the right, after the tuple. + +# fmt: off +_CVINFO_TYPES = ( + # Special Types + CvInfoType(key=CvdumpTypeKey(0x0000), name="T_NOTYPE", fmt="", size=0, pointer=None, verified=True ), # uncharacterized type (no type) + CvInfoType(key=CvdumpTypeKey(0x0001), name="T_ABS", fmt="", size=0, pointer=None, verified=False), # absolute symbol + CvInfoType(key=CvdumpTypeKey(0x0002), name="T_SEGMENT", fmt="", size=0, pointer=None, verified=False), # segment type + CvInfoType(key=CvdumpTypeKey(0x0004), name="T_CURRENCY", fmt="", size=0, pointer=None, verified=False), # BASIC 8 byte currency value + CvInfoType(key=CvdumpTypeKey(0x0005), name="T_NBASICSTR", fmt="", size=0, pointer=None, verified=False), # Near BASIC string + CvInfoType(key=CvdumpTypeKey(0x0006), name="T_FBASICSTR", fmt="", size=0, pointer=None, verified=False), # Far BASIC string + CvInfoType(key=CvdumpTypeKey(0x0007), name="T_NOTTRANS", fmt="", size=0, pointer=None, verified=False), # type not translated by cvpack + CvInfoType(key=CvdumpTypeKey(0x0060), name="T_BIT", fmt="", size=0, pointer=None, verified=False), # bit + CvInfoType(key=CvdumpTypeKey(0x0061), name="T_PASCHAR", fmt="", size=0, pointer=None, verified=False), # Pascal CHAR + CvInfoType(key=CvdumpTypeKey(0x0062), name="T_BOOL32FF", fmt="i", size=4, pointer=None, verified=False), # 32-bit BOOL where true is 0xffffffff + + # void types + CvInfoType(key=CvdumpTypeKey(0x0003), name="T_VOID", fmt="", size=0, pointer=None, verified=True ), # void + CvInfoType(key=CvdumpTypeKey(0x0103), name="T_PVOID", fmt="H", size=2, pointer=CvdumpTypeKey(0x0003), verified=False), # near pointer to void + CvInfoType(key=CvdumpTypeKey(0x0203), name="T_PFVOID", fmt="I", size=4, pointer=CvdumpTypeKey(0x0003), verified=False), # far pointer to void + CvInfoType(key=CvdumpTypeKey(0x0303), name="T_PHVOID", fmt="I", size=4, pointer=CvdumpTypeKey(0x0003), verified=False), # huge pointer to void + CvInfoType(key=CvdumpTypeKey(0x0403), name="T_32PVOID", fmt="I", size=4, pointer=CvdumpTypeKey(0x0003), verified=True ), # 32 bit pointer to void + CvInfoType(key=CvdumpTypeKey(0x0503), name="T_32PFVOID", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0003), verified=False), # 16:32 pointer to void + CvInfoType(key=CvdumpTypeKey(0x0603), name="T_64PVOID", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0003), verified=False), # 64 bit pointer to void + + # HRESULT types + # We will add the missing pointer types if they ever appear. + CvInfoType(key=CvdumpTypeKey(0x0008), name="T_HRESULT", fmt="I", size=4, pointer=None, verified=True ), # OLE/COM HRESULT + CvInfoType(key=CvdumpTypeKey(0x0408), name="T_32PHRESULT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0008), verified=True ), # OLE/COM HRESULT __ptr32 * + CvInfoType(key=CvdumpTypeKey(0x0608), name="T_64PHRESULT", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0008), verified=False), # OLE/COM HRESULT __ptr64 * + + # 8-bit signed char types + CvInfoType(key=CvdumpTypeKey(0x0010), name="T_CHAR", fmt="b", size=1, pointer=None, verified=True ), # 8 bit signed + CvInfoType(key=CvdumpTypeKey(0x0110), name="T_PCHAR", fmt="H", size=2, pointer=CvdumpTypeKey(0x0010), verified=False), # 16 bit pointer to 8 bit signed + CvInfoType(key=CvdumpTypeKey(0x0210), name="T_PFCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0010), verified=False), # 16:16 far pointer to 8 bit signed + CvInfoType(key=CvdumpTypeKey(0x0310), name="T_PHCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0010), verified=False), # 16:16 huge pointer to 8 bit signed + CvInfoType(key=CvdumpTypeKey(0x0410), name="T_32PCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0010), verified=True ), # 32 bit pointer to 8 bit signed + CvInfoType(key=CvdumpTypeKey(0x0510), name="T_32PFCHAR", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0010), verified=False), # 16:32 pointer to 8 bit signed + CvInfoType(key=CvdumpTypeKey(0x0610), name="T_64PCHAR", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0010), verified=False), # 64 bit pointer to 8 bit signed + + # 8-bit unsigned char types + CvInfoType(key=CvdumpTypeKey(0x0020), name="T_UCHAR", fmt="B", size=1, pointer=None, verified=True ), # 8 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0120), name="T_PUCHAR", fmt="H", size=2, pointer=CvdumpTypeKey(0x0020), verified=False), # 16 bit pointer to 8 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0220), name="T_PFUCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0020), verified=False), # 16:16 far pointer to 8 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0320), name="T_PHUCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0020), verified=False), # 16:16 huge pointer to 8 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0420), name="T_32PUCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0020), verified=True ), # 32 bit pointer to 8 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0520), name="T_32PFUCHAR", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0020), verified=False), # 16:32 pointer to 8 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0620), name="T_64PUCHAR", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0020), verified=False), # 64 bit pointer to 8 bit unsigned + + # 8-bit char types + # RCHAR means "Really a char", to distinguish from the 8-bit value T_CHAR. + CvInfoType(key=CvdumpTypeKey(0x0070), name="T_RCHAR", fmt="c", size=1, pointer=None, verified=True ), # really a char + CvInfoType(key=CvdumpTypeKey(0x0170), name="T_PRCHAR", fmt="H", size=2, pointer=CvdumpTypeKey(0x0070), verified=False), # 16 bit pointer to a real char + CvInfoType(key=CvdumpTypeKey(0x0270), name="T_PFRCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0070), verified=False), # 16:16 far pointer to a real char + CvInfoType(key=CvdumpTypeKey(0x0370), name="T_PHRCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0070), verified=False), # 16:16 huge pointer to a real char + CvInfoType(key=CvdumpTypeKey(0x0470), name="T_32PRCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0070), verified=True ), # 32 bit pointer to a real char + CvInfoType(key=CvdumpTypeKey(0x0570), name="T_32PFRCHAR", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0070), verified=False), # 16:32 pointer to a real char + CvInfoType(key=CvdumpTypeKey(0x0670), name="T_64PRCHAR", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0070), verified=False), # 64 bit pointer to a real char + + # 16-bit widechar types + CvInfoType(key=CvdumpTypeKey(0x0071), name="T_WCHAR", fmt="H", size=2, pointer=None, verified=True ), # wide char + CvInfoType(key=CvdumpTypeKey(0x0171), name="T_PWCHAR", fmt="H", size=2, pointer=CvdumpTypeKey(0x0071), verified=False), # 16 bit pointer to a wide char + CvInfoType(key=CvdumpTypeKey(0x0271), name="T_PFWCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0071), verified=False), # 16:16 far pointer to a wide char + CvInfoType(key=CvdumpTypeKey(0x0371), name="T_PHWCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0071), verified=False), # 16:16 huge pointer to a wide char + CvInfoType(key=CvdumpTypeKey(0x0471), name="T_32PWCHAR", fmt="I", size=4, pointer=CvdumpTypeKey(0x0071), verified=True ), # 32 bit pointer to a wide char + CvInfoType(key=CvdumpTypeKey(0x0571), name="T_32PFWCHAR", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0071), verified=False), # 16:32 pointer to a wide char + CvInfoType(key=CvdumpTypeKey(0x0671), name="T_64PWCHAR", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0071), verified=False), # 64 bit pointer to a wide char + + # 16-bit unicode char types + CvInfoType(key=CvdumpTypeKey(0x007a), name="T_CHAR16", fmt="H", size=2, pointer=None, verified=False), # 16-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x017a), name="T_PCHAR16", fmt="H", size=2, pointer=CvdumpTypeKey(0x007a), verified=False), # 16 bit pointer to a 16-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x027a), name="T_PFCHAR16", fmt="I", size=4, pointer=CvdumpTypeKey(0x007a), verified=False), # 16:16 far pointer to a 16-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x037a), name="T_PHCHAR16", fmt="I", size=4, pointer=CvdumpTypeKey(0x007a), verified=False), # 16:16 huge pointer to a 16-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x047a), name="T_32PCHAR16", fmt="I", size=4, pointer=CvdumpTypeKey(0x007a), verified=False), # 32 bit pointer to a 16-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x057a), name="T_32PFCHAR16", fmt="6x", size=6, pointer=CvdumpTypeKey(0x007a), verified=False), # 16:32 pointer to a 16-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x067a), name="T_64PCHAR16", fmt="Q", size=8, pointer=CvdumpTypeKey(0x007a), verified=False), # 64 bit pointer to a 16-bit unicode char + + # 32-bit unicode char types + CvInfoType(key=CvdumpTypeKey(0x007b), name="T_CHAR32", fmt="I", size=4, pointer=None, verified=False), # 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x017b), name="T_PCHAR32", fmt="H", size=2, pointer=CvdumpTypeKey(0x007b), verified=False), # 16 bit pointer to a 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x027b), name="T_PFCHAR32", fmt="I", size=4, pointer=CvdumpTypeKey(0x007b), verified=False), # 16:16 far pointer to a 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x037b), name="T_PHCHAR32", fmt="I", size=4, pointer=CvdumpTypeKey(0x007b), verified=False), # 16:16 huge pointer to a 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x047b), name="T_32PCHAR32", fmt="I", size=4, pointer=CvdumpTypeKey(0x007b), verified=False), # 32 bit pointer to a 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x057b), name="T_32PFCHAR32", fmt="6x", size=6, pointer=CvdumpTypeKey(0x007b), verified=False), # 16:32 pointer to a 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x067b), name="T_64PCHAR32", fmt="Q", size=8, pointer=CvdumpTypeKey(0x007b), verified=False), # 64 bit pointer to a 32-bit unicode char + + # 8-bit unicode char types + # Not part of cvinfo.h but found in other sources. See GH #85. + CvInfoType(key=CvdumpTypeKey(0x007c), name="T_CHAR8", fmt="B", size=1, pointer=None, verified=False), # 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x017c), name="T_PCHAR8", fmt="H", size=2, pointer=CvdumpTypeKey(0x007c), verified=False), # 16 bit pointer to a 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x027c), name="T_PFCHAR8", fmt="I", size=4, pointer=CvdumpTypeKey(0x007c), verified=False), # 16:16 far pointer to a 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x037c), name="T_PHCHAR8", fmt="I", size=4, pointer=CvdumpTypeKey(0x007c), verified=False), # 16:16 huge pointer to a 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x047c), name="T_32PCHAR8", fmt="I", size=4, pointer=CvdumpTypeKey(0x007c), verified=False), # 32 bit pointer to a 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x057c), name="T_32PFCHAR8", fmt="6x", size=6, pointer=CvdumpTypeKey(0x007c), verified=False), # 16:32 pointer to a 32-bit unicode char + CvInfoType(key=CvdumpTypeKey(0x067c), name="T_64PCHAR8", fmt="Q", size=8, pointer=CvdumpTypeKey(0x007c), verified=False), # 64 bit pointer to a 32-bit unicode char + + # 8-bit signed int types + CvInfoType(key=CvdumpTypeKey(0x0068), name="T_INT1", fmt="b", size=1, pointer=None, verified=False), # 8 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0168), name="T_PINT1", fmt="H", size=2, pointer=CvdumpTypeKey(0x0068), verified=False), # 16 bit pointer to 8 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0268), name="T_PFINT1", fmt="I", size=4, pointer=CvdumpTypeKey(0x0068), verified=False), # 16:16 far pointer to 8 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0368), name="T_PHINT1", fmt="I", size=4, pointer=CvdumpTypeKey(0x0068), verified=False), # 16:16 huge pointer to 8 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0468), name="T_32PINT1", fmt="I", size=4, pointer=CvdumpTypeKey(0x0068), verified=False), # 32 bit pointer to 8 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0568), name="T_32PFINT1", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0068), verified=False), # 16:32 pointer to 8 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0668), name="T_64PINT1", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0068), verified=False), # 64 bit pointer to 8 bit signed int + + # 8-bit unsigned int types + CvInfoType(key=CvdumpTypeKey(0x0069), name="T_UINT1", fmt="B", size=1, pointer=None, verified=False), # 8 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0169), name="T_PUINT1", fmt="H", size=2, pointer=CvdumpTypeKey(0x0069), verified=False), # 16 bit pointer to 8 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0269), name="T_PFUINT1", fmt="I", size=4, pointer=CvdumpTypeKey(0x0069), verified=False), # 16:16 far pointer to 8 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0369), name="T_PHUINT1", fmt="I", size=4, pointer=CvdumpTypeKey(0x0069), verified=False), # 16:16 huge pointer to 8 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0469), name="T_32PUINT1", fmt="I", size=4, pointer=CvdumpTypeKey(0x0069), verified=False), # 32 bit pointer to 8 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0569), name="T_32PFUINT1", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0069), verified=False), # 16:32 pointer to 8 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0669), name="T_64PUINT1", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0069), verified=False), # 64 bit pointer to 8 bit unsigned int + + # 16-bit signed short types + CvInfoType(key=CvdumpTypeKey(0x0011), name="T_SHORT", fmt="h", size=2, pointer=None, verified=True ), # 16 bit signed + CvInfoType(key=CvdumpTypeKey(0x0111), name="T_PSHORT", fmt="H", size=2, pointer=CvdumpTypeKey(0x0011), verified=False), # 16 bit pointer to 16 bit signed + CvInfoType(key=CvdumpTypeKey(0x0211), name="T_PFSHORT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0011), verified=False), # 16:16 far pointer to 16 bit signed + CvInfoType(key=CvdumpTypeKey(0x0311), name="T_PHSHORT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0011), verified=False), # 16:16 huge pointer to 16 bit signed + CvInfoType(key=CvdumpTypeKey(0x0411), name="T_32PSHORT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0011), verified=True ), # 32 bit pointer to 16 bit signed + CvInfoType(key=CvdumpTypeKey(0x0511), name="T_32PFSHORT", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0011), verified=False), # 16:32 pointer to 16 bit signed + CvInfoType(key=CvdumpTypeKey(0x0611), name="T_64PSHORT", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0011), verified=False), # 64 bit pointer to 16 bit signed + + # 16-bit unsigned short types + CvInfoType(key=CvdumpTypeKey(0x0021), name="T_USHORT", fmt="H", size=2, pointer=None, verified=True ), # 16 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0121), name="T_PUSHORT", fmt="H", size=2, pointer=CvdumpTypeKey(0x0021), verified=False), # 16 bit pointer to 16 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0221), name="T_PFUSHORT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0021), verified=False), # 16:16 far pointer to 16 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0321), name="T_PHUSHORT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0021), verified=False), # 16:16 huge pointer to 16 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0421), name="T_32PUSHORT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0021), verified=True ), # 32 bit pointer to 16 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0521), name="T_32PFUSHORT", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0021), verified=False), # 16:32 pointer to 16 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0621), name="T_64PUSHORT", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0021), verified=False), # 64 bit pointer to 16 bit unsigned + + # 16-bit signed int types + CvInfoType(key=CvdumpTypeKey(0x0072), name="T_INT2", fmt="h", size=2, pointer=None, verified=False), # 16 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0172), name="T_PINT2", fmt="H", size=2, pointer=CvdumpTypeKey(0x0072), verified=False), # 16 bit pointer to 16 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0272), name="T_PFINT2", fmt="I", size=4, pointer=CvdumpTypeKey(0x0072), verified=False), # 16:16 far pointer to 16 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0372), name="T_PHINT2", fmt="I", size=4, pointer=CvdumpTypeKey(0x0072), verified=False), # 16:16 huge pointer to 16 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0472), name="T_32PINT2", fmt="I", size=4, pointer=CvdumpTypeKey(0x0072), verified=False), # 32 bit pointer to 16 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0572), name="T_32PFINT2", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0072), verified=False), # 16:32 pointer to 16 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0672), name="T_64PINT2", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0072), verified=False), # 64 bit pointer to 16 bit signed int + + # 16-bit unsigned int types + CvInfoType(key=CvdumpTypeKey(0x0073), name="T_UINT2", fmt="H", size=2, pointer=None, verified=False), # 16 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0173), name="T_PUINT2", fmt="H", size=2, pointer=CvdumpTypeKey(0x0073), verified=False), # 16 bit pointer to 16 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0273), name="T_PFUINT2", fmt="I", size=4, pointer=CvdumpTypeKey(0x0073), verified=False), # 16:16 far pointer to 16 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0373), name="T_PHUINT2", fmt="I", size=4, pointer=CvdumpTypeKey(0x0073), verified=False), # 16:16 huge pointer to 16 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0473), name="T_32PUINT2", fmt="I", size=4, pointer=CvdumpTypeKey(0x0073), verified=False), # 32 bit pointer to 16 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0573), name="T_32PFUINT2", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0073), verified=False), # 16:32 pointer to 16 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0673), name="T_64PUINT2", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0073), verified=False), # 64 bit pointer to 16 bit unsigned int + + # 32-bit signed long types + CvInfoType(key=CvdumpTypeKey(0x0012), name="T_LONG", fmt="l", size=4, pointer=None, verified=True ), # 32 bit signed + CvInfoType(key=CvdumpTypeKey(0x0112), name="T_PLONG", fmt="H", size=2, pointer=CvdumpTypeKey(0x0012), verified=False), # 16 bit pointer to 32 bit signed + CvInfoType(key=CvdumpTypeKey(0x0212), name="T_PFLONG", fmt="I", size=4, pointer=CvdumpTypeKey(0x0012), verified=False), # 16:16 far pointer to 32 bit signed + CvInfoType(key=CvdumpTypeKey(0x0312), name="T_PHLONG", fmt="I", size=4, pointer=CvdumpTypeKey(0x0012), verified=False), # 16:16 huge pointer to 32 bit signed + CvInfoType(key=CvdumpTypeKey(0x0412), name="T_32PLONG", fmt="I", size=4, pointer=CvdumpTypeKey(0x0012), verified=True ), # 32 bit pointer to 32 bit signed + CvInfoType(key=CvdumpTypeKey(0x0512), name="T_32PFLONG", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0012), verified=False), # 16:32 pointer to 32 bit signed + CvInfoType(key=CvdumpTypeKey(0x0612), name="T_64PLONG", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0012), verified=False), # 64 bit pointer to 32 bit signed + + # 32-bit unsigned long types + CvInfoType(key=CvdumpTypeKey(0x0022), name="T_ULONG", fmt="L", size=4, pointer=None, verified=True ), # 32 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0122), name="T_PULONG", fmt="H", size=2, pointer=CvdumpTypeKey(0x0022), verified=False), # 16 bit pointer to 32 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0222), name="T_PFULONG", fmt="I", size=4, pointer=CvdumpTypeKey(0x0022), verified=False), # 16:16 far pointer to 32 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0322), name="T_PHULONG", fmt="I", size=4, pointer=CvdumpTypeKey(0x0022), verified=False), # 16:16 huge pointer to 32 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0422), name="T_32PULONG", fmt="I", size=4, pointer=CvdumpTypeKey(0x0022), verified=True ), # 32 bit pointer to 32 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0522), name="T_32PFULONG", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0022), verified=False), # 16:32 pointer to 32 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0622), name="T_64PULONG", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0022), verified=False), # 64 bit pointer to 32 bit unsigned + + # 32-bit signed int types + CvInfoType(key=CvdumpTypeKey(0x0074), name="T_INT4", fmt="i", size=4, pointer=None, verified=True ), # 32 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0174), name="T_PINT4", fmt="H", size=2, pointer=CvdumpTypeKey(0x0074), verified=False), # 16 bit pointer to 32 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0274), name="T_PFINT4", fmt="I", size=4, pointer=CvdumpTypeKey(0x0074), verified=False), # 16:16 far pointer to 32 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0374), name="T_PHINT4", fmt="I", size=4, pointer=CvdumpTypeKey(0x0074), verified=False), # 16:16 huge pointer to 32 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0474), name="T_32PINT4", fmt="I", size=4, pointer=CvdumpTypeKey(0x0074), verified=True ), # 32 bit pointer to 32 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0574), name="T_32PFINT4", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0074), verified=False), # 16:32 pointer to 32 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0674), name="T_64PINT4", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0074), verified=False), # 64 bit pointer to 32 bit signed int + + # 32-bit unsigned int types + CvInfoType(key=CvdumpTypeKey(0x0075), name="T_UINT4", fmt="I", size=4, pointer=None, verified=True ), # 32 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0175), name="T_PUINT4", fmt="H", size=2, pointer=CvdumpTypeKey(0x0075), verified=False), # 16 bit pointer to 32 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0275), name="T_PFUINT4", fmt="I", size=4, pointer=CvdumpTypeKey(0x0075), verified=False), # 16:16 far pointer to 32 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0375), name="T_PHUINT4", fmt="I", size=4, pointer=CvdumpTypeKey(0x0075), verified=False), # 16:16 huge pointer to 32 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0475), name="T_32PUINT4", fmt="I", size=4, pointer=CvdumpTypeKey(0x0075), verified=True ), # 32 bit pointer to 32 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0575), name="T_32PFUINT4", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0075), verified=False), # 16:32 pointer to 32 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0675), name="T_64PUINT4", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0075), verified=False), # 64 bit pointer to 32 bit unsigned int + + # 64-bit signed quad types + CvInfoType(key=CvdumpTypeKey(0x0013), name="T_QUAD", fmt="q", size=8, pointer=None, verified=True ), # 64 bit signed + CvInfoType(key=CvdumpTypeKey(0x0113), name="T_PQUAD", fmt="H", size=2, pointer=CvdumpTypeKey(0x0013), verified=False), # 16 bit pointer to 64 bit signed + CvInfoType(key=CvdumpTypeKey(0x0213), name="T_PFQUAD", fmt="I", size=4, pointer=CvdumpTypeKey(0x0013), verified=False), # 16:16 far pointer to 64 bit signed + CvInfoType(key=CvdumpTypeKey(0x0313), name="T_PHQUAD", fmt="I", size=4, pointer=CvdumpTypeKey(0x0013), verified=False), # 16:16 huge pointer to 64 bit signed + CvInfoType(key=CvdumpTypeKey(0x0413), name="T_32PQUAD", fmt="I", size=4, pointer=CvdumpTypeKey(0x0013), verified=True ), # 32 bit pointer to 64 bit signed + CvInfoType(key=CvdumpTypeKey(0x0513), name="T_32PFQUAD", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0013), verified=False), # 16:32 pointer to 64 bit signed + CvInfoType(key=CvdumpTypeKey(0x0613), name="T_64PQUAD", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0013), verified=False), # 64 bit pointer to 64 bit signed + + # 64-bit unsigned quad types + CvInfoType(key=CvdumpTypeKey(0x0023), name="T_UQUAD", fmt="Q", size=8, pointer=None, verified=True ), # 64 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0123), name="T_PUQUAD", fmt="H", size=2, pointer=CvdumpTypeKey(0x0023), verified=False), # 16 bit pointer to 64 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0223), name="T_PFUQUAD", fmt="I", size=4, pointer=CvdumpTypeKey(0x0023), verified=False), # 16:16 far pointer to 64 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0323), name="T_PHUQUAD", fmt="I", size=4, pointer=CvdumpTypeKey(0x0023), verified=False), # 16:16 huge pointer to 64 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0423), name="T_32PUQUAD", fmt="I", size=4, pointer=CvdumpTypeKey(0x0023), verified=True ), # 32 bit pointer to 64 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0523), name="T_32PFUQUAD", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0023), verified=False), # 16:32 pointer to 64 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0623), name="T_64PUQUAD", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0023), verified=False), # 64 bit pointer to 64 bit unsigned + + # 64-bit signed int types + CvInfoType(key=CvdumpTypeKey(0x0076), name="T_INT8", fmt="q", size=8, pointer=None, verified=False), # 64 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0176), name="T_PINT8", fmt="H", size=2, pointer=CvdumpTypeKey(0x0076), verified=False), # 16 bit pointer to 64 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0276), name="T_PFINT8", fmt="I", size=4, pointer=CvdumpTypeKey(0x0076), verified=False), # 16:16 far pointer to 64 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0376), name="T_PHINT8", fmt="I", size=4, pointer=CvdumpTypeKey(0x0076), verified=False), # 16:16 huge pointer to 64 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0476), name="T_32PINT8", fmt="I", size=4, pointer=CvdumpTypeKey(0x0076), verified=False), # 32 bit pointer to 64 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0576), name="T_32PFINT8", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0076), verified=False), # 16:32 pointer to 64 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0676), name="T_64PINT8", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0076), verified=False), # 64 bit pointer to 64 bit signed int + + # 64-bit unsigned int types + CvInfoType(key=CvdumpTypeKey(0x0077), name="T_UINT8", fmt="Q", size=8, pointer=None, verified=False), # 64 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0177), name="T_PUINT8", fmt="H", size=2, pointer=CvdumpTypeKey(0x0077), verified=False), # 16 bit pointer to 64 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0277), name="T_PFUINT8", fmt="I", size=4, pointer=CvdumpTypeKey(0x0077), verified=False), # 16:16 far pointer to 64 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0377), name="T_PHUINT8", fmt="I", size=4, pointer=CvdumpTypeKey(0x0077), verified=False), # 16:16 huge pointer to 64 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0477), name="T_32PUINT8", fmt="I", size=4, pointer=CvdumpTypeKey(0x0077), verified=False), # 32 bit pointer to 64 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0577), name="T_32PFUINT8", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0077), verified=False), # 16:32 pointer to 64 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0677), name="T_64PUINT8", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0077), verified=False), # 64 bit pointer to 64 bit unsigned int + + # 128-bit signed octet types + CvInfoType(key=CvdumpTypeKey(0x0014), name="T_OCT", fmt="16B", size=16, pointer=None, verified=False), # 128 bit signed + CvInfoType(key=CvdumpTypeKey(0x0114), name="T_POCT", fmt="H", size=2, pointer=CvdumpTypeKey(0x0014), verified=False), # 16 bit pointer to 128 bit signed + CvInfoType(key=CvdumpTypeKey(0x0214), name="T_PFOCT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0014), verified=False), # 16:16 far pointer to 128 bit signed + CvInfoType(key=CvdumpTypeKey(0x0314), name="T_PHOCT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0014), verified=False), # 16:16 huge pointer to 128 bit signed + CvInfoType(key=CvdumpTypeKey(0x0414), name="T_32POCT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0014), verified=False), # 32 bit pointer to 128 bit signed + CvInfoType(key=CvdumpTypeKey(0x0514), name="T_32PFOCT", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0014), verified=False), # 16:32 pointer to 128 bit signed + CvInfoType(key=CvdumpTypeKey(0x0614), name="T_64POCT", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0014), verified=False), # 64 bit pointer to 128 bit signed + + # 128-bit unsigned octet types + CvInfoType(key=CvdumpTypeKey(0x0024), name="T_UOCT", fmt="16B", size=16, pointer=None, verified=False), # 128 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0124), name="T_PUOCT", fmt="H", size=2, pointer=CvdumpTypeKey(0x0024), verified=False), # 16 bit pointer to 128 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0224), name="T_PFUOCT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0024), verified=False), # 16:16 far pointer to 128 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0324), name="T_PHUOCT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0024), verified=False), # 16:16 huge pointer to 128 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0424), name="T_32PUOCT", fmt="I", size=4, pointer=CvdumpTypeKey(0x0024), verified=False), # 32 bit pointer to 128 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0524), name="T_32PFUOCT", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0024), verified=False), # 16:32 pointer to 128 bit unsigned + CvInfoType(key=CvdumpTypeKey(0x0624), name="T_64PUOCT", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0024), verified=False), # 64 bit pointer to 128 bit unsigned + + # 128-bit signed int types + CvInfoType(key=CvdumpTypeKey(0x0078), name="T_INT16", fmt="16B", size=16, pointer=None, verified=False), # 128 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0178), name="T_PINT16", fmt="H", size=2, pointer=CvdumpTypeKey(0x0078), verified=False), # 16 bit pointer to 128 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0278), name="T_PFINT16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0078), verified=False), # 16:16 far pointer to 128 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0378), name="T_PHINT16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0078), verified=False), # 16:16 huge pointer to 128 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0478), name="T_32PINT16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0078), verified=False), # 32 bit pointer to 128 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0578), name="T_32PFINT16", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0078), verified=False), # 16:32 pointer to 128 bit signed int + CvInfoType(key=CvdumpTypeKey(0x0678), name="T_64PINT16", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0078), verified=False), # 64 bit pointer to 128 bit signed int + + # 128-bit unsigned int types + CvInfoType(key=CvdumpTypeKey(0x0079), name="T_UINT16", fmt="16B", size=16, pointer= None, verified=False), # 128 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0179), name="T_PUINT16", fmt="H", size=2, pointer=CvdumpTypeKey(0x0079), verified=False), # 16 bit pointer to 128 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0279), name="T_PFUINT16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0079), verified=False), # 16:16 far pointer to 128 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0379), name="T_PHUINT16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0079), verified=False), # 16:16 huge pointer to 128 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0479), name="T_32PUINT16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0079), verified=False), # 32 bit pointer to 128 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0579), name="T_32PFUINT16", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0079), verified=False), # 16:32 pointer to 128 bit unsigned int + CvInfoType(key=CvdumpTypeKey(0x0679), name="T_64PUINT16", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0079), verified=False), # 64 bit pointer to 128 bit unsigned int + + # 16-bit real types + CvInfoType(key=CvdumpTypeKey(0x0046), name="T_REAL16", fmt="2B", size=2, pointer=None, verified=False), # 16 bit real + CvInfoType(key=CvdumpTypeKey(0x0146), name="T_PREAL16", fmt="H", size=2, pointer=CvdumpTypeKey(0x0046), verified=False), # 16 bit pointer to 16 bit real + CvInfoType(key=CvdumpTypeKey(0x0246), name="T_PFREAL16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0046), verified=False), # 16:16 far pointer to 16 bit real + CvInfoType(key=CvdumpTypeKey(0x0346), name="T_PHREAL16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0046), verified=False), # 16:16 huge pointer to 16 bit real + CvInfoType(key=CvdumpTypeKey(0x0446), name="T_32PREAL16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0046), verified=False), # 32 bit pointer to 16 bit real + CvInfoType(key=CvdumpTypeKey(0x0546), name="T_32PFREAL16", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0046), verified=False), # 16:32 pointer to 16 bit real + CvInfoType(key=CvdumpTypeKey(0x0646), name="T_64PREAL16", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0046), verified=False), # 64 bit pointer to 16 bit real + + # 32-bit real types + CvInfoType(key=CvdumpTypeKey(0x0040), name="T_REAL32", fmt="f", size=4, pointer=None, verified=True ), # 32 bit real + CvInfoType(key=CvdumpTypeKey(0x0140), name="T_PREAL32", fmt="H", size=2, pointer=CvdumpTypeKey(0x0040), verified=False), # 16 bit pointer to 32 bit real + CvInfoType(key=CvdumpTypeKey(0x0240), name="T_PFREAL32", fmt="I", size=4, pointer=CvdumpTypeKey(0x0040), verified=False), # 16:16 far pointer to 32 bit real + CvInfoType(key=CvdumpTypeKey(0x0340), name="T_PHREAL32", fmt="I", size=4, pointer=CvdumpTypeKey(0x0040), verified=False), # 16:16 huge pointer to 32 bit real + CvInfoType(key=CvdumpTypeKey(0x0440), name="T_32PREAL32", fmt="I", size=4, pointer=CvdumpTypeKey(0x0040), verified=True ), # 32 bit pointer to 32 bit real + CvInfoType(key=CvdumpTypeKey(0x0540), name="T_32PFREAL32", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0040), verified=False), # 16:32 pointer to 32 bit real + CvInfoType(key=CvdumpTypeKey(0x0640), name="T_64PREAL32", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0040), verified=False), # 64 bit pointer to 32 bit real + + # 32-bit partial-precision real types + CvInfoType(key=CvdumpTypeKey(0x0045), name="T_REAL32PP", fmt="4B", size=4, pointer=None, verified=False), # 32 bit PP real + CvInfoType(key=CvdumpTypeKey(0x0145), name="T_PREAL32PP", fmt="H", size=2, pointer=CvdumpTypeKey(0x0045), verified=False), # 16 bit pointer to 32 bit PP real + CvInfoType(key=CvdumpTypeKey(0x0245), name="T_PFREAL32PP", fmt="I", size=4, pointer=CvdumpTypeKey(0x0045), verified=False), # 16:16 far pointer to 32 bit PP real + CvInfoType(key=CvdumpTypeKey(0x0345), name="T_PHREAL32PP", fmt="I", size=4, pointer=CvdumpTypeKey(0x0045), verified=False), # 16:16 huge pointer to 32 bit PP real + CvInfoType(key=CvdumpTypeKey(0x0445), name="T_32PREAL32PP", fmt="I", size=4, pointer=CvdumpTypeKey(0x0045), verified=False), # 32 bit pointer to 32 bit PP real + CvInfoType(key=CvdumpTypeKey(0x0545), name="T_32PFREAL32PP", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0045), verified=False), # 16:32 pointer to 32 bit PP real + CvInfoType(key=CvdumpTypeKey(0x0645), name="T_64PREAL32PP", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0045), verified=False), # 64 bit pointer to 32 bit PP real + + # 48-bit real types + CvInfoType(key=CvdumpTypeKey(0x0044), name="T_REAL48", fmt="6B", size=6, pointer=None, verified=False), # 48 bit real + CvInfoType(key=CvdumpTypeKey(0x0144), name="T_PREAL48", fmt="H", size=2, pointer=CvdumpTypeKey(0x0044), verified=False), # 16 bit pointer to 48 bit real + CvInfoType(key=CvdumpTypeKey(0x0244), name="T_PFREAL48", fmt="I", size=4, pointer=CvdumpTypeKey(0x0044), verified=False), # 16:16 far pointer to 48 bit real + CvInfoType(key=CvdumpTypeKey(0x0344), name="T_PHREAL48", fmt="I", size=4, pointer=CvdumpTypeKey(0x0044), verified=False), # 16:16 huge pointer to 48 bit real + CvInfoType(key=CvdumpTypeKey(0x0444), name="T_32PREAL48", fmt="I", size=4, pointer=CvdumpTypeKey(0x0044), verified=False), # 32 bit pointer to 48 bit real + CvInfoType(key=CvdumpTypeKey(0x0544), name="T_32PFREAL48", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0044), verified=False), # 16:32 pointer to 48 bit real + CvInfoType(key=CvdumpTypeKey(0x0644), name="T_64PREAL48", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0044), verified=False), # 64 bit pointer to 48 bit real + + # 64-bit real types + CvInfoType(key=CvdumpTypeKey(0x0041), name="T_REAL64", fmt="d", size=8, pointer=None, verified=True ), # 64 bit real + CvInfoType(key=CvdumpTypeKey(0x0141), name="T_PREAL64", fmt="H", size=2, pointer=CvdumpTypeKey(0x0041), verified=False), # 16 bit pointer to 64 bit real + CvInfoType(key=CvdumpTypeKey(0x0241), name="T_PFREAL64", fmt="I", size=4, pointer=CvdumpTypeKey(0x0041), verified=False), # 16:16 far pointer to 64 bit real + CvInfoType(key=CvdumpTypeKey(0x0341), name="T_PHREAL64", fmt="I", size=4, pointer=CvdumpTypeKey(0x0041), verified=False), # 16:16 huge pointer to 64 bit real + CvInfoType(key=CvdumpTypeKey(0x0441), name="T_32PREAL64", fmt="I", size=4, pointer=CvdumpTypeKey(0x0041), verified=True ), # 32 bit pointer to 64 bit real + CvInfoType(key=CvdumpTypeKey(0x0541), name="T_32PFREAL64", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0041), verified=False), # 16:32 pointer to 64 bit real + CvInfoType(key=CvdumpTypeKey(0x0641), name="T_64PREAL64", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0041), verified=False), # 64 bit pointer to 64 bit real + + # 80-bit real types + CvInfoType(key=CvdumpTypeKey(0x0042), name="T_REAL80", fmt="10B", size=10, pointer=None, verified=False), # 80 bit real + CvInfoType(key=CvdumpTypeKey(0x0142), name="T_PREAL80", fmt="H", size=2, pointer=CvdumpTypeKey(0x0042), verified=False), # 16 bit pointer to 80 bit real + CvInfoType(key=CvdumpTypeKey(0x0242), name="T_PFREAL80", fmt="I", size=4, pointer=CvdumpTypeKey(0x0042), verified=False), # 16:16 far pointer to 80 bit real + CvInfoType(key=CvdumpTypeKey(0x0342), name="T_PHREAL80", fmt="I", size=4, pointer=CvdumpTypeKey(0x0042), verified=False), # 16:16 huge pointer to 80 bit real + CvInfoType(key=CvdumpTypeKey(0x0442), name="T_32PREAL80", fmt="I", size=4, pointer=CvdumpTypeKey(0x0042), verified=False), # 32 bit pointer to 80 bit real + CvInfoType(key=CvdumpTypeKey(0x0542), name="T_32PFREAL80", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0042), verified=False), # 16:32 pointer to 80 bit real + CvInfoType(key=CvdumpTypeKey(0x0642), name="T_64PREAL80", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0042), verified=False), # 64 bit pointer to 80 bit real + + # 128-bit real types + CvInfoType(key=CvdumpTypeKey(0x0043), name="T_REAL128", fmt="16B", size=16, pointer=None, verified=False), # 128 bit real + CvInfoType(key=CvdumpTypeKey(0x0143), name="T_PREAL128", fmt="H", size=2, pointer=CvdumpTypeKey(0x0043), verified=False), # 16 bit pointer to 128 bit real + CvInfoType(key=CvdumpTypeKey(0x0243), name="T_PFREAL128", fmt="I", size=4, pointer=CvdumpTypeKey(0x0043), verified=False), # 16:16 far pointer to 128 bit real + CvInfoType(key=CvdumpTypeKey(0x0343), name="T_PHREAL128", fmt="I", size=4, pointer=CvdumpTypeKey(0x0043), verified=False), # 16:16 huge pointer to 128 bit real + CvInfoType(key=CvdumpTypeKey(0x0443), name="T_32PREAL128", fmt="I", size=4, pointer=CvdumpTypeKey(0x0043), verified=False), # 32 bit pointer to 128 bit real + CvInfoType(key=CvdumpTypeKey(0x0543), name="T_32PFREAL128", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0043), verified=False), # 16:32 pointer to 128 bit real + CvInfoType(key=CvdumpTypeKey(0x0643), name="T_64PREAL128", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0043), verified=False), # 64 bit pointer to 128 bit real + + # 32-bit complex types + CvInfoType(key=CvdumpTypeKey(0x0050), name="T_CPLX32", fmt="4B", size=4, pointer=None, verified=False), # 32 bit complex + CvInfoType(key=CvdumpTypeKey(0x0150), name="T_PCPLX32", fmt="H", size=2, pointer=CvdumpTypeKey(0x0050), verified=False), # 16 bit pointer to 32 bit complex + CvInfoType(key=CvdumpTypeKey(0x0250), name="T_PFCPLX32", fmt="I", size=4, pointer=CvdumpTypeKey(0x0050), verified=False), # 16:16 far pointer to 32 bit complex + CvInfoType(key=CvdumpTypeKey(0x0350), name="T_PHCPLX32", fmt="I", size=4, pointer=CvdumpTypeKey(0x0050), verified=False), # 16:16 huge pointer to 32 bit complex + CvInfoType(key=CvdumpTypeKey(0x0450), name="T_32PCPLX32", fmt="I", size=4, pointer=CvdumpTypeKey(0x0050), verified=False), # 32 bit pointer to 32 bit complex + CvInfoType(key=CvdumpTypeKey(0x0550), name="T_32PFCPLX32", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0050), verified=False), # 16:32 pointer to 32 bit complex + CvInfoType(key=CvdumpTypeKey(0x0650), name="T_64PCPLX32", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0050), verified=False), # 64 bit pointer to 32 bit complex + + # 64-bit complex types + CvInfoType(key=CvdumpTypeKey(0x0051), name="T_CPLX64", fmt="F", size=8, pointer=None, verified=False), # 64 bit complex + CvInfoType(key=CvdumpTypeKey(0x0151), name="T_PCPLX64", fmt="H", size=2, pointer=CvdumpTypeKey(0x0051), verified=False), # 16 bit pointer to 64 bit complex + CvInfoType(key=CvdumpTypeKey(0x0251), name="T_PFCPLX64", fmt="I", size=4, pointer=CvdumpTypeKey(0x0051), verified=False), # 16:16 far pointer to 64 bit complex + CvInfoType(key=CvdumpTypeKey(0x0351), name="T_PHCPLX64", fmt="I", size=4, pointer=CvdumpTypeKey(0x0051), verified=False), # 16:16 huge pointer to 64 bit complex + CvInfoType(key=CvdumpTypeKey(0x0451), name="T_32PCPLX64", fmt="I", size=4, pointer=CvdumpTypeKey(0x0051), verified=False), # 32 bit pointer to 64 bit complex + CvInfoType(key=CvdumpTypeKey(0x0551), name="T_32PFCPLX64", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0051), verified=False), # 16:32 pointer to 64 bit complex + CvInfoType(key=CvdumpTypeKey(0x0651), name="T_64PCPLX64", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0051), verified=False), # 64 bit pointer to 64 bit complex + + # 80-bit complex types + CvInfoType(key=CvdumpTypeKey(0x0052), name="T_CPLX80", fmt="10B", size=10, pointer=None, verified=False), # 80 bit complex + CvInfoType(key=CvdumpTypeKey(0x0152), name="T_PCPLX80", fmt="H", size=2, pointer=CvdumpTypeKey(0x0052), verified=False), # 16 bit pointer to 80 bit complex + CvInfoType(key=CvdumpTypeKey(0x0252), name="T_PFCPLX80", fmt="I", size=4, pointer=CvdumpTypeKey(0x0052), verified=False), # 16:16 far pointer to 80 bit complex + CvInfoType(key=CvdumpTypeKey(0x0352), name="T_PHCPLX80", fmt="I", size=4, pointer=CvdumpTypeKey(0x0052), verified=False), # 16:16 huge pointer to 80 bit complex + CvInfoType(key=CvdumpTypeKey(0x0452), name="T_32PCPLX80", fmt="I", size=4, pointer=CvdumpTypeKey(0x0052), verified=False), # 32 bit pointer to 80 bit complex + CvInfoType(key=CvdumpTypeKey(0x0552), name="T_32PFCPLX80", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0052), verified=False), # 16:32 pointer to 80 bit complex + CvInfoType(key=CvdumpTypeKey(0x0652), name="T_64PCPLX80", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0052), verified=False), # 64 bit pointer to 80 bit complex + + # 128-bit complex types + CvInfoType(key=CvdumpTypeKey(0x0053), name="T_CPLX128", fmt="D", size=16, pointer=None, verified=False), # 128 bit complex + CvInfoType(key=CvdumpTypeKey(0x0153), name="T_PCPLX128", fmt="H", size=2, pointer=CvdumpTypeKey(0x0053), verified=False), # 16 bit pointer to 128 bit complex + CvInfoType(key=CvdumpTypeKey(0x0253), name="T_PFCPLX128", fmt="I", size=4, pointer=CvdumpTypeKey(0x0053), verified=False), # 16:16 far pointer to 128 bit complex + CvInfoType(key=CvdumpTypeKey(0x0353), name="T_PHCPLX128", fmt="I", size=4, pointer=CvdumpTypeKey(0x0053), verified=False), # 16:16 huge pointer to 128 bit real + CvInfoType(key=CvdumpTypeKey(0x0453), name="T_32PCPLX128", fmt="I", size=4, pointer=CvdumpTypeKey(0x0053), verified=False), # 32 bit pointer to 128 bit complex + CvInfoType(key=CvdumpTypeKey(0x0553), name="T_32PFCPLX128", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0053), verified=False), # 16:32 pointer to 128 bit complex + CvInfoType(key=CvdumpTypeKey(0x0653), name="T_64PCPLX128", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0053), verified=False), # 64 bit pointer to 128 bit complex + + # 8-bit boolean types + CvInfoType(key=CvdumpTypeKey(0x0030), name="T_BOOL08", fmt="B", size=1, pointer=None, verified=False), # 8 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0130), name="T_PBOOL08", fmt="H", size=2, pointer=CvdumpTypeKey(0x0030), verified=False), # 16 bit pointer to 8 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0230), name="T_PFBOOL08", fmt="I", size=4, pointer=CvdumpTypeKey(0x0030), verified=False), # 16:16 far pointer to 8 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0330), name="T_PHBOOL08", fmt="I", size=4, pointer=CvdumpTypeKey(0x0030), verified=False), # 16:16 huge pointer to 8 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0430), name="T_32PBOOL08", fmt="I", size=4, pointer=CvdumpTypeKey(0x0030), verified=False), # 32 bit pointer to 8 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0530), name="T_32PFBOOL08", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0030), verified=False), # 16:32 pointer to 8 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0630), name="T_64PBOOL08", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0030), verified=False), # 64 bit pointer to 8 bit boolean + + # 16-bit boolean types + CvInfoType(key=CvdumpTypeKey(0x0031), name="T_BOOL16", fmt="H", size=2, pointer=None, verified=False), # 16 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0131), name="T_PBOOL16", fmt="H", size=2, pointer=CvdumpTypeKey(0x0031), verified=False), # 16 bit pointer to 16 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0231), name="T_PFBOOL16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0031), verified=False), # 16:16 far pointer to 16 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0331), name="T_PHBOOL16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0031), verified=False), # 16:16 huge pointer to 16 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0431), name="T_32PBOOL16", fmt="I", size=4, pointer=CvdumpTypeKey(0x0031), verified=False), # 32 bit pointer to 18 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0531), name="T_32PFBOOL16", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0031), verified=False), # 16:32 pointer to 16 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0631), name="T_64PBOOL16", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0031), verified=False), # 64 bit pointer to 18 bit boolean + + # 32-bit boolean types + CvInfoType(key=CvdumpTypeKey(0x0032), name="T_BOOL32", fmt="I", size=4, pointer=None, verified=False), # 32 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0132), name="T_PBOOL32", fmt="H", size=2, pointer=CvdumpTypeKey(0x0032), verified=False), # 16 bit pointer to 32 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0232), name="T_PFBOOL32", fmt="I", size=4, pointer=CvdumpTypeKey(0x0032), verified=False), # 16:16 far pointer to 32 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0332), name="T_PHBOOL32", fmt="I", size=4, pointer=CvdumpTypeKey(0x0032), verified=False), # 16:16 huge pointer to 32 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0432), name="T_32PBOOL32", fmt="I", size=4, pointer=CvdumpTypeKey(0x0032), verified=False), # 32 bit pointer to 32 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0532), name="T_32PFBOOL32", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0032), verified=False), # 16:32 pointer to 32 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0632), name="T_64PBOOL32", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0032), verified=False), # 64 bit pointer to 32 bit boolean + + # 64-bit boolean types + CvInfoType(key=CvdumpTypeKey(0x0033), name="T_BOOL64", fmt="Q", size=8, pointer=None, verified=False), # 64 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0133), name="T_PBOOL64", fmt="H", size=2, pointer=CvdumpTypeKey(0x0033), verified=False), # 16 bit pointer to 64 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0233), name="T_PFBOOL64", fmt="I", size=4, pointer=CvdumpTypeKey(0x0033), verified=False), # 16:16 far pointer to 64 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0333), name="T_PHBOOL64", fmt="I", size=4, pointer=CvdumpTypeKey(0x0033), verified=False), # 16:16 huge pointer to 64 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0433), name="T_32PBOOL64", fmt="I", size=4, pointer=CvdumpTypeKey(0x0033), verified=False), # 32 bit pointer to 64 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0533), name="T_32PFBOOL64", fmt="6x", size=6, pointer=CvdumpTypeKey(0x0033), verified=False), # 16:32 pointer to 64 bit boolean + CvInfoType(key=CvdumpTypeKey(0x0633), name="T_64PBOOL64", fmt="Q", size=8, pointer=CvdumpTypeKey(0x0033), verified=False), # 64 bit pointer to 64 bit boolean + + # Internal CV types + CvInfoType(key=CvdumpTypeKey(0x01f0), name="T_NCVPTR", fmt="", size=0, pointer=None, verified=False), # CV Internal type for created near pointers + CvInfoType(key=CvdumpTypeKey(0x02f0), name="T_FCVPTR", fmt="", size=0, pointer=None, verified=False), # CV Internal type for created far pointers + CvInfoType(key=CvdumpTypeKey(0x03f0), name="T_HCVPTR", fmt="", size=0, pointer=None, verified=False), # CV Internal type for created huge pointers + CvInfoType(key=CvdumpTypeKey(0x04f0), name="T_32NCVPTR", fmt="", size=0, pointer=None, verified=False), # CV Internal type for created near 32-bit pointers + CvInfoType(key=CvdumpTypeKey(0x05f0), name="T_32FCVPTR", fmt="", size=0, pointer=None, verified=False), # CV Internal type for created far 32-bit pointers + CvInfoType(key=CvdumpTypeKey(0x06f0), name="T_64NCVPTR", fmt="", size=0, pointer=None, verified=False), # CV Internal type for created near 64-bit pointers +) +# fmt: on + + +class CVInfoTypeEnum(CvdumpTypeKey, Enum): + # fmt: off + T_NOTYPE = CvdumpTypeKey(0x0000) + T_ABS = CvdumpTypeKey(0x0001) + T_SEGMENT = CvdumpTypeKey(0x0002) + T_VOID = CvdumpTypeKey(0x0003) + T_CURRENCY = CvdumpTypeKey(0x0004) + T_NBASICSTR = CvdumpTypeKey(0x0005) + T_FBASICSTR = CvdumpTypeKey(0x0006) + T_NOTTRANS = CvdumpTypeKey(0x0007) + T_HRESULT = CvdumpTypeKey(0x0008) + T_CHAR = CvdumpTypeKey(0x0010) + T_SHORT = CvdumpTypeKey(0x0011) + T_LONG = CvdumpTypeKey(0x0012) + T_QUAD = CvdumpTypeKey(0x0013) + T_OCT = CvdumpTypeKey(0x0014) + T_UCHAR = CvdumpTypeKey(0x0020) + T_USHORT = CvdumpTypeKey(0x0021) + T_ULONG = CvdumpTypeKey(0x0022) + T_UQUAD = CvdumpTypeKey(0x0023) + T_UOCT = CvdumpTypeKey(0x0024) + T_BOOL08 = CvdumpTypeKey(0x0030) + T_BOOL16 = CvdumpTypeKey(0x0031) + T_BOOL32 = CvdumpTypeKey(0x0032) + T_BOOL64 = CvdumpTypeKey(0x0033) + T_REAL32 = CvdumpTypeKey(0x0040) + T_REAL64 = CvdumpTypeKey(0x0041) + T_REAL80 = CvdumpTypeKey(0x0042) + T_REAL128 = CvdumpTypeKey(0x0043) + T_REAL48 = CvdumpTypeKey(0x0044) + T_REAL32PP = CvdumpTypeKey(0x0045) + T_REAL16 = CvdumpTypeKey(0x0046) + T_CPLX32 = CvdumpTypeKey(0x0050) + T_CPLX64 = CvdumpTypeKey(0x0051) + T_CPLX80 = CvdumpTypeKey(0x0052) + T_CPLX128 = CvdumpTypeKey(0x0053) + T_BIT = CvdumpTypeKey(0x0060) + T_PASCHAR = CvdumpTypeKey(0x0061) + T_BOOL32FF = CvdumpTypeKey(0x0062) + T_INT1 = CvdumpTypeKey(0x0068) + T_UINT1 = CvdumpTypeKey(0x0069) + T_RCHAR = CvdumpTypeKey(0x0070) + T_WCHAR = CvdumpTypeKey(0x0071) + T_INT2 = CvdumpTypeKey(0x0072) + T_UINT2 = CvdumpTypeKey(0x0073) + T_INT4 = CvdumpTypeKey(0x0074) + T_UINT4 = CvdumpTypeKey(0x0075) + T_INT8 = CvdumpTypeKey(0x0076) + T_UINT8 = CvdumpTypeKey(0x0077) + T_INT16 = CvdumpTypeKey(0x0078) + T_UINT16 = CvdumpTypeKey(0x0079) + T_CHAR16 = CvdumpTypeKey(0x007a) + T_CHAR32 = CvdumpTypeKey(0x007b) + T_CHAR8 = CvdumpTypeKey(0x007c) + T_PVOID = CvdumpTypeKey(0x0103) + T_PCHAR = CvdumpTypeKey(0x0110) + T_PSHORT = CvdumpTypeKey(0x0111) + T_PLONG = CvdumpTypeKey(0x0112) + T_PQUAD = CvdumpTypeKey(0x0113) + T_POCT = CvdumpTypeKey(0x0114) + T_PUCHAR = CvdumpTypeKey(0x0120) + T_PUSHORT = CvdumpTypeKey(0x0121) + T_PULONG = CvdumpTypeKey(0x0122) + T_PUQUAD = CvdumpTypeKey(0x0123) + T_PUOCT = CvdumpTypeKey(0x0124) + T_PBOOL08 = CvdumpTypeKey(0x0130) + T_PBOOL16 = CvdumpTypeKey(0x0131) + T_PBOOL32 = CvdumpTypeKey(0x0132) + T_PBOOL64 = CvdumpTypeKey(0x0133) + T_PREAL32 = CvdumpTypeKey(0x0140) + T_PREAL64 = CvdumpTypeKey(0x0141) + T_PREAL80 = CvdumpTypeKey(0x0142) + T_PREAL128 = CvdumpTypeKey(0x0143) + T_PREAL48 = CvdumpTypeKey(0x0144) + T_PREAL32PP = CvdumpTypeKey(0x0145) + T_PREAL16 = CvdumpTypeKey(0x0146) + T_PCPLX32 = CvdumpTypeKey(0x0150) + T_PCPLX64 = CvdumpTypeKey(0x0151) + T_PCPLX80 = CvdumpTypeKey(0x0152) + T_PCPLX128 = CvdumpTypeKey(0x0153) + T_PINT1 = CvdumpTypeKey(0x0168) + T_PUINT1 = CvdumpTypeKey(0x0169) + T_PRCHAR = CvdumpTypeKey(0x0170) + T_PWCHAR = CvdumpTypeKey(0x0171) + T_PINT2 = CvdumpTypeKey(0x0172) + T_PUINT2 = CvdumpTypeKey(0x0173) + T_PINT4 = CvdumpTypeKey(0x0174) + T_PUINT4 = CvdumpTypeKey(0x0175) + T_PINT8 = CvdumpTypeKey(0x0176) + T_PUINT8 = CvdumpTypeKey(0x0177) + T_PINT16 = CvdumpTypeKey(0x0178) + T_PUINT16 = CvdumpTypeKey(0x0179) + T_PCHAR16 = CvdumpTypeKey(0x017a) + T_PCHAR32 = CvdumpTypeKey(0x017b) + T_PCHAR8 = CvdumpTypeKey(0x017c) + T_NCVPTR = CvdumpTypeKey(0x01f0) + T_PFVOID = CvdumpTypeKey(0x0203) + T_PFCHAR = CvdumpTypeKey(0x0210) + T_PFSHORT = CvdumpTypeKey(0x0211) + T_PFLONG = CvdumpTypeKey(0x0212) + T_PFQUAD = CvdumpTypeKey(0x0213) + T_PFOCT = CvdumpTypeKey(0x0214) + T_PFUCHAR = CvdumpTypeKey(0x0220) + T_PFUSHORT = CvdumpTypeKey(0x0221) + T_PFULONG = CvdumpTypeKey(0x0222) + T_PFUQUAD = CvdumpTypeKey(0x0223) + T_PFUOCT = CvdumpTypeKey(0x0224) + T_PFBOOL08 = CvdumpTypeKey(0x0230) + T_PFBOOL16 = CvdumpTypeKey(0x0231) + T_PFBOOL32 = CvdumpTypeKey(0x0232) + T_PFBOOL64 = CvdumpTypeKey(0x0233) + T_PFREAL32 = CvdumpTypeKey(0x0240) + T_PFREAL64 = CvdumpTypeKey(0x0241) + T_PFREAL80 = CvdumpTypeKey(0x0242) + T_PFREAL128 = CvdumpTypeKey(0x0243) + T_PFREAL48 = CvdumpTypeKey(0x0244) + T_PFREAL32PP = CvdumpTypeKey(0x0245) + T_PFREAL16 = CvdumpTypeKey(0x0246) + T_PFCPLX32 = CvdumpTypeKey(0x0250) + T_PFCPLX64 = CvdumpTypeKey(0x0251) + T_PFCPLX80 = CvdumpTypeKey(0x0252) + T_PFCPLX128 = CvdumpTypeKey(0x0253) + T_PFINT1 = CvdumpTypeKey(0x0268) + T_PFUINT1 = CvdumpTypeKey(0x0269) + T_PFRCHAR = CvdumpTypeKey(0x0270) + T_PFWCHAR = CvdumpTypeKey(0x0271) + T_PFINT2 = CvdumpTypeKey(0x0272) + T_PFUINT2 = CvdumpTypeKey(0x0273) + T_PFINT4 = CvdumpTypeKey(0x0274) + T_PFUINT4 = CvdumpTypeKey(0x0275) + T_PFINT8 = CvdumpTypeKey(0x0276) + T_PFUINT8 = CvdumpTypeKey(0x0277) + T_PFINT16 = CvdumpTypeKey(0x0278) + T_PFUINT16 = CvdumpTypeKey(0x0279) + T_PFCHAR16 = CvdumpTypeKey(0x027a) + T_PFCHAR32 = CvdumpTypeKey(0x027b) + T_PFCHAR8 = CvdumpTypeKey(0x027c) + T_FCVPTR = CvdumpTypeKey(0x02f0) + T_PHVOID = CvdumpTypeKey(0x0303) + T_PHCHAR = CvdumpTypeKey(0x0310) + T_PHSHORT = CvdumpTypeKey(0x0311) + T_PHLONG = CvdumpTypeKey(0x0312) + T_PHQUAD = CvdumpTypeKey(0x0313) + T_PHOCT = CvdumpTypeKey(0x0314) + T_PHUCHAR = CvdumpTypeKey(0x0320) + T_PHUSHORT = CvdumpTypeKey(0x0321) + T_PHULONG = CvdumpTypeKey(0x0322) + T_PHUQUAD = CvdumpTypeKey(0x0323) + T_PHUOCT = CvdumpTypeKey(0x0324) + T_PHBOOL08 = CvdumpTypeKey(0x0330) + T_PHBOOL16 = CvdumpTypeKey(0x0331) + T_PHBOOL32 = CvdumpTypeKey(0x0332) + T_PHBOOL64 = CvdumpTypeKey(0x0333) + T_PHREAL32 = CvdumpTypeKey(0x0340) + T_PHREAL64 = CvdumpTypeKey(0x0341) + T_PHREAL80 = CvdumpTypeKey(0x0342) + T_PHREAL128 = CvdumpTypeKey(0x0343) + T_PHREAL48 = CvdumpTypeKey(0x0344) + T_PHREAL32PP = CvdumpTypeKey(0x0345) + T_PHREAL16 = CvdumpTypeKey(0x0346) + T_PHCPLX32 = CvdumpTypeKey(0x0350) + T_PHCPLX64 = CvdumpTypeKey(0x0351) + T_PHCPLX80 = CvdumpTypeKey(0x0352) + T_PHCPLX128 = CvdumpTypeKey(0x0353) + T_PHINT1 = CvdumpTypeKey(0x0368) + T_PHUINT1 = CvdumpTypeKey(0x0369) + T_PHRCHAR = CvdumpTypeKey(0x0370) + T_PHWCHAR = CvdumpTypeKey(0x0371) + T_PHINT2 = CvdumpTypeKey(0x0372) + T_PHUINT2 = CvdumpTypeKey(0x0373) + T_PHINT4 = CvdumpTypeKey(0x0374) + T_PHUINT4 = CvdumpTypeKey(0x0375) + T_PHINT8 = CvdumpTypeKey(0x0376) + T_PHUINT8 = CvdumpTypeKey(0x0377) + T_PHINT16 = CvdumpTypeKey(0x0378) + T_PHUINT16 = CvdumpTypeKey(0x0379) + T_PHCHAR16 = CvdumpTypeKey(0x037a) + T_PHCHAR32 = CvdumpTypeKey(0x037b) + T_PHCHAR8 = CvdumpTypeKey(0x037c) + T_HCVPTR = CvdumpTypeKey(0x03f0) + T_32PVOID = CvdumpTypeKey(0x0403) + T_32PHRESULT = CvdumpTypeKey(0x0408) + T_32PCHAR = CvdumpTypeKey(0x0410) + T_32PSHORT = CvdumpTypeKey(0x0411) + T_32PLONG = CvdumpTypeKey(0x0412) + T_32PQUAD = CvdumpTypeKey(0x0413) + T_32POCT = CvdumpTypeKey(0x0414) + T_32PUCHAR = CvdumpTypeKey(0x0420) + T_32PUSHORT = CvdumpTypeKey(0x0421) + T_32PULONG = CvdumpTypeKey(0x0422) + T_32PUQUAD = CvdumpTypeKey(0x0423) + T_32PUOCT = CvdumpTypeKey(0x0424) + T_32PBOOL08 = CvdumpTypeKey(0x0430) + T_32PBOOL16 = CvdumpTypeKey(0x0431) + T_32PBOOL32 = CvdumpTypeKey(0x0432) + T_32PBOOL64 = CvdumpTypeKey(0x0433) + T_32PREAL32 = CvdumpTypeKey(0x0440) + T_32PREAL64 = CvdumpTypeKey(0x0441) + T_32PREAL80 = CvdumpTypeKey(0x0442) + T_32PREAL128 = CvdumpTypeKey(0x0443) + T_32PREAL48 = CvdumpTypeKey(0x0444) + T_32PREAL32PP = CvdumpTypeKey(0x0445) + T_32PREAL16 = CvdumpTypeKey(0x0446) + T_32PCPLX32 = CvdumpTypeKey(0x0450) + T_32PCPLX64 = CvdumpTypeKey(0x0451) + T_32PCPLX80 = CvdumpTypeKey(0x0452) + T_32PCPLX128 = CvdumpTypeKey(0x0453) + T_32PINT1 = CvdumpTypeKey(0x0468) + T_32PUINT1 = CvdumpTypeKey(0x0469) + T_32PRCHAR = CvdumpTypeKey(0x0470) + T_32PWCHAR = CvdumpTypeKey(0x0471) + T_32PINT2 = CvdumpTypeKey(0x0472) + T_32PUINT2 = CvdumpTypeKey(0x0473) + T_32PINT4 = CvdumpTypeKey(0x0474) + T_32PUINT4 = CvdumpTypeKey(0x0475) + T_32PINT8 = CvdumpTypeKey(0x0476) + T_32PUINT8 = CvdumpTypeKey(0x0477) + T_32PINT16 = CvdumpTypeKey(0x0478) + T_32PUINT16 = CvdumpTypeKey(0x0479) + T_32PCHAR16 = CvdumpTypeKey(0x047a) + T_32PCHAR32 = CvdumpTypeKey(0x047b) + T_32PCHAR8 = CvdumpTypeKey(0x047c) + T_32NCVPTR = CvdumpTypeKey(0x04f0) + T_32PFVOID = CvdumpTypeKey(0x0503) + T_32PFCHAR = CvdumpTypeKey(0x0510) + T_32PFSHORT = CvdumpTypeKey(0x0511) + T_32PFLONG = CvdumpTypeKey(0x0512) + T_32PFQUAD = CvdumpTypeKey(0x0513) + T_32PFOCT = CvdumpTypeKey(0x0514) + T_32PFUCHAR = CvdumpTypeKey(0x0520) + T_32PFUSHORT = CvdumpTypeKey(0x0521) + T_32PFULONG = CvdumpTypeKey(0x0522) + T_32PFUQUAD = CvdumpTypeKey(0x0523) + T_32PFUOCT = CvdumpTypeKey(0x0524) + T_32PFBOOL08 = CvdumpTypeKey(0x0530) + T_32PFBOOL16 = CvdumpTypeKey(0x0531) + T_32PFBOOL32 = CvdumpTypeKey(0x0532) + T_32PFBOOL64 = CvdumpTypeKey(0x0533) + T_32PFREAL32 = CvdumpTypeKey(0x0540) + T_32PFREAL64 = CvdumpTypeKey(0x0541) + T_32PFREAL80 = CvdumpTypeKey(0x0542) + T_32PFREAL128 = CvdumpTypeKey(0x0543) + T_32PFREAL48 = CvdumpTypeKey(0x0544) + T_32PFREAL32PP= CvdumpTypeKey(0x0545) + T_32PFREAL16 = CvdumpTypeKey(0x0546) + T_32PFCPLX32 = CvdumpTypeKey(0x0550) + T_32PFCPLX64 = CvdumpTypeKey(0x0551) + T_32PFCPLX80 = CvdumpTypeKey(0x0552) + T_32PFCPLX128 = CvdumpTypeKey(0x0553) + T_32PFINT1 = CvdumpTypeKey(0x0568) + T_32PFUINT1 = CvdumpTypeKey(0x0569) + T_32PFRCHAR = CvdumpTypeKey(0x0570) + T_32PFWCHAR = CvdumpTypeKey(0x0571) + T_32PFINT2 = CvdumpTypeKey(0x0572) + T_32PFUINT2 = CvdumpTypeKey(0x0573) + T_32PFINT4 = CvdumpTypeKey(0x0574) + T_32PFUINT4 = CvdumpTypeKey(0x0575) + T_32PFINT8 = CvdumpTypeKey(0x0576) + T_32PFUINT8 = CvdumpTypeKey(0x0577) + T_32PFINT16 = CvdumpTypeKey(0x0578) + T_32PFUINT16 = CvdumpTypeKey(0x0579) + T_32PFCHAR16 = CvdumpTypeKey(0x057a) + T_32PFCHAR32 = CvdumpTypeKey(0x057b) + T_32PFCHAR8 = CvdumpTypeKey(0x057c) + T_32FCVPTR = CvdumpTypeKey(0x05f0) + T_64PVOID = CvdumpTypeKey(0x0603) + T_64PHRESULT = CvdumpTypeKey(0x0608) + T_64PCHAR = CvdumpTypeKey(0x0610) + T_64PSHORT = CvdumpTypeKey(0x0611) + T_64PLONG = CvdumpTypeKey(0x0612) + T_64PQUAD = CvdumpTypeKey(0x0613) + T_64POCT = CvdumpTypeKey(0x0614) + T_64PUCHAR = CvdumpTypeKey(0x0620) + T_64PUSHORT = CvdumpTypeKey(0x0621) + T_64PULONG = CvdumpTypeKey(0x0622) + T_64PUQUAD = CvdumpTypeKey(0x0623) + T_64PUOCT = CvdumpTypeKey(0x0624) + T_64PBOOL08 = CvdumpTypeKey(0x0630) + T_64PBOOL16 = CvdumpTypeKey(0x0631) + T_64PBOOL32 = CvdumpTypeKey(0x0632) + T_64PBOOL64 = CvdumpTypeKey(0x0633) + T_64PREAL32 = CvdumpTypeKey(0x0640) + T_64PREAL64 = CvdumpTypeKey(0x0641) + T_64PREAL80 = CvdumpTypeKey(0x0642) + T_64PREAL128 = CvdumpTypeKey(0x0643) + T_64PREAL48 = CvdumpTypeKey(0x0644) + T_64PREAL32PP = CvdumpTypeKey(0x0645) + T_64PREAL16 = CvdumpTypeKey(0x0646) + T_64PCPLX32 = CvdumpTypeKey(0x0650) + T_64PCPLX64 = CvdumpTypeKey(0x0651) + T_64PCPLX80 = CvdumpTypeKey(0x0652) + T_64PCPLX128 = CvdumpTypeKey(0x0653) + T_64PINT1 = CvdumpTypeKey(0x0668) + T_64PUINT1 = CvdumpTypeKey(0x0669) + T_64PRCHAR = CvdumpTypeKey(0x0670) + T_64PWCHAR = CvdumpTypeKey(0x0671) + T_64PINT2 = CvdumpTypeKey(0x0672) + T_64PUINT2 = CvdumpTypeKey(0x0673) + T_64PINT4 = CvdumpTypeKey(0x0674) + T_64PUINT4 = CvdumpTypeKey(0x0675) + T_64PINT8 = CvdumpTypeKey(0x0676) + T_64PUINT8 = CvdumpTypeKey(0x0677) + T_64PINT16 = CvdumpTypeKey(0x0678) + T_64PUINT16 = CvdumpTypeKey(0x0679) + T_64PCHAR16 = CvdumpTypeKey(0x067a) + T_64PCHAR32 = CvdumpTypeKey(0x067b) + T_64PCHAR8 = CvdumpTypeKey(0x067c) + T_64NCVPTR = CvdumpTypeKey(0x06f0) + # fmt: on + + +CvdumpTypeMap = MappingProxyType({cv.key: cv for cv in _CVINFO_TYPES}) diff --git a/reccmp/cvdump/parser.py b/reccmp/cvdump/parser.py index 2d167691..14f42e9d 100644 --- a/reccmp/cvdump/parser.py +++ b/reccmp/cvdump/parser.py @@ -3,6 +3,7 @@ from typing import NamedTuple from .types import CvdumpTypesParser from .symbols import CvdumpSymbolsParser +from .cvinfo import CvdumpTypeKey # e.g. ` 27 00034EC0 28 00034EE2 29 00034EE7 30 00034EF4` @@ -76,7 +77,7 @@ class GdataEntry(NamedTuple): section: int offset: int - type: str + type: CvdumpTypeKey name: str is_global: bool @@ -165,7 +166,7 @@ def _globals_section(self, line: str): GdataEntry( section=int(match.group("section"), 16), offset=int(match.group("offset"), 16), - type=match.group("type"), + type=CvdumpTypeKey.from_str(match.group("type")), name=match.group("name"), is_global=match.group("global") == "G", ) diff --git a/reccmp/cvdump/symbols.py b/reccmp/cvdump/symbols.py index 41f49206..be21fbb2 100644 --- a/reccmp/cvdump/symbols.py +++ b/reccmp/cvdump/symbols.py @@ -3,6 +3,7 @@ import re from re import Match from typing import NamedTuple +from reccmp.cvdump.types import CvdumpTypeKey logger = logging.getLogger(__name__) @@ -12,7 +13,7 @@ class StackOrRegisterSymbol(NamedTuple): symbol_type: str location: str """Should always be set/converted to lowercase.""" - data_type: str + data_type: CvdumpTypeKey name: str @@ -21,7 +22,7 @@ class LdataEntry(NamedTuple): section: int offset: int - type: str + type: CvdumpTypeKey name: str @@ -33,7 +34,7 @@ class SymbolsEntry: section: int offset: int size: int - func_type: str + func_type: CvdumpTypeKey name: str stack_symbols: list[StackOrRegisterSymbol] = field(default_factory=list) static_variables: list[LdataEntry] = field(default_factory=list) @@ -165,7 +166,7 @@ def _parse_generic_case(self, line, line_match: Match[str]): section=int(match.group("section"), 16), offset=int(match.group("offset"), 16), size=int(match.group("size"), 16), - func_type=match.group("func_type"), + func_type=CvdumpTypeKey.from_str(match.group("func_type")), name=match.group("name"), ) self.symbols.append(self.current_function) @@ -182,7 +183,7 @@ def _parse_generic_case(self, line, line_match: Match[str]): new_symbol = StackOrRegisterSymbol( symbol_type=symbol_type, location=match.group("location").lower(), - data_type=match.group("data_type"), + data_type=CvdumpTypeKey.from_str(match.group("data_type")), name=match.group("name"), ) self.current_function.stack_symbols.append(new_symbol) @@ -201,7 +202,7 @@ def _parse_generic_case(self, line, line_match: Match[str]): new_var = LdataEntry( section=int(match.group("section"), 16), offset=int(match.group("offset"), 16), - type=match.group("type"), + type=CvdumpTypeKey.from_str(match.group("type")), name=match.group("name"), ) diff --git a/reccmp/cvdump/types.py b/reccmp/cvdump/types.py index e8eeb190..13890c5f 100644 --- a/reccmp/cvdump/types.py +++ b/reccmp/cvdump/types.py @@ -3,19 +3,17 @@ import logging from typing import NamedTuple from typing_extensions import NotRequired, TypedDict +from .cvinfo import ( + CvInfoType, + CvdumpTypeKey, + CVInfoTypeEnum, + CvdumpTypeMap, +) logger = logging.getLogger(__name__) -# TODO: For now, this is here just to document where we -# expect a T_* (scalar) or 0x____ (complex) type key. -# Not all occurrences are normalized with normalize_type_id(). -# The unit tests show where some hex digits are capitalized. -# We would need to use typing.NewType for actual type-checking. -CvdumpTypeKey = str - - class CvdumpTypeError(Exception): pass @@ -28,6 +26,16 @@ class CvdumpIntegrityError(Exception): pass +def get_primitive(key: CvdumpTypeKey) -> CvInfoType: + """Throw CvdumpKeyError if we get a KeyError from the primitive map. + Log an error for the invalid type whether the exception is caught or not.""" + try: + return CvdumpTypeMap[key] + except KeyError as ex: + logger.error("Unknown scalar type 0x%x", key) + raise CvdumpKeyError(key) from ex + + class FieldListItem(NamedTuple): """Member of a class or structure""" @@ -57,23 +65,23 @@ class VirtualBasePointer: class ScalarType(NamedTuple): offset: int name: str | None - type: CvdumpTypeKey + type: CvInfoType @property def size(self) -> int: - return scalar_type_size(self.type) + return self.type.size @property def format_char(self) -> str: - return scalar_type_format_char(self.type) + return self.type.fmt @property def is_pointer(self) -> bool: - return scalar_type_pointer(self.type) + return self.type.pointer is not None class TypeInfo(NamedTuple): - key: str + key: CvdumpTypeKey size: int | None name: str | None = None members: list[FieldListItem] | None = None @@ -83,64 +91,6 @@ def is_scalar(self) -> bool: return self.members is None -def normalize_type_id(key: str) -> CvdumpTypeKey: - """Helper for TYPES parsing to ensure a consistent format. - If key begins with "T_" it is a built-in type. - Else it is a hex string. We prefer lower case letters and - no leading zeroes. (UDT identifier pads to 8 characters.)""" - if key[0] == "0": - return f"0x{key[-4:].lower()}" - - # Remove numeric value for "T_" type. We don't use this. - return key.partition("(")[0] - - -def scalar_type_pointer(type_name: str) -> bool: - return type_name.startswith("T_32P") - - -def scalar_type_size(type_name: str) -> int: - if scalar_type_pointer(type_name): - return 4 - - if "CHAR" in type_name: - return 2 if "WCHAR" in type_name else 1 - - if "SHORT" in type_name: - return 2 - - if "QUAD" in type_name or "64" in type_name: - return 8 - - return 4 - - -def scalar_type_signed(type_name: str) -> bool: - if scalar_type_pointer(type_name): - return False - - # According to cvinfo.h, T_WCHAR is unsigned - return not type_name.startswith("T_U") and not type_name.startswith("T_W") - - -def scalar_type_format_char(type_name: str) -> str: - if scalar_type_pointer(type_name): - return "L" - - # "Really a char" - if type_name.startswith("T_RCHAR"): - return "c" - - # floats - if type_name.startswith("T_REAL"): - return "d" if "64" in type_name else "f" - - size = scalar_type_size(type_name) - char = ({1: "b", 2: "h", 4: "l", 8: "q"}).get(size, "l") - - return char if scalar_type_signed(type_name) else char.upper() - - def member_list_to_struct_string(members: list[ScalarType]) -> str: """Create a string for use with struct.unpack""" @@ -325,6 +275,7 @@ class CvdumpTypesParser: def __init__(self) -> None: self.keys: dict[CvdumpTypeKey, CvdumpParsedType] = {} + self.alerted_types: set[int] = set() def _get_field_list(self, type_obj: CvdumpParsedType) -> list[FieldListItem]: """Return the field list for the given LF_CLASS/LF_STRUCTURE reference""" @@ -376,33 +327,38 @@ def _mock_array_members(self, type_obj: CvdumpParsedType) -> list[FieldListItem] for i in range(n_elements) ] - def get(self, type_key: str) -> TypeInfo: + def get(self, type_key: CvdumpTypeKey) -> TypeInfo: """Convert our dictionary values read from the cvdump output into a consistent format for the given type.""" # Scalar type. Handled here because it makes the recursive steps # much simpler. - if type_key.startswith("T_"): - size = scalar_type_size(type_key) + if type_key.is_scalar(): + cvinfo = get_primitive(type_key) + # We have seen some of the primitive types so far, but not all. + # The information in cvinfo.h is probably fine for most cases + # but warn users if we are dealing with an unseen type. + # (If you see this message in your project, we want to hear about it!) + if not cvinfo.verified and cvinfo.key not in self.alerted_types: + self.alerted_types.add(cvinfo.key) + logger.info( + "Unverified primitive type 0x%04x '%s'", + cvinfo.key, + cvinfo.name, + ) + return TypeInfo( key=type_key, - size=size, + size=cvinfo.size, ) # Go to our dictionary to find it. - obj = self.keys.get(type_key.lower()) + obj = self.keys.get(type_key) if obj is None: raise CvdumpKeyError(type_key) - # These type references are just a wrapper around a scalar - if obj.get("type") == "LF_ENUM": - underlying_type = obj.get("underlying_type") - if underlying_type is None: - raise CvdumpKeyError(f"Missing 'underlying_type' in {obj}") - return self.get(underlying_type) - if obj.get("type") == "LF_POINTER": - return self.get("T_32PVOID") + return self.get(CVInfoTypeEnum.T_32PVOID) if obj.get("is_forward_ref", False): # Get the forward reference to follow. @@ -414,6 +370,14 @@ def get(self, type_key: str) -> TypeInfo: return self.get(forward_ref) + # These type references are just a wrapper around a scalar + if obj.get("type") == "LF_ENUM": + underlying_type = obj.get("underlying_type") + if underlying_type is None: + raise CvdumpKeyError(f"Missing 'underlying_type' in {obj}") + + return self.get(underlying_type) + # Else it is not a forward reference, so build out the object here. if obj.get("type") == "LF_ARRAY": members = self._mock_array_members(obj) @@ -432,14 +396,21 @@ def get_by_name(self, name: str) -> TypeInfo: # TODO raise NotImplementedError - def get_scalars(self, type_key: str) -> list[ScalarType]: + def get_scalars(self, type_key: CvdumpTypeKey) -> list[ScalarType]: """Reduce the given type to a list of scalars so we can compare each component value.""" obj = self.get(type_key) if obj.is_scalar(): # Use obj.key here for alias types like LF_POINTER - return [ScalarType(offset=0, type=obj.key, name=None)] + cvinfo = get_primitive(obj.key) + return [ + ScalarType( + offset=0, + type=cvinfo, + name=None, + ) + ] # mypy? assert obj.members is not None @@ -458,7 +429,7 @@ def get_scalars(self, type_key: str) -> list[ScalarType]: for cm in self.get_scalars(m.type) ] - def get_scalars_gapless(self, type_key: str) -> list[ScalarType]: + def get_scalars_gapless(self, type_key: CvdumpTypeKey) -> list[ScalarType]: """Reduce the given type to a list of scalars so we can compare each component value.""" @@ -476,7 +447,7 @@ def get_scalars_gapless(self, type_key: str) -> list[ScalarType]: # Walk the scalar list in reverse; we assume a gap could not # come at the start of the struct. for scalar in scalars[::-1]: - this_extent = scalar.offset + scalar_type_size(scalar.type) + this_extent = scalar.offset + scalar.size size_diff = last_extent - this_extent # We need to add the gap fillers in reverse here for i in range(size_diff - 1, -1, -1): @@ -486,7 +457,7 @@ def get_scalars_gapless(self, type_key: str) -> list[ScalarType]: ScalarType( offset=this_extent + i, name="(padding)", - type="T_UCHAR", + type=get_primitive(CVInfoTypeEnum.T_UCHAR), ), ) @@ -495,17 +466,18 @@ def get_scalars_gapless(self, type_key: str) -> list[ScalarType]: return output - def get_format_string(self, type_key: str) -> str: + def get_format_string(self, type_key: CvdumpTypeKey) -> str: members = self.get_scalars_gapless(type_key) return member_list_to_struct_string(members) def read_all(self, section: str): - r_leafsplit = re.compile(r"\n(?=0x\w{4} : )") + r_leafsplit = re.compile(r"\n(?=0x\w{4,8} : )") for leaf in r_leafsplit.split(section): if (match := self.INDEX_RE.match(leaf)) is None: continue - (leaf_id, leaf_type) = match.groups() + (leaf_id_str, leaf_type) = match.groups() + leaf_id = CvdumpTypeKey.from_str(leaf_id_str) if leaf_type not in self.MODES_OF_INTEREST: continue @@ -557,7 +529,7 @@ def read_modifier(self, leaf: str, leaf_type: str) -> CvdumpParsedType: return { "type": leaf_type, "is_forward_ref": True, - "modifies": normalize_type_id(match.group("type")), + "modifies": CvdumpTypeKey.from_str(match.group("type")), "modification": match.group("modification"), } @@ -567,7 +539,7 @@ def read_array(self, leaf: str, leaf_type: str) -> CvdumpParsedType: return { "type": leaf_type, - "array_type": normalize_type_id(match.group("type")), + "array_type": CvdumpTypeKey.from_str(match.group("type")), "size": int(match.group("length")), } @@ -578,12 +550,14 @@ def read_fieldlist(self, leaf: str, leaf_type: str) -> CvdumpParsedType: # If this class has a vtable, create a mock member at offset 0 if self.VTABLE_RE.search(leaf) is not None: # For our purposes, any pointer type will do - members.append(FieldListItem(offset=0, type="T_32PVOID", name="vftable")) + members.append( + FieldListItem(offset=0, type=CVInfoTypeEnum.T_32PVOID, name="vftable") + ) # Superclass is set here in the fieldlist rather than in LF_CLASS for match in self.SUPERCLASS_RE.finditer(leaf): superclass_list: dict[CvdumpTypeKey, int] = obj.setdefault("super", {}) - superclass_list[normalize_type_id(match.group("type"))] = int( + superclass_list[CvdumpTypeKey.from_str(match.group("type"))] = int( match.group("offset") ) @@ -602,7 +576,7 @@ def read_fieldlist(self, leaf: str, leaf_type: str) -> CvdumpParsedType: virtual_base_pointer.bases.append( VirtualBaseClass( - type=match.group("type"), + type=CvdumpTypeKey.from_str(match.group("type")), index=-1, # default to -1 until we parse the correct value direct=match.group("indirect") != "I", ) @@ -630,7 +604,7 @@ def read_fieldlist(self, leaf: str, leaf_type: str) -> CvdumpParsedType: members += [ FieldListItem( offset=int(offset), - type=normalize_type_id(type_), + type=CvdumpTypeKey.from_str(type_), name=name, ) for (_, type_, offset, name) in self.LIST_RE.findall(leaf) @@ -658,7 +632,7 @@ def read_class_or_struct(self, leaf: str, leaf_type: str) -> CvdumpParsedType: # These cases get reported as UDT mismatch. obj["is_forward_ref"] = True else: - field_list_type = normalize_type_id(match.group("field_type")) + field_list_type = CvdumpTypeKey.from_str(match.group("field_type")) obj["field_list_type"] = field_list_type match = self.CLASS_NAME_RE.search(leaf) @@ -669,7 +643,7 @@ def read_class_or_struct(self, leaf: str, leaf_type: str) -> CvdumpParsedType: obj["name"] = match.group("name") udt = match.group("udt") if udt is not None: - obj["udt"] = normalize_type_id(udt) + obj["udt"] = CvdumpTypeKey.from_str(udt) obj["size"] = int(match.group("size")) @@ -680,7 +654,10 @@ def read_arglist(self, leaf: str, leaf_type: str) -> CvdumpParsedType: assert match is not None argcount = int(match.group("argcount")) - arglist = [arg_type for (_, arg_type) in self.LF_ARGLIST_ENTRY.findall(leaf)] + arglist = [ + CvdumpTypeKey.from_str(arg_type) + for (_, arg_type) in self.LF_ARGLIST_ENTRY.findall(leaf) + ] assert len(arglist) == argcount obj: CvdumpParsedType = {"type": leaf_type, "argcount": argcount} @@ -707,26 +684,32 @@ def read_pointer(self, leaf: str, leaf_type: str) -> CvdumpParsedType: "Pointer to member function", ) - return { + obj: CvdumpParsedType = { "type": leaf_type, - "element_type": match.group("element_type"), + "element_type": CvdumpTypeKey.from_str(match.group("element_type")), "pointer_type": match.group("type"), - # `containing_class` is set to `None` if not present - "containing_class": match.group("containing_class"), } + # `containing_class` is unset if not present + if match.group("containing_class") is not None: + obj["containing_class"] = CvdumpTypeKey.from_str( + match.group("containing_class") + ) + + return obj + def read_mfunction(self, leaf: str, leaf_type: str) -> CvdumpParsedType: match = self.LF_MFUNCTION_RE.search(leaf) assert match is not None return { "type": leaf_type, - "return_type": match.group("return_type"), - "class_type": match.group("class_type"), - "this_type": match.group("this_type"), + "return_type": CvdumpTypeKey.from_str(match.group("return_type")), + "class_type": CvdumpTypeKey.from_str(match.group("class_type")), + "this_type": CvdumpTypeKey.from_str(match.group("this_type")), "call_type": match.group("call_type"), "func_attr": match.group("func_attr"), "num_params": int(match.group("num_params")), - "arg_list_type": match.group("arg_list_type"), + "arg_list_type": CvdumpTypeKey.from_str(match.group("arg_list_type")), "this_adjust": int(match.group("this_adjust"), 16), } @@ -735,11 +718,11 @@ def read_procedure(self, leaf: str, leaf_type: str) -> CvdumpParsedType: assert match is not None return { "type": leaf_type, - "return_type": match.group("return_type"), + "return_type": CvdumpTypeKey.from_str(match.group("return_type")), "call_type": match.group("call_type"), "func_attr": match.group("func_attr"), "num_params": int(match.group("num_params")), - "arg_list_type": match.group("arg_list_type"), + "arg_list_type": CvdumpTypeKey.from_str(match.group("arg_list_type")), } def read_enum(self, leaf: str, leaf_type: str) -> CvdumpParsedType: @@ -779,11 +762,13 @@ def parse_enum_attribute(self, attribute: str) -> LfEnumAttrs: if attribute.startswith("UDT"): match = self.LF_ENUM_UDT.match(attribute) assert match is not None - return {"udt": normalize_type_id(match.group("udt"))} + return {"udt": CvdumpTypeKey.from_str(match.group("udt"))} if (match := self.LF_ENUM_TYPES.match(attribute)) is not None: return { - "underlying_type": normalize_type_id(match.group("underlying_type")), - "field_list_type": match.group("field_type"), + "underlying_type": CvdumpTypeKey.from_str( + match.group("underlying_type") + ), + "field_list_type": CvdumpTypeKey.from_str(match.group("field_type")), } logger.error("Unknown attribute in enum: %s", attribute) @@ -798,12 +783,12 @@ def read_union(self, leaf: str, leaf_type: str) -> CvdumpParsedType: if match.group("field_type") == "0x0000": obj["is_forward_ref"] = True else: - field_list_type = normalize_type_id(match.group("field_type")) + field_list_type = CvdumpTypeKey.from_str(match.group("field_type")) obj["field_list_type"] = field_list_type udt = match.group("udt") if udt is not None: - obj["udt"] = normalize_type_id(udt) + obj["udt"] = CvdumpTypeKey.from_str(udt) obj["size"] = int(match.group("size")) diff --git a/reccmp/ghidra/importer/function_importer.py b/reccmp/ghidra/importer/function_importer.py index cc8b9dcc..e53c65d0 100644 --- a/reccmp/ghidra/importer/function_importer.py +++ b/reccmp/ghidra/importer/function_importer.py @@ -17,6 +17,7 @@ Pointer, ComponentOffsetSettingsDefinition, ) +from reccmp.cvdump.cvinfo import CVInfoTypeEnum from .pdb_extraction import ( PdbFunction, @@ -135,7 +136,7 @@ def __init__( self.signature.return_type ) - if "T_NOTYPE(0000)" in self.signature.arglist: + if CVInfoTypeEnum.T_NOTYPE in self.signature.arglist: # Variadric functions have a T_NOTYPE as their last argument raise TypeNotImplementedError( f"Function '{self.get_full_name()}' is probably variadric, which is not implemented yet." @@ -144,10 +145,10 @@ def __init__( self.arguments: Sequence[ParameterImpl] = [ ParameterImpl( f"param{index}", - type_importer.import_pdb_type_into_ghidra(type_name), + type_importer.import_pdb_type_into_ghidra(type_key), api.getCurrentProgram(), ) - for (index, type_name) in enumerate(self.signature.arglist) + for (index, type_key) in enumerate(self.signature.arglist) ] def matches_ghidra_function(self, ghidra_function: Function) -> bool: @@ -347,7 +348,7 @@ def _rename_stack_parameter(self, index: int, param: Parameter): f"Could not find a matching symbol at offset {param.getStackOffset()} in {self.get_full_name()}" ) - if match.data_type == "T_NOTYPE(0000)": + if match.data_type == CVInfoTypeEnum.T_NOTYPE: logger.warning("Skipping stack parameter of type NOTYPE") return diff --git a/reccmp/ghidra/importer/pdb_extraction.py b/reccmp/ghidra/importer/pdb_extraction.py index 3701f576..2e3a91ae 100644 --- a/reccmp/ghidra/importer/pdb_extraction.py +++ b/reccmp/ghidra/importer/pdb_extraction.py @@ -1,5 +1,4 @@ from dataclasses import dataclass -import re import logging from reccmp.formats.exceptions import InvalidVirtualAddressError @@ -7,6 +6,7 @@ from reccmp.compare import Compare from reccmp.compare.db import ReccmpMatch from reccmp.cvdump.types import CvdumpParsedType +from reccmp.cvdump.cvinfo import CvdumpTypeKey, CVInfoTypeEnum logger = logging.getLogger(__file__) @@ -14,7 +14,7 @@ @dataclass class CppStackOrRegisterSymbol: name: str - data_type: str + data_type: CvdumpTypeKey @dataclass @@ -33,9 +33,9 @@ class CppRegisterSymbol(CppStackOrRegisterSymbol): class FunctionSignature: original_function_symbol: SymbolsEntry call_type: str - arglist: list[str] - return_type: str - class_type: str | None + arglist: list[CvdumpTypeKey] + return_type: CvdumpTypeKey + class_type: CvdumpTypeKey | None stack_symbols: list[CppStackOrRegisterSymbol] # if non-zero: an offset to the `this` parameter in a __thiscall this_adjust: int @@ -57,30 +57,26 @@ class PdbFunctionExtractor: def __init__(self, compare: Compare): self.compare = compare - scalar_type_regex = re.compile(r"t_(?P\w+)(?:\((?P\d+)\))?") - _call_type_map = { "ThisCall": "__thiscall", "C Near": "default", "STD Near": "__stdcall", } - def _get_cvdump_type(self, type_name: str | None) -> CvdumpParsedType | None: - return ( - None - if type_name is None - else self.compare.types.keys.get(type_name.lower()) - ) + def _get_cvdump_type( + self, type_key: CvdumpTypeKey | None + ) -> CvdumpParsedType | None: + return None if type_key is None else self.compare.types.keys.get(type_key) def get_func_signature(self, fn: SymbolsEntry) -> FunctionSignature | None: - function_type_str = fn.func_type - if function_type_str == "T_NOTYPE(0000)": + function_type_key = fn.func_type + if function_type_key == CVInfoTypeEnum.T_NOTYPE: logger.debug("Treating NOTYPE function as thunk: %s", fn.name) return None # get corresponding function type - function_type = self.compare.types.keys.get(function_type_str.lower()) + function_type = self.compare.types.keys.get(function_type_key) if function_type is None: logger.error( "Could not find function type %s for function %s", fn.func_type, fn.name diff --git a/reccmp/ghidra/importer/type_conversion.py b/reccmp/ghidra/importer/type_conversion.py new file mode 100644 index 00000000..002b22c0 --- /dev/null +++ b/reccmp/ghidra/importer/type_conversion.py @@ -0,0 +1,25 @@ +"""Converting scalar types (CvdumpTypeKey) into the corresponding type name in Ghidra.""" + +from reccmp.cvdump.cvinfo import CvdumpTypeMap, CvdumpTypeKey + + +_scalar_type_map = { + "T_RCHAR": "char", + "T_INT4": "int", + "T_UINT4": "uint", + "T_REAL32": "float", + "T_REAL64": "double", +} + + +def scalar_type_to_cpp(type_key: CvdumpTypeKey) -> str: + """Return the Ghidra name for the given scalar type.""" + cvtype = CvdumpTypeMap[type_key] + + if cvtype.name.startswith("T_32P"): + assert cvtype.pointer is not None + return f"{scalar_type_to_cpp(cvtype.pointer)} *" + + # Removing the "T_" prefix is good enough for most types. + # Some types require special handling via _scalar_type_map. + return _scalar_type_map.get(cvtype.name, cvtype.name[2:].lower()) diff --git a/reccmp/ghidra/importer/type_importer.py b/reccmp/ghidra/importer/type_importer.py index 72ba65f2..937dde51 100644 --- a/reccmp/ghidra/importer/type_importer.py +++ b/reccmp/ghidra/importer/type_importer.py @@ -27,6 +27,7 @@ FieldListItem, VirtualBasePointer, ) +from reccmp.cvdump.cvinfo import CvdumpTypeKey from .entity_names import NamespacePath, SanitizedEntityName, sanitize_name from .exceptions import ( @@ -45,6 +46,7 @@ get_scalar_ghidra_type, ) from .pdb_extraction import PdbFunctionExtractor +from .type_conversion import scalar_type_to_cpp logger = logging.getLogger(__name__) @@ -80,7 +82,7 @@ def types(self): return self.extraction.compare.types def import_pdb_type_into_ghidra( - self, type_index: str, slim_for_vbase: bool = False + self, type_index: CvdumpTypeKey, slim_for_vbase: bool = False ) -> DataType: """ Recursively imports a type from the PDB into Ghidra. @@ -93,24 +95,21 @@ def import_pdb_type_into_ghidra( that fits inside C. This value should always be `False` when the referenced type is not (a pointer to) a class. """ - type_index_lower = type_index.lower() - if type_index_lower.startswith("t_"): - return self._import_scalar_type(type_index_lower) + if type_index.is_scalar(): + return self._import_scalar_type(type_index) try: - type_pdb = self.extraction.compare.types.keys[type_index_lower] + type_pdb = self.extraction.compare.types.keys[type_index] except KeyError as e: raise TypeNotFoundError( - f"Failed to find referenced type '{type_index_lower}'" + f"Failed to find referenced type '{type_index:#x}'" ) from e type_category = type_pdb["type"] # follow forward reference (class, struct, union) if type_pdb.get("is_forward_ref", False): - return self._import_forward_ref_type( - type_index_lower, type_pdb, slim_for_vbase - ) + return self._import_forward_ref_type(type_index, type_pdb, slim_for_vbase) if type_category == "LF_POINTER": return get_or_add_pointer_type( @@ -136,29 +135,15 @@ def import_pdb_type_into_ghidra( else: raise TypeNotImplementedError(type_pdb) - _scalar_type_map = { - "rchar": "char", - "int4": "int", - "uint4": "uint", - "real32": "float", - "real64": "double", - } - - def _scalar_type_to_cpp(self, scalar_type: str) -> str: - if scalar_type.startswith("32p"): - return f"{self._scalar_type_to_cpp(scalar_type[3:])} *" - return self._scalar_type_map.get(scalar_type, scalar_type) - - def _import_scalar_type(self, type_index_lower: str) -> DataType: - if (match := self.extraction.scalar_type_regex.match(type_index_lower)) is None: - raise TypeNotFoundError(f"Type has unexpected format: {type_index_lower}") + def _import_scalar_type(self, type_key: CvdumpTypeKey) -> DataType: + if not type_key.is_scalar(): + raise TypeNotFoundError(f"Type has unexpected format: {type_key:#x}") - scalar_cpp_type = self._scalar_type_to_cpp(match.group("typename")) - return get_scalar_ghidra_type(self.api, scalar_cpp_type) + return get_scalar_ghidra_type(self.api, scalar_type_to_cpp(type_key)) def _import_forward_ref_type( self, - type_index, + type_index: CvdumpTypeKey, type_pdb: CvdumpParsedType, slim_for_vbase: bool = False, ) -> DataType: @@ -233,8 +218,8 @@ def _import_class_or_struct( type_in_pdb: CvdumpParsedType, slim_for_vbase: bool = False, ) -> DataType: - field_list_type: str = type_in_pdb["field_list_type"] - field_list = self.types.keys[field_list_type.lower()] + field_list_type = type_in_pdb["field_list_type"] + field_list = self.types.keys[field_list_type] class_size: int = type_in_pdb["size"] raw_name: str = type_in_pdb["name"] @@ -327,7 +312,7 @@ def _import_class_or_struct( def _get_components_from_base_classes( self, field_list: CvdumpParsedType ) -> Iterator[GhidraFieldListItem]: - non_virtual_base_classes: dict[str, int] = field_list.get("super", {}) + non_virtual_base_classes: dict[CvdumpTypeKey, int] = field_list.get("super", {}) for super_type, offset in non_virtual_base_classes.items(): # If we have virtual inheritance _and_ a non-virtual base class here, we play safe and import slim version. diff --git a/reccmp/tools/datacmp.py b/reccmp/tools/datacmp.py index 3eb5836c..0a092041 100755 --- a/reccmp/tools/datacmp.py +++ b/reccmp/tools/datacmp.py @@ -18,6 +18,7 @@ CvdumpKeyError, CvdumpIntegrityError, ) +from reccmp.cvdump.cvinfo import CvdumpTypeKey from reccmp.formats.pe import PEImage from reccmp.project.logging import argparse_add_logging_args, argparse_parse_logging from reccmp.project.detect import ( @@ -275,7 +276,9 @@ def do_the_comparison(target: RecCmpTarget) -> Iterable[ComparisonItem]: for var in compare.get_variables(): assert var.name is not None - type_name = var.get("data_type") + type_name = ( + CvdumpTypeKey(var.get("data_type")) if var.get("data_type") else None + ) # Start by assuming we can only compare the raw bytes data_size = var.size @@ -294,7 +297,7 @@ def do_the_comparison(target: RecCmpTarget) -> Iterable[ComparisonItem]: raw_only = False else: logger.info( - "No struct members for type '%s' used by variable '%s' (0x%x). Comparing raw data.", + "No struct members for type '0x%x' used by variable '%s' (0x%x). Comparing raw data.", type_name, var.name, var.orig_addr, @@ -305,7 +308,7 @@ def do_the_comparison(target: RecCmpTarget) -> Iterable[ComparisonItem]: # For example: we do not handle bitfields and this complicates fieldlist parsing # where they are used. (GH #299) logger.error( - "Could not materialize type '%s' used by variable '%s' (0x%x). Comparing raw data.", + "Could not materialize type '0x%x' used by variable '%s' (0x%x). Comparing raw data.", type_name, var.name, var.orig_addr, @@ -333,6 +336,7 @@ def do_the_comparison(target: RecCmpTarget) -> Iterable[ComparisonItem]: orig_data = tuple(orig_block.data) recomp_data = tuple(recomp_block.data) else: + assert type_name is not None compare_items = [ DataOffset(offset=sc.offset, name=sc.name or "", pointer=sc.is_pointer) for sc in compare.types.get_scalars_gapless(type_name) diff --git a/reccmp/tools/stackcmp.py b/reccmp/tools/stackcmp.py index 12d08580..82fc6692 100755 --- a/reccmp/tools/stackcmp.py +++ b/reccmp/tools/stackcmp.py @@ -18,6 +18,7 @@ argparse_parse_project_target, RecCmpProjectException, ) +from reccmp.cvdump.types import CvdumpTypeKey from reccmp.project.logging import argparse_add_logging_args, argparse_parse_logging # pylint: disable=duplicate-code # misdetects a code duplication with reccmp @@ -40,7 +41,7 @@ @dataclass class StackSymbol: name: str - data_type: str + data_type: CvdumpTypeKey @dataclass diff --git a/tests/test_compare_ingest_cvdump.py b/tests/test_compare_ingest_cvdump.py index e72d7d7e..83916c1b 100644 --- a/tests/test_compare_ingest_cvdump.py +++ b/tests/test_compare_ingest_cvdump.py @@ -463,6 +463,7 @@ def test_variable_size_with_type_info(binfile: PEImage): entity = db.get_by_recomp(0x101015B8) assert entity is not None assert entity.get("size") == 1024 + assert entity.get("data_type") == 0x1424 def test_gproc32(binfile: PEImage): diff --git a/tests/test_compare_mutate_match_array.py b/tests/test_compare_mutate_match_array.py index ebcd18d2..acb1fee8 100644 --- a/tests/test_compare_mutate_match_array.py +++ b/tests/test_compare_mutate_match_array.py @@ -8,7 +8,8 @@ ) from reccmp.types import EntityType from reccmp.compare.db import EntityDb -from reccmp.cvdump.types import CvdumpTypesParser, FieldListItem +from reccmp.cvdump.types import CvdumpTypesParser, FieldListItem, CVInfoTypeEnum +from reccmp.cvdump.cvinfo import CvdumpTypeKey as TK @pytest.fixture(name="db") @@ -28,9 +29,9 @@ def test_match_array_with_nothing(): def test_match_array(db: EntityDb, types_db: CvdumpTypesParser): """Should rename the entity for the array and create a new entity for the second member.""" - types_db.keys["0x1000"] = { + types_db.keys[TK(0x1000)] = { "type": "LF_ARRAY", - "array_type": "T_REAL32", + "array_type": CVInfoTypeEnum.T_REAL32, "size": 8, } @@ -38,7 +39,7 @@ def test_match_array(db: EntityDb, types_db: CvdumpTypesParser): # NOTE: It does not work if entity size is not set. # We should be able to set it because how else would we have the type key? batch.set_recomp( - 100, name="test", type=EntityType.DATA, data_type="0x1000", size=8 + 100, name="test", type=EntityType.DATA, data_type=0x1000, size=8 ) batch.match(100, 100) @@ -75,7 +76,7 @@ def test_match_array_key_unset(db: EntityDb): """Should have no effect if the data_type key is not in the types database.""" with db.batch() as batch: batch.set_recomp( - 100, name="test", type=EntityType.DATA, data_type="0x1000", size=8 + 100, name="test", type=EntityType.DATA, data_type=0x1000, size=8 ) batch.match(100, 100) @@ -106,7 +107,7 @@ def test_match_array_type_is_scalar(db: EntityDb): 100, name="test", type=EntityType.DATA, - data_type="T_REAL32(0040)", + data_type=CVInfoTypeEnum.T_REAL32, size=8, ) batch.match(100, 100) @@ -133,22 +134,22 @@ def test_match_array_type_is_scalar(db: EntityDb): def test_match_array_type_is_struct(db: EntityDb, types_db: CvdumpTypesParser): """Should have no effect if the data_type key is not an array. We do not currently populate entities for struct members.""" - types_db.keys["0x1000"] = { + types_db.keys[TK(0x1000)] = { "type": "LF_STRUCTURE", - "field_list_type": "0x1001", + "field_list_type": TK(0x1001), "size": 8, } - types_db.keys["0x1001"] = { + types_db.keys[TK(0x1001)] = { "type": "LF_FIELDLIST", "members": [ - FieldListItem(offset=0, name="hello", type="T_REAL32"), - FieldListItem(offset=4, name="world", type="T_REAL32"), + FieldListItem(offset=0, name="hello", type=CVInfoTypeEnum.T_REAL32), + FieldListItem(offset=4, name="world", type=CVInfoTypeEnum.T_REAL32), ], } with db.batch() as batch: batch.set_recomp( - 100, name="test", type=EntityType.DATA, data_type="0x1000", size=8 + 100, name="test", type=EntityType.DATA, data_type=0x1000, size=8 ) batch.match(100, 100) @@ -174,15 +175,15 @@ def test_match_array_type_is_struct(db: EntityDb, types_db: CvdumpTypesParser): def test_match_array_type_orig_smaller(db: EntityDb, types_db: CvdumpTypesParser): """Should not create entities on the orig side if the array is known to be smaller. (i.e. if another DATA entity is in the way.)""" - types_db.keys["0x1000"] = { + types_db.keys[TK(0x1000)] = { "type": "LF_ARRAY", - "array_type": "T_REAL32", + "array_type": CVInfoTypeEnum.T_REAL32, "size": 8, } with db.batch() as batch: batch.set_recomp( - 100, name="test", type=EntityType.DATA, data_type="0x1000", size=8 + 100, name="test", type=EntityType.DATA, data_type=0x1000, size=8 ) batch.set_orig(104, name="blocker", type=EntityType.DATA) batch.match(100, 100) @@ -215,27 +216,27 @@ def test_match_array_type_orig_smaller(db: EntityDb, types_db: CvdumpTypesParser def test_match_array_array_of_structs(db: EntityDb, types_db: CvdumpTypesParser): """If the type is an array of structs, create entities for one level of struct members.""" - types_db.keys["0x1000"] = { + types_db.keys[TK(0x1000)] = { "type": "LF_ARRAY", - "array_type": "0x1001", + "array_type": TK(0x1001), "size": 16, } - types_db.keys["0x1001"] = { + types_db.keys[TK(0x1001)] = { "type": "LF_STRUCTURE", - "field_list_type": "0x1002", + "field_list_type": TK(0x1002), "size": 8, } - types_db.keys["0x1002"] = { + types_db.keys[TK(0x1002)] = { "type": "LF_FIELDLIST", "members": [ - FieldListItem(offset=0, name="hello", type="T_REAL32"), - FieldListItem(offset=4, name="world", type="T_REAL32"), + FieldListItem(offset=0, name="hello", type=CVInfoTypeEnum.T_REAL32), + FieldListItem(offset=4, name="world", type=CVInfoTypeEnum.T_REAL32), ], } with db.batch() as batch: batch.set_recomp( - 100, name="test", type=EntityType.DATA, data_type="0x1000", size=16 + 100, name="test", type=EntityType.DATA, data_type=0x1000, size=16 ) batch.match(100, 100) @@ -288,20 +289,20 @@ def test_match_array_array_of_structs(db: EntityDb, types_db: CvdumpTypesParser) def test_match_array_array_of_arrays(db: EntityDb, types_db: CvdumpTypesParser): """For a multi-dimensional array, create entities for one level.""" - types_db.keys["0x1000"] = { + types_db.keys[TK(0x1000)] = { "type": "LF_ARRAY", - "array_type": "0x1001", + "array_type": TK(0x1001), "size": 16, } - types_db.keys["0x1001"] = { + types_db.keys[TK(0x1001)] = { "type": "LF_ARRAY", - "array_type": "T_REAL32", + "array_type": CVInfoTypeEnum.T_REAL32, "size": 8, } with db.batch() as batch: batch.set_recomp( - 100, name="test", type=EntityType.DATA, data_type="0x1000", size=16 + 100, name="test", type=EntityType.DATA, data_type=0x1000, size=16 ) batch.match(100, 100) @@ -353,39 +354,39 @@ def test_match_array_array_of_arrays(db: EntityDb, types_db: CvdumpTypesParser): def test_match_array_array_of_structs_limit(db: EntityDb, types_db: CvdumpTypesParser): """Does not create entities for offsets more than one level beyond the main entity.""" - types_db.keys["0x1000"] = { + types_db.keys[TK(0x1000)] = { "type": "LF_ARRAY", - "array_type": "0x1001", + "array_type": TK(0x1001), "size": 16, } - types_db.keys["0x1001"] = { + types_db.keys[TK(0x1001)] = { "type": "LF_STRUCTURE", - "field_list_type": "0x1002", + "field_list_type": TK(0x1002), "size": 8, } - types_db.keys["0x1002"] = { + types_db.keys[TK(0x1002)] = { "type": "LF_FIELDLIST", "members": [ - FieldListItem(offset=0, name="hello", type="0x1003"), - FieldListItem(offset=4, name="world", type="0x1003"), + FieldListItem(offset=0, name="hello", type=TK(0x1003)), + FieldListItem(offset=4, name="world", type=TK(0x1003)), ], } - types_db.keys["0x1003"] = { + types_db.keys[TK(0x1003)] = { "type": "LF_STRUCTURE", - "field_list_type": "0x1004", + "field_list_type": TK(0x1004), "size": 4, } - types_db.keys["0x1004"] = { + types_db.keys[TK(0x1004)] = { "type": "LF_FIELDLIST", "members": [ - FieldListItem(offset=0, name="x", type="T_SHORT"), - FieldListItem(offset=2, name="y", type="T_SHORT"), + FieldListItem(offset=0, name="x", type=CVInfoTypeEnum.T_SHORT), + FieldListItem(offset=2, name="y", type=CVInfoTypeEnum.T_SHORT), ], } with db.batch() as batch: batch.set_recomp( - 100, name="test", type=EntityType.DATA, data_type="0x1000", size=16 + 100, name="test", type=EntityType.DATA, data_type=0x1000, size=16 ) batch.match(100, 100) @@ -447,43 +448,43 @@ def test_match_array_array_of_union_structs(db: EntityDb, types_db: CvdumpTypesP - We create offset entities for unions, as with a struct or multidimensional array - We will not create entities deeper than the second level (in this case, array -> union) """ - types_db.keys["0x1000"] = { + types_db.keys[TK(0x1000)] = { "type": "LF_ARRAY", - "array_type": "0x1001", + "array_type": TK(0x1001), "size": 8, } - types_db.keys["0x1001"] = { + types_db.keys[TK(0x1001)] = { "type": "LF_UNION", - "field_list_type": "0x1002", + "field_list_type": TK(0x1002), "size": 4, } - types_db.keys["0x1002"] = { + types_db.keys[TK(0x1002)] = { "type": "LF_FIELDLIST", "members": [ - FieldListItem(offset=0, name="hello", type="0x1003"), - FieldListItem(offset=0, name="world", type="0x1003"), + FieldListItem(offset=0, name="hello", type=TK(0x1003)), + FieldListItem(offset=0, name="world", type=TK(0x1003)), ], } # These values will not be accessed because we do not completely flatten the structure. # But they are here to provide a complete example of type data. - types_db.keys["0x1003"] = { + types_db.keys[TK(0x1003)] = { "type": "LF_STRUCTURE", - "field_list_type": "0x1004", + "field_list_type": TK(0x1004), "size": 4, } - types_db.keys["0x1004"] = { + types_db.keys[TK(0x1004)] = { "type": "LF_FIELDLIST", "members": [ - FieldListItem(offset=0, name="a", type="T_CHAR"), - FieldListItem(offset=1, name="b", type="T_CHAR"), - FieldListItem(offset=2, name="c", type="T_CHAR"), - FieldListItem(offset=3, name="d", type="T_CHAR"), + FieldListItem(offset=0, name="a", type=CVInfoTypeEnum.T_CHAR), + FieldListItem(offset=1, name="b", type=CVInfoTypeEnum.T_CHAR), + FieldListItem(offset=2, name="c", type=CVInfoTypeEnum.T_CHAR), + FieldListItem(offset=3, name="d", type=CVInfoTypeEnum.T_CHAR), ], } with db.batch() as batch: batch.set_recomp( - 100, name="test", type=EntityType.DATA, data_type="0x1000", size=8 + 100, name="test", type=EntityType.DATA, data_type=0x1000, size=8 ) batch.match(100, 100) diff --git a/tests/test_cvdump.py b/tests/test_cvdump.py index 8fef6bdf..0946628e 100644 --- a/tests/test_cvdump.py +++ b/tests/test_cvdump.py @@ -1,8 +1,8 @@ import pytest -from reccmp.cvdump.types import ( - scalar_type_size, - scalar_type_pointer, - scalar_type_signed, +from reccmp.cvdump.cvinfo import ( + CVInfoTypeEnum, + CvdumpTypeKey, + CvdumpTypeMap, ) # These are all the types seen in the cvdump. @@ -15,45 +15,59 @@ # For reference: https://github.com/microsoft/microsoft-pdb/blob/master/include/cvinfo.h # fmt: off -# Fields are: type_name, size, is_signed, is_pointer -type_check_cases = ( - ("T_32PINT4", 4, False, True), - ("T_32PLONG", 4, False, True), - ("T_32PRCHAR", 4, False, True), - ("T_32PREAL32", 4, False, True), - ("T_32PUCHAR", 4, False, True), - ("T_32PUINT4", 4, False, True), - ("T_32PULONG", 4, False, True), - ("T_32PUSHORT", 4, False, True), - ("T_32PVOID", 4, False, True), - ("T_CHAR", 1, True, False), - ("T_INT4", 4, True, False), - ("T_LONG", 4, True, False), - ("T_QUAD", 8, True, False), - ("T_RCHAR", 1, True, False), - ("T_REAL32", 4, True, False), - ("T_REAL64", 8, True, False), - ("T_SHORT", 2, True, False), - ("T_UCHAR", 1, False, False), - ("T_UINT4", 4, False, False), - ("T_ULONG", 4, False, False), - ("T_UQUAD", 8, False, False), - ("T_USHORT", 2, False, False), - ("T_WCHAR", 2, False, False), +# Fields are: type_name, size, is_pointer +SCALARS_WITH_NORMALIZED_ID = ( + (CVInfoTypeEnum.T_32PINT4, 4, True), + (CVInfoTypeEnum.T_32PLONG, 4, True), + (CVInfoTypeEnum.T_32PRCHAR, 4, True), + (CVInfoTypeEnum.T_32PREAL32, 4, True), + (CVInfoTypeEnum.T_32PUCHAR, 4, True), + (CVInfoTypeEnum.T_32PUINT4, 4, True), + (CVInfoTypeEnum.T_32PULONG, 4, True), + (CVInfoTypeEnum.T_32PUSHORT, 4, True), + (CVInfoTypeEnum.T_32PVOID, 4, True), + (CVInfoTypeEnum.T_BOOL08, 1, False), + (CVInfoTypeEnum.T_CHAR, 1, False), + (CVInfoTypeEnum.T_INT4, 4, False), + (CVInfoTypeEnum.T_LONG, 4, False), + (CVInfoTypeEnum.T_QUAD, 8, False), + (CVInfoTypeEnum.T_RCHAR, 1, False), + (CVInfoTypeEnum.T_REAL32, 4, False), + (CVInfoTypeEnum.T_REAL64, 8, False), + (CVInfoTypeEnum.T_SHORT, 2, False), + (CVInfoTypeEnum.T_UCHAR, 1, False), + (CVInfoTypeEnum.T_UINT4, 4, False), + (CVInfoTypeEnum.T_ULONG, 4, False), + (CVInfoTypeEnum.T_UQUAD, 8, False), + (CVInfoTypeEnum.T_USHORT, 2, False), + (CVInfoTypeEnum.T_WCHAR, 2, False), ) # fmt: on -@pytest.mark.parametrize("type_name, size, _, __", type_check_cases) -def test_scalar_size(type_name: str, size: int, _, __): - assert scalar_type_size(type_name) == size +@pytest.mark.parametrize("type_key, size, _", SCALARS_WITH_NORMALIZED_ID) +def test_scalar_size(type_key: CvdumpTypeKey, size: int, _): + assert CvdumpTypeMap[type_key].size == size -@pytest.mark.parametrize("type_name, _, is_signed, __", type_check_cases) -def test_scalar_signed(type_name: str, _, is_signed: bool, __): - assert scalar_type_signed(type_name) == is_signed +@pytest.mark.parametrize("type_key, _, is_pointer", SCALARS_WITH_NORMALIZED_ID) +def test_scalar_pointer(type_key: CvdumpTypeKey, _, is_pointer: bool): + assert (CvdumpTypeMap[type_key].pointer is not None) == is_pointer -@pytest.mark.parametrize("type_name, _, __, is_pointer", type_check_cases) -def test_scalar_pointer(type_name: str, _, __, is_pointer: bool): - assert scalar_type_pointer(type_name) == is_pointer +def test_verify_cvinfo_enum(): + """Assert that CVInfoTypeEnum and CvdumpTypeMap have exactly the same items.""" + + # Check each enum member against the type map. + for e in CVInfoTypeEnum: + # Make sure the enum members are functionally equivalent to both these dependent types. + assert isinstance(e, CvdumpTypeKey) + assert isinstance(e, int) + # Make sure the enum's const name is the same as the type's name in the map. + # e.g. The value of CVInfoTypeEnum.T_INT4 resolves to the type key for T_INT4. + assert CvdumpTypeMap[e].name == e.name + + # Check each entry in the map against the enum. + for type_key, cvtype in CvdumpTypeMap.items(): + # Use the type's name to get the CvdumpTypeKey from the enum. + assert CVInfoTypeEnum[cvtype.name] == type_key diff --git a/tests/test_cvdump_analysis.py b/tests/test_cvdump_analysis.py index 5378226d..a786cce2 100644 --- a/tests/test_cvdump_analysis.py +++ b/tests/test_cvdump_analysis.py @@ -5,6 +5,7 @@ CvdumpAnalysis, CvdumpNode, ) +from reccmp.cvdump.cvinfo import CvdumpTypeKey as TK TEST_SYMBOLS = [ @@ -13,7 +14,7 @@ section=1, offset=0xCC3, size=0xA9, - func_type="0x100D", + func_type=TK(0x100D), name="__setargv", ), SymbolsEntry( @@ -21,7 +22,7 @@ section=1, offset=0x12EC, size=0x56, - func_type="0x100D", + func_type=TK(0x100D), name="check_managed_app", ), ] diff --git a/tests/test_cvdump_parser.py b/tests/test_cvdump_parser.py index 66e991da..3bdc1ffa 100644 --- a/tests/test_cvdump_parser.py +++ b/tests/test_cvdump_parser.py @@ -4,6 +4,7 @@ CvdumpParser, GdataEntry, ) +from reccmp.cvdump.cvinfo import CVInfoTypeEnum GLOBALS_SAMPLE = """ S_PROCREF: 0x00000000: ( 5, 000000D4) WinMain @@ -24,14 +25,14 @@ def test_globals(): assert parser.globals[0] == GdataEntry( section=0x0003, offset=0x00018F84, - type="T_UINT4(0075)", + type=CVInfoTypeEnum.T_UINT4, name="_winver", is_global=True, ) assert parser.globals[1] == GdataEntry( section=0x0003, offset=0x00018FCC, - type="T_INT4(0074)", + type=CVInfoTypeEnum.T_INT4, name="fSystemSet", is_global=False, ) diff --git a/tests/test_cvdump_symbols.py b/tests/test_cvdump_symbols.py index e9bd27fa..37b534b6 100644 --- a/tests/test_cvdump_symbols.py +++ b/tests/test_cvdump_symbols.py @@ -1,6 +1,7 @@ """Test Cvdump SYMBOLS parser, reading function stack/params""" from reccmp.cvdump.symbols import CvdumpSymbolsParser +from reccmp.cvdump.cvinfo import CvdumpTypeKey, CVInfoTypeEnum PROC_WITH_BLOC = """ (000638) S_GPROC32: [0001:000C6135], Cb: 00000361, Type: 0x10ED, RegistrationBook::ReadyWorld @@ -36,6 +37,7 @@ def test_sblock32(): # Make sure we can read the proc and all its stack references assert len(parser.symbols) == 1 assert len(parser.symbols[0].stack_symbols) == 8 + assert parser.symbols[0].stack_symbols[0].data_type == CvdumpTypeKey(0x10EC) LOCAL_PROC = """ @@ -58,6 +60,7 @@ def test_local_proc(): # Make sure we can read the proc assert len(parser.symbols) == 1 + assert parser.symbols[0].func_type == CvdumpTypeKey(0x1078) LDATA32_INSIDE_FUNCTION = """\ @@ -79,11 +82,16 @@ def test_ldata32_inside_function(): parser.read_line(line) assert len(parser.symbols) == 1 + assert parser.symbols[0].func_type == CvdumpTypeKey(0x1010) assert len(parser.symbols[0].static_variables) == 2 assert [v.name for v in parser.symbols[0].static_variables] == [ "got_it_already", "cd_pathname", ] + assert [v.type for v in parser.symbols[0].static_variables] == [ + CVInfoTypeEnum.T_INT4, + CvdumpTypeKey(0x100B), + ] def test_ldata32_outside_function(): diff --git a/tests/test_cvdump_types.py b/tests/test_cvdump_types.py index 5e74ab82..688c8ec8 100644 --- a/tests/test_cvdump_types.py +++ b/tests/test_cvdump_types.py @@ -1,13 +1,19 @@ """Specifically testing the Cvdump TYPES parser and type dependency tree walker.""" +# pylint:disable=too-many-lines + +from typing import Iterable import pytest from reccmp.cvdump.types import ( + CvdumpTypeKey as TK, + CVInfoTypeEnum, CvdumpTypesParser, CvdumpKeyError, CvdumpIntegrityError, EnumItem, FieldListItem, + ScalarType, VirtualBaseClass, VirtualBasePointer, ) @@ -357,6 +363,12 @@ """ +def simplify_scalars(scalars: Iterable[ScalarType]) -> list[tuple[int, str | None, TK]]: + """Helper for shortening tests. We only need to compare the scalar type key, + not each of the derived attributes.""" + return [(s.offset, s.name, s.type.key) for s in scalars] + + @pytest.fixture(name="parser") def types_parser_fixture(): parser = CvdumpTypesParser() @@ -371,75 +383,81 @@ def types_empty_parser_fixture(): def test_basic_parsing(parser: CvdumpTypesParser): - obj = parser.keys["0x4db6"] + obj = parser.keys[TK(0x4DB6)] assert obj["type"] == "LF_CLASS" assert obj["name"] == "MxString" - assert obj["udt"] == "0x4db6" + assert obj["udt"] == TK(0x4DB6) - assert len(parser.keys["0x4db5"]["members"]) == 2 + assert len(parser.keys[TK(0x4DB5)]["members"]) == 2 def test_scalar_types(parser: CvdumpTypesParser): """Full tests on the scalar_* methods are in another file. Here we are just testing the passthrough of the "T_" types.""" - assert parser.get("T_CHAR").name is None - assert parser.get("T_CHAR").size == 1 + assert parser.get(CVInfoTypeEnum.T_CHAR).name is None + assert parser.get(CVInfoTypeEnum.T_CHAR).size == 1 - assert parser.get("T_32PVOID").name is None - assert parser.get("T_32PVOID").size == 4 + assert parser.get(CVInfoTypeEnum.T_32PVOID).name is None + assert parser.get(CVInfoTypeEnum.T_32PVOID).size == 4 def test_resolve_forward_ref(parser: CvdumpTypesParser): # Non-forward ref - assert parser.get("0x22d5").name == "MxVariable" + assert parser.get(TK(0x22D5)).name == "MxVariable" # Forward ref - assert parser.get("0x14db").name == "MxString" - assert parser.get("0x14db").size == 16 + assert parser.get(TK(0x14DB)).name == "MxString" + assert parser.get(TK(0x14DB)).size == 16 def test_members(parser: CvdumpTypesParser): """Return the list of items to compare for a given complex type. If the class has a superclass, add those members too.""" # MxCore field list - mxcore_members = parser.get_scalars("0x405f") + mxcore_members = simplify_scalars(parser.get_scalars(TK(0x405F))) assert mxcore_members == [ - (0, "vftable", "T_32PVOID"), - (4, "m_id", "T_UINT4"), + (0, "vftable", CVInfoTypeEnum.T_32PVOID), + (4, "m_id", CVInfoTypeEnum.T_UINT4), ] # MxCore class id. Should be the same members - assert mxcore_members == parser.get_scalars("0x4060") + assert mxcore_members == simplify_scalars(parser.get_scalars(TK(0x4060))) # MxString field list. Should add inherited members from MxCore - assert parser.get_scalars("0x4db5") == [ - (0, "vftable", "T_32PVOID"), - (4, "m_id", "T_UINT4"), - (8, "m_data", "T_32PRCHAR"), - (12, "m_length", "T_USHORT"), + assert simplify_scalars(parser.get_scalars(TK(0x4DB5))) == [ + (0, "vftable", CVInfoTypeEnum.T_32PVOID), + (4, "m_id", CVInfoTypeEnum.T_UINT4), + (8, "m_data", CVInfoTypeEnum.T_32PRCHAR), + (12, "m_length", CVInfoTypeEnum.T_USHORT), ] # LegoRaceCar with multiple superclasses - assert parser.get("0x5594").members == [ - FieldListItem(offset=0, name="vftable", type="T_32PVOID"), - FieldListItem(offset=0, name="vftable", type="T_32PVOID"), - FieldListItem(offset=8, name="m_parentClass1Field1", type="T_REAL32"), - FieldListItem(offset=8, name="m_parentClass2Field1", type="T_UCHAR"), - FieldListItem(offset=12, name="m_parentClass2Field2", type="T_32PVOID"), - FieldListItem(offset=84, name="m_childClassField", type="T_UCHAR"), + assert parser.get(TK(0x5594)).members == [ + FieldListItem(offset=0, name="vftable", type=CVInfoTypeEnum.T_32PVOID), + FieldListItem(offset=0, name="vftable", type=CVInfoTypeEnum.T_32PVOID), + FieldListItem( + offset=8, name="m_parentClass1Field1", type=CVInfoTypeEnum.T_REAL32 + ), + FieldListItem( + offset=8, name="m_parentClass2Field1", type=CVInfoTypeEnum.T_UCHAR + ), + FieldListItem( + offset=12, name="m_parentClass2Field2", type=CVInfoTypeEnum.T_32PVOID + ), + FieldListItem(offset=84, name="m_childClassField", type=CVInfoTypeEnum.T_UCHAR), ] def test_virtual_base_classes(parser: CvdumpTypesParser): """Make sure that virtual base classes are parsed correctly.""" - lego_car_race_actor = parser.keys.get("0x5591") + lego_car_race_actor = parser.keys.get(TK(0x5591)) assert lego_car_race_actor is not None assert lego_car_race_actor["vbase"] == VirtualBasePointer( vboffset=4, bases=[ - VirtualBaseClass(type="0x1183", index=1, direct=False), - VirtualBaseClass(type="0x1468", index=2, direct=False), - VirtualBaseClass(type="0x15EA", index=3, direct=True), + VirtualBaseClass(type=TK(0x1183), index=1, direct=False), + VirtualBaseClass(type=TK(0x1468), index=2, direct=False), + VirtualBaseClass(type=TK(0x15EA), index=3, direct=True), ], ) @@ -447,29 +465,29 @@ def test_virtual_base_classes(parser: CvdumpTypesParser): def test_members_recursive(parser: CvdumpTypesParser): """Make sure that we unwrap the dependency tree correctly.""" # MxVariable field list - assert parser.get_scalars("0x22d4") == [ - (0, "vftable", "T_32PVOID"), - (4, "m_key.vftable", "T_32PVOID"), - (8, "m_key.m_id", "T_UINT4"), - (12, "m_key.m_data", "T_32PRCHAR"), - (16, "m_key.m_length", "T_USHORT"), # with padding - (20, "m_value.vftable", "T_32PVOID"), - (24, "m_value.m_id", "T_UINT4"), - (28, "m_value.m_data", "T_32PRCHAR"), - (32, "m_value.m_length", "T_USHORT"), # with padding + assert simplify_scalars(parser.get_scalars(TK(0x22D4))) == [ + (0, "vftable", CVInfoTypeEnum.T_32PVOID), + (4, "m_key.vftable", CVInfoTypeEnum.T_32PVOID), + (8, "m_key.m_id", CVInfoTypeEnum.T_UINT4), + (12, "m_key.m_data", CVInfoTypeEnum.T_32PRCHAR), + (16, "m_key.m_length", CVInfoTypeEnum.T_USHORT), # with padding + (20, "m_value.vftable", CVInfoTypeEnum.T_32PVOID), + (24, "m_value.m_id", CVInfoTypeEnum.T_UINT4), + (28, "m_value.m_data", CVInfoTypeEnum.T_32PRCHAR), + (32, "m_value.m_length", CVInfoTypeEnum.T_USHORT), # with padding ] def test_struct(parser: CvdumpTypesParser): """Basic test for converting type into struct.unpack format string.""" # MxCore: vftable and uint32. The vftable pointer is read as uint32. - assert parser.get_format_string("0x4060") == "" + assert "udt" not in empty_parser.keys[TK(0x3352)] + assert empty_parser.keys[TK(0x3352)]["name"] == "" MFUNCTION_UNK_RETURN_TYPE = """ @@ -818,7 +846,7 @@ def test_mfunction_unk_return_type(empty_parser: CvdumpTypesParser): """Should parse unknown return type as-is""" empty_parser.read_all(MFUNCTION_UNK_RETURN_TYPE) - assert empty_parser.keys["0x11d8"]["return_type"] == "???(047C)" + assert empty_parser.keys[TK(0x11D8)]["return_type"] == TK(0x47C) CLASS_WITH_UNIQUE_NAME = """ @@ -834,7 +862,7 @@ def test_class_unique_name(empty_parser: CvdumpTypesParser): """Make sure we can parse the UDT when the 'unique name' attribute is present""" empty_parser.read_all(CLASS_WITH_UNIQUE_NAME) - assert empty_parser.keys["0x1cf0"]["udt"] == "0x1cf0" + assert empty_parser.keys[TK(0x1CF0)]["udt"] == TK(0x1CF0) TWO_FORMATS_FOR_ARRAY_LENGTH = """ @@ -856,8 +884,8 @@ def test_two_formats_for_array_length(empty_parser: CvdumpTypesParser): """Make sure we can parse the UDT when the 'unique name' attribute is present""" empty_parser.read_all(TWO_FORMATS_FOR_ARRAY_LENGTH) - assert empty_parser.keys["0x62c1"]["size"] == 50 - assert empty_parser.keys["0x62c5"]["size"] == 131328 + assert empty_parser.keys[TK(0x62C1)]["size"] == 50 + assert empty_parser.keys[TK(0x62C5)]["size"] == 131328 LF_POINTER_TO_MEMBER = """ @@ -871,7 +899,7 @@ def test_two_formats_for_array_length(empty_parser: CvdumpTypesParser): def test_pointer_to_member(empty_parser: CvdumpTypesParser): """LF_POINTER with optional 'Containing class' attribute.""" empty_parser.read_all(LF_POINTER_TO_MEMBER) - assert empty_parser.keys["0x1646"]["element_type"] == "0x1645" + assert empty_parser.keys[TK(0x1646)]["element_type"] == TK(0x1645) MSVC700_ENUM_WITH_LOCAL_FLAG = """ @@ -885,15 +913,36 @@ def test_enum_with_local_flag(empty_parser: CvdumpTypesParser): """Make sure we can parse an enum with the LOCAL flag set. At the moment, the flag is ignored.""" empty_parser.read_all(MSVC700_ENUM_WITH_LOCAL_FLAG) - assert empty_parser.keys["0x26ba"] == { - "field_list_type": "0x26b9", + assert empty_parser.keys[TK(0x26BA)] == { + "field_list_type": 0x26B9, "name": "SomeEnumType::SomeEnumInternalName::__l2::__unnamed", "num_members": 3, "type": "LF_ENUM", - "underlying_type": "T_INT4", + "underlying_type": CVInfoTypeEnum.T_INT4, } +ENUM_FORWARD_REF = """ +0x10b6 : Length = 38, Leaf = 0x1507 LF_ENUM + # members = 69, type = T_CHAR(0010) field list type 0x10b5 + enum name = JukeboxScript::Script, UDT(0x000010b6) + +0x11a6 : Length = 38, Leaf = 0x1507 LF_ENUM + # members = 0, type = T_NOTYPE(0000) field list type 0x0000 +FORWARD REF, enum name = JukeboxScript::Script, UDT(0x000010b6) +""" + + +def test_enum_forward_ref(empty_parser: CvdumpTypesParser): + """Make sure that we resolve forward refs for LF_ENUM.""" + empty_parser.read_all(ENUM_FORWARD_REF) + + # Using non-standard T_CHAR(0010) base type to demonstrate the problem. + # The main concern is to not use T_NOTYPE as the basis of the enum. + # Previously we assumed all but a few specific types had size 4. + assert empty_parser.get(TK(0x11A6)).size == 1 + + MSVC700_POINTER_CONTAINING_CLASS_TYPE_OF_POINTED_TO = """ 0x64ca : Length = 18, Leaf = 0x1002 LF_POINTER Pointer to member function (NEAR32), Size: 0 @@ -908,10 +957,10 @@ def test_enum_with_containing_class_and_type_of_pointed_to( """Make sure that a pointer with these attributes is parsed correctly. 'Type of pointed to' is currently ignored.""" empty_parser.read_all(MSVC700_POINTER_CONTAINING_CLASS_TYPE_OF_POINTED_TO) - assert empty_parser.keys["0x64ca"] == { - "element_type": "0x2FD1", + assert empty_parser.keys[TK(0x64CA)] == { + "element_type": 0x2FD1, "type": "LF_POINTER", - "containing_class": "0x1165", + "containing_class": 0x1165, "pointer_type": "Pointer to member function", } @@ -928,9 +977,8 @@ def test_pointer_without_containing_class( ): empty_parser.read_all(POINTER_WITHOUT_CONTAINING_CLASS) - assert empty_parser.keys["0x534e"] == { - "containing_class": None, - "element_type": "0x2505", + assert empty_parser.keys[TK(0x534E)] == { + "element_type": 0x2505, "type": "LF_POINTER", "pointer_type": "Pointer", } @@ -948,13 +996,13 @@ def test_enum_with_whitespace_and_comma( ): empty_parser.read_all(ENUM_WITH_WHITESPACE_AND_COMMA) - assert empty_parser.keys["0x4dc2"] == { - "field_list_type": "0x2588", + assert empty_parser.keys[TK(0x4DC2)] == { + "field_list_type": 0x2588, "is_nested": True, "name": "CPool::__unnamed", "num_members": 1, "type": "LF_ENUM", - "underlying_type": "T_INT4", + "underlying_type": CVInfoTypeEnum.T_INT4, } @@ -969,4 +1017,62 @@ def test_this_adjust_hex(empty_parser: CvdumpTypesParser): Parms = 3, Arg list type = 0x6579, This adjust = 24""" ) - assert empty_parser.keys["0x657a"]["this_adjust"] == 0x24 + assert empty_parser.keys[TK(0x657A)]["this_adjust"] == TK(0x24) + + +BIG_TYPE_KEY_SAMPLE = """ +0x1023 : Length = 70, Leaf = 0x1505 LF_STRUCTURE + # members = 0, field list type 0x0000, FORWARD REF, + Derivation list type 0x0000, VT shape type 0x0000 + Size = 0, class name = threadlocaleinfostruct, unique name = Uthreadlocaleinfostruct@@, UDT(0x00011738) + +0x00011736 : Length = 14, Leaf = 0x1503 LF_ARRAY + Element type = 0x00011735 + Index type = T_ULONG(0022) + length = 96 + Name = + +0x00011737 : Length = 418, Leaf = 0x1203 LF_FIELDLIST + list[0] = LF_MEMBER, public, type = 0x00011736, offset = 72 + member name = 'lc_category' + +0x00011738 : Length = 70, Leaf = 0x1505 LF_STRUCTURE + # members = 18, field list type 0x11737, + Derivation list type 0x0000, VT shape type 0x0000 + Size = 216, class name = threadlocaleinfostruct, unique name = Uthreadlocaleinfostruct@@, UDT(0x00011738) +""" + + +def test_type_keys_over_ffff(empty_parser: CvdumpTypesParser): + """Make sure we can read type keys larger than 0xffff. + This checks various leaves where it could appear.""" + empty_parser.read_all(BIG_TYPE_KEY_SAMPLE) + assert empty_parser.keys[TK(0x1023)]["udt"] == TK(0x11738) + assert empty_parser.keys[TK(0x11736)]["array_type"] == TK(0x11735) + assert empty_parser.keys[TK(0x11737)]["members"][0].type == TK(0x11736) + assert empty_parser.keys[TK(0x11738)]["field_list_type"] == TK(0x11737) + + +ARRAY_WITH_UNKNOWN_ELEMENT = """ +0x1000 : Length = 14, Leaf = 0x1503 LF_ARRAY + Element type = ???(0555) + Index type = T_SHORT(0011) + length = 64 + Name = +""" + + +def test_unknown_primitive_type(empty_parser: CvdumpTypesParser): + """Make sure we raise an exception if an unknown primitive type is used. + Our list of primitive types should be comprehensive and the caller has + the option to catch the exception and continue on.""" + with pytest.raises(CvdumpKeyError): + empty_parser.get(TK(0x555)) + + with pytest.raises(CvdumpKeyError): + empty_parser.get_scalars(TK(0x555)) + + # Invalid type accessed indirectly via another type + empty_parser.read_all(ARRAY_WITH_UNKNOWN_ELEMENT) + with pytest.raises(CvdumpKeyError): + empty_parser.get_scalars(TK(0x1000)) diff --git a/tests/test_ghidra_type_conversion.py b/tests/test_ghidra_type_conversion.py new file mode 100644 index 00000000..0613a643 --- /dev/null +++ b/tests/test_ghidra_type_conversion.py @@ -0,0 +1,35 @@ +import pytest +from reccmp.cvdump.cvinfo import CVInfoTypeEnum, CvdumpTypeKey +from reccmp.ghidra.importer.type_conversion import scalar_type_to_cpp + +SAMPLES = ( + # Pointers + (CVInfoTypeEnum.T_32PCHAR, "char *"), + (CVInfoTypeEnum.T_32PINT4, "int *"), + (CVInfoTypeEnum.T_32PLONG, "long *"), + (CVInfoTypeEnum.T_32PRCHAR, "char *"), + (CVInfoTypeEnum.T_32PREAL32, "float *"), + (CVInfoTypeEnum.T_32PREAL64, "double *"), + (CVInfoTypeEnum.T_32PSHORT, "short *"), + (CVInfoTypeEnum.T_32PUCHAR, "uchar *"), + (CVInfoTypeEnum.T_32PUINT4, "uint *"), + (CVInfoTypeEnum.T_32PULONG, "ulong *"), + (CVInfoTypeEnum.T_32PUSHORT, "ushort *"), + # Scalars + (CVInfoTypeEnum.T_CHAR, "char"), + (CVInfoTypeEnum.T_INT4, "int"), + (CVInfoTypeEnum.T_LONG, "long"), + (CVInfoTypeEnum.T_RCHAR, "char"), + (CVInfoTypeEnum.T_REAL32, "float"), + (CVInfoTypeEnum.T_REAL64, "double"), + (CVInfoTypeEnum.T_SHORT, "short"), + (CVInfoTypeEnum.T_UCHAR, "uchar"), + (CVInfoTypeEnum.T_UINT4, "uint"), + (CVInfoTypeEnum.T_ULONG, "ulong"), + (CVInfoTypeEnum.T_USHORT, "ushort"), +) + + +@pytest.mark.parametrize("key, type_name", SAMPLES) +def test_ghidra_type_conversion(key: CvdumpTypeKey, type_name: str): + assert scalar_type_to_cpp(key) == type_name