scripts/gcc-plugins/stackleak_plugin.c

Source file repositories/reference/linux-study-clean/scripts/gcc-plugins/stackleak_plugin.c

File Facts

System
Linux kernel
Corpus path
scripts/gcc-plugins/stackleak_plugin.c
Extension
.c
Size
19081 bytes
Lines
636
Domain
Support Tooling And Documentation
Bucket
scripts
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (verbose) {
				fprintf(stderr, "stackleak: be careful, alloca() in %s()\n",
					DECL_NAME_POINTER(current_function_decl));
			}

			/* Insert __sanitizer_cov_stack_depth() call after alloca() */
			add_stack_tracking(&gsi, true);
			if (bb == entry_bb)
				prologue_instrumented = true;
		}
	}

	if (prologue_instrumented)
		return 0;

	/*
	 * Special cases to skip the instrumentation.
	 *
	 * Taking the address of static inline functions materializes them,
	 * but we mustn't instrument some of them as the resulting stack
	 * alignment required by the function call ABI will break other
	 * assumptions regarding the expected (but not otherwise enforced)
	 * register clobbering ABI.
	 *
	 * Case in point: native_save_fl on amd64 when optimized for size
	 * clobbers rdx if it were instrumented here.
	 *
	 * TODO: any more special cases?
	 */
	if (is_leaf &&
	    !TREE_PUBLIC(current_function_decl) &&
	    DECL_DECLARED_INLINE_P(current_function_decl)) {
		return 0;
	}

	if (is_leaf &&
	    !strncmp(IDENTIFIER_POINTER(DECL_NAME(current_function_decl)),
		     "_paravirt_", 10)) {
		return 0;
	}

	/* Insert __sanitizer_cov_stack_depth() call at the function beginning */
	bb = entry_bb;
	if (!single_pred_p(bb)) {
		/* gcc_assert(bb_loop_depth(bb) ||
				(bb->flags & BB_IRREDUCIBLE_LOOP)); */
		split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
		gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun)));
		bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun));
	}
	gsi = gsi_after_labels(bb);
	add_stack_tracking(&gsi, false);

	return 0;
}

static bool large_stack_frame(void)
{
#if BUILDING_GCC_VERSION >= 8000
	return maybe_ge(get_frame_size(), track_frame_size);
#else
	return (get_frame_size() >= track_frame_size);
#endif
}

static void remove_stack_tracking_gcall(void)
{
	rtx_insn *insn, *next;

	/*
	 * Find __sanitizer_cov_stack_depth() calls. Loop through the chain of insns,
	 * which is an RTL representation of the code for a function.
	 *
	 * The example of a matching insn:
	 *  (call_insn 8 4 10 2 (call (mem (symbol_ref ("__sanitizer_cov_stack_depth")
	 *  [flags 0x41] <function_decl 0x7f7cd3302a80 __sanitizer_cov_stack_depth>)
	 *  [0 __sanitizer_cov_stack_depth S1 A8]) (0)) 675 {*call} (expr_list
	 *  (symbol_ref ("__sanitizer_cov_stack_depth") [flags 0x41] <function_decl
	 *  0x7f7cd3302a80 __sanitizer_cov_stack_depth>) (expr_list (0) (nil))) (nil))
	 */
	for (insn = get_insns(); insn; insn = next) {
		rtx body;

		next = NEXT_INSN(insn);

		/* Check the expression code of the insn */
		if (!CALL_P(insn))
			continue;

		/*

Annotation

Implementation Notes