decomp: new feature in decompiler to hash the contents of a function for easy comparison

This commit is contained in:
Tyler Wilding
2026-04-19 15:53:17 -04:00
parent 174057791e
commit 65971bb6d6
9 changed files with 41 additions and 5 deletions
@@ -18,6 +18,7 @@
#include "fmt/format.h"
#include "third-party/json.hpp"
#include "third-party/zstd/lib/common/xxhash.h"
namespace decompiler {
/*!
@@ -710,6 +711,20 @@ std::string LinkedObjectFile::print_asm_function_disassembly(const std::string&
return result;
}
// Currently, just hashes the contents of every function, this makes it easy to
// compare between games to see if something is identical
void LinkedObjectFile::dump_asm_function_metadata(std::unordered_map<std::string, std::string> &map) {
ASSERT(segments <= 3);
for (int seg = segments; seg-- > 0;) {
// functions
for (auto& func : functions_by_seg.at(seg)) {
const auto& function_rep = print_function_disassembly(func, seg, false, "");
const auto func_hash = XXH64(function_rep.data(), function_rep.size(), 0);
map.emplace(func.name(), fmt::format("{}", func_hash));
}
}
}
/*!
* Print disassembled functions and data segments.
*/
+1
View File
@@ -67,6 +67,7 @@ class LinkedObjectFile {
bool write_hex,
const std::string& extra_name);
std::string print_asm_function_disassembly(const std::string& my_name);
void dump_asm_function_metadata(std::unordered_map<std::string, std::string> &map);
u32 read_data_word(const DecompilerLabel& label);
const DecompilerLabel& get_label_by_name(const std::string& name) const;
+16 -1
View File
@@ -11,6 +11,7 @@
#include <cstring>
#include <map>
#include <set>
#include <unordered_map>
#include "LinkedObjectFileCreation.h"
@@ -34,6 +35,7 @@
#include "decompiler/data/game_text.h"
#include "decompiler/data/tpage.h"
#include "third-party/json.hpp"
#include "third-party/xdelta3/xdelta3.h"
namespace decompiler {
@@ -630,18 +632,26 @@ void ObjectFileDB::write_object_file_words(const fs::path& output_dir,
void ObjectFileDB::write_disassembly(const fs::path& output_dir,
bool disassemble_data,
bool disassemble_code,
bool print_hex) {
bool print_hex,
bool dump_function_metadata) {
lg::info("- Writing functions...");
Timer timer;
uint32_t total_bytes = 0, total_files = 0;
std::string asm_functions;
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> file_func_metadata_map = {};
for_each_obj([&](ObjectFileData& obj) {
if (((obj.obj_version == 3 || (obj.obj_version == 5 && obj.linked_data.has_any_functions())) &&
disassemble_code) ||
(obj.obj_version != 3 && disassemble_data)) {
auto file_text = obj.linked_data.print_disassembly(print_hex);
if (dump_function_metadata) {
if (!file_func_metadata_map.contains(obj.to_unique_name())) {
file_func_metadata_map[obj.to_unique_name()] = std::unordered_map<std::string, std::string>{};
}
obj.linked_data.dump_asm_function_metadata(file_func_metadata_map[obj.to_unique_name()]);
}
asm_functions += obj.linked_data.print_asm_function_disassembly(obj.to_unique_name());
auto file_name = output_dir / (obj.to_unique_name() + ".asm");
@@ -655,6 +665,11 @@ void ObjectFileDB::write_disassembly(const fs::path& output_dir,
total_files++;
file_util::write_text_file(output_dir / "asm_functions.func", asm_functions);
if (dump_function_metadata) {
json data = file_func_metadata_map;
file_util::write_text_file(output_dir / "func_metadata.json", data.dump(2));
}
lg::info("Wrote functions dumps:");
lg::info(" Total {} files", total_files);
lg::info(" Total {} MB", total_bytes / ((float)(1u << 20u)));
+1 -1
View File
@@ -196,7 +196,7 @@ class ObjectFileDB {
void write_disassembly(const fs::path& output_dir,
bool disassemble_data,
bool disassemble_code,
bool print_hex);
bool print_hex, bool dump_function_metadata);
void process_object_file_data(
ObjectFileData& data,