diff --git a/tooling/cmd_hooks.cpp b/tooling/cmd_hooks.cpp index e69de29b..f7b5d47c 100644 --- a/tooling/cmd_hooks.cpp +++ b/tooling/cmd_hooks.cpp @@ -0,0 +1,56 @@ +#include "tool.hpp" +#include +#include +#include + +static std::string output_file = "hooks.def"; + +bool generateHooksFile(const std::string &output_filepath) { + Options &options = Options::get(); + + try { + DatabaseManager db(options.db_path); + + std::vector fix_functions = db.getFunctionsByType(FileType::Fix); + + std::ofstream output_stream(output_filepath); + if (!output_stream.is_open()) { + spdlog::error("Could not open output file {}", output_filepath); + return false; + } + + spdlog::info("Generating hooks file: {}", 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(); + + output_stream << "HOOK(0x" << func.address << ", " << func.name << ") // " << filename << std::endl; + + spdlog::debug("Added hook: {} {} from {}", func.address, func.name, filename); + } + + output_stream.close(); + + spdlog::info("Generated {} hooks in {}", fix_functions.size(), output_filepath); + return true; + + } catch (const std::exception &e) { + spdlog::error("Error generating hooks file: {}", e.what()); + return false; + } +} + +void register_cmd_hooks(CLI::App &app) { + 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([]() { + spdlog::info("=== Generating hooks file: {} ===", output_file); + if (generateHooksFile(output_file)) { + spdlog::info("Successfully generated hooks file"); + } else { + spdlog::error("Failed to generate hooks file"); + } + }); +} diff --git a/tooling/database.cpp b/tooling/database.cpp index c5410597..abeb26b3 100644 --- a/tooling/database.cpp +++ b/tooling/database.cpp @@ -220,3 +220,36 @@ bool DatabaseManager::checkDuplicateNames() { return found_duplicates; } + +std::vector DatabaseManager::getFunctionsByType(FileType type) { + std::vector functions; + + const char *sql = R"( + SELECT name, address, filepath + FROM Functions + WHERE type = ? AND address != '' + ORDER BY address; + )"; + + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr) != SQLITE_OK) { + spdlog::error("Failed to prepare getFunctionsByType query: {}", sqlite3_errmsg(db)); + return functions; + } + + sqlite3_bind_int(stmt, 1, static_cast(type)); + + while (sqlite3_step(stmt) == SQLITE_ROW) { + FunctionInfo func; + func.name = (const char *)sqlite3_column_text(stmt, 0); + func.address = (const char *)sqlite3_column_text(stmt, 1); + func.filepath = (const char *)sqlite3_column_text(stmt, 2); + func.type = type; + func.is_import = false; // Functions table contains non-imports + + functions.push_back(func); + } + + sqlite3_finalize(stmt); + return functions; +} diff --git a/tooling/tool.cpp b/tooling/tool.cpp index 7f73327a..dfbbab42 100644 --- a/tooling/tool.cpp +++ b/tooling/tool.cpp @@ -7,6 +7,7 @@ void register_cmd_scan(CLI::App &app); void register_cmd_dump(CLI::App &app); void register_cmd_verify(CLI::App &app); +void register_cmd_hooks(CLI::App &app); int main(int argc, char *argv[]) { // Initialize spdlog @@ -39,6 +40,7 @@ int main(int argc, char *argv[]) { register_cmd_scan(app); register_cmd_dump(app); register_cmd_verify(app); + register_cmd_hooks(app); CLI11_PARSE(app, argc, argv); return 0; diff --git a/tooling/tool.hpp b/tooling/tool.hpp index 14951b63..4abda1b1 100644 --- a/tooling/tool.hpp +++ b/tooling/tool.hpp @@ -68,6 +68,7 @@ public: void rollbackTransaction(); bool checkDuplicateAddresses(); bool checkDuplicateNames(); + std::vector getFunctionsByType(FileType type); }; // File processing functions