@@ -75,6 +75,41 @@ extern hash_set <tree> *asan_used_labels;
#define ASAN_USE_AFTER_SCOPE_ATTRIBUTE "use after scope memory"
+/* NOTE: The macros below are hard-coded to these values in libhwasan, and
+ hence can't be changed independently here. */
+/* How many bits are used to store a tag in a pointer.
+ For aarch64 MTE we have 4 bits per colour.
+ AArch64 has a Top-Byte-Ignore feature that allows the use of the top byte of
+ pointers for storing information, HWASAN can use that entire top byte if
+ required.
+ If changing this value, be careful of the predicates/constraints on the
+ addtag<mode>4 patterns in the backend. */
+#define HWASAN_TAG_SIZE 4
+/* Tag Granule of HWASAN shadow stack.
+ This is the size in real memory that each byte in the shadow memory refers
+ to. I.e. if a variable is X bytes long in memory then it's colour in shadow
+ memory will span X / HWASAN_TAG_GRANULE_SIZE bytes.
+ On top of this, most variables will need to be aligned to this amount since
+ two variables that are neighbours in memory and share a tag granule would
+ need to share the same colour (as the shared tag granule can only store one
+ colour). */
+#define HWASAN_TAG_GRANULE_SIZE (1ULL << HWASAN_TAG_SIZE)
+/* How many bits to shift in order to access the tag bits.
+ This approach assumes that the tag is stored in the top N bits of a pointer,
+ and hence that shifting a known amount will leave just the tag bits. */
+#define HWASAN_SHIFT 56
+#define HWASAN_SHIFT_RTX const_int_rtx[MAX_SAVED_CONST_INT + HWASAN_SHIFT]
+/* Define the tag for the stack background.
+ NOTE: Having a background colour of zero is hard-coded in the runtime
+ library, so we can't really change this.
+ This defines what colour the stack pointer will be and hence what colour all
+ uncoloured parts of the stack are (e.g. spilled registers).
+ It also provides a tag for stack allocation to avoid, since an object stored
+ on the stack will want to have a different colour to the background stack to
+ ensure things like the return address etc can't be affected by accesses
+ through pointer to a user-object. */
+#define HWASAN_STACK_BACKGROUND 0
+
/* Various flags for Asan builtins. */
enum asan_check_flags
{
@@ -372,7 +372,14 @@ align_local_variable (tree decl)
align = LOCAL_DECL_ALIGNMENT (decl);
SET_DECL_ALIGN (decl, align);
}
- return align / BITS_PER_UNIT;
+
+ unsigned int ret_align = align / BITS_PER_UNIT;
+
+ if (memory_tagging_p ())
+ ret_align = ret_align > HWASAN_TAG_GRANULE_SIZE
+ ? ret_align
+ : HWASAN_TAG_GRANULE_SIZE;
+ return ret_align;
}
/* Align given offset BASE with ALIGN. Truncate up if ALIGN_UP is true,
@@ -1117,6 +1124,29 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
alignb = stack_vars[i].alignb;
if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT)
{
+ if (memory_tagging_p ())
+ {
+ /* Allocate zero bytes to take advantage of the
+ alloc_stack_frame_space logic of ensuring the stack is aligned
+ despite having poly_int64's to deal with.
+
+ There must be no tag granule "shared" between different
+ objects. This means that no HWASAN_TAG_GRANULE_SIZE byte
+ chunk can have more than one object in it.
+
+ We ensure this by forcing the end of the last bit of data to
+ be aligned to HWASAN_TAG_GRANULE_SIZE bytes here, and setting
+ the start of each variable to be aligned to
+ HWASAN_TAG_GRANULE_SIZE bytes in `align_local_variable`.
+
+ We can't align just one of the start or end, since there are
+ untagged things stored on the stack that we have no control on
+ the alignment (e.g. function parameters which must conform to
+ ABI requirements) and these can't share a tag granule with a
+ tagged variable. */
+ gcc_assert (stack_vars[i].alignb >= HWASAN_TAG_GRANULE_SIZE);
+ alloc_stack_frame_space (0, HWASAN_TAG_GRANULE_SIZE);
+ }
base = virtual_stack_vars_rtx;
/* ASAN description strings don't yet have a syntax for expressing
polynomial offsets. */
@@ -1545,8 +1575,11 @@ defer_stack_allocation (tree var, bool toplevel)
/* If stack protection is enabled, *all* stack variables must be deferred,
so that we can re-order the strings to the top of the frame.
- Similarly for Address Sanitizer. */
- if (flag_stack_protect || asan_sanitize_stack_p ())
+ Similarly for Address Sanitizer.
+ When memory tagging we defer all stack variables so we can handle them in
+ one place (handle here meaning ensure aligned and record information on
+ its position on the stack). */
+ if (flag_stack_protect || asan_sanitize_stack_p () || memory_tagging_p ())
return true;
unsigned int align = TREE_CODE (var) == SSA_NAME