Skip to content

Commit

Permalink
headers: Generate a globals.h header with global variables
Browse files Browse the repository at this point in the history
  • Loading branch information
bwrsandman committed Sep 30, 2024
1 parent cda3885 commit b55980b
Show file tree
Hide file tree
Showing 10 changed files with 373 additions and 184 deletions.
98 changes: 80 additions & 18 deletions extracted_reversing_data_bw_141.json
Original file line number Diff line number Diff line change
Expand Up @@ -110068,6 +110068,34 @@
],
"signature": "unsigned int (struct SetupList *, int, int, int, int, int, int, int) __attribute__((stdcall))"
},
{
"kind": "FUNCTIONPROTO",
"type": "SetupList__ListBoxDraw",
"size": 4,
"call_type": "__stdcall",
"result": "uint32_t",
"args": [
"struct SetupList *",
"int",
"int",
"int",
"int",
"int",
"int",
"int"
],
"arg_names": [
"",
"",
"",
"",
"",
"",
"",
""
],
"signature": "uint32_t (struct SetupList *, int, int, int, int, int, int, int) __attribute__((stdcall))"
},
{
"kind": "STRUCT_DECL",
"type": "struct SetupList",
Expand Down Expand Up @@ -110140,7 +110168,7 @@
},
{
"name": "ListBoxDraw",
"type": "SetupList__ListBoxDraw_t **",
"type": "SetupList__ListBoxDraw *",
"offset": 620
},
{
Expand Down Expand Up @@ -125838,6 +125866,40 @@
"offset": 592
}
]
},
{
"kind": "FUNCTIONPROTO",
"type": "globals_funcptr__DAT_00eb9a98_t",
"size": 4,
"call_type": "__fastcall",
"result": "void",
"args": [
"void *",
"const void *",
"struct MobileWallHug *"
],
"arg_names": [
"this",
"edx",
"param_3"
],
"signature": "void (void *, const void *, struct MobileWallHug *) __attribute__((fastcall))"
},
{
"kind": "FUNCTIONPROTO",
"type": "globals_funcptr__PTR_00fa51d0_t",
"size": 4,
"call_type": "__cdecl",
"result": "void",
"args": [
"int",
"int"
],
"arg_names": [
"",
""
],
"signature": "void (int, int)"
}
],
"functions": [
Expand Down Expand Up @@ -146238,27 +146300,27 @@
{
"name": "FLOAT_00bf33f0",
"type": "float",
"address": 12534472
"address": 12530672
},
{
"name": "DAT_00bf42c8",
"type": "int",
"address": 12534476
"address": 12534472
},
{
"name": "DAT_00bf42cc",
"type": "int",
"address": 12576908
"address": 12534476
},
{
"name": "DAT_00bfe88c",
"type": "int",
"address": 12577044
"address": 12576908
},
{
"name": "DAT_00bfe914",
"type": "int",
"address": 12530672
"address": 12577044
},
{
"name": "LH3DColor_ARRAY_00bff0b8",
Expand Down Expand Up @@ -146538,7 +146600,7 @@
{
"name": "FLOAT_ARRAY_00d1a280",
"type": "float[8]",
"address": 8
"address": 13738624
},
{
"name": "Point2D_00d3ee60",
Expand Down Expand Up @@ -146608,7 +146670,7 @@
{
"name": "CHAR_ARRAY_00d414d8",
"type": "char[128]",
"address": 128
"address": 13898968
},
{
"name": "ARGS_NEWGAME",
Expand Down Expand Up @@ -146718,12 +146780,12 @@
{
"name": "CHAR_ARRAY_00d99580",
"type": "char[200]",
"address": 200
"address": 14259584
},
{
"name": "CHAR_ARRAY_00d99648",
"type": "char[128]",
"address": 128
"address": 14259784
},
{
"name": "PTR_00d99724",
Expand Down Expand Up @@ -146843,32 +146905,32 @@
{
"name": "LH3DMesh_g_current_list_matrix",
"type": "struct LHMatrix[256]",
"address": 15320420
"address": 15322664
},
{
"name": "LH3DMesh_g_pack",
"type": "struct g_pack_t *",
"address": 15321444
"address": 15334964
},
{
"name": "LH3DMesh_g_current_matrix",
"type": "struct LHMatrix *",
"address": 15322664
"address": 15334984
},
{
"name": "LH3DMesh_g_b_dont_care_about_texture",
"type": "_Bool",
"address": 15334964
"address": 15334996
},
{
"name": "g_ptr_blocks__10LH3DIsland",
"type": "struct LandBlock *[256]",
"address": 15334984
"address": 15320420
},
{
"name": "g_index_block__10LH3DIsland",
"type": "uint8_t[32][32]",
"address": 15334996
"address": 15321444
},
{
"name": "LH3DObject",
Expand Down Expand Up @@ -146972,7 +147034,7 @@
},
{
"name": "DAT_00eb9a98",
"type": "void (*)(void *, const void *, struct MobileWallHug *) __attribute__((fastcall))",
"type": "globals_funcptr__DAT_00eb9a98_t*",
"address": 15440536
},
{
Expand Down Expand Up @@ -147092,7 +147154,7 @@
},
{
"name": "PTR_00fa51d0",
"type": "void (*)(int, int)",
"type": "globals_funcptr__PTR_00fa51d0_t*",
"address": 16404944
},
{
Expand Down
67 changes: 42 additions & 25 deletions scripts/headers/analyze_headers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from pathlib import Path
from typing import List, Tuple, Set, Optional, Dict, Union

from clang.cindex import TranslationUnit, Diagnostic, Config, TranslationUnitLoadError
from clang.cindex import TranslationUnit, Diagnostic, Config, Token, TranslationUnitLoadError


@dataclass
Expand Down Expand Up @@ -133,22 +133,26 @@ def parse_source(path: Optional[Path] = None, source: Optional[str] = None) -> T
return translation_unit


def extract_function_pointers(struct_type) -> Dict[str, TypeInfo]:
def extract_function_pointers(struct_type) -> Dict[str, Tuple[TypeInfo, int]]:
function_map: Dict[str, TypeInfo] = {}
for t in struct_type.get_fields():
if t.type.kind.name != "POINTER":
continue
p = t.type.get_pointee()
if p.kind.name != "FUNCTIONPROTO":
underlying_type = t.type
pointer_depth = 0
while underlying_type.kind.name == "POINTER":
pointer_depth += 1
underlying_type = underlying_type.get_pointee()

if pointer_depth == 0 or underlying_type.kind.name != "FUNCTIONPROTO":
continue
result = p.get_result().spelling
args = list(c.spelling for c in p.argument_types())

result = underlying_type.get_result().spelling
args = list(c.spelling for c in underlying_type.argument_types())
arg_names = list(c.spelling for c in t.get_definition().get_children() if c.kind.name == 'PARM_DECL')
if len(arg_names) == 0:
arg_names = [''] * len(args)
assert(len(args) == len(arg_names))
function_map[t.spelling] = TypeInfo(kind_name=p.kind.name, size=t.type.get_size(),
location=Path(t.location.file.name), children=(result, list(zip(args, arg_names)), p.spelling))
function_map[t.spelling] = (TypeInfo(kind_name=underlying_type.kind.name, size=t.type.get_size(),
location=Path(t.location.file.name), children=(result, list(zip(args, arg_names)), underlying_type.spelling)), pointer_depth)
return function_map


Expand All @@ -168,7 +172,7 @@ def extract_type_info(tu: TranslationUnit) -> Tuple[bool, Dict[str, TypeInfo]]:
children: List[Tuple[str, int] | Tuple[str, str, int]] | str | Tuple[str, List[str], str] = []
if c.kind.name == "STRUCT_DECL":
extra_types = extract_function_pointers(struct_type)
types.update((f"{name.removeprefix("struct ")}__{k}", v) for k, v in extra_types.items())
types.update((f"{name.removeprefix("struct ")}__{k}", v[0]) for k, v in extra_types.items())
children = []
for f in struct_type.get_fields():
child_name = f.spelling
Expand Down Expand Up @@ -249,23 +253,38 @@ def extract_globals_in_header_info(tu: TranslationUnit) -> Tuple[bool, Dict[str,
globals_cursor = next(c for c in tu.cursor.get_children() if c.kind.name == "VAR_DECL" and c.spelling == "globals")
globals_decl_cursor = globals_cursor.type.get_fields()
globals_init_list = list(next(i for i in globals_cursor.get_children() if i.kind.name == 'INIT_LIST_EXPR').get_children())
globals_init_cursor = (next(next(j.get_tokens()) for j in i.walk_preorder() if j.kind.name == 'INTEGER_LITERAL') for i in globals_init_list)
literal_map: dict[str, Token] = {}
for i in globals_init_list:
for j in i.walk_preorder():
if j.kind.name == 'MEMBER_REF':
key = j.spelling
elif j.kind.name == 'INTEGER_LITERAL':
value = next(j.get_tokens())
literal_map[key] = value

types: Dict[str, TypeInfo] = {}
extra_types = extract_function_pointers(globals_cursor.type.get_declaration().type)
types.update((f"globals_funcptr__{k}_t", v[0]) for k, v in extra_types.items())

found_issues = False
global_addresses: Dict[str, GlobalInfo] = {}
for identifier, literal in zip(globals_decl_cursor, globals_init_cursor):
for identifier in globals_decl_cursor:
if identifier.spelling in GLOBALS_TO_IGNORE:
continue
var_type = identifier.type.get_pointee().spelling
var_name = identifier.spelling
if var_name in extra_types:
var_type = f"globals_funcptr__{var_name}_t" + (extra_types[var_name][1] - 1) * "*"
else:
var_type = identifier.type.get_pointee().spelling
literal_spelling = literal_map[var_name].spelling
try:
literal_value: int = ast.literal_eval(literal.spelling)
literal_value: int = ast.literal_eval(literal_spelling)
except ValueError as e:
found_issues = True
sys.stderr.write(f"global declaration \"{identifier.spelling}\" can't parse: \"{literal.spelling}\"\n")
sys.stderr.write(f"global declaration \"{identifier.spelling}\" can't parse: \"{literal_spelling}\"\n")
continue
global_addresses[var_name] = GlobalInfo(var_type, literal_value)
return found_issues, global_addresses
return found_issues, global_addresses, types


def extract_function_info(tu: TranslationUnit, known_types: Set[str], decorated_names: Set[str],
Expand Down Expand Up @@ -344,7 +363,7 @@ def extract_function_info(tu: TranslationUnit, known_types: Set[str], decorated_


def main(out_path) -> bool:
paths: List[Path] = list(itertools.chain([Path("rtti.h")], *(p.glob("*.h") for p in PATHS)))
paths: List[Path] = list(filter(lambda x: x != Path("src/globals.h"), itertools.chain([Path("rtti.h")], *(p.glob("*.h") for p in PATHS))))
include_all_headers_src = '\n'.join(f'#include "{p}"' for p in paths)

found_issues, types = extract_type_info(parse_source(source=include_all_headers_src))
Expand All @@ -359,15 +378,14 @@ def main(out_path) -> bool:
decorated_names: Set[str] = set()
function_metadata: List[FunctionMetadata] = []
for path in paths:
found_issues |= extract_function_info(parse_source(path=path), set(types.keys()), decorated_names,
function_metadata)
found_issues |= extract_function_info(parse_source(path=path), set(types.keys()), decorated_names, function_metadata)

new_issues, global_values = extract_globals_info(parse_source(source=include_all_headers_src),
set(types.keys()))
new_issues, global_values = extract_globals_info(parse_source(source=include_all_headers_src), set(types.keys()))
found_issues |= new_issues

new_issues, globals_in_header_values = extract_globals_in_header_info(parse_source(path=Path("src/globals.h")), set(types.keys()))
new_issues, globals_in_header_values, globals_extra_types = extract_globals_in_header_info(parse_source(path=Path("globals.h")))
global_values.update(globals_in_header_values)
types |= globals_extra_types
found_issues |= new_issues

# for global_name, (global_type, global_value) in global_values.items():
Expand Down Expand Up @@ -418,8 +436,7 @@ def main(out_path) -> bool:
f.consolidate_thiscall()
result_functions.append(asdict(f))

result_globals: List[Dict[str, str | int]] = [dict(name=global_name, type=g.type_name, value=g.address) for
global_name, g in global_values.items()]
result_globals: List[Dict[str, str | int]] = [dict(name=global_name, type=g.type_name, address=g.address) for global_name, g in global_values.items()]

result = dict(types=result_types, functions=result_functions, globals=result_globals)

Expand Down
Loading

0 comments on commit b55980b

Please sign in to comment.