1 /* Stack scrubbing infrastructure
2 Copyright (C) 2021-2023 Free Software Foundation, Inc.
3 Contributed by Alexandre Oliva <oliva@adacore.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
28 #include "coretypes.h"
30 #include "libgcc_tm.h"
33 #if ! STACK_GROWS_DOWNWARD
39 #define ATTRIBUTE_STRUB_CALLABLE __attribute__ ((__strub__ ("callable")))
41 /* Enter a stack scrubbing context, initializing the watermark to the caller's
43 void ATTRIBUTE_STRUB_CALLABLE
44 __strub_enter (void **watermark
)
46 *watermark
= __builtin_frame_address (0);
49 /* Update the watermark within a stack scrubbing context with the current stack
51 void ATTRIBUTE_STRUB_CALLABLE
52 __strub_update (void **watermark
)
54 void *sp
= __builtin_frame_address (0);
56 if (sp TOPS
*watermark
)
60 #if TARGET_STRUB_USE_DYNAMIC_ARRAY && ! defined TARGET_STRUB_MAY_USE_MEMSET
61 # define TARGET_STRUB_MAY_USE_MEMSET 1
64 #if defined __x86_64__ && __OPTIMIZE__
65 # define TARGET_STRUB_DISABLE_RED_ZONE \
66 /* __attribute__ ((__target__ ("no-red-zone"))) // not needed when optimizing */
67 #elif !defined RED_ZONE_SIZE || defined __i386__
68 # define TARGET_STRUB_DISABLE_RED_ZONE
71 #ifndef TARGET_STRUB_DISABLE_RED_ZONE
72 /* Dummy function, called to force the caller to not be a leaf function, so
73 that it can't use the red zone. */
74 static void ATTRIBUTE_STRUB_CALLABLE
75 __attribute__ ((__noinline__
, __noipa__
))
76 __strub_dummy_force_no_leaf (void)
81 /* Leave a stack scrubbing context, clearing the stack between its top and
83 void ATTRIBUTE_STRUB_CALLABLE
84 #if ! TARGET_STRUB_MAY_USE_MEMSET
85 __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns")))
87 #ifdef TARGET_STRUB_DISABLE_RED_ZONE
88 TARGET_STRUB_DISABLE_RED_ZONE
90 __strub_leave (void **mark
)
92 void *sp
= __builtin_stack_address ();
95 #if ! STACK_GROWS_DOWNWARD
96 base
= sp
; /* ??? Do we need an offset here? */
100 end
= sp
; /* ??? Does any platform require an offset here? */
106 #if TARGET_STRUB_USE_DYNAMIC_ARRAY
107 /* Compute the length without assuming the pointers are both sufficiently
108 aligned. They should be, but pointer differences expected to be exact may
109 yield unexpected results when the assumption doesn't hold. Given the
110 potential security implications, compute the length without that
111 expectation. If the pointers are misaligned, we may leave a partial
112 unscrubbed word behind. */
113 ptrdiff_t len
= ((char *)end
- (char *)base
) / sizeof (void *);
114 /* Allocate a dynamically-sized array covering the desired range, so that we
115 can safely call memset on it. */
119 #elifndef TARGET_STRUB_DISABLE_RED_ZONE
120 /* Prevent the use of the red zone, by making this function non-leaf through
121 an unreachable call that, because of the asm stmt, the compiler will
122 consider reachable. */
123 asm goto ("" : : : : no_leaf
);
127 __strub_dummy_force_no_leaf ();
132 /* ldist may turn these loops into a memset (thus the conditional
133 -fno-tree-loop-distribute-patterns above). Without the dynamic array
134 above, that call would likely be unsafe: possibly tail-called, and likely
135 scribbling over its own stack frame. */
136 #if ! STACK_GROWS_DOWNWARD
140 /* Make sure the stack overwrites are not optimized away. */
141 asm ("" : : "m" (end
[0]));
146 /* Make sure the stack overwrites are not optimized away. */
147 asm ("" : : "m" (base
[0]));