^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Licensed under the GPL v2, or (at your option) v3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Homepage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * https://github.com/ephox-gcc-plugins/sancov
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This plugin inserts a __sanitizer_cov_trace_pc() call at the start of basic blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * It supports all gcc versions with plugin support (from gcc-4.5 on).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * It is based on the commit "Add fuzzing coverage support" by Dmitry Vyukov <dvyukov@google.com>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * You can read about it more here:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * https://gcc.gnu.org/viewcvs/gcc?limit_changes=0&view=revision&revision=231296
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * https://lwn.net/Articles/674854/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * https://github.com/google/syzkaller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * https://lwn.net/Articles/677764/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * make run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "gcc-common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) __visible int plugin_is_GPL_compatible;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) tree sancov_fndecl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static struct plugin_info sancov_plugin_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) .version = "20160402",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) .help = "sancov plugin\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static unsigned int sancov_execute(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) basic_block bb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* Remove this line when this plugin and kcov will be in the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (!strcmp(DECL_NAME_POINTER(current_function_decl), DECL_NAME_POINTER(sancov_fndecl)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) FOR_EACH_BB_FN(bb, cfun) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) const_gimple stmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) gcall *gcall;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) gimple_stmt_iterator gsi = gsi_after_labels(bb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (gsi_end_p(gsi))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) stmt = gsi_stmt(gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) gcall = as_a_gcall(gimple_build_call(sancov_fndecl, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) gimple_set_location(gcall, gimple_location(stmt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) gsi_insert_before(&gsi, gcall, GSI_SAME_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define PASS_NAME sancov
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define NO_GATE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define TODO_FLAGS_FINISH TODO_dump_func | TODO_verify_stmts | TODO_update_ssa_no_phi | TODO_verify_flow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #include "gcc-generate-gimple-pass.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static void sancov_start_unit(void __unused *gcc_data, void __unused *user_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) tree leaf_attr, nothrow_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) tree BT_FN_VOID = build_function_type_list(void_type_node, NULL_TREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) sancov_fndecl = build_fn_decl("__sanitizer_cov_trace_pc", BT_FN_VOID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) DECL_ASSEMBLER_NAME(sancov_fndecl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) TREE_PUBLIC(sancov_fndecl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) DECL_EXTERNAL(sancov_fndecl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) DECL_ARTIFICIAL(sancov_fndecl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) DECL_PRESERVE_P(sancov_fndecl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) DECL_UNINLINABLE(sancov_fndecl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) TREE_USED(sancov_fndecl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) nothrow_attr = tree_cons(get_identifier("nothrow"), NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) decl_attributes(&sancov_fndecl, nothrow_attr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) gcc_assert(TREE_NOTHROW(sancov_fndecl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #if BUILDING_GCC_VERSION > 4005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) leaf_attr = tree_cons(get_identifier("leaf"), NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) decl_attributes(&sancov_fndecl, leaf_attr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) __visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) const char * const plugin_name = plugin_info->base_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) const int argc = plugin_info->argc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) const struct plugin_argument * const argv = plugin_info->argv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) bool enable = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static const struct ggc_root_tab gt_ggc_r_gt_sancov[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .base = &sancov_fndecl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .nelt = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .stride = sizeof(sancov_fndecl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .cb = >_ggc_mx_tree_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .pchw = >_pch_nx_tree_node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) LAST_GGC_ROOT_TAB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* BBs can be split afterwards?? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #if BUILDING_GCC_VERSION >= 4009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) PASS_INFO(sancov, "asan", 0, PASS_POS_INSERT_BEFORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) PASS_INFO(sancov, "nrv", 1, PASS_POS_INSERT_BEFORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!plugin_default_version_check(version, &gcc_version)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) error(G_("incompatible gcc/plugin versions"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) for (i = 0; i < argc; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (!strcmp(argv[i].key, "no-sancov")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) enable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) register_callback(plugin_name, PLUGIN_INFO, NULL, &sancov_plugin_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (!enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #if BUILDING_GCC_VERSION < 6000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) register_callback(plugin_name, PLUGIN_START_UNIT, &sancov_start_unit, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL, (void *)>_ggc_r_gt_sancov);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &sancov_pass_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }