From 47c9033b619f5331eb34b28f2902cb1ac5f5406f Mon Sep 17 00:00:00 2001 From: Mr-Wiseguy Date: Sat, 20 Apr 2024 20:00:48 -0400 Subject: [PATCH] Improved reloc pairing --- src/main.cpp | 79 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 80b527c..6501747 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -546,8 +546,12 @@ std::unordered_set renamed_funcs{ "sqrtf", "memcpy", "memset", + "strcmp", + "strcat", + "strcpy", "strchr", "strlen", + "strtok", "sprintf", "bzero", "bcopy", @@ -571,6 +575,9 @@ std::unordered_set renamed_funcs{ "truncf", "vsprintf", "__assert", + "malloc", + "free", + "realloc", }; 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) { @@ -650,6 +657,7 @@ bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, EL name = name + "_recomp"; ignored = false; } + if (section_index < context.sections.size()) { auto section_offset = value - elf_file.sections[section_index]->get_address(); const uint32_t* words = reinterpret_cast(elf_file.sections[section_index]->get_data() + section_offset); @@ -669,6 +677,11 @@ bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, EL num_instructions = 0x50 / 4; } } + + // Suffix local symbols to prevent name conflicts. + if (bind == ELFIO::STB_LOCAL) { + name = fmt::format("{}_{:08X}", name, rom_address); + } if (num_instructions > 0) { context.section_functions[section_index].push_back(context.functions.size()); @@ -931,6 +944,8 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co section_out.relocs.resize(rel_accessor.get_entries_num()); // Track whether the previous reloc was a HI16 and its previous full_immediate bool prev_hi = false; + // Track whether the previous reloc was a LO16 + bool prev_lo = false; uint32_t prev_hi_immediate = 0; uint32_t prev_hi_symbol = std::numeric_limits::max(); @@ -977,9 +992,10 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co if (reloc_out.type == RecompPort::RelocType::R_MIPS_LO16) { if (prev_hi) { if (prev_hi_symbol != rel_symbol) { - fmt::print(stderr, "[WARN] Paired HI16 and LO16 relocations have different symbols\n" + fmt::print(stderr, "Paired HI16 and LO16 relocations have different symbols\n" " LO16 reloc index {} in section {} referencing symbol {} with offset 0x{:08X}\n", i, section_out.name, reloc_out.symbol_index, reloc_out.address); + return nullptr; } uint32_t rel_immediate = instr.getProcessedImmediate(); uint32_t full_immediate = (prev_hi_immediate << 16) + (int16_t)rel_immediate; @@ -989,12 +1005,33 @@ ELFIO::section* read_sections(RecompPort::Context& context, const RecompPort::Co section_out.relocs[i - 1].target_address = full_immediate; reloc_out.target_address = full_immediate; } + else { + if (prev_lo) { + uint32_t rel_immediate = instr.getProcessedImmediate(); + uint32_t full_immediate; + + if (prev_hi_symbol != rel_symbol) { + fmt::print(stderr, "[WARN] LO16 reloc index {} in section {} referencing symbol {} with offset 0x{:08X} follows LO16 with different symbol\n", + i, section_out.name, reloc_out.symbol_index, reloc_out.address); + } + + full_immediate = (prev_hi_immediate << 16) + (int16_t)rel_immediate; + reloc_out.target_address = full_immediate; + } + else { + fmt::print(stderr, "Unpaired LO16 reloc index {} in section {} referencing symbol {} with offset 0x{:08X}\n", + i, section_out.name, reloc_out.symbol_index, reloc_out.address); + return nullptr; + } + } + prev_lo = true; } else { if (prev_hi) { fmt::print(stderr, "Unpaired HI16 reloc index {} in section {} referencing symbol {} with offset 0x{:08X}\n", i - 1, section_out.name, section_out.relocs[i - 1].symbol_index, section_out.relocs[i - 1].address); return nullptr; } + prev_lo = false; } if (reloc_out.type == RecompPort::RelocType::R_MIPS_HI16) { @@ -1321,29 +1358,28 @@ int main(int argc, char** argv) { std::vector section_statics{}; section_statics.assign(statics_set.begin(), statics_set.end()); - size_t closest_func_index = 0; for (size_t static_func_index = 0; static_func_index < section_statics.size(); static_func_index++) { uint32_t static_func_addr = section_statics[static_func_index]; - // Search for the closest function - while (section_funcs[closest_func_index] < static_func_addr && closest_func_index < section_funcs.size()) { - closest_func_index++; - } // Determine the end of this static function uint32_t cur_func_end = static_cast(section.size + section.ram_addr); + // Search for the closest function + size_t closest_func_index = 0; + while (section_funcs[closest_func_index] < static_func_addr && closest_func_index < section_funcs.size()) { + closest_func_index++; + } + // Check if there's a nonstatic function after this one if (closest_func_index < section_funcs.size()) { // If so, use that function's address as the end of this one cur_func_end = section_funcs[closest_func_index]; } - uint32_t next_static_index = static_func_index + 1; - // Check if there's a known static function after this one - if (next_static_index < section_statics.size()) { - // If so, check if it's before the current end address - if (section_statics[next_static_index] < cur_func_end) { - cur_func_end = section_statics[next_static_index]; + // Check for any known statics after this function and truncate this function's size to make sure it doesn't overlap. + for (uint32_t checked_func : statics_set) { + if (checked_func > static_func_addr && checked_func < cur_func_end) { + cur_func_end = checked_func; } } @@ -1366,6 +1402,8 @@ int main(int argc, char** argv) { "void {}(uint8_t* rdram, recomp_context* ctx);\n", func.name); bool result; + size_t prev_num_statics = static_funcs_by_section[func.section_index].size(); + if (config.single_file_output) { result = RecompPort::recompile_function(context, config, func, single_output_file, static_funcs_by_section, false); } @@ -1373,6 +1411,19 @@ int main(int argc, char** argv) { result = recompile_single_function(context, config, func, config.output_func_path / (func.name + ".c"), static_funcs_by_section); } + // Add any new static functions that were found while recompiling this one. + size_t cur_num_statics = static_funcs_by_section[func.section_index].size(); + if (cur_num_statics != prev_num_statics) { + for (size_t new_static_index = prev_num_statics; new_static_index < cur_num_statics; new_static_index++) { + uint32_t new_static_vram = static_funcs_by_section[func.section_index][new_static_index]; + + if (!statics_set.contains(new_static_vram)) { + statics_set.emplace(new_static_vram); + section_statics.push_back(new_static_vram); + } + } + } + if (result == false) { fmt::print(stderr, "Error recompiling {}\n", func.name); std::exit(EXIT_FAILURE); @@ -1423,10 +1474,6 @@ int main(int argc, char** argv) { const auto& section = context.sections[section_index]; const auto& section_funcs = context.section_functions[section_index]; - if (section.name == ".cosection") { - fmt::print(""); - } - if (!section_funcs.empty()) { std::string_view section_name_trimmed{ section.name };