111
|
1 /* AddressSanitizer, a fast memory error detector.
|
131
|
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
|
111
|
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
|
|
22 #include "config.h"
|
|
23 #include "system.h"
|
|
24 #include "coretypes.h"
|
|
25 #include "backend.h"
|
|
26 #include "target.h"
|
|
27 #include "rtl.h"
|
|
28 #include "tree.h"
|
|
29 #include "gimple.h"
|
|
30 #include "cfghooks.h"
|
|
31 #include "alloc-pool.h"
|
|
32 #include "tree-pass.h"
|
|
33 #include "memmodel.h"
|
|
34 #include "tm_p.h"
|
|
35 #include "ssa.h"
|
|
36 #include "stringpool.h"
|
|
37 #include "tree-ssanames.h"
|
|
38 #include "optabs.h"
|
|
39 #include "emit-rtl.h"
|
|
40 #include "cgraph.h"
|
|
41 #include "gimple-pretty-print.h"
|
|
42 #include "alias.h"
|
|
43 #include "fold-const.h"
|
|
44 #include "cfganal.h"
|
|
45 #include "gimplify.h"
|
|
46 #include "gimple-iterator.h"
|
|
47 #include "varasm.h"
|
|
48 #include "stor-layout.h"
|
|
49 #include "tree-iterator.h"
|
|
50 #include "stringpool.h"
|
|
51 #include "attribs.h"
|
|
52 #include "asan.h"
|
|
53 #include "dojump.h"
|
|
54 #include "explow.h"
|
|
55 #include "expr.h"
|
|
56 #include "output.h"
|
|
57 #include "langhooks.h"
|
|
58 #include "cfgloop.h"
|
|
59 #include "gimple-builder.h"
|
|
60 #include "gimple-fold.h"
|
|
61 #include "ubsan.h"
|
|
62 #include "params.h"
|
|
63 #include "builtins.h"
|
|
64 #include "fnmatch.h"
|
|
65 #include "tree-inline.h"
|
|
66
|
|
67 /* AddressSanitizer finds out-of-bounds and use-after-free bugs
|
|
68 with <2x slowdown on average.
|
|
69
|
|
70 The tool consists of two parts:
|
|
71 instrumentation module (this file) and a run-time library.
|
|
72 The instrumentation module adds a run-time check before every memory insn.
|
|
73 For a 8- or 16- byte load accessing address X:
|
|
74 ShadowAddr = (X >> 3) + Offset
|
|
75 ShadowValue = *(char*)ShadowAddr; // *(short*) for 16-byte access.
|
|
76 if (ShadowValue)
|
|
77 __asan_report_load8(X);
|
|
78 For a load of N bytes (N=1, 2 or 4) from address X:
|
|
79 ShadowAddr = (X >> 3) + Offset
|
|
80 ShadowValue = *(char*)ShadowAddr;
|
|
81 if (ShadowValue)
|
|
82 if ((X & 7) + N - 1 > ShadowValue)
|
|
83 __asan_report_loadN(X);
|
|
84 Stores are instrumented similarly, but using __asan_report_storeN functions.
|
|
85 A call too __asan_init_vN() is inserted to the list of module CTORs.
|
|
86 N is the version number of the AddressSanitizer API. The changes between the
|
|
87 API versions are listed in libsanitizer/asan/asan_interface_internal.h.
|
|
88
|
|
89 The run-time library redefines malloc (so that redzone are inserted around
|
|
90 the allocated memory) and free (so that reuse of free-ed memory is delayed),
|
|
91 provides __asan_report* and __asan_init_vN functions.
|
|
92
|
|
93 Read more:
|
|
94 http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
|
|
95
|
|
96 The current implementation supports detection of out-of-bounds and
|
|
97 use-after-free in the heap, on the stack and for global variables.
|
|
98
|
|
99 [Protection of stack variables]
|
|
100
|
|
101 To understand how detection of out-of-bounds and use-after-free works
|
|
102 for stack variables, lets look at this example on x86_64 where the
|
|
103 stack grows downward:
|
|
104
|
|
105 int
|
|
106 foo ()
|
|
107 {
|
|
108 char a[23] = {0};
|
|
109 int b[2] = {0};
|
|
110
|
|
111 a[5] = 1;
|
|
112 b[1] = 2;
|
|
113
|
|
114 return a[5] + b[1];
|
|
115 }
|
|
116
|
|
117 For this function, the stack protected by asan will be organized as
|
|
118 follows, from the top of the stack to the bottom:
|
|
119
|
|
120 Slot 1/ [red zone of 32 bytes called 'RIGHT RedZone']
|
|
121
|
|
122 Slot 2/ [8 bytes of red zone, that adds up to the space of 'a' to make
|
|
123 the next slot be 32 bytes aligned; this one is called Partial
|
|
124 Redzone; this 32 bytes alignment is an asan constraint]
|
|
125
|
|
126 Slot 3/ [24 bytes for variable 'a']
|
|
127
|
|
128 Slot 4/ [red zone of 32 bytes called 'Middle RedZone']
|
|
129
|
|
130 Slot 5/ [24 bytes of Partial Red Zone (similar to slot 2]
|
|
131
|
|
132 Slot 6/ [8 bytes for variable 'b']
|
|
133
|
|
134 Slot 7/ [32 bytes of Red Zone at the bottom of the stack, called
|
|
135 'LEFT RedZone']
|
|
136
|
|
137 The 32 bytes of LEFT red zone at the bottom of the stack can be
|
|
138 decomposed as such:
|
|
139
|
|
140 1/ The first 8 bytes contain a magical asan number that is always
|
|
141 0x41B58AB3.
|
|
142
|
|
143 2/ The following 8 bytes contains a pointer to a string (to be
|
|
144 parsed at runtime by the runtime asan library), which format is
|
|
145 the following:
|
|
146
|
|
147 "<function-name> <space> <num-of-variables-on-the-stack>
|
|
148 (<32-bytes-aligned-offset-in-bytes-of-variable> <space>
|
|
149 <length-of-var-in-bytes> ){n} "
|
|
150
|
|
151 where '(...){n}' means the content inside the parenthesis occurs 'n'
|
|
152 times, with 'n' being the number of variables on the stack.
|
|
153
|
|
154 3/ The following 8 bytes contain the PC of the current function which
|
|
155 will be used by the run-time library to print an error message.
|
|
156
|
|
157 4/ The following 8 bytes are reserved for internal use by the run-time.
|
|
158
|
|
159 The shadow memory for that stack layout is going to look like this:
|
|
160
|
|
161 - content of shadow memory 8 bytes for slot 7: 0xF1F1F1F1.
|
|
162 The F1 byte pattern is a magic number called
|
|
163 ASAN_STACK_MAGIC_LEFT and is a way for the runtime to know that
|
|
164 the memory for that shadow byte is part of a the LEFT red zone
|
|
165 intended to seat at the bottom of the variables on the stack.
|
|
166
|
|
167 - content of shadow memory 8 bytes for slots 6 and 5:
|
|
168 0xF4F4F400. The F4 byte pattern is a magic number
|
|
169 called ASAN_STACK_MAGIC_PARTIAL. It flags the fact that the
|
|
170 memory region for this shadow byte is a PARTIAL red zone
|
|
171 intended to pad a variable A, so that the slot following
|
|
172 {A,padding} is 32 bytes aligned.
|
|
173
|
|
174 Note that the fact that the least significant byte of this
|
|
175 shadow memory content is 00 means that 8 bytes of its
|
|
176 corresponding memory (which corresponds to the memory of
|
|
177 variable 'b') is addressable.
|
|
178
|
|
179 - content of shadow memory 8 bytes for slot 4: 0xF2F2F2F2.
|
|
180 The F2 byte pattern is a magic number called
|
|
181 ASAN_STACK_MAGIC_MIDDLE. It flags the fact that the memory
|
|
182 region for this shadow byte is a MIDDLE red zone intended to
|
|
183 seat between two 32 aligned slots of {variable,padding}.
|
|
184
|
|
185 - content of shadow memory 8 bytes for slot 3 and 2:
|
|
186 0xF4000000. This represents is the concatenation of
|
|
187 variable 'a' and the partial red zone following it, like what we
|
|
188 had for variable 'b'. The least significant 3 bytes being 00
|
|
189 means that the 3 bytes of variable 'a' are addressable.
|
|
190
|
|
191 - content of shadow memory 8 bytes for slot 1: 0xF3F3F3F3.
|
|
192 The F3 byte pattern is a magic number called
|
|
193 ASAN_STACK_MAGIC_RIGHT. It flags the fact that the memory
|
|
194 region for this shadow byte is a RIGHT red zone intended to seat
|
|
195 at the top of the variables of the stack.
|
|
196
|
|
197 Note that the real variable layout is done in expand_used_vars in
|
|
198 cfgexpand.c. As far as Address Sanitizer is concerned, it lays out
|
|
199 stack variables as well as the different red zones, emits some
|
|
200 prologue code to populate the shadow memory as to poison (mark as
|
|
201 non-accessible) the regions of the red zones and mark the regions of
|
|
202 stack variables as accessible, and emit some epilogue code to
|
|
203 un-poison (mark as accessible) the regions of red zones right before
|
|
204 the function exits.
|
|
205
|
|
206 [Protection of global variables]
|
|
207
|
|
208 The basic idea is to insert a red zone between two global variables
|
|
209 and install a constructor function that calls the asan runtime to do
|
|
210 the populating of the relevant shadow memory regions at load time.
|
|
211
|
|
212 So the global variables are laid out as to insert a red zone between
|
|
213 them. The size of the red zones is so that each variable starts on a
|
|
214 32 bytes boundary.
|
|
215
|
|
216 Then a constructor function is installed so that, for each global
|
|
217 variable, it calls the runtime asan library function
|
|
218 __asan_register_globals_with an instance of this type:
|
|
219
|
|
220 struct __asan_global
|
|
221 {
|
|
222 // Address of the beginning of the global variable.
|
|
223 const void *__beg;
|
|
224
|
|
225 // Initial size of the global variable.
|
|
226 uptr __size;
|
|
227
|
|
228 // Size of the global variable + size of the red zone. This
|
|
229 // size is 32 bytes aligned.
|
|
230 uptr __size_with_redzone;
|
|
231
|
|
232 // Name of the global variable.
|
|
233 const void *__name;
|
|
234
|
|
235 // Name of the module where the global variable is declared.
|
|
236 const void *__module_name;
|
|
237
|
|
238 // 1 if it has dynamic initialization, 0 otherwise.
|
|
239 uptr __has_dynamic_init;
|
|
240
|
|
241 // A pointer to struct that contains source location, could be NULL.
|
|
242 __asan_global_source_location *__location;
|
|
243 }
|
|
244
|
|
245 A destructor function that calls the runtime asan library function
|
|
246 _asan_unregister_globals is also installed. */
|
|
247
|
|
248 static unsigned HOST_WIDE_INT asan_shadow_offset_value;
|
|
249 static bool asan_shadow_offset_computed;
|
|
250 static vec<char *> sanitized_sections;
|
|
251 static tree last_alloca_addr;
|
|
252
|
|
253 /* Set of variable declarations that are going to be guarded by
|
|
254 use-after-scope sanitizer. */
|
|
255
|
131
|
256 hash_set<tree> *asan_handled_variables = NULL;
|
111
|
257
|
|
258 hash_set <tree> *asan_used_labels = NULL;
|
|
259
|
|
260 /* Sets shadow offset to value in string VAL. */
|
|
261
|
|
262 bool
|
|
263 set_asan_shadow_offset (const char *val)
|
|
264 {
|
|
265 char *endp;
|
|
266
|
|
267 errno = 0;
|
|
268 #ifdef HAVE_LONG_LONG
|
|
269 asan_shadow_offset_value = strtoull (val, &endp, 0);
|
|
270 #else
|
|
271 asan_shadow_offset_value = strtoul (val, &endp, 0);
|
|
272 #endif
|
|
273 if (!(*val != '\0' && *endp == '\0' && errno == 0))
|
|
274 return false;
|
|
275
|
|
276 asan_shadow_offset_computed = true;
|
|
277
|
|
278 return true;
|
|
279 }
|
|
280
|
|
281 /* Set list of user-defined sections that need to be sanitized. */
|
|
282
|
|
283 void
|
|
284 set_sanitized_sections (const char *sections)
|
|
285 {
|
|
286 char *pat;
|
|
287 unsigned i;
|
|
288 FOR_EACH_VEC_ELT (sanitized_sections, i, pat)
|
|
289 free (pat);
|
|
290 sanitized_sections.truncate (0);
|
|
291
|
|
292 for (const char *s = sections; *s; )
|
|
293 {
|
|
294 const char *end;
|
|
295 for (end = s; *end && *end != ','; ++end);
|
|
296 size_t len = end - s;
|
|
297 sanitized_sections.safe_push (xstrndup (s, len));
|
|
298 s = *end ? end + 1 : end;
|
|
299 }
|
|
300 }
|
|
301
|
|
302 bool
|
|
303 asan_mark_p (gimple *stmt, enum asan_mark_flags flag)
|
|
304 {
|
|
305 return (gimple_call_internal_p (stmt, IFN_ASAN_MARK)
|
|
306 && tree_to_uhwi (gimple_call_arg (stmt, 0)) == flag);
|
|
307 }
|
|
308
|
|
309 bool
|
|
310 asan_sanitize_stack_p (void)
|
|
311 {
|
|
312 return (sanitize_flags_p (SANITIZE_ADDRESS) && ASAN_STACK);
|
|
313 }
|
|
314
|
|
315 bool
|
|
316 asan_sanitize_allocas_p (void)
|
|
317 {
|
|
318 return (asan_sanitize_stack_p () && ASAN_PROTECT_ALLOCAS);
|
|
319 }
|
|
320
|
|
321 /* Checks whether section SEC should be sanitized. */
|
|
322
|
|
323 static bool
|
|
324 section_sanitized_p (const char *sec)
|
|
325 {
|
|
326 char *pat;
|
|
327 unsigned i;
|
|
328 FOR_EACH_VEC_ELT (sanitized_sections, i, pat)
|
|
329 if (fnmatch (pat, sec, FNM_PERIOD) == 0)
|
|
330 return true;
|
|
331 return false;
|
|
332 }
|
|
333
|
|
334 /* Returns Asan shadow offset. */
|
|
335
|
|
336 static unsigned HOST_WIDE_INT
|
|
337 asan_shadow_offset ()
|
|
338 {
|
|
339 if (!asan_shadow_offset_computed)
|
|
340 {
|
|
341 asan_shadow_offset_computed = true;
|
|
342 asan_shadow_offset_value = targetm.asan_shadow_offset ();
|
|
343 }
|
|
344 return asan_shadow_offset_value;
|
|
345 }
|
|
346
|
|
347 alias_set_type asan_shadow_set = -1;
|
|
348
|
|
349 /* Pointer types to 1, 2 or 4 byte integers in shadow memory. A separate
|
|
350 alias set is used for all shadow memory accesses. */
|
|
351 static GTY(()) tree shadow_ptr_types[3];
|
|
352
|
|
353 /* Decl for __asan_option_detect_stack_use_after_return. */
|
|
354 static GTY(()) tree asan_detect_stack_use_after_return;
|
|
355
|
|
356 /* Hashtable support for memory references used by gimple
|
|
357 statements. */
|
|
358
|
|
359 /* This type represents a reference to a memory region. */
|
|
360 struct asan_mem_ref
|
|
361 {
|
|
362 /* The expression of the beginning of the memory region. */
|
|
363 tree start;
|
|
364
|
|
365 /* The size of the access. */
|
|
366 HOST_WIDE_INT access_size;
|
|
367 };
|
|
368
|
|
369 object_allocator <asan_mem_ref> asan_mem_ref_pool ("asan_mem_ref");
|
|
370
|
|
371 /* Initializes an instance of asan_mem_ref. */
|
|
372
|
|
373 static void
|
|
374 asan_mem_ref_init (asan_mem_ref *ref, tree start, HOST_WIDE_INT access_size)
|
|
375 {
|
|
376 ref->start = start;
|
|
377 ref->access_size = access_size;
|
|
378 }
|
|
379
|
|
380 /* Allocates memory for an instance of asan_mem_ref into the memory
|
|
381 pool returned by asan_mem_ref_get_alloc_pool and initialize it.
|
|
382 START is the address of (or the expression pointing to) the
|
|
383 beginning of memory reference. ACCESS_SIZE is the size of the
|
|
384 access to the referenced memory. */
|
|
385
|
|
386 static asan_mem_ref*
|
|
387 asan_mem_ref_new (tree start, HOST_WIDE_INT access_size)
|
|
388 {
|
|
389 asan_mem_ref *ref = asan_mem_ref_pool.allocate ();
|
|
390
|
|
391 asan_mem_ref_init (ref, start, access_size);
|
|
392 return ref;
|
|
393 }
|
|
394
|
|
395 /* This builds and returns a pointer to the end of the memory region
|
|
396 that starts at START and of length LEN. */
|
|
397
|
|
398 tree
|
|
399 asan_mem_ref_get_end (tree start, tree len)
|
|
400 {
|
|
401 if (len == NULL_TREE || integer_zerop (len))
|
|
402 return start;
|
|
403
|
|
404 if (!ptrofftype_p (len))
|
|
405 len = convert_to_ptrofftype (len);
|
|
406
|
|
407 return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (start), start, len);
|
|
408 }
|
|
409
|
|
410 /* Return a tree expression that represents the end of the referenced
|
|
411 memory region. Beware that this function can actually build a new
|
|
412 tree expression. */
|
|
413
|
|
414 tree
|
|
415 asan_mem_ref_get_end (const asan_mem_ref *ref, tree len)
|
|
416 {
|
|
417 return asan_mem_ref_get_end (ref->start, len);
|
|
418 }
|
|
419
|
|
420 struct asan_mem_ref_hasher : nofree_ptr_hash <asan_mem_ref>
|
|
421 {
|
|
422 static inline hashval_t hash (const asan_mem_ref *);
|
|
423 static inline bool equal (const asan_mem_ref *, const asan_mem_ref *);
|
|
424 };
|
|
425
|
|
426 /* Hash a memory reference. */
|
|
427
|
|
428 inline hashval_t
|
|
429 asan_mem_ref_hasher::hash (const asan_mem_ref *mem_ref)
|
|
430 {
|
|
431 return iterative_hash_expr (mem_ref->start, 0);
|
|
432 }
|
|
433
|
|
434 /* Compare two memory references. We accept the length of either
|
|
435 memory references to be NULL_TREE. */
|
|
436
|
|
437 inline bool
|
|
438 asan_mem_ref_hasher::equal (const asan_mem_ref *m1,
|
|
439 const asan_mem_ref *m2)
|
|
440 {
|
|
441 return operand_equal_p (m1->start, m2->start, 0);
|
|
442 }
|
|
443
|
|
444 static hash_table<asan_mem_ref_hasher> *asan_mem_ref_ht;
|
|
445
|
|
446 /* Returns a reference to the hash table containing memory references.
|
|
447 This function ensures that the hash table is created. Note that
|
|
448 this hash table is updated by the function
|
|
449 update_mem_ref_hash_table. */
|
|
450
|
|
451 static hash_table<asan_mem_ref_hasher> *
|
|
452 get_mem_ref_hash_table ()
|
|
453 {
|
|
454 if (!asan_mem_ref_ht)
|
|
455 asan_mem_ref_ht = new hash_table<asan_mem_ref_hasher> (10);
|
|
456
|
|
457 return asan_mem_ref_ht;
|
|
458 }
|
|
459
|
|
460 /* Clear all entries from the memory references hash table. */
|
|
461
|
|
462 static void
|
|
463 empty_mem_ref_hash_table ()
|
|
464 {
|
|
465 if (asan_mem_ref_ht)
|
|
466 asan_mem_ref_ht->empty ();
|
|
467 }
|
|
468
|
|
469 /* Free the memory references hash table. */
|
|
470
|
|
471 static void
|
|
472 free_mem_ref_resources ()
|
|
473 {
|
|
474 delete asan_mem_ref_ht;
|
|
475 asan_mem_ref_ht = NULL;
|
|
476
|
|
477 asan_mem_ref_pool.release ();
|
|
478 }
|
|
479
|
|
480 /* Return true iff the memory reference REF has been instrumented. */
|
|
481
|
|
482 static bool
|
|
483 has_mem_ref_been_instrumented (tree ref, HOST_WIDE_INT access_size)
|
|
484 {
|
|
485 asan_mem_ref r;
|
|
486 asan_mem_ref_init (&r, ref, access_size);
|
|
487
|
|
488 asan_mem_ref *saved_ref = get_mem_ref_hash_table ()->find (&r);
|
|
489 return saved_ref && saved_ref->access_size >= access_size;
|
|
490 }
|
|
491
|
|
492 /* Return true iff the memory reference REF has been instrumented. */
|
|
493
|
|
494 static bool
|
|
495 has_mem_ref_been_instrumented (const asan_mem_ref *ref)
|
|
496 {
|
|
497 return has_mem_ref_been_instrumented (ref->start, ref->access_size);
|
|
498 }
|
|
499
|
|
500 /* Return true iff access to memory region starting at REF and of
|
|
501 length LEN has been instrumented. */
|
|
502
|
|
503 static bool
|
|
504 has_mem_ref_been_instrumented (const asan_mem_ref *ref, tree len)
|
|
505 {
|
|
506 HOST_WIDE_INT size_in_bytes
|
|
507 = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
|
|
508
|
|
509 return size_in_bytes != -1
|
|
510 && has_mem_ref_been_instrumented (ref->start, size_in_bytes);
|
|
511 }
|
|
512
|
|
513 /* Set REF to the memory reference present in a gimple assignment
|
|
514 ASSIGNMENT. Return true upon successful completion, false
|
|
515 otherwise. */
|
|
516
|
|
517 static bool
|
|
518 get_mem_ref_of_assignment (const gassign *assignment,
|
|
519 asan_mem_ref *ref,
|
|
520 bool *ref_is_store)
|
|
521 {
|
|
522 gcc_assert (gimple_assign_single_p (assignment));
|
|
523
|
|
524 if (gimple_store_p (assignment)
|
|
525 && !gimple_clobber_p (assignment))
|
|
526 {
|
|
527 ref->start = gimple_assign_lhs (assignment);
|
|
528 *ref_is_store = true;
|
|
529 }
|
|
530 else if (gimple_assign_load_p (assignment))
|
|
531 {
|
|
532 ref->start = gimple_assign_rhs1 (assignment);
|
|
533 *ref_is_store = false;
|
|
534 }
|
|
535 else
|
|
536 return false;
|
|
537
|
|
538 ref->access_size = int_size_in_bytes (TREE_TYPE (ref->start));
|
|
539 return true;
|
|
540 }
|
|
541
|
|
542 /* Return address of last allocated dynamic alloca. */
|
|
543
|
|
544 static tree
|
|
545 get_last_alloca_addr ()
|
|
546 {
|
|
547 if (last_alloca_addr)
|
|
548 return last_alloca_addr;
|
|
549
|
|
550 last_alloca_addr = create_tmp_reg (ptr_type_node, "last_alloca_addr");
|
|
551 gassign *g = gimple_build_assign (last_alloca_addr, null_pointer_node);
|
|
552 edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
|
|
553 gsi_insert_on_edge_immediate (e, g);
|
|
554 return last_alloca_addr;
|
|
555 }
|
|
556
|
131
|
557 /* Insert __asan_allocas_unpoison (top, bottom) call before
|
111
|
558 __builtin_stack_restore (new_sp) call.
|
|
559 The pseudocode of this routine should look like this:
|
|
560 top = last_alloca_addr;
|
|
561 bot = new_sp;
|
|
562 __asan_allocas_unpoison (top, bot);
|
|
563 last_alloca_addr = new_sp;
|
131
|
564 __builtin_stack_restore (new_sp);
|
111
|
565 In general, we can't use new_sp as bot parameter because on some
|
|
566 architectures SP has non zero offset from dynamic stack area. Moreover, on
|
|
567 some architectures this offset (STACK_DYNAMIC_OFFSET) becomes known for each
|
|
568 particular function only after all callees were expanded to rtl.
|
|
569 The most noticeable example is PowerPC{,64}, see
|
|
570 http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#DYNAM-STACK.
|
|
571 To overcome the issue we use following trick: pass new_sp as a second
|
|
572 parameter to __asan_allocas_unpoison and rewrite it during expansion with
|
131
|
573 new_sp + (virtual_dynamic_stack_rtx - sp) later in
|
|
574 expand_asan_emit_allocas_unpoison function. */
|
111
|
575
|
|
576 static void
|
|
577 handle_builtin_stack_restore (gcall *call, gimple_stmt_iterator *iter)
|
|
578 {
|
|
579 if (!iter || !asan_sanitize_allocas_p ())
|
|
580 return;
|
|
581
|
|
582 tree last_alloca = get_last_alloca_addr ();
|
|
583 tree restored_stack = gimple_call_arg (call, 0);
|
|
584 tree fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCAS_UNPOISON);
|
|
585 gimple *g = gimple_build_call (fn, 2, last_alloca, restored_stack);
|
131
|
586 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
111
|
587 g = gimple_build_assign (last_alloca, restored_stack);
|
131
|
588 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
111
|
589 }
|
|
590
|
|
591 /* Deploy and poison redzones around __builtin_alloca call. To do this, we
|
|
592 should replace this call with another one with changed parameters and
|
|
593 replace all its uses with new address, so
|
|
594 addr = __builtin_alloca (old_size, align);
|
|
595 is replaced by
|
|
596 left_redzone_size = max (align, ASAN_RED_ZONE_SIZE);
|
|
597 Following two statements are optimized out if we know that
|
|
598 old_size & (ASAN_RED_ZONE_SIZE - 1) == 0, i.e. alloca doesn't need partial
|
|
599 redzone.
|
|
600 misalign = old_size & (ASAN_RED_ZONE_SIZE - 1);
|
|
601 partial_redzone_size = ASAN_RED_ZONE_SIZE - misalign;
|
|
602 right_redzone_size = ASAN_RED_ZONE_SIZE;
|
|
603 additional_size = left_redzone_size + partial_redzone_size +
|
|
604 right_redzone_size;
|
|
605 new_size = old_size + additional_size;
|
|
606 new_alloca = __builtin_alloca (new_size, max (align, 32))
|
|
607 __asan_alloca_poison (new_alloca, old_size)
|
|
608 addr = new_alloca + max (align, ASAN_RED_ZONE_SIZE);
|
|
609 last_alloca_addr = new_alloca;
|
|
610 ADDITIONAL_SIZE is added to make new memory allocation contain not only
|
|
611 requested memory, but also left, partial and right redzones as well as some
|
|
612 additional space, required by alignment. */
|
|
613
|
|
614 static void
|
|
615 handle_builtin_alloca (gcall *call, gimple_stmt_iterator *iter)
|
|
616 {
|
|
617 if (!iter || !asan_sanitize_allocas_p ())
|
|
618 return;
|
|
619
|
|
620 gassign *g;
|
|
621 gcall *gg;
|
|
622 const HOST_WIDE_INT redzone_mask = ASAN_RED_ZONE_SIZE - 1;
|
|
623
|
|
624 tree last_alloca = get_last_alloca_addr ();
|
|
625 tree callee = gimple_call_fndecl (call);
|
|
626 tree old_size = gimple_call_arg (call, 0);
|
|
627 tree ptr_type = gimple_call_lhs (call) ? TREE_TYPE (gimple_call_lhs (call))
|
|
628 : ptr_type_node;
|
|
629 tree partial_size = NULL_TREE;
|
|
630 unsigned int align
|
|
631 = DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
|
|
632 ? 0 : tree_to_uhwi (gimple_call_arg (call, 1));
|
|
633
|
|
634 /* If ALIGN > ASAN_RED_ZONE_SIZE, we embed left redzone into first ALIGN
|
|
635 bytes of allocated space. Otherwise, align alloca to ASAN_RED_ZONE_SIZE
|
|
636 manually. */
|
|
637 align = MAX (align, ASAN_RED_ZONE_SIZE * BITS_PER_UNIT);
|
|
638
|
|
639 tree alloca_rz_mask = build_int_cst (size_type_node, redzone_mask);
|
|
640 tree redzone_size = build_int_cst (size_type_node, ASAN_RED_ZONE_SIZE);
|
|
641
|
|
642 /* Extract lower bits from old_size. */
|
|
643 wide_int size_nonzero_bits = get_nonzero_bits (old_size);
|
|
644 wide_int rz_mask
|
|
645 = wi::uhwi (redzone_mask, wi::get_precision (size_nonzero_bits));
|
|
646 wide_int old_size_lower_bits = wi::bit_and (size_nonzero_bits, rz_mask);
|
|
647
|
|
648 /* If alloca size is aligned to ASAN_RED_ZONE_SIZE, we don't need partial
|
|
649 redzone. Otherwise, compute its size here. */
|
|
650 if (wi::ne_p (old_size_lower_bits, 0))
|
|
651 {
|
|
652 /* misalign = size & (ASAN_RED_ZONE_SIZE - 1)
|
|
653 partial_size = ASAN_RED_ZONE_SIZE - misalign. */
|
|
654 g = gimple_build_assign (make_ssa_name (size_type_node, NULL),
|
|
655 BIT_AND_EXPR, old_size, alloca_rz_mask);
|
|
656 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
657 tree misalign = gimple_assign_lhs (g);
|
|
658 g = gimple_build_assign (make_ssa_name (size_type_node, NULL), MINUS_EXPR,
|
|
659 redzone_size, misalign);
|
|
660 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
661 partial_size = gimple_assign_lhs (g);
|
|
662 }
|
|
663
|
|
664 /* additional_size = align + ASAN_RED_ZONE_SIZE. */
|
|
665 tree additional_size = build_int_cst (size_type_node, align / BITS_PER_UNIT
|
|
666 + ASAN_RED_ZONE_SIZE);
|
|
667 /* If alloca has partial redzone, include it to additional_size too. */
|
|
668 if (partial_size)
|
|
669 {
|
|
670 /* additional_size += partial_size. */
|
|
671 g = gimple_build_assign (make_ssa_name (size_type_node), PLUS_EXPR,
|
|
672 partial_size, additional_size);
|
|
673 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
674 additional_size = gimple_assign_lhs (g);
|
|
675 }
|
|
676
|
|
677 /* new_size = old_size + additional_size. */
|
|
678 g = gimple_build_assign (make_ssa_name (size_type_node), PLUS_EXPR, old_size,
|
|
679 additional_size);
|
|
680 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
681 tree new_size = gimple_assign_lhs (g);
|
|
682
|
|
683 /* Build new __builtin_alloca call:
|
|
684 new_alloca_with_rz = __builtin_alloca (new_size, align). */
|
|
685 tree fn = builtin_decl_implicit (BUILT_IN_ALLOCA_WITH_ALIGN);
|
|
686 gg = gimple_build_call (fn, 2, new_size,
|
|
687 build_int_cst (size_type_node, align));
|
|
688 tree new_alloca_with_rz = make_ssa_name (ptr_type, gg);
|
|
689 gimple_call_set_lhs (gg, new_alloca_with_rz);
|
|
690 gsi_insert_before (iter, gg, GSI_SAME_STMT);
|
|
691
|
|
692 /* new_alloca = new_alloca_with_rz + align. */
|
|
693 g = gimple_build_assign (make_ssa_name (ptr_type), POINTER_PLUS_EXPR,
|
|
694 new_alloca_with_rz,
|
|
695 build_int_cst (size_type_node,
|
|
696 align / BITS_PER_UNIT));
|
|
697 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
698 tree new_alloca = gimple_assign_lhs (g);
|
|
699
|
|
700 /* Poison newly created alloca redzones:
|
|
701 __asan_alloca_poison (new_alloca, old_size). */
|
|
702 fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCA_POISON);
|
|
703 gg = gimple_build_call (fn, 2, new_alloca, old_size);
|
|
704 gsi_insert_before (iter, gg, GSI_SAME_STMT);
|
|
705
|
|
706 /* Save new_alloca_with_rz value into last_alloca to use it during
|
|
707 allocas unpoisoning. */
|
|
708 g = gimple_build_assign (last_alloca, new_alloca_with_rz);
|
|
709 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
710
|
|
711 /* Finally, replace old alloca ptr with NEW_ALLOCA. */
|
|
712 replace_call_with_value (iter, new_alloca);
|
|
713 }
|
|
714
|
|
715 /* Return the memory references contained in a gimple statement
|
|
716 representing a builtin call that has to do with memory access. */
|
|
717
|
|
718 static bool
|
|
719 get_mem_refs_of_builtin_call (gcall *call,
|
|
720 asan_mem_ref *src0,
|
|
721 tree *src0_len,
|
|
722 bool *src0_is_store,
|
|
723 asan_mem_ref *src1,
|
|
724 tree *src1_len,
|
|
725 bool *src1_is_store,
|
|
726 asan_mem_ref *dst,
|
|
727 tree *dst_len,
|
|
728 bool *dst_is_store,
|
|
729 bool *dest_is_deref,
|
|
730 bool *intercepted_p,
|
|
731 gimple_stmt_iterator *iter = NULL)
|
|
732 {
|
|
733 gcc_checking_assert (gimple_call_builtin_p (call, BUILT_IN_NORMAL));
|
|
734
|
|
735 tree callee = gimple_call_fndecl (call);
|
|
736 tree source0 = NULL_TREE, source1 = NULL_TREE,
|
|
737 dest = NULL_TREE, len = NULL_TREE;
|
|
738 bool is_store = true, got_reference_p = false;
|
|
739 HOST_WIDE_INT access_size = 1;
|
|
740
|
|
741 *intercepted_p = asan_intercepted_p ((DECL_FUNCTION_CODE (callee)));
|
|
742
|
|
743 switch (DECL_FUNCTION_CODE (callee))
|
|
744 {
|
|
745 /* (s, s, n) style memops. */
|
|
746 case BUILT_IN_BCMP:
|
|
747 case BUILT_IN_MEMCMP:
|
|
748 source0 = gimple_call_arg (call, 0);
|
|
749 source1 = gimple_call_arg (call, 1);
|
|
750 len = gimple_call_arg (call, 2);
|
|
751 break;
|
|
752
|
|
753 /* (src, dest, n) style memops. */
|
|
754 case BUILT_IN_BCOPY:
|
|
755 source0 = gimple_call_arg (call, 0);
|
|
756 dest = gimple_call_arg (call, 1);
|
|
757 len = gimple_call_arg (call, 2);
|
|
758 break;
|
|
759
|
|
760 /* (dest, src, n) style memops. */
|
|
761 case BUILT_IN_MEMCPY:
|
|
762 case BUILT_IN_MEMCPY_CHK:
|
|
763 case BUILT_IN_MEMMOVE:
|
|
764 case BUILT_IN_MEMMOVE_CHK:
|
|
765 case BUILT_IN_MEMPCPY:
|
|
766 case BUILT_IN_MEMPCPY_CHK:
|
|
767 dest = gimple_call_arg (call, 0);
|
|
768 source0 = gimple_call_arg (call, 1);
|
|
769 len = gimple_call_arg (call, 2);
|
|
770 break;
|
|
771
|
|
772 /* (dest, n) style memops. */
|
|
773 case BUILT_IN_BZERO:
|
|
774 dest = gimple_call_arg (call, 0);
|
|
775 len = gimple_call_arg (call, 1);
|
|
776 break;
|
|
777
|
|
778 /* (dest, x, n) style memops*/
|
|
779 case BUILT_IN_MEMSET:
|
|
780 case BUILT_IN_MEMSET_CHK:
|
|
781 dest = gimple_call_arg (call, 0);
|
|
782 len = gimple_call_arg (call, 2);
|
|
783 break;
|
|
784
|
|
785 case BUILT_IN_STRLEN:
|
|
786 source0 = gimple_call_arg (call, 0);
|
|
787 len = gimple_call_lhs (call);
|
|
788 break;
|
|
789
|
|
790 case BUILT_IN_STACK_RESTORE:
|
|
791 handle_builtin_stack_restore (call, iter);
|
|
792 break;
|
|
793
|
|
794 CASE_BUILT_IN_ALLOCA:
|
|
795 handle_builtin_alloca (call, iter);
|
|
796 break;
|
|
797 /* And now the __atomic* and __sync builtins.
|
|
798 These are handled differently from the classical memory memory
|
|
799 access builtins above. */
|
|
800
|
|
801 case BUILT_IN_ATOMIC_LOAD_1:
|
|
802 is_store = false;
|
|
803 /* FALLTHRU */
|
|
804 case BUILT_IN_SYNC_FETCH_AND_ADD_1:
|
|
805 case BUILT_IN_SYNC_FETCH_AND_SUB_1:
|
|
806 case BUILT_IN_SYNC_FETCH_AND_OR_1:
|
|
807 case BUILT_IN_SYNC_FETCH_AND_AND_1:
|
|
808 case BUILT_IN_SYNC_FETCH_AND_XOR_1:
|
|
809 case BUILT_IN_SYNC_FETCH_AND_NAND_1:
|
|
810 case BUILT_IN_SYNC_ADD_AND_FETCH_1:
|
|
811 case BUILT_IN_SYNC_SUB_AND_FETCH_1:
|
|
812 case BUILT_IN_SYNC_OR_AND_FETCH_1:
|
|
813 case BUILT_IN_SYNC_AND_AND_FETCH_1:
|
|
814 case BUILT_IN_SYNC_XOR_AND_FETCH_1:
|
|
815 case BUILT_IN_SYNC_NAND_AND_FETCH_1:
|
|
816 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
|
|
817 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
|
|
818 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
|
|
819 case BUILT_IN_SYNC_LOCK_RELEASE_1:
|
|
820 case BUILT_IN_ATOMIC_EXCHANGE_1:
|
|
821 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
|
|
822 case BUILT_IN_ATOMIC_STORE_1:
|
|
823 case BUILT_IN_ATOMIC_ADD_FETCH_1:
|
|
824 case BUILT_IN_ATOMIC_SUB_FETCH_1:
|
|
825 case BUILT_IN_ATOMIC_AND_FETCH_1:
|
|
826 case BUILT_IN_ATOMIC_NAND_FETCH_1:
|
|
827 case BUILT_IN_ATOMIC_XOR_FETCH_1:
|
|
828 case BUILT_IN_ATOMIC_OR_FETCH_1:
|
|
829 case BUILT_IN_ATOMIC_FETCH_ADD_1:
|
|
830 case BUILT_IN_ATOMIC_FETCH_SUB_1:
|
|
831 case BUILT_IN_ATOMIC_FETCH_AND_1:
|
|
832 case BUILT_IN_ATOMIC_FETCH_NAND_1:
|
|
833 case BUILT_IN_ATOMIC_FETCH_XOR_1:
|
|
834 case BUILT_IN_ATOMIC_FETCH_OR_1:
|
|
835 access_size = 1;
|
|
836 goto do_atomic;
|
|
837
|
|
838 case BUILT_IN_ATOMIC_LOAD_2:
|
|
839 is_store = false;
|
|
840 /* FALLTHRU */
|
|
841 case BUILT_IN_SYNC_FETCH_AND_ADD_2:
|
|
842 case BUILT_IN_SYNC_FETCH_AND_SUB_2:
|
|
843 case BUILT_IN_SYNC_FETCH_AND_OR_2:
|
|
844 case BUILT_IN_SYNC_FETCH_AND_AND_2:
|
|
845 case BUILT_IN_SYNC_FETCH_AND_XOR_2:
|
|
846 case BUILT_IN_SYNC_FETCH_AND_NAND_2:
|
|
847 case BUILT_IN_SYNC_ADD_AND_FETCH_2:
|
|
848 case BUILT_IN_SYNC_SUB_AND_FETCH_2:
|
|
849 case BUILT_IN_SYNC_OR_AND_FETCH_2:
|
|
850 case BUILT_IN_SYNC_AND_AND_FETCH_2:
|
|
851 case BUILT_IN_SYNC_XOR_AND_FETCH_2:
|
|
852 case BUILT_IN_SYNC_NAND_AND_FETCH_2:
|
|
853 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
|
|
854 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
|
|
855 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
|
|
856 case BUILT_IN_SYNC_LOCK_RELEASE_2:
|
|
857 case BUILT_IN_ATOMIC_EXCHANGE_2:
|
|
858 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
|
|
859 case BUILT_IN_ATOMIC_STORE_2:
|
|
860 case BUILT_IN_ATOMIC_ADD_FETCH_2:
|
|
861 case BUILT_IN_ATOMIC_SUB_FETCH_2:
|
|
862 case BUILT_IN_ATOMIC_AND_FETCH_2:
|
|
863 case BUILT_IN_ATOMIC_NAND_FETCH_2:
|
|
864 case BUILT_IN_ATOMIC_XOR_FETCH_2:
|
|
865 case BUILT_IN_ATOMIC_OR_FETCH_2:
|
|
866 case BUILT_IN_ATOMIC_FETCH_ADD_2:
|
|
867 case BUILT_IN_ATOMIC_FETCH_SUB_2:
|
|
868 case BUILT_IN_ATOMIC_FETCH_AND_2:
|
|
869 case BUILT_IN_ATOMIC_FETCH_NAND_2:
|
|
870 case BUILT_IN_ATOMIC_FETCH_XOR_2:
|
|
871 case BUILT_IN_ATOMIC_FETCH_OR_2:
|
|
872 access_size = 2;
|
|
873 goto do_atomic;
|
|
874
|
|
875 case BUILT_IN_ATOMIC_LOAD_4:
|
|
876 is_store = false;
|
|
877 /* FALLTHRU */
|
|
878 case BUILT_IN_SYNC_FETCH_AND_ADD_4:
|
|
879 case BUILT_IN_SYNC_FETCH_AND_SUB_4:
|
|
880 case BUILT_IN_SYNC_FETCH_AND_OR_4:
|
|
881 case BUILT_IN_SYNC_FETCH_AND_AND_4:
|
|
882 case BUILT_IN_SYNC_FETCH_AND_XOR_4:
|
|
883 case BUILT_IN_SYNC_FETCH_AND_NAND_4:
|
|
884 case BUILT_IN_SYNC_ADD_AND_FETCH_4:
|
|
885 case BUILT_IN_SYNC_SUB_AND_FETCH_4:
|
|
886 case BUILT_IN_SYNC_OR_AND_FETCH_4:
|
|
887 case BUILT_IN_SYNC_AND_AND_FETCH_4:
|
|
888 case BUILT_IN_SYNC_XOR_AND_FETCH_4:
|
|
889 case BUILT_IN_SYNC_NAND_AND_FETCH_4:
|
|
890 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
|
|
891 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
|
|
892 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
|
|
893 case BUILT_IN_SYNC_LOCK_RELEASE_4:
|
|
894 case BUILT_IN_ATOMIC_EXCHANGE_4:
|
|
895 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
|
|
896 case BUILT_IN_ATOMIC_STORE_4:
|
|
897 case BUILT_IN_ATOMIC_ADD_FETCH_4:
|
|
898 case BUILT_IN_ATOMIC_SUB_FETCH_4:
|
|
899 case BUILT_IN_ATOMIC_AND_FETCH_4:
|
|
900 case BUILT_IN_ATOMIC_NAND_FETCH_4:
|
|
901 case BUILT_IN_ATOMIC_XOR_FETCH_4:
|
|
902 case BUILT_IN_ATOMIC_OR_FETCH_4:
|
|
903 case BUILT_IN_ATOMIC_FETCH_ADD_4:
|
|
904 case BUILT_IN_ATOMIC_FETCH_SUB_4:
|
|
905 case BUILT_IN_ATOMIC_FETCH_AND_4:
|
|
906 case BUILT_IN_ATOMIC_FETCH_NAND_4:
|
|
907 case BUILT_IN_ATOMIC_FETCH_XOR_4:
|
|
908 case BUILT_IN_ATOMIC_FETCH_OR_4:
|
|
909 access_size = 4;
|
|
910 goto do_atomic;
|
|
911
|
|
912 case BUILT_IN_ATOMIC_LOAD_8:
|
|
913 is_store = false;
|
|
914 /* FALLTHRU */
|
|
915 case BUILT_IN_SYNC_FETCH_AND_ADD_8:
|
|
916 case BUILT_IN_SYNC_FETCH_AND_SUB_8:
|
|
917 case BUILT_IN_SYNC_FETCH_AND_OR_8:
|
|
918 case BUILT_IN_SYNC_FETCH_AND_AND_8:
|
|
919 case BUILT_IN_SYNC_FETCH_AND_XOR_8:
|
|
920 case BUILT_IN_SYNC_FETCH_AND_NAND_8:
|
|
921 case BUILT_IN_SYNC_ADD_AND_FETCH_8:
|
|
922 case BUILT_IN_SYNC_SUB_AND_FETCH_8:
|
|
923 case BUILT_IN_SYNC_OR_AND_FETCH_8:
|
|
924 case BUILT_IN_SYNC_AND_AND_FETCH_8:
|
|
925 case BUILT_IN_SYNC_XOR_AND_FETCH_8:
|
|
926 case BUILT_IN_SYNC_NAND_AND_FETCH_8:
|
|
927 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
|
|
928 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
|
|
929 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
|
|
930 case BUILT_IN_SYNC_LOCK_RELEASE_8:
|
|
931 case BUILT_IN_ATOMIC_EXCHANGE_8:
|
|
932 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
|
|
933 case BUILT_IN_ATOMIC_STORE_8:
|
|
934 case BUILT_IN_ATOMIC_ADD_FETCH_8:
|
|
935 case BUILT_IN_ATOMIC_SUB_FETCH_8:
|
|
936 case BUILT_IN_ATOMIC_AND_FETCH_8:
|
|
937 case BUILT_IN_ATOMIC_NAND_FETCH_8:
|
|
938 case BUILT_IN_ATOMIC_XOR_FETCH_8:
|
|
939 case BUILT_IN_ATOMIC_OR_FETCH_8:
|
|
940 case BUILT_IN_ATOMIC_FETCH_ADD_8:
|
|
941 case BUILT_IN_ATOMIC_FETCH_SUB_8:
|
|
942 case BUILT_IN_ATOMIC_FETCH_AND_8:
|
|
943 case BUILT_IN_ATOMIC_FETCH_NAND_8:
|
|
944 case BUILT_IN_ATOMIC_FETCH_XOR_8:
|
|
945 case BUILT_IN_ATOMIC_FETCH_OR_8:
|
|
946 access_size = 8;
|
|
947 goto do_atomic;
|
|
948
|
|
949 case BUILT_IN_ATOMIC_LOAD_16:
|
|
950 is_store = false;
|
|
951 /* FALLTHRU */
|
|
952 case BUILT_IN_SYNC_FETCH_AND_ADD_16:
|
|
953 case BUILT_IN_SYNC_FETCH_AND_SUB_16:
|
|
954 case BUILT_IN_SYNC_FETCH_AND_OR_16:
|
|
955 case BUILT_IN_SYNC_FETCH_AND_AND_16:
|
|
956 case BUILT_IN_SYNC_FETCH_AND_XOR_16:
|
|
957 case BUILT_IN_SYNC_FETCH_AND_NAND_16:
|
|
958 case BUILT_IN_SYNC_ADD_AND_FETCH_16:
|
|
959 case BUILT_IN_SYNC_SUB_AND_FETCH_16:
|
|
960 case BUILT_IN_SYNC_OR_AND_FETCH_16:
|
|
961 case BUILT_IN_SYNC_AND_AND_FETCH_16:
|
|
962 case BUILT_IN_SYNC_XOR_AND_FETCH_16:
|
|
963 case BUILT_IN_SYNC_NAND_AND_FETCH_16:
|
|
964 case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
|
|
965 case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
|
|
966 case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
|
|
967 case BUILT_IN_SYNC_LOCK_RELEASE_16:
|
|
968 case BUILT_IN_ATOMIC_EXCHANGE_16:
|
|
969 case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
|
|
970 case BUILT_IN_ATOMIC_STORE_16:
|
|
971 case BUILT_IN_ATOMIC_ADD_FETCH_16:
|
|
972 case BUILT_IN_ATOMIC_SUB_FETCH_16:
|
|
973 case BUILT_IN_ATOMIC_AND_FETCH_16:
|
|
974 case BUILT_IN_ATOMIC_NAND_FETCH_16:
|
|
975 case BUILT_IN_ATOMIC_XOR_FETCH_16:
|
|
976 case BUILT_IN_ATOMIC_OR_FETCH_16:
|
|
977 case BUILT_IN_ATOMIC_FETCH_ADD_16:
|
|
978 case BUILT_IN_ATOMIC_FETCH_SUB_16:
|
|
979 case BUILT_IN_ATOMIC_FETCH_AND_16:
|
|
980 case BUILT_IN_ATOMIC_FETCH_NAND_16:
|
|
981 case BUILT_IN_ATOMIC_FETCH_XOR_16:
|
|
982 case BUILT_IN_ATOMIC_FETCH_OR_16:
|
|
983 access_size = 16;
|
|
984 /* FALLTHRU */
|
|
985 do_atomic:
|
|
986 {
|
|
987 dest = gimple_call_arg (call, 0);
|
|
988 /* DEST represents the address of a memory location.
|
|
989 instrument_derefs wants the memory location, so lets
|
|
990 dereference the address DEST before handing it to
|
|
991 instrument_derefs. */
|
|
992 tree type = build_nonstandard_integer_type (access_size
|
|
993 * BITS_PER_UNIT, 1);
|
|
994 dest = build2 (MEM_REF, type, dest,
|
|
995 build_int_cst (build_pointer_type (char_type_node), 0));
|
|
996 break;
|
|
997 }
|
|
998
|
|
999 default:
|
|
1000 /* The other builtins memory access are not instrumented in this
|
|
1001 function because they either don't have any length parameter,
|
|
1002 or their length parameter is just a limit. */
|
|
1003 break;
|
|
1004 }
|
|
1005
|
|
1006 if (len != NULL_TREE)
|
|
1007 {
|
|
1008 if (source0 != NULL_TREE)
|
|
1009 {
|
|
1010 src0->start = source0;
|
|
1011 src0->access_size = access_size;
|
|
1012 *src0_len = len;
|
|
1013 *src0_is_store = false;
|
|
1014 }
|
|
1015
|
|
1016 if (source1 != NULL_TREE)
|
|
1017 {
|
|
1018 src1->start = source1;
|
|
1019 src1->access_size = access_size;
|
|
1020 *src1_len = len;
|
|
1021 *src1_is_store = false;
|
|
1022 }
|
|
1023
|
|
1024 if (dest != NULL_TREE)
|
|
1025 {
|
|
1026 dst->start = dest;
|
|
1027 dst->access_size = access_size;
|
|
1028 *dst_len = len;
|
|
1029 *dst_is_store = true;
|
|
1030 }
|
|
1031
|
|
1032 got_reference_p = true;
|
|
1033 }
|
|
1034 else if (dest)
|
|
1035 {
|
|
1036 dst->start = dest;
|
|
1037 dst->access_size = access_size;
|
|
1038 *dst_len = NULL_TREE;
|
|
1039 *dst_is_store = is_store;
|
|
1040 *dest_is_deref = true;
|
|
1041 got_reference_p = true;
|
|
1042 }
|
|
1043
|
|
1044 return got_reference_p;
|
|
1045 }
|
|
1046
|
|
1047 /* Return true iff a given gimple statement has been instrumented.
|
|
1048 Note that the statement is "defined" by the memory references it
|
|
1049 contains. */
|
|
1050
|
|
1051 static bool
|
|
1052 has_stmt_been_instrumented_p (gimple *stmt)
|
|
1053 {
|
|
1054 if (gimple_assign_single_p (stmt))
|
|
1055 {
|
|
1056 bool r_is_store;
|
|
1057 asan_mem_ref r;
|
|
1058 asan_mem_ref_init (&r, NULL, 1);
|
|
1059
|
|
1060 if (get_mem_ref_of_assignment (as_a <gassign *> (stmt), &r,
|
|
1061 &r_is_store))
|
|
1062 return has_mem_ref_been_instrumented (&r);
|
|
1063 }
|
|
1064 else if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
|
|
1065 {
|
|
1066 asan_mem_ref src0, src1, dest;
|
|
1067 asan_mem_ref_init (&src0, NULL, 1);
|
|
1068 asan_mem_ref_init (&src1, NULL, 1);
|
|
1069 asan_mem_ref_init (&dest, NULL, 1);
|
|
1070
|
|
1071 tree src0_len = NULL_TREE, src1_len = NULL_TREE, dest_len = NULL_TREE;
|
|
1072 bool src0_is_store = false, src1_is_store = false,
|
|
1073 dest_is_store = false, dest_is_deref = false, intercepted_p = true;
|
|
1074 if (get_mem_refs_of_builtin_call (as_a <gcall *> (stmt),
|
|
1075 &src0, &src0_len, &src0_is_store,
|
|
1076 &src1, &src1_len, &src1_is_store,
|
|
1077 &dest, &dest_len, &dest_is_store,
|
|
1078 &dest_is_deref, &intercepted_p))
|
|
1079 {
|
|
1080 if (src0.start != NULL_TREE
|
|
1081 && !has_mem_ref_been_instrumented (&src0, src0_len))
|
|
1082 return false;
|
|
1083
|
|
1084 if (src1.start != NULL_TREE
|
|
1085 && !has_mem_ref_been_instrumented (&src1, src1_len))
|
|
1086 return false;
|
|
1087
|
|
1088 if (dest.start != NULL_TREE
|
|
1089 && !has_mem_ref_been_instrumented (&dest, dest_len))
|
|
1090 return false;
|
|
1091
|
|
1092 return true;
|
|
1093 }
|
|
1094 }
|
|
1095 else if (is_gimple_call (stmt) && gimple_store_p (stmt))
|
|
1096 {
|
|
1097 asan_mem_ref r;
|
|
1098 asan_mem_ref_init (&r, NULL, 1);
|
|
1099
|
|
1100 r.start = gimple_call_lhs (stmt);
|
|
1101 r.access_size = int_size_in_bytes (TREE_TYPE (r.start));
|
|
1102 return has_mem_ref_been_instrumented (&r);
|
|
1103 }
|
|
1104
|
|
1105 return false;
|
|
1106 }
|
|
1107
|
|
1108 /* Insert a memory reference into the hash table. */
|
|
1109
|
|
1110 static void
|
|
1111 update_mem_ref_hash_table (tree ref, HOST_WIDE_INT access_size)
|
|
1112 {
|
|
1113 hash_table<asan_mem_ref_hasher> *ht = get_mem_ref_hash_table ();
|
|
1114
|
|
1115 asan_mem_ref r;
|
|
1116 asan_mem_ref_init (&r, ref, access_size);
|
|
1117
|
|
1118 asan_mem_ref **slot = ht->find_slot (&r, INSERT);
|
|
1119 if (*slot == NULL || (*slot)->access_size < access_size)
|
|
1120 *slot = asan_mem_ref_new (ref, access_size);
|
|
1121 }
|
|
1122
|
|
1123 /* Initialize shadow_ptr_types array. */
|
|
1124
|
|
1125 static void
|
|
1126 asan_init_shadow_ptr_types (void)
|
|
1127 {
|
|
1128 asan_shadow_set = new_alias_set ();
|
|
1129 tree types[3] = { signed_char_type_node, short_integer_type_node,
|
|
1130 integer_type_node };
|
|
1131
|
|
1132 for (unsigned i = 0; i < 3; i++)
|
|
1133 {
|
|
1134 shadow_ptr_types[i] = build_distinct_type_copy (types[i]);
|
|
1135 TYPE_ALIAS_SET (shadow_ptr_types[i]) = asan_shadow_set;
|
|
1136 shadow_ptr_types[i] = build_pointer_type (shadow_ptr_types[i]);
|
|
1137 }
|
|
1138
|
|
1139 initialize_sanitizer_builtins ();
|
|
1140 }
|
|
1141
|
|
1142 /* Create ADDR_EXPR of STRING_CST with the PP pretty printer text. */
|
|
1143
|
|
1144 static tree
|
|
1145 asan_pp_string (pretty_printer *pp)
|
|
1146 {
|
|
1147 const char *buf = pp_formatted_text (pp);
|
|
1148 size_t len = strlen (buf);
|
|
1149 tree ret = build_string (len + 1, buf);
|
|
1150 TREE_TYPE (ret)
|
|
1151 = build_array_type (TREE_TYPE (shadow_ptr_types[0]),
|
|
1152 build_index_type (size_int (len)));
|
|
1153 TREE_READONLY (ret) = 1;
|
|
1154 TREE_STATIC (ret) = 1;
|
|
1155 return build1 (ADDR_EXPR, shadow_ptr_types[0], ret);
|
|
1156 }
|
|
1157
|
|
1158 /* Return a CONST_INT representing 4 subsequent shadow memory bytes. */
|
|
1159
|
|
1160 static rtx
|
|
1161 asan_shadow_cst (unsigned char shadow_bytes[4])
|
|
1162 {
|
|
1163 int i;
|
|
1164 unsigned HOST_WIDE_INT val = 0;
|
|
1165 gcc_assert (WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN);
|
|
1166 for (i = 0; i < 4; i++)
|
|
1167 val |= (unsigned HOST_WIDE_INT) shadow_bytes[BYTES_BIG_ENDIAN ? 3 - i : i]
|
|
1168 << (BITS_PER_UNIT * i);
|
|
1169 return gen_int_mode (val, SImode);
|
|
1170 }
|
|
1171
|
|
1172 /* Clear shadow memory at SHADOW_MEM, LEN bytes. Can't call a library call here
|
|
1173 though. */
|
|
1174
|
|
1175 static void
|
|
1176 asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len)
|
|
1177 {
|
|
1178 rtx_insn *insn, *insns, *jump;
|
|
1179 rtx_code_label *top_label;
|
|
1180 rtx end, addr, tmp;
|
|
1181
|
|
1182 start_sequence ();
|
|
1183 clear_storage (shadow_mem, GEN_INT (len), BLOCK_OP_NORMAL);
|
|
1184 insns = get_insns ();
|
|
1185 end_sequence ();
|
|
1186 for (insn = insns; insn; insn = NEXT_INSN (insn))
|
|
1187 if (CALL_P (insn))
|
|
1188 break;
|
|
1189 if (insn == NULL_RTX)
|
|
1190 {
|
|
1191 emit_insn (insns);
|
|
1192 return;
|
|
1193 }
|
|
1194
|
|
1195 gcc_assert ((len & 3) == 0);
|
|
1196 top_label = gen_label_rtx ();
|
|
1197 addr = copy_to_mode_reg (Pmode, XEXP (shadow_mem, 0));
|
|
1198 shadow_mem = adjust_automodify_address (shadow_mem, SImode, addr, 0);
|
|
1199 end = force_reg (Pmode, plus_constant (Pmode, addr, len));
|
|
1200 emit_label (top_label);
|
|
1201
|
|
1202 emit_move_insn (shadow_mem, const0_rtx);
|
|
1203 tmp = expand_simple_binop (Pmode, PLUS, addr, gen_int_mode (4, Pmode), addr,
|
|
1204 true, OPTAB_LIB_WIDEN);
|
|
1205 if (tmp != addr)
|
|
1206 emit_move_insn (addr, tmp);
|
|
1207 emit_cmp_and_jump_insns (addr, end, LT, NULL_RTX, Pmode, true, top_label);
|
|
1208 jump = get_last_insn ();
|
|
1209 gcc_assert (JUMP_P (jump));
|
|
1210 add_reg_br_prob_note (jump,
|
|
1211 profile_probability::guessed_always ()
|
|
1212 .apply_scale (80, 100));
|
|
1213 }
|
|
1214
|
|
1215 void
|
|
1216 asan_function_start (void)
|
|
1217 {
|
|
1218 section *fnsec = function_section (current_function_decl);
|
|
1219 switch_to_section (fnsec);
|
|
1220 ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LASANPC",
|
|
1221 current_function_funcdef_no);
|
|
1222 }
|
|
1223
|
|
1224 /* Return number of shadow bytes that are occupied by a local variable
|
|
1225 of SIZE bytes. */
|
|
1226
|
|
1227 static unsigned HOST_WIDE_INT
|
|
1228 shadow_mem_size (unsigned HOST_WIDE_INT size)
|
|
1229 {
|
131
|
1230 /* It must be possible to align stack variables to granularity
|
|
1231 of shadow memory. */
|
|
1232 gcc_assert (BITS_PER_UNIT
|
|
1233 * ASAN_SHADOW_GRANULARITY <= MAX_SUPPORTED_STACK_ALIGNMENT);
|
|
1234
|
111
|
1235 return ROUND_UP (size, ASAN_SHADOW_GRANULARITY) / ASAN_SHADOW_GRANULARITY;
|
|
1236 }
|
|
1237
|
|
1238 /* Insert code to protect stack vars. The prologue sequence should be emitted
|
|
1239 directly, epilogue sequence returned. BASE is the register holding the
|
|
1240 stack base, against which OFFSETS array offsets are relative to, OFFSETS
|
|
1241 array contains pairs of offsets in reverse order, always the end offset
|
|
1242 of some gap that needs protection followed by starting offset,
|
|
1243 and DECLS is an array of representative decls for each var partition.
|
|
1244 LENGTH is the length of the OFFSETS array, DECLS array is LENGTH / 2 - 1
|
|
1245 elements long (OFFSETS include gap before the first variable as well
|
|
1246 as gaps after each stack variable). PBASE is, if non-NULL, some pseudo
|
|
1247 register which stack vars DECL_RTLs are based on. Either BASE should be
|
|
1248 assigned to PBASE, when not doing use after return protection, or
|
|
1249 corresponding address based on __asan_stack_malloc* return value. */
|
|
1250
|
|
1251 rtx_insn *
|
|
1252 asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
|
|
1253 HOST_WIDE_INT *offsets, tree *decls, int length)
|
|
1254 {
|
|
1255 rtx shadow_base, shadow_mem, ret, mem, orig_base;
|
|
1256 rtx_code_label *lab;
|
|
1257 rtx_insn *insns;
|
|
1258 char buf[32];
|
|
1259 unsigned char shadow_bytes[4];
|
|
1260 HOST_WIDE_INT base_offset = offsets[length - 1];
|
|
1261 HOST_WIDE_INT base_align_bias = 0, offset, prev_offset;
|
|
1262 HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset;
|
|
1263 HOST_WIDE_INT last_offset, last_size;
|
|
1264 int l;
|
|
1265 unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
|
|
1266 tree str_cst, decl, id;
|
|
1267 int use_after_return_class = -1;
|
|
1268
|
|
1269 if (shadow_ptr_types[0] == NULL_TREE)
|
|
1270 asan_init_shadow_ptr_types ();
|
|
1271
|
131
|
1272 expanded_location cfun_xloc
|
|
1273 = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
|
|
1274
|
111
|
1275 /* First of all, prepare the description string. */
|
|
1276 pretty_printer asan_pp;
|
|
1277
|
|
1278 pp_decimal_int (&asan_pp, length / 2 - 1);
|
|
1279 pp_space (&asan_pp);
|
|
1280 for (l = length - 2; l; l -= 2)
|
|
1281 {
|
|
1282 tree decl = decls[l / 2 - 1];
|
|
1283 pp_wide_integer (&asan_pp, offsets[l] - base_offset);
|
|
1284 pp_space (&asan_pp);
|
|
1285 pp_wide_integer (&asan_pp, offsets[l - 1] - offsets[l]);
|
|
1286 pp_space (&asan_pp);
|
131
|
1287
|
|
1288 expanded_location xloc
|
|
1289 = expand_location (DECL_SOURCE_LOCATION (decl));
|
|
1290 char location[32];
|
|
1291
|
|
1292 if (xloc.file == cfun_xloc.file)
|
|
1293 sprintf (location, ":%d", xloc.line);
|
|
1294 else
|
|
1295 location[0] = '\0';
|
|
1296
|
111
|
1297 if (DECL_P (decl) && DECL_NAME (decl))
|
|
1298 {
|
131
|
1299 unsigned idlen
|
|
1300 = IDENTIFIER_LENGTH (DECL_NAME (decl)) + strlen (location);
|
|
1301 pp_decimal_int (&asan_pp, idlen);
|
111
|
1302 pp_space (&asan_pp);
|
|
1303 pp_tree_identifier (&asan_pp, DECL_NAME (decl));
|
131
|
1304 pp_string (&asan_pp, location);
|
111
|
1305 }
|
|
1306 else
|
|
1307 pp_string (&asan_pp, "9 <unknown>");
|
131
|
1308
|
|
1309 if (l > 2)
|
|
1310 pp_space (&asan_pp);
|
111
|
1311 }
|
|
1312 str_cst = asan_pp_string (&asan_pp);
|
|
1313
|
|
1314 /* Emit the prologue sequence. */
|
|
1315 if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase
|
|
1316 && ASAN_USE_AFTER_RETURN)
|
|
1317 {
|
|
1318 use_after_return_class = floor_log2 (asan_frame_size - 1) - 5;
|
|
1319 /* __asan_stack_malloc_N guarantees alignment
|
|
1320 N < 6 ? (64 << N) : 4096 bytes. */
|
|
1321 if (alignb > (use_after_return_class < 6
|
|
1322 ? (64U << use_after_return_class) : 4096U))
|
|
1323 use_after_return_class = -1;
|
|
1324 else if (alignb > ASAN_RED_ZONE_SIZE && (asan_frame_size & (alignb - 1)))
|
|
1325 base_align_bias = ((asan_frame_size + alignb - 1)
|
|
1326 & ~(alignb - HOST_WIDE_INT_1)) - asan_frame_size;
|
|
1327 }
|
|
1328 /* Align base if target is STRICT_ALIGNMENT. */
|
|
1329 if (STRICT_ALIGNMENT)
|
|
1330 base = expand_binop (Pmode, and_optab, base,
|
|
1331 gen_int_mode (-((GET_MODE_ALIGNMENT (SImode)
|
|
1332 << ASAN_SHADOW_SHIFT)
|
|
1333 / BITS_PER_UNIT), Pmode), NULL_RTX,
|
|
1334 1, OPTAB_DIRECT);
|
|
1335
|
|
1336 if (use_after_return_class == -1 && pbase)
|
|
1337 emit_move_insn (pbase, base);
|
|
1338
|
|
1339 base = expand_binop (Pmode, add_optab, base,
|
|
1340 gen_int_mode (base_offset - base_align_bias, Pmode),
|
|
1341 NULL_RTX, 1, OPTAB_DIRECT);
|
|
1342 orig_base = NULL_RTX;
|
|
1343 if (use_after_return_class != -1)
|
|
1344 {
|
|
1345 if (asan_detect_stack_use_after_return == NULL_TREE)
|
|
1346 {
|
|
1347 id = get_identifier ("__asan_option_detect_stack_use_after_return");
|
|
1348 decl = build_decl (BUILTINS_LOCATION, VAR_DECL, id,
|
|
1349 integer_type_node);
|
|
1350 SET_DECL_ASSEMBLER_NAME (decl, id);
|
|
1351 TREE_ADDRESSABLE (decl) = 1;
|
|
1352 DECL_ARTIFICIAL (decl) = 1;
|
|
1353 DECL_IGNORED_P (decl) = 1;
|
|
1354 DECL_EXTERNAL (decl) = 1;
|
|
1355 TREE_STATIC (decl) = 1;
|
|
1356 TREE_PUBLIC (decl) = 1;
|
|
1357 TREE_USED (decl) = 1;
|
|
1358 asan_detect_stack_use_after_return = decl;
|
|
1359 }
|
|
1360 orig_base = gen_reg_rtx (Pmode);
|
|
1361 emit_move_insn (orig_base, base);
|
|
1362 ret = expand_normal (asan_detect_stack_use_after_return);
|
|
1363 lab = gen_label_rtx ();
|
|
1364 emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
|
|
1365 VOIDmode, 0, lab,
|
|
1366 profile_probability::very_likely ());
|
|
1367 snprintf (buf, sizeof buf, "__asan_stack_malloc_%d",
|
|
1368 use_after_return_class);
|
|
1369 ret = init_one_libfunc (buf);
|
|
1370 ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
|
|
1371 GEN_INT (asan_frame_size
|
|
1372 + base_align_bias),
|
|
1373 TYPE_MODE (pointer_sized_int_node));
|
|
1374 /* __asan_stack_malloc_[n] returns a pointer to fake stack if succeeded
|
|
1375 and NULL otherwise. Check RET value is NULL here and jump over the
|
|
1376 BASE reassignment in this case. Otherwise, reassign BASE to RET. */
|
|
1377 emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
|
|
1378 VOIDmode, 0, lab,
|
|
1379 profile_probability:: very_unlikely ());
|
|
1380 ret = convert_memory_address (Pmode, ret);
|
|
1381 emit_move_insn (base, ret);
|
|
1382 emit_label (lab);
|
|
1383 emit_move_insn (pbase, expand_binop (Pmode, add_optab, base,
|
|
1384 gen_int_mode (base_align_bias
|
|
1385 - base_offset, Pmode),
|
|
1386 NULL_RTX, 1, OPTAB_DIRECT));
|
|
1387 }
|
|
1388 mem = gen_rtx_MEM (ptr_mode, base);
|
|
1389 mem = adjust_address (mem, VOIDmode, base_align_bias);
|
|
1390 emit_move_insn (mem, gen_int_mode (ASAN_STACK_FRAME_MAGIC, ptr_mode));
|
|
1391 mem = adjust_address (mem, VOIDmode, GET_MODE_SIZE (ptr_mode));
|
|
1392 emit_move_insn (mem, expand_normal (str_cst));
|
|
1393 mem = adjust_address (mem, VOIDmode, GET_MODE_SIZE (ptr_mode));
|
|
1394 ASM_GENERATE_INTERNAL_LABEL (buf, "LASANPC", current_function_funcdef_no);
|
|
1395 id = get_identifier (buf);
|
|
1396 decl = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
|
|
1397 VAR_DECL, id, char_type_node);
|
|
1398 SET_DECL_ASSEMBLER_NAME (decl, id);
|
|
1399 TREE_ADDRESSABLE (decl) = 1;
|
|
1400 TREE_READONLY (decl) = 1;
|
|
1401 DECL_ARTIFICIAL (decl) = 1;
|
|
1402 DECL_IGNORED_P (decl) = 1;
|
|
1403 TREE_STATIC (decl) = 1;
|
|
1404 TREE_PUBLIC (decl) = 0;
|
|
1405 TREE_USED (decl) = 1;
|
|
1406 DECL_INITIAL (decl) = decl;
|
|
1407 TREE_ASM_WRITTEN (decl) = 1;
|
|
1408 TREE_ASM_WRITTEN (id) = 1;
|
|
1409 emit_move_insn (mem, expand_normal (build_fold_addr_expr (decl)));
|
|
1410 shadow_base = expand_binop (Pmode, lshr_optab, base,
|
131
|
1411 gen_int_shift_amount (Pmode, ASAN_SHADOW_SHIFT),
|
111
|
1412 NULL_RTX, 1, OPTAB_DIRECT);
|
|
1413 shadow_base
|
|
1414 = plus_constant (Pmode, shadow_base,
|
|
1415 asan_shadow_offset ()
|
|
1416 + (base_align_bias >> ASAN_SHADOW_SHIFT));
|
|
1417 gcc_assert (asan_shadow_set != -1
|
|
1418 && (ASAN_RED_ZONE_SIZE >> ASAN_SHADOW_SHIFT) == 4);
|
|
1419 shadow_mem = gen_rtx_MEM (SImode, shadow_base);
|
|
1420 set_mem_alias_set (shadow_mem, asan_shadow_set);
|
|
1421 if (STRICT_ALIGNMENT)
|
|
1422 set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
|
|
1423 prev_offset = base_offset;
|
|
1424 for (l = length; l; l -= 2)
|
|
1425 {
|
|
1426 if (l == 2)
|
|
1427 cur_shadow_byte = ASAN_STACK_MAGIC_RIGHT;
|
|
1428 offset = offsets[l - 1];
|
|
1429 if ((offset - base_offset) & (ASAN_RED_ZONE_SIZE - 1))
|
|
1430 {
|
|
1431 int i;
|
|
1432 HOST_WIDE_INT aoff
|
|
1433 = base_offset + ((offset - base_offset)
|
|
1434 & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
|
|
1435 shadow_mem = adjust_address (shadow_mem, VOIDmode,
|
|
1436 (aoff - prev_offset)
|
|
1437 >> ASAN_SHADOW_SHIFT);
|
|
1438 prev_offset = aoff;
|
|
1439 for (i = 0; i < 4; i++, aoff += ASAN_SHADOW_GRANULARITY)
|
|
1440 if (aoff < offset)
|
|
1441 {
|
|
1442 if (aoff < offset - (HOST_WIDE_INT)ASAN_SHADOW_GRANULARITY + 1)
|
|
1443 shadow_bytes[i] = 0;
|
|
1444 else
|
|
1445 shadow_bytes[i] = offset - aoff;
|
|
1446 }
|
|
1447 else
|
|
1448 shadow_bytes[i] = ASAN_STACK_MAGIC_MIDDLE;
|
|
1449 emit_move_insn (shadow_mem, asan_shadow_cst (shadow_bytes));
|
|
1450 offset = aoff;
|
|
1451 }
|
|
1452 while (offset <= offsets[l - 2] - ASAN_RED_ZONE_SIZE)
|
|
1453 {
|
|
1454 shadow_mem = adjust_address (shadow_mem, VOIDmode,
|
|
1455 (offset - prev_offset)
|
|
1456 >> ASAN_SHADOW_SHIFT);
|
|
1457 prev_offset = offset;
|
|
1458 memset (shadow_bytes, cur_shadow_byte, 4);
|
|
1459 emit_move_insn (shadow_mem, asan_shadow_cst (shadow_bytes));
|
|
1460 offset += ASAN_RED_ZONE_SIZE;
|
|
1461 }
|
|
1462 cur_shadow_byte = ASAN_STACK_MAGIC_MIDDLE;
|
|
1463 }
|
|
1464 do_pending_stack_adjust ();
|
|
1465
|
|
1466 /* Construct epilogue sequence. */
|
|
1467 start_sequence ();
|
|
1468
|
|
1469 lab = NULL;
|
|
1470 if (use_after_return_class != -1)
|
|
1471 {
|
|
1472 rtx_code_label *lab2 = gen_label_rtx ();
|
|
1473 char c = (char) ASAN_STACK_MAGIC_USE_AFTER_RET;
|
|
1474 emit_cmp_and_jump_insns (orig_base, base, EQ, NULL_RTX,
|
|
1475 VOIDmode, 0, lab2,
|
|
1476 profile_probability::very_likely ());
|
|
1477 shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
|
|
1478 set_mem_alias_set (shadow_mem, asan_shadow_set);
|
|
1479 mem = gen_rtx_MEM (ptr_mode, base);
|
|
1480 mem = adjust_address (mem, VOIDmode, base_align_bias);
|
|
1481 emit_move_insn (mem, gen_int_mode (ASAN_STACK_RETIRED_MAGIC, ptr_mode));
|
|
1482 unsigned HOST_WIDE_INT sz = asan_frame_size >> ASAN_SHADOW_SHIFT;
|
|
1483 if (use_after_return_class < 5
|
|
1484 && can_store_by_pieces (sz, builtin_memset_read_str, &c,
|
|
1485 BITS_PER_UNIT, true))
|
|
1486 store_by_pieces (shadow_mem, sz, builtin_memset_read_str, &c,
|
|
1487 BITS_PER_UNIT, true, 0);
|
|
1488 else if (use_after_return_class >= 5
|
|
1489 || !set_storage_via_setmem (shadow_mem,
|
|
1490 GEN_INT (sz),
|
|
1491 gen_int_mode (c, QImode),
|
|
1492 BITS_PER_UNIT, BITS_PER_UNIT,
|
|
1493 -1, sz, sz, sz))
|
|
1494 {
|
|
1495 snprintf (buf, sizeof buf, "__asan_stack_free_%d",
|
|
1496 use_after_return_class);
|
|
1497 ret = init_one_libfunc (buf);
|
|
1498 rtx addr = convert_memory_address (ptr_mode, base);
|
|
1499 rtx orig_addr = convert_memory_address (ptr_mode, orig_base);
|
|
1500 emit_library_call (ret, LCT_NORMAL, ptr_mode, addr, ptr_mode,
|
|
1501 GEN_INT (asan_frame_size + base_align_bias),
|
|
1502 TYPE_MODE (pointer_sized_int_node),
|
|
1503 orig_addr, ptr_mode);
|
|
1504 }
|
|
1505 lab = gen_label_rtx ();
|
|
1506 emit_jump (lab);
|
|
1507 emit_label (lab2);
|
|
1508 }
|
|
1509
|
|
1510 shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
|
|
1511 set_mem_alias_set (shadow_mem, asan_shadow_set);
|
|
1512
|
|
1513 if (STRICT_ALIGNMENT)
|
|
1514 set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
|
|
1515
|
|
1516 prev_offset = base_offset;
|
|
1517 last_offset = base_offset;
|
|
1518 last_size = 0;
|
|
1519 for (l = length; l; l -= 2)
|
|
1520 {
|
|
1521 offset = base_offset + ((offsets[l - 1] - base_offset)
|
|
1522 & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
|
|
1523 if (last_offset + last_size != offset)
|
|
1524 {
|
|
1525 shadow_mem = adjust_address (shadow_mem, VOIDmode,
|
|
1526 (last_offset - prev_offset)
|
|
1527 >> ASAN_SHADOW_SHIFT);
|
|
1528 prev_offset = last_offset;
|
|
1529 asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
|
|
1530 last_offset = offset;
|
|
1531 last_size = 0;
|
|
1532 }
|
|
1533 last_size += base_offset + ((offsets[l - 2] - base_offset)
|
|
1534 & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
|
|
1535 - offset;
|
|
1536
|
|
1537 /* Unpoison shadow memory that corresponds to a variable that is
|
|
1538 is subject of use-after-return sanitization. */
|
|
1539 if (l > 2)
|
|
1540 {
|
|
1541 decl = decls[l / 2 - 2];
|
|
1542 if (asan_handled_variables != NULL
|
|
1543 && asan_handled_variables->contains (decl))
|
|
1544 {
|
|
1545 HOST_WIDE_INT size = offsets[l - 3] - offsets[l - 2];
|
|
1546 if (dump_file && (dump_flags & TDF_DETAILS))
|
|
1547 {
|
|
1548 const char *n = (DECL_NAME (decl)
|
|
1549 ? IDENTIFIER_POINTER (DECL_NAME (decl))
|
|
1550 : "<unknown>");
|
|
1551 fprintf (dump_file, "Unpoisoning shadow stack for variable: "
|
|
1552 "%s (%" PRId64 " B)\n", n, size);
|
|
1553 }
|
|
1554
|
|
1555 last_size += size & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1);
|
|
1556 }
|
|
1557 }
|
|
1558 }
|
|
1559 if (last_size)
|
|
1560 {
|
|
1561 shadow_mem = adjust_address (shadow_mem, VOIDmode,
|
|
1562 (last_offset - prev_offset)
|
|
1563 >> ASAN_SHADOW_SHIFT);
|
|
1564 asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
|
|
1565 }
|
|
1566
|
|
1567 /* Clean-up set with instrumented stack variables. */
|
|
1568 delete asan_handled_variables;
|
|
1569 asan_handled_variables = NULL;
|
|
1570 delete asan_used_labels;
|
|
1571 asan_used_labels = NULL;
|
|
1572
|
|
1573 do_pending_stack_adjust ();
|
|
1574 if (lab)
|
|
1575 emit_label (lab);
|
|
1576
|
|
1577 insns = get_insns ();
|
|
1578 end_sequence ();
|
|
1579 return insns;
|
|
1580 }
|
|
1581
|
|
1582 /* Emit __asan_allocas_unpoison (top, bot) call. The BASE parameter corresponds
|
|
1583 to BOT argument, for TOP virtual_stack_dynamic_rtx is used. NEW_SEQUENCE
|
|
1584 indicates whether we're emitting new instructions sequence or not. */
|
|
1585
|
|
1586 rtx_insn *
|
|
1587 asan_emit_allocas_unpoison (rtx top, rtx bot, rtx_insn *before)
|
|
1588 {
|
|
1589 if (before)
|
|
1590 push_to_sequence (before);
|
|
1591 else
|
|
1592 start_sequence ();
|
|
1593 rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
|
|
1594 top = convert_memory_address (ptr_mode, top);
|
|
1595 bot = convert_memory_address (ptr_mode, bot);
|
|
1596 ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
|
|
1597 top, ptr_mode, bot, ptr_mode);
|
|
1598
|
|
1599 do_pending_stack_adjust ();
|
|
1600 rtx_insn *insns = get_insns ();
|
|
1601 end_sequence ();
|
|
1602 return insns;
|
|
1603 }
|
|
1604
|
|
1605 /* Return true if DECL, a global var, might be overridden and needs
|
|
1606 therefore a local alias. */
|
|
1607
|
|
1608 static bool
|
|
1609 asan_needs_local_alias (tree decl)
|
|
1610 {
|
|
1611 return DECL_WEAK (decl) || !targetm.binds_local_p (decl);
|
|
1612 }
|
|
1613
|
|
1614 /* Return true if DECL, a global var, is an artificial ODR indicator symbol
|
|
1615 therefore doesn't need protection. */
|
|
1616
|
|
1617 static bool
|
|
1618 is_odr_indicator (tree decl)
|
|
1619 {
|
|
1620 return (DECL_ARTIFICIAL (decl)
|
|
1621 && lookup_attribute ("asan odr indicator", DECL_ATTRIBUTES (decl)));
|
|
1622 }
|
|
1623
|
|
1624 /* Return true if DECL is a VAR_DECL that should be protected
|
|
1625 by Address Sanitizer, by appending a red zone with protected
|
|
1626 shadow memory after it and aligning it to at least
|
|
1627 ASAN_RED_ZONE_SIZE bytes. */
|
|
1628
|
|
1629 bool
|
131
|
1630 asan_protect_global (tree decl, bool ignore_decl_rtl_set_p)
|
111
|
1631 {
|
|
1632 if (!ASAN_GLOBALS)
|
|
1633 return false;
|
|
1634
|
|
1635 rtx rtl, symbol;
|
|
1636
|
|
1637 if (TREE_CODE (decl) == STRING_CST)
|
|
1638 {
|
|
1639 /* Instrument all STRING_CSTs except those created
|
|
1640 by asan_pp_string here. */
|
|
1641 if (shadow_ptr_types[0] != NULL_TREE
|
|
1642 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
|
|
1643 && TREE_TYPE (TREE_TYPE (decl)) == TREE_TYPE (shadow_ptr_types[0]))
|
|
1644 return false;
|
|
1645 return true;
|
|
1646 }
|
|
1647 if (!VAR_P (decl)
|
|
1648 /* TLS vars aren't statically protectable. */
|
|
1649 || DECL_THREAD_LOCAL_P (decl)
|
|
1650 /* Externs will be protected elsewhere. */
|
|
1651 || DECL_EXTERNAL (decl)
|
131
|
1652 /* PR sanitizer/81697: For architectures that use section anchors first
|
|
1653 call to asan_protect_global may occur before DECL_RTL (decl) is set.
|
|
1654 We should ignore DECL_RTL_SET_P then, because otherwise the first call
|
|
1655 to asan_protect_global will return FALSE and the following calls on the
|
|
1656 same decl after setting DECL_RTL (decl) will return TRUE and we'll end
|
|
1657 up with inconsistency at runtime. */
|
|
1658 || (!DECL_RTL_SET_P (decl) && !ignore_decl_rtl_set_p)
|
111
|
1659 /* Comdat vars pose an ABI problem, we can't know if
|
|
1660 the var that is selected by the linker will have
|
|
1661 padding or not. */
|
|
1662 || DECL_ONE_ONLY (decl)
|
|
1663 /* Similarly for common vars. People can use -fno-common.
|
|
1664 Note: Linux kernel is built with -fno-common, so we do instrument
|
|
1665 globals there even if it is C. */
|
|
1666 || (DECL_COMMON (decl) && TREE_PUBLIC (decl))
|
|
1667 /* Don't protect if using user section, often vars placed
|
|
1668 into user section from multiple TUs are then assumed
|
|
1669 to be an array of such vars, putting padding in there
|
|
1670 breaks this assumption. */
|
|
1671 || (DECL_SECTION_NAME (decl) != NULL
|
|
1672 && !symtab_node::get (decl)->implicit_section
|
|
1673 && !section_sanitized_p (DECL_SECTION_NAME (decl)))
|
|
1674 || DECL_SIZE (decl) == 0
|
|
1675 || ASAN_RED_ZONE_SIZE * BITS_PER_UNIT > MAX_OFILE_ALIGNMENT
|
131
|
1676 || TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST
|
111
|
1677 || !valid_constant_size_p (DECL_SIZE_UNIT (decl))
|
|
1678 || DECL_ALIGN_UNIT (decl) > 2 * ASAN_RED_ZONE_SIZE
|
|
1679 || TREE_TYPE (decl) == ubsan_get_source_location_type ()
|
|
1680 || is_odr_indicator (decl))
|
|
1681 return false;
|
|
1682
|
131
|
1683 if (!ignore_decl_rtl_set_p || DECL_RTL_SET_P (decl))
|
|
1684 {
|
|
1685
|
|
1686 rtl = DECL_RTL (decl);
|
|
1687 if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF)
|
|
1688 return false;
|
|
1689 symbol = XEXP (rtl, 0);
|
|
1690
|
|
1691 if (CONSTANT_POOL_ADDRESS_P (symbol)
|
|
1692 || TREE_CONSTANT_POOL_ADDRESS_P (symbol))
|
|
1693 return false;
|
|
1694 }
|
111
|
1695
|
|
1696 if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
|
|
1697 return false;
|
|
1698
|
|
1699 if (!TARGET_SUPPORTS_ALIASES && asan_needs_local_alias (decl))
|
|
1700 return false;
|
|
1701
|
|
1702 return true;
|
|
1703 }
|
|
1704
|
|
1705 /* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16,_n}.
|
|
1706 IS_STORE is either 1 (for a store) or 0 (for a load). */
|
|
1707
|
|
1708 static tree
|
|
1709 report_error_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
|
|
1710 int *nargs)
|
|
1711 {
|
|
1712 static enum built_in_function report[2][2][6]
|
|
1713 = { { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
|
|
1714 BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
|
|
1715 BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
|
|
1716 { BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
|
|
1717 BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
|
|
1718 BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } },
|
|
1719 { { BUILT_IN_ASAN_REPORT_LOAD1_NOABORT,
|
|
1720 BUILT_IN_ASAN_REPORT_LOAD2_NOABORT,
|
|
1721 BUILT_IN_ASAN_REPORT_LOAD4_NOABORT,
|
|
1722 BUILT_IN_ASAN_REPORT_LOAD8_NOABORT,
|
|
1723 BUILT_IN_ASAN_REPORT_LOAD16_NOABORT,
|
|
1724 BUILT_IN_ASAN_REPORT_LOAD_N_NOABORT },
|
|
1725 { BUILT_IN_ASAN_REPORT_STORE1_NOABORT,
|
|
1726 BUILT_IN_ASAN_REPORT_STORE2_NOABORT,
|
|
1727 BUILT_IN_ASAN_REPORT_STORE4_NOABORT,
|
|
1728 BUILT_IN_ASAN_REPORT_STORE8_NOABORT,
|
|
1729 BUILT_IN_ASAN_REPORT_STORE16_NOABORT,
|
|
1730 BUILT_IN_ASAN_REPORT_STORE_N_NOABORT } } };
|
|
1731 if (size_in_bytes == -1)
|
|
1732 {
|
|
1733 *nargs = 2;
|
|
1734 return builtin_decl_implicit (report[recover_p][is_store][5]);
|
|
1735 }
|
|
1736 *nargs = 1;
|
|
1737 int size_log2 = exact_log2 (size_in_bytes);
|
|
1738 return builtin_decl_implicit (report[recover_p][is_store][size_log2]);
|
|
1739 }
|
|
1740
|
|
1741 /* Construct a function tree for __asan_{load,store}{1,2,4,8,16,_n}.
|
|
1742 IS_STORE is either 1 (for a store) or 0 (for a load). */
|
|
1743
|
|
1744 static tree
|
|
1745 check_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
|
|
1746 int *nargs)
|
|
1747 {
|
|
1748 static enum built_in_function check[2][2][6]
|
|
1749 = { { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2,
|
|
1750 BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
|
|
1751 BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
|
|
1752 { BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2,
|
|
1753 BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
|
|
1754 BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } },
|
|
1755 { { BUILT_IN_ASAN_LOAD1_NOABORT,
|
|
1756 BUILT_IN_ASAN_LOAD2_NOABORT,
|
|
1757 BUILT_IN_ASAN_LOAD4_NOABORT,
|
|
1758 BUILT_IN_ASAN_LOAD8_NOABORT,
|
|
1759 BUILT_IN_ASAN_LOAD16_NOABORT,
|
|
1760 BUILT_IN_ASAN_LOADN_NOABORT },
|
|
1761 { BUILT_IN_ASAN_STORE1_NOABORT,
|
|
1762 BUILT_IN_ASAN_STORE2_NOABORT,
|
|
1763 BUILT_IN_ASAN_STORE4_NOABORT,
|
|
1764 BUILT_IN_ASAN_STORE8_NOABORT,
|
|
1765 BUILT_IN_ASAN_STORE16_NOABORT,
|
|
1766 BUILT_IN_ASAN_STOREN_NOABORT } } };
|
|
1767 if (size_in_bytes == -1)
|
|
1768 {
|
|
1769 *nargs = 2;
|
|
1770 return builtin_decl_implicit (check[recover_p][is_store][5]);
|
|
1771 }
|
|
1772 *nargs = 1;
|
|
1773 int size_log2 = exact_log2 (size_in_bytes);
|
|
1774 return builtin_decl_implicit (check[recover_p][is_store][size_log2]);
|
|
1775 }
|
|
1776
|
|
1777 /* Split the current basic block and create a condition statement
|
|
1778 insertion point right before or after the statement pointed to by
|
|
1779 ITER. Return an iterator to the point at which the caller might
|
|
1780 safely insert the condition statement.
|
|
1781
|
|
1782 THEN_BLOCK must be set to the address of an uninitialized instance
|
|
1783 of basic_block. The function will then set *THEN_BLOCK to the
|
|
1784 'then block' of the condition statement to be inserted by the
|
|
1785 caller.
|
|
1786
|
|
1787 If CREATE_THEN_FALLTHRU_EDGE is false, no edge will be created from
|
|
1788 *THEN_BLOCK to *FALLTHROUGH_BLOCK.
|
|
1789
|
|
1790 Similarly, the function will set *FALLTRHOUGH_BLOCK to the 'else
|
|
1791 block' of the condition statement to be inserted by the caller.
|
|
1792
|
|
1793 Note that *FALLTHROUGH_BLOCK is a new block that contains the
|
|
1794 statements starting from *ITER, and *THEN_BLOCK is a new empty
|
|
1795 block.
|
|
1796
|
|
1797 *ITER is adjusted to point to always point to the first statement
|
|
1798 of the basic block * FALLTHROUGH_BLOCK. That statement is the
|
|
1799 same as what ITER was pointing to prior to calling this function,
|
|
1800 if BEFORE_P is true; otherwise, it is its following statement. */
|
|
1801
|
|
1802 gimple_stmt_iterator
|
|
1803 create_cond_insert_point (gimple_stmt_iterator *iter,
|
|
1804 bool before_p,
|
|
1805 bool then_more_likely_p,
|
|
1806 bool create_then_fallthru_edge,
|
|
1807 basic_block *then_block,
|
|
1808 basic_block *fallthrough_block)
|
|
1809 {
|
|
1810 gimple_stmt_iterator gsi = *iter;
|
|
1811
|
|
1812 if (!gsi_end_p (gsi) && before_p)
|
|
1813 gsi_prev (&gsi);
|
|
1814
|
|
1815 basic_block cur_bb = gsi_bb (*iter);
|
|
1816
|
|
1817 edge e = split_block (cur_bb, gsi_stmt (gsi));
|
|
1818
|
|
1819 /* Get a hold on the 'condition block', the 'then block' and the
|
|
1820 'else block'. */
|
|
1821 basic_block cond_bb = e->src;
|
|
1822 basic_block fallthru_bb = e->dest;
|
|
1823 basic_block then_bb = create_empty_bb (cond_bb);
|
|
1824 if (current_loops)
|
|
1825 {
|
|
1826 add_bb_to_loop (then_bb, cond_bb->loop_father);
|
|
1827 loops_state_set (LOOPS_NEED_FIXUP);
|
|
1828 }
|
|
1829
|
|
1830 /* Set up the newly created 'then block'. */
|
|
1831 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
|
|
1832 profile_probability fallthrough_probability
|
|
1833 = then_more_likely_p
|
|
1834 ? profile_probability::very_unlikely ()
|
|
1835 : profile_probability::very_likely ();
|
|
1836 e->probability = fallthrough_probability.invert ();
|
131
|
1837 then_bb->count = e->count ();
|
111
|
1838 if (create_then_fallthru_edge)
|
|
1839 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
|
|
1840
|
|
1841 /* Set up the fallthrough basic block. */
|
|
1842 e = find_edge (cond_bb, fallthru_bb);
|
|
1843 e->flags = EDGE_FALSE_VALUE;
|
|
1844 e->probability = fallthrough_probability;
|
|
1845
|
|
1846 /* Update dominance info for the newly created then_bb; note that
|
|
1847 fallthru_bb's dominance info has already been updated by
|
|
1848 split_bock. */
|
|
1849 if (dom_info_available_p (CDI_DOMINATORS))
|
|
1850 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
|
|
1851
|
|
1852 *then_block = then_bb;
|
|
1853 *fallthrough_block = fallthru_bb;
|
|
1854 *iter = gsi_start_bb (fallthru_bb);
|
|
1855
|
|
1856 return gsi_last_bb (cond_bb);
|
|
1857 }
|
|
1858
|
|
1859 /* Insert an if condition followed by a 'then block' right before the
|
|
1860 statement pointed to by ITER. The fallthrough block -- which is the
|
|
1861 else block of the condition as well as the destination of the
|
|
1862 outcoming edge of the 'then block' -- starts with the statement
|
|
1863 pointed to by ITER.
|
|
1864
|
|
1865 COND is the condition of the if.
|
|
1866
|
|
1867 If THEN_MORE_LIKELY_P is true, the probability of the edge to the
|
|
1868 'then block' is higher than the probability of the edge to the
|
|
1869 fallthrough block.
|
|
1870
|
|
1871 Upon completion of the function, *THEN_BB is set to the newly
|
|
1872 inserted 'then block' and similarly, *FALLTHROUGH_BB is set to the
|
|
1873 fallthrough block.
|
|
1874
|
|
1875 *ITER is adjusted to still point to the same statement it was
|
|
1876 pointing to initially. */
|
|
1877
|
|
1878 static void
|
|
1879 insert_if_then_before_iter (gcond *cond,
|
|
1880 gimple_stmt_iterator *iter,
|
|
1881 bool then_more_likely_p,
|
|
1882 basic_block *then_bb,
|
|
1883 basic_block *fallthrough_bb)
|
|
1884 {
|
|
1885 gimple_stmt_iterator cond_insert_point =
|
|
1886 create_cond_insert_point (iter,
|
|
1887 /*before_p=*/true,
|
|
1888 then_more_likely_p,
|
|
1889 /*create_then_fallthru_edge=*/true,
|
|
1890 then_bb,
|
|
1891 fallthrough_bb);
|
|
1892 gsi_insert_after (&cond_insert_point, cond, GSI_NEW_STMT);
|
|
1893 }
|
|
1894
|
|
1895 /* Build (base_addr >> ASAN_SHADOW_SHIFT) + asan_shadow_offset ().
|
|
1896 If RETURN_ADDRESS is set to true, return memory location instread
|
|
1897 of a value in the shadow memory. */
|
|
1898
|
|
1899 static tree
|
|
1900 build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
|
|
1901 tree base_addr, tree shadow_ptr_type,
|
|
1902 bool return_address = false)
|
|
1903 {
|
|
1904 tree t, uintptr_type = TREE_TYPE (base_addr);
|
|
1905 tree shadow_type = TREE_TYPE (shadow_ptr_type);
|
|
1906 gimple *g;
|
|
1907
|
|
1908 t = build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT);
|
|
1909 g = gimple_build_assign (make_ssa_name (uintptr_type), RSHIFT_EXPR,
|
|
1910 base_addr, t);
|
|
1911 gimple_set_location (g, location);
|
|
1912 gsi_insert_after (gsi, g, GSI_NEW_STMT);
|
|
1913
|
|
1914 t = build_int_cst (uintptr_type, asan_shadow_offset ());
|
|
1915 g = gimple_build_assign (make_ssa_name (uintptr_type), PLUS_EXPR,
|
|
1916 gimple_assign_lhs (g), t);
|
|
1917 gimple_set_location (g, location);
|
|
1918 gsi_insert_after (gsi, g, GSI_NEW_STMT);
|
|
1919
|
|
1920 g = gimple_build_assign (make_ssa_name (shadow_ptr_type), NOP_EXPR,
|
|
1921 gimple_assign_lhs (g));
|
|
1922 gimple_set_location (g, location);
|
|
1923 gsi_insert_after (gsi, g, GSI_NEW_STMT);
|
|
1924
|
|
1925 if (!return_address)
|
|
1926 {
|
|
1927 t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g),
|
|
1928 build_int_cst (shadow_ptr_type, 0));
|
|
1929 g = gimple_build_assign (make_ssa_name (shadow_type), MEM_REF, t);
|
|
1930 gimple_set_location (g, location);
|
|
1931 gsi_insert_after (gsi, g, GSI_NEW_STMT);
|
|
1932 }
|
|
1933
|
|
1934 return gimple_assign_lhs (g);
|
|
1935 }
|
|
1936
|
|
1937 /* BASE can already be an SSA_NAME; in that case, do not create a
|
|
1938 new SSA_NAME for it. */
|
|
1939
|
|
1940 static tree
|
|
1941 maybe_create_ssa_name (location_t loc, tree base, gimple_stmt_iterator *iter,
|
|
1942 bool before_p)
|
|
1943 {
|
|
1944 if (TREE_CODE (base) == SSA_NAME)
|
|
1945 return base;
|
|
1946 gimple *g = gimple_build_assign (make_ssa_name (TREE_TYPE (base)),
|
|
1947 TREE_CODE (base), base);
|
|
1948 gimple_set_location (g, loc);
|
|
1949 if (before_p)
|
|
1950 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
1951 else
|
|
1952 gsi_insert_after (iter, g, GSI_NEW_STMT);
|
|
1953 return gimple_assign_lhs (g);
|
|
1954 }
|
|
1955
|
|
1956 /* LEN can already have necessary size and precision;
|
|
1957 in that case, do not create a new variable. */
|
|
1958
|
|
1959 tree
|
|
1960 maybe_cast_to_ptrmode (location_t loc, tree len, gimple_stmt_iterator *iter,
|
|
1961 bool before_p)
|
|
1962 {
|
|
1963 if (ptrofftype_p (len))
|
|
1964 return len;
|
|
1965 gimple *g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
|
|
1966 NOP_EXPR, len);
|
|
1967 gimple_set_location (g, loc);
|
|
1968 if (before_p)
|
|
1969 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
1970 else
|
|
1971 gsi_insert_after (iter, g, GSI_NEW_STMT);
|
|
1972 return gimple_assign_lhs (g);
|
|
1973 }
|
|
1974
|
|
1975 /* Instrument the memory access instruction BASE. Insert new
|
|
1976 statements before or after ITER.
|
|
1977
|
|
1978 Note that the memory access represented by BASE can be either an
|
|
1979 SSA_NAME, or a non-SSA expression. LOCATION is the source code
|
|
1980 location. IS_STORE is TRUE for a store, FALSE for a load.
|
|
1981 BEFORE_P is TRUE for inserting the instrumentation code before
|
|
1982 ITER, FALSE for inserting it after ITER. IS_SCALAR_ACCESS is TRUE
|
|
1983 for a scalar memory access and FALSE for memory region access.
|
|
1984 NON_ZERO_P is TRUE if memory region is guaranteed to have non-zero
|
|
1985 length. ALIGN tells alignment of accessed memory object.
|
|
1986
|
|
1987 START_INSTRUMENTED and END_INSTRUMENTED are TRUE if start/end of
|
|
1988 memory region have already been instrumented.
|
|
1989
|
|
1990 If BEFORE_P is TRUE, *ITER is arranged to still point to the
|
|
1991 statement it was pointing to prior to calling this function,
|
|
1992 otherwise, it points to the statement logically following it. */
|
|
1993
|
|
1994 static void
|
|
1995 build_check_stmt (location_t loc, tree base, tree len,
|
|
1996 HOST_WIDE_INT size_in_bytes, gimple_stmt_iterator *iter,
|
|
1997 bool is_non_zero_len, bool before_p, bool is_store,
|
|
1998 bool is_scalar_access, unsigned int align = 0)
|
|
1999 {
|
|
2000 gimple_stmt_iterator gsi = *iter;
|
|
2001 gimple *g;
|
|
2002
|
|
2003 gcc_assert (!(size_in_bytes > 0 && !is_non_zero_len));
|
|
2004
|
|
2005 gsi = *iter;
|
|
2006
|
|
2007 base = unshare_expr (base);
|
|
2008 base = maybe_create_ssa_name (loc, base, &gsi, before_p);
|
|
2009
|
|
2010 if (len)
|
|
2011 {
|
|
2012 len = unshare_expr (len);
|
|
2013 len = maybe_cast_to_ptrmode (loc, len, iter, before_p);
|
|
2014 }
|
|
2015 else
|
|
2016 {
|
|
2017 gcc_assert (size_in_bytes != -1);
|
|
2018 len = build_int_cst (pointer_sized_int_node, size_in_bytes);
|
|
2019 }
|
|
2020
|
|
2021 if (size_in_bytes > 1)
|
|
2022 {
|
|
2023 if ((size_in_bytes & (size_in_bytes - 1)) != 0
|
|
2024 || size_in_bytes > 16)
|
|
2025 is_scalar_access = false;
|
|
2026 else if (align && align < size_in_bytes * BITS_PER_UNIT)
|
|
2027 {
|
|
2028 /* On non-strict alignment targets, if
|
|
2029 16-byte access is just 8-byte aligned,
|
|
2030 this will result in misaligned shadow
|
|
2031 memory 2 byte load, but otherwise can
|
|
2032 be handled using one read. */
|
|
2033 if (size_in_bytes != 16
|
|
2034 || STRICT_ALIGNMENT
|
|
2035 || align < 8 * BITS_PER_UNIT)
|
|
2036 is_scalar_access = false;
|
|
2037 }
|
|
2038 }
|
|
2039
|
|
2040 HOST_WIDE_INT flags = 0;
|
|
2041 if (is_store)
|
|
2042 flags |= ASAN_CHECK_STORE;
|
|
2043 if (is_non_zero_len)
|
|
2044 flags |= ASAN_CHECK_NON_ZERO_LEN;
|
|
2045 if (is_scalar_access)
|
|
2046 flags |= ASAN_CHECK_SCALAR_ACCESS;
|
|
2047
|
|
2048 g = gimple_build_call_internal (IFN_ASAN_CHECK, 4,
|
|
2049 build_int_cst (integer_type_node, flags),
|
|
2050 base, len,
|
|
2051 build_int_cst (integer_type_node,
|
|
2052 align / BITS_PER_UNIT));
|
|
2053 gimple_set_location (g, loc);
|
|
2054 if (before_p)
|
|
2055 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
|
|
2056 else
|
|
2057 {
|
|
2058 gsi_insert_after (&gsi, g, GSI_NEW_STMT);
|
|
2059 gsi_next (&gsi);
|
|
2060 *iter = gsi;
|
|
2061 }
|
|
2062 }
|
|
2063
|
|
2064 /* If T represents a memory access, add instrumentation code before ITER.
|
|
2065 LOCATION is source code location.
|
|
2066 IS_STORE is either TRUE (for a store) or FALSE (for a load). */
|
|
2067
|
|
2068 static void
|
|
2069 instrument_derefs (gimple_stmt_iterator *iter, tree t,
|
|
2070 location_t location, bool is_store)
|
|
2071 {
|
|
2072 if (is_store && !ASAN_INSTRUMENT_WRITES)
|
|
2073 return;
|
|
2074 if (!is_store && !ASAN_INSTRUMENT_READS)
|
|
2075 return;
|
|
2076
|
|
2077 tree type, base;
|
|
2078 HOST_WIDE_INT size_in_bytes;
|
|
2079 if (location == UNKNOWN_LOCATION)
|
|
2080 location = EXPR_LOCATION (t);
|
|
2081
|
|
2082 type = TREE_TYPE (t);
|
|
2083 switch (TREE_CODE (t))
|
|
2084 {
|
|
2085 case ARRAY_REF:
|
|
2086 case COMPONENT_REF:
|
|
2087 case INDIRECT_REF:
|
|
2088 case MEM_REF:
|
|
2089 case VAR_DECL:
|
|
2090 case BIT_FIELD_REF:
|
|
2091 break;
|
|
2092 /* FALLTHRU */
|
|
2093 default:
|
|
2094 return;
|
|
2095 }
|
|
2096
|
|
2097 size_in_bytes = int_size_in_bytes (type);
|
|
2098 if (size_in_bytes <= 0)
|
|
2099 return;
|
|
2100
|
131
|
2101 poly_int64 bitsize, bitpos;
|
111
|
2102 tree offset;
|
|
2103 machine_mode mode;
|
|
2104 int unsignedp, reversep, volatilep = 0;
|
|
2105 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
|
|
2106 &unsignedp, &reversep, &volatilep);
|
|
2107
|
|
2108 if (TREE_CODE (t) == COMPONENT_REF
|
|
2109 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
|
|
2110 {
|
|
2111 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
|
|
2112 instrument_derefs (iter, build3 (COMPONENT_REF, TREE_TYPE (repr),
|
|
2113 TREE_OPERAND (t, 0), repr,
|
|
2114 TREE_OPERAND (t, 2)),
|
|
2115 location, is_store);
|
|
2116 return;
|
|
2117 }
|
|
2118
|
131
|
2119 if (!multiple_p (bitpos, BITS_PER_UNIT)
|
|
2120 || maybe_ne (bitsize, size_in_bytes * BITS_PER_UNIT))
|
111
|
2121 return;
|
|
2122
|
|
2123 if (VAR_P (inner) && DECL_HARD_REGISTER (inner))
|
|
2124 return;
|
|
2125
|
131
|
2126 poly_int64 decl_size;
|
111
|
2127 if (VAR_P (inner)
|
|
2128 && offset == NULL_TREE
|
|
2129 && DECL_SIZE (inner)
|
131
|
2130 && poly_int_tree_p (DECL_SIZE (inner), &decl_size)
|
|
2131 && known_subrange_p (bitpos, bitsize, 0, decl_size))
|
111
|
2132 {
|
|
2133 if (DECL_THREAD_LOCAL_P (inner))
|
|
2134 return;
|
|
2135 if (!ASAN_GLOBALS && is_global_var (inner))
|
|
2136 return;
|
|
2137 if (!TREE_STATIC (inner))
|
|
2138 {
|
|
2139 /* Automatic vars in the current function will be always
|
|
2140 accessible. */
|
|
2141 if (decl_function_context (inner) == current_function_decl
|
|
2142 && (!asan_sanitize_use_after_scope ()
|
|
2143 || !TREE_ADDRESSABLE (inner)))
|
|
2144 return;
|
|
2145 }
|
|
2146 /* Always instrument external vars, they might be dynamically
|
|
2147 initialized. */
|
|
2148 else if (!DECL_EXTERNAL (inner))
|
|
2149 {
|
|
2150 /* For static vars if they are known not to be dynamically
|
|
2151 initialized, they will be always accessible. */
|
|
2152 varpool_node *vnode = varpool_node::get (inner);
|
|
2153 if (vnode && !vnode->dynamically_initialized)
|
|
2154 return;
|
|
2155 }
|
|
2156 }
|
|
2157
|
|
2158 base = build_fold_addr_expr (t);
|
|
2159 if (!has_mem_ref_been_instrumented (base, size_in_bytes))
|
|
2160 {
|
|
2161 unsigned int align = get_object_alignment (t);
|
|
2162 build_check_stmt (location, base, NULL_TREE, size_in_bytes, iter,
|
|
2163 /*is_non_zero_len*/size_in_bytes > 0, /*before_p=*/true,
|
|
2164 is_store, /*is_scalar_access*/true, align);
|
|
2165 update_mem_ref_hash_table (base, size_in_bytes);
|
|
2166 update_mem_ref_hash_table (t, size_in_bytes);
|
|
2167 }
|
|
2168
|
|
2169 }
|
|
2170
|
|
2171 /* Insert a memory reference into the hash table if access length
|
|
2172 can be determined in compile time. */
|
|
2173
|
|
2174 static void
|
|
2175 maybe_update_mem_ref_hash_table (tree base, tree len)
|
|
2176 {
|
|
2177 if (!POINTER_TYPE_P (TREE_TYPE (base))
|
|
2178 || !INTEGRAL_TYPE_P (TREE_TYPE (len)))
|
|
2179 return;
|
|
2180
|
|
2181 HOST_WIDE_INT size_in_bytes = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
|
|
2182
|
|
2183 if (size_in_bytes != -1)
|
|
2184 update_mem_ref_hash_table (base, size_in_bytes);
|
|
2185 }
|
|
2186
|
|
2187 /* Instrument an access to a contiguous memory region that starts at
|
|
2188 the address pointed to by BASE, over a length of LEN (expressed in
|
|
2189 the sizeof (*BASE) bytes). ITER points to the instruction before
|
|
2190 which the instrumentation instructions must be inserted. LOCATION
|
|
2191 is the source location that the instrumentation instructions must
|
|
2192 have. If IS_STORE is true, then the memory access is a store;
|
|
2193 otherwise, it's a load. */
|
|
2194
|
|
2195 static void
|
|
2196 instrument_mem_region_access (tree base, tree len,
|
|
2197 gimple_stmt_iterator *iter,
|
|
2198 location_t location, bool is_store)
|
|
2199 {
|
|
2200 if (!POINTER_TYPE_P (TREE_TYPE (base))
|
|
2201 || !INTEGRAL_TYPE_P (TREE_TYPE (len))
|
|
2202 || integer_zerop (len))
|
|
2203 return;
|
|
2204
|
|
2205 HOST_WIDE_INT size_in_bytes = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
|
|
2206
|
|
2207 if ((size_in_bytes == -1)
|
|
2208 || !has_mem_ref_been_instrumented (base, size_in_bytes))
|
|
2209 {
|
|
2210 build_check_stmt (location, base, len, size_in_bytes, iter,
|
|
2211 /*is_non_zero_len*/size_in_bytes > 0, /*before_p*/true,
|
|
2212 is_store, /*is_scalar_access*/false, /*align*/0);
|
|
2213 }
|
|
2214
|
|
2215 maybe_update_mem_ref_hash_table (base, len);
|
|
2216 *iter = gsi_for_stmt (gsi_stmt (*iter));
|
|
2217 }
|
|
2218
|
|
2219 /* Instrument the call to a built-in memory access function that is
|
|
2220 pointed to by the iterator ITER.
|
|
2221
|
|
2222 Upon completion, return TRUE iff *ITER has been advanced to the
|
|
2223 statement following the one it was originally pointing to. */
|
|
2224
|
|
2225 static bool
|
|
2226 instrument_builtin_call (gimple_stmt_iterator *iter)
|
|
2227 {
|
|
2228 if (!ASAN_MEMINTRIN)
|
|
2229 return false;
|
|
2230
|
|
2231 bool iter_advanced_p = false;
|
|
2232 gcall *call = as_a <gcall *> (gsi_stmt (*iter));
|
|
2233
|
|
2234 gcc_checking_assert (gimple_call_builtin_p (call, BUILT_IN_NORMAL));
|
|
2235
|
|
2236 location_t loc = gimple_location (call);
|
|
2237
|
|
2238 asan_mem_ref src0, src1, dest;
|
|
2239 asan_mem_ref_init (&src0, NULL, 1);
|
|
2240 asan_mem_ref_init (&src1, NULL, 1);
|
|
2241 asan_mem_ref_init (&dest, NULL, 1);
|
|
2242
|
|
2243 tree src0_len = NULL_TREE, src1_len = NULL_TREE, dest_len = NULL_TREE;
|
|
2244 bool src0_is_store = false, src1_is_store = false, dest_is_store = false,
|
|
2245 dest_is_deref = false, intercepted_p = true;
|
|
2246
|
|
2247 if (get_mem_refs_of_builtin_call (call,
|
|
2248 &src0, &src0_len, &src0_is_store,
|
|
2249 &src1, &src1_len, &src1_is_store,
|
|
2250 &dest, &dest_len, &dest_is_store,
|
|
2251 &dest_is_deref, &intercepted_p, iter))
|
|
2252 {
|
|
2253 if (dest_is_deref)
|
|
2254 {
|
|
2255 instrument_derefs (iter, dest.start, loc, dest_is_store);
|
|
2256 gsi_next (iter);
|
|
2257 iter_advanced_p = true;
|
|
2258 }
|
|
2259 else if (!intercepted_p
|
|
2260 && (src0_len || src1_len || dest_len))
|
|
2261 {
|
|
2262 if (src0.start != NULL_TREE)
|
|
2263 instrument_mem_region_access (src0.start, src0_len,
|
|
2264 iter, loc, /*is_store=*/false);
|
|
2265 if (src1.start != NULL_TREE)
|
|
2266 instrument_mem_region_access (src1.start, src1_len,
|
|
2267 iter, loc, /*is_store=*/false);
|
|
2268 if (dest.start != NULL_TREE)
|
|
2269 instrument_mem_region_access (dest.start, dest_len,
|
|
2270 iter, loc, /*is_store=*/true);
|
|
2271
|
|
2272 *iter = gsi_for_stmt (call);
|
|
2273 gsi_next (iter);
|
|
2274 iter_advanced_p = true;
|
|
2275 }
|
|
2276 else
|
|
2277 {
|
|
2278 if (src0.start != NULL_TREE)
|
|
2279 maybe_update_mem_ref_hash_table (src0.start, src0_len);
|
|
2280 if (src1.start != NULL_TREE)
|
|
2281 maybe_update_mem_ref_hash_table (src1.start, src1_len);
|
|
2282 if (dest.start != NULL_TREE)
|
|
2283 maybe_update_mem_ref_hash_table (dest.start, dest_len);
|
|
2284 }
|
|
2285 }
|
|
2286 return iter_advanced_p;
|
|
2287 }
|
|
2288
|
|
2289 /* Instrument the assignment statement ITER if it is subject to
|
|
2290 instrumentation. Return TRUE iff instrumentation actually
|
|
2291 happened. In that case, the iterator ITER is advanced to the next
|
|
2292 logical expression following the one initially pointed to by ITER,
|
|
2293 and the relevant memory reference that which access has been
|
|
2294 instrumented is added to the memory references hash table. */
|
|
2295
|
|
2296 static bool
|
|
2297 maybe_instrument_assignment (gimple_stmt_iterator *iter)
|
|
2298 {
|
|
2299 gimple *s = gsi_stmt (*iter);
|
|
2300
|
|
2301 gcc_assert (gimple_assign_single_p (s));
|
|
2302
|
|
2303 tree ref_expr = NULL_TREE;
|
|
2304 bool is_store, is_instrumented = false;
|
|
2305
|
|
2306 if (gimple_store_p (s))
|
|
2307 {
|
|
2308 ref_expr = gimple_assign_lhs (s);
|
|
2309 is_store = true;
|
|
2310 instrument_derefs (iter, ref_expr,
|
|
2311 gimple_location (s),
|
|
2312 is_store);
|
|
2313 is_instrumented = true;
|
|
2314 }
|
|
2315
|
|
2316 if (gimple_assign_load_p (s))
|
|
2317 {
|
|
2318 ref_expr = gimple_assign_rhs1 (s);
|
|
2319 is_store = false;
|
|
2320 instrument_derefs (iter, ref_expr,
|
|
2321 gimple_location (s),
|
|
2322 is_store);
|
|
2323 is_instrumented = true;
|
|
2324 }
|
|
2325
|
|
2326 if (is_instrumented)
|
|
2327 gsi_next (iter);
|
|
2328
|
|
2329 return is_instrumented;
|
|
2330 }
|
|
2331
|
|
2332 /* Instrument the function call pointed to by the iterator ITER, if it
|
|
2333 is subject to instrumentation. At the moment, the only function
|
|
2334 calls that are instrumented are some built-in functions that access
|
|
2335 memory. Look at instrument_builtin_call to learn more.
|
|
2336
|
|
2337 Upon completion return TRUE iff *ITER was advanced to the statement
|
|
2338 following the one it was originally pointing to. */
|
|
2339
|
|
2340 static bool
|
|
2341 maybe_instrument_call (gimple_stmt_iterator *iter)
|
|
2342 {
|
|
2343 gimple *stmt = gsi_stmt (*iter);
|
|
2344 bool is_builtin = gimple_call_builtin_p (stmt, BUILT_IN_NORMAL);
|
|
2345
|
|
2346 if (is_builtin && instrument_builtin_call (iter))
|
|
2347 return true;
|
|
2348
|
|
2349 if (gimple_call_noreturn_p (stmt))
|
|
2350 {
|
|
2351 if (is_builtin)
|
|
2352 {
|
|
2353 tree callee = gimple_call_fndecl (stmt);
|
|
2354 switch (DECL_FUNCTION_CODE (callee))
|
|
2355 {
|
|
2356 case BUILT_IN_UNREACHABLE:
|
|
2357 case BUILT_IN_TRAP:
|
|
2358 /* Don't instrument these. */
|
|
2359 return false;
|
|
2360 default:
|
|
2361 break;
|
|
2362 }
|
|
2363 }
|
|
2364 tree decl = builtin_decl_implicit (BUILT_IN_ASAN_HANDLE_NO_RETURN);
|
|
2365 gimple *g = gimple_build_call (decl, 0);
|
|
2366 gimple_set_location (g, gimple_location (stmt));
|
|
2367 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
2368 }
|
|
2369
|
|
2370 bool instrumented = false;
|
|
2371 if (gimple_store_p (stmt))
|
|
2372 {
|
|
2373 tree ref_expr = gimple_call_lhs (stmt);
|
|
2374 instrument_derefs (iter, ref_expr,
|
|
2375 gimple_location (stmt),
|
|
2376 /*is_store=*/true);
|
|
2377
|
|
2378 instrumented = true;
|
|
2379 }
|
|
2380
|
|
2381 /* Walk through gimple_call arguments and check them id needed. */
|
|
2382 unsigned args_num = gimple_call_num_args (stmt);
|
|
2383 for (unsigned i = 0; i < args_num; ++i)
|
|
2384 {
|
|
2385 tree arg = gimple_call_arg (stmt, i);
|
|
2386 /* If ARG is not a non-aggregate register variable, compiler in general
|
|
2387 creates temporary for it and pass it as argument to gimple call.
|
|
2388 But in some cases, e.g. when we pass by value a small structure that
|
|
2389 fits to register, compiler can avoid extra overhead by pulling out
|
|
2390 these temporaries. In this case, we should check the argument. */
|
|
2391 if (!is_gimple_reg (arg) && !is_gimple_min_invariant (arg))
|
|
2392 {
|
|
2393 instrument_derefs (iter, arg,
|
|
2394 gimple_location (stmt),
|
|
2395 /*is_store=*/false);
|
|
2396 instrumented = true;
|
|
2397 }
|
|
2398 }
|
|
2399 if (instrumented)
|
|
2400 gsi_next (iter);
|
|
2401 return instrumented;
|
|
2402 }
|
|
2403
|
|
2404 /* Walk each instruction of all basic block and instrument those that
|
|
2405 represent memory references: loads, stores, or function calls.
|
|
2406 In a given basic block, this function avoids instrumenting memory
|
|
2407 references that have already been instrumented. */
|
|
2408
|
|
2409 static void
|
|
2410 transform_statements (void)
|
|
2411 {
|
|
2412 basic_block bb, last_bb = NULL;
|
|
2413 gimple_stmt_iterator i;
|
|
2414 int saved_last_basic_block = last_basic_block_for_fn (cfun);
|
|
2415
|
|
2416 FOR_EACH_BB_FN (bb, cfun)
|
|
2417 {
|
|
2418 basic_block prev_bb = bb;
|
|
2419
|
|
2420 if (bb->index >= saved_last_basic_block) continue;
|
|
2421
|
|
2422 /* Flush the mem ref hash table, if current bb doesn't have
|
|
2423 exactly one predecessor, or if that predecessor (skipping
|
|
2424 over asan created basic blocks) isn't the last processed
|
|
2425 basic block. Thus we effectively flush on extended basic
|
|
2426 block boundaries. */
|
|
2427 while (single_pred_p (prev_bb))
|
|
2428 {
|
|
2429 prev_bb = single_pred (prev_bb);
|
|
2430 if (prev_bb->index < saved_last_basic_block)
|
|
2431 break;
|
|
2432 }
|
|
2433 if (prev_bb != last_bb)
|
|
2434 empty_mem_ref_hash_table ();
|
|
2435 last_bb = bb;
|
|
2436
|
|
2437 for (i = gsi_start_bb (bb); !gsi_end_p (i);)
|
|
2438 {
|
|
2439 gimple *s = gsi_stmt (i);
|
|
2440
|
|
2441 if (has_stmt_been_instrumented_p (s))
|
|
2442 gsi_next (&i);
|
|
2443 else if (gimple_assign_single_p (s)
|
|
2444 && !gimple_clobber_p (s)
|
|
2445 && maybe_instrument_assignment (&i))
|
|
2446 /* Nothing to do as maybe_instrument_assignment advanced
|
|
2447 the iterator I. */;
|
|
2448 else if (is_gimple_call (s) && maybe_instrument_call (&i))
|
|
2449 /* Nothing to do as maybe_instrument_call
|
|
2450 advanced the iterator I. */;
|
|
2451 else
|
|
2452 {
|
|
2453 /* No instrumentation happened.
|
|
2454
|
|
2455 If the current instruction is a function call that
|
|
2456 might free something, let's forget about the memory
|
|
2457 references that got instrumented. Otherwise we might
|
|
2458 miss some instrumentation opportunities. Do the same
|
|
2459 for a ASAN_MARK poisoning internal function. */
|
|
2460 if (is_gimple_call (s)
|
|
2461 && (!nonfreeing_call_p (s)
|
|
2462 || asan_mark_p (s, ASAN_MARK_POISON)))
|
|
2463 empty_mem_ref_hash_table ();
|
|
2464
|
|
2465 gsi_next (&i);
|
|
2466 }
|
|
2467 }
|
|
2468 }
|
|
2469 free_mem_ref_resources ();
|
|
2470 }
|
|
2471
|
|
2472 /* Build
|
|
2473 __asan_before_dynamic_init (module_name)
|
|
2474 or
|
|
2475 __asan_after_dynamic_init ()
|
|
2476 call. */
|
|
2477
|
|
2478 tree
|
|
2479 asan_dynamic_init_call (bool after_p)
|
|
2480 {
|
|
2481 if (shadow_ptr_types[0] == NULL_TREE)
|
|
2482 asan_init_shadow_ptr_types ();
|
|
2483
|
|
2484 tree fn = builtin_decl_implicit (after_p
|
|
2485 ? BUILT_IN_ASAN_AFTER_DYNAMIC_INIT
|
|
2486 : BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT);
|
|
2487 tree module_name_cst = NULL_TREE;
|
|
2488 if (!after_p)
|
|
2489 {
|
|
2490 pretty_printer module_name_pp;
|
|
2491 pp_string (&module_name_pp, main_input_filename);
|
|
2492
|
|
2493 module_name_cst = asan_pp_string (&module_name_pp);
|
|
2494 module_name_cst = fold_convert (const_ptr_type_node,
|
|
2495 module_name_cst);
|
|
2496 }
|
|
2497
|
|
2498 return build_call_expr (fn, after_p ? 0 : 1, module_name_cst);
|
|
2499 }
|
|
2500
|
|
2501 /* Build
|
|
2502 struct __asan_global
|
|
2503 {
|
|
2504 const void *__beg;
|
|
2505 uptr __size;
|
|
2506 uptr __size_with_redzone;
|
|
2507 const void *__name;
|
|
2508 const void *__module_name;
|
|
2509 uptr __has_dynamic_init;
|
|
2510 __asan_global_source_location *__location;
|
|
2511 char *__odr_indicator;
|
|
2512 } type. */
|
|
2513
|
|
2514 static tree
|
|
2515 asan_global_struct (void)
|
|
2516 {
|
|
2517 static const char *field_names[]
|
|
2518 = { "__beg", "__size", "__size_with_redzone",
|
|
2519 "__name", "__module_name", "__has_dynamic_init", "__location",
|
|
2520 "__odr_indicator" };
|
|
2521 tree fields[ARRAY_SIZE (field_names)], ret;
|
|
2522 unsigned i;
|
|
2523
|
|
2524 ret = make_node (RECORD_TYPE);
|
|
2525 for (i = 0; i < ARRAY_SIZE (field_names); i++)
|
|
2526 {
|
|
2527 fields[i]
|
|
2528 = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
|
|
2529 get_identifier (field_names[i]),
|
|
2530 (i == 0 || i == 3) ? const_ptr_type_node
|
|
2531 : pointer_sized_int_node);
|
|
2532 DECL_CONTEXT (fields[i]) = ret;
|
|
2533 if (i)
|
|
2534 DECL_CHAIN (fields[i - 1]) = fields[i];
|
|
2535 }
|
|
2536 tree type_decl = build_decl (input_location, TYPE_DECL,
|
|
2537 get_identifier ("__asan_global"), ret);
|
|
2538 DECL_IGNORED_P (type_decl) = 1;
|
|
2539 DECL_ARTIFICIAL (type_decl) = 1;
|
|
2540 TYPE_FIELDS (ret) = fields[0];
|
|
2541 TYPE_NAME (ret) = type_decl;
|
|
2542 TYPE_STUB_DECL (ret) = type_decl;
|
|
2543 layout_type (ret);
|
|
2544 return ret;
|
|
2545 }
|
|
2546
|
|
2547 /* Create and return odr indicator symbol for DECL.
|
|
2548 TYPE is __asan_global struct type as returned by asan_global_struct. */
|
|
2549
|
|
2550 static tree
|
|
2551 create_odr_indicator (tree decl, tree type)
|
|
2552 {
|
|
2553 char *name;
|
|
2554 tree uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type)));
|
|
2555 tree decl_name
|
|
2556 = (HAS_DECL_ASSEMBLER_NAME_P (decl) ? DECL_ASSEMBLER_NAME (decl)
|
|
2557 : DECL_NAME (decl));
|
|
2558 /* DECL_NAME theoretically might be NULL. Bail out with 0 in this case. */
|
|
2559 if (decl_name == NULL_TREE)
|
|
2560 return build_int_cst (uptr, 0);
|
|
2561 const char *dname = IDENTIFIER_POINTER (decl_name);
|
|
2562 if (HAS_DECL_ASSEMBLER_NAME_P (decl))
|
|
2563 dname = targetm.strip_name_encoding (dname);
|
|
2564 size_t len = strlen (dname) + sizeof ("__odr_asan_");
|
|
2565 name = XALLOCAVEC (char, len);
|
|
2566 snprintf (name, len, "__odr_asan_%s", dname);
|
|
2567 #ifndef NO_DOT_IN_LABEL
|
|
2568 name[sizeof ("__odr_asan") - 1] = '.';
|
|
2569 #elif !defined(NO_DOLLAR_IN_LABEL)
|
|
2570 name[sizeof ("__odr_asan") - 1] = '$';
|
|
2571 #endif
|
|
2572 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (name),
|
|
2573 char_type_node);
|
|
2574 TREE_ADDRESSABLE (var) = 1;
|
|
2575 TREE_READONLY (var) = 0;
|
|
2576 TREE_THIS_VOLATILE (var) = 1;
|
|
2577 DECL_GIMPLE_REG_P (var) = 0;
|
|
2578 DECL_ARTIFICIAL (var) = 1;
|
|
2579 DECL_IGNORED_P (var) = 1;
|
|
2580 TREE_STATIC (var) = 1;
|
|
2581 TREE_PUBLIC (var) = 1;
|
|
2582 DECL_VISIBILITY (var) = DECL_VISIBILITY (decl);
|
|
2583 DECL_VISIBILITY_SPECIFIED (var) = DECL_VISIBILITY_SPECIFIED (decl);
|
|
2584
|
|
2585 TREE_USED (var) = 1;
|
|
2586 tree ctor = build_constructor_va (TREE_TYPE (var), 1, NULL_TREE,
|
|
2587 build_int_cst (unsigned_type_node, 0));
|
|
2588 TREE_CONSTANT (ctor) = 1;
|
|
2589 TREE_STATIC (ctor) = 1;
|
|
2590 DECL_INITIAL (var) = ctor;
|
|
2591 DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("asan odr indicator"),
|
|
2592 NULL, DECL_ATTRIBUTES (var));
|
|
2593 make_decl_rtl (var);
|
|
2594 varpool_node::finalize_decl (var);
|
|
2595 return fold_convert (uptr, build_fold_addr_expr (var));
|
|
2596 }
|
|
2597
|
|
2598 /* Return true if DECL, a global var, might be overridden and needs
|
|
2599 an additional odr indicator symbol. */
|
|
2600
|
|
2601 static bool
|
|
2602 asan_needs_odr_indicator_p (tree decl)
|
|
2603 {
|
|
2604 /* Don't emit ODR indicators for kernel because:
|
|
2605 a) Kernel is written in C thus doesn't need ODR indicators.
|
|
2606 b) Some kernel code may have assumptions about symbols containing specific
|
|
2607 patterns in their names. Since ODR indicators contain original names
|
|
2608 of symbols they are emitted for, these assumptions would be broken for
|
|
2609 ODR indicator symbols. */
|
|
2610 return (!(flag_sanitize & SANITIZE_KERNEL_ADDRESS)
|
|
2611 && !DECL_ARTIFICIAL (decl)
|
|
2612 && !DECL_WEAK (decl)
|
|
2613 && TREE_PUBLIC (decl));
|
|
2614 }
|
|
2615
|
|
2616 /* Append description of a single global DECL into vector V.
|
|
2617 TYPE is __asan_global struct type as returned by asan_global_struct. */
|
|
2618
|
|
2619 static void
|
|
2620 asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
|
|
2621 {
|
|
2622 tree init, uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type)));
|
|
2623 unsigned HOST_WIDE_INT size;
|
|
2624 tree str_cst, module_name_cst, refdecl = decl;
|
|
2625 vec<constructor_elt, va_gc> *vinner = NULL;
|
|
2626
|
|
2627 pretty_printer asan_pp, module_name_pp;
|
|
2628
|
|
2629 if (DECL_NAME (decl))
|
|
2630 pp_tree_identifier (&asan_pp, DECL_NAME (decl));
|
|
2631 else
|
|
2632 pp_string (&asan_pp, "<unknown>");
|
|
2633 str_cst = asan_pp_string (&asan_pp);
|
|
2634
|
|
2635 pp_string (&module_name_pp, main_input_filename);
|
|
2636 module_name_cst = asan_pp_string (&module_name_pp);
|
|
2637
|
|
2638 if (asan_needs_local_alias (decl))
|
|
2639 {
|
|
2640 char buf[20];
|
|
2641 ASM_GENERATE_INTERNAL_LABEL (buf, "LASAN", vec_safe_length (v) + 1);
|
|
2642 refdecl = build_decl (DECL_SOURCE_LOCATION (decl),
|
|
2643 VAR_DECL, get_identifier (buf), TREE_TYPE (decl));
|
|
2644 TREE_ADDRESSABLE (refdecl) = TREE_ADDRESSABLE (decl);
|
|
2645 TREE_READONLY (refdecl) = TREE_READONLY (decl);
|
|
2646 TREE_THIS_VOLATILE (refdecl) = TREE_THIS_VOLATILE (decl);
|
|
2647 DECL_GIMPLE_REG_P (refdecl) = DECL_GIMPLE_REG_P (decl);
|
|
2648 DECL_ARTIFICIAL (refdecl) = DECL_ARTIFICIAL (decl);
|
|
2649 DECL_IGNORED_P (refdecl) = DECL_IGNORED_P (decl);
|
|
2650 TREE_STATIC (refdecl) = 1;
|
|
2651 TREE_PUBLIC (refdecl) = 0;
|
|
2652 TREE_USED (refdecl) = 1;
|
|
2653 assemble_alias (refdecl, DECL_ASSEMBLER_NAME (decl));
|
|
2654 }
|
|
2655
|
|
2656 tree odr_indicator_ptr
|
|
2657 = (asan_needs_odr_indicator_p (decl) ? create_odr_indicator (decl, type)
|
|
2658 : build_int_cst (uptr, 0));
|
|
2659 CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
|
|
2660 fold_convert (const_ptr_type_node,
|
|
2661 build_fold_addr_expr (refdecl)));
|
|
2662 size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
|
|
2663 CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size));
|
|
2664 size += asan_red_zone_size (size);
|
|
2665 CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size));
|
|
2666 CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
|
|
2667 fold_convert (const_ptr_type_node, str_cst));
|
|
2668 CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
|
|
2669 fold_convert (const_ptr_type_node, module_name_cst));
|
|
2670 varpool_node *vnode = varpool_node::get (decl);
|
|
2671 int has_dynamic_init = 0;
|
|
2672 /* FIXME: Enable initialization order fiasco detection in LTO mode once
|
|
2673 proper fix for PR 79061 will be applied. */
|
|
2674 if (!in_lto_p)
|
|
2675 has_dynamic_init = vnode ? vnode->dynamically_initialized : 0;
|
|
2676 CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
|
|
2677 build_int_cst (uptr, has_dynamic_init));
|
|
2678 tree locptr = NULL_TREE;
|
|
2679 location_t loc = DECL_SOURCE_LOCATION (decl);
|
|
2680 expanded_location xloc = expand_location (loc);
|
|
2681 if (xloc.file != NULL)
|
|
2682 {
|
|
2683 static int lasanloccnt = 0;
|
|
2684 char buf[25];
|
|
2685 ASM_GENERATE_INTERNAL_LABEL (buf, "LASANLOC", ++lasanloccnt);
|
|
2686 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (buf),
|
|
2687 ubsan_get_source_location_type ());
|
|
2688 TREE_STATIC (var) = 1;
|
|
2689 TREE_PUBLIC (var) = 0;
|
|
2690 DECL_ARTIFICIAL (var) = 1;
|
|
2691 DECL_IGNORED_P (var) = 1;
|
|
2692 pretty_printer filename_pp;
|
|
2693 pp_string (&filename_pp, xloc.file);
|
|
2694 tree str = asan_pp_string (&filename_pp);
|
|
2695 tree ctor = build_constructor_va (TREE_TYPE (var), 3,
|
|
2696 NULL_TREE, str, NULL_TREE,
|
|
2697 build_int_cst (unsigned_type_node,
|
|
2698 xloc.line), NULL_TREE,
|
|
2699 build_int_cst (unsigned_type_node,
|
|
2700 xloc.column));
|
|
2701 TREE_CONSTANT (ctor) = 1;
|
|
2702 TREE_STATIC (ctor) = 1;
|
|
2703 DECL_INITIAL (var) = ctor;
|
|
2704 varpool_node::finalize_decl (var);
|
|
2705 locptr = fold_convert (uptr, build_fold_addr_expr (var));
|
|
2706 }
|
|
2707 else
|
|
2708 locptr = build_int_cst (uptr, 0);
|
|
2709 CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, locptr);
|
|
2710 CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, odr_indicator_ptr);
|
|
2711 init = build_constructor (type, vinner);
|
|
2712 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
|
|
2713 }
|
|
2714
|
|
2715 /* Initialize sanitizer.def builtins if the FE hasn't initialized them. */
|
|
2716 void
|
|
2717 initialize_sanitizer_builtins (void)
|
|
2718 {
|
|
2719 tree decl;
|
|
2720
|
|
2721 if (builtin_decl_implicit_p (BUILT_IN_ASAN_INIT))
|
|
2722 return;
|
|
2723
|
|
2724 tree BT_FN_VOID = build_function_type_list (void_type_node, NULL_TREE);
|
|
2725 tree BT_FN_VOID_PTR
|
|
2726 = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
|
|
2727 tree BT_FN_VOID_CONST_PTR
|
|
2728 = build_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE);
|
|
2729 tree BT_FN_VOID_PTR_PTR
|
|
2730 = build_function_type_list (void_type_node, ptr_type_node,
|
|
2731 ptr_type_node, NULL_TREE);
|
|
2732 tree BT_FN_VOID_PTR_PTR_PTR
|
|
2733 = build_function_type_list (void_type_node, ptr_type_node,
|
|
2734 ptr_type_node, ptr_type_node, NULL_TREE);
|
|
2735 tree BT_FN_VOID_PTR_PTRMODE
|
|
2736 = build_function_type_list (void_type_node, ptr_type_node,
|
|
2737 pointer_sized_int_node, NULL_TREE);
|
|
2738 tree BT_FN_VOID_INT
|
|
2739 = build_function_type_list (void_type_node, integer_type_node, NULL_TREE);
|
|
2740 tree BT_FN_SIZE_CONST_PTR_INT
|
|
2741 = build_function_type_list (size_type_node, const_ptr_type_node,
|
|
2742 integer_type_node, NULL_TREE);
|
|
2743
|
|
2744 tree BT_FN_VOID_UINT8_UINT8
|
|
2745 = build_function_type_list (void_type_node, unsigned_char_type_node,
|
|
2746 unsigned_char_type_node, NULL_TREE);
|
|
2747 tree BT_FN_VOID_UINT16_UINT16
|
|
2748 = build_function_type_list (void_type_node, uint16_type_node,
|
|
2749 uint16_type_node, NULL_TREE);
|
|
2750 tree BT_FN_VOID_UINT32_UINT32
|
|
2751 = build_function_type_list (void_type_node, uint32_type_node,
|
|
2752 uint32_type_node, NULL_TREE);
|
|
2753 tree BT_FN_VOID_UINT64_UINT64
|
|
2754 = build_function_type_list (void_type_node, uint64_type_node,
|
|
2755 uint64_type_node, NULL_TREE);
|
|
2756 tree BT_FN_VOID_FLOAT_FLOAT
|
|
2757 = build_function_type_list (void_type_node, float_type_node,
|
|
2758 float_type_node, NULL_TREE);
|
|
2759 tree BT_FN_VOID_DOUBLE_DOUBLE
|
|
2760 = build_function_type_list (void_type_node, double_type_node,
|
|
2761 double_type_node, NULL_TREE);
|
|
2762 tree BT_FN_VOID_UINT64_PTR
|
|
2763 = build_function_type_list (void_type_node, uint64_type_node,
|
|
2764 ptr_type_node, NULL_TREE);
|
|
2765
|
|
2766 tree BT_FN_BOOL_VPTR_PTR_IX_INT_INT[5];
|
|
2767 tree BT_FN_IX_CONST_VPTR_INT[5];
|
|
2768 tree BT_FN_IX_VPTR_IX_INT[5];
|
|
2769 tree BT_FN_VOID_VPTR_IX_INT[5];
|
|
2770 tree vptr
|
|
2771 = build_pointer_type (build_qualified_type (void_type_node,
|
|
2772 TYPE_QUAL_VOLATILE));
|
|
2773 tree cvptr
|
|
2774 = build_pointer_type (build_qualified_type (void_type_node,
|
|
2775 TYPE_QUAL_VOLATILE
|
|
2776 |TYPE_QUAL_CONST));
|
|
2777 tree boolt
|
|
2778 = lang_hooks.types.type_for_size (BOOL_TYPE_SIZE, 1);
|
|
2779 int i;
|
|
2780 for (i = 0; i < 5; i++)
|
|
2781 {
|
|
2782 tree ix = build_nonstandard_integer_type (BITS_PER_UNIT * (1 << i), 1);
|
|
2783 BT_FN_BOOL_VPTR_PTR_IX_INT_INT[i]
|
|
2784 = build_function_type_list (boolt, vptr, ptr_type_node, ix,
|
|
2785 integer_type_node, integer_type_node,
|
|
2786 NULL_TREE);
|
|
2787 BT_FN_IX_CONST_VPTR_INT[i]
|
|
2788 = build_function_type_list (ix, cvptr, integer_type_node, NULL_TREE);
|
|
2789 BT_FN_IX_VPTR_IX_INT[i]
|
|
2790 = build_function_type_list (ix, vptr, ix, integer_type_node,
|
|
2791 NULL_TREE);
|
|
2792 BT_FN_VOID_VPTR_IX_INT[i]
|
|
2793 = build_function_type_list (void_type_node, vptr, ix,
|
|
2794 integer_type_node, NULL_TREE);
|
|
2795 }
|
|
2796 #define BT_FN_BOOL_VPTR_PTR_I1_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[0]
|
|
2797 #define BT_FN_I1_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[0]
|
|
2798 #define BT_FN_I1_VPTR_I1_INT BT_FN_IX_VPTR_IX_INT[0]
|
|
2799 #define BT_FN_VOID_VPTR_I1_INT BT_FN_VOID_VPTR_IX_INT[0]
|
|
2800 #define BT_FN_BOOL_VPTR_PTR_I2_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[1]
|
|
2801 #define BT_FN_I2_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[1]
|
|
2802 #define BT_FN_I2_VPTR_I2_INT BT_FN_IX_VPTR_IX_INT[1]
|
|
2803 #define BT_FN_VOID_VPTR_I2_INT BT_FN_VOID_VPTR_IX_INT[1]
|
|
2804 #define BT_FN_BOOL_VPTR_PTR_I4_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[2]
|
|
2805 #define BT_FN_I4_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[2]
|
|
2806 #define BT_FN_I4_VPTR_I4_INT BT_FN_IX_VPTR_IX_INT[2]
|
|
2807 #define BT_FN_VOID_VPTR_I4_INT BT_FN_VOID_VPTR_IX_INT[2]
|
|
2808 #define BT_FN_BOOL_VPTR_PTR_I8_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[3]
|
|
2809 #define BT_FN_I8_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[3]
|
|
2810 #define BT_FN_I8_VPTR_I8_INT BT_FN_IX_VPTR_IX_INT[3]
|
|
2811 #define BT_FN_VOID_VPTR_I8_INT BT_FN_VOID_VPTR_IX_INT[3]
|
|
2812 #define BT_FN_BOOL_VPTR_PTR_I16_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[4]
|
|
2813 #define BT_FN_I16_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[4]
|
|
2814 #define BT_FN_I16_VPTR_I16_INT BT_FN_IX_VPTR_IX_INT[4]
|
|
2815 #define BT_FN_VOID_VPTR_I16_INT BT_FN_VOID_VPTR_IX_INT[4]
|
|
2816 #undef ATTR_NOTHROW_LEAF_LIST
|
|
2817 #define ATTR_NOTHROW_LEAF_LIST ECF_NOTHROW | ECF_LEAF
|
|
2818 #undef ATTR_TMPURE_NOTHROW_LEAF_LIST
|
|
2819 #define ATTR_TMPURE_NOTHROW_LEAF_LIST ECF_TM_PURE | ATTR_NOTHROW_LEAF_LIST
|
|
2820 #undef ATTR_NORETURN_NOTHROW_LEAF_LIST
|
|
2821 #define ATTR_NORETURN_NOTHROW_LEAF_LIST ECF_NORETURN | ATTR_NOTHROW_LEAF_LIST
|
|
2822 #undef ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST
|
|
2823 #define ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST \
|
|
2824 ECF_CONST | ATTR_NORETURN_NOTHROW_LEAF_LIST
|
|
2825 #undef ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST
|
|
2826 #define ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST \
|
|
2827 ECF_TM_PURE | ATTR_NORETURN_NOTHROW_LEAF_LIST
|
|
2828 #undef ATTR_COLD_NOTHROW_LEAF_LIST
|
|
2829 #define ATTR_COLD_NOTHROW_LEAF_LIST \
|
|
2830 /* ECF_COLD missing */ ATTR_NOTHROW_LEAF_LIST
|
|
2831 #undef ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST
|
|
2832 #define ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST \
|
|
2833 /* ECF_COLD missing */ ATTR_NORETURN_NOTHROW_LEAF_LIST
|
|
2834 #undef ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST
|
|
2835 #define ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST \
|
|
2836 /* ECF_COLD missing */ ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST
|
|
2837 #undef ATTR_PURE_NOTHROW_LEAF_LIST
|
|
2838 #define ATTR_PURE_NOTHROW_LEAF_LIST ECF_PURE | ATTR_NOTHROW_LEAF_LIST
|
|
2839 #undef DEF_BUILTIN_STUB
|
|
2840 #define DEF_BUILTIN_STUB(ENUM, NAME)
|
131
|
2841 #undef DEF_SANITIZER_BUILTIN_1
|
|
2842 #define DEF_SANITIZER_BUILTIN_1(ENUM, NAME, TYPE, ATTRS) \
|
111
|
2843 do { \
|
|
2844 decl = add_builtin_function ("__builtin_" NAME, TYPE, ENUM, \
|
|
2845 BUILT_IN_NORMAL, NAME, NULL_TREE); \
|
|
2846 set_call_expr_flags (decl, ATTRS); \
|
|
2847 set_builtin_decl (ENUM, decl, true); \
|
131
|
2848 } while (0)
|
|
2849 #undef DEF_SANITIZER_BUILTIN
|
|
2850 #define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
|
|
2851 DEF_SANITIZER_BUILTIN_1 (ENUM, NAME, TYPE, ATTRS);
|
111
|
2852
|
|
2853 #include "sanitizer.def"
|
|
2854
|
|
2855 /* -fsanitize=object-size uses __builtin_object_size, but that might
|
|
2856 not be available for e.g. Fortran at this point. We use
|
|
2857 DEF_SANITIZER_BUILTIN here only as a convenience macro. */
|
|
2858 if ((flag_sanitize & SANITIZE_OBJECT_SIZE)
|
|
2859 && !builtin_decl_implicit_p (BUILT_IN_OBJECT_SIZE))
|
131
|
2860 DEF_SANITIZER_BUILTIN_1 (BUILT_IN_OBJECT_SIZE, "object_size",
|
|
2861 BT_FN_SIZE_CONST_PTR_INT,
|
|
2862 ATTR_PURE_NOTHROW_LEAF_LIST);
|
|
2863
|
|
2864 #undef DEF_SANITIZER_BUILTIN_1
|
111
|
2865 #undef DEF_SANITIZER_BUILTIN
|
|
2866 #undef DEF_BUILTIN_STUB
|
|
2867 }
|
|
2868
|
|
2869 /* Called via htab_traverse. Count number of emitted
|
|
2870 STRING_CSTs in the constant hash table. */
|
|
2871
|
|
2872 int
|
|
2873 count_string_csts (constant_descriptor_tree **slot,
|
|
2874 unsigned HOST_WIDE_INT *data)
|
|
2875 {
|
|
2876 struct constant_descriptor_tree *desc = *slot;
|
|
2877 if (TREE_CODE (desc->value) == STRING_CST
|
|
2878 && TREE_ASM_WRITTEN (desc->value)
|
|
2879 && asan_protect_global (desc->value))
|
|
2880 ++*data;
|
|
2881 return 1;
|
|
2882 }
|
|
2883
|
|
2884 /* Helper structure to pass two parameters to
|
|
2885 add_string_csts. */
|
|
2886
|
|
2887 struct asan_add_string_csts_data
|
|
2888 {
|
|
2889 tree type;
|
|
2890 vec<constructor_elt, va_gc> *v;
|
|
2891 };
|
|
2892
|
|
2893 /* Called via hash_table::traverse. Call asan_add_global
|
|
2894 on emitted STRING_CSTs from the constant hash table. */
|
|
2895
|
|
2896 int
|
|
2897 add_string_csts (constant_descriptor_tree **slot,
|
|
2898 asan_add_string_csts_data *aascd)
|
|
2899 {
|
|
2900 struct constant_descriptor_tree *desc = *slot;
|
|
2901 if (TREE_CODE (desc->value) == STRING_CST
|
|
2902 && TREE_ASM_WRITTEN (desc->value)
|
|
2903 && asan_protect_global (desc->value))
|
|
2904 {
|
|
2905 asan_add_global (SYMBOL_REF_DECL (XEXP (desc->rtl, 0)),
|
|
2906 aascd->type, aascd->v);
|
|
2907 }
|
|
2908 return 1;
|
|
2909 }
|
|
2910
|
|
2911 /* Needs to be GTY(()), because cgraph_build_static_cdtor may
|
|
2912 invoke ggc_collect. */
|
|
2913 static GTY(()) tree asan_ctor_statements;
|
|
2914
|
|
2915 /* Module-level instrumentation.
|
|
2916 - Insert __asan_init_vN() into the list of CTORs.
|
|
2917 - TODO: insert redzones around globals.
|
|
2918 */
|
|
2919
|
|
2920 void
|
|
2921 asan_finish_file (void)
|
|
2922 {
|
|
2923 varpool_node *vnode;
|
|
2924 unsigned HOST_WIDE_INT gcount = 0;
|
|
2925
|
|
2926 if (shadow_ptr_types[0] == NULL_TREE)
|
|
2927 asan_init_shadow_ptr_types ();
|
|
2928 /* Avoid instrumenting code in the asan ctors/dtors.
|
|
2929 We don't need to insert padding after the description strings,
|
|
2930 nor after .LASAN* array. */
|
|
2931 flag_sanitize &= ~SANITIZE_ADDRESS;
|
|
2932
|
|
2933 /* For user-space we want asan constructors to run first.
|
|
2934 Linux kernel does not support priorities other than default, and the only
|
|
2935 other user of constructors is coverage. So we run with the default
|
|
2936 priority. */
|
|
2937 int priority = flag_sanitize & SANITIZE_USER_ADDRESS
|
|
2938 ? MAX_RESERVED_INIT_PRIORITY - 1 : DEFAULT_INIT_PRIORITY;
|
|
2939
|
|
2940 if (flag_sanitize & SANITIZE_USER_ADDRESS)
|
|
2941 {
|
|
2942 tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT);
|
|
2943 append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
|
|
2944 fn = builtin_decl_implicit (BUILT_IN_ASAN_VERSION_MISMATCH_CHECK);
|
|
2945 append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
|
|
2946 }
|
|
2947 FOR_EACH_DEFINED_VARIABLE (vnode)
|
|
2948 if (TREE_ASM_WRITTEN (vnode->decl)
|
|
2949 && asan_protect_global (vnode->decl))
|
|
2950 ++gcount;
|
|
2951 hash_table<tree_descriptor_hasher> *const_desc_htab = constant_pool_htab ();
|
|
2952 const_desc_htab->traverse<unsigned HOST_WIDE_INT *, count_string_csts>
|
|
2953 (&gcount);
|
|
2954 if (gcount)
|
|
2955 {
|
|
2956 tree type = asan_global_struct (), var, ctor;
|
|
2957 tree dtor_statements = NULL_TREE;
|
|
2958 vec<constructor_elt, va_gc> *v;
|
|
2959 char buf[20];
|
|
2960
|
|
2961 type = build_array_type_nelts (type, gcount);
|
|
2962 ASM_GENERATE_INTERNAL_LABEL (buf, "LASAN", 0);
|
|
2963 var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (buf),
|
|
2964 type);
|
|
2965 TREE_STATIC (var) = 1;
|
|
2966 TREE_PUBLIC (var) = 0;
|
|
2967 DECL_ARTIFICIAL (var) = 1;
|
|
2968 DECL_IGNORED_P (var) = 1;
|
|
2969 vec_alloc (v, gcount);
|
|
2970 FOR_EACH_DEFINED_VARIABLE (vnode)
|
|
2971 if (TREE_ASM_WRITTEN (vnode->decl)
|
|
2972 && asan_protect_global (vnode->decl))
|
|
2973 asan_add_global (vnode->decl, TREE_TYPE (type), v);
|
|
2974 struct asan_add_string_csts_data aascd;
|
|
2975 aascd.type = TREE_TYPE (type);
|
|
2976 aascd.v = v;
|
|
2977 const_desc_htab->traverse<asan_add_string_csts_data *, add_string_csts>
|
|
2978 (&aascd);
|
|
2979 ctor = build_constructor (type, v);
|
|
2980 TREE_CONSTANT (ctor) = 1;
|
|
2981 TREE_STATIC (ctor) = 1;
|
|
2982 DECL_INITIAL (var) = ctor;
|
131
|
2983 SET_DECL_ALIGN (var, MAX (DECL_ALIGN (var),
|
|
2984 ASAN_SHADOW_GRANULARITY * BITS_PER_UNIT));
|
|
2985
|
111
|
2986 varpool_node::finalize_decl (var);
|
|
2987
|
|
2988 tree fn = builtin_decl_implicit (BUILT_IN_ASAN_REGISTER_GLOBALS);
|
|
2989 tree gcount_tree = build_int_cst (pointer_sized_int_node, gcount);
|
|
2990 append_to_statement_list (build_call_expr (fn, 2,
|
|
2991 build_fold_addr_expr (var),
|
|
2992 gcount_tree),
|
|
2993 &asan_ctor_statements);
|
|
2994
|
|
2995 fn = builtin_decl_implicit (BUILT_IN_ASAN_UNREGISTER_GLOBALS);
|
|
2996 append_to_statement_list (build_call_expr (fn, 2,
|
|
2997 build_fold_addr_expr (var),
|
|
2998 gcount_tree),
|
|
2999 &dtor_statements);
|
|
3000 cgraph_build_static_cdtor ('D', dtor_statements, priority);
|
|
3001 }
|
|
3002 if (asan_ctor_statements)
|
|
3003 cgraph_build_static_cdtor ('I', asan_ctor_statements, priority);
|
|
3004 flag_sanitize |= SANITIZE_ADDRESS;
|
|
3005 }
|
|
3006
|
|
3007 /* Poison or unpoison (depending on IS_CLOBBER variable) shadow memory based
|
|
3008 on SHADOW address. Newly added statements will be added to ITER with
|
|
3009 given location LOC. We mark SIZE bytes in shadow memory, where
|
|
3010 LAST_CHUNK_SIZE is greater than zero in situation where we are at the
|
|
3011 end of a variable. */
|
|
3012
|
|
3013 static void
|
|
3014 asan_store_shadow_bytes (gimple_stmt_iterator *iter, location_t loc,
|
|
3015 tree shadow,
|
|
3016 unsigned HOST_WIDE_INT base_addr_offset,
|
|
3017 bool is_clobber, unsigned size,
|
|
3018 unsigned last_chunk_size)
|
|
3019 {
|
|
3020 tree shadow_ptr_type;
|
|
3021
|
|
3022 switch (size)
|
|
3023 {
|
|
3024 case 1:
|
|
3025 shadow_ptr_type = shadow_ptr_types[0];
|
|
3026 break;
|
|
3027 case 2:
|
|
3028 shadow_ptr_type = shadow_ptr_types[1];
|
|
3029 break;
|
|
3030 case 4:
|
|
3031 shadow_ptr_type = shadow_ptr_types[2];
|
|
3032 break;
|
|
3033 default:
|
|
3034 gcc_unreachable ();
|
|
3035 }
|
|
3036
|
|
3037 unsigned char c = (char) is_clobber ? ASAN_STACK_MAGIC_USE_AFTER_SCOPE : 0;
|
|
3038 unsigned HOST_WIDE_INT val = 0;
|
|
3039 unsigned last_pos = size;
|
|
3040 if (last_chunk_size && !is_clobber)
|
|
3041 last_pos = BYTES_BIG_ENDIAN ? 0 : size - 1;
|
|
3042 for (unsigned i = 0; i < size; ++i)
|
|
3043 {
|
|
3044 unsigned char shadow_c = c;
|
|
3045 if (i == last_pos)
|
|
3046 shadow_c = last_chunk_size;
|
|
3047 val |= (unsigned HOST_WIDE_INT) shadow_c << (BITS_PER_UNIT * i);
|
|
3048 }
|
|
3049
|
|
3050 /* Handle last chunk in unpoisoning. */
|
|
3051 tree magic = build_int_cst (TREE_TYPE (shadow_ptr_type), val);
|
|
3052
|
|
3053 tree dest = build2 (MEM_REF, TREE_TYPE (shadow_ptr_type), shadow,
|
|
3054 build_int_cst (shadow_ptr_type, base_addr_offset));
|
|
3055
|
|
3056 gimple *g = gimple_build_assign (dest, magic);
|
|
3057 gimple_set_location (g, loc);
|
|
3058 gsi_insert_after (iter, g, GSI_NEW_STMT);
|
|
3059 }
|
|
3060
|
|
3061 /* Expand the ASAN_MARK builtins. */
|
|
3062
|
|
3063 bool
|
|
3064 asan_expand_mark_ifn (gimple_stmt_iterator *iter)
|
|
3065 {
|
|
3066 gimple *g = gsi_stmt (*iter);
|
|
3067 location_t loc = gimple_location (g);
|
|
3068 HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (g, 0));
|
|
3069 bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
|
|
3070
|
|
3071 tree base = gimple_call_arg (g, 1);
|
|
3072 gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
|
|
3073 tree decl = TREE_OPERAND (base, 0);
|
|
3074
|
|
3075 /* For a nested function, we can have: ASAN_MARK (2, &FRAME.2.fp_input, 4) */
|
|
3076 if (TREE_CODE (decl) == COMPONENT_REF
|
|
3077 && DECL_NONLOCAL_FRAME (TREE_OPERAND (decl, 0)))
|
|
3078 decl = TREE_OPERAND (decl, 0);
|
|
3079
|
|
3080 gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
|
|
3081
|
|
3082 if (is_poison)
|
|
3083 {
|
|
3084 if (asan_handled_variables == NULL)
|
|
3085 asan_handled_variables = new hash_set<tree> (16);
|
|
3086 asan_handled_variables->add (decl);
|
|
3087 }
|
|
3088 tree len = gimple_call_arg (g, 2);
|
|
3089
|
|
3090 gcc_assert (tree_fits_shwi_p (len));
|
|
3091 unsigned HOST_WIDE_INT size_in_bytes = tree_to_shwi (len);
|
|
3092 gcc_assert (size_in_bytes);
|
|
3093
|
|
3094 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
|
|
3095 NOP_EXPR, base);
|
|
3096 gimple_set_location (g, loc);
|
|
3097 gsi_replace (iter, g, false);
|
|
3098 tree base_addr = gimple_assign_lhs (g);
|
|
3099
|
|
3100 /* Generate direct emission if size_in_bytes is small. */
|
|
3101 if (size_in_bytes <= ASAN_PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD)
|
|
3102 {
|
|
3103 unsigned HOST_WIDE_INT shadow_size = shadow_mem_size (size_in_bytes);
|
|
3104
|
|
3105 tree shadow = build_shadow_mem_access (iter, loc, base_addr,
|
|
3106 shadow_ptr_types[0], true);
|
|
3107
|
|
3108 for (unsigned HOST_WIDE_INT offset = 0; offset < shadow_size;)
|
|
3109 {
|
|
3110 unsigned size = 1;
|
|
3111 if (shadow_size - offset >= 4)
|
|
3112 size = 4;
|
|
3113 else if (shadow_size - offset >= 2)
|
|
3114 size = 2;
|
|
3115
|
|
3116 unsigned HOST_WIDE_INT last_chunk_size = 0;
|
|
3117 unsigned HOST_WIDE_INT s = (offset + size) * ASAN_SHADOW_GRANULARITY;
|
|
3118 if (s > size_in_bytes)
|
|
3119 last_chunk_size = ASAN_SHADOW_GRANULARITY - (s - size_in_bytes);
|
|
3120
|
|
3121 asan_store_shadow_bytes (iter, loc, shadow, offset, is_poison,
|
|
3122 size, last_chunk_size);
|
|
3123 offset += size;
|
|
3124 }
|
|
3125 }
|
|
3126 else
|
|
3127 {
|
|
3128 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
|
|
3129 NOP_EXPR, len);
|
|
3130 gimple_set_location (g, loc);
|
|
3131 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
3132 tree sz_arg = gimple_assign_lhs (g);
|
|
3133
|
|
3134 tree fun
|
|
3135 = builtin_decl_implicit (is_poison ? BUILT_IN_ASAN_POISON_STACK_MEMORY
|
|
3136 : BUILT_IN_ASAN_UNPOISON_STACK_MEMORY);
|
|
3137 g = gimple_build_call (fun, 2, base_addr, sz_arg);
|
|
3138 gimple_set_location (g, loc);
|
|
3139 gsi_insert_after (iter, g, GSI_NEW_STMT);
|
|
3140 }
|
|
3141
|
|
3142 return false;
|
|
3143 }
|
|
3144
|
|
3145 /* Expand the ASAN_{LOAD,STORE} builtins. */
|
|
3146
|
|
3147 bool
|
|
3148 asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
|
|
3149 {
|
|
3150 gimple *g = gsi_stmt (*iter);
|
|
3151 location_t loc = gimple_location (g);
|
|
3152 bool recover_p;
|
|
3153 if (flag_sanitize & SANITIZE_USER_ADDRESS)
|
|
3154 recover_p = (flag_sanitize_recover & SANITIZE_USER_ADDRESS) != 0;
|
|
3155 else
|
|
3156 recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
|
|
3157
|
|
3158 HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0));
|
|
3159 gcc_assert (flags < ASAN_CHECK_LAST);
|
|
3160 bool is_scalar_access = (flags & ASAN_CHECK_SCALAR_ACCESS) != 0;
|
|
3161 bool is_store = (flags & ASAN_CHECK_STORE) != 0;
|
|
3162 bool is_non_zero_len = (flags & ASAN_CHECK_NON_ZERO_LEN) != 0;
|
|
3163
|
|
3164 tree base = gimple_call_arg (g, 1);
|
|
3165 tree len = gimple_call_arg (g, 2);
|
|
3166 HOST_WIDE_INT align = tree_to_shwi (gimple_call_arg (g, 3));
|
|
3167
|
|
3168 HOST_WIDE_INT size_in_bytes
|
|
3169 = is_scalar_access && tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
|
|
3170
|
|
3171 if (use_calls)
|
|
3172 {
|
|
3173 /* Instrument using callbacks. */
|
|
3174 gimple *g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
|
|
3175 NOP_EXPR, base);
|
|
3176 gimple_set_location (g, loc);
|
|
3177 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
3178 tree base_addr = gimple_assign_lhs (g);
|
|
3179
|
|
3180 int nargs;
|
|
3181 tree fun = check_func (is_store, recover_p, size_in_bytes, &nargs);
|
|
3182 if (nargs == 1)
|
|
3183 g = gimple_build_call (fun, 1, base_addr);
|
|
3184 else
|
|
3185 {
|
|
3186 gcc_assert (nargs == 2);
|
|
3187 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
|
|
3188 NOP_EXPR, len);
|
|
3189 gimple_set_location (g, loc);
|
|
3190 gsi_insert_before (iter, g, GSI_SAME_STMT);
|
|
3191 tree sz_arg = gimple_assign_lhs (g);
|
|
3192 g = gimple_build_call (fun, nargs, base_addr, sz_arg);
|
|
3193 }
|
|
3194 gimple_set_location (g, loc);
|
|
3195 gsi_replace (iter, g, false);
|
|
3196 return false;
|
|
3197 }
|
|
3198
|
|
3199 HOST_WIDE_INT real_size_in_bytes = size_in_bytes == -1 ? 1 : size_in_bytes;
|
|
3200
|
|
3201 tree shadow_ptr_type = shadow_ptr_types[real_size_in_bytes == 16 ? 1 : 0];
|
|
3202 tree shadow_type = TREE_TYPE (shadow_ptr_type);
|
|
3203
|
|
3204 gimple_stmt_iterator gsi = *iter;
|
|
3205
|
|
3206 if (!is_non_zero_len)
|
|
3207 {
|
|
3208 /* So, the length of the memory area to asan-protect is
|
|
3209 non-constant. Let's guard the generated instrumentation code
|
|
3210 like:
|
|
3211
|
|
3212 if (len != 0)
|
|
3213 {
|
|
3214 //asan instrumentation code goes here.
|
|
3215 }
|
|
3216 // falltrough instructions, starting with *ITER. */
|
|
3217
|
|
3218 g = gimple_build_cond (NE_EXPR,
|
|
3219 len,
|
|
3220 build_int_cst (TREE_TYPE (len), 0),
|
|
3221 NULL_TREE, NULL_TREE);
|
|
3222 gimple_set_location (g, loc);
|
|
3223
|
|
3224 basic_block then_bb, fallthrough_bb;
|
|
3225 insert_if_then_before_iter (as_a <gcond *> (g), iter,
|
|
3226 /*then_more_likely_p=*/true,
|
|
3227 &then_bb, &fallthrough_bb);
|
|
3228 /* Note that fallthrough_bb starts with the statement that was
|
|
3229 pointed to by ITER. */
|
|
3230
|
|
3231 /* The 'then block' of the 'if (len != 0) condition is where
|
|
3232 we'll generate the asan instrumentation code now. */
|
|
3233 gsi = gsi_last_bb (then_bb);
|
|
3234 }
|
|
3235
|
|
3236 /* Get an iterator on the point where we can add the condition
|
|
3237 statement for the instrumentation. */
|
|
3238 basic_block then_bb, else_bb;
|
|
3239 gsi = create_cond_insert_point (&gsi, /*before_p*/false,
|
|
3240 /*then_more_likely_p=*/false,
|
|
3241 /*create_then_fallthru_edge*/recover_p,
|
|
3242 &then_bb,
|
|
3243 &else_bb);
|
|
3244
|
|
3245 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
|
|
3246 NOP_EXPR, base);
|
|
3247 gimple_set_location (g, loc);
|
|
3248 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
|
|
3249 tree base_addr = gimple_assign_lhs (g);
|
|
3250
|
|
3251 tree t = NULL_TREE;
|
|
3252 if (real_size_in_bytes >= 8)
|
|
3253 {
|
|
3254 tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
|
|
3255 shadow_ptr_type);
|
|
3256 t = shadow;
|
|
3257 }
|
|
3258 else
|
|
3259 {
|
|
3260 /* Slow path for 1, 2 and 4 byte accesses. */
|
|
3261 /* Test (shadow != 0)
|
|
3262 & ((base_addr & 7) + (real_size_in_bytes - 1)) >= shadow). */
|
|
3263 tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
|
|
3264 shadow_ptr_type);
|
|
3265 gimple *shadow_test = build_assign (NE_EXPR, shadow, 0);
|
|
3266 gimple_seq seq = NULL;
|
|
3267 gimple_seq_add_stmt (&seq, shadow_test);
|
|
3268 /* Aligned (>= 8 bytes) can test just
|
|
3269 (real_size_in_bytes - 1 >= shadow), as base_addr & 7 is known
|
|
3270 to be 0. */
|
|
3271 if (align < 8)
|
|
3272 {
|
|
3273 gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
|
|
3274 base_addr, 7));
|
|
3275 gimple_seq_add_stmt (&seq,
|
|
3276 build_type_cast (shadow_type,
|
|
3277 gimple_seq_last (seq)));
|
|
3278 if (real_size_in_bytes > 1)
|
|
3279 gimple_seq_add_stmt (&seq,
|
|
3280 build_assign (PLUS_EXPR,
|
|
3281 gimple_seq_last (seq),
|
|
3282 real_size_in_bytes - 1));
|
|
3283 t = gimple_assign_lhs (gimple_seq_last_stmt (seq));
|
|
3284 }
|
|
3285 else
|
|
3286 t = build_int_cst (shadow_type, real_size_in_bytes - 1);
|
|
3287 gimple_seq_add_stmt (&seq, build_assign (GE_EXPR, t, shadow));
|
|
3288 gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
|
|
3289 gimple_seq_last (seq)));
|
|
3290 t = gimple_assign_lhs (gimple_seq_last (seq));
|
|
3291 gimple_seq_set_location (seq, loc);
|
|
3292 gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
|
|
3293
|
|
3294 /* For non-constant, misaligned or otherwise weird access sizes,
|
|
3295 check first and last byte. */
|
|
3296 if (size_in_bytes == -1)
|
|
3297 {
|
|
3298 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
|
|
3299 MINUS_EXPR, len,
|
|
3300 build_int_cst (pointer_sized_int_node, 1));
|
|
3301 gimple_set_location (g, loc);
|
|
3302 gsi_insert_after (&gsi, g, GSI_NEW_STMT);
|
|
3303 tree last = gimple_assign_lhs (g);
|
|
3304 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
|
|
3305 PLUS_EXPR, base_addr, last);
|
|
3306 gimple_set_location (g, loc);
|
|
3307 gsi_insert_after (&gsi, g, GSI_NEW_STMT);
|
|
3308 tree base_end_addr = gimple_assign_lhs (g);
|
|
3309
|
|
3310 tree shadow = build_shadow_mem_access (&gsi, loc, base_end_addr,
|
|
3311 shadow_ptr_type);
|
|
3312 gimple *shadow_test = build_assign (NE_EXPR, shadow, 0);
|
|
3313 gimple_seq seq = NULL;
|
|
3314 gimple_seq_add_stmt (&seq, shadow_test);
|
|
3315 gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
|
|
3316 base_end_addr, 7));
|
|
3317 gimple_seq_add_stmt (&seq, build_type_cast (shadow_type,
|
|
3318 gimple_seq_last (seq)));
|
|
3319 gimple_seq_add_stmt (&seq, build_assign (GE_EXPR,
|
|
3320 gimple_seq_last (seq),
|
|
3321 shadow));
|
|
3322 gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
|
|
3323 gimple_seq_last (seq)));
|
|
3324 gimple_seq_add_stmt (&seq, build_assign (BIT_IOR_EXPR, t,
|
|
3325 gimple_seq_last (seq)));
|
|
3326 t = gimple_assign_lhs (gimple_seq_last (seq));
|
|
3327 gimple_seq_set_location (seq, loc);
|
|
3328 gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
|
|
3329 }
|
|
3330 }
|
|
3331
|
|
3332 g = gimple_build_cond (NE_EXPR, t, build_int_cst (TREE_TYPE (t), 0),
|
|
3333 NULL_TREE, NULL_TREE);
|
|
3334 gimple_set_location (g, loc);
|
|
3335 gsi_insert_after (&gsi, g, GSI_NEW_STMT);
|
|
3336
|
|
3337 /* Generate call to the run-time library (e.g. __asan_report_load8). */
|
|
3338 gsi = gsi_start_bb (then_bb);
|
|
3339 int nargs;
|
|
3340 tree fun = report_error_func (is_store, recover_p, size_in_bytes, &nargs);
|
|
3341 g = gimple_build_call (fun, nargs, base_addr, len);
|
|
3342 gimple_set_location (g, loc);
|
|
3343 gsi_insert_after (&gsi, g, GSI_NEW_STMT);
|
|
3344
|
|
3345 gsi_remove (iter, true);
|
|
3346 *iter = gsi_start_bb (else_bb);
|
|
3347
|
|
3348 return true;
|
|
3349 }
|
|
3350
|
|
3351 /* Create ASAN shadow variable for a VAR_DECL which has been rewritten
|
|
3352 into SSA. Already seen VAR_DECLs are stored in SHADOW_VARS_MAPPING. */
|
|
3353
|
|
3354 static tree
|
|
3355 create_asan_shadow_var (tree var_decl,
|
|
3356 hash_map<tree, tree> &shadow_vars_mapping)
|
|
3357 {
|
|
3358 tree *slot = shadow_vars_mapping.get (var_decl);
|
|
3359 if (slot == NULL)
|
|
3360 {
|
|
3361 tree shadow_var = copy_node (var_decl);
|
|
3362
|
|
3363 copy_body_data id;
|
|
3364 memset (&id, 0, sizeof (copy_body_data));
|
|
3365 id.src_fn = id.dst_fn = current_function_decl;
|
|
3366 copy_decl_for_dup_finish (&id, var_decl, shadow_var);
|
|
3367
|
|
3368 DECL_ARTIFICIAL (shadow_var) = 1;
|
|
3369 DECL_IGNORED_P (shadow_var) = 1;
|
|
3370 DECL_SEEN_IN_BIND_EXPR_P (shadow_var) = 0;
|
|
3371 gimple_add_tmp_var (shadow_var);
|
|
3372
|
|
3373 shadow_vars_mapping.put (var_decl, shadow_var);
|
|
3374 return shadow_var;
|
|
3375 }
|
|
3376 else
|
|
3377 return *slot;
|
|
3378 }
|
|
3379
|
|
3380 /* Expand ASAN_POISON ifn. */
|
|
3381
|
|
3382 bool
|
|
3383 asan_expand_poison_ifn (gimple_stmt_iterator *iter,
|
|
3384 bool *need_commit_edge_insert,
|
|
3385 hash_map<tree, tree> &shadow_vars_mapping)
|
|
3386 {
|
|
3387 gimple *g = gsi_stmt (*iter);
|
|
3388 tree poisoned_var = gimple_call_lhs (g);
|
|
3389 if (!poisoned_var || has_zero_uses (poisoned_var))
|
|
3390 {
|
|
3391 gsi_remove (iter, true);
|
|
3392 return true;
|
|
3393 }
|
|
3394
|
|
3395 if (SSA_NAME_VAR (poisoned_var) == NULL_TREE)
|
|
3396 SET_SSA_NAME_VAR_OR_IDENTIFIER (poisoned_var,
|
|
3397 create_tmp_var (TREE_TYPE (poisoned_var)));
|
|
3398
|
|
3399 tree shadow_var = create_asan_shadow_var (SSA_NAME_VAR (poisoned_var),
|
|
3400 shadow_vars_mapping);
|
|
3401
|
|
3402 bool recover_p;
|
|
3403 if (flag_sanitize & SANITIZE_USER_ADDRESS)
|
|
3404 recover_p = (flag_sanitize_recover & SANITIZE_USER_ADDRESS) != 0;
|
|
3405 else
|
|
3406 recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
|
|
3407 tree size = DECL_SIZE_UNIT (shadow_var);
|
|
3408 gimple *poison_call
|
|
3409 = gimple_build_call_internal (IFN_ASAN_MARK, 3,
|
|
3410 build_int_cst (integer_type_node,
|
|
3411 ASAN_MARK_POISON),
|
|
3412 build_fold_addr_expr (shadow_var), size);
|
|
3413
|
|
3414 gimple *use;
|
|
3415 imm_use_iterator imm_iter;
|
|
3416 FOR_EACH_IMM_USE_STMT (use, imm_iter, poisoned_var)
|
|
3417 {
|
|
3418 if (is_gimple_debug (use))
|
|
3419 continue;
|
|
3420
|
|
3421 int nargs;
|
|
3422 bool store_p = gimple_call_internal_p (use, IFN_ASAN_POISON_USE);
|
|
3423 tree fun = report_error_func (store_p, recover_p, tree_to_uhwi (size),
|
|
3424 &nargs);
|
|
3425
|
|
3426 gcall *call = gimple_build_call (fun, 1,
|
|
3427 build_fold_addr_expr (shadow_var));
|
|
3428 gimple_set_location (call, gimple_location (use));
|
|
3429 gimple *call_to_insert = call;
|
|
3430
|
|
3431 /* The USE can be a gimple PHI node. If so, insert the call on
|
|
3432 all edges leading to the PHI node. */
|
|
3433 if (is_a <gphi *> (use))
|
|
3434 {
|
|
3435 gphi *phi = dyn_cast<gphi *> (use);
|
|
3436 for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
|
|
3437 if (gimple_phi_arg_def (phi, i) == poisoned_var)
|
|
3438 {
|
|
3439 edge e = gimple_phi_arg_edge (phi, i);
|
|
3440
|
|
3441 /* Do not insert on an edge we can't split. */
|
|
3442 if (e->flags & EDGE_ABNORMAL)
|
|
3443 continue;
|
|
3444
|
|
3445 if (call_to_insert == NULL)
|
|
3446 call_to_insert = gimple_copy (call);
|
|
3447
|
|
3448 gsi_insert_seq_on_edge (e, call_to_insert);
|
|
3449 *need_commit_edge_insert = true;
|
|
3450 call_to_insert = NULL;
|
|
3451 }
|
|
3452 }
|
|
3453 else
|
|
3454 {
|
|
3455 gimple_stmt_iterator gsi = gsi_for_stmt (use);
|
|
3456 if (store_p)
|
|
3457 gsi_replace (&gsi, call, true);
|
|
3458 else
|
|
3459 gsi_insert_before (&gsi, call, GSI_NEW_STMT);
|
|
3460 }
|
|
3461 }
|
|
3462
|
|
3463 SSA_NAME_IS_DEFAULT_DEF (poisoned_var) = true;
|
|
3464 SSA_NAME_DEF_STMT (poisoned_var) = gimple_build_nop ();
|
|
3465 gsi_replace (iter, poison_call, false);
|
|
3466
|
|
3467 return true;
|
|
3468 }
|
|
3469
|
|
3470 /* Instrument the current function. */
|
|
3471
|
|
3472 static unsigned int
|
|
3473 asan_instrument (void)
|
|
3474 {
|
|
3475 if (shadow_ptr_types[0] == NULL_TREE)
|
|
3476 asan_init_shadow_ptr_types ();
|
|
3477 transform_statements ();
|
|
3478 last_alloca_addr = NULL_TREE;
|
|
3479 return 0;
|
|
3480 }
|
|
3481
|
|
3482 static bool
|
|
3483 gate_asan (void)
|
|
3484 {
|
|
3485 return sanitize_flags_p (SANITIZE_ADDRESS);
|
|
3486 }
|
|
3487
|
|
3488 namespace {
|
|
3489
|
|
3490 const pass_data pass_data_asan =
|
|
3491 {
|
|
3492 GIMPLE_PASS, /* type */
|
|
3493 "asan", /* name */
|
|
3494 OPTGROUP_NONE, /* optinfo_flags */
|
|
3495 TV_NONE, /* tv_id */
|
|
3496 ( PROP_ssa | PROP_cfg | PROP_gimple_leh ), /* properties_required */
|
|
3497 0, /* properties_provided */
|
|
3498 0, /* properties_destroyed */
|
|
3499 0, /* todo_flags_start */
|
|
3500 TODO_update_ssa, /* todo_flags_finish */
|
|
3501 };
|
|
3502
|
|
3503 class pass_asan : public gimple_opt_pass
|
|
3504 {
|
|
3505 public:
|
|
3506 pass_asan (gcc::context *ctxt)
|
|
3507 : gimple_opt_pass (pass_data_asan, ctxt)
|
|
3508 {}
|
|
3509
|
|
3510 /* opt_pass methods: */
|
|
3511 opt_pass * clone () { return new pass_asan (m_ctxt); }
|
|
3512 virtual bool gate (function *) { return gate_asan (); }
|
|
3513 virtual unsigned int execute (function *) { return asan_instrument (); }
|
|
3514
|
|
3515 }; // class pass_asan
|
|
3516
|
|
3517 } // anon namespace
|
|
3518
|
|
3519 gimple_opt_pass *
|
|
3520 make_pass_asan (gcc::context *ctxt)
|
|
3521 {
|
|
3522 return new pass_asan (ctxt);
|
|
3523 }
|
|
3524
|
|
3525 namespace {
|
|
3526
|
|
3527 const pass_data pass_data_asan_O0 =
|
|
3528 {
|
|
3529 GIMPLE_PASS, /* type */
|
|
3530 "asan0", /* name */
|
|
3531 OPTGROUP_NONE, /* optinfo_flags */
|
|
3532 TV_NONE, /* tv_id */
|
|
3533 ( PROP_ssa | PROP_cfg | PROP_gimple_leh ), /* properties_required */
|
|
3534 0, /* properties_provided */
|
|
3535 0, /* properties_destroyed */
|
|
3536 0, /* todo_flags_start */
|
|
3537 TODO_update_ssa, /* todo_flags_finish */
|
|
3538 };
|
|
3539
|
|
3540 class pass_asan_O0 : public gimple_opt_pass
|
|
3541 {
|
|
3542 public:
|
|
3543 pass_asan_O0 (gcc::context *ctxt)
|
|
3544 : gimple_opt_pass (pass_data_asan_O0, ctxt)
|
|
3545 {}
|
|
3546
|
|
3547 /* opt_pass methods: */
|
|
3548 virtual bool gate (function *) { return !optimize && gate_asan (); }
|
|
3549 virtual unsigned int execute (function *) { return asan_instrument (); }
|
|
3550
|
|
3551 }; // class pass_asan_O0
|
|
3552
|
|
3553 } // anon namespace
|
|
3554
|
|
3555 gimple_opt_pass *
|
|
3556 make_pass_asan_O0 (gcc::context *ctxt)
|
|
3557 {
|
|
3558 return new pass_asan_O0 (ctxt);
|
|
3559 }
|
|
3560
|
|
3561 #include "gt-asan.h"
|