Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b3ba361
Use integer for type key in all cvdump parsing (WIP)
disinvite Jan 31, 2026
db873b6
Fix hex display of type key
disinvite Jan 31, 2026
5f0a742
Merge branch 'isledecomp:master' into strong-type-for-cvdump-key
disinvite Feb 5, 2026
89f2c04
float/double dubbed unsigned
disinvite Feb 5, 2026
94ef73f
Add cvdump type names
disinvite Feb 6, 2026
9eaaec7
Remove some magic numbers
disinvite Feb 6, 2026
ac3343c
Expand CVInfo listing to include type metadata
disinvite Feb 6, 2026
6358de9
Remove T_NOTYPE uses
disinvite Feb 6, 2026
8278cda
Get scalar data from cvinfo.py.
disinvite Feb 6, 2026
6bb34b6
Bug: all types were pointers
disinvite Feb 7, 2026
a1ec1f0
Assume 32-bit enum footprint if NOTYPE specified. Alert to unusual ty…
disinvite Feb 7, 2026
5a6fc61
Fix the actual bug: LF_ENUM forward refs not followed.
disinvite Feb 7, 2026
88bda4e
Remove magic numbers in ghidra files
disinvite Feb 7, 2026
4c00031
Use MappingProxy for immutable dict
disinvite Feb 7, 2026
864567a
Use kwargs instead. Move test-only functions out of cvdump/types.py
disinvite Feb 7, 2026
a13b93f
Move more pieces into cvinfo module.
disinvite Feb 7, 2026
495fc40
Dynamic enum for scalar CV type keys.
disinvite Feb 7, 2026
0e08d81
Now enable strong typing for the key.
disinvite Feb 7, 2026
aa09c50
Remove scalar check magic numbers. Mypy fix for datacmp
disinvite Feb 7, 2026
db54ff4
Move normalize fn into type class. Close type conversion gap in GLOBA…
disinvite Feb 7, 2026
d6b2e3b
Split leaves properly for keys over 0xffff
disinvite Feb 7, 2026
419660e
Add T_CHAR8 types seen in #85. Log type key for ??? types.
disinvite Feb 8, 2026
02ba207
Bugfix: wrong pointer links for T_LONG
disinvite Feb 8, 2026
7812397
Move Ghidra type name conversion to its own module and add tests.
disinvite Feb 8, 2026
c3c1a8b
Explicit enum for CV scalar keys. Expose mapping proxy directly (no d…
disinvite Feb 10, 2026
d6454a5
Wrap KeyError from CV primitive map
disinvite Feb 11, 2026
9d719a4
weird -> verified
disinvite Feb 12, 2026
4e9cce5
Clean up cvinfo type comments
disinvite Feb 12, 2026
f3ebb84
Drop tests for type.is_signed
disinvite Feb 12, 2026
497bc13
Improve some variable names to reflect type changes
disinvite Feb 12, 2026
b15e5bb
Fix dropped parametrize var
disinvite Feb 12, 2026
965659e
Add a few tests for reading type keys
disinvite Feb 12, 2026
171bfab
Use existing CV primitive in ScalarType wrapper
disinvite Feb 12, 2026
b44a6ab
Merge branch 'master' into strong-type-for-cvdump-key
disinvite Feb 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions reccmp/compare/ingest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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)


Expand Down
14 changes: 8 additions & 6 deletions reccmp/compare/mutate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down
7 changes: 6 additions & 1 deletion reccmp/cvdump/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
761 changes: 761 additions & 0 deletions reccmp/cvdump/cvinfo.py

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions reccmp/cvdump/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down Expand Up @@ -76,7 +77,7 @@ class GdataEntry(NamedTuple):

section: int
offset: int
type: str
type: CvdumpTypeKey
name: str
is_global: bool

Expand Down Expand Up @@ -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",
)
Expand Down
13 changes: 7 additions & 6 deletions reccmp/cvdump/symbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import re
from re import Match
from typing import NamedTuple
from reccmp.cvdump.types import CvdumpTypeKey


logger = logging.getLogger(__name__)
Expand All @@ -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


Expand All @@ -21,7 +22,7 @@ class LdataEntry(NamedTuple):

section: int
offset: int
type: str
type: CvdumpTypeKey
name: str


Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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"),
)

Expand Down
Loading