/* The impelmentation code of optimization pass for RAP. Supply the API for RAP */ #include "../gcc-common.h" #include /* There are many optimization methrod can do for RAP. From simple to complex and aside with the gcc internal work stage. Maybe the most efficent methrod is add gcc intenal library and require to merge. Because of the lack of analysis for function pointer. Wrok with gcc plugin we have more isolate and also indepened with gcc version methrod, but need more replicate data 1, If a function pointer variable has not external linkage and live at code generation, it's legal function set must be only just the current file scope avail function and the proper type. 2, Global alias anylysis for the avail function set. */ /* Contains the beed called optimization level of GCC */ int gcc_optimize_level = 0; /* Count how many function we have optimized */ int rap_opt_statistics = 0; /* Contain the statistics data, maybe gcc will called many times, we need output data in the same file, for the conventices of scripts process. */ char *dump_rap_opt_statistics_filename = "rap_opt_statistics"; FILE *dump_rap_opt_statistics_fd; // Hold all the ROP target functions. static bitmap sensi_funcs = BITMAP_ALLOC (NULL); /* Contains the type database which are pointer analysis can not sloved */ static struct pointer_set_t *pointer_types; /* Try make GCC call ipa-pta pass if optimization level is NOT 0 */ void rap_try_call_ipa_pta (void* gcc_data, void* user_data) { /* Make sure we have reach */ bool init = false; //gcc_assert (current_pass); if (current_pass && ((void*)current_pass == (void*)&pass_ipa_pta)) { *(bool*)gcc_data = true; init = true; /* The variable optimize is defined int GCC */ *(int*)user_data = optimize; } gcc_assert (init); return; } /* Tools for type database operates */ static void insert_type_db (tree t) { tree ty = TREE_TYPE (t); if (! pointer_types) pointer_types = pointer_set_create (); gcc_assert (FUNCTION_POINTER_TYPE_P (t)); pointer_set_insert (pointer_types, (const void *)ty); return; } /* If after alias analysis some function pointer may be point anything, we have to make the conservation solution, contain and cache the the point to type, when emit RAP guard code, make sure all the functions of the compatible type NOT igonred and optimized Return value is trivial */ static bool rap_base_type_db_fliter (const void *db_type, void *fn) { tree f = (tree) fn; gcc_assert (TREE_CODE (f) == FUNCTION_DECL); if (types_compatible_p ((tree)db_type, TREE_TYPE(f))) if (bitmap_clear_bit (sensi_funcs, DECL_UID(f))) return true; return true; } /* The real worker */ static void rap_gather_function_targets_1 (tree t) { //types_compatible_p() //TREE_TYPE() //FUNCTION_POINTER_TYPE_P() struct ptr_info_def *pi; bitmap set; pi = SSA_NAME_PTR_INFO (t); if (pi && pi->pt) { if (pi->pt.anything) /* we are in trouble, pointer analysis can not give any answer about this pointer point to */ insert_type_db (t); } else { set = pi->pt.vars; if (! bitmap_empty_p (set)) bitmap_ior_into (sensi_funcs, set); } return; } /* Entry point of build the oracle, gather what functions never may be indirected called */ void rap_gather_function_targets () { struct cgraph_node *node; struct varpool_node *var; tree t; struct function *func; unsigned int i; /* This optimization depend on GCC optimizations */ if (0 == gcc_optimize_level) return; /* Gather function pointer infos from global may available variable */ FOR_EACH_VARIABLE (var) { if (var->alias) continue; gcc_assert (t = var->symbol.decl); /* We only care about function pointer variables */ if (! FUNCTION_POINTER_TYPE_P (t)) continue; rap_gather_function_targets_1 (t); } /* Gather function pointer infos from every function */ FOR_EACH_DEFINED_FUNCTION (node) { t = NULL; /* Nodes without a body are not interesting. */ if (!cgraph_function_with_gimple_body_p (node)) continue; func = DECL_STRUCT_FUNCTION (node->symbol.decl); //push_cfun (func); /* Function pointers will be SSA_NAME contained in current function, When gcc after pointer analysis we gather all the functions may be pointed by some function pointer and we ignore which function pointer can access it. All this gathered function are the sensitive data, need RAP add guard instruction. */ FOR_EACH_VEC_ELT (func->gimple_df->ssa_names, i, t) { if (! (t || FUNCTION_POINTER_TYPE_P (t))) continue; rap_gather_function_targets_1 (t); } } // FOR_EACH_DEFINED_FUNCTION (node) /* We have see all of the data about alias and build the type database, It's time for the final fliter */ if (! pointer_types) return; /* fial fliter */ FOR_EACH_DEFINED_FUNCTION (node) { t = NULL; /* Nodes without a body are not interesting. */ if (!cgraph_function_with_gimple_body_p (node)) continue; func = DECL_STRUCT_FUNCTION (node->symbol.decl); pointer_set_traverse (pointer_types, rap_base_type_db_fliter, func); } return; } // end of rap_gather_function_targets /* Basic test of function nature */ static inline bool is_rap_function_may_be_aliased (tree f) { return (TREE_CODE (f) != CONST_DECL && !((TREE_STATIC (f) || TREE_PUBLIC (f) || DECL_EXTERNAL (f)) && TREE_READONLY (f) && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (f))) && (TREE_PUBLIC (f) || DECL_EXTERNAL (f) || TREE_ADDRESSABLE (f))); } /* Entry point of the oracle, look up current function weather or not beed gathered into our target function set. If NOT return 1 otherwise return 0 */ int is_rap_function_maybe_roped (tree f) { if (0 == gcc_optimize_level) return ! is_rap_function_may_be_aliased (f); else return ! bitmap_bit_p (DECL_UID (f)) } /* Write some statistics for our algorithm */ void dump_rap_opt_statistics () { dump_rap_opt_statistics_fd = fopen (dump_rap_opt_statistics_filename, "a"); fprintf (dump_rap_opt_statistics_fd, "%d\n", rap_opt_statistics); return; } /* Clean and cloese function for optimizations */ void rap_optimization_clean () { /* Now we have finish our job, close file and destroy the GCC allocated data*/ fclose (dump_rap_opt_statistics_fd); bitmap_clear (sensi_funcs); pointer_set_destroy (pointer_types); return; }