summaryrefslogtreecommitdiff
path: root/scripts/gcc-plugins
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/gcc-plugins')
-rw-r--r--scripts/gcc-plugins/Kconfig14
-rw-r--r--scripts/gcc-plugins/Makefile4
-rw-r--r--scripts/gcc-plugins/arm_ssp_per_task_plugin.c107
-rw-r--r--scripts/gcc-plugins/gcc-common.h45
-rw-r--r--scripts/gcc-plugins/randomize_layout_plugin.c18
-rw-r--r--scripts/gcc-plugins/sancov_plugin.c134
-rw-r--r--scripts/gcc-plugins/structleak_plugin.c257
7 files changed, 5 insertions, 574 deletions
diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig
index e383cda05367..6b34ba19358d 100644
--- a/scripts/gcc-plugins/Kconfig
+++ b/scripts/gcc-plugins/Kconfig
@@ -19,16 +19,6 @@ menuconfig GCC_PLUGINS
if GCC_PLUGINS
-config GCC_PLUGIN_SANCOV
- bool
- # Plugin can be removed once the kernel only supports GCC 6+
- depends on !CC_HAS_SANCOV_TRACE_PC
- help
- This plugin inserts a __sanitizer_cov_trace_pc() call at the start of
- basic blocks. It supports all gcc versions with plugin support (from
- gcc-4.5 on). It is based on the commit "Add fuzzing coverage support"
- by Dmitry Vyukov <dvyukov@google.com>.
-
config GCC_PLUGIN_LATENT_ENTROPY
bool "Generate some entropy during boot and runtime"
help
@@ -46,8 +36,4 @@ config GCC_PLUGIN_LATENT_ENTROPY
* https://grsecurity.net/
* https://pax.grsecurity.net/
-config GCC_PLUGIN_ARM_SSP_PER_TASK
- bool
- depends on GCC_PLUGINS && ARM
-
endif
diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile
index 320afd3cf8e8..05b14aba41ef 100644
--- a/scripts/gcc-plugins/Makefile
+++ b/scripts/gcc-plugins/Makefile
@@ -66,3 +66,7 @@ quiet_cmd_plugin_cxx_o_c = HOSTCXX $@
$(plugin-objs): $(obj)/%.o: $(src)/%.c FORCE
$(call if_changed_dep,plugin_cxx_o_c)
+
+$(obj)/../../include/generated/gcc-plugins.h: $(plugin-single) $(plugin-multi) FORCE
+ $(call if_changed,touch)
+always-y += ../../include/generated/gcc-plugins.h
diff --git a/scripts/gcc-plugins/arm_ssp_per_task_plugin.c b/scripts/gcc-plugins/arm_ssp_per_task_plugin.c
deleted file mode 100644
index 7328d037f975..000000000000
--- a/scripts/gcc-plugins/arm_ssp_per_task_plugin.c
+++ /dev/null
@@ -1,107 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include "gcc-common.h"
-
-__visible int plugin_is_GPL_compatible;
-
-static unsigned int canary_offset;
-
-static unsigned int arm_pertask_ssp_rtl_execute(void)
-{
- rtx_insn *insn;
-
- for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) {
- const char *sym;
- rtx body;
- rtx current;
-
- /*
- * Find a SET insn involving a SYMBOL_REF to __stack_chk_guard
- */
- if (!INSN_P(insn))
- continue;
- body = PATTERN(insn);
- if (GET_CODE(body) != SET ||
- GET_CODE(SET_SRC(body)) != SYMBOL_REF)
- continue;
- sym = XSTR(SET_SRC(body), 0);
- if (strcmp(sym, "__stack_chk_guard"))
- continue;
-
- /*
- * Replace the source of the SET insn with an expression that
- * produces the address of the current task's stack canary value
- */
- current = gen_reg_rtx(Pmode);
-
- emit_insn_before(gen_load_tp_hard(current), insn);
-
- SET_SRC(body) = gen_rtx_PLUS(Pmode, current,
- GEN_INT(canary_offset));
- }
- return 0;
-}
-
-#define PASS_NAME arm_pertask_ssp_rtl
-
-#define NO_GATE
-#include "gcc-generate-rtl-pass.h"
-
-#if BUILDING_GCC_VERSION >= 9000
-static bool no(void)
-{
- return false;
-}
-
-static void arm_pertask_ssp_start_unit(void *gcc_data, void *user_data)
-{
- targetm.have_stack_protect_combined_set = no;
- targetm.have_stack_protect_combined_test = no;
-}
-#endif
-
-__visible int plugin_init(struct plugin_name_args *plugin_info,
- struct plugin_gcc_version *version)
-{
- const char * const plugin_name = plugin_info->base_name;
- const int argc = plugin_info->argc;
- const struct plugin_argument *argv = plugin_info->argv;
- int i;
-
- if (!plugin_default_version_check(version, &gcc_version)) {
- error(G_("incompatible gcc/plugin versions"));
- return 1;
- }
-
- for (i = 0; i < argc; ++i) {
- if (!strcmp(argv[i].key, "disable"))
- return 0;
-
- /* all remaining options require a value */
- if (!argv[i].value) {
- error(G_("no value supplied for option '-fplugin-arg-%s-%s'"),
- plugin_name, argv[i].key);
- return 1;
- }
-
- if (!strcmp(argv[i].key, "offset")) {
- canary_offset = atoi(argv[i].value);
- continue;
- }
- error(G_("unknown option '-fplugin-arg-%s-%s'"),
- plugin_name, argv[i].key);
- return 1;
- }
-
- PASS_INFO(arm_pertask_ssp_rtl, "expand", 1, PASS_POS_INSERT_AFTER);
-
- register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP,
- NULL, &arm_pertask_ssp_rtl_pass_info);
-
-#if BUILDING_GCC_VERSION >= 9000
- register_callback(plugin_info->base_name, PLUGIN_START_UNIT,
- arm_pertask_ssp_start_unit, NULL);
-#endif
-
- return 0;
-}
diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
index 3222c1070444..3fdaf1c4b258 100644
--- a/scripts/gcc-plugins/gcc-common.h
+++ b/scripts/gcc-plugins/gcc-common.h
@@ -3,11 +3,7 @@
#define GCC_COMMON_H_INCLUDED
#include "bversion.h"
-#if BUILDING_GCC_VERSION >= 6000
#include "gcc-plugin.h"
-#else
-#include "plugin.h"
-#endif
#include "plugin-version.h"
#include "config.h"
#include "system.h"
@@ -39,9 +35,7 @@
#include "hash-map.h"
-#if BUILDING_GCC_VERSION >= 7000
#include "memmodel.h"
-#endif
#include "emit-rtl.h"
#include "debug.h"
#include "target.h"
@@ -74,9 +68,7 @@
#include "context.h"
#include "tree-ssa-alias.h"
#include "tree-ssa.h"
-#if BUILDING_GCC_VERSION >= 7000
#include "tree-vrp.h"
-#endif
#include "tree-ssanames.h"
#include "print-tree.h"
#include "tree-eh.h"
@@ -149,16 +141,6 @@ static inline opt_pass *get_pass_for_id(int id)
return g->get_passes()->get_pass_for_id(id);
}
-#if BUILDING_GCC_VERSION < 6000
-/* gimple related */
-template <>
-template <>
-inline bool is_a_helper<const gassign *>::test(const_gimple gs)
-{
- return gs->code == GIMPLE_ASSIGN;
-}
-#endif
-
#define TODO_verify_ssa TODO_verify_il
#define TODO_verify_flow TODO_verify_il
#define TODO_verify_stmts TODO_verify_il
@@ -181,7 +163,6 @@ static inline const char *get_decl_section_name(const_tree decl)
#define varpool_get_node(decl) varpool_node::get(decl)
#define dump_varpool_node(file, node) (node)->dump(file)
-#if BUILDING_GCC_VERSION >= 8000
#define cgraph_create_edge(caller, callee, call_stmt, count, freq) \
(caller)->create_edge((callee), (call_stmt), (count))
@@ -189,15 +170,6 @@ static inline const char *get_decl_section_name(const_tree decl)
old_call_stmt, call_stmt, count, freq, reason) \
(caller)->create_edge_including_clones((callee), \
(old_call_stmt), (call_stmt), (count), (reason))
-#else
-#define cgraph_create_edge(caller, callee, call_stmt, count, freq) \
- (caller)->create_edge((callee), (call_stmt), (count), (freq))
-
-#define cgraph_create_edge_including_clones(caller, callee, \
- old_call_stmt, call_stmt, count, freq, reason) \
- (caller)->create_edge_including_clones((callee), \
- (old_call_stmt), (call_stmt), (count), (freq), (reason))
-#endif
typedef struct cgraph_node *cgraph_node_ptr;
typedef struct cgraph_edge *cgraph_edge_p;
@@ -293,14 +265,12 @@ static inline void cgraph_call_edge_duplication_hooks(cgraph_edge *cs1, cgraph_e
symtab->call_edge_duplication_hooks(cs1, cs2);
}
-#if BUILDING_GCC_VERSION >= 6000
typedef gimple *gimple_ptr;
typedef const gimple *const_gimple_ptr;
#define gimple gimple_ptr
#define const_gimple const_gimple_ptr
#undef CONST_CAST_GIMPLE
#define CONST_CAST_GIMPLE(X) CONST_CAST(gimple, (X))
-#endif
/* gimple related */
static inline gimple gimple_build_assign_with_ops(enum tree_code subcode, tree lhs, tree op1, tree op2 MEM_STAT_DECL)
@@ -400,15 +370,7 @@ static inline void ipa_remove_stmt_references(symtab_node *referring_node, gimpl
referring_node->remove_stmt_references(stmt);
}
-#if BUILDING_GCC_VERSION < 6000
-#define get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, preversep, pvolatilep, keep_aligning) \
- get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, pvolatilep, keep_aligning)
-#define gen_rtx_set(ARG0, ARG1) gen_rtx_SET(VOIDmode, (ARG0), (ARG1))
-#endif
-
-#if BUILDING_GCC_VERSION >= 6000
#define gen_rtx_set(ARG0, ARG1) gen_rtx_SET((ARG0), (ARG1))
-#endif
#ifdef __cplusplus
static inline void debug_tree(const_tree t)
@@ -425,15 +387,8 @@ static inline void debug_gimple_stmt(const_gimple s)
#define debug_gimple_stmt(s) debug_gimple_stmt(CONST_CAST_GIMPLE(s))
#endif
-#if BUILDING_GCC_VERSION >= 7000
#define get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, preversep, pvolatilep, keep_aligning) \
get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, preversep, pvolatilep)
-#endif
-
-#if BUILDING_GCC_VERSION < 7000
-#define SET_DECL_ALIGN(decl, align) DECL_ALIGN(decl) = (align)
-#define SET_DECL_MODE(decl, mode) DECL_MODE(decl) = (mode)
-#endif
#if BUILDING_GCC_VERSION >= 14000
#define last_stmt(x) last_nondebug_stmt(x)
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index 5694df3da2e9..971a1908a8cc 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -344,29 +344,13 @@ static int relayout_struct(tree type)
shuffle(type, (tree *)newtree, shuffle_length);
- /*
- * set up a bogus anonymous struct field designed to error out on unnamed struct initializers
- * as gcc provides no other way to detect such code
- */
- list = make_node(FIELD_DECL);
- TREE_CHAIN(list) = newtree[0];
- TREE_TYPE(list) = void_type_node;
- DECL_SIZE(list) = bitsize_zero_node;
- DECL_NONADDRESSABLE_P(list) = 1;
- DECL_FIELD_BIT_OFFSET(list) = bitsize_zero_node;
- DECL_SIZE_UNIT(list) = size_zero_node;
- DECL_FIELD_OFFSET(list) = size_zero_node;
- DECL_CONTEXT(list) = type;
- // to satisfy the constify plugin
- TREE_READONLY(list) = 1;
-
for (i = 0; i < num_fields - 1; i++)
TREE_CHAIN(newtree[i]) = newtree[i+1];
TREE_CHAIN(newtree[num_fields - 1]) = NULL_TREE;
main_variant = TYPE_MAIN_VARIANT(type);
for (variant = main_variant; variant; variant = TYPE_NEXT_VARIANT(variant)) {
- TYPE_FIELDS(variant) = list;
+ TYPE_FIELDS(variant) = newtree[0];
TYPE_ATTRIBUTES(variant) = copy_list(TYPE_ATTRIBUTES(variant));
TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("randomize_performed"), NULL_TREE, TYPE_ATTRIBUTES(variant));
TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("designated_init"), NULL_TREE, TYPE_ATTRIBUTES(variant));
diff --git a/scripts/gcc-plugins/sancov_plugin.c b/scripts/gcc-plugins/sancov_plugin.c
deleted file mode 100644
index b76cb9c42cec..000000000000
--- a/scripts/gcc-plugins/sancov_plugin.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
- * Licensed under the GPL v2, or (at your option) v3
- *
- * Homepage:
- * https://github.com/ephox-gcc-plugins/sancov
- *
- * This plugin inserts a __sanitizer_cov_trace_pc() call at the start of basic blocks.
- * It supports all gcc versions with plugin support (from gcc-4.5 on).
- * It is based on the commit "Add fuzzing coverage support" by Dmitry Vyukov <dvyukov@google.com>.
- *
- * You can read about it more here:
- * https://gcc.gnu.org/viewcvs/gcc?limit_changes=0&view=revision&revision=231296
- * https://lwn.net/Articles/674854/
- * https://github.com/google/syzkaller
- * https://lwn.net/Articles/677764/
- *
- * Usage:
- * make run
- */
-
-#include "gcc-common.h"
-
-__visible int plugin_is_GPL_compatible;
-
-tree sancov_fndecl;
-
-static struct plugin_info sancov_plugin_info = {
- .version = PLUGIN_VERSION,
- .help = "sancov plugin\n",
-};
-
-static unsigned int sancov_execute(void)
-{
- basic_block bb;
-
- /* Remove this line when this plugin and kcov will be in the kernel.
- if (!strcmp(DECL_NAME_POINTER(current_function_decl), DECL_NAME_POINTER(sancov_fndecl)))
- return 0;
- */
-
- FOR_EACH_BB_FN(bb, cfun) {
- const_gimple stmt;
- gcall *gcall;
- gimple_stmt_iterator gsi = gsi_after_labels(bb);
-
- if (gsi_end_p(gsi))
- continue;
-
- stmt = gsi_stmt(gsi);
- gcall = as_a_gcall(gimple_build_call(sancov_fndecl, 0));
- gimple_set_location(gcall, gimple_location(stmt));
- gsi_insert_before(&gsi, gcall, GSI_SAME_STMT);
- }
- return 0;
-}
-
-#define PASS_NAME sancov
-
-#define NO_GATE
-#define TODO_FLAGS_FINISH TODO_dump_func | TODO_verify_stmts | TODO_update_ssa_no_phi | TODO_verify_flow
-
-#include "gcc-generate-gimple-pass.h"
-
-static void sancov_start_unit(void __unused *gcc_data, void __unused *user_data)
-{
- tree leaf_attr, nothrow_attr;
- tree BT_FN_VOID = build_function_type_list(void_type_node, NULL_TREE);
-
- sancov_fndecl = build_fn_decl("__sanitizer_cov_trace_pc", BT_FN_VOID);
-
- DECL_ASSEMBLER_NAME(sancov_fndecl);
- TREE_PUBLIC(sancov_fndecl) = 1;
- DECL_EXTERNAL(sancov_fndecl) = 1;
- DECL_ARTIFICIAL(sancov_fndecl) = 1;
- DECL_PRESERVE_P(sancov_fndecl) = 1;
- DECL_UNINLINABLE(sancov_fndecl) = 1;
- TREE_USED(sancov_fndecl) = 1;
-
- nothrow_attr = tree_cons(get_identifier("nothrow"), NULL, NULL);
- decl_attributes(&sancov_fndecl, nothrow_attr, 0);
- gcc_assert(TREE_NOTHROW(sancov_fndecl));
- leaf_attr = tree_cons(get_identifier("leaf"), NULL, NULL);
- decl_attributes(&sancov_fndecl, leaf_attr, 0);
-}
-
-__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;
-
- static const struct ggc_root_tab gt_ggc_r_gt_sancov[] = {
- {
- .base = &sancov_fndecl,
- .nelt = 1,
- .stride = sizeof(sancov_fndecl),
- .cb = &gt_ggc_mx_tree_node,
- .pchw = &gt_pch_nx_tree_node
- },
- LAST_GGC_ROOT_TAB
- };
-
- /* BBs can be split afterwards?? */
- PASS_INFO(sancov, "asan", 0, PASS_POS_INSERT_BEFORE);
-
- if (!plugin_default_version_check(version, &gcc_version)) {
- error(G_("incompatible gcc/plugin versions"));
- return 1;
- }
-
- for (i = 0; i < argc; ++i) {
- if (!strcmp(argv[i].key, "no-sancov")) {
- enable = false;
- continue;
- }
- error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
- }
-
- register_callback(plugin_name, PLUGIN_INFO, NULL, &sancov_plugin_info);
-
- if (!enable)
- return 0;
-
-#if BUILDING_GCC_VERSION < 6000
- register_callback(plugin_name, PLUGIN_START_UNIT, &sancov_start_unit, NULL);
- register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL, (void *)&gt_ggc_r_gt_sancov);
- register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &sancov_pass_info);
-#endif
-
- return 0;
-}
diff --git a/scripts/gcc-plugins/structleak_plugin.c b/scripts/gcc-plugins/structleak_plugin.c
deleted file mode 100644
index d8c744233832..000000000000
--- a/scripts/gcc-plugins/structleak_plugin.c
+++ /dev/null
@@ -1,257 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright 2013-2017 by PaX Team <pageexec@freemail.hu>
- *
- * Note: the choice of the license means that the compilation process is
- * NOT 'eligible' as defined by gcc's library exception to the GPL v3,
- * but for the kernel it doesn't matter since it doesn't link against
- * any of the gcc libraries
- *
- * gcc plugin to forcibly initialize certain local variables that could
- * otherwise leak kernel stack to userland if they aren't properly initialized
- * by later code
- *
- * Homepage: https://pax.grsecurity.net/
- *
- * Options:
- * -fplugin-arg-structleak_plugin-disable
- * -fplugin-arg-structleak_plugin-verbose
- * -fplugin-arg-structleak_plugin-byref
- * -fplugin-arg-structleak_plugin-byref-all
- *
- * Usage:
- * $ # for 4.5/4.6/C based 4.7
- * $ gcc -I`gcc -print-file-name=plugin`/include -I`gcc -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o structleak_plugin.so structleak_plugin.c
- * $ # for C++ based 4.7/4.8+
- * $ g++ -I`g++ -print-file-name=plugin`/include -I`g++ -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o structleak_plugin.so structleak_plugin.c
- * $ gcc -fplugin=./structleak_plugin.so test.c -O2
- *
- * TODO: eliminate redundant initializers
- */
-
-#include "gcc-common.h"
-
-/* unused C type flag in all versions 4.5-6 */
-#define TYPE_USERSPACE(TYPE) TYPE_LANG_FLAG_5(TYPE)
-
-__visible int plugin_is_GPL_compatible;
-
-static struct plugin_info structleak_plugin_info = {
- .version = PLUGIN_VERSION,
- .help = "disable\tdo not activate plugin\n"
- "byref\tinit structs passed by reference\n"
- "byref-all\tinit anything passed by reference\n"
- "verbose\tprint all initialized variables\n",
-};
-
-#define BYREF_STRUCT 1
-#define BYREF_ALL 2
-
-static bool verbose;
-static int byref;
-
-static tree handle_user_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
-{
- *no_add_attrs = true;
-
- /* check for types? for now accept everything linux has to offer */
- if (TREE_CODE(*node) != FIELD_DECL)
- return NULL_TREE;
-
- *no_add_attrs = false;
- return NULL_TREE;
-}
-
-static struct attribute_spec user_attr = { };
-
-static void register_attributes(void *event_data, void *data)
-{
- user_attr.name = "user";
- user_attr.handler = handle_user_attribute;
- user_attr.affects_type_identity = true;
-
- register_attribute(&user_attr);
-}
-
-static tree get_field_type(tree field)
-{
- return strip_array_types(TREE_TYPE(field));
-}
-
-static bool is_userspace_type(tree type)
-{
- tree field;
-
- for (field = TYPE_FIELDS(type); field; field = TREE_CHAIN(field)) {
- tree fieldtype = get_field_type(field);
- enum tree_code code = TREE_CODE(fieldtype);
-
- if (code == RECORD_TYPE || code == UNION_TYPE)
- if (is_userspace_type(fieldtype))
- return true;
-
- if (lookup_attribute("user", DECL_ATTRIBUTES(field)))
- return true;
- }
- return false;
-}
-
-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) == ENUMERAL_TYPE)
- return;
-
- if (TYPE_USERSPACE(type))
- return;
-
- if (is_userspace_type(type))
- TYPE_USERSPACE(type) = 1;
-}
-
-static void initialize(tree var)
-{
- basic_block bb;
- gimple_stmt_iterator gsi;
- tree initializer;
- gimple init_stmt;
- tree type;
-
- /* this is the original entry bb before the forced split */
- bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
-
- /* first check if variable is already initialized, warn otherwise */
- for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
- gimple stmt = gsi_stmt(gsi);
- tree rhs1;
-
- /* we're looking for an assignment of a single rhs... */
- if (!gimple_assign_single_p(stmt))
- continue;
- rhs1 = gimple_assign_rhs1(stmt);
- /* ... of a non-clobbering expression... */
- if (TREE_CLOBBER_P(rhs1))
- continue;
- /* ... to our variable... */
- if (gimple_get_lhs(stmt) != var)
- continue;
- /* if it's an initializer then we're good */
- if (TREE_CODE(rhs1) == CONSTRUCTOR)
- return;
- }
-
- /* these aren't the 0days you're looking for */
- if (verbose)
- inform(DECL_SOURCE_LOCATION(var),
- "%s variable will be forcibly initialized",
- (byref && TREE_ADDRESSABLE(var)) ? "byref"
- : "userspace");
-
- /* build the initializer expression */
- type = TREE_TYPE(var);
- if (AGGREGATE_TYPE_P(type))
- initializer = build_constructor(type, NULL);
- else
- initializer = fold_convert(type, integer_zero_node);
-
- /* build the initializer stmt */
- init_stmt = gimple_build_assign(var, initializer);
- gsi = gsi_after_labels(single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
- gsi_insert_before(&gsi, init_stmt, GSI_NEW_STMT);
- update_stmt(init_stmt);
-}
-
-static unsigned int structleak_execute(void)
-{
- basic_block bb;
- tree var;
- unsigned int i;
-
- /* split the first bb where we can put the forced initializers */
- gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
- bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
- if (!single_pred_p(bb)) {
- split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
- gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
- }
-
- /* enumerate all local variables and forcibly initialize our targets */
- FOR_EACH_LOCAL_DECL(cfun, i, var) {
- tree type = TREE_TYPE(var);
-
- gcc_assert(DECL_P(var));
- if (!auto_var_in_fn_p(var, current_function_decl))
- continue;
-
- /* only care about structure types unless byref-all */
- if (byref != BYREF_ALL && TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE)
- continue;
-
- /* if the type is of interest, examine the variable */
- if (TYPE_USERSPACE(type) ||
- (byref && TREE_ADDRESSABLE(var)))
- initialize(var);
- }
-
- return 0;
-}
-
-#define PASS_NAME structleak
-#define NO_GATE
-#define PROPERTIES_REQUIRED PROP_cfg
-#define TODO_FLAGS_FINISH TODO_verify_il | TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func | TODO_remove_unused_locals | TODO_update_ssa | TODO_ggc_collect | TODO_verify_flow
-#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;
-
- PASS_INFO(structleak, "early_optimizations", 1, PASS_POS_INSERT_BEFORE);
-
- 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, "verbose")) {
- verbose = true;
- continue;
- }
- if (!strcmp(argv[i].key, "byref")) {
- byref = BYREF_STRUCT;
- continue;
- }
- if (!strcmp(argv[i].key, "byref-all")) {
- byref = BYREF_ALL;
- continue;
- }
- error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
- }
-
- register_callback(plugin_name, PLUGIN_INFO, NULL, &structleak_plugin_info);
- if (enable) {
- register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &structleak_pass_info);
- register_callback(plugin_name, PLUGIN_FINISH_TYPE, finish_type, NULL);
- }
- register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
-
- return 0;
-}