From ac9879a4aacf25e4c3a880d5cc82039a53dc3052 Mon Sep 17 00:00:00 2001 From: Guus Waals <_@guusw.nl> Date: Mon, 2 Jun 2025 00:05:18 +0800 Subject: [PATCH] WIP Dump required function pointer types for globals --- game_re/gh_fix/r3_restore.cxx | 60 ++++++++++++------------ game_re/gh_fix/r3_windowUnlockCursor.cxx | 6 +-- game_re/gh_global.cxx | 12 ++--- game_re/gh_global.h | 12 ++--- game_re/gh_stub/getHWND.cxx | 2 +- game_re/gh_stub/level_displayFn.cxx | 4 +- game_re/r3/binders/dbg_mem.cxx | 37 ++++++++++----- java/ghidra/re3lib/DataTypeWriter.java | 7 ++- java/ghidra/re3lib/FunctionDumper.java | 19 ++------ java/ghidra/re3lib/TypeDumper.java | 25 +++++++++- tooling/cmd_hooks.cpp | 37 ++++++++++++--- 11 files changed, 134 insertions(+), 87 deletions(-) diff --git a/game_re/gh_fix/r3_restore.cxx b/game_re/gh_fix/r3_restore.cxx index 4977a27b..197a4dc3 100644 --- a/game_re/gh_fix/r3_restore.cxx +++ b/game_re/gh_fix/r3_restore.cxx @@ -4,37 +4,35 @@ #include extern "C" { -undefined IPT_fn_vActivateAllEntryElements(void); // 00505490 // IPT_fn_vActivateAllEntryElements // cdecl // Params: | Types: | Return: undefined -undefined FUN_00443120(undefined4 param_1); // 00443120 // FUN_00443120 // cdecl // Params: param_1 | Types: undefined4 | Return: undefined -undefined FUN_004fb300(void); // 004fb300 // FUN_004fb300 // cdecl // Params: | Types: | Return: undefined -undefined FUN_0047bae0(void); // 0047bae0 // FUN_0047bae0 // cdecl // Params: | Types: | Return: undefined -void r3_noop(void * p_cTxt1, void * p_cTxt2); // 00401100 // r3_noop // stdcall // Params: p_cTxt1;p_cTxt2 | Types: void *;void * | Return: void -undefined r3_load_textures_2(void); // 00471760 // r3_load_textures_2 // cdecl // Params: | Types: | Return: undefined -undefined gfx_init2(void); // 00470be0 // gfx_init2 // cdecl // Params: | Types: | Return: undefined -undefined FUN_00402470(undefined4 param_1); // 00402470 // FUN_00402470 // cdecl // Params: param_1 | Types: undefined4 | Return: undefined -undefined FUN_00470410(void); // 00470410 // FUN_00470410 // cdecl // Params: | Types: | Return: undefined -undefined FUN_00445460(void); // 00445460 // FUN_00445460 // cdecl // Params: | Types: | Return: undefined -undefined FUN_00442c50(void); // 00442c50 // FUN_00442c50 // cdecl // Params: | Types: | Return: undefined -undefined FUN_0051a7a0(short hGLDDevice, undefined4 param_2); // 0051a7a0 // FUN_0051a7a0 // cdecl // Params: hGLDDevice;param_2 | Types: short;undefined4 | Return: undefined -undefined r3_closeConcatTextureFile(void); // 004711d0 // r3_closeConcatTextureFile // cdecl // Params: | Types: | Return: undefined -undefined r3_processInput1(void); // 00446f10 // r3_processInput1 // cdecl // Params: | Types: | Return: undefined -undefined SND_fn_vResumeSound(void); // 0040a1e0 // SND_fn_vResumeSound // cdecl // Params: | Types: | Return: undefined -undefined FUN_004fa650(void); // 004fa650 // FUN_004fa650 // cdecl // Params: | Types: | Return: undefined -undefined FUN_00445440(void); // 00445440 // FUN_00445440 // cdecl // Params: | Types: | Return: undefined -undefined FUN_004725a0(void); // 004725a0 // FUN_004725a0 // cdecl // Params: | Types: | Return: undefined -undefined FUN_00470db0(void); // 00470db0 // FUN_00470db0 // cdecl // Params: | Types: | Return: undefined -undefined r3_windowLockCursor(void); // 00401320 // r3_windowLockCursor // cdecl // Params: | Types: | Return: undefined -undefined FUN_00442f70(undefined4 param_1); // 00442f70 // FUN_00442f70 // cdecl // Params: param_1 | Types: undefined4 | Return: undefined -undefined FUN_00470350(void); // 00470350 // FUN_00470350 // cdecl // Params: | Types: | Return: undefined -undefined FUN_00503710(void); // 00503710 // FUN_00503710 // cdecl // Params: | Types: | Return: undefined -undefined FUN_00472150(void); // 00472150 // FUN_00472150 // cdecl // Params: | Types: | Return: undefined -undefined FUN_0051a900(short hGLDDevice); // 0051a900 // FUN_0051a900 // cdecl // Params: hGLDDevice | Types: short | Return: undefined -undefined level_displayFn(void); // 00446fc0 // level_displayFn // cdecl // Params: | Types: | Return: undefined -undefined FUN_005038e0(void); // 005038e0 // FUN_005038e0 // cdecl // Params: | Types: | Return: undefined - -// 00401490 // r3_restore(stdcall) -// Parameters: param_1 | Types: undefined4 | Return: undefined4 +undefined FUN_00470350(void); // 00470350 // FUN_00470350 // cdecl +undefined r3_load_textures_2(void); // 00471760 // r3_load_textures_2 // cdecl +void level_displayFn(byte param); // 00446fc0 // level_displayFn // cdecl +void r3_noop(void * p_cTxt1, void * p_cTxt2); // 00401100 // r3_noop // stdcall +undefined r3_closeConcatTextureFile(void); // 004711d0 // r3_closeConcatTextureFile // cdecl +undefined FUN_00470db0(void); // 00470db0 // FUN_00470db0 // cdecl +undefined FUN_00503710(void); // 00503710 // FUN_00503710 // cdecl +undefined FUN_00443120(undefined4 param_1); // 00443120 // FUN_00443120 // cdecl +undefined FUN_00442c50(void); // 00442c50 // FUN_00442c50 // cdecl +undefined FUN_00470410(void); // 00470410 // FUN_00470410 // cdecl +undefined FUN_00472150(void); // 00472150 // FUN_00472150 // cdecl +undefined FUN_00445460(void); // 00445460 // FUN_00445460 // cdecl +undefined FUN_00442f70(undefined4 param_1); // 00442f70 // FUN_00442f70 // cdecl +undefined FUN_00445440(void); // 00445440 // FUN_00445440 // cdecl +undefined SND_fn_vResumeSound(void); // 0040a1e0 // SND_fn_vResumeSound // cdecl +undefined IPT_fn_vActivateAllEntryElements(void); // 00505490 // IPT_fn_vActivateAllEntryElements // cdecl +undefined r3_windowLockCursor(void); // 00401320 // r3_windowLockCursor // cdecl +undefined FUN_00402470(undefined4 param_1); // 00402470 // FUN_00402470 // cdecl +undefined gfx_init2(void); // 00470be0 // gfx_init2 // cdecl +undefined FUN_004725a0(void); // 004725a0 // FUN_004725a0 // cdecl +undefined FUN_0051a900(short hGLDDevice); // 0051a900 // FUN_0051a900 // cdecl +undefined FUN_005038e0(void); // 005038e0 // FUN_005038e0 // cdecl +undefined FUN_004fb300(void); // 004fb300 // FUN_004fb300 // cdecl +undefined FUN_004fa650(void); // 004fa650 // FUN_004fa650 // cdecl +undefined r3_processInput1(void); // 00446f10 // r3_processInput1 // cdecl +undefined FUN_0047bae0(void); // 0047bae0 // FUN_0047bae0 // cdecl +undefined FUN_0051a7a0(short hGLDDevice, undefined4 param_2); // 0051a7a0 // FUN_0051a7a0 // cdecl +// 00401490 /* WARNING: Inlined function: r3_get_engine_mode */ undefined4 __stdcall r3_restore(undefined4 param_1) @@ -54,7 +52,7 @@ undefined4 __stdcall r3_restore(undefined4 param_1) SetWindowTextA(g_gameHWND,g_windowTitleRestoring); UpdateWindow(hWnd); SetForegroundWindow(hWnd); - if ((code *)p_fn_vDisplayAll == r3_noop) { + if (p_fn_vDisplayAll == r3_noop) { /* Set window callback? */ p_fn_vDisplayAll = level_displayFn; } diff --git a/game_re/gh_fix/r3_windowUnlockCursor.cxx b/game_re/gh_fix/r3_windowUnlockCursor.cxx index 13dbb7fe..e3180b8f 100644 --- a/game_re/gh_fix/r3_windowUnlockCursor.cxx +++ b/game_re/gh_fix/r3_windowUnlockCursor.cxx @@ -5,10 +5,8 @@ extern "C" { -// 004013a0 // r3_windowUnlockCursor(cdecl) -// Parameters: | Types: | Return: void - -void default r3_windowUnlockCursor(void) +// 004013a0 +void r3_windowUnlockCursor(void) { HCURSOR hCursor; diff --git a/game_re/gh_global.cxx b/game_re/gh_global.cxx index 60dfbe77..362326f1 100644 --- a/game_re/gh_global.cxx +++ b/game_re/gh_global.cxx @@ -1,7 +1,7 @@ // AUTO-GENERATED FILE #include undefined4& crt_unhandled_exception_handler= (undefined4&) GH_MEM(0x00404a58); -undefined4& DAT_00597ca0= (undefined4&) GH_MEM(0x00597ca0); +dword& DWORD_00597ca0= (dword&) GH_MEM(0x00597ca0); char(&s__s_not_initialized__005b63e0)[20] = reinterpret_cast(GH_MEM(0x005b63e0)); char(&s_Please_run_the__s_setup__005b63f4)[28] = reinterpret_cast(GH_MEM(0x005b63f4)); char(&s_dashCC)[4] = reinterpret_cast(GH_MEM(0x005b6410)); @@ -64,8 +64,8 @@ undefined1& g_errModDInput= (undefined1&) GH_MEM(0x005bd29c); undefined4& DAT_005bd454= (undefined4&) GH_MEM(0x005bd454); const char* s__jc_z_d__s_005bd460 = "\\jc\\z%d:%s"; // 005bd460 undefined1& g_errModMmg= (undefined1&) GH_MEM(0x005bd58c); -undefined* PTR_r3_processInput1_005bdb1c = (undefined*)&GH_MEM(0x005bdb1c); // 005bdb1c -pointer& p_fn_vDisplayAll= (pointer&) GH_MEM(0x005bdb24); +pointer& PTR_r3_processInput1_005bdb1c= (pointer&) GH_MEM(0x005bdb1c); +level_displayFn *& p_fn_vDisplayAll= (level_displayFn *&) GH_MEM(0x005bdb24); const char* s_R3_DVD_005bdfd8 = "R3_DVD"; // 005bdfd8 const char* s_R3_DVD_005be0ec = "R3_DVD"; // 005be0ec const char* s__s_DVD_missing_005be0f4 = "%s DVD missing "; // 005be0f4 @@ -115,8 +115,8 @@ char *& PTR_005cf9b4= (char *&) GH_MEM(0x005cf9b4); GameStructure& g_currentBinkMovie= (GameStructure&) GH_MEM(0x005d2660); char(&s_volumeNameBuffer)[128] = reinterpret_cast(GH_MEM(0x005d27b0)); r3_main_data& r3_main_data_005d28b6= (r3_main_data&) GH_MEM(0x005d28b6); -undefined4& g_soundOnHD= (undefined4&) GH_MEM(0x005d29bc); -undefined4& g_complete= (undefined4&) GH_MEM(0x005d29c0); +dword& g_soundOnHD= (dword&) GH_MEM(0x005d29bc); +dword& g_complete= (dword&) GH_MEM(0x005d29c0); int& g_windowInitialized= (int&) GH_MEM(0x0077d0a4); int& g_runMaximized= (int&) GH_MEM(0x0077d0a8); undefined4& g_engineShouldRun= (undefined4&) GH_MEM(0x0077d0b0); @@ -137,7 +137,7 @@ char(&s_quitting1)[64] = reinterpret_cast(GH_MEM(0x007825c0)); char(&s_wndStrQuiting)[56] = reinterpret_cast(GH_MEM(0x00782600)); GAM_EngineStructure& g_stEngineStructure= (GAM_EngineStructure&) GH_MEM(0x007d7dc0); undefined4& DAT_007d9cc4= (undefined4&) GH_MEM(0x007d9cc4); -undefined4& g_config_unused0= (undefined4&) GH_MEM(0x007d9df0); +byte& g_config_unused0= (byte&) GH_MEM(0x007d9df0); char(&g_driveLetter)[4] = reinterpret_cast(GH_MEM(0x007d9e70)); undefined4& g_GLI_adapter= (undefined4&) GH_MEM(0x007edd60); undefined1& g_GLI_tnl= (undefined1&) GH_MEM(0x007edd64); diff --git a/game_re/gh_global.h b/game_re/gh_global.h index e3d9a0a2..38e5cebb 100644 --- a/game_re/gh_global.h +++ b/game_re/gh_global.h @@ -6,7 +6,7 @@ extern undefined4& crt_unhandled_exception_handler; // 00404a58 -extern undefined4& DAT_00597ca0; // 00597ca0 +extern dword& DWORD_00597ca0; // 00597ca0 extern char(&s__s_not_initialized__005b63e0)[20]; // 005b63e0 extern char(&s_Please_run_the__s_setup__005b63f4)[28]; // 005b63f4 extern char(&s_dashCC)[4]; // 005b6410 @@ -69,8 +69,8 @@ extern undefined1& g_errModDInput; // 005bd29c extern undefined4& DAT_005bd454; // 005bd454 extern const char* s__jc_z_d__s_005bd460; // 005bd460 extern undefined1& g_errModMmg; // 005bd58c -extern undefined* PTR_r3_processInput1_005bdb1c; // 005bdb1c -extern pointer& p_fn_vDisplayAll; // 005bdb24 +extern pointer& PTR_r3_processInput1_005bdb1c; // 005bdb1c +extern level_displayFn *& p_fn_vDisplayAll; // 005bdb24 extern const char* s_R3_DVD_005bdfd8; // 005bdfd8 extern const char* s_R3_DVD_005be0ec; // 005be0ec extern const char* s__s_DVD_missing_005be0f4; // 005be0f4 @@ -120,8 +120,8 @@ extern char *& PTR_005cf9b4; // 005cf9b4 extern GameStructure& g_currentBinkMovie; // 005d2660 extern char(&s_volumeNameBuffer)[128]; // 005d27b0 extern r3_main_data& r3_main_data_005d28b6; // 005d28b6 -extern undefined4& g_soundOnHD; // 005d29bc -extern undefined4& g_complete; // 005d29c0 +extern dword& g_soundOnHD; // 005d29bc +extern dword& g_complete; // 005d29c0 extern int& g_windowInitialized; // 0077d0a4 extern int& g_runMaximized; // 0077d0a8 extern undefined4& g_engineShouldRun; // 0077d0b0 @@ -142,7 +142,7 @@ extern char(&s_quitting1)[64]; // 007825c0 extern char(&s_wndStrQuiting)[56]; // 00782600 extern GAM_EngineStructure& g_stEngineStructure; // 007d7dc0 extern undefined4& DAT_007d9cc4; // 007d9cc4 -extern undefined4& g_config_unused0; // 007d9df0 +extern byte& g_config_unused0; // 007d9df0 extern char(&g_driveLetter)[4]; // 007d9e70 extern undefined4& g_GLI_adapter; // 007edd60 extern undefined1& g_GLI_tnl; // 007edd64 diff --git a/game_re/gh_stub/getHWND.cxx b/game_re/gh_stub/getHWND.cxx index a8ddb3f7..94ff9a8d 100644 --- a/game_re/gh_stub/getHWND.cxx +++ b/game_re/gh_stub/getHWND.cxx @@ -9,5 +9,5 @@ // 00401300 // getHWND extern "C" HWND getHWND(void) { - return gh_stub_impl_stdcall<0x00401300, typedef HWND HWND__ *>(); + return gh_stub_impl_stdcall<0x00401300, HWND>(); } diff --git a/game_re/gh_stub/level_displayFn.cxx b/game_re/gh_stub/level_displayFn.cxx index 088e258e..f15cf90f 100644 --- a/game_re/gh_stub/level_displayFn.cxx +++ b/game_re/gh_stub/level_displayFn.cxx @@ -8,6 +8,6 @@ // 00446fc0 // level_displayFn -extern "C" undefined level_displayFn(void) { - return gh_stub_impl_cdecl<0x00446fc0, undefined>(); +extern "C" void level_displayFn(byte param) { + gh_stub_impl_cdecl<0x00446fc0, void>(param); } diff --git a/game_re/r3/binders/dbg_mem.cxx b/game_re/r3/binders/dbg_mem.cxx index 9a5ba69c..468ae309 100644 --- a/game_re/r3/binders/dbg_mem.cxx +++ b/game_re/r3/binders/dbg_mem.cxx @@ -10,13 +10,19 @@ static uintptr_t g_gh_translationOffset{}; extern "C" { -#define cdecl -#define stdcall __stdcall -#define HOOK(addr, name, call_conv) void call_conv name(void *); +#define HOOK(addr, name) void name(void *); +#define HOOK_S0(addr, name) void __stdcall name(); +#define HOOK_S1(addr, name) void __stdcall name(int); +#define HOOK_S2(addr, name) void __stdcall name(int, int); +#define HOOK_S3(addr, name) void __stdcall name(int, int, int); +#define HOOK_S4(addr, name) void __stdcall name(int, int, int, int); #include "hooks.def" #undef HOOK -#undef stdcall -#undef cdecl +#undef HOOK_S0 +#undef HOOK_S1 +#undef HOOK_S2 +#undef HOOK_S3 +#undef HOOK_S4 } struct R3Bin { @@ -37,19 +43,20 @@ struct R3Bin { g_gh_translationOffset = translationOffset = uintptr_t(module) - GH_BASE_ADDR; - std::string msg = fmt::format("Rayman3.exe Base address: 0x{:x}\n", uintptr_t(module)); + std::string msg = + fmt::format("Rayman3.exe Base address: 0x{:x}\n", uintptr_t(module)); OutputDebugStringA(msg.c_str()); - - msg = fmt::format("Rayman3.exe Translation offset: 0x{:x}\n", translationOffset); + + msg = fmt::format("Rayman3.exe Translation offset: 0x{:x}\n", + translationOffset); OutputDebugStringA(msg.c_str()); - + // Now we have to relocate the module to the new base address relocateModule(); patchFunctions(); } - inline void relocate(void *instr, void *from, - void *originalPointee) { + inline void relocate(void *instr, void *from, void *originalPointee) { void *relocated_addr = (void *)(uintptr_t(from) + translationOffset); void *relocated_to = (void *)(uintptr_t(originalPointee) + translationOffset); @@ -179,7 +186,13 @@ struct R3Bin { "Failed to patch function {} at {} (RVA: {})", name, resolved, at)); } void patchFunctions() { -#define HOOK(addr, name, call_conv) patchFunction((void*)addr, &name, #name); +#define HOOK(addr, name) patchFunction((void *)addr, &name, #name); +#define HOOK_S0(addr, name) HOOK(addr, name) +#define HOOK_S1(addr, name) HOOK(addr, name) +#define HOOK_S2(addr, name) HOOK(addr, name) +#define HOOK_S3(addr, name) HOOK(addr, name) +#define HOOK_S4(addr, name) HOOK(addr, name) + #include "hooks.def" } diff --git a/java/ghidra/re3lib/DataTypeWriter.java b/java/ghidra/re3lib/DataTypeWriter.java index 2ff37189..5445276f 100644 --- a/java/ghidra/re3lib/DataTypeWriter.java +++ b/java/ghidra/re3lib/DataTypeWriter.java @@ -149,7 +149,6 @@ public class DataTypeWriter { blocks.put(funcName, new Block(funcType, code.toString(), dependencies)); } } - // Step 3: Topological sort and write List sortedBlocks = topologicalSort(blocks); @@ -171,7 +170,7 @@ public class DataTypeWriter { StringBuilder code = new StringBuilder(); // if (dt.getDisplayName().contains("HIE_tduLinkedObject")) { - // System.out.println("DEBUG " + dt.getDisplayName()); + // System.out.println("DEBUG " + dt.getDisplayName()); // } if (dt.equals(DataType.DEFAULT)) { @@ -189,7 +188,7 @@ public class DataTypeWriter { } else if (dt instanceof Union) { writeUnionBlock((Union) dt, code, dependencies); } else if (dt instanceof Enum) { - if(dt.getDisplayName().contains(".conflict")) + if (dt.getDisplayName().contains(".conflict")) return null; writeEnumBlock((Enum) dt, code, dependencies); } else if (dt instanceof TypeDef) { @@ -265,7 +264,7 @@ public class DataTypeWriter { DataType depType = getImmediateDependencyType(componentDataType); if (depType != null) { dependencies.add(depType.getDisplayName()); - if(depType instanceof FunctionDefinition) { + if (depType instanceof FunctionDefinition) { requiredFunctionTypes.add(depType.getDisplayName()); } } diff --git a/java/ghidra/re3lib/FunctionDumper.java b/java/ghidra/re3lib/FunctionDumper.java index 25a3b356..626070fe 100644 --- a/java/ghidra/re3lib/FunctionDumper.java +++ b/java/ghidra/re3lib/FunctionDumper.java @@ -82,7 +82,7 @@ public class FunctionDumper { // Helper method to extract return type from Ghidra function private String extractReturnType(Function function) { var returnType = function.getReturnType(); - return returnType != null ? returnType.toString() : "void"; + return returnType != null ? returnType.getDisplayName() : "void"; } boolean isValidFunction(Function function) { @@ -179,8 +179,6 @@ public class FunctionDumper { String parameterNames = extractParameterNames(externalFunction); String parameterTypes = extractParameterTypes(externalFunction); String returnType = extractReturnType(externalFunction); - - script.println("Parameters: " + parameterNames + " | Types: " + parameterTypes + " | Return: " + returnType); try (PrintWriter writer2 = new PrintWriter(f4, "UTF-8")) { writer2.println("// AUTO-GENERATED FILE!!!!"); @@ -345,9 +343,9 @@ public class FunctionDumper { HashMap replacementMap = new HashMap<>(); String newFunctionName = sanitizedFunctionName; - if (callingConvention != FunctionDatabase.CallingConvention.Stdcall || - callingConvention != FunctionDatabase.CallingConvention.Fastcall) { - newFunctionName = callingConventionName + " " + newFunctionName; + if (callingConvention == FunctionDatabase.CallingConvention.Stdcall || + callingConvention == FunctionDatabase.CallingConvention.Fastcall) { + newFunctionName = "__" + callingConvention.toString() + " " + newFunctionName; } String originalFunctionName = function.getName(); @@ -486,14 +484,9 @@ public class FunctionDumper { String callingConv = externalFunction.getCallingConventionName(); FunctionDatabase.CallingConvention conv = FunctionDatabase.CallingConvention.fromString(callingConv); - // Add parameter information to the comment - String extParamNames = extractParameterNames(externalFunction); - String extParamTypes = extractParameterTypes(externalFunction); - String extReturnType = extractReturnType(externalFunction); - headers.add("" + proto + "; // " + externalFunction.getEntryPoint() + " // " - + name + " // " + conv + " // Params: " + extParamNames + " | Types: " + extParamTypes + " | Return: " + extReturnType); + + name + " // " + conv); } for (String header : headers) { @@ -501,8 +494,6 @@ public class FunctionDumper { } writer2.println(); writer2.print("// " + function.getEntryPoint()); - writer2.println(" // " + function.getName() + "(" + callingConvention + ")"); - writer2.println("// Parameters: " + parameterNames + " | Types: " + parameterTypes + " | Return: " + returnType); String codeString = codeWriter.toString(); for (HashMap.Entry entry : replacementMap.entrySet()) { String oldName = entry.getKey(); diff --git a/java/ghidra/re3lib/TypeDumper.java b/java/ghidra/re3lib/TypeDumper.java index 9e244a19..1de39383 100644 --- a/java/ghidra/re3lib/TypeDumper.java +++ b/java/ghidra/re3lib/TypeDumper.java @@ -8,6 +8,7 @@ import java.util.Iterator; import java.util.List; import ghidra.app.script.GhidraScript; +import ghidra.program.model.address.Address; import ghidra.program.model.data.CategoryPath; import ghidra.program.model.data.Composite; import ghidra.program.model.data.DataType; @@ -20,7 +21,9 @@ import ghidra.program.model.data.TypeDef; import ghidra.program.model.data.TypedefDataType; import ghidra.program.model.data.Union; import ghidra.program.model.data.UnionDataType; +import ghidra.program.model.listing.Data; import ghidra.program.model.listing.Program; +import re3lib.FunctionDatabase.GlobalEntry; public class TypeDumper { Program currentProgram; @@ -35,6 +38,25 @@ public class TypeDumper { public void run() throws Exception { ProgramBasedDataTypeManager dtm = currentProgram.getDataTypeManager(); + HashSet requiredFunctionTypes = new HashSet<>(); + FunctionDatabase fd = new FunctionDatabase(script); + List globals = fd.loadAllGlobals(); + for (GlobalEntry globalEntry : globals) { + // Fetch type of global from ghidra + Address addr = globalEntry.address; + if (globalEntry.name == "p_fn_vDisplayAll") + script.println("EEEEE"); + + Data data = script.getDataAt(addr); + if (data != null) { + DataType type = data.getDataType(); + if (type instanceof FunctionDefinition) { + requiredFunctionTypes.add(type.getDisplayName()); + script.println("Adding required global function type: " + type.getDisplayName()); + } + } + } + HashSet typeBlacklist = Utils.loadSimpleBlacklist(RemanConfig.INSTANCE.typeBlacklistPath); HashSet categoryPathBlacklist = Utils .loadSimpleBlacklist(RemanConfig.INSTANCE.categoryPathBlacklistPath); @@ -89,7 +111,7 @@ public class TypeDumper { if (dt instanceof Structure || dt instanceof TypeDef || dt instanceof EnumDataType || dt instanceof Union || dt instanceof Enum || dt instanceof FunctionDefinition) { - if (dt.getDisplayName().contains("NormalizeFn") || dt.getDisplayName().contains("_M_IX86")) + if (dt.getDisplayName().contains("level_displayFn") || dt.getDisplayName().contains("_M_IX86")) script.println("DEBUG " + dt.getDisplayName() + " - " + dt.getClass().getSimpleName()); // if (dt.getDisplayName().contains("tdstObjectTypeElement_") || @@ -113,6 +135,7 @@ public class TypeDumper { writer.println("#include "); DataTypeWriter dtw = new DataTypeWriter(dtm, writer); + dtw.requiredFunctionTypes = requiredFunctionTypes; dtw.write(filteredTypes, script.getMonitor()); Utils.headerGuardPost(writer, "STRUCTS"); diff --git a/tooling/cmd_hooks.cpp b/tooling/cmd_hooks.cpp index 31c8d2a4..e69c4b63 100644 --- a/tooling/cmd_hooks.cpp +++ b/tooling/cmd_hooks.cpp @@ -11,7 +11,8 @@ bool generateHooksFile(const std::string &output_filepath) { try { DatabaseManager db(options.db_path); - std::vector fix_functions = db.getFunctionsByType(FileType::Fix); + std::vector fix_functions = + db.getFunctionsByType(FileType::Fix); std::ofstream output_stream(output_filepath); if (!output_stream.is_open()) { @@ -23,17 +24,40 @@ bool generateHooksFile(const std::string &output_filepath) { for (const auto &func : fix_functions) { // Extract just the filename from the full path - std::string filename = std::filesystem::path(func.filepath).filename().string(); + std::string filename = + std::filesystem::path(func.filepath).filename().string(); std::string conv_str = callingConventionToString(func.calling_convention); + size_t numParams = 0; + if (!func.parameter_types.empty()) { + std::string params = func.parameter_types; + std::stringstream ss(params); + std::string param; + while (std::getline(ss, param, ';')) { + if (!param.empty()) { + numParams++; + } + } + } - output_stream << "HOOK(0x" << func.address << ", " << func.name << ", " << conv_str << ") // " << filename << std::endl; + if (func.parameter_types == "void") + numParams = 0; - spdlog::debug("Added hook: {} {} {} from {}", func.address, func.name, conv_str, filename); + if (conv_str == "stdcall") { + output_stream << "HOOK_S" << numParams << "(0x" << func.address << ", " + << func.name << ") // " << filename << std::endl; + } else { + output_stream << "HOOK(0x" << func.address << ", " << func.name + << ") // " << filename << std::endl; + } + + spdlog::debug("Added hook: {} {} {} from {}", func.address, func.name, + conv_str, filename); } output_stream.close(); - spdlog::info("Generated {} hooks in {}", fix_functions.size(), output_filepath); + spdlog::info("Generated {} hooks in {}", fix_functions.size(), + output_filepath); return true; } catch (const std::exception &e) { @@ -43,7 +67,8 @@ bool generateHooksFile(const std::string &output_filepath) { } void register_cmd_hooks(CLI::App &app) { - auto cmd = app.add_subcommand("hooks", "Generate hooks file for Fix-type functions"); + auto cmd = + app.add_subcommand("hooks", "Generate hooks file for Fix-type functions"); cmd->add_option("-o,--output", output_file, "Output file for hooks") ->default_val("hooks.def"); cmd->final_callback([]() {