881 lines · 22.9 KB · C
RawDownload
		return; 	DECL_SIZE(decl) = 0;	DECL_SIZE_UNIT(decl) = 0;	SET_DECL_ALIGN(decl, 0);	SET_DECL_MODE (decl, VOIDmode);	SET_DECL_RTL(decl, 0);	update_decl_size(decl);	layout_decl(decl, 0);} static void finish_type(void *event_data, void *data){	tree type = (tree)event_data; 	if (type == NULL_TREE || type == error_mark_node)		return; 	if (TREE_CODE(type) != RECORD_TYPE)		return; 	if (TYPE_FIELDS(type) == NULL_TREE)		return; 	if (lookup_attribute("randomize_considered", TYPE_ATTRIBUTES(type)))		return; #ifdef __DEBUG_PLUGIN	fprintf(stderr, "Calling randomize_type on %s\n", ORIG_TYPE_NAME(type));#endif#ifdef __DEBUG_VERBOSE	debug_tree(type);#endif	randomize_type(type); 	return;} static struct attribute_spec randomize_layout_attr = { };static struct attribute_spec no_randomize_layout_attr = { };static struct attribute_spec randomize_considered_attr = { };static struct attribute_spec randomize_performed_attr = { }; static void register_attributes(void *event_data, void *data){	randomize_layout_attr.name		= "randomize_layout";	randomize_layout_attr.type_required	= true;	randomize_layout_attr.handler		= handle_randomize_layout_attr;	randomize_layout_attr.affects_type_identity = true; 	no_randomize_layout_attr.name		= "no_randomize_layout";	no_randomize_layout_attr.type_required	= true;	no_randomize_layout_attr.handler	= handle_randomize_layout_attr;	no_randomize_layout_attr.affects_type_identity = true; 	randomize_considered_attr.name		= "randomize_considered";	randomize_considered_attr.type_required	= true;	randomize_considered_attr.handler	= handle_randomize_considered_attr; 	randomize_performed_attr.name		= "randomize_performed";	randomize_performed_attr.type_required	= true;	randomize_performed_attr.handler	= handle_randomize_performed_attr; 	register_attribute(&randomize_layout_attr);	register_attribute(&no_randomize_layout_attr);	register_attribute(&randomize_considered_attr);	register_attribute(&randomize_performed_attr);} static void check_bad_casts_in_constructor(tree var, tree init){	unsigned HOST_WIDE_INT idx;	tree field, val;	tree field_type, val_type; 	FOR_EACH_CONSTRUCTOR_ELT(CONSTRUCTOR_ELTS(init), idx, field, val) {		if (TREE_CODE(val) == CONSTRUCTOR) {			check_bad_casts_in_constructor(var, val);			continue;		} 		/* pipacs' plugin creates franken-arrays that differ from those produced by		   normal code which all have valid 'field' trees. work around this */		if (field == NULL_TREE)			continue;		field_type = TREE_TYPE(field);		val_type = TREE_TYPE(val); 		if (TREE_CODE(field_type) != POINTER_TYPE || TREE_CODE(val_type) != POINTER_TYPE)			continue; 		if (field_type == val_type)			continue; 		field_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(field_type))));		val_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(val_type)))); 		if (field_type == void_type_node)			continue;		if (field_type == val_type)			continue;		if (TREE_CODE(val_type) != RECORD_TYPE)			continue; 		if (!lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(val_type)))			continue;		MISMATCH(DECL_SOURCE_LOCATION(var), "constructor\n", TYPE_MAIN_VARIANT(field_type), TYPE_MAIN_VARIANT(val_type));	}} /* derived from the constify plugin */static void check_global_variables(void *event_data, void *data){	struct varpool_node *node;	tree init; 	FOR_EACH_VARIABLE(node) {		tree var = NODE_DECL(node);		init = DECL_INITIAL(var);		if (init == NULL_TREE)			continue; 		if (TREE_CODE(init) != CONSTRUCTOR)			continue; 		check_bad_casts_in_constructor(var, init);	}} static bool dominated_by_is_err(const_tree rhs, basic_block bb){	basic_block dom;	gimple dom_stmt;	gimple call_stmt;	const_tree dom_lhs;	const_tree poss_is_err_cond;	const_tree poss_is_err_func;	const_tree is_err_arg; 	dom = get_immediate_dominator(CDI_DOMINATORS, bb);	if (!dom)		return false; 	dom_stmt = last_stmt(dom);	if (!dom_stmt)		return false; 	if (gimple_code(dom_stmt) != GIMPLE_COND)		return false; 	if (gimple_cond_code(dom_stmt) != NE_EXPR)		return false; 	if (!integer_zerop(gimple_cond_rhs(dom_stmt)))		return false; 	poss_is_err_cond = gimple_cond_lhs(dom_stmt); 	if (TREE_CODE(poss_is_err_cond) != SSA_NAME)		return false; 	call_stmt = SSA_NAME_DEF_STMT(poss_is_err_cond); 	if (gimple_code(call_stmt) != GIMPLE_CALL)		return false; 	dom_lhs = gimple_get_lhs(call_stmt);	poss_is_err_func = gimple_call_fndecl(call_stmt);	if (!poss_is_err_func)		return false;	if (dom_lhs != poss_is_err_cond)		return false;	if (strcmp(DECL_NAME_POINTER(poss_is_err_func), "IS_ERR"))		return false; 	is_err_arg = gimple_call_arg(call_stmt, 0);	if (!is_err_arg)		return false; 	if (is_err_arg != rhs)		return false; 	return true;} static void handle_local_var_initializers(void){	tree var;	unsigned int i; 	FOR_EACH_LOCAL_DECL(cfun, i, var) {		tree init = DECL_INITIAL(var);		if (!init)			continue;		if (TREE_CODE(init) != CONSTRUCTOR)			continue;		check_bad_casts_in_constructor(var, init);	}} /* * iterate over all statements to find "bad" casts: * those where the address of the start of a structure is cast * to a pointer of a structure of a different type, or a * structure pointer type is cast to a different structure pointer type */static unsigned int find_bad_casts_execute(void){	basic_block bb; 	handle_local_var_initializers(); 	FOR_EACH_BB_FN(bb, cfun) {		gimple_stmt_iterator gsi; 		for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {			gimple stmt;			const_tree lhs;			const_tree lhs_type;			const_tree rhs1;			const_tree rhs_type;			const_tree ptr_lhs_type;			const_tree ptr_rhs_type;			const_tree op0;			const_tree op0_type;			enum tree_code rhs_code; 			stmt = gsi_stmt(gsi); #ifdef __DEBUG_PLUGIN#ifdef __DEBUG_VERBOSE			debug_gimple_stmt(stmt);			debug_tree(gimple_get_lhs(stmt));#endif#endif 			if (gimple_code(stmt) != GIMPLE_ASSIGN)				continue; #ifdef __DEBUG_PLUGIN#ifdef __DEBUG_VERBOSE			debug_tree(gimple_assign_rhs1(stmt));#endif#endif  			rhs_code = gimple_assign_rhs_code(stmt); 			if (rhs_code != ADDR_EXPR && rhs_code != SSA_NAME)				continue; 			lhs = gimple_get_lhs(stmt);			lhs_type = TREE_TYPE(lhs);			rhs1 = gimple_assign_rhs1(stmt);			rhs_type = TREE_TYPE(rhs1); 			if (TREE_CODE(rhs_type) != POINTER_TYPE ||			    TREE_CODE(lhs_type) != POINTER_TYPE)				continue; 			ptr_lhs_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(lhs_type))));			ptr_rhs_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(rhs_type)))); 			if (ptr_rhs_type == void_type_node)				continue; 			if (ptr_lhs_type == void_type_node)				continue; 			if (dominated_by_is_err(rhs1, bb))				continue; 			if (TREE_CODE(ptr_rhs_type) != RECORD_TYPE) {#ifndef __DEBUG_PLUGIN				if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(ptr_lhs_type)))#endif				MISMATCH(gimple_location(stmt), "rhs", ptr_lhs_type, ptr_rhs_type);				continue;			} 			if (rhs_code == SSA_NAME && ptr_lhs_type == ptr_rhs_type)				continue; 			if (rhs_code == ADDR_EXPR) {				op0 = TREE_OPERAND(rhs1, 0); 				if (op0 == NULL_TREE)					continue; 				if (TREE_CODE(op0) != VAR_DECL)					continue; 				op0_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(op0))));				if (op0_type == ptr_lhs_type)					continue; #ifndef __DEBUG_PLUGIN				if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(op0_type)))#endif				MISMATCH(gimple_location(stmt), "op0", ptr_lhs_type, op0_type);			} else {				const_tree ssa_name_var = SSA_NAME_VAR(rhs1);				/* skip bogus type casts introduced by container_of */				if (ssa_name_var != NULL_TREE && DECL_NAME(ssa_name_var) && 				    !strcmp((const char *)DECL_NAME_POINTER(ssa_name_var), "__mptr"))					continue;#ifndef __DEBUG_PLUGIN				if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(ptr_rhs_type)))#endif				MISMATCH(gimple_location(stmt), "ssa", ptr_lhs_type, ptr_rhs_type);			} 		}	}	return 0;} #define PASS_NAME find_bad_casts#define NO_GATE#define TODO_FLAGS_FINISH TODO_dump_func#include "gcc-generate-gimple-pass.h" __visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version){	int i;	const char * const plugin_name = plugin_info->base_name;	const int argc = plugin_info->argc;	const struct plugin_argument * const argv = plugin_info->argv;	bool enable = true;	int obtained_seed = 0;	struct register_pass_info find_bad_casts_pass_info; 	find_bad_casts_pass_info.pass			= make_find_bad_casts_pass();	find_bad_casts_pass_info.reference_pass_name	= "ssa";	find_bad_casts_pass_info.ref_pass_instance_number	= 1;	find_bad_casts_pass_info.pos_op			= PASS_POS_INSERT_AFTER; 	if (!plugin_default_version_check(version, &gcc_version)) {		error(G_("incompatible gcc/plugin versions"));		return 1;	} 	if (strncmp(lang_hooks.name, "GNU C", 5) && !strncmp(lang_hooks.name, "GNU C+", 6)) {		inform(UNKNOWN_LOCATION, G_("%s supports C only, not %s"), plugin_name, lang_hooks.name);		enable = false;	} 	for (i = 0; i < argc; ++i) {		if (!strcmp(argv[i].key, "disable")) {			enable = false;			continue;		}		if (!strcmp(argv[i].key, "performance-mode")) {			performance_mode = 1;			continue;		}		error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);	} 	if (strlen(randstruct_seed) != 64) {		error(G_("invalid seed value supplied for %s plugin"), plugin_name);		return 1;	}	obtained_seed = sscanf(randstruct_seed, "%016llx%016llx%016llx%016llx",		&shuffle_seed[0], &shuffle_seed[1], &shuffle_seed[2], &shuffle_seed[3]);	if (obtained_seed != 4) {		error(G_("Invalid seed supplied for %s plugin"), plugin_name);		return 1;	} 	register_callback(plugin_name, PLUGIN_INFO, NULL, &randomize_layout_plugin_info);	if (enable) {		register_callback(plugin_name, PLUGIN_ALL_IPA_PASSES_START, check_global_variables, NULL);		register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &find_bad_casts_pass_info);		register_callback(plugin_name, PLUGIN_FINISH_TYPE, finish_type, NULL);		register_callback(plugin_name, PLUGIN_FINISH_DECL, randomize_layout_finish_decl, NULL);	}	register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL); 	return 0;}

Lines 501–881 of 881. Previous lines