aboutsummaryrefslogtreecommitdiff
path: root/gcc/asan.cc
diff options
context:
space:
mode:
authorKito Cheng <kito.cheng@sifive.com>2024-11-15 12:14:54 +0800
committerKito Cheng <kito.cheng@sifive.com>2024-11-25 06:34:33 +0000
commit63c68752768fd6d67c695e09c85e0e1ca59cd6d4 (patch)
treedb22e5ec77d788752b497e3f8246f8a66096a2ec /gcc/asan.cc
parente4f4b2dc08b6720acab563db48fd4b0427d2b0c6 (diff)
downloadgcc-63c68752768fd6d67c695e09c85e0e1ca59cd6d4.zip
gcc-63c68752768fd6d67c695e09c85e0e1ca59cd6d4.tar.gz
gcc-63c68752768fd6d67c695e09c85e0e1ca59cd6d4.tar.bz2
asan: Support dynamic shadow offset
AddressSanitizer has supported dynamic shadow offsets since 2016[1], but GCC hasn't implemented this yet because targets using dynamic shadow offsets, such as Fuchsia and iOS, are mostly unsupported in GCC. However, RISC-V 64 switched to dynamic shadow offsets this year[2] because virtual memory space support varies across different RISC-V cores, such as Sv39, Sv48, and Sv57. We realized that the best way to handle this situation is by using a dynamic shadow offset to obtain the offset at runtime. We introduce a new target hook, TARGET_ASAN_DYNAMIC_SHADOW_OFFSET_P, to determine if the target is using a dynamic shadow offset, so this change won't affect the static offset path. Additionally, TARGET_ASAN_SHADOW_OFFSET continues to work even if TARGET_ASAN_DYNAMIC_SHADOW_OFFSET_P is non-zero, ensuring that KASAN functions as expected. This patch set has been verified on the Banana Pi F3, currently one of the most popular RISC-V development boards. All AddressSanitizer-related tests passed without introducing new regressions. It was also verified on AArch64 and x86_64 with no regressions in AddressSanitizer. [1] https://github.com/llvm/llvm-project/commit/130a190bf08a3d955d9db24dac936159dc049e12 [2] https://github.com/llvm/llvm-project/commit/da0c8b275564f814a53a5c19497669ae2d99538d gcc/ChangeLog: * asan.cc (asan_dynamic_shadow_offset_p): New. (asan_shadow_memory_dynamic_address): New. (asan_local_shadow_memory_dynamic_address): New. (get_asan_shadow_memory_dynamic_address_decl): New. (asan_maybe_insert_dynamic_shadow_at_function_entry): New. (asan_emit_stack_protection): Support dynamic shadow offset. (build_shadow_mem_access): Ditto. * asan.h (asan_maybe_insert_dynamic_shadow_at_function_entry): New. * doc/tm.texi (TARGET_ASAN_DYNAMIC_SHADOW_OFFSET_P): New. * doc/tm.texi.in (TARGET_ASAN_DYNAMIC_SHADOW_OFFSET_P): Ditto. * sanopt.cc (pass_sanopt::execute): Handle dynamic shadow offset. * target.def (asan_dynamic_shadow_offset_p): New. * toplev.cc (process_options): Handle dynamic shadow offset.
Diffstat (limited to 'gcc/asan.cc')
-rw-r--r--gcc/asan.cc80
1 files changed, 75 insertions, 5 deletions
diff --git a/gcc/asan.cc b/gcc/asan.cc
index 087595b..a54ecf2 100644
--- a/gcc/asan.cc
+++ b/gcc/asan.cc
@@ -457,6 +457,13 @@ asan_shadow_offset ()
return asan_shadow_offset_value;
}
+static bool
+asan_dynamic_shadow_offset_p ()
+{
+ return (asan_shadow_offset_value == 0)
+ && targetm.asan_dynamic_shadow_offset_p ();
+}
+
/* Returns Asan shadow offset has been set. */
bool
asan_shadow_offset_set_p ()
@@ -473,6 +480,55 @@ static GTY(()) tree shadow_ptr_types[3];
/* Decl for __asan_option_detect_stack_use_after_return. */
static GTY(()) tree asan_detect_stack_use_after_return;
+static GTY (()) tree asan_shadow_memory_dynamic_address;
+
+/* Local copy for the asan_shadow_memory_dynamic_address within the
+ function. */
+static GTY (()) tree asan_local_shadow_memory_dynamic_address;
+
+static tree
+get_asan_shadow_memory_dynamic_address_decl ()
+{
+ if (asan_shadow_memory_dynamic_address == NULL_TREE)
+ {
+ tree id, decl;
+ id = get_identifier ("__asan_shadow_memory_dynamic_address");
+ decl
+ = build_decl (BUILTINS_LOCATION, VAR_DECL, id, pointer_sized_int_node);
+ SET_DECL_ASSEMBLER_NAME (decl, id);
+ TREE_ADDRESSABLE (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+ DECL_EXTERNAL (decl) = 1;
+ TREE_STATIC (decl) = 1;
+ TREE_PUBLIC (decl) = 1;
+ TREE_USED (decl) = 1;
+ asan_shadow_memory_dynamic_address = decl;
+ }
+
+ return asan_shadow_memory_dynamic_address;
+}
+
+void
+asan_maybe_insert_dynamic_shadow_at_function_entry (function *fun)
+{
+ asan_local_shadow_memory_dynamic_address = NULL_TREE;
+ if (!asan_dynamic_shadow_offset_p ())
+ return;
+
+ gimple *g;
+
+ tree lhs = create_tmp_var (pointer_sized_int_node,
+ "__local_asan_shadow_memory_dynamic_address");
+
+ g = gimple_build_assign (lhs, get_asan_shadow_memory_dynamic_address_decl ());
+ gimple_set_location (g, fun->function_start_locus);
+ edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ gsi_insert_on_edge_immediate (e, g);
+
+ asan_local_shadow_memory_dynamic_address = lhs;
+}
+
/* Hashtable support for memory references used by gimple
statements. */
@@ -2033,10 +2089,21 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
shadow_base = expand_binop (Pmode, lshr_optab, base,
gen_int_shift_amount (Pmode, ASAN_SHADOW_SHIFT),
NULL_RTX, 1, OPTAB_DIRECT);
- shadow_base
- = plus_constant (Pmode, shadow_base,
- asan_shadow_offset ()
- + (base_align_bias >> ASAN_SHADOW_SHIFT));
+ if (asan_dynamic_shadow_offset_p ())
+ {
+ ret = expand_normal (get_asan_shadow_memory_dynamic_address_decl ());
+ shadow_base
+ = expand_simple_binop (Pmode, PLUS, shadow_base, ret, NULL_RTX,
+ /* unsignedp = */ 1, OPTAB_WIDEN);
+ shadow_base = plus_constant (Pmode, shadow_base,
+ (base_align_bias >> ASAN_SHADOW_SHIFT));
+ }
+ else
+ {
+ shadow_base = plus_constant (Pmode, shadow_base,
+ asan_shadow_offset ()
+ + (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);
@@ -2558,7 +2625,10 @@ build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
gimple_set_location (g, location);
gsi_insert_after (gsi, g, GSI_NEW_STMT);
- t = build_int_cst (uintptr_type, asan_shadow_offset ());
+ if (asan_dynamic_shadow_offset_p ())
+ t = asan_local_shadow_memory_dynamic_address;
+ else
+ t = build_int_cst (uintptr_type, asan_shadow_offset ());
g = gimple_build_assign (make_ssa_name (uintptr_type), PLUS_EXPR,
gimple_assign_lhs (g), t);
gimple_set_location (g, location);