diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 673a48b..e17c2fb 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(selfpatch-slr SHARED main.cpp attrib.cpp) +add_library(selfpatch-slr SHARED main.cpp attrib.cpp access_discover.cpp) set_target_properties(selfpatch-slr PROPERTIES PREFIX "") target_compile_definitions(selfpatch-slr PRIVATE _GNU_SOURCE) diff --git a/plugin/access_discover.cpp b/plugin/access_discover.cpp new file mode 100644 index 0000000..1ab3d7b --- /dev/null +++ b/plugin/access_discover.cpp @@ -0,0 +1,83 @@ +#include "access_discover.h" + +#include + +static void print_gimple_tree(tree t, int depth, int indent = 2) { + if (!t) + return; + + for (int i = 0; i < depth; ++i) + std::cout << " "; + + std::cout << get_tree_code_name(TREE_CODE(t)); + + if (TREE_CODE(t) == FIELD_DECL && DECL_NAME(t)) + std::cout << " <" << IDENTIFIER_POINTER(DECL_NAME(t)) << ">"; + else if (TREE_CODE(t) == SSA_NAME && SSA_NAME_VAR(t) && DECL_NAME(SSA_NAME_VAR(t))) + std::cout << " "; + + std::cout << std::endl; + + for (int i = 0; i < TREE_CODE_LENGTH(TREE_CODE(t)); ++i) + print_gimple_tree(TREE_OPERAND(t, i), depth + indent, indent); +} + +static void print_gimple_statement(gimple* stmt) { + if (!stmt) + return; + + print_gimple_stmt(stdout, stmt, 0, TDF_NONE); + + for (unsigned i = 0; i < gimple_num_ops(stmt); ++i) { + tree operand = gimple_op(stmt, i); + print_gimple_tree(operand, 2, 2); + } +} + +static int scan_gimple_statement(const char* funcname, gimple_stmt_iterator* gsi) { + /* + gimple *stmt = gsi_stmt(gsi); + scan_stmt_for_offsetof(funcname, &gsi); + for (unsigned i = 0; i < gimple_num_ops(stmt); ++i) { + tree op = gimple_op(stmt, i); + scan_tree_for_components(op, funcname, &gsi); + } + + Build map: location->LocationPattern + */ + print_gimple_statement(gsi_stmt(*gsi)); + return 0; +} + +static void clean_unnecessary_locations() { + // Remove all LocationPatterns that do no do any relevant struct accesses +} + +static const pass_data access_discover_pass_data = { + GIMPLE_PASS, + "access_discover", + OPTGROUP_NONE, + TV_NONE, + 0,0,0,0, + TODO_update_ssa | TODO_cleanup_cfg | TODO_verify_il +}; + +access_discover_pass::access_discover_pass(gcc::context *ctxt) : gimple_opt_pass(access_discover_pass_data, ctxt) {} + +unsigned int access_discover_pass::execute(function* fun) { + const char* funcname = fun->decl && DECL_NAME(fun->decl) + ? IDENTIFIER_POINTER(DECL_NAME(fun->decl)) + : ""; + + basic_block bb; + FOR_EACH_BB_FN(bb, fun) { + for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) { + int stmt_scan_success; + if ((stmt_scan_success = scan_gimple_statement(funcname, &gsi)) != 0) + return stmt_scan_success; + } + } + + clean_unnecessary_locations(); + return 0; +} diff --git a/plugin/access_discover.h b/plugin/access_discover.h new file mode 100644 index 0000000..22a14b9 --- /dev/null +++ b/plugin/access_discover.h @@ -0,0 +1,11 @@ +#pragma once +#include "gcc_includes.h" + +struct access_discover_pass : gimple_opt_pass { + access_discover_pass(gcc::context *ctxt); + unsigned int execute(function* fun) override; +}; + +#define ACCESS_DISCOVER_PASS_REFPASS "optimized" +#define ACCESS_DISCOVER_PASS_POSOP PASS_POS_INSERT_AFTER + diff --git a/plugin/attrib.cpp b/plugin/attrib.cpp index c9dd8b5..e518eaf 100644 --- a/plugin/attrib.cpp +++ b/plugin/attrib.cpp @@ -1,7 +1,6 @@ #include "attrib.h" -#include -#include +#include "gcc_includes.h" #include #include diff --git a/plugin/gcc_includes.h b/plugin/gcc_includes.h new file mode 100644 index 0000000..dd1b862 --- /dev/null +++ b/plugin/gcc_includes.h @@ -0,0 +1,23 @@ +#ifndef GCC_PLUGIN_INCLUDES_H +#define GCC_PLUGIN_INCLUDES_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/plugin/main.cpp b/plugin/main.cpp index 8d5b72f..36f3dae 100644 --- a/plugin/main.cpp +++ b/plugin/main.cpp @@ -1,8 +1,8 @@ #include -#include -#include +#include "gcc_includes.h" #include "attrib.h" +#include "access_discover.h" int plugin_is_GPL_compatible; @@ -14,5 +14,12 @@ int plugin_init(plugin_name_args *plugin_info, plugin_gcc_version *version) { register_callback(plugin_info->base_name, PLUGIN_ATTRIBUTES, register_attributes, NULL); + struct register_pass_info access_discover_pass_info; + access_discover_pass_info.pass = new access_discover_pass(nullptr); + access_discover_pass_info.ref_pass_instance_number = 1; + access_discover_pass_info.reference_pass_name = ACCESS_DISCOVER_PASS_REFPASS; + access_discover_pass_info.pos_op = ACCESS_DISCOVER_PASS_POSOP; + register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, nullptr, &access_discover_pass_info); + return 0; } diff --git a/subject/offsetof_passthrough.h b/subject/offsetof_passthrough.h index a3be078..88ba956 100644 --- a/subject/offsetof_passthrough.h +++ b/subject/offsetof_passthrough.h @@ -10,9 +10,12 @@ static size_t __spslr_offsetof(const char *t, const char *m, size_t v) { return v; } -/* Replace __builtin_offsetof with encoding of type and member that survives C frontend */ +/* +Replace __builtin_offsetof with encoding of type and member that survives C frontend +Macro recursion prevention leaves the inner __builtin_offsetof there, otherwise use "(((size_t)&((T*)0)->M))" +*/ #undef __builtin_offsetof #define __builtin_offsetof(T,M) \ - ((size_t (*)(const char*, const char*, size_t))__spslr_offsetof)((#T), (#M), (((size_t)&((T*)0)->M))) + ((size_t (*)(const char*, const char*, size_t))__spslr_offsetof)((#T), (#M), __builtin_offsetof(T,M)) #endif