From 9bc5c26bcc4368d1ccf910cd0bdef13e59eb35e3 Mon Sep 17 00:00:00 2001 From: MS <disinvite@users.noreply.github.com> Date: Sun, 9 Jun 2024 13:38:57 -0400 Subject: [PATCH] Handle S_BLOCK32 in cvdump symbols parser (#1012) --- tools/isledecomp/isledecomp/cvdump/symbols.py | 12 +++++- tools/isledecomp/tests/test_cvdump_symbols.py | 38 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tools/isledecomp/tests/test_cvdump_symbols.py diff --git a/tools/isledecomp/isledecomp/cvdump/symbols.py b/tools/isledecomp/isledecomp/cvdump/symbols.py index 22c1b32e..73cb152e 100644 --- a/tools/isledecomp/isledecomp/cvdump/symbols.py +++ b/tools/isledecomp/isledecomp/cvdump/symbols.py @@ -88,6 +88,10 @@ class CvdumpSymbolsParser: def __init__(self): self.symbols: list[SymbolsEntry] = [] self.current_function: Optional[SymbolsEntry] = None + # If we read an S_BLOCK32 node, increment this level. + # This is so we do not end the proc early by reading an S_END + # that indicates the end of the block. + self.block_level: int = 0 def read_line(self, line: str): if (match := self._symbol_line_generic_regex.match(line)) is not None: @@ -145,8 +149,14 @@ class CvdumpSymbolsParser: ) self.current_function.stack_symbols.append(new_symbol) + elif symbol_type == "S_BLOCK32": + self.block_level += 1 elif symbol_type == "S_END": - self.current_function = None + if self.block_level > 0: + self.block_level -= 1 + assert self.block_level >= 0 + else: + self.current_function = None elif symbol_type in self._unhandled_symbols: return else: diff --git a/tools/isledecomp/tests/test_cvdump_symbols.py b/tools/isledecomp/tests/test_cvdump_symbols.py new file mode 100644 index 00000000..f4ca1aff --- /dev/null +++ b/tools/isledecomp/tests/test_cvdump_symbols.py @@ -0,0 +1,38 @@ +"""Test Cvdump SYMBOLS parser, reading function stack/params""" + +from isledecomp.cvdump.symbols import CvdumpSymbolsParser + +PROC_WITH_BLOC = """ +(000638) S_GPROC32: [0001:000C6135], Cb: 00000361, Type: 0x10ED, RegistrationBook::ReadyWorld + Parent: 00000000, End: 00000760, Next: 00000000 + Debug start: 0000000C, Debug end: 0000035C + Flags: Frame Ptr Present +(00067C) S_BPREL32: [FFFFFFD0], Type: 0x10EC, this +(000690) S_BPREL32: [FFFFFFDC], Type: 0x10F5, checkmarkBuffer +(0006AC) S_BPREL32: [FFFFFFE8], Type: 0x10F6, letterBuffer +(0006C8) S_BPREL32: [FFFFFFF4], Type: T_SHORT(0011), i +(0006D8) S_BPREL32: [FFFFFFF8], Type: 0x10F8, players +(0006EC) S_BPREL32: [FFFFFFFC], Type: 0x1044, gameState +(000704) S_BLOCK32: [0001:000C624F], Cb: 000001DA, + Parent: 00000638, End: 0000072C +(00071C) S_BPREL32: [FFFFFFD8], Type: T_SHORT(0011), j +(00072C) S_END +(000730) S_BLOCK32: [0001:000C6448], Cb: 00000032, + Parent: 00000638, End: 0000075C +(000748) S_BPREL32: [FFFFFFD4], Type: 0x10FA, infoman +(00075C) S_END +(000760) S_END +""" + + +def test_sblock32(): + """S_END has double duty as marking the end of a function (S_GPROC32) + and a scope block (S_BLOCK32). Make sure we can distinguish between + the two and not end a function early.""" + parser = CvdumpSymbolsParser() + for line in PROC_WITH_BLOC.split("\n"): + parser.read_line(line) + + # 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