mirror of
https://github.com/open-goal/jak-project
synced 2026-06-16 14:50:32 -04:00
[Decompiler - New IR] Add AtomicOp (#181)
* wip decompiler ir * add AtomicOp stuff * fix windows build and warnings * add instruction parser * include * make minilzo shared * odr fix * a * fix merge conflicts * move decompiler into namespace * update the code coverage to include the decompiler * add demo test * add register use test to example test
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include "common/log/log.h"
|
||||
#include "common/goos/PrettyPrinter.h"
|
||||
|
||||
namespace decompiler {
|
||||
/*!
|
||||
* Set the number of segments in this object file.
|
||||
* This can only be done once, and must be done before adding any words.
|
||||
@@ -45,7 +46,7 @@ int LinkedObjectFile::get_label_id_for(int seg, int offset) {
|
||||
if (kv == label_per_seg_by_offset.at(seg).end()) {
|
||||
// create a new label
|
||||
int id = labels.size();
|
||||
Label label;
|
||||
DecompilerLabel label;
|
||||
label.target_segment = seg;
|
||||
label.offset = offset;
|
||||
label.name = "L" + std::to_string(id);
|
||||
@@ -498,7 +499,7 @@ void LinkedObjectFile::process_fp_relative_links() {
|
||||
} break;
|
||||
|
||||
default:
|
||||
printf("unknown fp using op: %s\n", instr.to_string(*this).c_str());
|
||||
printf("unknown fp using op: %s\n", instr.to_string(labels).c_str());
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
@@ -544,7 +545,7 @@ std::string LinkedObjectFile::to_asm_json(const std::string& obj_file_name) {
|
||||
}
|
||||
auto& instr = func.instructions.at(i);
|
||||
op["id"] = i;
|
||||
op["asm_op"] = instr.to_string(*this);
|
||||
op["asm_op"] = instr.to_string(labels);
|
||||
|
||||
if (func.has_basic_ops() && func.instr_starts_basic_op(i)) {
|
||||
op["basic_op"] = func.get_basic_op_at_instr(i)->print(*this);
|
||||
@@ -608,7 +609,7 @@ std::string LinkedObjectFile::print_function_disassembly(Function& func,
|
||||
}
|
||||
|
||||
auto& instr = func.instructions.at(i);
|
||||
std::string line = " " + instr.to_string(*this);
|
||||
std::string line = " " + instr.to_string(labels);
|
||||
|
||||
if (write_hex) {
|
||||
if (line.length() < 60) {
|
||||
@@ -1053,14 +1054,15 @@ goos::Object LinkedObjectFile::to_form_script_object(int seg,
|
||||
return result;
|
||||
}
|
||||
|
||||
u32 LinkedObjectFile::read_data_word(const Label& label) {
|
||||
u32 LinkedObjectFile::read_data_word(const DecompilerLabel& label) {
|
||||
assert(0 == (label.offset % 4));
|
||||
auto& word = words_by_seg.at(label.target_segment).at(label.offset / 4);
|
||||
assert(word.kind == LinkedWord::Kind::PLAIN_DATA);
|
||||
return word.data;
|
||||
}
|
||||
|
||||
std::string LinkedObjectFile::get_goal_string_by_label(const Label& label) const {
|
||||
std::string LinkedObjectFile::get_goal_string_by_label(const DecompilerLabel& label) const {
|
||||
assert(0 == (label.offset % 4));
|
||||
return get_goal_string(label.target_segment, (label.offset / 4) - 1, false);
|
||||
}
|
||||
}
|
||||
} // namespace decompiler
|
||||
@@ -14,19 +14,11 @@
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "LinkedWord.h"
|
||||
#include "decompiler/Disasm/DecompilerLabel.h"
|
||||
#include "decompiler/Function/Function.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
/*!
|
||||
* A label to a location in this object file.
|
||||
* Doesn't have to be word aligned.
|
||||
*/
|
||||
struct Label {
|
||||
std::string name;
|
||||
int target_segment;
|
||||
int offset; // in bytes
|
||||
};
|
||||
|
||||
namespace decompiler {
|
||||
/*!
|
||||
* An object file's data with linking information included.
|
||||
*/
|
||||
@@ -69,8 +61,8 @@ class LinkedObjectFile {
|
||||
const std::string& extra_name);
|
||||
std::string print_asm_function_disassembly(const std::string& my_name);
|
||||
|
||||
u32 read_data_word(const Label& label);
|
||||
std::string get_goal_string_by_label(const Label& label) const;
|
||||
u32 read_data_word(const DecompilerLabel& label);
|
||||
std::string get_goal_string_by_label(const DecompilerLabel& label) const;
|
||||
|
||||
struct Stats {
|
||||
uint32_t total_code_bytes = 0;
|
||||
@@ -131,7 +123,7 @@ class LinkedObjectFile {
|
||||
std::vector<std::vector<LinkedWord>> words_by_seg;
|
||||
std::vector<uint32_t> offset_of_data_zone_by_seg;
|
||||
std::vector<std::vector<Function>> functions_by_seg;
|
||||
std::vector<Label> labels;
|
||||
std::vector<DecompilerLabel> labels;
|
||||
|
||||
private:
|
||||
goos::Object to_form_script(int seg, int word_idx, std::vector<bool>& seen);
|
||||
@@ -142,5 +134,6 @@ class LinkedObjectFile {
|
||||
|
||||
std::vector<std::unordered_map<int, int>> label_per_seg_by_offset;
|
||||
};
|
||||
} // namespace decompiler
|
||||
|
||||
#endif // NEXT_LINKEDOBJECTFILE_H
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "decompiler/util/DecompilerTypeSystem.h"
|
||||
#include "common/link_types.h"
|
||||
|
||||
namespace decompiler {
|
||||
// There are three link versions:
|
||||
// V2 - not really in use anymore, but V4 will resue logic from it (and the game didn't rename the
|
||||
// functions) V3 - optimized for code and small stuff. Supports segments (main, debug, top-level) V4
|
||||
@@ -819,3 +820,4 @@ LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
|
||||
|
||||
return result;
|
||||
}
|
||||
} // namespace decompiler
|
||||
@@ -11,9 +11,11 @@
|
||||
|
||||
#include "LinkedObjectFile.h"
|
||||
|
||||
namespace decompiler {
|
||||
class DecompilerTypeSystem;
|
||||
LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts);
|
||||
} // namespace decompiler
|
||||
|
||||
#endif // NEXT_LINKEDOBJECTFILECREATION_H
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace decompiler {
|
||||
class LinkedWord {
|
||||
public:
|
||||
explicit LinkedWord(uint32_t _data) : data(_data) {}
|
||||
@@ -31,5 +32,6 @@ class LinkedWord {
|
||||
int label_id = -1;
|
||||
std::string symbol_name;
|
||||
};
|
||||
} // namespace decompiler
|
||||
|
||||
#endif // JAK2_DISASSEMBLER_LINKEDWORD_H
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "common/log/log.h"
|
||||
#include "third-party/json.hpp"
|
||||
|
||||
namespace decompiler {
|
||||
namespace {
|
||||
std::string strip_dgo_extension(const std::string& x) {
|
||||
auto ext = x.substr(x.length() - 4, 4);
|
||||
@@ -715,7 +716,7 @@ void ObjectFileDB::process_tpages() {
|
||||
100.f * float(success) / float(total), timer.getMs());
|
||||
}
|
||||
|
||||
std::string ObjectFileDB::process_game_text() {
|
||||
std::string ObjectFileDB::process_game_text_files() {
|
||||
lg::info("- Finding game text...");
|
||||
std::string text_string = "COMMON";
|
||||
Timer timer;
|
||||
@@ -727,7 +728,7 @@ std::string ObjectFileDB::process_game_text() {
|
||||
for_each_obj([&](ObjectFileData& data) {
|
||||
if (data.name_in_dgo.substr(1) == text_string) {
|
||||
file_count++;
|
||||
auto statistics = ::process_game_text(data);
|
||||
auto statistics = process_game_text(data);
|
||||
string_count += statistics.total_text;
|
||||
char_count += statistics.total_chars;
|
||||
if (text_by_language_by_id.find(statistics.language) != text_by_language_by_id.end()) {
|
||||
@@ -743,7 +744,7 @@ std::string ObjectFileDB::process_game_text() {
|
||||
return write_game_text(text_by_language_by_id);
|
||||
}
|
||||
|
||||
std::string ObjectFileDB::process_game_count() {
|
||||
std::string ObjectFileDB::process_game_count_file() {
|
||||
lg::info("- Finding game count file...");
|
||||
bool found = false;
|
||||
std::string result;
|
||||
@@ -752,7 +753,7 @@ std::string ObjectFileDB::process_game_count() {
|
||||
if (data.name_in_dgo == "game-cnt") {
|
||||
assert(!found);
|
||||
found = true;
|
||||
result = write_game_count(::process_game_count(data));
|
||||
result = write_game_count(process_game_count(data));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1125,4 +1126,5 @@ void ObjectFileDB::dump_raw_objects(const std::string& output_dir) {
|
||||
auto dest = output_dir + "/" + data.to_unique_name();
|
||||
file_util::write_binary_file(dest, data.data.data(), data.data.size());
|
||||
});
|
||||
}
|
||||
}
|
||||
} // namespace decompiler
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "decompiler/util/DecompilerTypeSystem.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace decompiler {
|
||||
/*!
|
||||
* A "record" which can be used to identify an object file.
|
||||
*/
|
||||
@@ -67,8 +68,8 @@ class ObjectFileDB {
|
||||
void analyze_functions();
|
||||
void process_tpages();
|
||||
void analyze_expressions();
|
||||
std::string process_game_count();
|
||||
std::string process_game_text();
|
||||
std::string process_game_count_file();
|
||||
std::string process_game_text_files();
|
||||
|
||||
ObjectFileData& lookup_record(const ObjectFileRecord& rec);
|
||||
DecompilerTypeSystem dts;
|
||||
@@ -148,5 +149,6 @@ class ObjectFileDB {
|
||||
uint32_t unique_obj_bytes = 0;
|
||||
} stats;
|
||||
};
|
||||
} // namespace decompiler
|
||||
|
||||
#endif // JAK2_DISASSEMBLER_OBJECTFILEDB_H
|
||||
|
||||
Reference in New Issue
Block a user