#include #include #include #include #include #include #include "accumulation.h" #include "emit.h" /* Notes: Datapins for same var/symbol are randomized in order of their level, from bottom of nest to top Between CUs, types with the same name HAVE TO HAVE the same layout -> randomized together */ struct OPTIONS { std::string out_file; std::string load_targets_file; std::string dump_targets_file; std::vector spslr_files; bool no_new_targets = false; bool is_module = false; }; int main(int argc, char** argv) { static option long_options[] = { { "help", no_argument, 0, 0 }, { "out", required_argument, 0, 0 }, { "load-targets", required_argument, 0, 0 }, { "dump-targets", required_argument, 0, 0 }, { "no-new-targets", no_argument, 0, 0 }, { "module", no_argument, 0, 0 }, { 0, 0, 0, 0 } }; OPTIONS opts{}; int option_index = 0; int c; while ((c = getopt_long(argc, argv, "h:o:", long_options, &option_index)) == 0) { const option& opt = long_options[option_index]; std::string optname { opt.name }; if (optname == "help") { std::cout << "Usage:\n" << " spslr_patchcompile --out= [options] ...\n\n" << "Options:\n" << " --read-targets=\n" << " --emit-targets=\n" << " --no-new-targets\n" << " --module\n"; return 0; } else if (optname == "out") { opts.out_file = optarg; } else if (optname == "load-targets") { opts.load_targets_file = optarg; } else if (optname == "dump-targets") { opts.dump_targets_file = optarg; } else if (optname == "no-new-targets") { opts.no_new_targets = true; } else if (optname == "module") { opts.is_module = true; } else { std::cerr << "Invalid option, try \"--help\"!\n"; return 1; } } for (int i = optind; i < argc; ++i) opts.spslr_files.emplace_back(argv[i]); if (opts.out_file.empty()) { std::cerr << "Missing output file path, supply it via --out=!\n"; return 1; } if (opts.spslr_files.empty()) { std::cerr << "Missing spslr files! Pass one or more .spslr metadata files as positional arguments.\n"; return 1; } if (opts.no_new_targets && opts.load_targets_file.empty()) { std::cerr << "--no-new-targets requires --load-targets\n"; return 1; } if (!opts.load_targets_file.empty()) { if (!load_target_map(opts.load_targets_file)) { std::cerr << "Failed to load target map: " << opts.load_targets_file << "\n"; return 1; } } if (!accumulate(opts.spslr_files, opts.no_new_targets)) { std::cerr << "Failed to accumulate data from spslr directory!" << std::endl; return 1; } std::filesystem::path out_path { opts.out_file }; if (out_path.has_parent_path()) { std::error_code ec; std::filesystem::create_directories(out_path.parent_path(), ec); if (ec) { std::cerr << "failed to create output directory '" << out_path.parent_path().string() << "': " << ec.message() << "\n"; return 1; } } std::ofstream out(out_path); if (!out) { std::cerr << "Failed to open output file!" << std::endl; return 1; } if (!emit_patcher_program_asm(out, opts.is_module)) { std::cerr << "Failed to write emit patcher program!" << std::endl; return 1; } if (!opts.dump_targets_file.empty()) { if (!dump_target_map(opts.dump_targets_file)) { std::cerr << "Failed to write target map: " << opts.dump_targets_file << "\n"; return 1; } } return 0; }