mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2025-05-14 08:12:19 +00:00
Move handling of HI16/LO16 relocs for non-relocatable reference sections into elf parsing by patching the output binary (fixes patch regeneration) (#127)
This commit is contained in:
parent
b18e0ca2dd
commit
198de1b5cf
2 changed files with 32 additions and 11 deletions
32
src/elf.cpp
32
src/elf.cpp
|
@ -104,10 +104,10 @@ bool read_symbols(N64Recomp::Context& context, const ELFIO::elfio& elf_file, ELF
|
||||||
|
|
||||||
if (section_index < context.sections.size()) {
|
if (section_index < context.sections.size()) {
|
||||||
auto section_offset = value - elf_file.sections[section_index]->get_address();
|
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);
|
|
||||||
uint32_t vram = static_cast<uint32_t>(value);
|
uint32_t vram = static_cast<uint32_t>(value);
|
||||||
uint32_t num_instructions = type == ELFIO::STT_FUNC ? size / 4 : 0;
|
uint32_t num_instructions = type == ELFIO::STT_FUNC ? size / 4 : 0;
|
||||||
uint32_t rom_address = static_cast<uint32_t>(section_offset + section.rom_addr);
|
uint32_t rom_address = static_cast<uint32_t>(section_offset + section.rom_addr);
|
||||||
|
const uint32_t* words = reinterpret_cast<const uint32_t*>(context.rom.data() + rom_address);
|
||||||
|
|
||||||
section.function_addrs.push_back(vram);
|
section.function_addrs.push_back(vram);
|
||||||
context.functions_by_vram[vram].push_back(context.functions.size());
|
context.functions_by_vram[vram].push_back(context.functions.size());
|
||||||
|
@ -551,6 +551,36 @@ ELFIO::section* read_sections(N64Recomp::Context& context, const N64Recomp::ElfP
|
||||||
return a.address < b.address;
|
return a.address < b.address;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Patch the ROM word for HI16 and LO16 reference symbol relocs to non-relocatable sections.
|
||||||
|
for (size_t i = 0; i < section_out.relocs.size(); i++) {
|
||||||
|
auto& reloc = section_out.relocs[i];
|
||||||
|
if (reloc.reference_symbol && (reloc.type == N64Recomp::RelocType::R_MIPS_HI16 || reloc.type == N64Recomp::RelocType::R_MIPS_LO16)) {
|
||||||
|
bool target_section_relocatable = context.is_reference_section_relocatable(reloc.target_section);
|
||||||
|
if (!target_section_relocatable) {
|
||||||
|
uint32_t reloc_rom_addr = reloc.address - section_out.ram_addr + section_out.rom_addr;
|
||||||
|
uint32_t reloc_rom_word = byteswap(*reinterpret_cast<const uint32_t*>(context.rom.data() + reloc_rom_addr));
|
||||||
|
|
||||||
|
uint32_t ref_section_vram = context.get_reference_section_vram(reloc.target_section);
|
||||||
|
uint32_t full_immediate = reloc.target_section_offset + ref_section_vram;
|
||||||
|
|
||||||
|
uint32_t imm;
|
||||||
|
|
||||||
|
if (reloc.type == N64Recomp::RelocType::R_MIPS_HI16) {
|
||||||
|
imm = (full_immediate >> 16) + ((full_immediate >> 15) & 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
imm = full_immediate & 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
*reinterpret_cast<uint32_t*>(context.rom.data() + reloc_rom_addr) = byteswap(reloc_rom_word | imm);
|
||||||
|
// Remove the reloc by setting it to a type of NONE.
|
||||||
|
reloc.type = N64Recomp::RelocType::R_MIPS_NONE;
|
||||||
|
reloc.reference_symbol = false;
|
||||||
|
reloc.symbol_index = (uint32_t)-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -184,19 +184,10 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con
|
||||||
reloc_reference_symbol = reloc.symbol_index;
|
reloc_reference_symbol = reloc.symbol_index;
|
||||||
// Don't try to relocate special section symbols.
|
// Don't try to relocate special section symbols.
|
||||||
if (context.is_regular_reference_section(reloc.target_section) || reloc_section == N64Recomp::SectionAbsolute) {
|
if (context.is_regular_reference_section(reloc.target_section) || reloc_section == N64Recomp::SectionAbsolute) {
|
||||||
|
// TODO this may not be needed anymore as HI16/LO16 relocs to non-relocatable sections is handled directly in elf parsing.
|
||||||
bool ref_section_relocatable = context.is_reference_section_relocatable(reloc.target_section);
|
bool ref_section_relocatable = context.is_reference_section_relocatable(reloc.target_section);
|
||||||
// Resolve HI16 and LO16 reference symbol relocs to non-relocatable sections by patching the instruction immediate.
|
// Resolve HI16 and LO16 reference symbol relocs to non-relocatable sections by patching the instruction immediate.
|
||||||
if (!ref_section_relocatable && (reloc_type == N64Recomp::RelocType::R_MIPS_HI16 || reloc_type == N64Recomp::RelocType::R_MIPS_LO16)) {
|
if (!ref_section_relocatable && (reloc_type == N64Recomp::RelocType::R_MIPS_HI16 || reloc_type == N64Recomp::RelocType::R_MIPS_LO16)) {
|
||||||
uint32_t ref_section_vram = context.get_reference_section_vram(reloc.target_section);
|
|
||||||
uint32_t full_immediate = reloc.target_section_offset + ref_section_vram;
|
|
||||||
|
|
||||||
if (reloc_type == N64Recomp::RelocType::R_MIPS_HI16) {
|
|
||||||
imm = (full_immediate >> 16) + ((full_immediate >> 15) & 1);
|
|
||||||
}
|
|
||||||
else if (reloc_type == N64Recomp::RelocType::R_MIPS_LO16) {
|
|
||||||
imm = full_immediate & 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The reloc has been processed, so set it to none to prevent it getting processed a second time during instruction code generation.
|
// The reloc has been processed, so set it to none to prevent it getting processed a second time during instruction code generation.
|
||||||
reloc_type = N64Recomp::RelocType::R_MIPS_NONE;
|
reloc_type = N64Recomp::RelocType::R_MIPS_NONE;
|
||||||
reloc_reference_symbol = (size_t)-1;
|
reloc_reference_symbol = (size_t)-1;
|
||||||
|
|
Loading…
Add table
Reference in a new issue