17.2 Stack Scrubbing

GNAT can generate code to zero-out stack frames used by subprograms.

It can be activated with the Machine_Attribute pragma, on specific subprograms and variables.

function Foo returns Integer;
pragma Machine_Attribute (Foo, "strub");
--  Foo and its callers are modified so as to scrub the stack
--  space used by Foo after it returns.

procedure Bar;
pragma Machine_Attribute (Bar, "strub", "internal");
--  Bar is turned into a wrapper for its original body,
--  and they scrub the stack used by the original body.

Var : Integer;
pragma Machine_Attribute (Var, "strub");
--  Reading from Var in a subprogram enables stack scrubbing
--  of the stack space used by the subprogram.

There are also `-fstrub' command line options to control default settings. For usage and more details on the command line option, and on the strub attribute, see Using the GNU Compiler Collection (GCC).

Note that Ada secondary stacks are not scrubbed. The restriction No_Secondary_Stack avoids their use, and thus their accidental preservation of data that should be scrubbed.

Attributes Access and Unconstrained_Access of variables and constants with strub enabled require types with strub enabled; there is no way to express an access-to-strub type otherwise. Unchecked_Access bypasses this constraint, but the resulting access type designates a non-strub type.

VI : Integer;
XsVI : access Integer := VI'Access; -- Error.
UXsVI : access Integer := VI'Unchecked_Access; -- OK,
-- UXsVI.all does not enable strub in the enclosing subprogram.

type Strub_Int is new Integer;
pragma Machine_Attribute (Strub_Int, "strub");
VSI : Strub_Int;
XsVSI : access Strub_Int := VSI'Access; -- OK.
-- XsVSI.all enables strub in the enclosing subprogram.

Every access-to-subprogram type, renaming, and overriding and overridden dispatching operations that may refer to a subprogram with an attribute-modified interface must be annotated with the same interface-modifying attribute. Access-to-subprogram types can be explicitly converted to different strub modes, as long as they are interface-compatible (i.e., adding or removing at-calls is not allowed). For example, a strub-disabled subprogram can be turned callable through such an explicit conversion:

type TBar is access procedure;

type TBar_Callable is access procedure;
pragma Machine_Attribute (TBar_Callable, "strub", "callable");

Bar_Callable_Ptr : constant TBar_Callable
           := TBar_Callable (TBar'(Bar'Access));

procedure Bar_Callable renames Bar_Callable_Ptr.all;
pragma Machine_Attribute (Bar_Callable, "strub", "callable");

Note that the renaming declaration is expanded to a full subprogram body, it won’t be just an alias. Only if it is inlined will it be as efficient as a call by dereferencing the access-to-subprogram constant Bar_Callable_Ptr.