mirror of
https://github.com/open-goal/jak-project
synced 2026-08-21 14:54:53 -04:00
[decompiler] Clean up config more (#458)
* remove global config * fix dir
This commit is contained in:
@@ -680,8 +680,7 @@ std::string LinkedObjectFile::print_asm_function_disassembly(const std::string&
|
||||
/*!
|
||||
* Print disassembled functions and data segments.
|
||||
*/
|
||||
std::string LinkedObjectFile::print_disassembly() {
|
||||
bool write_hex = get_config().write_hex_near_instructions;
|
||||
std::string LinkedObjectFile::print_disassembly(bool write_hex) {
|
||||
std::string result;
|
||||
|
||||
assert(segments <= 3);
|
||||
|
||||
@@ -51,7 +51,7 @@ class LinkedObjectFile {
|
||||
void disassemble_functions();
|
||||
void process_fp_relative_links();
|
||||
std::string print_scripts();
|
||||
std::string print_disassembly();
|
||||
std::string print_disassembly(bool write_hex);
|
||||
bool has_any_functions();
|
||||
void append_word_to_string(std::string& dest, const LinkedWord& word) const;
|
||||
std::string print_function_disassembly(Function& func,
|
||||
|
||||
@@ -609,7 +609,8 @@ static void link_v5(LinkedObjectFile& f,
|
||||
static void link_v3(LinkedObjectFile& f,
|
||||
const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts) {
|
||||
DecompilerTypeSystem& dts,
|
||||
int game_version) {
|
||||
auto header = (const LinkHeaderV3*)(&data.at(0));
|
||||
assert(name == header->name);
|
||||
assert(header->segments == 3);
|
||||
@@ -656,11 +657,11 @@ static void link_v3(LinkedObjectFile& f,
|
||||
// HACK!
|
||||
// why is this a thing?
|
||||
// HACK!
|
||||
if (get_config().game_version == 1 && name == "level-h" && seg_id == 0) {
|
||||
if (game_version == 1 && name == "level-h" && seg_id == 0) {
|
||||
segment_size++;
|
||||
}
|
||||
|
||||
if (get_config().game_version == 2) {
|
||||
if (game_version == 2) {
|
||||
bool adjusted = false;
|
||||
while (segment_size % 4) {
|
||||
segment_size++;
|
||||
@@ -800,14 +801,15 @@ static void link_v3(LinkedObjectFile& f,
|
||||
*/
|
||||
LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts) {
|
||||
DecompilerTypeSystem& dts,
|
||||
int game_version) {
|
||||
LinkedObjectFile result;
|
||||
const auto* header = (const LinkHeaderCommon*)&data.at(0);
|
||||
|
||||
// use appropriate linker
|
||||
if (header->version == 3) {
|
||||
assert(header->type_tag == 0);
|
||||
link_v3(result, data, name, dts);
|
||||
link_v3(result, data, name, dts, game_version);
|
||||
} else if (header->version == 4 || header->version == 2) {
|
||||
assert(header->type_tag == 0xffffffff);
|
||||
link_v2_or_v4(result, data, name, dts);
|
||||
|
||||
@@ -6,16 +6,12 @@
|
||||
* This implements a decoder for the GOAL linking format.
|
||||
*/
|
||||
|
||||
#ifndef NEXT_LINKEDOBJECTFILECREATION_H
|
||||
#define NEXT_LINKEDOBJECTFILECREATION_H
|
||||
|
||||
#include "LinkedObjectFile.h"
|
||||
|
||||
namespace decompiler {
|
||||
class DecompilerTypeSystem;
|
||||
LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts);
|
||||
DecompilerTypeSystem& dts,
|
||||
int game_version);
|
||||
} // namespace decompiler
|
||||
|
||||
#endif // NEXT_LINKEDOBJECTFILECREATION_H
|
||||
|
||||
@@ -110,7 +110,8 @@ ObjectFileData& ObjectFileDB::lookup_record(const ObjectFileRecord& rec) {
|
||||
ObjectFileDB::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) {
|
||||
const std::vector<std::string>& str_files,
|
||||
const Config& config) {
|
||||
Timer timer;
|
||||
|
||||
lg::info("-Loading types...");
|
||||
@@ -128,14 +129,14 @@ ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos,
|
||||
|
||||
lg::info("-Loading {} DGOs...", _dgos.size());
|
||||
for (auto& dgo : _dgos) {
|
||||
get_objs_from_dgo(dgo);
|
||||
get_objs_from_dgo(dgo, config);
|
||||
}
|
||||
|
||||
lg::info("-Loading {} plain object files...", object_files.size());
|
||||
for (auto& obj : object_files) {
|
||||
auto data = file_util::read_binary_file(obj);
|
||||
auto name = obj_filename_to_name(obj);
|
||||
add_obj_from_dgo(name, name, data.data(), data.size(), "NO-XGO");
|
||||
add_obj_from_dgo(name, name, data.data(), data.size(), "NO-XGO", config);
|
||||
}
|
||||
|
||||
lg::info("-Loading {} streaming object files...", str_files.size());
|
||||
@@ -149,7 +150,7 @@ ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos,
|
||||
// append the chunk ID to the full name
|
||||
std::string name = obj_name + fmt::format("+{}", i);
|
||||
auto& data = reader.get_chunk(i);
|
||||
add_obj_from_dgo(name, name, data.data(), data.size(), "NO-XGO");
|
||||
add_obj_from_dgo(name, name, data.data(), data.size(), "NO-XGO", config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +191,7 @@ constexpr int MAX_CHUNK_SIZE = 0x8000;
|
||||
/*!
|
||||
* Load the objects stored in the given DGO into the ObjectFileDB
|
||||
*/
|
||||
void ObjectFileDB::get_objs_from_dgo(const std::string& filename) {
|
||||
void ObjectFileDB::get_objs_from_dgo(const std::string& filename, const Config& config) {
|
||||
auto dgo_data = file_util::read_binary_file(filename);
|
||||
stats.total_dgo_bytes += dgo_data.size();
|
||||
|
||||
@@ -221,7 +222,8 @@ void ObjectFileDB::get_objs_from_dgo(const std::string& filename) {
|
||||
|
||||
auto name = get_object_file_name(obj_header.name, reader.here(), obj_header.object_count);
|
||||
|
||||
add_obj_from_dgo(name, obj_header.name, reader.here(), obj_header.object_count, dgo_base_name);
|
||||
add_obj_from_dgo(name, obj_header.name, reader.here(), obj_header.object_count, dgo_base_name,
|
||||
config);
|
||||
reader.ffwd(obj_header.object_count);
|
||||
}
|
||||
|
||||
@@ -236,8 +238,8 @@ void ObjectFileDB::add_obj_from_dgo(const std::string& obj_name,
|
||||
const std::string& name_in_dgo,
|
||||
const uint8_t* obj_data,
|
||||
uint32_t obj_size,
|
||||
const std::string& dgo_name) {
|
||||
const auto& config = get_config();
|
||||
const std::string& dgo_name,
|
||||
const Config& config) {
|
||||
if (!config.allowed_objects.empty()) {
|
||||
if (config.allowed_objects.find(obj_name) == config.allowed_objects.end()) {
|
||||
return;
|
||||
@@ -390,14 +392,14 @@ std::string ObjectFileDB::generate_obj_listing() {
|
||||
/*!
|
||||
* Process all of the linking data of all objects.
|
||||
*/
|
||||
void ObjectFileDB::process_link_data() {
|
||||
void ObjectFileDB::process_link_data(const Config& config) {
|
||||
lg::info("Processing Link Data...");
|
||||
Timer process_link_timer;
|
||||
|
||||
LinkedObjectFile::Stats combined_stats;
|
||||
|
||||
for_each_obj([&](ObjectFileData& obj) {
|
||||
obj.linked_data = to_linked_object_file(obj.data, obj.record.name, dts);
|
||||
obj.linked_data = to_linked_object_file(obj.data, obj.record.name, dts, config.game_version);
|
||||
combined_stats.add(obj.linked_data.stats);
|
||||
});
|
||||
|
||||
@@ -454,7 +456,8 @@ void ObjectFileDB::write_object_file_words(const std::string& output_dir,
|
||||
*/
|
||||
void ObjectFileDB::write_disassembly(const std::string& output_dir,
|
||||
bool disassemble_data,
|
||||
bool disassemble_code) {
|
||||
bool disassemble_code,
|
||||
bool print_hex) {
|
||||
lg::info("- Writing functions...");
|
||||
Timer timer;
|
||||
uint32_t total_bytes = 0, total_files = 0;
|
||||
@@ -463,7 +466,7 @@ void ObjectFileDB::write_disassembly(const std::string& output_dir,
|
||||
|
||||
for_each_obj([&](ObjectFileData& obj) {
|
||||
if ((obj.obj_version == 3 && disassemble_code) || (obj.obj_version != 3 && disassemble_data)) {
|
||||
auto file_text = obj.linked_data.print_disassembly();
|
||||
auto file_text = obj.linked_data.print_disassembly(print_hex);
|
||||
asm_functions += obj.linked_data.print_asm_function_disassembly(obj.to_unique_name());
|
||||
auto file_name = file_util::combine_path(output_dir, obj.to_unique_name() + ".asm");
|
||||
|
||||
@@ -488,7 +491,7 @@ void ObjectFileDB::write_disassembly(const std::string& output_dir,
|
||||
/*!
|
||||
* Find code/data zones, identify functions, and disassemble
|
||||
*/
|
||||
void ObjectFileDB::find_code() {
|
||||
void ObjectFileDB::find_code(const Config& config) {
|
||||
lg::info("Finding code in object files...");
|
||||
LinkedObjectFile::Stats combined_stats;
|
||||
Timer timer;
|
||||
@@ -499,7 +502,7 @@ void ObjectFileDB::find_code() {
|
||||
obj.linked_data.find_functions();
|
||||
obj.linked_data.disassemble_functions();
|
||||
|
||||
if (get_config().game_version == 1 || obj.to_unique_name() != "effect-control-v0") {
|
||||
if (config.game_version == 1 || obj.to_unique_name() != "effect-control-v0") {
|
||||
obj.linked_data.process_fp_relative_links();
|
||||
} else {
|
||||
lg::warn("Skipping process_fp_relative_links in {}", obj.to_unique_name().c_str());
|
||||
@@ -619,12 +622,11 @@ std::string ObjectFileDB::process_game_count_file() {
|
||||
/*!
|
||||
* This is the main decompiler routine which runs after we've identified functions.
|
||||
*/
|
||||
void ObjectFileDB::analyze_functions_ir1() {
|
||||
void ObjectFileDB::analyze_functions_ir1(const Config& config) {
|
||||
lg::info("- Analyzing Functions...");
|
||||
Timer timer;
|
||||
|
||||
int total_functions = 0;
|
||||
const auto& config = get_config();
|
||||
|
||||
// Step 1 - analyze the "top level" or "login" code for each object file.
|
||||
// this will give us type definitions, method definitions, and function definitions...
|
||||
@@ -665,7 +667,8 @@ void ObjectFileDB::analyze_functions_ir1() {
|
||||
|
||||
unique_names.insert(name);
|
||||
|
||||
if (config.asm_functions_by_name.find(name) != config.asm_functions_by_name.end()) {
|
||||
if (config.hacks.asm_functions_by_name.find(name) !=
|
||||
config.hacks.asm_functions_by_name.end()) {
|
||||
func.warnings.info("Flagged as asm by config");
|
||||
func.suspected_asm = true;
|
||||
}
|
||||
@@ -735,7 +738,10 @@ void ObjectFileDB::analyze_functions_ir1() {
|
||||
|
||||
// if we got an inspect method, inspect it.
|
||||
if (func.is_inspect_method) {
|
||||
auto result = inspect_inspect_method(func, func.method_of_type, dts, data.linked_data);
|
||||
auto result = inspect_inspect_method(
|
||||
func, func.method_of_type, dts, data.linked_data,
|
||||
config.hacks.types_with_bad_inspect_methods.find(func.method_of_type) !=
|
||||
config.hacks.types_with_bad_inspect_methods.end());
|
||||
all_type_defs += ";; " + data.to_unique_name() + "\n";
|
||||
all_type_defs += result.print_as_deftype() + "\n";
|
||||
}
|
||||
|
||||
@@ -49,32 +49,34 @@ class ObjectFileDB {
|
||||
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);
|
||||
const std::vector<std::string>& str_files,
|
||||
const Config& config);
|
||||
std::string generate_dgo_listing();
|
||||
std::string generate_obj_listing();
|
||||
void process_link_data();
|
||||
void process_link_data(const Config& config);
|
||||
void process_labels();
|
||||
void find_code();
|
||||
void find_code(const Config& config);
|
||||
void find_and_write_scripts(const std::string& output_dir);
|
||||
void dump_raw_objects(const std::string& output_dir);
|
||||
|
||||
void write_object_file_words(const std::string& output_dir, bool dump_data, bool dump_code);
|
||||
void write_disassembly(const std::string& output_dir,
|
||||
bool disassemble_data,
|
||||
bool disassemble_code);
|
||||
bool disassemble_code,
|
||||
bool print_hex);
|
||||
|
||||
void analyze_functions_ir1();
|
||||
void analyze_functions_ir2(const std::string& output_dir);
|
||||
void ir2_top_level_pass();
|
||||
void analyze_functions_ir1(const Config& config);
|
||||
void analyze_functions_ir2(const std::string& output_dir, const Config& config);
|
||||
void ir2_top_level_pass(const Config& config);
|
||||
void ir2_stack_spill_slot_pass();
|
||||
void ir2_basic_block_pass();
|
||||
void ir2_atomic_op_pass();
|
||||
void ir2_type_analysis_pass();
|
||||
void ir2_atomic_op_pass(const Config& config);
|
||||
void ir2_type_analysis_pass(const Config& config);
|
||||
void ir2_register_usage_pass();
|
||||
void ir2_variable_pass();
|
||||
void ir2_cfg_build_pass();
|
||||
void ir2_store_current_forms();
|
||||
void ir2_build_expressions();
|
||||
void ir2_build_expressions(const Config& config);
|
||||
void ir2_insert_lets();
|
||||
void ir2_rewrite_inline_asm_instructions();
|
||||
void ir2_insert_anonymous_functions();
|
||||
@@ -94,16 +96,18 @@ class ObjectFileDB {
|
||||
|
||||
bool lookup_function_type(const FunctionName& name,
|
||||
const std::string& obj_name,
|
||||
const Config& config,
|
||||
TypeSpec* result);
|
||||
|
||||
public:
|
||||
void load_map_file(const std::string& map_data);
|
||||
void get_objs_from_dgo(const std::string& filename);
|
||||
void get_objs_from_dgo(const std::string& filename, const Config& config);
|
||||
void add_obj_from_dgo(const std::string& obj_name,
|
||||
const std::string& name_in_dgo,
|
||||
const uint8_t* obj_data,
|
||||
uint32_t obj_size,
|
||||
const std::string& dgo_name);
|
||||
const std::string& dgo_name,
|
||||
const Config& config);
|
||||
|
||||
/*!
|
||||
* Apply f to all ObjectFileData's. Does it in the right order.
|
||||
|
||||
@@ -29,18 +29,18 @@ namespace decompiler {
|
||||
* At this point, we assume that the files are loaded and we've run find_code to locate all
|
||||
* functions, but nothing else.
|
||||
*/
|
||||
void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir) {
|
||||
void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir, const Config& config) {
|
||||
lg::info("Using IR2 analysis...");
|
||||
lg::info("Processing top-level functions...");
|
||||
ir2_top_level_pass();
|
||||
ir2_top_level_pass(config);
|
||||
lg::info("Processing basic blocks and control flow graph...");
|
||||
ir2_basic_block_pass();
|
||||
lg::info("Finding stack spills...");
|
||||
ir2_stack_spill_slot_pass();
|
||||
lg::info("Converting to atomic ops...");
|
||||
ir2_atomic_op_pass();
|
||||
ir2_atomic_op_pass(config);
|
||||
lg::info("Running type analysis...");
|
||||
ir2_type_analysis_pass();
|
||||
ir2_type_analysis_pass(config);
|
||||
lg::info("Register usage analysis...");
|
||||
ir2_register_usage_pass();
|
||||
lg::info("Variable analysis...");
|
||||
@@ -51,7 +51,7 @@ void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir) {
|
||||
lg::info("Storing temporary form result...");
|
||||
ir2_store_current_forms();
|
||||
lg::info("Expression building...");
|
||||
ir2_build_expressions();
|
||||
ir2_build_expressions(config);
|
||||
lg::info("Re-writing inline asm instructions...");
|
||||
ir2_rewrite_inline_asm_instructions();
|
||||
|
||||
@@ -74,7 +74,7 @@ void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir) {
|
||||
* - Find method definitions
|
||||
* - Warn for non-unique function names.
|
||||
*/
|
||||
void ObjectFileDB::ir2_top_level_pass() {
|
||||
void ObjectFileDB::ir2_top_level_pass(const Config& config) {
|
||||
Timer timer;
|
||||
int total_functions = 0;
|
||||
int total_named_global_functions = 0;
|
||||
@@ -134,8 +134,8 @@ void ObjectFileDB::ir2_top_level_pass() {
|
||||
|
||||
unique_names.insert(name);
|
||||
|
||||
if (get_config().asm_functions_by_name.find(name) !=
|
||||
get_config().asm_functions_by_name.end()) {
|
||||
if (config.hacks.asm_functions_by_name.find(name) !=
|
||||
config.hacks.asm_functions_by_name.end()) {
|
||||
func.warnings.info("Flagged as asm by config");
|
||||
func.suspected_asm = true;
|
||||
}
|
||||
@@ -253,7 +253,7 @@ void ObjectFileDB::ir2_stack_spill_slot_pass() {
|
||||
* Conversion of MIPS instructions into AtomicOps. The AtomicOps represent what we
|
||||
* think are IR of the original GOAL compiler.
|
||||
*/
|
||||
void ObjectFileDB::ir2_atomic_op_pass() {
|
||||
void ObjectFileDB::ir2_atomic_op_pass(const Config& config) {
|
||||
Timer timer;
|
||||
int total_functions = 0;
|
||||
int attempted = 0;
|
||||
@@ -266,8 +266,8 @@ void ObjectFileDB::ir2_atomic_op_pass() {
|
||||
attempted++;
|
||||
try {
|
||||
bool inline_asm =
|
||||
get_config().hint_inline_assembly_functions.find(func.guessed_name.to_string()) !=
|
||||
get_config().hint_inline_assembly_functions.end();
|
||||
config.hacks.hint_inline_assembly_functions.find(func.guessed_name.to_string()) !=
|
||||
config.hacks.hint_inline_assembly_functions.end();
|
||||
auto ops = convert_function_to_atomic_ops(func, data.linked_data.labels, func.warnings,
|
||||
inline_asm);
|
||||
func.ir2.atomic_ops = std::make_shared<FunctionAtomicOps>(std::move(ops));
|
||||
@@ -288,13 +288,23 @@ void ObjectFileDB::ir2_atomic_op_pass() {
|
||||
100.f * attempted / total_functions, 100.f * successful / attempted);
|
||||
}
|
||||
|
||||
template <typename Key, typename Value>
|
||||
Value try_lookup(const std::unordered_map<Key, Value>& map, const Key& key) {
|
||||
auto lookup = map.find(key);
|
||||
if (lookup == map.end()) {
|
||||
return Value();
|
||||
} else {
|
||||
return lookup->second;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Analyze registers and determine the type in each register at each instruction.
|
||||
* - Figure out the type of each function, from configs.
|
||||
* - Propagate types.
|
||||
* - NOTE: this will update register info usage more accurately for functions.
|
||||
*/
|
||||
void ObjectFileDB::ir2_type_analysis_pass() {
|
||||
void ObjectFileDB::ir2_type_analysis_pass(const Config& config) {
|
||||
Timer timer;
|
||||
int total_functions = 0;
|
||||
int non_asm_functions = 0;
|
||||
@@ -307,21 +317,21 @@ void ObjectFileDB::ir2_type_analysis_pass() {
|
||||
if (!func.suspected_asm) {
|
||||
non_asm_functions++;
|
||||
TypeSpec ts;
|
||||
if (lookup_function_type(func.guessed_name, data.to_unique_name(), &ts) &&
|
||||
if (lookup_function_type(func.guessed_name, data.to_unique_name(), config, &ts) &&
|
||||
func.ir2.atomic_ops_succeeded) {
|
||||
func.type = ts;
|
||||
attempted_functions++;
|
||||
// try type analysis here.
|
||||
auto func_name = func.guessed_name.to_string();
|
||||
auto casts = get_config().type_casts_by_function_by_atomic_op_idx[func_name];
|
||||
auto label_types = get_config().label_types[data.to_unique_name()];
|
||||
auto casts = try_lookup(config.type_casts_by_function_by_atomic_op_idx, func_name);
|
||||
auto label_types = try_lookup(config.label_types, data.to_unique_name());
|
||||
func.ir2.env.set_type_casts(casts);
|
||||
func.ir2.env.set_label_types(label_types);
|
||||
if (get_config().pair_functions_by_name.find(func_name) !=
|
||||
get_config().pair_functions_by_name.end()) {
|
||||
if (config.hacks.pair_functions_by_name.find(func_name) !=
|
||||
config.hacks.pair_functions_by_name.end()) {
|
||||
func.ir2.env.set_sloppy_pair_typing();
|
||||
}
|
||||
func.ir2.env.set_stack_var_hints(get_config().stack_var_hints_by_function[func_name]);
|
||||
func.ir2.env.set_stack_var_hints(try_lookup(config.stack_var_hints_by_function, func_name));
|
||||
if (run_type_analysis_ir2(ts, dts, func)) {
|
||||
successful_functions++;
|
||||
func.ir2.env.types_succeeded = true;
|
||||
@@ -436,7 +446,7 @@ void ObjectFileDB::ir2_store_current_forms() {
|
||||
lg::info("Stored debug forms for {} functions in {:.2f} ms\n", total, timer.getMs());
|
||||
}
|
||||
|
||||
void ObjectFileDB::ir2_build_expressions() {
|
||||
void ObjectFileDB::ir2_build_expressions(const Config& config) {
|
||||
Timer timer;
|
||||
int total = 0;
|
||||
int attempted = 0;
|
||||
@@ -449,13 +459,13 @@ void ObjectFileDB::ir2_build_expressions() {
|
||||
func.ir2.env.types_succeeded) {
|
||||
attempted++;
|
||||
auto name = func.guessed_name.to_string();
|
||||
auto arg_config = get_config().function_arg_names.find(name);
|
||||
auto var_config = get_config().function_var_overrides.find(name);
|
||||
auto arg_config = config.function_arg_names.find(name);
|
||||
auto var_config = config.function_var_overrides.find(name);
|
||||
if (convert_to_expressions(func.ir2.top_form, *func.ir2.form_pool, func,
|
||||
arg_config != get_config().function_arg_names.end()
|
||||
arg_config != config.function_arg_names.end()
|
||||
? arg_config->second
|
||||
: std::vector<std::string>{},
|
||||
var_config != get_config().function_var_overrides.end()
|
||||
var_config != config.function_var_overrides.end()
|
||||
? var_config->second
|
||||
: std::unordered_map<std::string, LocalVarOverride>{},
|
||||
dts)) {
|
||||
@@ -826,12 +836,11 @@ std::string ObjectFileDB::ir2_function_to_string(ObjectFileData& data, Function&
|
||||
*/
|
||||
bool ObjectFileDB::lookup_function_type(const FunctionName& name,
|
||||
const std::string& obj_name,
|
||||
const Config& config,
|
||||
TypeSpec* result) {
|
||||
auto& cfg = get_config();
|
||||
|
||||
// don't return function types that are explictly flagged as bad in config.
|
||||
if (cfg.no_type_analysis_functions_by_name.find(name.to_string()) !=
|
||||
cfg.no_type_analysis_functions_by_name.end()) {
|
||||
if (config.hacks.no_type_analysis_functions_by_name.find(name.to_string()) !=
|
||||
config.hacks.no_type_analysis_functions_by_name.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -867,7 +876,7 @@ bool ObjectFileDB::lookup_function_type(const FunctionName& name,
|
||||
return true;
|
||||
} else if (name.kind == FunctionName::FunctionKind::UNIDENTIFIED) {
|
||||
// try looking up the object
|
||||
const auto& map = get_config().anon_function_types_by_obj_by_id;
|
||||
const auto& map = config.anon_function_types_by_obj_by_id;
|
||||
auto obj_kv = map.find(obj_name);
|
||||
if (obj_kv != map.end()) {
|
||||
auto func_kv = obj_kv->second.find(name.get_anon_id());
|
||||
|
||||
Reference in New Issue
Block a user