mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2026-04-28 04:51:43 +00:00
Move mod context fields into base context, move import symbols into separate vector, misc cleanup
This commit is contained in:
parent
623013a371
commit
5f1b9a845b
7 changed files with 220 additions and 199 deletions
|
|
@ -50,8 +50,6 @@ int main(int argc, const char** argv) {
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
N64Recomp::ModContext mod_context{};
|
||||
|
||||
std::span<const char> symbol_data_span { reinterpret_cast<const char*>(symbol_data.data()), symbol_data.size() };
|
||||
|
||||
std::vector<uint8_t> dummy_rom{};
|
||||
|
|
@ -73,6 +71,8 @@ int main(int argc, const char** argv) {
|
|||
sections_by_vrom[reference_context.sections[section_index].rom_addr] = section_index;
|
||||
}
|
||||
|
||||
N64Recomp::Context mod_context;
|
||||
|
||||
N64Recomp::ModSymbolsError error = N64Recomp::parse_mod_symbols(symbol_data_span, rom_data, sections_by_vrom, reference_context, mod_context);
|
||||
if (error != N64Recomp::ModSymbolsError::Good) {
|
||||
fprintf(stderr, "Error parsing mod symbols: %d\n", (int)error);
|
||||
|
|
@ -81,35 +81,30 @@ 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.
|
||||
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.base_context.reference_symbols.size(); reference_symbol_index++) {
|
||||
const auto& sym = mod_context.base_context.reference_symbols[reference_symbol_index];
|
||||
for (size_t reference_symbol_index = 0; reference_symbol_index < mod_context.reference_symbols.size(); reference_symbol_index++) {
|
||||
const auto& sym = mod_context.reference_symbols[reference_symbol_index];
|
||||
uint16_t section_index = sym.section_index;
|
||||
if (section_index != N64Recomp::SectionAbsolute && section_index != N64Recomp::SectionSelf && section_index != N64Recomp::SectionImport) {
|
||||
const auto& section = mod_context.base_context.reference_sections[section_index];
|
||||
if (section_index != N64Recomp::SectionAbsolute && section_index != N64Recomp::SectionSelf) {
|
||||
const auto& section = mod_context.reference_sections[section_index];
|
||||
|
||||
uint32_t vram = section.ram_addr + sym.section_offset;
|
||||
reference_symbols_by_vram[vram].push_back(reference_symbol_index);
|
||||
}
|
||||
}
|
||||
|
||||
size_t import_symbols_start = mod_context.base_context.reference_symbols.size() - mod_context.import_symbol_dependency_indices.size();
|
||||
|
||||
|
||||
// Use the mapping to populate the symbol index for every R_MIPS_26 reference symbol reloc.
|
||||
for (auto& section : mod_context.base_context.sections) {
|
||||
for (auto& section : mod_context.sections) {
|
||||
for (auto& reloc : section.relocs) {
|
||||
if (reloc.type == N64Recomp::RelocType::R_MIPS_26 && reloc.reference_symbol) {
|
||||
if (reloc.target_section == N64Recomp::SectionImport) {
|
||||
reloc.symbol_index = reloc.target_section_offset + import_symbols_start;
|
||||
}
|
||||
else {
|
||||
const auto& target_section = mod_context.base_context.reference_sections[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 target_vram = target_section.ram_addr + reloc.target_section_offset;
|
||||
|
||||
auto find_funcs_it = reference_symbols_by_vram.find(target_vram);
|
||||
bool found = false;
|
||||
if (find_funcs_it != reference_symbols_by_vram.end()) {
|
||||
for (size_t symbol_index : find_funcs_it->second) {
|
||||
const auto& cur_symbol = mod_context.base_context.reference_symbols[symbol_index];
|
||||
const auto& cur_symbol = mod_context.get_reference_symbol(reloc.target_section, symbol_index);
|
||||
if (cur_symbol.section_index == reloc.target_section) {
|
||||
reloc.symbol_index = symbol_index;
|
||||
found = true;
|
||||
|
|
@ -126,10 +121,10 @@ int main(int argc, const char** argv) {
|
|||
}
|
||||
}
|
||||
|
||||
mod_context.base_context.rom = std::move(rom_data);
|
||||
mod_context.rom = std::move(rom_data);
|
||||
|
||||
std::vector<std::vector<uint32_t>> static_funcs_by_section{};
|
||||
static_funcs_by_section.resize(mod_context.base_context.sections.size());
|
||||
static_funcs_by_section.resize(mod_context.sections.size());
|
||||
|
||||
std::ofstream output_file { argv[3] };
|
||||
|
||||
|
|
@ -142,8 +137,8 @@ int main(int argc, const char** argv) {
|
|||
std::string recomp_include = "#include \"librecomp/recomp.h\"";
|
||||
|
||||
bool should_write_header = true;
|
||||
for (const auto& func : mod_context.base_context.functions) {
|
||||
N64Recomp::recompile_function(mod_context.base_context, func, recomp_include, output_file, static_funcs_by_section, should_write_header);
|
||||
for (const auto& func : mod_context.functions) {
|
||||
N64Recomp::recompile_function(mod_context, func, recomp_include, output_file, static_funcs_by_section, should_write_header);
|
||||
should_write_header = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,13 +113,19 @@ static bool read_dependency_file(const std::filesystem::path& dependency_path, N
|
|||
throw toml::parse_error("Invalid dependency function", function_node.source());
|
||||
}
|
||||
const std::string& function_name = function_node.ref<std::string>();
|
||||
context.reference_symbol_names.emplace_back(function_name);
|
||||
context.reference_symbols_by_name[function_name] = context.reference_symbols.size();
|
||||
context.reference_symbols.emplace_back(
|
||||
N64Recomp::ReferenceSymbol {
|
||||
.section_index = N64Recomp::SectionImport,
|
||||
.section_offset = 0,
|
||||
.is_function = true
|
||||
context.reference_symbols_by_name[function_name] = N64Recomp::SymbolReference {
|
||||
.section_index = N64Recomp::SectionImport,
|
||||
.symbol_index = import_symbol_dependency_indices.size()
|
||||
};
|
||||
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);
|
||||
|
|
@ -230,8 +236,8 @@ static inline uint32_t round_up_16(uint32_t value) {
|
|||
return (value + 15) & (~15);
|
||||
}
|
||||
|
||||
N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context, std::vector<N64Recomp::Dependency>&& dependencies, std::vector<size_t>&& import_symbol_dependency_indices, bool& good) {
|
||||
N64Recomp::ModContext ret{};
|
||||
N64Recomp::Context build_mod_context(const N64Recomp::Context& input_context, std::vector<N64Recomp::Dependency>&& dependencies, std::vector<size_t>&& import_symbol_dependency_indices, bool& good) {
|
||||
N64Recomp::Context ret{};
|
||||
good = false;
|
||||
|
||||
// Make a vector containing 0, 1, 2, ... section count - 1
|
||||
|
|
@ -254,16 +260,14 @@ N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context,
|
|||
);
|
||||
|
||||
// TODO avoid a copy here.
|
||||
ret.base_context.rom = input_context.rom;
|
||||
ret.rom = input_context.rom;
|
||||
ret.dependencies = std::move(dependencies);
|
||||
ret.import_symbol_dependency_indices = std::move(import_symbol_dependency_indices);
|
||||
|
||||
uint32_t rom_to_ram = (uint32_t)-1;
|
||||
size_t output_section_index = (size_t)-1;
|
||||
ret.base_context.sections.resize(1);
|
||||
ret.sections.resize(1);
|
||||
|
||||
size_t num_imports = ret.import_symbol_dependency_indices.size();
|
||||
size_t import_symbol_start_index = input_context.reference_symbols.size() - num_imports;
|
||||
size_t num_imports = ret.import_symbols.size();
|
||||
|
||||
// Iterate over the input sections in their sorted order.
|
||||
for (uint16_t section_index : section_order) {
|
||||
|
|
@ -275,7 +279,7 @@ N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context,
|
|||
// If so, check if it has a vram address directly after the current output section. If it does, then add this
|
||||
// section's size to the output section's bss size.
|
||||
if (output_section_index != -1 && cur_section.size != 0) {
|
||||
auto& section_out = ret.base_context.sections[output_section_index];
|
||||
auto& section_out = ret.sections[output_section_index];
|
||||
uint32_t output_section_bss_start = section_out.ram_addr + section_out.size;
|
||||
uint32_t output_section_bss_end = output_section_bss_start + section_out.bss_size;
|
||||
// Check if the current section starts at the end of the output section, allowing for a range of matches to account for 16 byte section alignment.
|
||||
|
|
@ -289,18 +293,18 @@ N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context,
|
|||
|
||||
// Check if this section matches up with the previous section to merge them together.
|
||||
if (rom_to_ram == cur_rom_to_ram) {
|
||||
auto& section_out = ret.base_context.sections[output_section_index];
|
||||
auto& section_out = ret.sections[output_section_index];
|
||||
uint32_t cur_section_end = cur_section.rom_addr + cur_section.size;
|
||||
section_out.size = cur_section_end - section_out.rom_addr;
|
||||
}
|
||||
// Otherwise, create a new output section and advance to it.
|
||||
else {
|
||||
output_section_index++;
|
||||
ret.base_context.sections.resize(output_section_index + 1);
|
||||
ret.base_context.section_functions.resize(output_section_index + 1);
|
||||
ret.sections.resize(output_section_index + 1);
|
||||
ret.section_functions.resize(output_section_index + 1);
|
||||
rom_to_ram = cur_rom_to_ram;
|
||||
|
||||
auto& new_section = ret.base_context.sections[output_section_index];
|
||||
auto& new_section = ret.sections[output_section_index];
|
||||
new_section.rom_addr = cur_section.rom_addr;
|
||||
new_section.ram_addr = cur_section.ram_addr;
|
||||
new_section.size = cur_section.size;
|
||||
|
|
@ -312,13 +316,12 @@ N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context,
|
|||
bool export_section = cur_section.name == N64Recomp::ExportSectionName;
|
||||
|
||||
// Add the functions from the current input section to the current output section.
|
||||
auto& section_out = ret.base_context.sections[output_section_index];
|
||||
|
||||
size_t starting_function_index = ret.base_context.functions.size();
|
||||
auto& section_out = ret.sections[output_section_index];
|
||||
|
||||
const auto& cur_section_funcs = input_context.section_functions[section_index];
|
||||
|
||||
for (size_t section_function_index = 0; section_function_index < cur_section_funcs.size(); section_function_index++) {
|
||||
size_t output_func_index = ret.base_context.functions.size();
|
||||
size_t output_func_index = ret.functions.size();
|
||||
size_t input_func_index = cur_section_funcs[section_function_index];
|
||||
const auto& cur_func = input_context.functions[input_func_index];
|
||||
|
||||
|
|
@ -333,7 +336,9 @@ N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context,
|
|||
original_func_exists = false;
|
||||
}
|
||||
// Ignore reference symbols in the import section, as those are imports and not original symbols.
|
||||
else if (input_context.reference_symbols[find_sym_it->second].section_index == N64Recomp::SectionImport) {
|
||||
else if (
|
||||
find_sym_it->second.section_index == N64Recomp::SectionImport ||
|
||||
find_sym_it->second.section_index == N64Recomp::SectionHook) {
|
||||
original_func_exists = false;
|
||||
}
|
||||
else {
|
||||
|
|
@ -347,7 +352,7 @@ N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context,
|
|||
}
|
||||
|
||||
// Check that the reference symbol is actually a function.
|
||||
const auto& reference_symbol = input_context.reference_symbols[find_sym_it->second];
|
||||
const auto& reference_symbol = input_context.get_reference_symbol(find_sym_it->second.section_index, find_sym_it->second.symbol_index);
|
||||
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);
|
||||
return {};
|
||||
|
|
@ -374,11 +379,11 @@ N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context,
|
|||
name_out = cur_func.name;
|
||||
}
|
||||
|
||||
ret.base_context.section_functions[output_section_index].push_back(output_func_index);
|
||||
ret.section_functions[output_section_index].push_back(output_func_index);
|
||||
|
||||
|
||||
// Add this function to the output context.
|
||||
ret.base_context.functions.emplace_back(
|
||||
ret.functions.emplace_back(
|
||||
cur_func.vram,
|
||||
cur_func.rom,
|
||||
std::vector<uint32_t>{}, // words
|
||||
|
|
@ -390,7 +395,7 @@ N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context,
|
|||
);
|
||||
|
||||
// Resize the words vector so the function has the correct size. No need to copy the words, as they aren't used when making a mod symbol file.
|
||||
ret.base_context.functions[output_func_index].words.resize(cur_func.words.size());
|
||||
ret.functions[output_func_index].words.resize(cur_func.words.size());
|
||||
}
|
||||
|
||||
// Copy relocs and patch HI16/LO16/26 relocs for non-relocatable reference symbols
|
||||
|
|
@ -402,10 +407,7 @@ N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context,
|
|||
}
|
||||
// Reloc to an imported symbol.
|
||||
if (cur_reloc.target_section == N64Recomp::SectionImport) {
|
||||
// Copy the reloc and set the target section offset to be the import symbol index.
|
||||
N64Recomp::Reloc reloc_out = cur_reloc;
|
||||
reloc_out.symbol_index = reloc_out.symbol_index - import_symbol_start_index;
|
||||
section_out.relocs.emplace_back(reloc_out);
|
||||
section_out.relocs.emplace_back(cur_reloc);
|
||||
}
|
||||
// Reloc to a reference symbol.
|
||||
else if (cur_reloc.reference_symbol) {
|
||||
|
|
@ -415,7 +417,7 @@ N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context,
|
|||
uint32_t reloc_target_address = reloc_section.ram_addr + cur_reloc.target_section_offset;
|
||||
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.base_context.rom.data() + reloc_rom_address);
|
||||
uint32_t* reloc_word_ptr = reinterpret_cast<uint32_t*>(ret.rom.data() + reloc_rom_address);
|
||||
uint32_t reloc_word = byteswap(*reloc_word_ptr);
|
||||
switch (cur_reloc.type) {
|
||||
case N64Recomp::RelocType::R_MIPS_32:
|
||||
|
|
@ -471,27 +473,11 @@ N64Recomp::ModContext build_mod_context(const N64Recomp::Context& input_context,
|
|||
}
|
||||
}
|
||||
|
||||
// Copy the import reference symbols from the end of the input context to this context.
|
||||
ret.base_context.reference_symbols.resize(num_imports);
|
||||
ret.base_context.reference_symbol_names.resize(num_imports);
|
||||
for (size_t import_symbol_index = 0; import_symbol_index < num_imports; import_symbol_index++) {
|
||||
size_t reference_symbol_index = import_symbol_index + import_symbol_start_index;
|
||||
const auto& reference_symbol = input_context.reference_symbols[reference_symbol_index];
|
||||
const std::string& reference_symbol_name = input_context.reference_symbol_names[reference_symbol_index];
|
||||
|
||||
if (reference_symbol.section_index != N64Recomp::SectionImport) {
|
||||
fmt::print("Import symbol index {} (reference symbol index {}, name {}) is not in the import section!\n",
|
||||
import_symbol_index, reference_symbol_index, reference_symbol_name);
|
||||
return {};
|
||||
}
|
||||
|
||||
ret.base_context.reference_symbols[import_symbol_index] = reference_symbol;
|
||||
ret.base_context.reference_symbol_names[import_symbol_index] = reference_symbol_name;
|
||||
ret.base_context.reference_symbols_by_name[reference_symbol_name] = import_symbol_index;
|
||||
}
|
||||
// Copy the import reference symbols from the input context as-is to this context.
|
||||
ret.import_symbols = input_context.import_symbols;
|
||||
|
||||
// Copy the reference sections from the input context as-is for resolving reference symbol relocations.
|
||||
ret.base_context.reference_sections = input_context.reference_sections;
|
||||
ret.reference_sections = input_context.reference_sections;
|
||||
|
||||
good = true;
|
||||
return ret;
|
||||
|
|
@ -570,14 +556,14 @@ int main(int argc, const char** argv) {
|
|||
}
|
||||
|
||||
bool mod_context_good;
|
||||
N64Recomp::ModContext mod_context = build_mod_context(context, std::move(dependencies), std::move(import_symbol_dependency_indices), mod_context_good);
|
||||
N64Recomp::Context mod_context = build_mod_context(context, std::move(dependencies), std::move(import_symbol_dependency_indices), mod_context_good);
|
||||
std::vector<uint8_t> symbols_bin = N64Recomp::symbols_to_bin_v1(mod_context);
|
||||
|
||||
std::ofstream output_syms_file{ config.output_syms_path, std::ios::binary };
|
||||
output_syms_file.write(reinterpret_cast<const char*>(symbols_bin.data()), symbols_bin.size());
|
||||
|
||||
std::ofstream output_binary_file{ config.output_binary_path, std::ios::binary };
|
||||
output_binary_file.write(reinterpret_cast<const char*>(mod_context.base_context.rom.data()), mod_context.base_context.rom.size());
|
||||
output_binary_file.write(reinterpret_cast<const char*>(mod_context.rom.data()), mod_context.rom.size());
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ namespace N64Recomp {
|
|||
constexpr uint16_t SectionSelf = (uint16_t)-1;
|
||||
constexpr uint16_t SectionAbsolute = (uint16_t)-2;
|
||||
constexpr uint16_t SectionImport = (uint16_t)-3; // Imported symbols for mods
|
||||
constexpr uint16_t SectionHook = (uint16_t)-4;
|
||||
constexpr std::string_view PatchSectionName = ".recomp_patch";
|
||||
constexpr std::string_view ForcedPatchSectionName = ".recomp_force_patch";
|
||||
constexpr std::string_view ExportSectionName = ".recomp_export";
|
||||
|
|
@ -85,6 +86,7 @@ namespace N64Recomp {
|
|||
};
|
||||
|
||||
struct ReferenceSymbol {
|
||||
std::string name;
|
||||
uint16_t section_index;
|
||||
uint32_t section_offset;
|
||||
bool is_function;
|
||||
|
|
@ -116,6 +118,42 @@ namespace N64Recomp {
|
|||
extern const std::unordered_set<std::string> ignored_funcs;
|
||||
extern const std::unordered_set<std::string> renamed_funcs;
|
||||
|
||||
struct Dependency {
|
||||
uint8_t major_version;
|
||||
uint8_t minor_version;
|
||||
uint8_t patch_version;
|
||||
std::string mod_id;
|
||||
};
|
||||
|
||||
struct ImportSymbol {
|
||||
ReferenceSymbol base;
|
||||
size_t dependency_index;
|
||||
};
|
||||
|
||||
struct HookSymbol {
|
||||
ReferenceSymbol base;
|
||||
size_t dependency_index;
|
||||
};
|
||||
|
||||
struct SymbolReference {
|
||||
// Reference symbol section index, or one of the special section indices such as SectionImport.
|
||||
uint16_t section_index;
|
||||
size_t symbol_index;
|
||||
};
|
||||
|
||||
enum class ReplacementFlags : uint32_t {
|
||||
Force = 1 << 0,
|
||||
};
|
||||
inline ReplacementFlags operator&(ReplacementFlags lhs, ReplacementFlags rhs) { return ReplacementFlags(uint32_t(lhs) & uint32_t(rhs)); }
|
||||
inline ReplacementFlags operator|(ReplacementFlags lhs, ReplacementFlags rhs) { return ReplacementFlags(uint32_t(lhs) | uint32_t(rhs)); }
|
||||
|
||||
struct FunctionReplacement {
|
||||
uint32_t func_index;
|
||||
uint32_t original_section_vrom;
|
||||
uint32_t original_vram;
|
||||
ReplacementFlags flags;
|
||||
};
|
||||
|
||||
struct Context {
|
||||
std::vector<Section> sections;
|
||||
std::vector<Function> functions;
|
||||
|
|
@ -136,10 +174,17 @@ namespace N64Recomp {
|
|||
std::vector<ReferenceSection> reference_sections;
|
||||
// A list of the reference symbols.
|
||||
std::vector<ReferenceSymbol> reference_symbols;
|
||||
// Name of every reference symbol in the same order as `reference_symbols`.
|
||||
std::vector<std::string> reference_symbol_names;
|
||||
// Mapping of symbol name to reference symbol index.
|
||||
std::unordered_map<std::string, size_t> reference_symbols_by_name;
|
||||
std::unordered_map<std::string, SymbolReference> reference_symbols_by_name;
|
||||
|
||||
//// Mod dependencies and their symbols
|
||||
std::vector<Dependency> dependencies;
|
||||
std::vector<ImportSymbol> import_symbols;
|
||||
std::vector<HookSymbol> hook_symbols;
|
||||
// Indices of every exported function.
|
||||
std::vector<size_t> exported_funcs;
|
||||
|
||||
std::vector<FunctionReplacement> replacements;
|
||||
|
||||
// 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);
|
||||
|
|
@ -150,41 +195,39 @@ namespace N64Recomp {
|
|||
static bool from_elf_file(const std::filesystem::path& elf_file_path, Context& out, const ElfParsingConfig& flags, bool for_dumping_context, DataSymbolMap& data_syms_out, bool& found_entrypoint_out);
|
||||
|
||||
Context() = default;
|
||||
|
||||
bool has_reference_symbols() const {
|
||||
return !reference_symbols.empty() || !import_symbols.empty() || !hook_symbols.empty();
|
||||
}
|
||||
|
||||
bool is_regular_reference_section(uint16_t section_index) const {
|
||||
return section_index != SectionImport && section_index != SectionHook;
|
||||
}
|
||||
|
||||
const ReferenceSymbol& get_reference_symbol(uint16_t section_index, size_t symbol_index) const {
|
||||
if (section_index == SectionImport) {
|
||||
return import_symbols[symbol_index].base;
|
||||
}
|
||||
else if (section_index == SectionHook) {
|
||||
return hook_symbols[symbol_index].base;
|
||||
}
|
||||
return reference_symbols[symbol_index];
|
||||
}
|
||||
|
||||
const ReferenceSymbol& get_reference_symbol(const SymbolReference& ref) const {
|
||||
return get_reference_symbol(ref.section_index, ref.symbol_index);
|
||||
}
|
||||
|
||||
bool is_reference_section_relocatable(uint16_t section_index) const {
|
||||
if (section_index == SectionImport || section_index == SectionHook) {
|
||||
return true;
|
||||
}
|
||||
return reference_sections[section_index].relocatable;
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
enum class ReplacementFlags : uint32_t {
|
||||
Force = 1 << 0,
|
||||
};
|
||||
inline ReplacementFlags operator&(ReplacementFlags lhs, ReplacementFlags rhs) { return ReplacementFlags(uint32_t(lhs) & uint32_t(rhs)); }
|
||||
inline ReplacementFlags operator|(ReplacementFlags lhs, ReplacementFlags rhs) { return ReplacementFlags(uint32_t(lhs) | uint32_t(rhs)); }
|
||||
|
||||
struct FunctionReplacement {
|
||||
uint32_t func_index;
|
||||
uint32_t original_section_vrom;
|
||||
uint32_t original_vram;
|
||||
ReplacementFlags flags;
|
||||
};
|
||||
|
||||
struct Dependency {
|
||||
uint8_t major_version;
|
||||
uint8_t minor_version;
|
||||
uint8_t patch_version;
|
||||
std::string mod_id;
|
||||
};
|
||||
|
||||
struct ModContext {
|
||||
Context base_context;
|
||||
std::vector<FunctionReplacement> replacements;
|
||||
// Indices of every exported function.
|
||||
std::vector<size_t> exported_funcs;
|
||||
// List of dependencies of this mod.
|
||||
std::vector<Dependency> dependencies;
|
||||
// Index of the dependency that each imported function belongs to.
|
||||
// Imported symbols exist at the end of `base_context.reference_symbols`.
|
||||
std::vector<size_t> import_symbol_dependency_indices;
|
||||
};
|
||||
enum class ModSymbolsError {
|
||||
Good,
|
||||
NotASymbolFile,
|
||||
|
|
@ -193,8 +236,8 @@ namespace N64Recomp {
|
|||
FunctionOutOfBounds,
|
||||
};
|
||||
|
||||
ModSymbolsError parse_mod_symbols(std::span<const char> data, std::span<const uint8_t> binary, const std::unordered_map<uint32_t, uint16_t>& sections_by_vrom, const Context& reference_context, ModContext& mod_context_out);
|
||||
std::vector<uint8_t> symbols_to_bin_v1(const ModContext& mod_context);
|
||||
ModSymbolsError parse_mod_symbols(std::span<const char> data, std::span<const uint8_t> binary, const std::unordered_map<uint32_t, uint16_t>& sections_by_vrom, const Context& reference_context, Context& context_out);
|
||||
std::vector<uint8_t> symbols_to_bin_v1(const Context& mod_context);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -614,7 +614,6 @@ bool N64Recomp::Context::from_symbol_file(const std::filesystem::path& symbol_fi
|
|||
void N64Recomp::Context::import_reference_context(const N64Recomp::Context& reference_context) {
|
||||
reference_sections.resize(reference_context.sections.size());
|
||||
reference_symbols.reserve(reference_context.functions.size());
|
||||
reference_symbol_names.reserve(reference_context.functions.size());
|
||||
|
||||
// Copy the reference context's sections into the real context's reference sections.
|
||||
for (size_t section_index = 0; section_index < reference_context.sections.size(); section_index++) {
|
||||
|
|
@ -632,14 +631,17 @@ void N64Recomp::Context::import_reference_context(const N64Recomp::Context& refe
|
|||
const N64Recomp::Section& func_section = reference_context.sections[func_in.section_index];
|
||||
|
||||
// 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, reference_symbols.size());
|
||||
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
|
||||
});
|
||||
reference_symbol_names.emplace_back(func_in.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -729,16 +731,19 @@ bool N64Recomp::Context::read_data_reference_syms(const std::filesystem::path& d
|
|||
}
|
||||
|
||||
// TODO Check if reference_symbols_by_name already contains the name and show a conflict error if so.
|
||||
this->reference_symbols_by_name.emplace(name.value(), reference_symbols.size());
|
||||
this->reference_symbols_by_name.emplace(name.value(), SymbolReference {
|
||||
.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
|
||||
}
|
||||
);
|
||||
this->reference_symbol_names.emplace_back(name.value());
|
||||
}
|
||||
else {
|
||||
throw toml::parse_error("Invalid data symbol entry", data_sym_el.source());
|
||||
|
|
|
|||
21
src/elf.cpp
21
src/elf.cpp
|
|
@ -345,7 +345,7 @@ ELFIO::section* read_sections(N64Recomp::Context& context, const N64Recomp::ElfP
|
|||
section_out.bss_size = bss_find->second->get_size();
|
||||
}
|
||||
|
||||
if (!context.reference_symbols.empty() || section_out.relocatable) {
|
||||
if (context.has_reference_symbols() || section_out.relocatable) {
|
||||
// Check if a reloc section was found that corresponds with this section
|
||||
auto reloc_find = reloc_sections_by_name.find(section_out.name);
|
||||
if (reloc_find != reloc_sections_by_name.end()) {
|
||||
|
|
@ -405,22 +405,13 @@ ELFIO::section* read_sections(N64Recomp::Context& context, const N64Recomp::ElfP
|
|||
|
||||
reloc_out.reference_symbol = true;
|
||||
// Replace the reloc's symbol index with the index into the reference symbol array.
|
||||
reloc_out.symbol_index = sym_find_it->second;
|
||||
rel_section_vram = 0;
|
||||
rel_symbol_offset = context.reference_symbols[reloc_out.symbol_index].section_offset;
|
||||
reloc_out.target_section = context.reference_symbols[reloc_out.symbol_index].section_index;
|
||||
reloc_out.target_section = sym_find_it->second.section_index;
|
||||
reloc_out.symbol_index = sym_find_it->second.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;
|
||||
|
||||
bool target_section_relocatable = false;
|
||||
|
||||
if (reloc_out.target_section == N64Recomp::SectionImport) {
|
||||
target_section_relocatable = true;
|
||||
}
|
||||
else if (reloc_out.target_section == N64Recomp::SectionAbsolute) {
|
||||
target_section_relocatable = false;
|
||||
}
|
||||
else if (context.reference_sections[reloc_out.target_section].relocatable) {
|
||||
target_section_relocatable = true;
|
||||
}
|
||||
bool target_section_relocatable = context.is_reference_section_relocatable(reloc_out.target_section);
|
||||
|
||||
if (reloc_out.type == N64Recomp::RelocType::R_MIPS_32 && target_section_relocatable) {
|
||||
fmt::print(stderr, "Cannot reference {} in a statically initialized variable as it's defined in a relocatable section!\n",
|
||||
|
|
|
|||
|
|
@ -30,12 +30,15 @@ struct FuncV1 {
|
|||
};
|
||||
|
||||
constexpr uint32_t SectionSelfVromV1 = 0xFFFFFFFF;
|
||||
|
||||
// Special sections
|
||||
constexpr uint32_t SectionImportVromV1 = 0xFFFFFFFE;
|
||||
constexpr uint32_t SectionHookVromV1 = 0xFFFFFFFD;
|
||||
|
||||
struct RelocV1 {
|
||||
uint32_t section_offset;
|
||||
uint32_t type;
|
||||
uint32_t target_section_offset; // If this reloc references an import symbol, this indicates the import symbol index instead
|
||||
uint32_t target_section_offset_or_index; // If this reloc references a special section (see above), this indicates the section's symbol index instead
|
||||
uint32_t target_section_vrom;
|
||||
};
|
||||
|
||||
|
|
@ -89,9 +92,8 @@ static inline uint32_t round_up_4(uint32_t value) {
|
|||
return (value + 3) & (~3);
|
||||
}
|
||||
|
||||
bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uint16_t>& sections_by_vrom, N64Recomp::ModContext& mod_context) {
|
||||
bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uint16_t>& sections_by_vrom, N64Recomp::Context& mod_context) {
|
||||
size_t offset = sizeof(FileHeader);
|
||||
N64Recomp::Context& base_context = mod_context.base_context;
|
||||
const FileSubHeaderV1* subheader = reinterpret_data<FileSubHeaderV1>(data, offset);
|
||||
if (subheader == nullptr) {
|
||||
return false;
|
||||
|
|
@ -114,22 +116,18 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t import_symbol_base_index = base_context.reference_symbols.size();
|
||||
|
||||
base_context.sections.resize(num_sections);
|
||||
mod_context.sections.resize(num_sections);
|
||||
mod_context.replacements.resize(num_replacements);
|
||||
mod_context.exported_funcs.resize(num_exports);
|
||||
mod_context.dependencies.resize(num_dependencies);
|
||||
mod_context.import_symbol_dependency_indices.resize(num_imports);
|
||||
base_context.reference_symbols.resize(import_symbol_base_index + num_imports);
|
||||
base_context.reference_symbol_names.resize(import_symbol_base_index + num_imports);
|
||||
mod_context.import_symbols.resize(num_imports);
|
||||
for (size_t section_index = 0; section_index < num_sections; section_index++) {
|
||||
const SectionHeaderV1* section_header = reinterpret_data<SectionHeaderV1>(data, offset);
|
||||
if (section_header == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
N64Recomp::Section& cur_section = base_context.sections[section_index];
|
||||
N64Recomp::Section& cur_section = mod_context.sections[section_index];
|
||||
|
||||
cur_section.rom_addr = section_header->file_offset;
|
||||
cur_section.ram_addr = section_header->vram;
|
||||
|
|
@ -153,8 +151,8 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t start_func_index = base_context.functions.size();
|
||||
base_context.functions.resize(base_context.functions.size() + num_funcs);
|
||||
size_t start_func_index = mod_context.functions.size();
|
||||
mod_context.functions.resize(mod_context.functions.size() + num_funcs);
|
||||
cur_section.relocs.resize(num_relocs);
|
||||
|
||||
for (size_t func_index = 0; func_index < num_funcs; func_index++) {
|
||||
|
|
@ -169,7 +167,7 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
|
|||
return false;
|
||||
}
|
||||
|
||||
N64Recomp::Function& cur_func = base_context.functions[start_func_index + func_index];
|
||||
N64Recomp::Function& cur_func = mod_context.functions[start_func_index + func_index];
|
||||
cur_func.vram = cur_section.ram_addr + funcs[func_index].section_offset;
|
||||
cur_func.rom = cur_section.rom_addr + funcs[func_index].section_offset;
|
||||
cur_func.words.resize(funcs[func_index].size / sizeof(uint32_t)); // Filled in later
|
||||
|
|
@ -179,18 +177,23 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
|
|||
|
||||
for (size_t reloc_index = 0; reloc_index < num_relocs; reloc_index++) {
|
||||
N64Recomp::Reloc& cur_reloc = cur_section.relocs[reloc_index];
|
||||
cur_reloc.address = cur_section.ram_addr + relocs[reloc_index].section_offset;
|
||||
cur_reloc.type = static_cast<N64Recomp::RelocType>(relocs[reloc_index].type);
|
||||
cur_reloc.target_section_offset = relocs[reloc_index].target_section_offset;
|
||||
uint32_t target_section_vrom = relocs[reloc_index].target_section_vrom;
|
||||
const RelocV1& reloc_in = relocs[reloc_index];
|
||||
cur_reloc.address = cur_section.ram_addr + reloc_in.section_offset;
|
||||
cur_reloc.type = static_cast<N64Recomp::RelocType>(reloc_in.type);
|
||||
uint32_t target_section_vrom = reloc_in.target_section_vrom;
|
||||
uint16_t reloc_target_section;
|
||||
uint32_t reloc_target_section_offset;
|
||||
uint32_t reloc_symbol_index;
|
||||
if (target_section_vrom == SectionSelfVromV1) {
|
||||
cur_reloc.target_section = N64Recomp::SectionSelf;
|
||||
reloc_target_section = N64Recomp::SectionSelf;
|
||||
reloc_target_section_offset = reloc_in.target_section_offset_or_index;
|
||||
reloc_symbol_index = 0; // Not used for normal relocs.
|
||||
}
|
||||
else if (target_section_vrom == SectionImportVromV1) {
|
||||
cur_reloc.target_section = N64Recomp::SectionImport;
|
||||
reloc_target_section = N64Recomp::SectionImport;
|
||||
reloc_target_section_offset = 0; // Not used for imports or reference symbols.
|
||||
reloc_symbol_index = reloc_in.target_section_offset_or_index;
|
||||
cur_reloc.reference_symbol = true;
|
||||
// Import symbol relocs encode the import symbol index into the target_section_offset field.
|
||||
cur_reloc.symbol_index = cur_reloc.target_section_offset + import_symbol_base_index;
|
||||
}
|
||||
else {
|
||||
// TODO lookup by section index by original vrom
|
||||
|
|
@ -200,9 +203,14 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
|
|||
reloc_index, section_index, target_section_vrom);
|
||||
return false;
|
||||
}
|
||||
cur_reloc.target_section = find_section_it->second;
|
||||
reloc_target_section = find_section_it->second;
|
||||
reloc_target_section_offset = reloc_in.target_section_offset_or_index;
|
||||
reloc_symbol_index = 0; // Not used for normal relocs.
|
||||
cur_reloc.reference_symbol = true;
|
||||
}
|
||||
cur_reloc.target_section = reloc_target_section;
|
||||
cur_reloc.target_section_offset = reloc_target_section_offset;
|
||||
cur_reloc.symbol_index = reloc_symbol_index;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -233,9 +241,9 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
|
|||
uint32_t name_start = export_in.name_start;
|
||||
uint32_t name_size = export_in.name_size;
|
||||
|
||||
if (func_index >= base_context.functions.size()) {
|
||||
if (func_index >= mod_context.functions.size()) {
|
||||
printf("Export %zu has a function index of %u, but the symbol file only has %zu functions\n",
|
||||
export_index, func_index, base_context.functions.size());
|
||||
export_index, func_index, mod_context.functions.size());
|
||||
}
|
||||
|
||||
if (name_start + name_size > string_data_size) {
|
||||
|
|
@ -246,7 +254,7 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
|
|||
// Add the function to the exported function list.
|
||||
mod_context.exported_funcs[export_index] = func_index;
|
||||
// Populate the exported function's name from the string data.
|
||||
base_context.functions[func_index].name = std::string_view(string_data + name_start, string_data + name_start + name_size);
|
||||
mod_context.functions[func_index].name = std::string_view(string_data + name_start, string_data + name_start + name_size);
|
||||
}
|
||||
|
||||
const DependencyV1* dependencies = reinterpret_data<DependencyV1>(data, offset, num_dependencies);
|
||||
|
|
@ -283,7 +291,6 @@ bool parse_v1(std::span<const char> data, const std::unordered_map<uint32_t, uin
|
|||
uint32_t name_start = import_in.name_start;
|
||||
uint32_t name_size = import_in.name_size;
|
||||
uint32_t dependency_index = import_in.dependency;
|
||||
size_t reference_symbol_index = import_symbol_base_index + import_index;
|
||||
|
||||
if (name_start + name_size > string_data_size) {
|
||||
printf("Import %zu has a name start of %u and size of %u, which extend beyond the string data's total size of %zu\n",
|
||||
|
|
@ -297,25 +304,29 @@ 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 };
|
||||
|
||||
base_context.reference_symbols[reference_symbol_index] = N64Recomp::ReferenceSymbol{
|
||||
.section_index = N64Recomp::SectionImport,
|
||||
.section_offset = static_cast<uint32_t>(import_index),
|
||||
.is_function = true,
|
||||
mod_context.import_symbols[import_index] = N64Recomp::ImportSymbol{
|
||||
.base = {
|
||||
.name = std::string{import_name},
|
||||
.section_index = N64Recomp::SectionImport,
|
||||
.section_offset = 0,
|
||||
.is_function = true,
|
||||
},
|
||||
.dependency_index = dependency_index,
|
||||
};
|
||||
base_context.reference_symbol_names[reference_symbol_index] = import_name;
|
||||
base_context.reference_symbols_by_name[std::string{import_name}] = reference_symbol_index;
|
||||
mod_context.import_symbol_dependency_indices[import_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();
|
||||
}
|
||||
|
||||
N64Recomp::ModSymbolsError N64Recomp::parse_mod_symbols(std::span<const char> data, std::span<const uint8_t> binary, const std::unordered_map<uint32_t, uint16_t>& sections_by_vrom, const Context& reference_context, ModContext& mod_context_out) {
|
||||
N64Recomp::ModSymbolsError N64Recomp::parse_mod_symbols(std::span<const char> data, std::span<const uint8_t> binary, const std::unordered_map<uint32_t, uint16_t>& sections_by_vrom, const Context& reference_context, Context& mod_context_out) {
|
||||
size_t offset = 0;
|
||||
mod_context_out = {};
|
||||
const FileHeader* header = reinterpret_data<FileHeader>(data, offset);
|
||||
|
||||
mod_context_out.base_context.import_reference_context(reference_context);
|
||||
mod_context_out.import_reference_context(reference_context);
|
||||
|
||||
if (header == nullptr) {
|
||||
return ModSymbolsError::NotASymbolFile;
|
||||
|
|
@ -341,7 +352,7 @@ N64Recomp::ModSymbolsError N64Recomp::parse_mod_symbols(std::span<const char> da
|
|||
}
|
||||
|
||||
// Fill in the words for each function.
|
||||
for (auto& cur_func : mod_context_out.base_context.functions) {
|
||||
for (auto& cur_func : mod_context_out.functions) {
|
||||
if (cur_func.rom + cur_func.words.size() * sizeof(cur_func.words[0]) > binary.size()) {
|
||||
mod_context_out = {};
|
||||
return ModSymbolsError::FunctionOutOfBounds;
|
||||
|
|
@ -368,10 +379,9 @@ void vec_put(std::vector<uint8_t>& vec, const std::string& data) {
|
|||
memcpy(vec.data() + start_size, data.data(), data.size());
|
||||
}
|
||||
|
||||
std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::ModContext& mod_context) {
|
||||
std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::Context& context) {
|
||||
std::vector<uint8_t> ret{};
|
||||
ret.reserve(1024);
|
||||
const N64Recomp::Context& context = mod_context.base_context;
|
||||
|
||||
const static FileHeader header {
|
||||
.magic = {'N', '6', '4', 'R', 'S', 'Y', 'M', 'S'},
|
||||
|
|
@ -380,13 +390,13 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::ModContext& m
|
|||
|
||||
vec_put(ret, &header);
|
||||
|
||||
size_t num_exported_funcs = mod_context.exported_funcs.size();
|
||||
size_t num_dependencies = mod_context.dependencies.size();
|
||||
size_t num_imported_funcs = mod_context.import_symbol_dependency_indices.size();
|
||||
size_t num_exported_funcs = context.exported_funcs.size();
|
||||
size_t num_dependencies = context.dependencies.size();
|
||||
size_t num_imported_funcs = context.import_symbols.size();
|
||||
|
||||
FileSubHeaderV1 sub_header {
|
||||
.num_sections = static_cast<uint32_t>(context.sections.size()),
|
||||
.num_replacements = static_cast<uint32_t>(mod_context.replacements.size()),
|
||||
.num_replacements = static_cast<uint32_t>(context.replacements.size()),
|
||||
.num_exports = static_cast<uint32_t>(num_exported_funcs),
|
||||
.num_dependencies = static_cast<uint32_t>(num_dependencies),
|
||||
.num_imports = static_cast<uint32_t>(num_imported_funcs),
|
||||
|
|
@ -404,8 +414,8 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::ModContext& m
|
|||
std::vector<uint32_t> exported_func_name_positions{};
|
||||
exported_func_name_positions.resize(num_exported_funcs);
|
||||
for (size_t export_index = 0; export_index < num_exported_funcs; export_index++) {
|
||||
size_t function_index = mod_context.exported_funcs[export_index];
|
||||
const Function& exported_func = mod_context.base_context.functions[function_index];
|
||||
size_t function_index = context.exported_funcs[export_index];
|
||||
const Function& exported_func = context.functions[function_index];
|
||||
|
||||
exported_func_name_positions[export_index] = static_cast<uint32_t>(ret.size() - strings_start);
|
||||
vec_put(ret, exported_func.name);
|
||||
|
|
@ -415,7 +425,7 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::ModContext& m
|
|||
std::vector<uint32_t> dependency_name_positions{};
|
||||
dependency_name_positions.resize(num_dependencies);
|
||||
for (size_t dependency_index = 0; dependency_index < num_dependencies; dependency_index++) {
|
||||
const Dependency& dependency = mod_context.dependencies[dependency_index];
|
||||
const Dependency& dependency = context.dependencies[dependency_index];
|
||||
|
||||
dependency_name_positions[dependency_index] = static_cast<uint32_t>(ret.size() - strings_start);
|
||||
vec_put(ret, dependency.mod_id);
|
||||
|
|
@ -425,17 +435,12 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::ModContext& m
|
|||
std::vector<uint32_t> imported_func_name_positions{};
|
||||
imported_func_name_positions.resize(num_imported_funcs);
|
||||
std::unordered_map<std::string, uint32_t> mod_id_name_positions{};
|
||||
// Calculate the index of the first import symbol. Import symbols are all grouped at the end of the reference symbol list.
|
||||
size_t import_symbol_base_index = mod_context.base_context.reference_symbols.size() - num_imported_funcs;
|
||||
for (size_t import_index = 0; import_index < num_imported_funcs; import_index++) {
|
||||
// Get the index of the reference symbol for this import.
|
||||
size_t reference_symbol_index = import_symbol_base_index + import_index;
|
||||
const ReferenceSymbol& imported_func = mod_context.base_context.reference_symbols[reference_symbol_index];
|
||||
const std::string& imported_func_name = mod_context.base_context.reference_symbol_names[reference_symbol_index];
|
||||
const ImportSymbol& imported_func = context.import_symbols[import_index];
|
||||
|
||||
// Write this import's name into the strings data.
|
||||
imported_func_name_positions[import_index] = static_cast<uint32_t>(ret.size() - strings_start);
|
||||
vec_put(ret, imported_func_name);
|
||||
vec_put(ret, imported_func.base.name);
|
||||
}
|
||||
|
||||
// Align the data after the strings to 4 bytes.
|
||||
|
|
@ -470,13 +475,13 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::ModContext& m
|
|||
|
||||
for (const Reloc& cur_reloc : cur_section.relocs) {
|
||||
uint32_t target_section_vrom;
|
||||
uint32_t target_section_offset = cur_reloc.target_section_offset;
|
||||
uint32_t target_section_offset_or_index = cur_reloc.target_section_offset;
|
||||
if (cur_reloc.target_section == SectionSelf) {
|
||||
target_section_vrom = SectionSelfVromV1;
|
||||
}
|
||||
else if (cur_reloc.target_section == SectionImport) {
|
||||
target_section_vrom = SectionImportVromV1;
|
||||
target_section_offset = cur_reloc.symbol_index;
|
||||
target_section_offset_or_index = cur_reloc.symbol_index;
|
||||
}
|
||||
else if (cur_reloc.reference_symbol) {
|
||||
target_section_vrom = context.reference_sections[cur_reloc.target_section].rom_addr;
|
||||
|
|
@ -487,7 +492,7 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::ModContext& m
|
|||
RelocV1 reloc_out {
|
||||
.section_offset = cur_reloc.address - cur_section.ram_addr,
|
||||
.type = static_cast<uint32_t>(cur_reloc.type),
|
||||
.target_section_offset = target_section_offset,
|
||||
.target_section_offset_or_index = target_section_offset_or_index,
|
||||
.target_section_vrom = target_section_vrom
|
||||
};
|
||||
|
||||
|
|
@ -496,7 +501,7 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::ModContext& m
|
|||
}
|
||||
|
||||
// Write the function replacements.
|
||||
for (const FunctionReplacement& cur_replacement : mod_context.replacements) {
|
||||
for (const FunctionReplacement& cur_replacement : context.replacements) {
|
||||
uint32_t flags = 0;
|
||||
if ((cur_replacement.flags & ReplacementFlags::Force) == ReplacementFlags::Force) {
|
||||
flags |= 0x1;
|
||||
|
|
@ -514,8 +519,8 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::ModContext& m
|
|||
|
||||
// Write the exported functions.
|
||||
for (size_t export_index = 0; export_index < num_exported_funcs; export_index++) {
|
||||
size_t function_index = mod_context.exported_funcs[export_index];
|
||||
const Function& exported_func = mod_context.base_context.functions[function_index];
|
||||
size_t function_index = context.exported_funcs[export_index];
|
||||
const Function& exported_func = context.functions[function_index];
|
||||
|
||||
ExportV1 export_out {
|
||||
.func_index = static_cast<uint32_t>(function_index),
|
||||
|
|
@ -528,7 +533,7 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::ModContext& m
|
|||
|
||||
// Write the dependencies.
|
||||
for (size_t dependency_index = 0; dependency_index < num_dependencies; dependency_index++) {
|
||||
const Dependency& dependency = mod_context.dependencies[dependency_index];
|
||||
const Dependency& dependency = context.dependencies[dependency_index];
|
||||
|
||||
DependencyV1 dependency_out {
|
||||
.major_version = dependency.major_version,
|
||||
|
|
@ -544,15 +549,12 @@ std::vector<uint8_t> N64Recomp::symbols_to_bin_v1(const N64Recomp::ModContext& m
|
|||
// Write the imported functions.
|
||||
for (size_t import_index = 0; import_index < num_imported_funcs; import_index++) {
|
||||
// Get the index of the reference symbol for this import.
|
||||
size_t reference_symbol_index = import_symbol_base_index + import_index;
|
||||
const ReferenceSymbol& imported_func = mod_context.base_context.reference_symbols[reference_symbol_index];
|
||||
const std::string& imported_func_name = mod_context.base_context.reference_symbol_names[reference_symbol_index];
|
||||
size_t dependency_index = mod_context.import_symbol_dependency_indices[import_index];
|
||||
const ImportSymbol& imported_func = context.import_symbols[import_index];
|
||||
|
||||
ImportV1 import_out {
|
||||
.name_start = imported_func_name_positions[import_index],
|
||||
.name_size = static_cast<uint32_t>(imported_func_name.size()),
|
||||
.dependency = static_cast<uint32_t>(dependency_index)
|
||||
.name_size = static_cast<uint32_t>(imported_func.base.name.size()),
|
||||
.dependency = static_cast<uint32_t>(imported_func.dependency_index)
|
||||
};
|
||||
|
||||
vec_put(ret, &import_out);
|
||||
|
|
|
|||
|
|
@ -238,13 +238,12 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
|
|||
return true;
|
||||
};
|
||||
|
||||
auto print_func_call = [reloc_target_section_offset, reloc_reference_symbol, reloc_type, &context, §ion, &func, &static_funcs_out, &needs_link_branch, &print_unconditional_branch]
|
||||
auto print_func_call = [reloc_target_section_offset, reloc_section, reloc_reference_symbol, reloc_type, &context, §ion, &func, &static_funcs_out, &needs_link_branch, &print_unconditional_branch]
|
||||
(uint32_t target_func_vram, bool link_branch = true, bool indent = false)
|
||||
{
|
||||
std::string jal_target_name{};
|
||||
if (reloc_reference_symbol != (size_t)-1) {
|
||||
const auto& ref_symbol = context.reference_symbols[reloc_reference_symbol];
|
||||
const std::string& ref_symbol_name = context.reference_symbol_names[reloc_reference_symbol];
|
||||
const auto& ref_symbol = context.get_reference_symbol(reloc_section, reloc_reference_symbol);
|
||||
|
||||
if (reloc_type != N64Recomp::RelocType::R_MIPS_26) {
|
||||
fmt::print(stderr, "Unsupported reloc type {} on jal instruction in {}\n", (int)reloc_type, func.name);
|
||||
|
|
@ -256,7 +255,7 @@ bool process_instruction(const N64Recomp::Context& context, const N64Recomp::Fun
|
|||
return false;
|
||||
}
|
||||
|
||||
jal_target_name = ref_symbol_name;
|
||||
jal_target_name = ref_symbol.name;
|
||||
}
|
||||
else {
|
||||
size_t matched_func_index = 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue