How to protect from stack overflow on embedded targets?

How can I make -fstack-check work on stm32f4 or something like that?

Are there others ways to protect from overflows?

If I recall correctly it does work. I think it raises a Storage_Error. It might go straight to the last chance handler instead of unwinding.

Another option is to statically check the stack size. AdaCore has a proprietary tool for this (GNATstack), but you can get the data from GCC and do something yourself. I have someone elses stack analysis tool here that I made a few tweaks to to get it working with the current GCC version: prunt_board_3_software/firmware at master · Prunt3D/prunt_board_3_software · GitHub

Cool! Can you rewrite it in Ada as standalone Alire crate?

A better starting point for that would be to pull mucheckstack out of Muen. I encountered some friction with getting it working, which is why I don’t use it in the above project.

Let me explain why -fstack-check doesn’t work for me. Event on tiny function it wants 4Kb stack, like this:

        @ args = 0, pretend = 0, frame = 40
        @ frame_needed = 0, uses_anonymous_args = 0
        push    {r4, r5, r6, r7, r8, r9, lr}
        vpush.64        {d8}
        sub     sp, sp, #44
        vmov.f32        s16, s0
        sub     r0, sp, #4384  <---------
        subs    r0, r0, #8
        bl      __gnat_stack_check
Tested code
procedure Compute (Value : in out Float) is
   Data : array (1 .. 3) of Float := (Value, others => <>);
begin
   for J in 2 .. Data'Last loop
      Data (J) := Data (J - 1) * Value;
   end loop;
   for Item of reverse Data loop
      Value := Value + Item;
   end loop;
end Compute;

Do I really need 4Kb spare space for 40 byte frame? :roll_eyes:

1 Like

The extra 4kb is so that an exception can be raised with a full backtrace. It’s controlled by STACK_CHECK_PROTECT. Note that this does not accumulate for every frame, it’s just one extra bit of space on top of the stack.