Hi all,
This patch adds support for non-fixed shadow in asan stack instrumentation.
It is required for Kernel AddressSanitizer, as the shadow offset is
not known at the compile time, and the shadow may not be allocated
during the early boot stages.
This option is intended to be triggered by -fsanitize=kernel-address
option, together with enabling instrumentation with calls.
Bootstrapped®tested on x86_64.
Codereview: https://codereview.appspot.com/118040043/
--
Alexey
2014-07-21 Yury Gribov
Alexey Preobrazhensky
New asan-fixed-shadow-offset parameter.
gcc/
* asan.c (asan_emit_stack_protection): Add support for new parameter.
* params.def: Define new parameter.
* params.h: Likewise.
gcc/testsuite/
* c-c++-common/asan/no-fixed-shadow-offset.c: New.
Index: gcc/asan.c
===
--- gcc/asan.c (revision 212896)
+++ gcc/asan.c (working copy)
@@ -979,6 +979,8 @@
HOST_WIDE_INT *offsets, tree *decls, int length)
{
rtx shadow_base, shadow_mem, ret, mem, orig_base, lab;
+ rtx shadow_start = NULL_RTX;
+ rtx skip_prologue_lab = NULL_RTX, skip_epilogue_lab = NULL_RTX;
char buf[30];
unsigned char shadow_bytes[4];
HOST_WIDE_INT base_offset = offsets[length - 1];
@@ -1112,10 +1114,26 @@
shadow_base = expand_binop (Pmode, lshr_optab, base,
GEN_INT (ASAN_SHADOW_SHIFT),
NULL_RTX, 1, OPTAB_DIRECT);
- shadow_base
-= plus_constant (Pmode, shadow_base,
-targetm.asan_shadow_offset ()
-+ (base_align_bias >> ASAN_SHADOW_SHIFT));
+ if (ASAN_FIXED_SHADOW_OFFSET)
+{
+ shadow_base
+= plus_constant (Pmode, shadow_base,
+targetm.asan_shadow_offset ()
++ (base_align_bias >> ASAN_SHADOW_SHIFT));
+}
+ else
+{
+ ret = init_one_libfunc ("__asan_get_shadow_ptr");
+ shadow_start = gen_reg_rtx (ptr_mode);
+ emit_library_call_value (ret, shadow_start, LCT_NORMAL, ptr_mode, 0);
+ skip_prologue_lab = gen_label_rtx ();
+ emit_cmp_and_jump_insns (shadow_start, const0_rtx, EQ, NULL_RTX,
VOIDmode,
+ 0, skip_prologue_lab, PROB_VERY_UNLIKELY);
+ shadow_base = expand_binop (Pmode, add_optab, shadow_base, shadow_start,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ shadow_base = plus_constant (Pmode, shadow_base,
+ base_align_bias >> ASAN_SHADOW_SHIFT);
+}
gcc_assert (asan_shadow_set != -1
&& (ASAN_RED_ZONE_SIZE >> ASAN_SHADOW_SHIFT) == 4);
shadow_mem = gen_rtx_MEM (SImode, shadow_base);
@@ -1165,17 +1183,19 @@
}
do_pending_stack_adjust ();
+ if (skip_prologue_lab)
+emit_label (skip_prologue_lab);
+
/* Construct epilogue sequence. */
start_sequence ();
- lab = NULL_RTX;
if (use_after_return_class != -1)
{
- rtx lab2 = gen_label_rtx ();
char c = (char) ASAN_STACK_MAGIC_USE_AFTER_RET;
int very_likely = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
+ lab = gen_label_rtx ();
emit_cmp_and_jump_insns (orig_base, base, EQ, NULL_RTX,
- VOIDmode, 0, lab2, very_likely);
+ VOIDmode, 0, lab, very_likely);
shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
set_mem_alias_set (shadow_mem, asan_shadow_set);
mem = gen_rtx_MEM (ptr_mode, base);
@@ -1204,11 +1224,19 @@
TYPE_MODE (pointer_sized_int_node),
orig_addr, ptr_mode);
}
- lab = gen_label_rtx ();
- emit_jump (lab);
- emit_label (lab2);
+ skip_epilogue_lab = gen_label_rtx ();
+ emit_jump (skip_epilogue_lab);
+ emit_label (lab);
}
+ if (!ASAN_FIXED_SHADOW_OFFSET)
+{
+ if (!skip_epilogue_lab)
+ skip_epilogue_lab = gen_label_rtx ();
+ emit_cmp_and_jump_insns (shadow_start, const0_rtx, EQ, NULL_RTX,
VOIDmode,
+ 0, skip_epilogue_lab, PROB_VERY_UNLIKELY);
+}
+
shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
set_mem_alias_set (shadow_mem, asan_shadow_set);
@@ -1245,9 +1273,10 @@
}
do_pending_stack_adjust ();
- if (lab)
-emit_label (lab);
+ if (skip_epilogue_lab)
+emit_label (skip_epilogue_lab);
+
ret = get_insns ();
end_sequence ();
return ret;
Index: gcc/params.def
===
--- gcc/params.def (revision 212896)
+++ gcc/params.def (working copy)
@@ -1081,6 +1081,11 @@
" in function becomes greater or equal than this threshold",
1, 0, INT_MAX)
+DEFPARAM (PARAM_ASAN_FIXED_SHADOW_OFFSET,
+ "asan-fixed-shadow-offset",
+