^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright 2012-2016 by the PaX Team <pageexec@freemail.hu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2016 by Emese Revfy <re.emese@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Licensed under the GPL v2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Note: the choice of the license means that the compilation process is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * NOT 'eligible' as defined by gcc's library exception to the GPL v3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * but for the kernel it doesn't matter since it doesn't link against
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * any of the gcc libraries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * This gcc plugin helps generate a little bit of entropy from program state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * used throughout the uptime of the kernel. Here is an instrumentation example:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * before:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * void __latent_entropy test(int argc, char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * if (argc <= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * printf("%s: no command arguments :(\n", *argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * printf("%s: %d command arguments!\n", *argv, args - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * after:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * void __latent_entropy test(int argc, char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * // latent_entropy_execute() 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * unsigned long local_entropy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * // init_local_entropy() 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * void *local_entropy_frameaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * // init_local_entropy() 3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * unsigned long tmp_latent_entropy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * // init_local_entropy() 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * local_entropy_frameaddr = __builtin_frame_address(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * local_entropy = (unsigned long) local_entropy_frameaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * // init_local_entropy() 4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * tmp_latent_entropy = latent_entropy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * // init_local_entropy() 5.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * local_entropy ^= tmp_latent_entropy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * // latent_entropy_execute() 3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * if (argc <= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * // perturb_local_entropy()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * local_entropy += 4623067384293424948;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * printf("%s: no command arguments :(\n", *argv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * // perturb_local_entropy()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * local_entropy ^= 3896280633962944730;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * printf("%s: %d command arguments!\n", *argv, args - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * // latent_entropy_execute() 4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * tmp_latent_entropy = rol(tmp_latent_entropy, local_entropy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * latent_entropy = tmp_latent_entropy;
^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) * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * - add ipa pass to identify not explicitly marked candidate functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * - mix in more program state (function arguments/return values,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * loop variables, etc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * - more instrumentation control via attribute parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * BUGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * - none known
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * Options:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * -fplugin-arg-latent_entropy_plugin-disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * Attribute: __attribute__((latent_entropy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * The latent_entropy gcc attribute can be only on functions and variables.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * If it is on a function then the plugin will instrument it. If the attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * is on a variable then the plugin will initialize it with a random value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * The variable must be an integer, an integer array type or a structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * with integer fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #include "gcc-common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) __visible int plugin_is_GPL_compatible;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static GTY(()) tree latent_entropy_decl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static struct plugin_info latent_entropy_plugin_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .version = "201606141920vanilla",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .help = "disable\tturn off latent entropy instrumentation\n",
^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) static unsigned HOST_WIDE_INT seed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * get_random_seed() (this is a GCC function) generates the seed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * This is a simple random generator without any cryptographic security because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * the entropy doesn't come from here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static unsigned HOST_WIDE_INT get_random_const(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned HOST_WIDE_INT ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) for (i = 0; i < 8 * sizeof(ret); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) ret = (ret << 1) | (seed & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) seed >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (ret & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) seed ^= 0xD800000000000000ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static tree tree_get_random_const(tree type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) unsigned long long mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(type)) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) mask = 2 * (mask - 1) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (TYPE_UNSIGNED(type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return build_int_cstu(type, mask & get_random_const());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return build_int_cst(type, mask & get_random_const());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static tree handle_latent_entropy_attribute(tree *node, tree name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) tree args __unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int flags __unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) bool *no_add_attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) tree type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #if BUILDING_GCC_VERSION <= 4007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) VEC(constructor_elt, gc) *vals;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) vec<constructor_elt, va_gc> *vals;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) switch (TREE_CODE(*node)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) *no_add_attrs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) error("%qE attribute only applies to functions and variables",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) case VAR_DECL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (DECL_INITIAL(*node)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) *no_add_attrs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) error("variable %qD with %qE attribute must not be initialized",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) *node, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (!TREE_STATIC(*node)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) *no_add_attrs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) error("variable %qD with %qE attribute must not be local",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) *node, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) type = TREE_TYPE(*node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) switch (TREE_CODE(type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) *no_add_attrs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) error("variable %qD with %qE attribute must be an integer or a fixed length integer array type or a fixed sized structure with integer fields",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) *node, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) case RECORD_TYPE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) tree fld, lst = TYPE_FIELDS(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) unsigned int nelt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) for (fld = lst; fld; nelt++, fld = TREE_CHAIN(fld)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) tree fieldtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) fieldtype = TREE_TYPE(fld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (TREE_CODE(fieldtype) == INTEGER_TYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) *no_add_attrs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) error("structure variable %qD with %qE attribute has a non-integer field %qE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) *node, name, fld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (fld)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #if BUILDING_GCC_VERSION <= 4007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) vals = VEC_alloc(constructor_elt, gc, nelt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) vec_alloc(vals, nelt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) for (fld = lst; fld; fld = TREE_CHAIN(fld)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) tree random_const, fld_t = TREE_TYPE(fld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) random_const = tree_get_random_const(fld_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) CONSTRUCTOR_APPEND_ELT(vals, fld, random_const);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /* Initialize the fields with random constants */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) DECL_INITIAL(*node) = build_constructor(type, vals);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /* Initialize the variable with a random constant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) case INTEGER_TYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) DECL_INITIAL(*node) = tree_get_random_const(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) case ARRAY_TYPE: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) tree elt_type, array_size, elt_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) unsigned int i, nelt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) HOST_WIDE_INT array_size_int, elt_size_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) elt_type = TREE_TYPE(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) elt_size = TYPE_SIZE_UNIT(TREE_TYPE(type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) array_size = TYPE_SIZE_UNIT(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (TREE_CODE(elt_type) != INTEGER_TYPE || !array_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) || TREE_CODE(array_size) != INTEGER_CST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) *no_add_attrs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) error("array variable %qD with %qE attribute must be a fixed length integer array type",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) *node, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) array_size_int = TREE_INT_CST_LOW(array_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) elt_size_int = TREE_INT_CST_LOW(elt_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) nelt = array_size_int / elt_size_int;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) #if BUILDING_GCC_VERSION <= 4007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) vals = VEC_alloc(constructor_elt, gc, nelt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) vec_alloc(vals, nelt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) for (i = 0; i < nelt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) tree cst = size_int(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) tree rand_cst = tree_get_random_const(elt_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) CONSTRUCTOR_APPEND_ELT(vals, cst, rand_cst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * Initialize the elements of the array with random
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * constants
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) DECL_INITIAL(*node) = build_constructor(type, vals);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) case FUNCTION_DECL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static struct attribute_spec latent_entropy_attr = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static void register_attributes(void *event_data __unused, void *data __unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) latent_entropy_attr.name = "latent_entropy";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) latent_entropy_attr.decl_required = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) latent_entropy_attr.handler = handle_latent_entropy_attribute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) register_attribute(&latent_entropy_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static bool latent_entropy_gate(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) tree list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* don't bother with noreturn functions for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (TREE_THIS_VOLATILE(current_function_decl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* gcc-4.5 doesn't discover some trivial noreturn functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (EDGE_COUNT(EXIT_BLOCK_PTR_FOR_FN(cfun)->preds) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) list = DECL_ATTRIBUTES(current_function_decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return lookup_attribute("latent_entropy", list) != NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static tree create_var(tree type, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) tree var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) var = create_tmp_var(type, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) add_referenced_var(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) mark_sym_for_renaming(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * Set up the next operation and its constant operand to use in the latent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * entropy PRNG. When RHS is specified, the request is for perturbing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * local latent entropy variable, otherwise it is for perturbing the global
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * latent entropy variable where the two operands are already given by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * local and global latent entropy variables themselves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * The operation is one of add/xor/rol when instrumenting the local entropy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * variable and one of add/xor when perturbing the global entropy variable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * Rotation is not used for the latter case because it would transmit less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * entropy to the global variable than the other two operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static enum tree_code get_op(tree *rhs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static enum tree_code op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) unsigned HOST_WIDE_INT random_const;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) random_const = get_random_const();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) switch (op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) case BIT_XOR_EXPR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) op = PLUS_EXPR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) case PLUS_EXPR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (rhs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) op = LROTATE_EXPR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * This code limits the value of random_const to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * the size of a long for the rotation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) random_const %= TYPE_PRECISION(long_unsigned_type_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) case LROTATE_EXPR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) op = BIT_XOR_EXPR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (rhs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) *rhs = build_int_cstu(long_unsigned_type_node, random_const);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static gimple create_assign(enum tree_code code, tree lhs, tree op1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) tree op2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return gimple_build_assign_with_ops(code, lhs, op1, op2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static void perturb_local_entropy(basic_block bb, tree local_entropy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) gimple_stmt_iterator gsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) gimple assign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) tree rhs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) enum tree_code op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) op = get_op(&rhs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) assign = create_assign(op, local_entropy, local_entropy, rhs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) gsi = gsi_after_labels(bb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) gsi_insert_before(&gsi, assign, GSI_NEW_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) update_stmt(assign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static void __perturb_latent_entropy(gimple_stmt_iterator *gsi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) tree local_entropy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) gimple assign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) tree temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) enum tree_code op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* 1. create temporary copy of latent_entropy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) temp = create_var(long_unsigned_type_node, "temp_latent_entropy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* 2. read... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) add_referenced_var(latent_entropy_decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) mark_sym_for_renaming(latent_entropy_decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) assign = gimple_build_assign(temp, latent_entropy_decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) gsi_insert_before(gsi, assign, GSI_NEW_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) update_stmt(assign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* 3. ...modify... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) op = get_op(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) assign = create_assign(op, temp, temp, local_entropy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) gsi_insert_after(gsi, assign, GSI_NEW_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) update_stmt(assign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /* 4. ...write latent_entropy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) assign = gimple_build_assign(latent_entropy_decl, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) gsi_insert_after(gsi, assign, GSI_NEW_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) update_stmt(assign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static bool handle_tail_calls(basic_block bb, tree local_entropy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) gimple_stmt_iterator gsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) gcall *call;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) gimple stmt = gsi_stmt(gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (!is_gimple_call(stmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) call = as_a_gcall(stmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (!gimple_call_tail_p(call))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) __perturb_latent_entropy(&gsi, local_entropy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static void perturb_latent_entropy(tree local_entropy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) edge_iterator ei;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) edge e, last_bb_e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) basic_block last_bb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) gcc_assert(single_pred_p(EXIT_BLOCK_PTR_FOR_FN(cfun)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) last_bb_e = single_pred_edge(EXIT_BLOCK_PTR_FOR_FN(cfun));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) FOR_EACH_EDGE(e, ei, last_bb_e->src->preds) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (ENTRY_BLOCK_PTR_FOR_FN(cfun) == e->src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (EXIT_BLOCK_PTR_FOR_FN(cfun) == e->src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) handle_tail_calls(e->src, local_entropy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) last_bb = single_pred(EXIT_BLOCK_PTR_FOR_FN(cfun));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (!handle_tail_calls(last_bb, local_entropy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) gimple_stmt_iterator gsi = gsi_last_bb(last_bb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) __perturb_latent_entropy(&gsi, local_entropy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) static void init_local_entropy(basic_block bb, tree local_entropy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) gimple assign, call;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) tree frame_addr, rand_const, tmp, fndecl, udi_frame_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) enum tree_code op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) unsigned HOST_WIDE_INT rand_cst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) gimple_stmt_iterator gsi = gsi_after_labels(bb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* 1. create local_entropy_frameaddr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) frame_addr = create_var(ptr_type_node, "local_entropy_frameaddr");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* 2. local_entropy_frameaddr = __builtin_frame_address() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) fndecl = builtin_decl_implicit(BUILT_IN_FRAME_ADDRESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) call = gimple_build_call(fndecl, 1, integer_zero_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) gimple_call_set_lhs(call, frame_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) gsi_insert_before(&gsi, call, GSI_NEW_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) update_stmt(call);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) udi_frame_addr = fold_convert(long_unsigned_type_node, frame_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) assign = gimple_build_assign(local_entropy, udi_frame_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) gsi_insert_after(&gsi, assign, GSI_NEW_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) update_stmt(assign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* 3. create temporary copy of latent_entropy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) tmp = create_var(long_unsigned_type_node, "temp_latent_entropy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /* 4. read the global entropy variable into local entropy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) add_referenced_var(latent_entropy_decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) mark_sym_for_renaming(latent_entropy_decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) assign = gimple_build_assign(tmp, latent_entropy_decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) gsi_insert_after(&gsi, assign, GSI_NEW_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) update_stmt(assign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* 5. mix local_entropy_frameaddr into local entropy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) assign = create_assign(BIT_XOR_EXPR, local_entropy, local_entropy, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) gsi_insert_after(&gsi, assign, GSI_NEW_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) update_stmt(assign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) rand_cst = get_random_const();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) rand_const = build_int_cstu(long_unsigned_type_node, rand_cst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) op = get_op(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) assign = create_assign(op, local_entropy, local_entropy, rand_const);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) gsi_insert_after(&gsi, assign, GSI_NEW_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) update_stmt(assign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static bool create_latent_entropy_decl(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) varpool_node_ptr node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (latent_entropy_decl != NULL_TREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) FOR_EACH_VARIABLE(node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) tree name, var = NODE_DECL(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (DECL_NAME_LENGTH(var) < sizeof("latent_entropy") - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) name = DECL_NAME(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (strcmp(IDENTIFIER_POINTER(name), "latent_entropy"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) latent_entropy_decl = var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return latent_entropy_decl != NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static unsigned int latent_entropy_execute(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) basic_block bb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) tree local_entropy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (!create_latent_entropy_decl())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* prepare for step 2 below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) if (!single_pred_p(bb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* 1. create the local entropy variable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) local_entropy = create_var(long_unsigned_type_node, "local_entropy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /* 2. initialize the local entropy variable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) init_local_entropy(bb, local_entropy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) bb = bb->next_bb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * 3. instrument each BB with an operation on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * local entropy variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) while (bb != EXIT_BLOCK_PTR_FOR_FN(cfun)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) perturb_local_entropy(bb, local_entropy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) bb = bb->next_bb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) /* 4. mix local entropy into the global entropy variable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) perturb_latent_entropy(local_entropy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static void latent_entropy_start_unit(void *gcc_data __unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) void *user_data __unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) tree type, id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) int quals;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) seed = get_random_seed(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (in_lto_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* extern volatile unsigned long latent_entropy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) quals = TYPE_QUALS(long_unsigned_type_node) | TYPE_QUAL_VOLATILE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) type = build_qualified_type(long_unsigned_type_node, quals);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) id = get_identifier("latent_entropy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) latent_entropy_decl = build_decl(UNKNOWN_LOCATION, VAR_DECL, id, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) TREE_STATIC(latent_entropy_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) TREE_PUBLIC(latent_entropy_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) TREE_USED(latent_entropy_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) DECL_PRESERVE_P(latent_entropy_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) TREE_THIS_VOLATILE(latent_entropy_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) DECL_EXTERNAL(latent_entropy_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) DECL_ARTIFICIAL(latent_entropy_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) lang_hooks.decls.pushdecl(latent_entropy_decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) #define PASS_NAME latent_entropy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) #define PROPERTIES_REQUIRED PROP_gimple_leh | PROP_cfg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) #define TODO_FLAGS_FINISH TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) | TODO_update_ssa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) #include "gcc-generate-gimple-pass.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) __visible int plugin_init(struct plugin_name_args *plugin_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct plugin_gcc_version *version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) bool enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) const char * const plugin_name = plugin_info->base_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) const int argc = plugin_info->argc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) const struct plugin_argument * const argv = plugin_info->argv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static const struct ggc_root_tab gt_ggc_r_gt_latent_entropy[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) .base = &latent_entropy_decl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) .nelt = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) .stride = sizeof(latent_entropy_decl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) .cb = >_ggc_mx_tree_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) .pchw = >_pch_nx_tree_node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) LAST_GGC_ROOT_TAB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) PASS_INFO(latent_entropy, "optimized", 1, PASS_POS_INSERT_BEFORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (!plugin_default_version_check(version, &gcc_version)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) error(G_("incompatible gcc/plugin versions"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) for (i = 0; i < argc; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (!(strcmp(argv[i].key, "disable"))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) register_callback(plugin_name, PLUGIN_INFO, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) &latent_entropy_plugin_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) register_callback(plugin_name, PLUGIN_START_UNIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) &latent_entropy_start_unit, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) NULL, (void *)>_ggc_r_gt_latent_entropy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) &latent_entropy_pass_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }