]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/asan.h
libsanitizer: mid-end: Introduce stack variable handling for HWASAN
[thirdparty/gcc.git] / gcc / asan.h
1 /* AddressSanitizer, a fast memory error detector.
2 Copyright (C) 2011-2020 Free Software Foundation, Inc.
3 Contributed by Kostya Serebryany <kcc@google.com>
4
5 This file is part of GCC.
6
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
10 version.
11
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
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #ifndef TREE_ASAN
22 #define TREE_ASAN
23
24 extern void asan_function_start (void);
25 extern void asan_finish_file (void);
26 extern rtx_insn *asan_emit_stack_protection (rtx, rtx, unsigned int,
27 HOST_WIDE_INT *, tree *, int);
28 extern rtx_insn *asan_emit_allocas_unpoison (rtx, rtx, rtx_insn *);
29 extern bool asan_protect_global (tree, bool ignore_decl_rtl_set_p = false);
30 extern void initialize_sanitizer_builtins (void);
31 extern tree asan_dynamic_init_call (bool);
32 extern bool asan_expand_check_ifn (gimple_stmt_iterator *, bool);
33 extern bool asan_expand_mark_ifn (gimple_stmt_iterator *);
34 extern bool asan_expand_poison_ifn (gimple_stmt_iterator *, bool *,
35 hash_map<tree, tree> &);
36
37 extern void hwasan_record_frame_init ();
38 extern void hwasan_record_stack_var (rtx, rtx, poly_int64, poly_int64);
39 extern void hwasan_emit_prologue ();
40 extern rtx_insn *hwasan_emit_untag_frame (rtx, rtx);
41 extern rtx hwasan_get_frame_extent ();
42 extern rtx hwasan_frame_base ();
43 extern void hwasan_maybe_emit_frame_base_init (void);
44 extern bool stack_vars_base_reg_p (rtx);
45 extern uint8_t hwasan_current_frame_tag ();
46 extern void hwasan_increment_frame_tag ();
47 extern rtx hwasan_truncate_to_tag_size (rtx, rtx);
48 extern void hwasan_finish_file (void);
49 extern bool hwasan_sanitize_p (void);
50 extern bool hwasan_sanitize_stack_p (void);
51 extern bool hwasan_sanitize_allocas_p (void);
52
53 extern gimple_stmt_iterator create_cond_insert_point
54 (gimple_stmt_iterator *, bool, bool, bool, basic_block *, basic_block *);
55
56 /* Alias set for accessing the shadow memory. */
57 extern alias_set_type asan_shadow_set;
58
59 /* Hash set of labels that are either used in a goto, or their address
60 has been taken. */
61 extern hash_set <tree> *asan_used_labels;
62
63 /* Shadow memory is found at
64 (address >> ASAN_SHADOW_SHIFT) + asan_shadow_offset (). */
65 #define ASAN_SHADOW_SHIFT 3
66 #define ASAN_SHADOW_GRANULARITY (1UL << ASAN_SHADOW_SHIFT)
67
68 /* Red zone size, stack and global variables are padded by ASAN_RED_ZONE_SIZE
69 up to 2 * ASAN_RED_ZONE_SIZE - 1 bytes. */
70 #define ASAN_RED_ZONE_SIZE 32
71
72 /* Stack variable use more compact red zones. The size includes also
73 size of variable itself. */
74
75 #define ASAN_MIN_RED_ZONE_SIZE 16
76
77 /* Shadow memory values for stack protection. Left is below protected vars,
78 the first pointer in stack corresponding to that offset contains
79 ASAN_STACK_FRAME_MAGIC word, the second pointer to a string describing
80 the frame. Middle is for padding in between variables, right is
81 above the last protected variable and partial immediately after variables
82 up to ASAN_RED_ZONE_SIZE alignment. */
83 #define ASAN_STACK_MAGIC_LEFT 0xf1
84 #define ASAN_STACK_MAGIC_MIDDLE 0xf2
85 #define ASAN_STACK_MAGIC_RIGHT 0xf3
86 #define ASAN_STACK_MAGIC_USE_AFTER_RET 0xf5
87 #define ASAN_STACK_MAGIC_USE_AFTER_SCOPE 0xf8
88
89 #define ASAN_STACK_FRAME_MAGIC 0x41b58ab3
90 #define ASAN_STACK_RETIRED_MAGIC 0x45e0360e
91
92 #define ASAN_USE_AFTER_SCOPE_ATTRIBUTE "use after scope memory"
93
94 /* NOTE: The values below and the hooks under targetm.memtag define an ABI and
95 are hard-coded to these values in libhwasan, hence they can't be changed
96 independently here. */
97 /* How many bits are used to store a tag in a pointer.
98 The default version uses the entire top byte of a pointer (i.e. 8 bits). */
99 #define HWASAN_TAG_SIZE targetm.memtag.tag_size ()
100 /* Tag Granule of HWASAN shadow stack.
101 This is the size in real memory that each byte in the shadow memory refers
102 to. I.e. if a variable is X bytes long in memory then its tag in shadow
103 memory will span X / HWASAN_TAG_GRANULE_SIZE bytes.
104 Most variables will need to be aligned to this amount since two variables
105 that are neighbors in memory and share a tag granule would need to share the
106 same tag (the shared tag granule can only store one tag). */
107 #define HWASAN_TAG_GRANULE_SIZE targetm.memtag.granule_size ()
108 /* Define the tag for the stack background.
109 This defines what tag the stack pointer will be and hence what tag all
110 variables that are not given special tags are (e.g. spilled registers,
111 and parameters passed on the stack). */
112 #define HWASAN_STACK_BACKGROUND gen_int_mode (0, QImode)
113
114 /* Various flags for Asan builtins. */
115 enum asan_check_flags
116 {
117 ASAN_CHECK_STORE = 1 << 0,
118 ASAN_CHECK_SCALAR_ACCESS = 1 << 1,
119 ASAN_CHECK_NON_ZERO_LEN = 1 << 2,
120 ASAN_CHECK_LAST = 1 << 3
121 };
122
123 /* Flags for Asan check builtins. */
124 #define IFN_ASAN_MARK_FLAGS DEF(POISON), DEF(UNPOISON)
125
126 enum asan_mark_flags
127 {
128 #define DEF(X) ASAN_MARK_##X
129 IFN_ASAN_MARK_FLAGS
130 #undef DEF
131 };
132
133 /* Return true if STMT is ASAN_MARK with FLAG as first argument. */
134 extern bool asan_mark_p (gimple *stmt, enum asan_mark_flags flag);
135
136 /* Return the size of padding needed to insert after a protected
137 decl of SIZE. */
138
139 static inline unsigned int
140 asan_red_zone_size (unsigned int size)
141 {
142 unsigned int c = size & (ASAN_RED_ZONE_SIZE - 1);
143 return c ? 2 * ASAN_RED_ZONE_SIZE - c : ASAN_RED_ZONE_SIZE;
144 }
145
146 /* Return how much a stack variable occupis on a stack
147 including a space for red zone. */
148
149 static inline unsigned HOST_WIDE_INT
150 asan_var_and_redzone_size (unsigned HOST_WIDE_INT size)
151 {
152 if (size <= 4)
153 return 16;
154 else if (size <= 16)
155 return 32;
156 else if (size <= 128)
157 return size + 32;
158 else if (size <= 512)
159 return size + 64;
160 else if (size <= 4096)
161 return size + 128;
162 else
163 return size + 256;
164 }
165
166 extern bool set_asan_shadow_offset (const char *);
167
168 extern bool asan_shadow_offset_set_p ();
169
170 extern void set_sanitized_sections (const char *);
171
172 extern bool asan_sanitize_stack_p (void);
173
174 extern bool asan_sanitize_allocas_p (void);
175
176 extern hash_set<tree> *asan_handled_variables;
177
178 /* Return TRUE if builtin with given FCODE will be intercepted by
179 libasan. */
180
181 static inline bool
182 asan_intercepted_p (enum built_in_function fcode)
183 {
184 return fcode == BUILT_IN_INDEX
185 || fcode == BUILT_IN_MEMCHR
186 || fcode == BUILT_IN_MEMCMP
187 || fcode == BUILT_IN_MEMCPY
188 || fcode == BUILT_IN_MEMMOVE
189 || fcode == BUILT_IN_MEMSET
190 || fcode == BUILT_IN_STRCASECMP
191 || fcode == BUILT_IN_STRCAT
192 || fcode == BUILT_IN_STRCHR
193 || fcode == BUILT_IN_STRCMP
194 || fcode == BUILT_IN_STRCPY
195 || fcode == BUILT_IN_STRDUP
196 || fcode == BUILT_IN_STRLEN
197 || fcode == BUILT_IN_STRNCASECMP
198 || fcode == BUILT_IN_STRNCAT
199 || fcode == BUILT_IN_STRNCMP
200 || fcode == BUILT_IN_STRCSPN
201 || fcode == BUILT_IN_STRPBRK
202 || fcode == BUILT_IN_STRSPN
203 || fcode == BUILT_IN_STRSTR
204 || fcode == BUILT_IN_STRNCPY;
205 }
206
207 /* Return TRUE if we should instrument for use-after-scope sanity checking. */
208
209 static inline bool
210 asan_sanitize_use_after_scope (void)
211 {
212 return (flag_sanitize_address_use_after_scope && asan_sanitize_stack_p ());
213 }
214
215 /* Return true if DECL should be guarded on the stack. */
216
217 static inline bool
218 asan_protect_stack_decl (tree decl)
219 {
220 return DECL_P (decl)
221 && (!DECL_ARTIFICIAL (decl)
222 || (asan_sanitize_use_after_scope () && TREE_ADDRESSABLE (decl)));
223 }
224
225 /* Return true when flag_sanitize & FLAG is non-zero. If FN is non-null,
226 remove all flags mentioned in "no_sanitize" of DECL_ATTRIBUTES. */
227
228 static inline bool
229 sanitize_flags_p (unsigned int flag, const_tree fn = current_function_decl)
230 {
231 unsigned int result_flags = flag_sanitize & flag;
232 if (result_flags == 0)
233 return false;
234
235 if (fn != NULL_TREE)
236 {
237 tree value = lookup_attribute ("no_sanitize", DECL_ATTRIBUTES (fn));
238 if (value)
239 result_flags &= ~tree_to_uhwi (TREE_VALUE (value));
240 }
241
242 return result_flags;
243 }
244
245 #endif /* TREE_ASAN */