Some cleanup by making some Context members private

This commit is contained in:
Mr-Wiseguy 2024-08-18 14:11:03 -04:00
parent 5f1b9a845b
commit f300b6dccc
8 changed files with 191 additions and 126 deletions

View file

@ -81,14 +81,12 @@ int main(int argc, const char** argv) {
// Populate R_MIPS_26 reloc symbol indices. Start by building a map of vram address to matching reference symbols. // Populate R_MIPS_26 reloc symbol indices. Start by building a map of vram address to matching reference symbols.
std::unordered_map<uint32_t, std::vector<size_t>> reference_symbols_by_vram{}; std::unordered_map<uint32_t, std::vector<size_t>> reference_symbols_by_vram{};
for (size_t reference_symbol_index = 0; reference_symbol_index < mod_context.reference_symbols.size(); reference_symbol_index++) { for (size_t reference_symbol_index = 0; reference_symbol_index < mod_context.num_regular_reference_symbols(); reference_symbol_index++) {
const auto& sym = mod_context.reference_symbols[reference_symbol_index]; const auto& sym = mod_context.get_regular_reference_symbol(reference_symbol_index);
uint16_t section_index = sym.section_index; uint16_t section_index = sym.section_index;
if (section_index != N64Recomp::SectionAbsolute && section_index != N64Recomp::SectionSelf) { if (section_index != N64Recomp::SectionAbsolute && section_index != N64Recomp::SectionSelf) {
const auto& section = mod_context.reference_sections[section_index]; uint32_t section_vram = mod_context.get_reference_section_vram(section_index);
reference_symbols_by_vram[section_vram + sym.section_offset].push_back(reference_symbol_index);
uint32_t vram = section.ram_addr + sym.section_offset;
reference_symbols_by_vram[vram].push_back(reference_symbol_index);
} }
} }
@ -97,8 +95,8 @@ int main(int argc, const char** argv) {
for (auto& reloc : section.relocs) { for (auto& reloc : section.relocs) {
if (reloc.type == N64Recomp::RelocType::R_MIPS_26 && reloc.reference_symbol) { if (reloc.type == N64Recomp::RelocType::R_MIPS_26 && reloc.reference_symbol) {
if (mod_context.is_regular_reference_section(reloc.target_section)) { if (mod_context.is_regular_reference_section(reloc.target_section)) {
const auto& target_section = mod_context.reference_sections[reloc.target_section]; uint32_t section_vram = mod_context.get_reference_section_vram(reloc.target_section);
uint32_t target_vram = target_section.ram_addr + reloc.target_section_offset; uint32_t target_vram = section_vram + reloc.target_section_offset;
auto find_funcs_it = reference_symbols_by_vram.find(target_vram); auto find_funcs_it = reference_symbols_by_vram.find(target_vram);
bool found = false; bool found = false;

View file

@ -113,21 +113,9 @@ static bool read_dependency_file(const std::filesystem::path& dependency_path, N
throw toml::parse_error("Invalid dependency function", function_node.source()); throw toml::parse_error("Invalid dependency function", function_node.source());
} }
const std::string& function_name = function_node.ref<std::string>(); const std::string& function_name = function_node.ref<std::string>();
context.reference_symbols_by_name[function_name] = N64Recomp::SymbolReference { size_t symbol_index = import_symbol_dependency_indices.size();
.section_index = N64Recomp::SectionImport,
.symbol_index = import_symbol_dependency_indices.size() context.add_import_symbol(function_name, dependency_index, symbol_index);
};
context.import_symbols.emplace_back(
N64Recomp::ImportSymbol {
.base = N64Recomp::ReferenceSymbol {
.name = function_name,
.section_index = N64Recomp::SectionImport,
.section_offset = 0,
.is_function = true
},
.dependency_index = dependency_index,
}
);
import_symbol_dependency_indices.emplace_back(dependency_index); import_symbol_dependency_indices.emplace_back(dependency_index);
} }
} }
@ -328,22 +316,8 @@ N64Recomp::Context build_mod_context(const N64Recomp::Context& input_context, st
// If this is the patch section, create a replacement for this function. // If this is the patch section, create a replacement for this function.
if (patch_section || force_patch_section) { if (patch_section || force_patch_section) {
// Find the corresponding symbol in the reference symbols. // Find the corresponding symbol in the reference symbols.
bool original_func_exists = false; N64Recomp::SymbolReference cur_reference;
auto find_sym_it = input_context.reference_symbols_by_name.find(cur_func.name); bool original_func_exists = input_context.find_regular_reference_symbol(cur_func.name, cur_reference);
// Check if the function was found.
if (find_sym_it == input_context.reference_symbols_by_name.end()) {
original_func_exists = false;
}
// Ignore reference symbols in the import section, as those are imports and not original symbols.
else if (
find_sym_it->second.section_index == N64Recomp::SectionImport ||
find_sym_it->second.section_index == N64Recomp::SectionHook) {
original_func_exists = false;
}
else {
original_func_exists = true;
}
// Check that the function being patched exists in the original reference symbols. // Check that the function being patched exists in the original reference symbols.
if (!original_func_exists) { if (!original_func_exists) {
@ -352,20 +326,21 @@ N64Recomp::Context build_mod_context(const N64Recomp::Context& input_context, st
} }
// Check that the reference symbol is actually a function. // Check that the reference symbol is actually a function.
const auto& reference_symbol = input_context.get_reference_symbol(find_sym_it->second.section_index, find_sym_it->second.symbol_index); const auto& reference_symbol = input_context.get_reference_symbol(cur_reference);
if (!reference_symbol.is_function) { if (!reference_symbol.is_function) {
fmt::print("Function {0} is marked as a patch, but {0} was a variable in the original ROM!\n", cur_func.name); fmt::print("Function {0} is marked as a patch, but {0} was a variable in the original ROM!\n", cur_func.name);
return {}; return {};
} }
const auto& reference_section = input_context.reference_sections[reference_symbol.section_index]; uint32_t reference_section_vram = input_context.get_reference_section_vram(reference_symbol.section_index);
uint32_t reference_section_rom = input_context.get_reference_section_rom(reference_symbol.section_index);
// Add a replacement for this function to the output context. // Add a replacement for this function to the output context.
ret.replacements.emplace_back( ret.replacements.emplace_back(
N64Recomp::FunctionReplacement { N64Recomp::FunctionReplacement {
.func_index = (uint32_t)output_func_index, .func_index = (uint32_t)output_func_index,
.original_section_vrom = reference_section.rom_addr, .original_section_vrom = reference_section_rom,
.original_vram = reference_section.ram_addr + reference_symbol.section_offset, .original_vram = reference_section_vram + reference_symbol.section_offset,
.flags = force_patch_section ? N64Recomp::ReplacementFlags::Force : N64Recomp::ReplacementFlags{} .flags = force_patch_section ? N64Recomp::ReplacementFlags::Force : N64Recomp::ReplacementFlags{}
} }
); );
@ -405,16 +380,17 @@ N64Recomp::Context build_mod_context(const N64Recomp::Context& input_context, st
if (cur_reloc.type == N64Recomp::RelocType::R_MIPS_NONE) { if (cur_reloc.type == N64Recomp::RelocType::R_MIPS_NONE) {
continue; continue;
} }
// Reloc to an imported symbol. // Reloc to a special section symbol.
if (cur_reloc.target_section == N64Recomp::SectionImport) { if (!input_context.is_regular_reference_section(cur_reloc.target_section)) {
section_out.relocs.emplace_back(cur_reloc); section_out.relocs.emplace_back(cur_reloc);
} }
// Reloc to a reference symbol. // Reloc to a reference symbol.
else if (cur_reloc.reference_symbol) { else if (cur_reloc.reference_symbol) {
const auto& reloc_section = input_context.reference_sections[cur_reloc.target_section]; bool is_relocatable = input_context.is_reference_section_relocatable(cur_reloc.target_section);
uint32_t section_vram = input_context.get_reference_section_vram(cur_reloc.target_section);
// Patch relocations to non-relocatable reference sections. // Patch relocations to non-relocatable reference sections.
if (!reloc_section.relocatable) { if (!is_relocatable) {
uint32_t reloc_target_address = reloc_section.ram_addr + cur_reloc.target_section_offset; uint32_t reloc_target_address = section_vram + cur_reloc.target_section_offset;
uint32_t reloc_rom_address = cur_reloc.address - cur_section.ram_addr + cur_section.rom_addr; uint32_t reloc_rom_address = cur_reloc.address - cur_section.ram_addr + cur_section.rom_addr;
uint32_t* reloc_word_ptr = reinterpret_cast<uint32_t*>(ret.rom.data() + reloc_rom_address); uint32_t* reloc_word_ptr = reinterpret_cast<uint32_t*>(ret.rom.data() + reloc_rom_address);
@ -477,7 +453,7 @@ N64Recomp::Context build_mod_context(const N64Recomp::Context& input_context, st
ret.import_symbols = input_context.import_symbols; ret.import_symbols = input_context.import_symbols;
// Copy the reference sections from the input context as-is for resolving reference symbol relocations. // Copy the reference sections from the input context as-is for resolving reference symbol relocations.
ret.reference_sections = input_context.reference_sections; ret.copy_reference_sections_from(input_context);
good = true; good = true;
return ret; return ret;
@ -510,7 +486,10 @@ int main(int argc, const char** argv) {
} }
// Use the reference context to build a reference symbol list for the actual context. // Use the reference context to build a reference symbol list for the actual context.
context.import_reference_context(reference_context); if (!context.import_reference_context(reference_context)) {
fmt::print(stderr, "Internal error: failed to import reference context\n");
return EXIT_FAILURE;
}
} }
for (const std::filesystem::path& cur_data_sym_path : config.data_reference_syms_file_paths) { for (const std::filesystem::path& cur_data_sym_path : config.data_reference_syms_file_paths) {

View file

@ -154,7 +154,16 @@ namespace N64Recomp {
ReplacementFlags flags; ReplacementFlags flags;
}; };
struct Context { class Context {
private:
//// Reference symbols (used for populating relocations for patches)
// A list of the sections that contain the reference symbols.
std::vector<ReferenceSection> reference_sections;
// A list of the reference symbols.
std::vector<ReferenceSymbol> reference_symbols;
// Mapping of symbol name to reference symbol index.
std::unordered_map<std::string, SymbolReference> reference_symbols_by_name;
public:
std::vector<Section> sections; std::vector<Section> sections;
std::vector<Function> functions; std::vector<Function> functions;
// A list of the list of each function (by index in `functions`) in a given section // A list of the list of each function (by index in `functions`) in a given section
@ -169,14 +178,6 @@ namespace N64Recomp {
// A mapping of function name to index in the functions vector // A mapping of function name to index in the functions vector
std::unordered_map<std::string, size_t> functions_by_name; std::unordered_map<std::string, size_t> functions_by_name;
//// Reference symbols (used for populating relocations for patches)
// A list of the sections that contain the reference symbols.
std::vector<ReferenceSection> reference_sections;
// A list of the reference symbols.
std::vector<ReferenceSymbol> reference_symbols;
// Mapping of symbol name to reference symbol index.
std::unordered_map<std::string, SymbolReference> reference_symbols_by_name;
//// Mod dependencies and their symbols //// Mod dependencies and their symbols
std::vector<Dependency> dependencies; std::vector<Dependency> dependencies;
std::vector<ImportSymbol> import_symbols; std::vector<ImportSymbol> import_symbols;
@ -187,7 +188,7 @@ namespace N64Recomp {
std::vector<FunctionReplacement> replacements; std::vector<FunctionReplacement> replacements;
// Imports sections and function symbols from a provided context into this context's reference sections and reference functions. // Imports sections and function symbols from a provided context into this context's reference sections and reference functions.
void import_reference_context(const Context& reference_context); bool import_reference_context(const Context& reference_context);
// Reads a data symbol file and adds its contents into this context's reference data symbols. // Reads a data symbol file and adds its contents into this context's reference data symbols.
bool read_data_reference_syms(const std::filesystem::path& data_syms_file_path); bool read_data_reference_syms(const std::filesystem::path& data_syms_file_path);
@ -204,6 +205,38 @@ namespace N64Recomp {
return section_index != SectionImport && section_index != SectionHook; return section_index != SectionImport && section_index != SectionHook;
} }
bool find_reference_symbol(const std::string& symbol_name, SymbolReference& ref_out) const {
auto find_sym_it = reference_symbols_by_name.find(symbol_name);
// Check if the symbol was found.
if (find_sym_it == reference_symbols_by_name.end()) {
return false;
}
ref_out = find_sym_it->second;
return true;
}
bool reference_symbol_exists(const std::string& symbol_name) const {
SymbolReference dummy_ref;
return find_reference_symbol(symbol_name, dummy_ref);
}
bool find_regular_reference_symbol(const std::string& symbol_name, SymbolReference& ref_out) const {
SymbolReference ref_found;
if (!find_reference_symbol(symbol_name, ref_found)) {
return false;
}
// Ignore reference symbols in special sections.
if (!is_regular_reference_section(ref_found.section_index)) {
return false;
}
ref_out = ref_found;
return true;
}
const ReferenceSymbol& get_reference_symbol(uint16_t section_index, size_t symbol_index) const { const ReferenceSymbol& get_reference_symbol(uint16_t section_index, size_t symbol_index) const {
if (section_index == SectionImport) { if (section_index == SectionImport) {
return import_symbols[symbol_index].base; return import_symbols[symbol_index].base;
@ -214,16 +247,102 @@ namespace N64Recomp {
return reference_symbols[symbol_index]; return reference_symbols[symbol_index];
} }
size_t num_regular_reference_symbols() {
return reference_symbols.size();
}
const ReferenceSymbol& get_regular_reference_symbol(size_t index) const {
return reference_symbols[index];
}
const ReferenceSymbol& get_reference_symbol(const SymbolReference& ref) const { const ReferenceSymbol& get_reference_symbol(const SymbolReference& ref) const {
return get_reference_symbol(ref.section_index, ref.symbol_index); return get_reference_symbol(ref.section_index, ref.symbol_index);
} }
bool is_reference_section_relocatable(uint16_t section_index) const { bool is_reference_section_relocatable(uint16_t section_index) const {
if (section_index == SectionImport || section_index == SectionHook) { if (section_index == SectionAbsolute) {
return false;
}
else if (section_index == SectionImport || section_index == SectionHook) {
return true; return true;
} }
return reference_sections[section_index].relocatable; return reference_sections[section_index].relocatable;
} }
bool add_reference_symbol(const std::string& symbol_name, uint16_t section_index, uint32_t vram, bool is_function) {
uint32_t section_vram;
if (section_index == SectionAbsolute) {
section_vram = 0;
}
else if (section_index < reference_sections.size()) {
section_vram = reference_sections[section_index].ram_addr;
}
// Invalid section index.
else {
return false;
}
// TODO Check if reference_symbols_by_name already contains the name and show a conflict error if so.
reference_symbols_by_name.emplace(symbol_name, N64Recomp::SymbolReference{
.section_index = section_index,
.symbol_index = reference_symbols.size()
});
reference_symbols.emplace_back(N64Recomp::ReferenceSymbol{
.name = symbol_name,
.section_index = section_index,
.section_offset = vram - section_vram,
.is_function = is_function
});
return true;
}
void add_import_symbol(const std::string& symbol_name, size_t dependency_index, size_t symbol_index) {
reference_symbols_by_name[symbol_name] = N64Recomp::SymbolReference {
.section_index = N64Recomp::SectionImport,
.symbol_index = symbol_index
};
import_symbols.emplace_back(
N64Recomp::ImportSymbol {
.base = N64Recomp::ReferenceSymbol {
.name = symbol_name,
.section_index = N64Recomp::SectionImport,
.section_offset = 0,
.is_function = true
},
.dependency_index = dependency_index,
}
);
}
uint32_t get_reference_section_vram(uint16_t section_index) const {
if (section_index == N64Recomp::SectionAbsolute) {
return 0;
}
else if (!is_regular_reference_section(section_index)) {
return 0;
}
else {
return reference_sections[section_index].ram_addr;
}
}
uint32_t get_reference_section_rom(uint16_t section_index) const {
if (section_index == N64Recomp::SectionAbsolute) {
return (uint32_t)-1;
}
else if (!is_regular_reference_section(section_index)) {
return (uint32_t)-1;
}
else {
return reference_sections[section_index].rom_addr;
}
}
void copy_reference_sections_from(const Context& rhs) {
reference_sections = rhs.reference_sections;
}
}; };
bool recompile_function(const Context& context, const Function& func, const std::string& recomp_include, std::ofstream& output_file, std::span<std::vector<uint32_t>> static_funcs, bool write_header); bool recompile_function(const Context& context, const Function& func, const std::string& recomp_include, std::ofstream& output_file, std::span<std::vector<uint32_t>> static_funcs, bool write_header);

View file

@ -611,7 +611,7 @@ bool N64Recomp::Context::from_symbol_file(const std::filesystem::path& symbol_fi
return true; return true;
} }
void N64Recomp::Context::import_reference_context(const N64Recomp::Context& reference_context) { bool N64Recomp::Context::import_reference_context(const N64Recomp::Context& reference_context) {
reference_sections.resize(reference_context.sections.size()); reference_sections.resize(reference_context.sections.size());
reference_symbols.reserve(reference_context.functions.size()); reference_symbols.reserve(reference_context.functions.size());
@ -628,21 +628,12 @@ void N64Recomp::Context::import_reference_context(const N64Recomp::Context& refe
// Copy the functions from the reference context into the reference context's function map. // Copy the functions from the reference context into the reference context's function map.
for (const N64Recomp::Function& func_in: reference_context.functions) { for (const N64Recomp::Function& func_in: reference_context.functions) {
const N64Recomp::Section& func_section = reference_context.sections[func_in.section_index]; if (!add_reference_symbol(func_in.name, func_in.section_index, func_in.vram, true)) {
return false;
// TODO Check if reference_symbols_by_name already contains the name and show a conflict error if so. }
reference_symbols_by_name.emplace(func_in.name, N64Recomp::SymbolReference{
.section_index = func_in.section_index,
.symbol_index = reference_symbols.size()
});
reference_symbols.emplace_back(N64Recomp::ReferenceSymbol{
.name = func_in.name,
.section_index = func_in.section_index,
.section_offset = func_in.vram - static_cast<uint32_t>(func_section.ram_addr),
.is_function = true
});
} }
return true;
} }
// Reads a data symbol file and adds its contents into this context's reference data symbols. // Reads a data symbol file and adds its contents into this context's reference data symbols.
@ -730,20 +721,9 @@ bool N64Recomp::Context::read_data_reference_syms(const std::filesystem::path& d
throw toml::parse_error("Reference data symbol entry is missing required field(s)", data_sym_el.source()); throw toml::parse_error("Reference data symbol entry is missing required field(s)", data_sym_el.source());
} }
// TODO Check if reference_symbols_by_name already contains the name and show a conflict error if so. if (!this->add_reference_symbol(name.value(), ref_section_index, vram_addr.value(), false)) {
this->reference_symbols_by_name.emplace(name.value(), SymbolReference { throw toml::parse_error("Internal error: Failed to add reference symbol to context", data_sym_el.source());
.section_index = ref_section_index, }
.symbol_index = reference_symbols.size()
});
this->reference_symbols.emplace_back(
ReferenceSymbol {
.name = name.value(),
.section_index = ref_section_index,
.section_offset = vram_addr.value() - ref_section_vram,
.is_function = false
}
);
} }
else { else {
throw toml::parse_error("Invalid data symbol entry", data_sym_el.source()); throw toml::parse_error("Invalid data symbol entry", data_sym_el.source());

View file

@ -213,6 +213,7 @@ ELFIO::section* read_sections(N64Recomp::Context& context, const N64Recomp::ElfP
ELFIO::section* symtab_section = nullptr; ELFIO::section* symtab_section = nullptr;
std::vector<SegmentEntry> segments{}; std::vector<SegmentEntry> segments{};
segments.resize(elf_file.segments.size()); segments.resize(elf_file.segments.size());
bool has_reference_symbols = context.has_reference_symbols();
// Copy the data for each segment into the segment entry list // Copy the data for each segment into the segment entry list
for (size_t segment_index = 0; segment_index < elf_file.segments.size(); segment_index++) { for (size_t segment_index = 0; segment_index < elf_file.segments.size(); segment_index++) {
@ -263,7 +264,8 @@ ELFIO::section* read_sections(N64Recomp::Context& context, const N64Recomp::ElfP
// If this reloc section is for a section that has been marked as relocatable, record it in the reloc section lookup. // If this reloc section is for a section that has been marked as relocatable, record it in the reloc section lookup.
// Alternatively, if this recompilation uses reference symbols then record all reloc sections. // Alternatively, if this recompilation uses reference symbols then record all reloc sections.
if (elf_config.all_sections_relocatable || !context.reference_sections.empty() || elf_config.relocatable_sections.contains(reloc_target_section)) { bool section_is_relocatable = elf_config.all_sections_relocatable || elf_config.relocatable_sections.contains(reloc_target_section);
if (has_reference_symbols || section_is_relocatable) {
reloc_sections_by_name[reloc_target_section] = section.get(); reloc_sections_by_name[reloc_target_section] = section.get();
} }
} }
@ -396,8 +398,8 @@ ELFIO::section* read_sections(N64Recomp::Context& context, const N64Recomp::ElfP
// Check if the symbol is undefined and to know whether to look for it in the reference symbols. // Check if the symbol is undefined and to know whether to look for it in the reference symbols.
if (rel_symbol_section_index == ELFIO::SHN_UNDEF) { if (rel_symbol_section_index == ELFIO::SHN_UNDEF) {
// Undefined sym, check the reference symbols. // Undefined sym, check the reference symbols.
auto sym_find_it = context.reference_symbols_by_name.find(rel_symbol_name); N64Recomp::SymbolReference sym_ref;
if (sym_find_it == context.reference_symbols_by_name.end()) { if (!context.find_reference_symbol(rel_symbol_name, sym_ref)) {
fmt::print(stderr, "Undefined symbol: {}, not found in input or reference symbols!\n", fmt::print(stderr, "Undefined symbol: {}, not found in input or reference symbols!\n",
rel_symbol_name); rel_symbol_name);
return nullptr; return nullptr;
@ -406,8 +408,8 @@ ELFIO::section* read_sections(N64Recomp::Context& context, const N64Recomp::ElfP
reloc_out.reference_symbol = true; reloc_out.reference_symbol = true;
// Replace the reloc's symbol index with the index into the reference symbol array. // Replace the reloc's symbol index with the index into the reference symbol array.
rel_section_vram = 0; rel_section_vram = 0;
reloc_out.target_section = sym_find_it->second.section_index; reloc_out.target_section = sym_ref.section_index;
reloc_out.symbol_index = sym_find_it->second.symbol_index; reloc_out.symbol_index = sym_ref.symbol_index;
const auto& reference_symbol = context.get_reference_symbol(reloc_out.target_section, reloc_out.symbol_index); const auto& reference_symbol = context.get_reference_symbol(reloc_out.target_section, reloc_out.symbol_index);
rel_symbol_offset = reference_symbol.section_offset; rel_symbol_offset = reference_symbol.section_offset;
@ -504,10 +506,7 @@ ELFIO::section* read_sections(N64Recomp::Context& context, const N64Recomp::ElfP
// TODO set section_out.has_mips32_relocs to true if this section should emit its mips32 relocs (mainly for TLB mapping). // TODO set section_out.has_mips32_relocs to true if this section should emit its mips32 relocs (mainly for TLB mapping).
if (reloc_out.reference_symbol) { if (reloc_out.reference_symbol) {
uint32_t reloc_target_section_addr = 0; uint32_t reloc_target_section_addr = context.get_reference_section_vram(reloc_out.target_section);
if (reloc_out.target_section != N64Recomp::SectionAbsolute) {
reloc_target_section_addr = context.reference_sections[reloc_out.target_section].ram_addr;
}
// Patch the word in the ROM to incorporate the symbol's value. // Patch the word in the ROM to incorporate the symbol's value.
uint32_t updated_reloc_word = reloc_rom_word + reloc_target_section_addr + reloc_out.target_section_offset; uint32_t updated_reloc_word = reloc_rom_word + reloc_target_section_addr + reloc_out.target_section_offset;
*reinterpret_cast<uint32_t*>(context.rom.data() + reloc_rom_addr) = byteswap(updated_reloc_word); *reinterpret_cast<uint32_t*>(context.rom.data() + reloc_rom_addr) = byteswap(updated_reloc_word);

View file

@ -320,7 +320,9 @@ int main(int argc, char** argv) {
} }
// Use the reference context to build a reference symbol list for the actual context. // Use the reference context to build a reference symbol list for the actual context.
context.import_reference_context(reference_context); if (!context.import_reference_context(reference_context)) {
exit_failure("Internal error: Failed to import reference context\n");
}
} }
for (const std::filesystem::path& cur_data_sym_path : config.data_reference_syms_file_paths) { for (const std::filesystem::path& cur_data_sym_path : config.data_reference_syms_file_paths) {
@ -586,7 +588,8 @@ int main(int argc, char** argv) {
bool in_normal_patch_section = func_section.name == N64Recomp::PatchSectionName; bool in_normal_patch_section = func_section.name == N64Recomp::PatchSectionName;
bool in_force_patch_section = func_section.name == N64Recomp::ForcedPatchSectionName; bool in_force_patch_section = func_section.name == N64Recomp::ForcedPatchSectionName;
bool in_patch_section = in_normal_patch_section || in_force_patch_section; bool in_patch_section = in_normal_patch_section || in_force_patch_section;
bool reference_symbol_found = context.reference_symbols_by_name.contains(func.name); N64Recomp::SymbolReference dummy_ref;
bool reference_symbol_found = context.reference_symbol_exists(func.name);
// This is a patch function, but no corresponding symbol was found in the original symbol list. // This is a patch function, but no corresponding symbol was found in the original symbol list.
if (in_patch_section && !reference_symbol_found) { if (in_patch_section && !reference_symbol_found) {

View file

@ -116,11 +116,14 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
return false; return false;
} }
// TODO add proper add methods for these vectors and change these to reserves instead.
mod_context.sections.resize(num_sections); mod_context.sections.resize(num_sections);
mod_context.replacements.resize(num_replacements); mod_context.replacements.resize(num_replacements);
mod_context.exported_funcs.resize(num_exports); mod_context.exported_funcs.resize(num_exports);
mod_context.dependencies.resize(num_dependencies); mod_context.dependencies.resize(num_dependencies);
mod_context.import_symbols.resize(num_imports);
mod_context.import_symbols.reserve(num_imports);
for (size_t section_index = 0; section_index < num_sections; section_index++) { for (size_t section_index = 0; section_index < num_sections; section_index++) {
const SectionHeaderV1* section_header = reinterpret_data<SectionHeaderV1>(data, offset); const SectionHeaderV1* section_header = reinterpret_data<SectionHeaderV1>(data, offset);
if (section_header == nullptr) { if (section_header == nullptr) {
@ -304,18 +307,7 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
std::string_view import_name{ string_data + name_start, string_data + name_start + name_size }; std::string_view import_name{ string_data + name_start, string_data + name_start + name_size };
mod_context.import_symbols[import_index] = N64Recomp::ImportSymbol{ mod_context.add_import_symbol(std::string{import_name}, dependency_index, import_index);
.base = {
.name = std::string{import_name},
.section_index = N64Recomp::SectionImport,
.section_offset = 0,
.is_function = true,
},
.dependency_index = dependency_index,
};
auto& symbol_reference = mod_context.reference_symbols_by_name[std::string{import_name}];
symbol_reference.section_index = N64Recomp::SectionImport;
symbol_reference.symbol_index = import_index;
} }
return offset == data.size(); return offset == data.size();
@ -484,7 +476,7 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::Context& cont
target_section_offset_or_index = cur_reloc.symbol_index; target_section_offset_or_index = cur_reloc.symbol_index;
} }
else if (cur_reloc.reference_symbol) { else if (cur_reloc.reference_symbol) {
target_section_vrom = context.reference_sections[cur_reloc.target_section].rom_addr; target_section_vrom = context.get_reference_section_rom(cur_reloc.target_section);
} }
else { else {
target_section_vrom = context.sections[cur_reloc.target_section].rom_addr; target_section_vrom = context.sections[cur_reloc.target_section].rom_addr;

View file

@ -171,18 +171,13 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
if (reloc_type == N64Recomp::RelocType::R_MIPS_HI16 || reloc_type == N64Recomp::RelocType::R_MIPS_LO16 || reloc_type == N64Recomp::RelocType::R_MIPS_26) { if (reloc_type == N64Recomp::RelocType::R_MIPS_HI16 || reloc_type == N64Recomp::RelocType::R_MIPS_LO16 || reloc_type == N64Recomp::RelocType::R_MIPS_26) {
if (reloc.reference_symbol) { if (reloc.reference_symbol) {
reloc_reference_symbol = reloc.symbol_index; reloc_reference_symbol = reloc.symbol_index;
static N64Recomp::ReferenceSection dummy_section{ // Don't try to relocate special section symbols.
.rom_addr = 0, if (context.is_regular_reference_section(reloc.target_section)) {
.ram_addr = 0, bool ref_section_relocatable = context.is_reference_section_relocatable(reloc.target_section);
.size = 0, uint32_t ref_section_vram = context.get_reference_section_vram(reloc.target_section);
.relocatable = false
};
// Don't try to relocate import symbols.
if (reloc.target_section != N64Recomp::SectionImport) {
const auto& reloc_reference_section = reloc.target_section == N64Recomp::SectionAbsolute ? dummy_section : context.reference_sections[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 (!reloc_reference_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 full_immediate = reloc.target_section_offset + reloc_reference_section.ram_addr; uint32_t full_immediate = reloc.target_section_offset + ref_section_vram;
if (reloc_type == N64Recomp::RelocType::R_MIPS_HI16) { if (reloc_type == N64Recomp::RelocType::R_MIPS_HI16) {
imm = (full_immediate >> 16) + ((full_immediate >> 15) & 1); imm = (full_immediate >> 16) + ((full_immediate >> 15) & 1);