Improved reloc pairing
This commit is contained in:
parent
50d55bd171
commit
47c9033b61
79
src/main.cpp
79
src/main.cpp
|
@ -546,8 +546,12 @@ std::unordered_set<std::string> renamed_funcs{
|
|||
"sqrtf",
|
||||
"memcpy",
|
||||
"memset",
|
||||
"strcmp",
|
||||
"strcat",
|
||||
"strcpy",
|
||||
"strchr",
|
||||
"strlen",
|
||||
"strtok",
|
||||
"sprintf",
|
||||
"bzero",
|
||||
"bcopy",
|
||||
|
@ -571,6 +575,9 @@ std::unordered_set<std::string> 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<const uint32_t*>(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<uint32_t>::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<uint32_t> 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<uint32_t>(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 };
|
||||
|
||||
|
|
Loading…
Reference in a new issue