Match static function variables (#530)

* Match static function variables

* IsleApp::Tick static variables
This commit is contained in:
MS
2024-02-05 06:43:13 -05:00
committed by GitHub
parent 0497ef13fb
commit 264b9e815b
10 changed files with 167 additions and 17 deletions

View File

@@ -134,7 +134,9 @@ class Compare:
except UnicodeDecodeError:
pass
self._db.set_recomp_symbol(addr, sym.node_type, sym.name(), sym.size())
self._db.set_recomp_symbol(
addr, sym.node_type, sym.name(), sym.decorated_name, sym.size()
)
for lineref in cv.lines:
addr = self.recomp_bin.get_abs_addr(lineref.section, lineref.offset)
@@ -168,7 +170,12 @@ class Compare:
self._db.skip_compare(fun.offset)
for var in codebase.iter_variables():
self._db.match_variable(var.offset, var.name)
if var.is_static and var.parent_function is not None:
self._db.match_static_variable(
var.offset, var.name, var.parent_function
)
else:
self._db.match_variable(var.offset, var.name)
for tbl in codebase.iter_vtables():
self._db.match_vtable(tbl.offset, tbl.name)

View File

@@ -12,6 +12,7 @@ _SETUP_SQL = """
orig_addr int,
recomp_addr int,
name text,
decorated_name text,
size int,
should_skip int default(FALSE)
);
@@ -65,12 +66,13 @@ class CompareDb:
addr: int,
compare_type: Optional[SymbolType],
name: Optional[str],
decorated_name: Optional[str],
size: Optional[int],
):
compare_value = compare_type.value if compare_type is not None else None
self._db.execute(
"INSERT INTO `symbols` (recomp_addr, compare_type, name, size) VALUES (?,?,?,?)",
(addr, compare_value, name, size),
"INSERT INTO `symbols` (recomp_addr, compare_type, name, decorated_name, size) VALUES (?,?,?,?,?)",
(addr, compare_value, name, decorated_name, size),
)
def get_unmatched_strings(self) -> List[str]:
@@ -214,6 +216,56 @@ class CompareDb:
return did_match
def match_static_variable(self, addr: int, name: str, function_addr: int) -> bool:
"""Matching a static function variable by combining the variable name
with the decorated (mangled) name of its parent function."""
cur = self._db.execute(
"""SELECT name, decorated_name
FROM `symbols`
WHERE orig_addr = ?""",
(function_addr,),
)
if (result := cur.fetchone()) is None:
logger.error("No function for static variable: %s", name)
return False
# Get the friendly name for the "failed to match" error message
(function_name, decorated_name) = result
# Now we have to combine the variable name (read from the marker)
# and the decorated name of the enclosing function (the above variable)
# into a LIKE clause and try to match.
# For example, the variable "g_startupDelay" from function "IsleApp::Tick"
# has symbol: "?g_startupDelay@?1??Tick@IsleApp@@QAEXH@Z@4HA"
# The function's decorated name is: "?Tick@IsleApp@@QAEXH@Z"
cur = self._db.execute(
"""UPDATE `symbols`
SET orig_addr = ?
WHERE name LIKE '%' || ? || '%' || ? || '%'
AND orig_addr IS NULL
AND (compare_type = ? OR compare_type = ? OR compare_type IS NULL)""",
(
addr,
name,
decorated_name,
SymbolType.DATA.value,
SymbolType.POINTER.value,
),
)
did_match = cur.rowcount > 0
if not did_match:
logger.error(
"Failed to match static variable %s from function %s",
name,
function_name,
)
return did_match
def match_variable(self, addr: int, name: str) -> bool:
did_match = self._match_on(SymbolType.DATA, addr, name) or self._match_on(
SymbolType.POINTER, addr, name