> 3. The GCC estimate itself is also fixable (make account_stack_vars()
> add the redzones it is going to allocate anyway, ~30 lines in
> cfgexpand.cc). That reduces total KASAN stack usage by ~7% for
> +0.35% text and fixes this particular case on its own (704 -> 368),
> so it is probably worth upstreaming. But it is a correctness fix, not a
> cure: it doesn't change the number of frames above 1024/2048 at all.
For what it's worth, the patch looks like this:
diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index 0261f861b..56e335cb2 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -1653,12 +1653,17 @@ expand_stack_vars (bool (*pred) (unsigned),
class stack_vars_data *data)
gcc_assert (known_eq (large_alloc, large_size));
}
-/* Take into account all sizes of partitions and reset DECL_RTLs. */
+/* Take into account all sizes of partitions and reset DECL_RTLs.
+ When the stack is sanitized by ASan, account for the red zones that
+ expand_stack_vars will later allocate around each protected variable,
+ so that the inliner's stack size estimate is not wildly optimistic. */
static poly_uint64
account_stack_vars (void)
{
unsigned si, j, i, n = stack_vars_num;
poly_uint64 size = 0;
+ bool asan_vars = false;
+ bool asan_p = asan_sanitize_stack_p ();
for (si = 0; si < n; ++si)
{
@@ -1668,10 +1673,32 @@ account_stack_vars (void)
if (stack_vars[i].representative != i)
continue;
- size += stack_vars[i].size;
+ poly_uint64 vsize = stack_vars[i].size;
+ unsigned HOST_WIDE_INT csize;
+ if (asan_p
+ && vsize.is_constant (&csize)
+ && stack_vars[i].alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT)
+ {
+ bool prot = false;
+ for (j = i; j != EOC; j = stack_vars[j].next)
+ if (asan_protect_stack_decl (stack_vars[j].decl))
+ {
+ prot = true;
+ break;
+ }
+ if (prot)
+ {
+ vsize = asan_var_and_redzone_size (csize);
+ asan_vars = true;
+ }
+ }
+ size += vsize;
for (j = i; j != EOC; j = stack_vars[j].next)
set_rtl (stack_vars[j].decl, NULL);
}
+ /* Leading red zone of the ASan protected frame region. */
+ if (asan_vars)
+ size += ASAN_RED_ZONE_SIZE;
return size;
}