From 873219d4c595496b1cbbe828fd2754087eea7fa4 Mon Sep 17 00:00:00 2001 From: Mr-Wiseguy Date: Sun, 23 Jun 2024 14:24:11 -0400 Subject: [PATCH] Consolidate context dumping toggle into a single bool, begin work on data symbol context dumping --- src/main.cpp | 93 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 34 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d1e46e2..bd01977 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -672,7 +672,7 @@ std::unordered_set renamed_funcs{ "_matherr", }; -bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, ELFIO::section* symtab_section, uint32_t entrypoint, bool has_entrypoint, bool use_absolute_symbols) { +bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, ELFIO::section* symtab_section, uint32_t entrypoint, bool has_entrypoint, bool use_absolute_symbols, bool do_renaming) { bool found_entrypoint_func = false; ELFIO::symbol_section_accessor symbols{ elf_file, symtab_section }; fmt::print("Num symbols: {}\n", symbols.get_symbols_num()); @@ -732,13 +732,15 @@ bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, EL type = ELFIO::STT_FUNC; } - if (reimplemented_funcs.contains(name)) { - reimplemented = true; - name = name + "_recomp"; - ignored = true; - } else if (ignored_funcs.contains(name)) { - name = name + "_recomp"; - ignored = true; + if (do_renaming) { + if (reimplemented_funcs.contains(name)) { + reimplemented = true; + name = name + "_recomp"; + ignored = true; + } else if (ignored_funcs.contains(name)) { + name = name + "_recomp"; + ignored = true; + } } auto& section = context.sections[section_index]; @@ -746,9 +748,11 @@ bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, EL // Check if this symbol is a function or has no type (like a regular glabel would) // Symbols with no type have a dummy entry created so that their symbol can be looked up for function calls if (ignored || type == ELFIO::STT_FUNC || type == ELFIO::STT_NOTYPE || type == ELFIO::STT_OBJECT) { - if (renamed_funcs.contains(name)) { - name = name + "_recomp"; - ignored = false; + if (do_renaming) { + if (renamed_funcs.contains(name)) { + name = name + "_recomp"; + ignored = false; + } } if (section_index < context.sections.size()) { @@ -1258,48 +1262,61 @@ std::vector reloc_names { "R_MIPS_GPREL16", }; -void dump_context(const RecompPort::Context& context, const std::filesystem::path& path) { - std::ofstream context_file {path}; +void dump_context(const RecompPort::Context& context, const std::filesystem::path& func_path, const std::filesystem::path& data_path) { + std::ofstream func_context_file {func_path}; + std::ofstream data_context_file {data_path}; + + fmt::print(func_context_file, "# Autogenerated from an ELF via N64Recomp\n"); + fmt::print(data_context_file, "# Autogenerated from an ELF via N64Recomp\n"); + + auto print_section = [](std::ofstream& output_file, const std::string& name, uint64_t rom_addr, uint64_t ram_addr, uint64_t size) { + fmt::print(output_file, + "[[section]]\n" + "name = \"{}\"\n" + "rom = 0x{:08X}\n" + "vram = 0x{:08X}\n" + "size = 0x{:X}\n" + "\n", + name, rom_addr, ram_addr, size); + }; for (size_t section_index = 0; section_index < context.sections.size(); section_index++) { const RecompPort::Section& section = context.sections[section_index]; const std::vector& section_funcs = context.section_functions[section_index]; if (!section_funcs.empty()) { - fmt::print(context_file, - "# Autogenerated from an ELF via N64Recomp\n" - "[[section]]\n" - "name = \"{}\"\n" - "rom = 0x{:08X}\n" - "vram = 0x{:08X}\n" - "size = 0x{:X}\n" - "\n", - section.name, section.rom_addr, section.ram_addr, section.size); + print_section(func_context_file, section.name, section.rom_addr, section.ram_addr, section.size); + print_section(data_context_file, section.name, section.rom_addr, section.ram_addr, section.size); + // Dump relocs into the function context file. if (!section.relocs.empty()) { - fmt::print(context_file, "relocs = [\n"); + fmt::print(func_context_file, "relocs = [\n"); for (const RecompPort::Reloc& reloc : section.relocs) { if (reloc.target_section == section_index || reloc.target_section == section.bss_section_index) { // TODO allow MIPS32 relocs for TLB mapping support. if (reloc.type == RecompPort::RelocType::R_MIPS_HI16 || reloc.type == RecompPort::RelocType::R_MIPS_LO16) { - fmt::print(context_file, " {{ type = \"{}\", vram = 0x{:08X}, target_vram = 0x{:08X} }},\n", + fmt::print(func_context_file, " {{ type = \"{}\", vram = 0x{:08X}, target_vram = 0x{:08X} }},\n", reloc_names[static_cast(reloc.type)], reloc.address, reloc.target_address); } } } - fmt::print(context_file, "]\n\n"); + fmt::print(func_context_file, "]\n\n"); } - fmt::print(context_file, "functions = [\n"); + // Dump functions into the function context file. + fmt::print(func_context_file, "functions = [\n"); for (const size_t& function_index : section_funcs) { const RecompPort::Function& func = context.functions[function_index]; - fmt::print(context_file, " {{ name = \"{}\", vram = 0x{:08X}, size = 0x{:X} }},\n", + fmt::print(func_context_file, " {{ name = \"{}\", vram = 0x{:08X}, size = 0x{:X} }},\n", func.name, func.vram, func.words.size() * sizeof(func.words[0])); } - fmt::print(context_file, "]\n\n"); + // Dump variables into the data context file. + + + fmt::print(func_context_file, "]\n\n"); } } } @@ -1326,6 +1343,9 @@ int main(int argc, char** argv) { std::exit(EXIT_FAILURE); }; + // TODO expose a way to dump the context from the command line. + bool dumping_context = false; + if (argc != 2) { fmt::print("Usage: {} [config file]\n", argv[0]); std::exit(EXIT_SUCCESS); @@ -1397,7 +1417,7 @@ int main(int argc, char** argv) { } // Read all of the symbols in the elf and look for the entrypoint function - bool found_entrypoint_func = read_symbols(context, elf_file, symtab_section, config.entrypoint, config.has_entrypoint, config.use_absolute_symbols); + bool found_entrypoint_func = read_symbols(context, elf_file, symtab_section, config.entrypoint, config.has_entrypoint, config.use_absolute_symbols, !dumping_context); // Add any manual functions add_manual_functions(context, elf_file, config.manual_functions); @@ -1405,6 +1425,12 @@ int main(int argc, char** argv) { if (config.has_entrypoint && !found_entrypoint_func) { exit_failure("Could not find entrypoint function\n"); } + + if (dumping_context) { + fmt::print("Dumping context\n"); + dump_context(context, "dump.toml", "data_dump.toml"); + return 0; + } } // Build a context from the provided symbols file. else if (!config.symbols_file_path.empty()) { @@ -1412,6 +1438,10 @@ int main(int argc, char** argv) { exit_failure("A ROM file must be provided when using a symbols file\n"); } + if (dumping_context) { + exit_failure("Cannot dump context when using a symbols file\n"); + } + std::vector rom = read_file(config.rom_file_path); if (rom.empty()) { exit_failure("Failed to load ROM file: " + config.rom_file_path.string() + "\n"); @@ -1485,11 +1515,6 @@ int main(int argc, char** argv) { std::vector> static_funcs_by_section{ context.sections.size() }; - // TODO expose a way to dump the context from the command line. Make sure not to rename functions when doing so. - //fmt::print("Dumping context\n"); - //dump_context(context, "dump.toml"); - //return 0; - fmt::print("Working dir: {}\n", std::filesystem::current_path().string()); // Stub out any functions specified in the config file.