Implement fixed address and globally loaded sections in mods, respect section index in mod self-section relocs (#150)

This commit is contained in:
Wiseguy 2025-07-19 03:39:41 -04:00 committed by GitHub
parent 6860826da3
commit c1a6dc93bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 28 additions and 3 deletions

View File

@ -104,6 +104,8 @@ namespace N64Recomp {
bool executable = false;
bool relocatable = false; // TODO is this needed? relocs being non-empty should be an equivalent check.
bool has_mips32_relocs = false;
bool fixed_address = false; // Only used in mods, indicates that the section shouldn't be relocated or placed into mod memory.
bool globally_loaded = false; // Only used in mods, indicates that the section's functions should be globally loaded. Does not actually load the section's contents into ram.
std::optional<uint32_t> got_ram_addr = std::nullopt;
};

View File

@ -20,6 +20,11 @@ struct FileSubHeaderV1 {
uint32_t string_data_size;
};
enum class SectionFlags : uint32_t {
FixedAddress = 1 << 0,
GloballyLoaded = 1 << 1,
};
struct SectionHeaderV1 {
uint32_t flags;
uint32_t file_offset;
@ -172,10 +177,22 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
cur_section.bss_size = section_header->bss_size;
cur_section.name = "mod_section_" + std::to_string(section_index);
cur_section.relocatable = true;
cur_section.fixed_address = (section_header->flags & static_cast<uint32_t>(SectionFlags::FixedAddress)) != 0;
cur_section.globally_loaded = (section_header->flags & static_cast<uint32_t>(SectionFlags::GloballyLoaded)) != 0;
if (cur_section.fixed_address && !cur_section.globally_loaded) {
printf("Fixed address sections that aren't globally loaded aren't currently supported\n");
return false;
}
if (cur_section.globally_loaded && !cur_section.fixed_address) {
printf("A globally loaded section must have a fixed address\n");
return false;
}
uint32_t num_funcs = section_header->num_funcs;
uint32_t num_relocs = section_header->num_relocs;
const FuncV1* funcs = reinterpret_data<FuncV1>(data, offset, num_funcs);
if (funcs == nullptr) {
printf("Failed to read funcs (count: %d)\n", num_funcs);

View File

@ -152,6 +152,7 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con
}
N64Recomp::RelocType reloc_type = N64Recomp::RelocType::R_MIPS_NONE;
bool has_reloc = false;
uint32_t reloc_section = 0;
uint32_t reloc_target_section_offset = 0;
size_t reloc_reference_symbol = (size_t)-1;
@ -162,6 +163,7 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con
// Check if this instruction has a reloc.
if (section.relocs.size() > 0 && section.relocs[reloc_index].address == instr_vram) {
has_reloc = true;
// Get the reloc data for this instruction
const auto& reloc = section.relocs[reloc_index];
reloc_section = reloc.target_section;
@ -257,7 +259,7 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con
return true;
};
auto print_func_call_by_address = [&generator, reloc_target_section_offset, reloc_section, reloc_reference_symbol, reloc_type, &context, &func, &static_funcs_out, &needs_link_branch, &print_indent, &process_delay_slot, &print_link_branch]
auto print_func_call_by_address = [&generator, reloc_target_section_offset, has_reloc, reloc_section, reloc_reference_symbol, reloc_type, &context, &func, &static_funcs_out, &needs_link_branch, &print_indent, &process_delay_slot, &print_link_branch]
(uint32_t target_func_vram, bool tail_call = false, bool indent = false)
{
bool call_by_lookup = false;
@ -294,7 +296,11 @@ bool process_instruction(GeneratorType& generator, const N64Recomp::Context& con
}
}
else {
JalResolutionResult jal_result = resolve_jal(context, func.section_index, target_func_vram, matched_func_index);
uint32_t target_section = func.section_index;
if (has_reloc) {
target_section = reloc_section;
}
JalResolutionResult jal_result = resolve_jal(context, target_section, target_func_vram, matched_func_index);
switch (jal_result) {
case JalResolutionResult::NoMatch: