2018-09-03 23:27:20 +00:00
|
|
|
/* Write by David fuqiang Fan <feqin1023@gmail.com>, member of HardenedLinux.
|
2018-09-25 10:03:06 +00:00
|
|
|
The code of this file try to make some optimizationsfor PaX RAP.
|
2018-09-18 20:25:11 +00:00
|
|
|
Supply the API for RAP.
|
2018-09-25 10:03:06 +00:00
|
|
|
|
2018-09-18 20:25:11 +00:00
|
|
|
And we also call function wich compute function type hash from PaX RAP.
|
2018-09-25 10:03:06 +00:00
|
|
|
Code architecture inspired by RAP of PaX Team <pageexec@freemail.hu>.
|
2018-09-18 20:25:11 +00:00
|
|
|
|
|
|
|
Licensed under the GPL v2. */
|
2018-08-19 20:10:13 +00:00
|
|
|
|
2018-09-03 04:53:58 +00:00
|
|
|
#include <stdio.h>
|
2018-09-04 15:46:48 +00:00
|
|
|
#include <string.h>
|
2018-09-04 12:23:56 +00:00
|
|
|
#include "rap.h"
|
2018-09-04 15:46:48 +00:00
|
|
|
#include "tree-pass.h"
|
2018-09-04 12:23:56 +00:00
|
|
|
//#include "../include/pointer-set.h"
|
|
|
|
|
2018-08-19 20:10:13 +00:00
|
|
|
/* 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. */
|
|
|
|
|
2018-09-04 12:23:56 +00:00
|
|
|
/* This data structure defined in gcc source. */
|
|
|
|
//extern struct simple_ipa_opt_pass pass_ipa_pta;
|
2018-08-19 20:10:13 +00:00
|
|
|
|
2018-09-02 13:56:47 +00:00
|
|
|
/* Contains the beed called optimization level of GCC */
|
|
|
|
int gcc_optimize_level = 0;
|
|
|
|
/* Count how many function we have optimized */
|
2018-09-04 12:23:56 +00:00
|
|
|
int rap_opt_statistics_data = 0;
|
2018-09-03 04:53:58 +00:00
|
|
|
/* Contain the statistics data, maybe gcc will called many times, we need output
|
|
|
|
data in the same file, for the conventices of scripts process. */
|
2018-09-04 12:23:56 +00:00
|
|
|
const char *dump_rap_opt_statistics_filename = "rap_opt_statistics_dump";
|
2018-09-03 04:53:58 +00:00
|
|
|
FILE *dump_rap_opt_statistics_fd;
|
|
|
|
// Hold all the ROP target functions.
|
2018-09-06 11:59:44 +00:00
|
|
|
static bitmap sensi_funcs;
|
2018-09-02 13:56:47 +00:00
|
|
|
/* Contains the type database which are pointer analysis can not sloved */
|
|
|
|
static struct pointer_set_t *pointer_types;
|
2018-09-06 11:59:44 +00:00
|
|
|
//
|
|
|
|
static bool will_call_ipa_pta;
|
2018-09-25 02:14:03 +00:00
|
|
|
/* For compatiable with the original RAP */
|
|
|
|
typedef rap_hash_t.hash rap_hash_value_type;
|
2018-09-06 11:59:44 +00:00
|
|
|
|
2018-09-16 15:47:13 +00:00
|
|
|
/* Test GCC will call some passes which is benefit. */
|
|
|
|
void
|
|
|
|
rap_check_will_call_passes (void* gcc_data, void* user_data)
|
|
|
|
{
|
|
|
|
//gcc_assert (current_pass);
|
|
|
|
if (current_pass
|
|
|
|
&&
|
|
|
|
(! strcmp (((struct opt_pass *)current_pass)->name, "inline")))
|
|
|
|
{
|
|
|
|
if (*(bool*)gcc_data)
|
2018-09-25 02:14:03 +00:00
|
|
|
fprintf(dump_rap_opt_statistics_fd, "[+] NOT call pass 'inline'\n");
|
2018-09-16 15:47:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2018-09-02 13:56:47 +00:00
|
|
|
|
|
|
|
/* 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)
|
2018-08-19 20:10:13 +00:00
|
|
|
{
|
|
|
|
/* Make sure we have reach */
|
2018-09-06 11:59:44 +00:00
|
|
|
bool will_call_ipa_pta = false;
|
2018-08-19 20:10:13 +00:00
|
|
|
|
|
|
|
//gcc_assert (current_pass);
|
2018-09-02 13:56:47 +00:00
|
|
|
if (current_pass
|
|
|
|
&&
|
2018-09-04 15:46:48 +00:00
|
|
|
(! strcmp (((struct opt_pass *)current_pass)->name, "pta")))
|
2018-09-02 13:56:47 +00:00
|
|
|
{
|
|
|
|
*(bool*)gcc_data = true;
|
|
|
|
/* The variable optimize is defined int GCC */
|
|
|
|
*(int*)user_data = optimize;
|
|
|
|
}
|
2018-09-06 11:59:44 +00:00
|
|
|
//gcc_assert (init);
|
2018-08-19 20:10:13 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-09-02 13:56:47 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2018-08-19 20:10:13 +00:00
|
|
|
|
2018-09-02 13:56:47 +00:00
|
|
|
/* 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;
|
2018-08-19 20:10:13 +00:00
|
|
|
}
|
|
|
|
|
2018-09-02 13:56:47 +00:00
|
|
|
/* 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);
|
2018-09-04 12:23:56 +00:00
|
|
|
if (pi)
|
2018-09-02 13:56:47 +00:00
|
|
|
{
|
|
|
|
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 ()
|
2018-08-19 20:10:13 +00:00
|
|
|
{
|
|
|
|
struct cgraph_node *node;
|
|
|
|
struct varpool_node *var;
|
2018-09-02 13:56:47 +00:00
|
|
|
tree t;
|
|
|
|
struct function *func;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
/* This optimization depend on GCC optimizations */
|
|
|
|
if (0 == gcc_optimize_level)
|
|
|
|
return;
|
2018-09-06 11:59:44 +00:00
|
|
|
//
|
|
|
|
gcc_assert (will_call_ipa_pta);
|
|
|
|
bitmap sensi_funcs = BITMAP_ALLOC (NULL);
|
2018-09-02 13:56:47 +00:00
|
|
|
|
2018-08-25 21:29:38 +00:00
|
|
|
/* Gather function pointer infos from global may available variable */
|
2018-08-19 20:10:13 +00:00
|
|
|
FOR_EACH_VARIABLE (var)
|
|
|
|
{
|
|
|
|
if (var->alias)
|
2018-09-02 13:56:47 +00:00
|
|
|
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);
|
2018-08-19 20:10:13 +00:00
|
|
|
}
|
|
|
|
/* Gather function pointer infos from every function */
|
|
|
|
FOR_EACH_DEFINED_FUNCTION (node)
|
|
|
|
{
|
2018-09-02 13:56:47 +00:00
|
|
|
t = NULL;
|
2018-08-19 20:10:13 +00:00
|
|
|
|
|
|
|
/* Nodes without a body are not interesting. */
|
|
|
|
if (!cgraph_function_with_gimple_body_p (node))
|
2018-09-02 13:56:47 +00:00
|
|
|
continue;
|
2018-08-19 20:10:13 +00:00
|
|
|
func = DECL_STRUCT_FUNCTION (node->symbol.decl);
|
2018-08-27 04:46:34 +00:00
|
|
|
//push_cfun (func);
|
2018-08-25 21:29:38 +00:00
|
|
|
/* 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. */
|
2018-09-04 12:23:56 +00:00
|
|
|
FOR_EACH_VEC_ELT (*func->gimple_df->ssa_names, i, t)
|
2018-08-27 04:46:34 +00:00
|
|
|
{
|
2018-09-02 13:56:47 +00:00
|
|
|
if (! (t || FUNCTION_POINTER_TYPE_P (t)))
|
|
|
|
continue;
|
|
|
|
rap_gather_function_targets_1 (t);
|
2018-08-25 21:29:38 +00:00
|
|
|
}
|
|
|
|
} // FOR_EACH_DEFINED_FUNCTION (node)
|
2018-09-02 13:56:47 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|
2018-08-19 20:10:13 +00:00
|
|
|
|
2018-08-25 21:29:38 +00:00
|
|
|
return;
|
|
|
|
} // end of rap_gather_function_targets
|
2018-08-19 20:10:13 +00:00
|
|
|
|
2018-09-02 13:56:47 +00:00
|
|
|
|
|
|
|
/* Basic test of function nature */
|
2018-08-19 20:10:13 +00:00
|
|
|
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)
|
2018-09-08 14:16:38 +00:00
|
|
|
/*|| TREE_ADDRESSABLE (f)*/ ));
|
2018-08-19 20:10:13 +00:00
|
|
|
}
|
|
|
|
|
2018-09-02 13:56:47 +00:00
|
|
|
/* Entry point of the oracle, look up current function weather or not beed
|
2018-09-03 23:15:27 +00:00
|
|
|
gathered into our target function set. If YES return 1 otherwise return 0 */
|
2018-08-25 21:29:38 +00:00
|
|
|
int
|
|
|
|
is_rap_function_maybe_roped (tree f)
|
2018-08-19 20:10:13 +00:00
|
|
|
{
|
2018-09-03 23:15:27 +00:00
|
|
|
if (! is_rap_function_may_be_aliased (f))
|
|
|
|
return 0;
|
|
|
|
/* Ask the oracle for help */
|
2018-09-02 13:56:47 +00:00
|
|
|
if (0 == gcc_optimize_level)
|
2018-09-03 23:15:27 +00:00
|
|
|
/* Function is_rap_function_may_be_aliased() must be failed we arive here,
|
|
|
|
but our oracle dependent the GCC optimizations. */
|
|
|
|
return 1;
|
2018-09-02 13:56:47 +00:00
|
|
|
else
|
2018-09-04 12:23:56 +00:00
|
|
|
return bitmap_bit_p (sensi_funcs, DECL_UID (f));
|
2018-08-19 20:10:13 +00:00
|
|
|
}
|
|
|
|
|
2018-09-03 04:53:58 +00:00
|
|
|
/* Write some statistics for our algorithm */
|
|
|
|
void
|
|
|
|
dump_rap_opt_statistics ()
|
|
|
|
{
|
|
|
|
dump_rap_opt_statistics_fd = fopen (dump_rap_opt_statistics_filename, "a");
|
2018-09-04 12:23:56 +00:00
|
|
|
fprintf (dump_rap_opt_statistics_fd, "%d\n", rap_opt_statistics_data);
|
2018-09-03 04:53:58 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-09-30 15:40:37 +00:00
|
|
|
/* Type definition for hash value maps. */
|
|
|
|
#define HL_CFI_MAP_CACHE_SIZE 3
|
|
|
|
struct cfi_function_hash_maps_t
|
|
|
|
{
|
|
|
|
struct pointer_map_t map;
|
|
|
|
// FIFO cache.
|
|
|
|
struct cfi_function_hash_pair_t
|
|
|
|
{
|
|
|
|
tree type;
|
|
|
|
rap_hash_value_type val;
|
|
|
|
} cfi_cache [HL_CFI_MAP_CACHE_SIZE];
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Constains the fucntion type and hash value maps. */
|
|
|
|
static struct pointer_map_t *cfi_function_hash_maps;
|
2018-09-25 10:03:06 +00:00
|
|
|
|
2018-09-26 22:10:51 +00:00
|
|
|
/* Search the [function type : hash value] table, if not have compatiable
|
|
|
|
type match, create one and insert into the table. */
|
|
|
|
static rap_hash_value_type
|
|
|
|
find_or_create_cfi_hash_val (tree type)
|
2018-09-25 10:03:06 +00:00
|
|
|
{
|
2018-09-30 15:40:37 +00:00
|
|
|
int i;
|
2018-09-26 22:10:51 +00:00
|
|
|
gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
|
2018-09-30 15:40:37 +00:00
|
|
|
//struct pointer_map_t *cfi_function_hash_maps;
|
|
|
|
if (! cfi_function_hash_maps.map)
|
|
|
|
cfi_function_hash_maps.map = pointer_map_create ();
|
|
|
|
|
|
|
|
/* Search */
|
|
|
|
for (i = 0; i < HL_CFI_MAP_CACHE_SIZE; i++)
|
|
|
|
if (types_compatible_p (type, cfi_function_hash_maps.cfi_cache[i].type))
|
|
|
|
return cfi_function_hash_maps.cfi_cache.val;
|
|
|
|
|
|
|
|
|
|
|
|
/* Update */
|
|
|
|
|
|
|
|
|
2018-09-26 22:10:51 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#define BUILD_SOURCE_HASH_TREE 1
|
|
|
|
#define BUILD_TARGET_HASH_TREE 2
|
|
|
|
|
|
|
|
/* Build cfi hash tree, target or source depend on the argument.
|
|
|
|
??? should we reuse the tree node. */
|
|
|
|
static tree
|
2018-09-27 15:39:28 +00:00
|
|
|
build_cfi_hash_tree (gimple cs, int direct)
|
2018-09-26 22:10:51 +00:00
|
|
|
{
|
|
|
|
//tree hash_tree, var;
|
|
|
|
rap_hash_value_type val;
|
2018-09-30 15:40:37 +00:00
|
|
|
tree decl, func_type;
|
2018-09-26 22:10:51 +00:00
|
|
|
|
2018-09-27 15:39:28 +00:00
|
|
|
gcc_assert(is_gimple_call (cs));
|
|
|
|
|
|
|
|
decl = gimple_call_fn (cs);
|
2018-09-30 15:40:37 +00:00
|
|
|
func_type = TREE_TYPE (TREE_TYPE (decl));
|
2018-09-27 15:39:28 +00:00
|
|
|
// safe guard
|
|
|
|
gcc_assert (TREE_CODE (decl) == SSA_NAME);
|
|
|
|
gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
|
2018-09-26 22:10:51 +00:00
|
|
|
|
|
|
|
// create source hash tree.
|
|
|
|
if (direct == BUILD_SOURCE_HASH_TREE)
|
|
|
|
{
|
|
|
|
val = find_or_create_cfi_hash_val (func_type);
|
|
|
|
return build_int_cst(integer_type_node, val);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-30 15:40:37 +00:00
|
|
|
tree target, off_type;
|
2018-09-26 22:10:51 +00:00
|
|
|
int target_offset;
|
|
|
|
|
|
|
|
gcc_assert (direct == BUILD_TARGET_HASH_TREE);
|
|
|
|
|
|
|
|
target = create_tmp_var (integer_type_node, "hl_target");
|
|
|
|
target = make_ssa_name (var, NULL);
|
|
|
|
|
|
|
|
/* This code fragment of compute target function hash offset comes
|
|
|
|
from Pax RAP. */
|
2018-09-28 02:11:58 +00:00
|
|
|
/* We need the forward offset. */
|
2018-09-26 22:10:51 +00:00
|
|
|
if (UNITS_PER_WORD == 8)
|
2018-09-28 02:11:58 +00:00
|
|
|
{
|
|
|
|
target_offset = - 2 * sizeof(rap_hash_value_type);
|
2018-09-30 15:40:37 +00:00
|
|
|
off_type = long_integer_type_node;
|
2018-09-28 02:11:58 +00:00
|
|
|
}
|
2018-09-26 22:10:51 +00:00
|
|
|
else if (UNITS_PER_WORD == 4)
|
2018-09-28 02:11:58 +00:00
|
|
|
{
|
|
|
|
target_offset = - sizeof(rap_hash_value_type);
|
2018-09-30 15:40:37 +00:00
|
|
|
off_type = integer_type_node;
|
2018-09-28 02:11:58 +00:00
|
|
|
}
|
2018-09-26 22:10:51 +00:00
|
|
|
else
|
|
|
|
gcc_unreachable();
|
|
|
|
|
2018-09-28 02:11:58 +00:00
|
|
|
/* Build the tree for : ((rap_hash_value_type *)target_function - 1)
|
|
|
|
This code is referenced from gcc source: gimplify_modify_expr_rhs() */
|
2018-09-26 22:10:51 +00:00
|
|
|
|
2018-09-28 02:11:58 +00:00
|
|
|
// integer_ptr_type_node
|
|
|
|
// func is the function pointer, ADDR_EXPR, pointer(function)
|
2018-09-30 15:40:37 +00:00
|
|
|
gcc_assert (FUNCTION_POINTER_TYPE_P ( TREE_TYPE (decl)));
|
|
|
|
// type is the result type of cast.
|
|
|
|
fold_build2 (MEM_REF, off_type, decl,
|
|
|
|
// This is a pointer type tree reprensent the offset.
|
2018-09-28 02:11:58 +00:00
|
|
|
build_int_cst_wide (integer_ptr_type_node,
|
|
|
|
TREE_INT_CST_LOW (target_offset),
|
|
|
|
TREE_INT_CST_HIGH (target_offset)));
|
2018-09-26 22:10:51 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-09-25 10:03:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-25 02:14:03 +00:00
|
|
|
/* Build the check statement:
|
|
|
|
if ((int *)(cs->target_function - sizeof(rap_hash_value_type)) != hash)
|
|
|
|
error () */
|
2018-09-26 22:10:51 +00:00
|
|
|
static void
|
|
|
|
build_fe_cfi (gimple_stmt_iterator *gp)
|
2018-09-25 02:14:03 +00:00
|
|
|
{
|
2018-09-25 10:03:06 +00:00
|
|
|
gimple cs;
|
2018-09-26 22:10:51 +00:00
|
|
|
tree target_hash; // hash get behind the function definitions.
|
|
|
|
tree source_hash; // hash get before indirect calls.
|
2018-09-25 10:03:06 +00:00
|
|
|
|
|
|
|
cs = gsi_stmt (*gp);
|
2018-09-26 22:10:51 +00:00
|
|
|
gcc_assert (is_gimple_call (cs));
|
2018-09-25 02:14:03 +00:00
|
|
|
decl = gimple_call_fn (cs);
|
|
|
|
/* We must be indirect call */
|
2018-09-25 10:03:06 +00:00
|
|
|
gcc_assert (TREE_CODE (decl) == SSA_NAME);
|
2018-09-27 15:39:28 +00:00
|
|
|
gcc_assert (TREE_TYPE (TREE_TYPE (decl)) == cs->gimple_call.u.fntype);
|
|
|
|
|
2018-09-26 22:10:51 +00:00
|
|
|
/* build source hash tree */
|
2018-09-27 15:39:28 +00:00
|
|
|
source_hash = build_cfi_hash_tree (cs, BUILD_SOURCE_HASH_TREE);
|
2018-09-26 22:10:51 +00:00
|
|
|
/* build target hash tree */
|
2018-09-27 15:39:28 +00:00
|
|
|
target_hash = build_cfi_hash_tree (cs, BUILD_TARGET_HASH_TREE);
|
2018-09-26 22:10:51 +00:00
|
|
|
|
|
|
|
/* Build the condition expression and insert into the code block, because
|
|
|
|
the conditional import new branch, so we also need update the blocks */
|
|
|
|
|
2018-09-25 02:14:03 +00:00
|
|
|
}
|
2018-09-18 20:25:11 +00:00
|
|
|
|
|
|
|
// types_compatible_p
|
|
|
|
/*
|
|
|
|
|
|
|
|
cgraph_local_node_p
|
|
|
|
|
|
|
|
types_compatible_p
|
|
|
|
flag_ltrans
|
|
|
|
flag_lto
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2018-09-21 14:17:22 +00:00
|
|
|
/* This new pass will be added after the GCC pass ipa "pta". */
|
2018-09-18 20:25:11 +00:00
|
|
|
static unsigned int
|
|
|
|
rap_fe_cfi_execute ()
|
|
|
|
{
|
|
|
|
struct cgraph_node *node;
|
2018-09-25 10:03:06 +00:00
|
|
|
//if (! flag_ltrans)
|
|
|
|
//gcc_assert(0);
|
|
|
|
//struct pointer_map_t *indirect_function_maps;
|
2018-09-18 20:25:11 +00:00
|
|
|
|
|
|
|
FOR_EACH_DEFINED_FUNCTION (node)
|
|
|
|
{
|
|
|
|
struct function *func;
|
|
|
|
basic_block bb;
|
|
|
|
|
|
|
|
/* Without body not our intent. */
|
|
|
|
if (!cgraph_function_with_gimple_body_p (node))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
func = DECL_STRUCT_FUNCTION (node->symbol.decl);
|
|
|
|
push_cfun (func);
|
|
|
|
|
|
|
|
FOR_EACH_BB_FN (bb, func)
|
|
|
|
{
|
|
|
|
gimple_stmt_iterator gsi;
|
|
|
|
|
|
|
|
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
|
|
|
{
|
2018-09-25 10:03:06 +00:00
|
|
|
//tree decl;
|
2018-09-25 02:14:03 +00:00
|
|
|
gimple cs;
|
2018-09-26 22:10:51 +00:00
|
|
|
//tree hash;
|
2018-09-25 02:14:03 +00:00
|
|
|
cs = gsi_stmt (gsi);
|
|
|
|
/* We are in forward cfi only cares about function call */
|
|
|
|
if (! is_gimple_call (cs))
|
|
|
|
continue;
|
2018-09-25 10:03:06 +00:00
|
|
|
/* Indirect calls */
|
|
|
|
if (NULL == gimple_call_fndecl (cs))
|
2018-09-25 02:14:03 +00:00
|
|
|
{
|
2018-09-25 10:03:06 +00:00
|
|
|
//decl = gimple_call_fn (cs);
|
2018-09-26 22:10:51 +00:00
|
|
|
//hash = find_cfi_hash_tree (decl);
|
|
|
|
//gcc_assert (hash);
|
|
|
|
build_fe_cfi (&gsi);
|
2018-09-25 02:14:03 +00:00
|
|
|
}
|
2018-09-18 20:25:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pop_cfun ();
|
|
|
|
}
|
2018-09-25 10:03:06 +00:00
|
|
|
//indirect_function_maps = pointer_map_create ();
|
|
|
|
//gimple_call_fndecl (const_gimple gs)
|
2018-09-18 20:25:11 +00:00
|
|
|
|
2018-09-25 10:03:06 +00:00
|
|
|
return 0;
|
2018-09-18 20:25:11 +00:00
|
|
|
}
|
|
|
|
|
2018-09-25 10:03:06 +00:00
|
|
|
/* Genetate the pass structure */
|
2018-09-18 20:25:11 +00:00
|
|
|
#define PASS_NAME rap_fe_cfi
|
2018-09-21 14:17:22 +00:00
|
|
|
//#define PROPERTIES_REQUIRED PROP_gimple_any
|
|
|
|
//#define PROPERTIES_PROVIDED PROP_gimple_lcf
|
|
|
|
#define TODO_FLAGS_FINISH TODO_update_ssa_any | TODO_verify_all | TODO_dump_func | \
|
|
|
|
TODO_remove_unused_locals | TODO_cleanup_cfg | TODO_rebuild_cgraph_edges
|
|
|
|
#include "gcc-generate-simple_ipa-pass.h"
|
2018-09-18 20:25:11 +00:00
|
|
|
|