mirror of
https://github.com/N64Recomp/N64Recomp.git
synced 2026-04-30 22:11:43 +00:00
Consolidate context dumping toggle into a single bool, begin work on data symbol context dumping
This commit is contained in:
parent
16819a0515
commit
873219d4c5
1 changed files with 59 additions and 34 deletions
93
src/main.cpp
93
src/main.cpp
|
|
@ -672,7 +672,7 @@ std::unordered_set<std::string> renamed_funcs{
|
||||||
"_matherr",
|
"_matherr",
|
||||||
};
|
};
|
||||||
|
|
||||||
bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, ELFIO::section* symtab_section, uint32_t entrypoint, bool has_entrypoint, bool use_absolute_symbols) {
|
bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, ELFIO::section* symtab_section, uint32_t entrypoint, bool has_entrypoint, bool use_absolute_symbols, bool do_renaming) {
|
||||||
bool found_entrypoint_func = false;
|
bool found_entrypoint_func = false;
|
||||||
ELFIO::symbol_section_accessor symbols{ elf_file, symtab_section };
|
ELFIO::symbol_section_accessor symbols{ elf_file, symtab_section };
|
||||||
fmt::print("Num symbols: {}\n", symbols.get_symbols_num());
|
fmt::print("Num symbols: {}\n", symbols.get_symbols_num());
|
||||||
|
|
@ -732,13 +732,15 @@ bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, EL
|
||||||
type = ELFIO::STT_FUNC;
|
type = ELFIO::STT_FUNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reimplemented_funcs.contains(name)) {
|
if (do_renaming) {
|
||||||
reimplemented = true;
|
if (reimplemented_funcs.contains(name)) {
|
||||||
name = name + "_recomp";
|
reimplemented = true;
|
||||||
ignored = true;
|
name = name + "_recomp";
|
||||||
} else if (ignored_funcs.contains(name)) {
|
ignored = true;
|
||||||
name = name + "_recomp";
|
} else if (ignored_funcs.contains(name)) {
|
||||||
ignored = true;
|
name = name + "_recomp";
|
||||||
|
ignored = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& section = context.sections[section_index];
|
auto& section = context.sections[section_index];
|
||||||
|
|
@ -746,9 +748,11 @@ bool read_symbols(RecompPort::Context& context, const ELFIO::elfio& elf_file, EL
|
||||||
// Check if this symbol is a function or has no type (like a regular glabel would)
|
// Check if this symbol is a function or has no type (like a regular glabel would)
|
||||||
// Symbols with no type have a dummy entry created so that their symbol can be looked up for function calls
|
// Symbols with no type have a dummy entry created so that their symbol can be looked up for function calls
|
||||||
if (ignored || type == ELFIO::STT_FUNC || type == ELFIO::STT_NOTYPE || type == ELFIO::STT_OBJECT) {
|
if (ignored || type == ELFIO::STT_FUNC || type == ELFIO::STT_NOTYPE || type == ELFIO::STT_OBJECT) {
|
||||||
if (renamed_funcs.contains(name)) {
|
if (do_renaming) {
|
||||||
name = name + "_recomp";
|
if (renamed_funcs.contains(name)) {
|
||||||
ignored = false;
|
name = name + "_recomp";
|
||||||
|
ignored = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (section_index < context.sections.size()) {
|
if (section_index < context.sections.size()) {
|
||||||
|
|
@ -1258,48 +1262,61 @@ std::vector<std::string> reloc_names {
|
||||||
"R_MIPS_GPREL16",
|
"R_MIPS_GPREL16",
|
||||||
};
|
};
|
||||||
|
|
||||||
void dump_context(const RecompPort::Context& context, const std::filesystem::path& path) {
|
void dump_context(const RecompPort::Context& context, const std::filesystem::path& func_path, const std::filesystem::path& data_path) {
|
||||||
std::ofstream context_file {path};
|
std::ofstream func_context_file {func_path};
|
||||||
|
std::ofstream data_context_file {data_path};
|
||||||
|
|
||||||
|
fmt::print(func_context_file, "# Autogenerated from an ELF via N64Recomp\n");
|
||||||
|
fmt::print(data_context_file, "# Autogenerated from an ELF via N64Recomp\n");
|
||||||
|
|
||||||
|
auto print_section = [](std::ofstream& output_file, const std::string& name, uint64_t rom_addr, uint64_t ram_addr, uint64_t size) {
|
||||||
|
fmt::print(output_file,
|
||||||
|
"[[section]]\n"
|
||||||
|
"name = \"{}\"\n"
|
||||||
|
"rom = 0x{:08X}\n"
|
||||||
|
"vram = 0x{:08X}\n"
|
||||||
|
"size = 0x{:X}\n"
|
||||||
|
"\n",
|
||||||
|
name, rom_addr, ram_addr, size);
|
||||||
|
};
|
||||||
|
|
||||||
for (size_t section_index = 0; section_index < context.sections.size(); section_index++) {
|
for (size_t section_index = 0; section_index < context.sections.size(); section_index++) {
|
||||||
const RecompPort::Section& section = context.sections[section_index];
|
const RecompPort::Section& section = context.sections[section_index];
|
||||||
const std::vector<size_t>& section_funcs = context.section_functions[section_index];
|
const std::vector<size_t>& section_funcs = context.section_functions[section_index];
|
||||||
if (!section_funcs.empty()) {
|
if (!section_funcs.empty()) {
|
||||||
fmt::print(context_file,
|
print_section(func_context_file, section.name, section.rom_addr, section.ram_addr, section.size);
|
||||||
"# Autogenerated from an ELF via N64Recomp\n"
|
print_section(data_context_file, section.name, section.rom_addr, section.ram_addr, section.size);
|
||||||
"[[section]]\n"
|
|
||||||
"name = \"{}\"\n"
|
|
||||||
"rom = 0x{:08X}\n"
|
|
||||||
"vram = 0x{:08X}\n"
|
|
||||||
"size = 0x{:X}\n"
|
|
||||||
"\n",
|
|
||||||
section.name, section.rom_addr, section.ram_addr, section.size);
|
|
||||||
|
|
||||||
|
// Dump relocs into the function context file.
|
||||||
if (!section.relocs.empty()) {
|
if (!section.relocs.empty()) {
|
||||||
fmt::print(context_file, "relocs = [\n");
|
fmt::print(func_context_file, "relocs = [\n");
|
||||||
|
|
||||||
for (const RecompPort::Reloc& reloc : section.relocs) {
|
for (const RecompPort::Reloc& reloc : section.relocs) {
|
||||||
if (reloc.target_section == section_index || reloc.target_section == section.bss_section_index) {
|
if (reloc.target_section == section_index || reloc.target_section == section.bss_section_index) {
|
||||||
// TODO allow MIPS32 relocs for TLB mapping support.
|
// TODO allow MIPS32 relocs for TLB mapping support.
|
||||||
if (reloc.type == RecompPort::RelocType::R_MIPS_HI16 || reloc.type == RecompPort::RelocType::R_MIPS_LO16) {
|
if (reloc.type == RecompPort::RelocType::R_MIPS_HI16 || reloc.type == RecompPort::RelocType::R_MIPS_LO16) {
|
||||||
fmt::print(context_file, " {{ type = \"{}\", vram = 0x{:08X}, target_vram = 0x{:08X} }},\n",
|
fmt::print(func_context_file, " {{ type = \"{}\", vram = 0x{:08X}, target_vram = 0x{:08X} }},\n",
|
||||||
reloc_names[static_cast<int>(reloc.type)], reloc.address, reloc.target_address);
|
reloc_names[static_cast<int>(reloc.type)], reloc.address, reloc.target_address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::print(context_file, "]\n\n");
|
fmt::print(func_context_file, "]\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::print(context_file, "functions = [\n");
|
// Dump functions into the function context file.
|
||||||
|
fmt::print(func_context_file, "functions = [\n");
|
||||||
|
|
||||||
for (const size_t& function_index : section_funcs) {
|
for (const size_t& function_index : section_funcs) {
|
||||||
const RecompPort::Function& func = context.functions[function_index];
|
const RecompPort::Function& func = context.functions[function_index];
|
||||||
fmt::print(context_file, " {{ name = \"{}\", vram = 0x{:08X}, size = 0x{:X} }},\n",
|
fmt::print(func_context_file, " {{ name = \"{}\", vram = 0x{:08X}, size = 0x{:X} }},\n",
|
||||||
func.name, func.vram, func.words.size() * sizeof(func.words[0]));
|
func.name, func.vram, func.words.size() * sizeof(func.words[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::print(context_file, "]\n\n");
|
// Dump variables into the data context file.
|
||||||
|
|
||||||
|
|
||||||
|
fmt::print(func_context_file, "]\n\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1326,6 +1343,9 @@ int main(int argc, char** argv) {
|
||||||
std::exit(EXIT_FAILURE);
|
std::exit(EXIT_FAILURE);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO expose a way to dump the context from the command line.
|
||||||
|
bool dumping_context = false;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
fmt::print("Usage: {} [config file]\n", argv[0]);
|
fmt::print("Usage: {} [config file]\n", argv[0]);
|
||||||
std::exit(EXIT_SUCCESS);
|
std::exit(EXIT_SUCCESS);
|
||||||
|
|
@ -1397,7 +1417,7 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read all of the symbols in the elf and look for the entrypoint function
|
// Read all of the symbols in the elf and look for the entrypoint function
|
||||||
bool found_entrypoint_func = read_symbols(context, elf_file, symtab_section, config.entrypoint, config.has_entrypoint, config.use_absolute_symbols);
|
bool found_entrypoint_func = read_symbols(context, elf_file, symtab_section, config.entrypoint, config.has_entrypoint, config.use_absolute_symbols, !dumping_context);
|
||||||
|
|
||||||
// Add any manual functions
|
// Add any manual functions
|
||||||
add_manual_functions(context, elf_file, config.manual_functions);
|
add_manual_functions(context, elf_file, config.manual_functions);
|
||||||
|
|
@ -1405,6 +1425,12 @@ int main(int argc, char** argv) {
|
||||||
if (config.has_entrypoint && !found_entrypoint_func) {
|
if (config.has_entrypoint && !found_entrypoint_func) {
|
||||||
exit_failure("Could not find entrypoint function\n");
|
exit_failure("Could not find entrypoint function\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dumping_context) {
|
||||||
|
fmt::print("Dumping context\n");
|
||||||
|
dump_context(context, "dump.toml", "data_dump.toml");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Build a context from the provided symbols file.
|
// Build a context from the provided symbols file.
|
||||||
else if (!config.symbols_file_path.empty()) {
|
else if (!config.symbols_file_path.empty()) {
|
||||||
|
|
@ -1412,6 +1438,10 @@ int main(int argc, char** argv) {
|
||||||
exit_failure("A ROM file must be provided when using a symbols file\n");
|
exit_failure("A ROM file must be provided when using a symbols file\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dumping_context) {
|
||||||
|
exit_failure("Cannot dump context when using a symbols file\n");
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> rom = read_file(config.rom_file_path);
|
std::vector<uint8_t> rom = read_file(config.rom_file_path);
|
||||||
if (rom.empty()) {
|
if (rom.empty()) {
|
||||||
exit_failure("Failed to load ROM file: " + config.rom_file_path.string() + "\n");
|
exit_failure("Failed to load ROM file: " + config.rom_file_path.string() + "\n");
|
||||||
|
|
@ -1485,11 +1515,6 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
std::vector<std::vector<uint32_t>> static_funcs_by_section{ context.sections.size() };
|
std::vector<std::vector<uint32_t>> static_funcs_by_section{ context.sections.size() };
|
||||||
|
|
||||||
// TODO expose a way to dump the context from the command line. Make sure not to rename functions when doing so.
|
|
||||||
//fmt::print("Dumping context\n");
|
|
||||||
//dump_context(context, "dump.toml");
|
|
||||||
//return 0;
|
|
||||||
|
|
||||||
fmt::print("Working dir: {}\n", std::filesystem::current_path().string());
|
fmt::print("Working dir: {}\n", std::filesystem::current_path().string());
|
||||||
|
|
||||||
// Stub out any functions specified in the config file.
|
// Stub out any functions specified in the config file.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue