mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2026-04-30 22:11:43 +00:00
Some cleanup by making some Context members private
This commit is contained in:
parent
5f1b9a845b
commit
f300b6dccc
8 changed files with 191 additions and 126 deletions
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
17
src/elf.cpp
17
src/elf.cpp
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue