mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 21:27:52 -04:00
b56025412b
- Recognize new type definitions/parents/type flags in the decompiler - Analyze autogenerated inspect methods and dump guesses at fields to a file - Utility functions for accessing static data by label - Better ordering in the decompiler to go through functions in the order they appeared in the source - Added a decent number of types to `all-types.gc` based on the new field analyzer - Correct a few `int`/`integer` mistakes in `gcommon.gc` (this should really be a warning) - Correct a few type issues in `gcommon` and `gkernel-h` - Option in the decompiler to be strict about `define-extern` redefining a type of a symbol - Add a test to check consistency in types between `all-types.gc` (used by decompiler) and `goal_src` (used by the compiler)
138 lines
4.3 KiB
C++
138 lines
4.3 KiB
C++
#pragma once
|
|
|
|
/*!
|
|
* @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"
|
|
|
|
/*!
|
|
* A "record" which can be used to identify an object file.
|
|
*/
|
|
struct ObjectFileRecord {
|
|
std::string name; // including -ag, not including dgo suffix
|
|
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
|
|
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;
|
|
std::string to_unique_name() const;
|
|
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);
|
|
std::string generate_dgo_listing();
|
|
std::string generate_obj_listing();
|
|
void process_link_data();
|
|
void process_labels();
|
|
void find_code();
|
|
void find_and_write_scripts(const std::string& output_dir);
|
|
|
|
void write_object_file_words(const std::string& output_dir, bool dump_v3_only);
|
|
void write_disassembly(const std::string& output_dir, bool disassemble_objects_without_functions);
|
|
void analyze_functions();
|
|
ObjectFileData& lookup_record(const ObjectFileRecord& rec);
|
|
DecompilerTypeSystem dts;
|
|
std::string all_type_defs;
|
|
|
|
private:
|
|
void load_map_file(const std::string& map_data);
|
|
void get_objs_from_dgo(const std::string& filename);
|
|
void add_obj_from_dgo(const std::string& obj_name,
|
|
const std::string& name_in_dgo,
|
|
uint8_t* obj_data,
|
|
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());
|
|
for (const auto& name : obj_file_order) {
|
|
for (auto& obj : obj_files_by_name.at(name)) {
|
|
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) {
|
|
// 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)) {
|
|
// printf("fn %d\n", fn);
|
|
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++;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// 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;
|
|
|
|
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
|