jak-project/decompiler/ObjectFile/ObjectFileDB.h

153 lines
4.9 KiB
C
Raw Normal View History

#pragma once
2020-08-22 23:30:17 -04:00
/*!
* @file ObjectFileDB.h
* A "database" of object files found in DGO files.
* Eliminates duplicate object files, and also assigns unique names to all object files
* (there may be different object files with the same name sometimes)
*/
#ifndef JAK2_DISASSEMBLER_OBJECTFILEDB_H
#define JAK2_DISASSEMBLER_OBJECTFILEDB_H
#include <cassert>
#include <string>
#include <unordered_map>
#include <vector>
#include "LinkedObjectFile.h"
#include "decompiler/util/DecompilerTypeSystem.h"
#include "common/common_types.h"
2020-08-22 23:30:17 -04:00
/*!
* A "record" which can be used to identify an object file.
*/
struct ObjectFileRecord {
std::string name; // including -ag, not including dgo suffix
2020-08-22 23:30:17 -04:00
int version = -1;
uint32_t hash = 0;
};
/*!
* All of the data for a single object file
*/
struct ObjectFileData {
std::vector<uint8_t> data; // raw bytes
LinkedObjectFile linked_data; // data including linking annotations
ObjectFileRecord record; // name
2020-09-03 20:11:31 -04:00
std::vector<std::string> dgo_names;
int obj_version = -1;
bool has_multiple_versions = false;
std::string name_in_dgo;
std::string name_from_map;
2020-09-03 20:11:31 -04:00
std::string to_unique_name() const;
2020-08-22 23:30:17 -04:00
uint32_t reference_count = 0; // number of times its used.
};
class ObjectFileDB {
public:
ObjectFileDB(const std::vector<std::string>& _dgos,
const std::string& obj_file_name_map_file,
const std::vector<std::string>& object_files,
const std::vector<std::string>& str_files);
2020-08-22 23:30:17 -04:00
std::string generate_dgo_listing();
2020-09-03 20:11:31 -04:00
std::string generate_obj_listing();
2020-08-22 23:30:17 -04:00
void process_link_data();
void process_labels();
void find_code();
void find_and_write_scripts(const std::string& output_dir);
void dump_raw_objects(const std::string& output_dir);
2020-08-22 23:30:17 -04:00
void write_object_file_words(const std::string& output_dir, bool dump_v3_only);
2020-11-27 16:38:36 -05:00
void write_disassembly(const std::string& output_dir,
bool disassemble_objects_without_functions,
bool write_json,
const std::string& file_suffix = "");
2020-11-27 16:38:36 -05:00
void write_debug_type_analysis(const std::string& output_dir, const std::string& suffix = "");
2020-08-22 23:30:17 -04:00
void analyze_functions();
void process_tpages();
void analyze_expressions();
std::string process_game_count();
std::string process_game_text();
ObjectFileData& lookup_record(const ObjectFileRecord& rec);
DecompilerTypeSystem dts;
std::string all_type_defs;
2020-08-22 23:30:17 -04:00
private:
void load_map_file(const std::string& map_data);
2020-08-22 23:30:17 -04:00
void get_objs_from_dgo(const std::string& filename);
void add_obj_from_dgo(const std::string& obj_name,
2020-09-03 20:11:31 -04:00
const std::string& name_in_dgo,
const uint8_t* obj_data,
2020-08-22 23:30:17 -04:00
uint32_t obj_size,
const std::string& dgo_name);
/*!
* Apply f to all ObjectFileData's. Does it in the right order.
*/
template <typename Func>
void for_each_obj(Func f) {
assert(obj_files_by_name.size() == obj_file_order.size());
2020-08-26 01:21:33 -04:00
for (const auto& name : obj_file_order) {
for (auto& obj : obj_files_by_name.at(name)) {
2020-08-22 23:30:17 -04:00
f(obj);
}
}
}
/*!
* Apply f to all functions
* takes (Function, segment, linked_data)
* Does it in the right order.
*/
template <typename Func>
void for_each_function(Func f) {
for_each_obj([&](ObjectFileData& data) {
2020-08-26 01:21:33 -04:00
// printf("IN %s\n", data.record.to_unique_name().c_str());
2020-08-22 23:30:17 -04:00
for (int i = 0; i < int(data.linked_data.segments); i++) {
2020-08-26 01:21:33 -04:00
// printf("seg %d\n", i);
2020-08-22 23:30:17 -04:00
int fn = 0;
for (auto& goal_func : data.linked_data.functions_by_seg.at(i)) {
2020-08-26 01:21:33 -04:00
// printf("fn %d\n", fn);
2020-08-22 23:30:17 -04:00
f(goal_func, i, data);
fn++;
}
}
});
}
template <typename Func>
void for_each_function_def_order(Func f) {
for_each_obj([&](ObjectFileData& data) {
// printf("IN %s\n", data.record.to_unique_name().c_str());
for (int i = 0; i < int(data.linked_data.segments); i++) {
// printf("seg %d\n", i);
int fn = 0;
// for (auto& goal_func : data.linked_data.functions_by_seg.at(i)) {
for (size_t j = data.linked_data.functions_by_seg.at(i).size(); j-- > 0;) {
// printf("fn %d\n", fn);
f(data.linked_data.functions_by_seg.at(i).at(j), i, data);
fn++;
}
}
});
}
2020-08-22 23:30:17 -04:00
// Danger: after adding all object files, we assume that the vector never reallocates.
std::unordered_map<std::string, std::vector<ObjectFileData>> obj_files_by_name;
std::unordered_map<std::string, std::vector<ObjectFileRecord>> obj_files_by_dgo;
std::vector<std::string> obj_file_order;
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> dgo_obj_name_map;
2020-08-22 23:30:17 -04:00
struct {
uint32_t total_dgo_bytes = 0;
uint32_t total_obj_files = 0;
uint32_t unique_obj_files = 0;
uint32_t unique_obj_bytes = 0;
} stats;
};
#endif // JAK2_DISASSEMBLER_OBJECTFILEDB_H