Hi. We make direct emission for asan_emit_stack_protection for smaller stacks. That's fine but we're missing the piece that marks the stack as released and we run out of pre-allocated stacks. I also included some stack-related constants that were used in asan.c.
Patch can bootstrap on x86_64-linux-gnu and survives regression tests. Ready to be installed? Thanks, Martin gcc/ChangeLog: 2020-05-19 Martin Liska <mli...@suse.cz> PR sanitizer/94910 * asan.c (asan_emit_stack_protection): Emit also **SavedFlagPtr(FakeStack) = 0 in order to release a stack frame. * asan.h (ASAN_MIN_STACK_FRAME_SIZE_LOG): New. (ASAN_MAX_STACK_FRAME_SIZE_LOG): Likewise. (ASAN_MIN_STACK_FRAME_SIZE): Likewise. (ASAN_MAX_STACK_FRAME_SIZE): Likewise. --- gcc/asan.c | 26 ++++++++++++++++++++++---- gcc/asan.h | 8 ++++++++ 2 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/gcc/asan.c b/gcc/asan.c index c9872f1b007..4cdf294e82b 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1375,7 +1375,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, char buf[32]; HOST_WIDE_INT base_offset = offsets[length - 1]; HOST_WIDE_INT base_align_bias = 0, offset, prev_offset; - HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset; + unsigned HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset; HOST_WIDE_INT last_offset, last_size, last_size_aligned; int l; unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT; @@ -1428,7 +1428,9 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, str_cst = asan_pp_string (&asan_pp); /* Emit the prologue sequence. */ - if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase + if (asan_frame_size >= ASAN_MIN_STACK_FRAME_SIZE + && asan_frame_size <= ASAN_MAX_STACK_FRAME_SIZE + && pbase && param_asan_use_after_return) { use_after_return_class = floor_log2 (asan_frame_size - 1) - 5; @@ -1598,8 +1600,24 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, if (use_after_return_class < 5 && can_store_by_pieces (sz, builtin_memset_read_str, &c, BITS_PER_UNIT, true)) - store_by_pieces (shadow_mem, sz, builtin_memset_read_str, &c, - BITS_PER_UNIT, true, RETURN_BEGIN); + { + /* Emit: + memset(ShadowBase, kAsanStackAfterReturnMagic, ShadowSize); + **SavedFlagPtr(FakeStack) = 0 + */ + store_by_pieces (shadow_mem, sz, builtin_memset_read_str, &c, + BITS_PER_UNIT, true, RETURN_BEGIN); + + unsigned HOST_WIDE_INT offset + = (1 << (use_after_return_class + ASAN_MIN_STACK_FRAME_SIZE_LOG)); + offset -= GET_MODE_SIZE (ptr_mode); + mem = adjust_address (mem, Pmode, offset); + mem = gen_rtx_MEM (ptr_mode, mem); + rtx tmp_reg = gen_reg_rtx (Pmode); + emit_move_insn (tmp_reg, mem); + mem = adjust_address (mem, QImode, 0); + emit_move_insn (mem, const0_rtx); + } else if (use_after_return_class >= 5 || !set_storage_via_setmem (shadow_mem, GEN_INT (sz), diff --git a/gcc/asan.h b/gcc/asan.h index 9efd33f9b86..5ff0735045f 100644 --- a/gcc/asan.h +++ b/gcc/asan.h @@ -58,6 +58,14 @@ extern hash_set <tree> *asan_used_labels; #define ASAN_MIN_RED_ZONE_SIZE 16 +/* Minimal and maximal frame size for a fake stack frame. */ + +#define ASAN_MIN_STACK_FRAME_SIZE_LOG 6 +#define ASAN_MAX_STACK_FRAME_SIZE_LOG 16 + +#define ASAN_MIN_STACK_FRAME_SIZE (1UL << ASAN_MIN_STACK_FRAME_SIZE_LOG) +#define ASAN_MAX_STACK_FRAME_SIZE (1UL << ASAN_MAX_STACK_FRAME_SIZE_LOG) + /* Shadow memory values for stack protection. Left is below protected vars, the first pointer in stack corresponding to that offset contains ASAN_STACK_FRAME_MAGIC word, the second pointer to a string describing