Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Copyright 2011-2017 by the PaX Team <pageexec@freemail.hu>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Modified by Alexander Popov <alex.popov@linux.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 is needed for tracking the lowest border of the kernel stack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * It instruments the kernel code inserting stackleak_track_stack() calls:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *  - after alloca();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *  - for the functions with a stack frame size greater than or equal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *     to the "track-min-size" plugin parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * This plugin is ported from grsecurity/PaX. For more information see:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *   https://grsecurity.net/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  *   https://pax.grsecurity.net/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * Debugging:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  *  - use fprintf() to stderr, debug_generic_expr(), debug_gimple_stmt(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *     print_rtl_single() and debug_rtx();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  *  - add "-fdump-tree-all -fdump-rtl-all" to the plugin CFLAGS in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *     Makefile.gcc-plugins to see the verbose dumps of the gcc passes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *  - use gcc -E to understand the preprocessing shenanigans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  *  - use gcc with enabled CFG/GIMPLE/SSA verification (--enable-checking).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include "gcc-common.h"
^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 track_frame_size = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static bool build_for_x86 = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) static const char track_function[] = "stackleak_track_stack";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) static bool disable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) static bool verbose = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * Mark these global variables (roots) for gcc garbage collector since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  * they point to the garbage-collected memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) static GTY(()) tree track_function_decl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static struct plugin_info stackleak_plugin_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	.version = "201707101337",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	.help = "track-min-size=nn\ttrack stack for functions with a stack frame size >= nn bytes\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		"arch=target_arch\tspecify target build arch\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		"disable\t\tdo not activate the plugin\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		"verbose\t\tprint info about the instrumentation\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) static void add_stack_tracking_gcall(gimple_stmt_iterator *gsi, bool after)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	gimple stmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	gcall *gimple_call;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	cgraph_node_ptr node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	basic_block bb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	/* Insert calling stackleak_track_stack() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	stmt = gimple_build_call(track_function_decl, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	gimple_call = as_a_gcall(stmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	if (after)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		gsi_insert_after(gsi, gimple_call, GSI_CONTINUE_LINKING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		gsi_insert_before(gsi, gimple_call, GSI_SAME_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	/* Update the cgraph */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	bb = gimple_bb(gimple_call);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	node = cgraph_get_create_node(track_function_decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	gcc_assert(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	cgraph_create_edge(cgraph_get_node(current_function_decl), node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			gimple_call, bb->count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 			compute_call_stmt_bb_frequency(current_function_decl, bb));
^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) static bool is_alloca(gimple stmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	if (gimple_call_builtin_p(stmt, BUILT_IN_ALLOCA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) #if BUILDING_GCC_VERSION >= 4007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	if (gimple_call_builtin_p(stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	return false;
^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) static tree get_current_stack_pointer_decl(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	varpool_node_ptr node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	FOR_EACH_VARIABLE(node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		tree var = NODE_DECL(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		tree name = DECL_NAME(var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		if (DECL_NAME_LENGTH(var) != sizeof("current_stack_pointer") - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		if (strcmp(IDENTIFIER_POINTER(name), "current_stack_pointer"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		return var;
^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 (verbose) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		fprintf(stderr, "stackleak: missing current_stack_pointer in %s()\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			DECL_NAME_POINTER(current_function_decl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	return NULL_TREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static void add_stack_tracking_gasm(gimple_stmt_iterator *gsi, bool after)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	gasm *asm_call = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	tree sp_decl, input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	vec<tree, va_gc> *inputs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	/* 'no_caller_saved_registers' is currently supported only for x86 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	gcc_assert(build_for_x86);
^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) 	 * Insert calling stackleak_track_stack() in asm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	 *   asm volatile("call stackleak_track_stack"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	 *		  :: "r" (current_stack_pointer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	 * Use ASM_CALL_CONSTRAINT trick from arch/x86/include/asm/asm.h.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	 * This constraint is taken into account during gcc shrink-wrapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	 * optimization. It is needed to be sure that stackleak_track_stack()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	 * call is inserted after the prologue of the containing function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	 * when the stack frame is prepared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	sp_decl = get_current_stack_pointer_decl();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	if (sp_decl == NULL_TREE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		add_stack_tracking_gcall(gsi, after);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	input = build_tree_list(NULL_TREE, build_const_char_string(2, "r"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	input = chainon(NULL_TREE, build_tree_list(input, sp_decl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	vec_safe_push(inputs, input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	asm_call = gimple_build_asm_vec("call stackleak_track_stack",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 					inputs, NULL, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	gimple_asm_set_volatile(asm_call, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	if (after)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		gsi_insert_after(gsi, asm_call, GSI_CONTINUE_LINKING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		gsi_insert_before(gsi, asm_call, GSI_SAME_STMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	update_stmt(asm_call);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static void add_stack_tracking(gimple_stmt_iterator *gsi, bool after)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	 * The 'no_caller_saved_registers' attribute is used for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	 * stackleak_track_stack(). If the compiler supports this attribute for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	 * the target arch, we can add calling stackleak_track_stack() in asm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	 * That improves performance: we avoid useless operations with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	 * caller-saved registers in the functions from which we will remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	 * stackleak_track_stack() call during the stackleak_cleanup pass.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	if (lookup_attribute_spec(get_identifier("no_caller_saved_registers")))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		add_stack_tracking_gasm(gsi, after);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		add_stack_tracking_gcall(gsi, after);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)  * Work with the GIMPLE representation of the code. Insert the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)  * stackleak_track_stack() call after alloca() and into the beginning
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)  * of the function if it is not instrumented.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static unsigned int stackleak_instrument_execute(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	basic_block bb, entry_bb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	bool prologue_instrumented = false, is_leaf = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	gimple_stmt_iterator gsi = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	 * ENTRY_BLOCK_PTR is a basic block which represents possible entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	 * point of a function. This block does not contain any code and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	 * has a CFG edge to its successor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	entry_bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	 * Loop through the GIMPLE statements in each of cfun basic blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	 * cfun is a global variable which represents the function that is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	 * currently processed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	FOR_EACH_BB_FN(bb, cfun) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			gimple stmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 			stmt = gsi_stmt(gsi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			/* Leaf function is a function which makes no calls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 			if (is_gimple_call(stmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 				is_leaf = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			if (!is_alloca(stmt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			if (verbose) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 				fprintf(stderr, "stackleak: be careful, alloca() in %s()\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 					DECL_NAME_POINTER(current_function_decl));
^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) 			/* Insert stackleak_track_stack() call after alloca() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 			add_stack_tracking(&gsi, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 			if (bb == entry_bb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 				prologue_instrumented = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	if (prologue_instrumented)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	 * Special cases to skip the instrumentation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	 * Taking the address of static inline functions materializes them,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	 * but we mustn't instrument some of them as the resulting stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	 * alignment required by the function call ABI will break other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	 * assumptions regarding the expected (but not otherwise enforced)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	 * register clobbering ABI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	 * Case in point: native_save_fl on amd64 when optimized for size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	 * clobbers rdx if it were instrumented here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	 * TODO: any more special cases?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	if (is_leaf &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	    !TREE_PUBLIC(current_function_decl) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	    DECL_DECLARED_INLINE_P(current_function_decl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		return 0;
^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) 	if (is_leaf &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	    !strncmp(IDENTIFIER_POINTER(DECL_NAME(current_function_decl)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		     "_paravirt_", 10)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	/* Insert stackleak_track_stack() call at the function beginning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	bb = entry_bb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	if (!single_pred_p(bb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		/* gcc_assert(bb_loop_depth(bb) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 				(bb->flags & BB_IRREDUCIBLE_LOOP)); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	gsi = gsi_after_labels(bb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	add_stack_tracking(&gsi, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static bool large_stack_frame(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) #if BUILDING_GCC_VERSION >= 8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	return maybe_ge(get_frame_size(), track_frame_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	return (get_frame_size() >= track_frame_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static void remove_stack_tracking_gcall(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	rtx_insn *insn, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	 * Find stackleak_track_stack() calls. Loop through the chain of insns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	 * which is an RTL representation of the code for a function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	 * The example of a matching insn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	 *  (call_insn 8 4 10 2 (call (mem (symbol_ref ("stackleak_track_stack")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	 *  [flags 0x41] <function_decl 0x7f7cd3302a80 stackleak_track_stack>)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	 *  [0 stackleak_track_stack S1 A8]) (0)) 675 {*call} (expr_list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	 *  (symbol_ref ("stackleak_track_stack") [flags 0x41] <function_decl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	 *  0x7f7cd3302a80 stackleak_track_stack>) (expr_list (0) (nil))) (nil))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	for (insn = get_insns(); insn; insn = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		rtx body;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 		next = NEXT_INSN(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		/* Check the expression code of the insn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		if (!CALL_P(insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 			continue;
^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) 		 * Check the expression code of the insn body, which is an RTL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		 * Expression (RTX) describing the side effect performed by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		 * that insn.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		body = PATTERN(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		if (GET_CODE(body) == PARALLEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 			body = XVECEXP(body, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		if (GET_CODE(body) != CALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		 * Check the first operand of the call expression. It should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		 * be a mem RTX describing the needed subroutine with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		 * symbol_ref RTX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		body = XEXP(body, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		if (GET_CODE(body) != MEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		body = XEXP(body, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		if (GET_CODE(body) != SYMBOL_REF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		if (SYMBOL_REF_DECL(body) != track_function_decl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		/* Delete the stackleak_track_stack() call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		delete_insn_and_edges(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) #if BUILDING_GCC_VERSION >= 4007 && BUILDING_GCC_VERSION < 8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		if (GET_CODE(next) == NOTE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		    NOTE_KIND(next) == NOTE_INSN_CALL_ARG_LOCATION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 			insn = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 			next = NEXT_INSN(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 			delete_insn_and_edges(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static bool remove_stack_tracking_gasm(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	bool removed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	rtx_insn *insn, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	/* 'no_caller_saved_registers' is currently supported only for x86 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	gcc_assert(build_for_x86);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	 * Find stackleak_track_stack() asm calls. Loop through the chain of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	 * insns, which is an RTL representation of the code for a function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	 * The example of a matching insn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	 *  (insn 11 5 12 2 (parallel [ (asm_operands/v
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	 *  ("call stackleak_track_stack") ("") 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	 *  [ (reg/v:DI 7 sp [ current_stack_pointer ]) ]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	 *  [ (asm_input:DI ("r")) ] [])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	 *  (clobber (reg:CC 17 flags)) ]) -1 (nil))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	for (insn = get_insns(); insn; insn = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		rtx body;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		next = NEXT_INSN(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		/* Check the expression code of the insn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		if (!NONJUMP_INSN_P(insn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		 * Check the expression code of the insn body, which is an RTL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		 * Expression (RTX) describing the side effect performed by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		 * that insn.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		body = PATTERN(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		if (GET_CODE(body) != PARALLEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		body = XVECEXP(body, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 		if (GET_CODE(body) != ASM_OPERANDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		if (strcmp(ASM_OPERANDS_TEMPLATE(body),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 						"call stackleak_track_stack")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		delete_insn_and_edges(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 		gcc_assert(!removed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		removed = true;
^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) 	return removed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)  * Work with the RTL representation of the code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)  * Remove the unneeded stackleak_track_stack() calls from the functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)  * which don't call alloca() and don't have a large enough stack frame size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static unsigned int stackleak_cleanup_execute(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	const char *fn = DECL_NAME_POINTER(current_function_decl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	bool removed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	 * Leave stack tracking in functions that call alloca().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	 * Additional case:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	 *   gcc before version 7 called allocate_dynamic_stack_space() from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	 *   expand_stack_vars() for runtime alignment of constant-sized stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	 *   variables. That caused cfun->calls_alloca to be set for functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	 *   that in fact don't use alloca().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	 *   For more info see gcc commit 7072df0aae0c59ae437e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	 *   Let's leave such functions instrumented as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	if (cfun->calls_alloca) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 		if (verbose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 			fprintf(stderr, "stackleak: instrument %s(): calls_alloca\n", fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	/* Leave stack tracking in functions with large stack frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	if (large_stack_frame()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		if (verbose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 			fprintf(stderr, "stackleak: instrument %s()\n", fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	if (lookup_attribute_spec(get_identifier("no_caller_saved_registers")))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		removed = remove_stack_tracking_gasm();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	if (!removed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		remove_stack_tracking_gcall();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)  * STRING_CST may or may not be NUL terminated:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)  * https://gcc.gnu.org/onlinedocs/gccint/Constant-expressions.html
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) static inline bool string_equal(tree node, const char *string, int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	if (TREE_STRING_LENGTH(node) < length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	if (TREE_STRING_LENGTH(node) > length + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 	if (TREE_STRING_LENGTH(node) == length + 1 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	    TREE_STRING_POINTER(node)[length] != '\0')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	return !memcmp(TREE_STRING_POINTER(node), string, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) #define STRING_EQUAL(node, str)	string_equal(node, str, strlen(str))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static bool stackleak_gate(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	tree section;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	section = lookup_attribute("section",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 				   DECL_ATTRIBUTES(current_function_decl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	if (section && TREE_VALUE(section)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 		section = TREE_VALUE(TREE_VALUE(section));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		if (STRING_EQUAL(section, ".init.text"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		if (STRING_EQUAL(section, ".devinit.text"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		if (STRING_EQUAL(section, ".cpuinit.text"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		if (STRING_EQUAL(section, ".meminit.text"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	return track_frame_size >= 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* Build the function declaration for stackleak_track_stack() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static void stackleak_start_unit(void *gcc_data __unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 				 void *user_data __unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	tree fntype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	/* void stackleak_track_stack(void) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	fntype = build_function_type_list(void_type_node, NULL_TREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	track_function_decl = build_fn_decl(track_function, fntype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	DECL_ASSEMBLER_NAME(track_function_decl); /* for LTO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 	TREE_PUBLIC(track_function_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	TREE_USED(track_function_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 	DECL_EXTERNAL(track_function_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	DECL_ARTIFICIAL(track_function_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	DECL_PRESERVE_P(track_function_decl) = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)  * Pass gate function is a predicate function that gets executed before the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)  * corresponding pass. If the return value is 'true' the pass gets executed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)  * otherwise, it is skipped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) static bool stackleak_instrument_gate(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	return stackleak_gate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) #define PASS_NAME stackleak_instrument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) #define PROPERTIES_REQUIRED PROP_gimple_leh | PROP_cfg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) #define TODO_FLAGS_START TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) #define TODO_FLAGS_FINISH TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 			| TODO_update_ssa | TODO_rebuild_cgraph_edges
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) #include "gcc-generate-gimple-pass.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static bool stackleak_cleanup_gate(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	return stackleak_gate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) #define PASS_NAME stackleak_cleanup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) #define TODO_FLAGS_FINISH TODO_dump_func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) #include "gcc-generate-rtl-pass.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)  * Every gcc plugin exports a plugin_init() function that is called right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)  * after the plugin is loaded. This function is responsible for registering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)  * the plugin callbacks and doing other required initialization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) __visible int plugin_init(struct plugin_name_args *plugin_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 			  struct plugin_gcc_version *version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	const char * const plugin_name = plugin_info->base_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	const int argc = plugin_info->argc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	const struct plugin_argument * const argv = plugin_info->argv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	/* Extra GGC root tables describing our GTY-ed data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	static const struct ggc_root_tab gt_ggc_r_gt_stackleak[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 			.base = &track_function_decl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 			.nelt = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 			.stride = sizeof(track_function_decl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 			.cb = &gt_ggc_mx_tree_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 			.pchw = &gt_pch_nx_tree_node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 		LAST_GGC_ROOT_TAB
^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) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	 * The stackleak_instrument pass should be executed before the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	 * "optimized" pass, which is the control flow graph cleanup that is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	 * performed just before expanding gcc trees to the RTL. In former
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	 * versions of the plugin this new pass was inserted before the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	 * "tree_profile" pass, which is currently called "profile".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	PASS_INFO(stackleak_instrument, "optimized", 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 						PASS_POS_INSERT_BEFORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	 * The stackleak_cleanup pass should be executed before the "*free_cfg"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	 * pass. It's the moment when the stack frame size is already final,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	 * function prologues and epilogues are generated, and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	 * machine-dependent code transformations are not done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	PASS_INFO(stackleak_cleanup, "*free_cfg", 1, PASS_POS_INSERT_BEFORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	if (!plugin_default_version_check(version, &gcc_version)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 		error(G_("incompatible gcc/plugin versions"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	/* Parse the plugin arguments */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	for (i = 0; i < argc; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 		if (!strcmp(argv[i].key, "track-min-size")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 			if (!argv[i].value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 				error(G_("no value supplied for option '-fplugin-arg-%s-%s'"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 					plugin_name, argv[i].key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 				return 1;
^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) 			track_frame_size = atoi(argv[i].value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 			if (track_frame_size < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 				error(G_("invalid option argument '-fplugin-arg-%s-%s=%s'"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 					plugin_name, argv[i].key, argv[i].value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 		} else if (!strcmp(argv[i].key, "arch")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 			if (!argv[i].value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 				error(G_("no value supplied for option '-fplugin-arg-%s-%s'"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 					plugin_name, argv[i].key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 				return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 			if (!strcmp(argv[i].value, "x86"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 				build_for_x86 = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 		} else if (!strcmp(argv[i].key, "disable")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 			disable = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 		} else if (!strcmp(argv[i].key, "verbose")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 			verbose = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 			error(G_("unknown option '-fplugin-arg-%s-%s'"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 					plugin_name, argv[i].key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 			return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 		}
^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) 	if (disable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 		if (verbose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 			fprintf(stderr, "stackleak: disabled for this translation unit\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	/* Give the information about the plugin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	register_callback(plugin_name, PLUGIN_INFO, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 						&stackleak_plugin_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	/* Register to be called before processing a translation unit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 	register_callback(plugin_name, PLUGIN_START_UNIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 					&stackleak_start_unit, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	/* Register an extra GCC garbage collector (GGC) root table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 	register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 					(void *)&gt_ggc_r_gt_stackleak);
^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) 	 * Hook into the Pass Manager to register new gcc passes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	 * The stack frame size info is available only at the last RTL pass,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	 * when it's too late to insert complex code like a function call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	 * So we register two gcc passes to instrument every function at first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	 * and remove the unneeded instrumentation later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 					&stackleak_instrument_pass_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 					&stackleak_cleanup_pass_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }