^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright 2014-2016 by Open Source Security, Inc., Brad Spengler <spender@grsecurity.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * and PaX Team <pageexec@freemail.hu>
^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) * Usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * $ # for 4.5/4.6/C based 4.7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * $ gcc -I`gcc -print-file-name=plugin`/include -I`gcc -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o randomize_layout_plugin.so randomize_layout_plugin.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * $ # for C++ based 4.7/4.8+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * $ g++ -I`g++ -print-file-name=plugin`/include -I`g++ -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o randomize_layout_plugin.so randomize_layout_plugin.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * $ gcc -fplugin=./randomize_layout_plugin.so test.c -O2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "gcc-common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "randomize_layout_seed.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #if BUILDING_GCC_MAJOR < 4 || (BUILDING_GCC_MAJOR == 4 && BUILDING_GCC_MINOR < 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #error "The RANDSTRUCT plugin requires GCC 4.7 or newer."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define ORIG_TYPE_NAME(node) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) (TYPE_NAME(TYPE_MAIN_VARIANT(node)) != NULL_TREE ? ((const unsigned char *)IDENTIFIER_POINTER(TYPE_NAME(TYPE_MAIN_VARIANT(node)))) : (const unsigned char *)"anonymous")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define INFORM(loc, msg, ...) inform(loc, "randstruct: " msg, ##__VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define MISMATCH(loc, how, ...) INFORM(loc, "casting between randomized structure pointer types (" how "): %qT and %qT\n", __VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) __visible int plugin_is_GPL_compatible;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int performance_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static struct plugin_info randomize_layout_plugin_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .version = "201402201816vanilla",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) .help = "disable\t\t\tdo not activate plugin\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) "performance-mode\tenable cacheline-aware layout randomization\n"
^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) struct whitelist_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) const char *pathname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) const char *lhs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) const char *rhs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static const struct whitelist_entry whitelist[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* NIU overloads mapping with page struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) { "drivers/net/ethernet/sun/niu.c", "page", "address_space" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* unix_skb_parms via UNIXCB() buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { "net/unix/af_unix.c", "unix_skb_parms", "char" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* big_key payload.data struct splashing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) { "security/keys/big_key.c", "path", "void *" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* walk struct security_hook_heads as an array of struct hlist_head */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { "security/security.c", "hlist_head", "security_hook_heads" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* from old Linux dcache.h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static inline unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) partial_name_hash(unsigned long c, unsigned long prevhash)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return (prevhash + (c << 4) + (c >> 4)) * 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static inline unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) name_hash(const unsigned char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) unsigned long hash = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned int len = strlen((const char *)name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) while (len--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) hash = partial_name_hash(*name++, hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return (unsigned int)hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static tree handle_randomize_layout_attr(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) tree type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) *no_add_attrs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (TREE_CODE(*node) == FUNCTION_DECL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) error("%qE attribute does not apply to functions (%qF)", name, *node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (TREE_CODE(*node) == PARM_DECL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) error("%qE attribute does not apply to function parameters (%qD)", name, *node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (TREE_CODE(*node) == VAR_DECL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) error("%qE attribute does not apply to variables (%qD)", name, *node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (TYPE_P(*node)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) type = *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) gcc_assert(TREE_CODE(*node) == TYPE_DECL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) type = TREE_TYPE(*node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (TREE_CODE(type) != RECORD_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) error("%qE attribute used on %qT applies to struct types only", name, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return NULL_TREE;
^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) if (lookup_attribute(IDENTIFIER_POINTER(name), TYPE_ATTRIBUTES(type))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) error("%qE attribute is already applied to the type %qT", name, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *no_add_attrs = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* set on complete types that we don't need to inspect further at all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static tree handle_randomize_considered_attr(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) *no_add_attrs = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * set on types that we've performed a shuffle on, to prevent re-shuffling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * this does not preclude us from inspecting its fields for potential shuffles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static tree handle_randomize_performed_attr(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) *no_add_attrs = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * 64bit variant of Bob Jenkins' public domain PRNG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * 256 bits of internal state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) typedef unsigned long long u64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) typedef struct ranctx { u64 a; u64 b; u64 c; u64 d; } ranctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define rot(x,k) (((x)<<(k))|((x)>>(64-(k))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static u64 ranval(ranctx *x) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) u64 e = x->a - rot(x->b, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) x->a = x->b ^ rot(x->c, 13);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) x->b = x->c + rot(x->d, 37);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) x->c = x->d + e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) x->d = e + x->a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return x->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static void raninit(ranctx *x, u64 *seed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) x->a = seed[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) x->b = seed[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) x->c = seed[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) x->d = seed[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) for (i=0; i < 30; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) (void)ranval(x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static u64 shuffle_seed[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct partition_group {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) tree tree_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) unsigned long start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) unsigned long length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static void partition_struct(tree *fields, unsigned long length, struct partition_group *size_groups, unsigned long *num_groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) unsigned long accum_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) unsigned long accum_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) unsigned long group_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) gcc_assert(length < INT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) memset(size_groups, 0, sizeof(struct partition_group) * length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) for (i = 0; i < length; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (size_groups[group_idx].tree_start == NULL_TREE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) size_groups[group_idx].tree_start = fields[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) size_groups[group_idx].start = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) accum_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) accum_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) accum_size += (unsigned long)int_size_in_bytes(TREE_TYPE(fields[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) accum_length++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (accum_size >= 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) size_groups[group_idx].length = accum_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) accum_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) group_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (size_groups[group_idx].tree_start != NULL_TREE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) !size_groups[group_idx].length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) size_groups[group_idx].length = accum_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) group_idx++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) *num_groups = group_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static void performance_shuffle(tree *newtree, unsigned long length, ranctx *prng_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) unsigned long i, x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct partition_group size_group[length];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) unsigned long num_groups = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) unsigned long randnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) partition_struct(newtree, length, (struct partition_group *)&size_group, &num_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) for (i = num_groups - 1; i > 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct partition_group tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) randnum = ranval(prng_state) % (i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) tmp = size_group[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) size_group[i] = size_group[randnum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) size_group[randnum] = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) for (x = 0; x < num_groups; x++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) for (i = size_group[x].start + size_group[x].length - 1; i > size_group[x].start; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) tree tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (DECL_BIT_FIELD_TYPE(newtree[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) randnum = ranval(prng_state) % (i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) // we could handle this case differently if desired
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (DECL_BIT_FIELD_TYPE(newtree[randnum]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) tmp = newtree[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) newtree[i] = newtree[randnum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) newtree[randnum] = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^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) static void full_shuffle(tree *newtree, unsigned long length, ranctx *prng_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned long i, randnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) for (i = length - 1; i > 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) tree tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) randnum = ranval(prng_state) % (i + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) tmp = newtree[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) newtree[i] = newtree[randnum];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) newtree[randnum] = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^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) /* modern in-place Fisher-Yates shuffle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static void shuffle(const_tree type, tree *newtree, unsigned long length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) u64 seed[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) ranctx prng_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) const unsigned char *structname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (length == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) gcc_assert(TREE_CODE(type) == RECORD_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) structname = ORIG_TYPE_NAME(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) #ifdef __DEBUG_PLUGIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) fprintf(stderr, "Shuffling struct %s %p\n", (const char *)structname, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #ifdef __DEBUG_VERBOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) debug_tree((tree)type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) seed[i] = shuffle_seed[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) seed[i] ^= name_hash(structname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) raninit(&prng_state, (u64 *)&seed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (performance_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) performance_shuffle(newtree, length, &prng_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) full_shuffle(newtree, length, &prng_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static bool is_flexible_array(const_tree field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) const_tree fieldtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) const_tree typesize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) const_tree elemtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) const_tree elemsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) fieldtype = TREE_TYPE(field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) typesize = TYPE_SIZE(fieldtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (TREE_CODE(fieldtype) != ARRAY_TYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) elemtype = TREE_TYPE(fieldtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) elemsize = TYPE_SIZE(elemtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* size of type is represented in bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (typesize == NULL_TREE && TYPE_DOMAIN(fieldtype) != NULL_TREE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) TYPE_MAX_VALUE(TYPE_DOMAIN(fieldtype)) == NULL_TREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (typesize != NULL_TREE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) (TREE_CONSTANT(typesize) && (!tree_to_uhwi(typesize) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) tree_to_uhwi(typesize) == tree_to_uhwi(elemsize))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int relayout_struct(tree type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) unsigned long num_fields = (unsigned long)list_length(TYPE_FIELDS(type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) unsigned long shuffle_length = num_fields;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) tree field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) tree newtree[num_fields];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) unsigned long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) tree list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) tree variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) tree main_variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) expanded_location xloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) bool has_flexarray = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (TYPE_FIELDS(type) == NULL_TREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (num_fields < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) gcc_assert(TREE_CODE(type) == RECORD_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) gcc_assert(num_fields < INT_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(type)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) lookup_attribute("no_randomize_layout", TYPE_ATTRIBUTES(TYPE_MAIN_VARIANT(type))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* Workaround for 3rd-party VirtualBox source that we can't modify ourselves */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (!strcmp((const char *)ORIG_TYPE_NAME(type), "INTNETTRUNKFACTORY") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) !strcmp((const char *)ORIG_TYPE_NAME(type), "RAWPCIFACTORY"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /* throw out any structs in uapi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) xloc = expand_location(DECL_SOURCE_LOCATION(TYPE_FIELDS(type)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (strstr(xloc.file, "/uapi/"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) error(G_("attempted to randomize userland API struct %s"), ORIG_TYPE_NAME(type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) for (field = TYPE_FIELDS(type), i = 0; field; field = TREE_CHAIN(field), i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) gcc_assert(TREE_CODE(field) == FIELD_DECL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) newtree[i] = field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * enforce that we don't randomize the layout of the last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * element of a struct if it's a 0 or 1-length array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * or a proper flexible array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (is_flexible_array(newtree[num_fields - 1])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) has_flexarray = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) shuffle_length--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) shuffle(type, (tree *)newtree, shuffle_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * set up a bogus anonymous struct field designed to error out on unnamed struct initializers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * as gcc provides no other way to detect such code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) list = make_node(FIELD_DECL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) TREE_CHAIN(list) = newtree[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) TREE_TYPE(list) = void_type_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) DECL_SIZE(list) = bitsize_zero_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) DECL_NONADDRESSABLE_P(list) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) DECL_FIELD_BIT_OFFSET(list) = bitsize_zero_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) DECL_SIZE_UNIT(list) = size_zero_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) DECL_FIELD_OFFSET(list) = size_zero_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) DECL_CONTEXT(list) = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) // to satisfy the constify plugin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) TREE_READONLY(list) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) for (i = 0; i < num_fields - 1; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) TREE_CHAIN(newtree[i]) = newtree[i+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) TREE_CHAIN(newtree[num_fields - 1]) = NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) main_variant = TYPE_MAIN_VARIANT(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) for (variant = main_variant; variant; variant = TYPE_NEXT_VARIANT(variant)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) TYPE_FIELDS(variant) = list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) TYPE_ATTRIBUTES(variant) = copy_list(TYPE_ATTRIBUTES(variant));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("randomize_performed"), NULL_TREE, TYPE_ATTRIBUTES(variant));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("designated_init"), NULL_TREE, TYPE_ATTRIBUTES(variant));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (has_flexarray)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("has_flexarray"), NULL_TREE, TYPE_ATTRIBUTES(type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * force a re-layout of the main variant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * the TYPE_SIZE for all variants will be recomputed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * by finalize_type_size()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) TYPE_SIZE(main_variant) = NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) layout_type(main_variant);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) gcc_assert(TYPE_SIZE(main_variant) != NULL_TREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /* from constify plugin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static const_tree get_field_type(const_tree field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return strip_array_types(TREE_TYPE(field));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* from constify plugin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) static bool is_fptr(const_tree fieldtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (TREE_CODE(fieldtype) != POINTER_TYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return TREE_CODE(TREE_TYPE(fieldtype)) == FUNCTION_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* derived from constify plugin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) static int is_pure_ops_struct(const_tree node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) const_tree field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) gcc_assert(TREE_CODE(node) == RECORD_TYPE || TREE_CODE(node) == UNION_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) for (field = TYPE_FIELDS(node); field; field = TREE_CHAIN(field)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) const_tree fieldtype = get_field_type(field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) enum tree_code code = TREE_CODE(fieldtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (node == fieldtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (code == RECORD_TYPE || code == UNION_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (!is_pure_ops_struct(fieldtype))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (!is_fptr(fieldtype))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) static void randomize_type(tree type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) tree variant;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) gcc_assert(TREE_CODE(type) == RECORD_TYPE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (lookup_attribute("randomize_considered", TYPE_ATTRIBUTES(type)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (lookup_attribute("randomize_layout", TYPE_ATTRIBUTES(TYPE_MAIN_VARIANT(type))) || is_pure_ops_struct(type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) relayout_struct(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) for (variant = TYPE_MAIN_VARIANT(type); variant; variant = TYPE_NEXT_VARIANT(variant)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("randomize_considered"), NULL_TREE, TYPE_ATTRIBUTES(type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) #ifdef __DEBUG_PLUGIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) fprintf(stderr, "Marking randomize_considered on struct %s\n", ORIG_TYPE_NAME(type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) #ifdef __DEBUG_VERBOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) debug_tree(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) #endif
^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 void update_decl_size(tree decl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) tree lastval, lastidx, field, init, type, flexsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) unsigned HOST_WIDE_INT len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) type = TREE_TYPE(decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (!lookup_attribute("has_flexarray", TYPE_ATTRIBUTES(type)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) init = DECL_INITIAL(decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (init == NULL_TREE || init == error_mark_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (TREE_CODE(init) != CONSTRUCTOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) len = CONSTRUCTOR_NELTS(init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (!len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) lastval = CONSTRUCTOR_ELT(init, CONSTRUCTOR_NELTS(init) - 1)->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) lastidx = CONSTRUCTOR_ELT(init, CONSTRUCTOR_NELTS(init) - 1)->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) for (field = TYPE_FIELDS(TREE_TYPE(decl)); TREE_CHAIN(field); field = TREE_CHAIN(field))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (lastidx != field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (TREE_CODE(lastval) != STRING_CST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) error("Only string constants are supported as initializers "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) "for randomized structures with flexible arrays");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) flexsize = bitsize_int(TREE_STRING_LENGTH(lastval) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) tree_to_uhwi(TYPE_SIZE(TREE_TYPE(TREE_TYPE(lastval)))));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) DECL_SIZE(decl) = size_binop(PLUS_EXPR, TYPE_SIZE(type), flexsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static void randomize_layout_finish_decl(void *event_data, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) tree decl = (tree)event_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) tree type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (decl == NULL_TREE || decl == error_mark_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) type = TREE_TYPE(decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (TREE_CODE(decl) != VAR_DECL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (!lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(type)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) DECL_SIZE(decl) = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) DECL_SIZE_UNIT(decl) = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) SET_DECL_ALIGN(decl, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) SET_DECL_MODE (decl, VOIDmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) SET_DECL_RTL(decl, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) update_decl_size(decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) layout_decl(decl, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) static void finish_type(void *event_data, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) tree type = (tree)event_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (type == NULL_TREE || type == error_mark_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (TREE_CODE(type) != RECORD_TYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (TYPE_FIELDS(type) == NULL_TREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (lookup_attribute("randomize_considered", TYPE_ATTRIBUTES(type)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) #ifdef __DEBUG_PLUGIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) fprintf(stderr, "Calling randomize_type on %s\n", ORIG_TYPE_NAME(type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) #ifdef __DEBUG_VERBOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) debug_tree(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) randomize_type(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static struct attribute_spec randomize_layout_attr = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static struct attribute_spec no_randomize_layout_attr = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) static struct attribute_spec randomize_considered_attr = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) static struct attribute_spec randomize_performed_attr = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static void register_attributes(void *event_data, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) randomize_layout_attr.name = "randomize_layout";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) randomize_layout_attr.type_required = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) randomize_layout_attr.handler = handle_randomize_layout_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) #if BUILDING_GCC_VERSION >= 4007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) randomize_layout_attr.affects_type_identity = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) no_randomize_layout_attr.name = "no_randomize_layout";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) no_randomize_layout_attr.type_required = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) no_randomize_layout_attr.handler = handle_randomize_layout_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) #if BUILDING_GCC_VERSION >= 4007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) no_randomize_layout_attr.affects_type_identity = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) randomize_considered_attr.name = "randomize_considered";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) randomize_considered_attr.type_required = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) randomize_considered_attr.handler = handle_randomize_considered_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) randomize_performed_attr.name = "randomize_performed";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) randomize_performed_attr.type_required = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) randomize_performed_attr.handler = handle_randomize_performed_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) register_attribute(&randomize_layout_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) register_attribute(&no_randomize_layout_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) register_attribute(&randomize_considered_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) register_attribute(&randomize_performed_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) static void check_bad_casts_in_constructor(tree var, tree init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) unsigned HOST_WIDE_INT idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) tree field, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) tree field_type, val_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) FOR_EACH_CONSTRUCTOR_ELT(CONSTRUCTOR_ELTS(init), idx, field, val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (TREE_CODE(val) == CONSTRUCTOR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) check_bad_casts_in_constructor(var, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /* pipacs' plugin creates franken-arrays that differ from those produced by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) normal code which all have valid 'field' trees. work around this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (field == NULL_TREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) field_type = TREE_TYPE(field);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) val_type = TREE_TYPE(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (TREE_CODE(field_type) != POINTER_TYPE || TREE_CODE(val_type) != POINTER_TYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (field_type == val_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) field_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(field_type))));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) val_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(val_type))));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (field_type == void_type_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (field_type == val_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (TREE_CODE(val_type) != RECORD_TYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (!lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(val_type)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) MISMATCH(DECL_SOURCE_LOCATION(var), "constructor\n", TYPE_MAIN_VARIANT(field_type), TYPE_MAIN_VARIANT(val_type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /* derived from the constify plugin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static void check_global_variables(void *event_data, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct varpool_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) tree init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) FOR_EACH_VARIABLE(node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) tree var = NODE_DECL(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) init = DECL_INITIAL(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) if (init == NULL_TREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (TREE_CODE(init) != CONSTRUCTOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) check_bad_casts_in_constructor(var, init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) static bool dominated_by_is_err(const_tree rhs, basic_block bb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) basic_block dom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) gimple dom_stmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) gimple call_stmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) const_tree dom_lhs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) const_tree poss_is_err_cond;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) const_tree poss_is_err_func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) const_tree is_err_arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) dom = get_immediate_dominator(CDI_DOMINATORS, bb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (!dom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) dom_stmt = last_stmt(dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (!dom_stmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) if (gimple_code(dom_stmt) != GIMPLE_COND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (gimple_cond_code(dom_stmt) != NE_EXPR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (!integer_zerop(gimple_cond_rhs(dom_stmt)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) poss_is_err_cond = gimple_cond_lhs(dom_stmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (TREE_CODE(poss_is_err_cond) != SSA_NAME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) call_stmt = SSA_NAME_DEF_STMT(poss_is_err_cond);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (gimple_code(call_stmt) != GIMPLE_CALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) dom_lhs = gimple_get_lhs(call_stmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) poss_is_err_func = gimple_call_fndecl(call_stmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (!poss_is_err_func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (dom_lhs != poss_is_err_cond)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (strcmp(DECL_NAME_POINTER(poss_is_err_func), "IS_ERR"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) is_err_arg = gimple_call_arg(call_stmt, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (!is_err_arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (is_err_arg != rhs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) static void handle_local_var_initializers(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) tree var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) FOR_EACH_LOCAL_DECL(cfun, i, var) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) tree init = DECL_INITIAL(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (!init)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (TREE_CODE(init) != CONSTRUCTOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) check_bad_casts_in_constructor(var, init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) static bool type_name_eq(gimple stmt, const_tree type_tree, const char *wanted_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) const char *type_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (type_tree == NULL_TREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) switch (TREE_CODE(type_tree)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) case RECORD_TYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) type_name = TYPE_NAME_POINTER(type_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) case INTEGER_TYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (TYPE_PRECISION(type_tree) == CHAR_TYPE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) type_name = "char";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) INFORM(gimple_location(stmt), "found non-char INTEGER_TYPE cast comparison: %qT\n", type_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) debug_tree(type_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) case POINTER_TYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (TREE_CODE(TREE_TYPE(type_tree)) == VOID_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) type_name = "void *";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) INFORM(gimple_location(stmt), "found non-void POINTER_TYPE cast comparison %qT\n", type_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) debug_tree(type_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) INFORM(gimple_location(stmt), "unhandled cast comparison: %qT\n", type_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) debug_tree(type_tree);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return strcmp(type_name, wanted_name) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) static bool whitelisted_cast(gimple stmt, const_tree lhs_tree, const_tree rhs_tree)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) const struct whitelist_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) expanded_location xloc = expand_location(gimple_location(stmt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) for (entry = whitelist; entry->pathname; entry++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (!strstr(xloc.file, entry->pathname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (type_name_eq(stmt, lhs_tree, entry->lhs) && type_name_eq(stmt, rhs_tree, entry->rhs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * iterate over all statements to find "bad" casts:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) * those where the address of the start of a structure is cast
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * to a pointer of a structure of a different type, or a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * structure pointer type is cast to a different structure pointer type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) static unsigned int find_bad_casts_execute(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) basic_block bb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) handle_local_var_initializers();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) FOR_EACH_BB_FN(bb, cfun) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) gimple_stmt_iterator gsi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) gimple stmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) const_tree lhs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) const_tree lhs_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) const_tree rhs1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) const_tree rhs_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) const_tree ptr_lhs_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) const_tree ptr_rhs_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) const_tree op0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) const_tree op0_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) enum tree_code rhs_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) stmt = gsi_stmt(gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) #ifdef __DEBUG_PLUGIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) #ifdef __DEBUG_VERBOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) debug_gimple_stmt(stmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) debug_tree(gimple_get_lhs(stmt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (gimple_code(stmt) != GIMPLE_ASSIGN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) #ifdef __DEBUG_PLUGIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) #ifdef __DEBUG_VERBOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) debug_tree(gimple_assign_rhs1(stmt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) rhs_code = gimple_assign_rhs_code(stmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (rhs_code != ADDR_EXPR && rhs_code != SSA_NAME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) lhs = gimple_get_lhs(stmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) lhs_type = TREE_TYPE(lhs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) rhs1 = gimple_assign_rhs1(stmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) rhs_type = TREE_TYPE(rhs1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (TREE_CODE(rhs_type) != POINTER_TYPE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) TREE_CODE(lhs_type) != POINTER_TYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) ptr_lhs_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(lhs_type))));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) ptr_rhs_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(rhs_type))));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (ptr_rhs_type == void_type_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (ptr_lhs_type == void_type_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (dominated_by_is_err(rhs1, bb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) if (TREE_CODE(ptr_rhs_type) != RECORD_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) #ifndef __DEBUG_PLUGIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(ptr_lhs_type)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (!whitelisted_cast(stmt, ptr_lhs_type, ptr_rhs_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) MISMATCH(gimple_location(stmt), "rhs", ptr_lhs_type, ptr_rhs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (rhs_code == SSA_NAME && ptr_lhs_type == ptr_rhs_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (rhs_code == ADDR_EXPR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) op0 = TREE_OPERAND(rhs1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (op0 == NULL_TREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (TREE_CODE(op0) != VAR_DECL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) op0_type = TYPE_MAIN_VARIANT(strip_array_types(TYPE_MAIN_VARIANT(TREE_TYPE(op0))));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (op0_type == ptr_lhs_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) #ifndef __DEBUG_PLUGIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(op0_type)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (!whitelisted_cast(stmt, ptr_lhs_type, op0_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) MISMATCH(gimple_location(stmt), "op0", ptr_lhs_type, op0_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) const_tree ssa_name_var = SSA_NAME_VAR(rhs1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) /* skip bogus type casts introduced by container_of */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (ssa_name_var != NULL_TREE && DECL_NAME(ssa_name_var) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) !strcmp((const char *)DECL_NAME_POINTER(ssa_name_var), "__mptr"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) #ifndef __DEBUG_PLUGIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(ptr_rhs_type)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (!whitelisted_cast(stmt, ptr_lhs_type, ptr_rhs_type))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) MISMATCH(gimple_location(stmt), "ssa", ptr_lhs_type, ptr_rhs_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) #define PASS_NAME find_bad_casts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) #define NO_GATE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) #define TODO_FLAGS_FINISH TODO_dump_func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) #include "gcc-generate-gimple-pass.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) __visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) const char * const plugin_name = plugin_info->base_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) const int argc = plugin_info->argc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) const struct plugin_argument * const argv = plugin_info->argv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) bool enable = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) int obtained_seed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct register_pass_info find_bad_casts_pass_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) find_bad_casts_pass_info.pass = make_find_bad_casts_pass();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) find_bad_casts_pass_info.reference_pass_name = "ssa";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) find_bad_casts_pass_info.ref_pass_instance_number = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) find_bad_casts_pass_info.pos_op = PASS_POS_INSERT_AFTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (!plugin_default_version_check(version, &gcc_version)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) error(G_("incompatible gcc/plugin versions"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) if (strncmp(lang_hooks.name, "GNU C", 5) && !strncmp(lang_hooks.name, "GNU C+", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) inform(UNKNOWN_LOCATION, G_("%s supports C only, not %s"), plugin_name, lang_hooks.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) enable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) for (i = 0; i < argc; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) if (!strcmp(argv[i].key, "disable")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) enable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (!strcmp(argv[i].key, "performance-mode")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) performance_mode = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (strlen(randstruct_seed) != 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) error(G_("invalid seed value supplied for %s plugin"), plugin_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) obtained_seed = sscanf(randstruct_seed, "%016llx%016llx%016llx%016llx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) &shuffle_seed[0], &shuffle_seed[1], &shuffle_seed[2], &shuffle_seed[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) if (obtained_seed != 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) error(G_("Invalid seed supplied for %s plugin"), plugin_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) register_callback(plugin_name, PLUGIN_INFO, NULL, &randomize_layout_plugin_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) register_callback(plugin_name, PLUGIN_ALL_IPA_PASSES_START, check_global_variables, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &find_bad_casts_pass_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) register_callback(plugin_name, PLUGIN_FINISH_TYPE, finish_type, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) register_callback(plugin_name, PLUGIN_FINISH_DECL, randomize_layout_finish_decl, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }