Line data Source code
1 : /* AddressSanitizer, a fast memory error detector.
2 : Copyright (C) 2012-2026 Free Software Foundation, Inc.
3 : Contributed by Kostya Serebryany <kcc@google.com>
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it under
8 : the terms of the GNU General Public License as published by the Free
9 : Software Foundation; either version 3, or (at your option) any later
10 : version.
11 :
12 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 :
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 "builtins.h"
63 : #include "fnmatch.h"
64 : #include "tree-inline.h"
65 : #include "tree-ssa.h"
66 : #include "tree-eh.h"
67 : #include "diagnostic-core.h"
68 :
69 : /* AddressSanitizer finds out-of-bounds and use-after-free bugs
70 : with <2x slowdown on average.
71 :
72 : The tool consists of two parts:
73 : instrumentation module (this file) and a run-time library.
74 : The instrumentation module adds a run-time check before every memory insn.
75 : For a 8- or 16- byte load accessing address X:
76 : ShadowAddr = (X >> 3) + Offset
77 : ShadowValue = *(char*)ShadowAddr; // *(short*) for 16-byte access.
78 : if (ShadowValue)
79 : __asan_report_load8(X);
80 : For a load of N bytes (N=1, 2 or 4) from address X:
81 : ShadowAddr = (X >> 3) + Offset
82 : ShadowValue = *(char*)ShadowAddr;
83 : if (ShadowValue)
84 : if ((X & 7) + N - 1 > ShadowValue)
85 : __asan_report_loadN(X);
86 : Stores are instrumented similarly, but using __asan_report_storeN functions.
87 : A call too __asan_init_vN() is inserted to the list of module CTORs.
88 : N is the version number of the AddressSanitizer API. The changes between the
89 : API versions are listed in libsanitizer/asan/asan_interface_internal.h.
90 :
91 : The run-time library redefines malloc (so that redzone are inserted around
92 : the allocated memory) and free (so that reuse of free-ed memory is delayed),
93 : provides __asan_report* and __asan_init_vN functions.
94 :
95 : Read more:
96 : http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm
97 :
98 : The current implementation supports detection of out-of-bounds and
99 : use-after-free in the heap, on the stack and for global variables.
100 :
101 : [Protection of stack variables]
102 :
103 : To understand how detection of out-of-bounds and use-after-free works
104 : for stack variables, lets look at this example on x86_64 where the
105 : stack grows downward:
106 :
107 : int
108 : foo ()
109 : {
110 : char a[24] = {0};
111 : int b[2] = {0};
112 :
113 : a[5] = 1;
114 : b[1] = 2;
115 :
116 : return a[5] + b[1];
117 : }
118 :
119 : For this function, the stack protected by asan will be organized as
120 : follows, from the top of the stack to the bottom:
121 :
122 : Slot 1/ [red zone of 32 bytes called 'RIGHT RedZone']
123 :
124 : Slot 2/ [8 bytes of red zone, that adds up to the space of 'a' to make
125 : the next slot be 32 bytes aligned; this one is called Partial
126 : Redzone; this 32 bytes alignment is an asan constraint]
127 :
128 : Slot 3/ [24 bytes for variable 'a']
129 :
130 : Slot 4/ [red zone of 32 bytes called 'Middle RedZone']
131 :
132 : Slot 5/ [24 bytes of Partial Red Zone (similar to slot 2]
133 :
134 : Slot 6/ [8 bytes for variable 'b']
135 :
136 : Slot 7/ [32 bytes of Red Zone at the bottom of the stack, called
137 : 'LEFT RedZone']
138 :
139 : The 32 bytes of LEFT red zone at the bottom of the stack can be
140 : decomposed as such:
141 :
142 : 1/ The first 8 bytes contain a magical asan number that is always
143 : 0x41B58AB3.
144 :
145 : 2/ The following 8 bytes contains a pointer to a string (to be
146 : parsed at runtime by the runtime asan library), which format is
147 : the following:
148 :
149 : "<function-name> <space> <num-of-variables-on-the-stack>
150 : (<32-bytes-aligned-offset-in-bytes-of-variable> <space>
151 : <length-of-var-in-bytes> ){n} "
152 :
153 : where '(...){n}' means the content inside the parenthesis occurs 'n'
154 : times, with 'n' being the number of variables on the stack.
155 :
156 : 3/ The following 8 bytes contain the PC of the current function which
157 : will be used by the run-time library to print an error message.
158 :
159 : 4/ The following 8 bytes are reserved for internal use by the run-time.
160 :
161 : The shadow memory for that stack layout is going to look like this:
162 :
163 : - content of shadow memory 8 bytes for slot 7: 0xF1F1F1F1.
164 : The F1 byte pattern is a magic number called
165 : ASAN_STACK_MAGIC_LEFT and is a way for the runtime to know that
166 : the memory for that shadow byte is part of a the LEFT red zone
167 : intended to seat at the bottom of the variables on the stack.
168 :
169 : - content of shadow memory 8 bytes for slots 6 and 5:
170 : 0xF4F4F400. The F4 byte pattern is a magic number
171 : called ASAN_STACK_MAGIC_PARTIAL. It flags the fact that the
172 : memory region for this shadow byte is a PARTIAL red zone
173 : intended to pad a variable A, so that the slot following
174 : {A,padding} is 32 bytes aligned.
175 :
176 : Note that the fact that the least significant byte of this
177 : shadow memory content is 00 means that 8 bytes of its
178 : corresponding memory (which corresponds to the memory of
179 : variable 'b') is addressable.
180 :
181 : - content of shadow memory 8 bytes for slot 4: 0xF2F2F2F2.
182 : The F2 byte pattern is a magic number called
183 : ASAN_STACK_MAGIC_MIDDLE. It flags the fact that the memory
184 : region for this shadow byte is a MIDDLE red zone intended to
185 : seat between two 32 aligned slots of {variable,padding}.
186 :
187 : - content of shadow memory 8 bytes for slot 3 and 2:
188 : 0xF4000000. This represents is the concatenation of
189 : variable 'a' and the partial red zone following it, like what we
190 : had for variable 'b'. The least significant 3 bytes being 00
191 : means that the 3 bytes of variable 'a' are addressable.
192 :
193 : - content of shadow memory 8 bytes for slot 1: 0xF3F3F3F3.
194 : The F3 byte pattern is a magic number called
195 : ASAN_STACK_MAGIC_RIGHT. It flags the fact that the memory
196 : region for this shadow byte is a RIGHT red zone intended to seat
197 : at the top of the variables of the stack.
198 :
199 : Note that the real variable layout is done in expand_used_vars in
200 : cfgexpand.cc. As far as Address Sanitizer is concerned, it lays out
201 : stack variables as well as the different red zones, emits some
202 : prologue code to populate the shadow memory as to poison (mark as
203 : non-accessible) the regions of the red zones and mark the regions of
204 : stack variables as accessible, and emit some epilogue code to
205 : un-poison (mark as accessible) the regions of red zones right before
206 : the function exits.
207 :
208 : [Protection of global variables]
209 :
210 : The basic idea is to insert a red zone between two global variables
211 : and install a constructor function that calls the asan runtime to do
212 : the populating of the relevant shadow memory regions at load time.
213 :
214 : So the global variables are laid out as to insert a red zone between
215 : them. The size of the red zones is so that each variable starts on a
216 : 32 bytes boundary.
217 :
218 : Then a constructor function is installed so that, for each global
219 : variable, it calls the runtime asan library function
220 : __asan_register_globals_with an instance of this type:
221 :
222 : struct __asan_global
223 : {
224 : // Address of the beginning of the global variable.
225 : const void *__beg;
226 :
227 : // Initial size of the global variable.
228 : uptr __size;
229 :
230 : // Size of the global variable + size of the red zone. This
231 : // size is 32 bytes aligned.
232 : uptr __size_with_redzone;
233 :
234 : // Name of the global variable.
235 : const void *__name;
236 :
237 : // Name of the module where the global variable is declared.
238 : const void *__module_name;
239 :
240 : // 1 if it has dynamic initialization, 0 otherwise.
241 : uptr __has_dynamic_init;
242 :
243 : // A pointer to struct that contains source location, could be NULL.
244 : __asan_global_source_location *__location;
245 : }
246 :
247 : A destructor function that calls the runtime asan library function
248 : _asan_unregister_globals is also installed. */
249 :
250 : static unsigned HOST_WIDE_INT asan_shadow_offset_value;
251 : static bool asan_shadow_offset_computed;
252 : static vec<char *> sanitized_sections;
253 : static tree last_alloca_addr;
254 :
255 : /* Set of variable declarations that are going to be guarded by
256 : use-after-scope sanitizer. */
257 :
258 : hash_set<tree> *asan_handled_variables = NULL;
259 :
260 : hash_set <tree> *asan_used_labels = NULL;
261 :
262 : /* Global variables for HWASAN stack tagging. */
263 : /* hwasan_frame_tag_offset records the offset from the frame base tag that the
264 : next object should have. */
265 : static uint8_t hwasan_frame_tag_offset = 0;
266 : /* hwasan_frame_base_ptr is a pointer with the same address as
267 : `virtual_stack_vars_rtx` for the current frame, and with the frame base tag
268 : stored in it. N.b. this global RTX does not need to be marked GTY, but is
269 : done so anyway. The need is not there since all uses are in just one pass
270 : (cfgexpand) and there are no calls to ggc_collect between the uses. We mark
271 : it GTY(()) anyway to allow the use of the variable later on if needed by
272 : future features. */
273 : static GTY(()) rtx hwasan_frame_base_ptr = NULL_RTX;
274 : /* hwasan_frame_base_init_seq is the sequence of RTL insns that will initialize
275 : the hwasan_frame_base_ptr. When the hwasan_frame_base_ptr is requested, we
276 : generate this sequence but do not emit it. If the sequence was created it
277 : is emitted once the function body has been expanded.
278 :
279 : This delay is because the frame base pointer may be needed anywhere in the
280 : function body, or needed by the expand_used_vars function. Emitting once in
281 : a known place is simpler than requiring the emission of the instructions to
282 : be know where it should go depending on the first place the hwasan frame
283 : base is needed. */
284 : static GTY(()) rtx_insn *hwasan_frame_base_init_seq = NULL;
285 :
286 : /* Structure defining the extent of one object on the stack that HWASAN needs
287 : to tag in the corresponding shadow stack space.
288 :
289 : The range this object spans on the stack is between `untagged_base +
290 : nearest_offset` and `untagged_base + farthest_offset`.
291 : `tagged_base` is an rtx containing the same value as `untagged_base` but
292 : with a random tag stored in the top byte. We record both `untagged_base`
293 : and `tagged_base` so that `hwasan_emit_prologue` can use both without having
294 : to emit RTL into the instruction stream to re-calculate one from the other.
295 : (`hwasan_emit_prologue` needs to use both bases since the
296 : __hwasan_tag_memory call it emits uses an untagged value, and it calculates
297 : the tag to store in shadow memory based on the tag_offset plus the tag in
298 : tagged_base). */
299 : struct hwasan_stack_var
300 : {
301 : rtx untagged_base;
302 : rtx tagged_base;
303 : poly_int64 nearest_offset;
304 : poly_int64 farthest_offset;
305 : uint8_t tag_offset;
306 : };
307 :
308 : /* Variable recording all stack variables that HWASAN needs to tag.
309 : Does not need to be marked as GTY(()) since every use is in the cfgexpand
310 : pass and gcc_collect is not called in the middle of that pass. */
311 : static vec<hwasan_stack_var> hwasan_tagged_stack_vars;
312 :
313 :
314 : /* Sets shadow offset to value in string VAL. */
315 :
316 : bool
317 11 : set_asan_shadow_offset (const char *val)
318 : {
319 11 : char *endp;
320 :
321 11 : errno = 0;
322 : #ifdef HAVE_LONG_LONG
323 11 : asan_shadow_offset_value = strtoull (val, &endp, 0);
324 : #else
325 : asan_shadow_offset_value = strtoul (val, &endp, 0);
326 : #endif
327 11 : if (!(*val != '\0' && *endp == '\0' && errno == 0))
328 : return false;
329 :
330 11 : asan_shadow_offset_computed = true;
331 :
332 11 : return true;
333 : }
334 :
335 : /* Set list of user-defined sections that need to be sanitized. */
336 :
337 : void
338 40 : set_sanitized_sections (const char *sections)
339 : {
340 40 : char *pat;
341 40 : unsigned i;
342 50 : FOR_EACH_VEC_ELT (sanitized_sections, i, pat)
343 10 : free (pat);
344 40 : sanitized_sections.truncate (0);
345 :
346 130 : for (const char *s = sections; *s; )
347 : {
348 : const char *end;
349 220 : for (end = s; *end && *end != ','; ++end);
350 50 : size_t len = end - s;
351 50 : sanitized_sections.safe_push (xstrndup (s, len));
352 50 : s = *end ? end + 1 : end;
353 : }
354 40 : }
355 :
356 : bool
357 105907 : asan_mark_p (gimple *stmt, enum asan_mark_flags flag)
358 : {
359 105907 : return (gimple_call_internal_p (stmt, IFN_ASAN_MARK)
360 105907 : && tree_to_uhwi (gimple_call_arg (stmt, 0)) == flag);
361 : }
362 :
363 : bool
364 21140649 : asan_sanitize_stack_p (void)
365 : {
366 21140649 : return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_stack);
367 : }
368 :
369 : bool
370 1516303 : asan_sanitize_allocas_p (void)
371 : {
372 1516303 : return (asan_sanitize_stack_p () && param_asan_protect_allocas);
373 : }
374 :
375 : bool
376 13734 : asan_instrument_reads (void)
377 : {
378 13734 : return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_instrument_reads);
379 : }
380 :
381 : bool
382 12691 : asan_instrument_writes (void)
383 : {
384 12691 : return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_instrument_writes);
385 : }
386 :
387 : bool
388 4409 : asan_memintrin (void)
389 : {
390 4409 : return (sanitize_flags_p (SANITIZE_ADDRESS) && param_asan_memintrin);
391 : }
392 :
393 :
394 : /* Support for --param asan-kernel-mem-intrinsic-prefix=1. */
395 : static GTY(()) rtx asan_memfn_rtls[3];
396 :
397 : rtx
398 42 : asan_memfn_rtl (tree fndecl)
399 : {
400 42 : int i;
401 42 : const char *f, *p;
402 42 : char buf[sizeof ("__hwasan_memmove")];
403 :
404 42 : switch (DECL_FUNCTION_CODE (fndecl))
405 : {
406 : case BUILT_IN_MEMCPY: i = 0; f = "memcpy"; break;
407 14 : case BUILT_IN_MEMSET: i = 1; f = "memset"; break;
408 14 : case BUILT_IN_MEMMOVE: i = 2; f = "memmove"; break;
409 0 : default: gcc_unreachable ();
410 : }
411 42 : if (asan_memfn_rtls[i] == NULL_RTX)
412 : {
413 42 : tree save_name = DECL_NAME (fndecl);
414 42 : tree save_assembler_name = DECL_ASSEMBLER_NAME (fndecl);
415 42 : rtx save_rtl = DECL_RTL (fndecl);
416 42 : if (flag_sanitize & SANITIZE_KERNEL_HWADDRESS)
417 : p = "__hwasan_";
418 : else
419 42 : p = "__asan_";
420 42 : strcpy (buf, p);
421 42 : strcat (buf, f);
422 42 : DECL_NAME (fndecl) = get_identifier (buf);
423 42 : DECL_ASSEMBLER_NAME_RAW (fndecl) = NULL_TREE;
424 42 : SET_DECL_RTL (fndecl, NULL_RTX);
425 42 : asan_memfn_rtls[i] = DECL_RTL (fndecl);
426 42 : DECL_NAME (fndecl) = save_name;
427 42 : DECL_ASSEMBLER_NAME_RAW (fndecl) = save_assembler_name;
428 42 : SET_DECL_RTL (fndecl, save_rtl);
429 : }
430 42 : return asan_memfn_rtls[i];
431 : }
432 :
433 :
434 : /* Checks whether section SEC should be sanitized. */
435 :
436 : static bool
437 270 : section_sanitized_p (const char *sec)
438 : {
439 270 : char *pat;
440 270 : unsigned i;
441 420 : FOR_EACH_VEC_ELT (sanitized_sections, i, pat)
442 330 : if (fnmatch (pat, sec, FNM_PERIOD) == 0)
443 : return true;
444 : return false;
445 : }
446 :
447 : /* Returns Asan shadow offset. */
448 :
449 : static unsigned HOST_WIDE_INT
450 23693 : asan_shadow_offset ()
451 : {
452 23693 : if (!asan_shadow_offset_computed)
453 : {
454 1751 : asan_shadow_offset_computed = true;
455 1751 : asan_shadow_offset_value = targetm.asan_shadow_offset ();
456 : }
457 23693 : return asan_shadow_offset_value;
458 : }
459 :
460 : static bool
461 30084 : asan_dynamic_shadow_offset_p ()
462 : {
463 30084 : return (asan_shadow_offset_value == 0)
464 30084 : && targetm.asan_dynamic_shadow_offset_p ();
465 : }
466 :
467 : /* Returns Asan shadow offset has been set. */
468 : bool
469 0 : asan_shadow_offset_set_p ()
470 : {
471 0 : return asan_shadow_offset_computed;
472 : }
473 :
474 : alias_set_type asan_shadow_set = -1;
475 :
476 : /* Pointer types to 1, 2 or 4 byte integers in shadow memory. A separate
477 : alias set is used for all shadow memory accesses. */
478 : static GTY(()) tree shadow_ptr_types[3];
479 :
480 : /* Decl for __asan_option_detect_stack_use_after_return. */
481 : static GTY(()) tree asan_detect_stack_use_after_return;
482 :
483 : static GTY (()) tree asan_shadow_memory_dynamic_address;
484 :
485 : /* Local copy for the asan_shadow_memory_dynamic_address within the
486 : function. */
487 : static GTY (()) tree asan_local_shadow_memory_dynamic_address;
488 :
489 : static tree
490 0 : get_asan_shadow_memory_dynamic_address_decl ()
491 : {
492 0 : if (asan_shadow_memory_dynamic_address == NULL_TREE)
493 : {
494 0 : tree id, decl;
495 0 : id = get_identifier ("__asan_shadow_memory_dynamic_address");
496 0 : decl
497 0 : = build_decl (BUILTINS_LOCATION, VAR_DECL, id, pointer_sized_int_node);
498 0 : SET_DECL_ASSEMBLER_NAME (decl, id);
499 0 : TREE_ADDRESSABLE (decl) = 1;
500 0 : DECL_ARTIFICIAL (decl) = 1;
501 0 : DECL_IGNORED_P (decl) = 1;
502 0 : DECL_EXTERNAL (decl) = 1;
503 0 : TREE_STATIC (decl) = 1;
504 0 : TREE_PUBLIC (decl) = 1;
505 0 : TREE_USED (decl) = 1;
506 0 : asan_shadow_memory_dynamic_address = decl;
507 : }
508 :
509 0 : return asan_shadow_memory_dynamic_address;
510 : }
511 :
512 : void
513 6391 : asan_maybe_insert_dynamic_shadow_at_function_entry (function *fun)
514 : {
515 6391 : asan_local_shadow_memory_dynamic_address = NULL_TREE;
516 6391 : if (!asan_dynamic_shadow_offset_p ())
517 : return;
518 :
519 0 : gimple *g;
520 :
521 0 : tree lhs = create_tmp_var (pointer_sized_int_node,
522 : "__local_asan_shadow_memory_dynamic_address");
523 :
524 0 : g = gimple_build_assign (lhs, get_asan_shadow_memory_dynamic_address_decl ());
525 0 : gimple_set_location (g, fun->function_start_locus);
526 0 : edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
527 0 : gsi_insert_on_edge_immediate (e, g);
528 :
529 0 : asan_local_shadow_memory_dynamic_address = lhs;
530 : }
531 :
532 : /* Hashtable support for memory references used by gimple
533 : statements. */
534 :
535 : /* This type represents a reference to a memory region. */
536 : struct asan_mem_ref
537 : {
538 : /* The expression of the beginning of the memory region. */
539 : tree start;
540 :
541 : /* The size of the access. */
542 : HOST_WIDE_INT access_size;
543 : };
544 :
545 : object_allocator <asan_mem_ref> asan_mem_ref_pool ("asan_mem_ref");
546 :
547 : /* Initializes an instance of asan_mem_ref. */
548 :
549 : static void
550 159517 : asan_mem_ref_init (asan_mem_ref *ref, tree start, HOST_WIDE_INT access_size)
551 : {
552 159584 : ref->start = start;
553 159584 : ref->access_size = access_size;
554 0 : }
555 :
556 : /* Allocates memory for an instance of asan_mem_ref into the memory
557 : pool returned by asan_mem_ref_get_alloc_pool and initialize it.
558 : START is the address of (or the expression pointing to) the
559 : beginning of memory reference. ACCESS_SIZE is the size of the
560 : access to the referenced memory. */
561 :
562 : static asan_mem_ref*
563 37486 : asan_mem_ref_new (tree start, HOST_WIDE_INT access_size)
564 : {
565 0 : asan_mem_ref *ref = asan_mem_ref_pool.allocate ();
566 :
567 37486 : asan_mem_ref_init (ref, start, access_size);
568 37486 : return ref;
569 : }
570 :
571 : /* This builds and returns a pointer to the end of the memory region
572 : that starts at START and of length LEN. */
573 :
574 : tree
575 0 : asan_mem_ref_get_end (tree start, tree len)
576 : {
577 0 : if (len == NULL_TREE || integer_zerop (len))
578 : return start;
579 :
580 0 : if (!ptrofftype_p (len))
581 0 : len = convert_to_ptrofftype (len);
582 :
583 0 : return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (start), start, len);
584 : }
585 :
586 : /* Return a tree expression that represents the end of the referenced
587 : memory region. Beware that this function can actually build a new
588 : tree expression. */
589 :
590 : tree
591 0 : asan_mem_ref_get_end (const asan_mem_ref *ref, tree len)
592 : {
593 0 : return asan_mem_ref_get_end (ref->start, len);
594 : }
595 :
596 : struct asan_mem_ref_hasher : nofree_ptr_hash <asan_mem_ref>
597 : {
598 : static inline hashval_t hash (const asan_mem_ref *);
599 : static inline bool equal (const asan_mem_ref *, const asan_mem_ref *);
600 : };
601 :
602 : /* Hash a memory reference. */
603 :
604 : inline hashval_t
605 254619 : asan_mem_ref_hasher::hash (const asan_mem_ref *mem_ref)
606 : {
607 254619 : return iterative_hash_expr (mem_ref->start, 0);
608 : }
609 :
610 : /* Compare two memory references. We accept the length of either
611 : memory references to be NULL_TREE. */
612 :
613 : inline bool
614 192249 : asan_mem_ref_hasher::equal (const asan_mem_ref *m1,
615 : const asan_mem_ref *m2)
616 : {
617 192249 : return operand_equal_p (m1->start, m2->start, 0);
618 : }
619 :
620 : static hash_table<asan_mem_ref_hasher> *asan_mem_ref_ht;
621 :
622 : /* Returns a reference to the hash table containing memory references.
623 : This function ensures that the hash table is created. Note that
624 : this hash table is updated by the function
625 : update_mem_ref_hash_table. */
626 :
627 : static hash_table<asan_mem_ref_hasher> *
628 83094 : get_mem_ref_hash_table ()
629 : {
630 83094 : if (!asan_mem_ref_ht)
631 3529 : asan_mem_ref_ht = new hash_table<asan_mem_ref_hasher> (10);
632 :
633 83094 : return asan_mem_ref_ht;
634 : }
635 :
636 : /* Clear all entries from the memory references hash table. */
637 :
638 : static void
639 37311 : empty_mem_ref_hash_table ()
640 : {
641 37311 : if (asan_mem_ref_ht)
642 20740 : asan_mem_ref_ht->empty ();
643 37311 : }
644 :
645 : /* Free the memory references hash table. */
646 :
647 : static void
648 6572 : free_mem_ref_resources ()
649 : {
650 6572 : delete asan_mem_ref_ht;
651 6572 : asan_mem_ref_ht = NULL;
652 :
653 6572 : asan_mem_ref_pool.release ();
654 6572 : }
655 :
656 : /* Return true iff the memory reference REF has been instrumented. */
657 :
658 : static bool
659 45596 : has_mem_ref_been_instrumented (tree ref, HOST_WIDE_INT access_size)
660 : {
661 45596 : asan_mem_ref r;
662 45596 : asan_mem_ref_init (&r, ref, access_size);
663 :
664 45596 : asan_mem_ref *saved_ref = get_mem_ref_hash_table ()->find (&r);
665 45596 : return saved_ref && saved_ref->access_size >= access_size;
666 : }
667 :
668 : /* Return true iff the memory reference REF has been instrumented. */
669 :
670 : static bool
671 26692 : has_mem_ref_been_instrumented (const asan_mem_ref *ref)
672 : {
673 0 : return has_mem_ref_been_instrumented (ref->start, ref->access_size);
674 : }
675 :
676 : /* Return true iff access to memory region starting at REF and of
677 : length LEN has been instrumented. */
678 :
679 : static bool
680 963 : has_mem_ref_been_instrumented (const asan_mem_ref *ref, tree len)
681 : {
682 963 : HOST_WIDE_INT size_in_bytes
683 963 : = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
684 :
685 251 : return size_in_bytes != -1
686 251 : && has_mem_ref_been_instrumented (ref->start, size_in_bytes);
687 : }
688 :
689 : /* Set REF to the memory reference present in a gimple assignment
690 : ASSIGNMENT. Return true upon successful completion, false
691 : otherwise. */
692 :
693 : static bool
694 30131 : get_mem_ref_of_assignment (const gassign *assignment,
695 : asan_mem_ref *ref,
696 : bool *ref_is_store)
697 : {
698 30131 : gcc_assert (gimple_assign_single_p (assignment));
699 :
700 30131 : if (gimple_store_p (assignment)
701 30131 : && !gimple_clobber_p (assignment))
702 : {
703 13055 : ref->start = gimple_assign_lhs (assignment);
704 13055 : *ref_is_store = true;
705 : }
706 17076 : else if (gimple_assign_load_p (assignment))
707 : {
708 13570 : ref->start = gimple_assign_rhs1 (assignment);
709 13570 : *ref_is_store = false;
710 : }
711 : else
712 : return false;
713 :
714 26625 : ref->access_size = int_size_in_bytes (TREE_TYPE (ref->start));
715 26625 : return true;
716 : }
717 :
718 : /* Return address of last allocated dynamic alloca. */
719 :
720 : static tree
721 400 : get_last_alloca_addr ()
722 : {
723 400 : if (last_alloca_addr)
724 : return last_alloca_addr;
725 :
726 187 : last_alloca_addr = create_tmp_reg (ptr_type_node, "last_alloca_addr");
727 187 : gassign *g = gimple_build_assign (last_alloca_addr, null_pointer_node);
728 187 : edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
729 187 : gsi_insert_on_edge_immediate (e, g);
730 187 : return last_alloca_addr;
731 : }
732 :
733 : /* Insert __asan_allocas_unpoison (top, bottom) call before
734 : __builtin_stack_restore (new_sp) call.
735 : The pseudocode of this routine should look like this:
736 : top = last_alloca_addr;
737 : bot = new_sp;
738 : __asan_allocas_unpoison (top, bot);
739 : last_alloca_addr = new_sp;
740 : __builtin_stack_restore (new_sp);
741 : In general, we can't use new_sp as bot parameter because on some
742 : architectures SP has non zero offset from dynamic stack area. Moreover, on
743 : some architectures this offset (STACK_DYNAMIC_OFFSET) becomes known for each
744 : particular function only after all callees were expanded to rtl.
745 : The most noticeable example is PowerPC{,64}, see
746 : http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#DYNAM-STACK.
747 : To overcome the issue we use following trick: pass new_sp as a second
748 : parameter to __asan_allocas_unpoison and rewrite it during expansion with
749 : new_sp + (virtual_dynamic_stack_rtx - sp) later in
750 : expand_asan_emit_allocas_unpoison function.
751 :
752 : HWASAN needs to do very similar, the eventual pseudocode should be:
753 : __hwasan_tag_memory (virtual_stack_dynamic_rtx,
754 : 0,
755 : new_sp - sp);
756 : __builtin_stack_restore (new_sp)
757 :
758 : Need to use the same trick to handle STACK_DYNAMIC_OFFSET as described
759 : above. */
760 :
761 : static void
762 410 : handle_builtin_stack_restore (gcall *call, gimple_stmt_iterator *iter)
763 : {
764 410 : if (!iter
765 412 : || !(asan_sanitize_allocas_p () || hwasan_sanitize_allocas_p ()
766 2 : || memtag_sanitize_allocas_p ()))
767 : return;
768 :
769 203 : tree restored_stack = gimple_call_arg (call, 0);
770 :
771 203 : gimple *g;
772 :
773 203 : if (hwasan_sanitize_allocas_p () || memtag_sanitize_allocas_p ())
774 : {
775 0 : enum internal_fn fn = IFN_HWASAN_ALLOCA_UNPOISON;
776 : /* There is only one piece of information `expand_HWASAN_ALLOCA_UNPOISON`
777 : needs to work. This is the length of the area that we're
778 : deallocating. Since the stack pointer is known at expand time, the
779 : position of the new stack pointer after deallocation is enough
780 : information to calculate this length. */
781 0 : g = gimple_build_call_internal (fn, 1, restored_stack);
782 : }
783 : else
784 : {
785 203 : tree last_alloca = get_last_alloca_addr ();
786 203 : tree fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCAS_UNPOISON);
787 203 : g = gimple_build_call (fn, 2, last_alloca, restored_stack);
788 203 : gsi_insert_before (iter, g, GSI_SAME_STMT);
789 203 : g = gimple_build_assign (last_alloca, restored_stack);
790 : }
791 :
792 203 : gsi_insert_before (iter, g, GSI_SAME_STMT);
793 : }
794 :
795 : /* Deploy and poison redzones around __builtin_alloca call. To do this, we
796 : should replace this call with another one with changed parameters and
797 : replace all its uses with new address, so
798 : addr = __builtin_alloca (old_size, align);
799 : is replaced by
800 : left_redzone_size = max (align, ASAN_RED_ZONE_SIZE);
801 : Following two statements are optimized out if we know that
802 : old_size & (ASAN_RED_ZONE_SIZE - 1) == 0, i.e. alloca doesn't need partial
803 : redzone.
804 : misalign = old_size & (ASAN_RED_ZONE_SIZE - 1);
805 : partial_redzone_size = ASAN_RED_ZONE_SIZE - misalign;
806 : right_redzone_size = ASAN_RED_ZONE_SIZE;
807 : additional_size = left_redzone_size + partial_redzone_size +
808 : right_redzone_size;
809 : new_size = old_size + additional_size;
810 : new_alloca = __builtin_alloca (new_size, max (align, 32))
811 : __asan_alloca_poison (new_alloca, old_size)
812 : addr = new_alloca + max (align, ASAN_RED_ZONE_SIZE);
813 : last_alloca_addr = new_alloca;
814 : ADDITIONAL_SIZE is added to make new memory allocation contain not only
815 : requested memory, but also left, partial and right redzones as well as some
816 : additional space, required by alignment. */
817 :
818 : static void
819 398 : handle_builtin_alloca (gcall *call, gimple_stmt_iterator *iter)
820 : {
821 398 : if (!iter
822 400 : || !(asan_sanitize_allocas_p () || hwasan_sanitize_allocas_p ()
823 2 : || memtag_sanitize_allocas_p ()))
824 201 : return;
825 :
826 197 : gassign *g;
827 197 : gcall *gg;
828 197 : tree callee = gimple_call_fndecl (call);
829 197 : tree lhs = gimple_call_lhs (call);
830 197 : tree old_size = gimple_call_arg (call, 0);
831 197 : tree ptr_type = lhs ? TREE_TYPE (lhs) : ptr_type_node;
832 197 : tree partial_size = NULL_TREE;
833 197 : unsigned int align
834 197 : = DECL_FUNCTION_CODE (callee) == BUILT_IN_ALLOCA
835 390 : ? 0 : tree_to_uhwi (gimple_call_arg (call, 1));
836 :
837 197 : bool throws = false;
838 197 : edge e = NULL;
839 197 : if (stmt_can_throw_internal (cfun, call))
840 : {
841 9 : if (!lhs)
842 : return;
843 9 : throws = true;
844 9 : e = find_fallthru_edge (gsi_bb (*iter)->succs);
845 : }
846 :
847 197 : if (hwasan_sanitize_allocas_p () || memtag_sanitize_allocas_p ())
848 : {
849 0 : gimple_seq stmts = NULL;
850 0 : location_t loc = gimple_location (gsi_stmt (*iter));
851 : /* HWASAN and MEMTAG need a different expansion.
852 :
853 : addr = __builtin_alloca (size, align);
854 :
855 : in case of HWASAN, should be replaced by
856 :
857 : new_size = size rounded up to HWASAN_TAG_GRANULE_SIZE byte alignment;
858 : untagged_addr = __builtin_alloca (new_size, align);
859 : tag = __hwasan_choose_alloca_tag ();
860 : addr = ifn_HWASAN_SET_TAG (untagged_addr, tag);
861 : __hwasan_tag_memory (untagged_addr, tag, new_size);
862 :
863 : in case of MEMTAG, should be replaced by
864 :
865 : new_size = size rounded up to HWASAN_TAG_GRANULE_SIZE byte alignment;
866 : untagged_addr = __builtin_alloca (new_size, align);
867 : addr = ifn_HWASAN_ALLOCA_POISON (untagged_addr, new_size);
868 :
869 : where a new tag is chosen and set on untagged_addr when
870 : HWASAN_ALLOCA_POISON is expanded. */
871 :
872 : /* Ensure alignment at least HWASAN_TAG_GRANULE_SIZE bytes so we start on
873 : a tag granule. */
874 0 : align = align > HWASAN_TAG_GRANULE_SIZE ? align : HWASAN_TAG_GRANULE_SIZE;
875 :
876 0 : tree old_size = gimple_call_arg (call, 0);
877 0 : tree new_size = gimple_build_round_up (&stmts, loc, size_type_node,
878 : old_size,
879 0 : HWASAN_TAG_GRANULE_SIZE);
880 :
881 : /* Make the alloca call */
882 0 : tree untagged_addr
883 0 : = gimple_build (&stmts, loc,
884 : as_combined_fn (BUILT_IN_ALLOCA_WITH_ALIGN), ptr_type,
885 0 : new_size, build_int_cst (size_type_node, align));
886 :
887 0 : tree addr;
888 :
889 0 : if (memtag_sanitize_p ())
890 0 : addr = gimple_build (&stmts, loc, CFN_HWASAN_ALLOCA_POISON, ptr_type,
891 : untagged_addr, new_size);
892 : else
893 : {
894 : /* Choose the tag.
895 : Here we use an internal function so we can choose the tag at expand
896 : time. We need the decision to be made after stack variables have been
897 : assigned their tag (i.e. once the hwasan_frame_tag_offset variable has
898 : been set to one after the last stack variables tag). */
899 0 : tree tag = gimple_build (&stmts, loc, CFN_HWASAN_CHOOSE_TAG,
900 : unsigned_char_type_node);
901 :
902 : /* Add tag to pointer. */
903 0 : addr = gimple_build (&stmts, loc, CFN_HWASAN_SET_TAG, ptr_type,
904 : untagged_addr, tag);
905 :
906 : /* Tag shadow memory.
907 : NOTE: require using `untagged_addr` here for libhwasan API. */
908 0 : gimple_build (&stmts, loc, as_combined_fn (BUILT_IN_HWASAN_TAG_MEM),
909 : void_type_node, untagged_addr, tag, new_size);
910 : }
911 :
912 : /* Insert the built up code sequence into the original instruction stream
913 : the iterator points to. */
914 0 : gsi_insert_seq_before (iter, stmts, GSI_SAME_STMT);
915 :
916 : /* Finally, replace old alloca ptr with NEW_ALLOCA. */
917 0 : replace_call_with_value (iter, addr);
918 0 : return;
919 : }
920 :
921 197 : tree last_alloca = get_last_alloca_addr ();
922 197 : const HOST_WIDE_INT redzone_mask = ASAN_RED_ZONE_SIZE - 1;
923 :
924 : /* If ALIGN > ASAN_RED_ZONE_SIZE, we embed left redzone into first ALIGN
925 : bytes of allocated space. Otherwise, align alloca to ASAN_RED_ZONE_SIZE
926 : manually. */
927 197 : align = MAX (align, ASAN_RED_ZONE_SIZE * BITS_PER_UNIT);
928 :
929 197 : tree alloca_rz_mask = build_int_cst (size_type_node, redzone_mask);
930 197 : tree redzone_size = build_int_cst (size_type_node, ASAN_RED_ZONE_SIZE);
931 :
932 : /* Extract lower bits from old_size. */
933 197 : wide_int size_nonzero_bits = get_nonzero_bits (old_size);
934 197 : wide_int rz_mask
935 197 : = wi::uhwi (redzone_mask, wi::get_precision (size_nonzero_bits));
936 197 : wide_int old_size_lower_bits = wi::bit_and (size_nonzero_bits, rz_mask);
937 :
938 : /* If alloca size is aligned to ASAN_RED_ZONE_SIZE, we don't need partial
939 : redzone. Otherwise, compute its size here. */
940 197 : if (wi::ne_p (old_size_lower_bits, 0))
941 : {
942 : /* misalign = size & (ASAN_RED_ZONE_SIZE - 1)
943 : partial_size = ASAN_RED_ZONE_SIZE - misalign. */
944 194 : g = gimple_build_assign (make_ssa_name (size_type_node, NULL),
945 : BIT_AND_EXPR, old_size, alloca_rz_mask);
946 194 : gsi_insert_before (iter, g, GSI_SAME_STMT);
947 194 : tree misalign = gimple_assign_lhs (g);
948 194 : g = gimple_build_assign (make_ssa_name (size_type_node, NULL), MINUS_EXPR,
949 : redzone_size, misalign);
950 194 : gsi_insert_before (iter, g, GSI_SAME_STMT);
951 194 : partial_size = gimple_assign_lhs (g);
952 : }
953 :
954 : /* additional_size = align + ASAN_RED_ZONE_SIZE. */
955 394 : tree additional_size = build_int_cst (size_type_node, align / BITS_PER_UNIT
956 197 : + ASAN_RED_ZONE_SIZE);
957 : /* If alloca has partial redzone, include it to additional_size too. */
958 197 : if (partial_size)
959 : {
960 : /* additional_size += partial_size. */
961 194 : g = gimple_build_assign (make_ssa_name (size_type_node), PLUS_EXPR,
962 : partial_size, additional_size);
963 194 : gsi_insert_before (iter, g, GSI_SAME_STMT);
964 194 : additional_size = gimple_assign_lhs (g);
965 : }
966 :
967 : /* new_size = old_size + additional_size. */
968 197 : g = gimple_build_assign (make_ssa_name (size_type_node), PLUS_EXPR, old_size,
969 : additional_size);
970 197 : gsi_insert_before (iter, g, GSI_SAME_STMT);
971 197 : tree new_size = gimple_assign_lhs (g);
972 :
973 : /* Build new __builtin_alloca call:
974 : new_alloca_with_rz = __builtin_alloca (new_size, align). */
975 197 : tree fn = builtin_decl_implicit (BUILT_IN_ALLOCA_WITH_ALIGN);
976 197 : gg = gimple_build_call (fn, 2, new_size,
977 197 : build_int_cst (size_type_node, align));
978 197 : tree new_alloca_with_rz = make_ssa_name (ptr_type, gg);
979 197 : gimple_call_set_lhs (gg, new_alloca_with_rz);
980 197 : if (throws)
981 : {
982 9 : gimple_call_set_lhs (call, NULL);
983 9 : gsi_replace (iter, gg, true);
984 : }
985 : else
986 188 : gsi_insert_before (iter, gg, GSI_SAME_STMT);
987 :
988 : /* new_alloca = new_alloca_with_rz + align. */
989 197 : g = gimple_build_assign (make_ssa_name (ptr_type), POINTER_PLUS_EXPR,
990 : new_alloca_with_rz,
991 : build_int_cst (size_type_node,
992 197 : align / BITS_PER_UNIT));
993 197 : gimple_stmt_iterator gsi = gsi_none ();
994 197 : if (throws)
995 : {
996 9 : gsi_insert_on_edge_immediate (e, g);
997 9 : gsi = gsi_for_stmt (g);
998 : }
999 : else
1000 188 : gsi_insert_before (iter, g, GSI_SAME_STMT);
1001 197 : tree new_alloca = gimple_assign_lhs (g);
1002 :
1003 : /* Poison newly created alloca redzones:
1004 : __asan_alloca_poison (new_alloca, old_size). */
1005 197 : fn = builtin_decl_implicit (BUILT_IN_ASAN_ALLOCA_POISON);
1006 197 : gg = gimple_build_call (fn, 2, new_alloca, old_size);
1007 197 : if (throws)
1008 9 : gsi_insert_after (&gsi, gg, GSI_NEW_STMT);
1009 : else
1010 188 : gsi_insert_before (iter, gg, GSI_SAME_STMT);
1011 :
1012 : /* Save new_alloca_with_rz value into last_alloca to use it during
1013 : allocas unpoisoning. */
1014 197 : g = gimple_build_assign (last_alloca, new_alloca_with_rz);
1015 197 : if (throws)
1016 9 : gsi_insert_after (&gsi, g, GSI_NEW_STMT);
1017 : else
1018 188 : gsi_insert_before (iter, g, GSI_SAME_STMT);
1019 :
1020 : /* Finally, replace old alloca ptr with NEW_ALLOCA. */
1021 197 : if (throws)
1022 : {
1023 9 : g = gimple_build_assign (lhs, new_alloca);
1024 9 : gsi_insert_after (&gsi, g, GSI_NEW_STMT);
1025 : }
1026 : else
1027 188 : replace_call_with_value (iter, new_alloca);
1028 197 : }
1029 :
1030 : /* Return the memory references contained in a gimple statement
1031 : representing a builtin call that has to do with memory access. */
1032 :
1033 : static bool
1034 8806 : get_mem_refs_of_builtin_call (gcall *call,
1035 : asan_mem_ref *src0,
1036 : tree *src0_len,
1037 : bool *src0_is_store,
1038 : asan_mem_ref *src1,
1039 : tree *src1_len,
1040 : bool *src1_is_store,
1041 : asan_mem_ref *dst,
1042 : tree *dst_len,
1043 : bool *dst_is_store,
1044 : bool *dest_is_deref,
1045 : bool *intercepted_p,
1046 : gimple_stmt_iterator *iter = NULL)
1047 : {
1048 8806 : gcc_checking_assert (gimple_call_builtin_p (call, BUILT_IN_NORMAL));
1049 :
1050 8806 : tree callee = gimple_call_fndecl (call);
1051 8806 : tree source0 = NULL_TREE, source1 = NULL_TREE,
1052 8806 : dest = NULL_TREE, len = NULL_TREE;
1053 8806 : bool is_store = true, got_reference_p = false;
1054 8806 : HOST_WIDE_INT access_size = 1;
1055 :
1056 8806 : *intercepted_p = asan_intercepted_p ((DECL_FUNCTION_CODE (callee)));
1057 :
1058 8806 : switch (DECL_FUNCTION_CODE (callee))
1059 : {
1060 : /* (s, s, n) style memops. */
1061 112 : case BUILT_IN_BCMP:
1062 112 : case BUILT_IN_MEMCMP:
1063 112 : source0 = gimple_call_arg (call, 0);
1064 112 : source1 = gimple_call_arg (call, 1);
1065 112 : len = gimple_call_arg (call, 2);
1066 112 : break;
1067 :
1068 : /* (src, dest, n) style memops. */
1069 0 : case BUILT_IN_BCOPY:
1070 0 : source0 = gimple_call_arg (call, 0);
1071 0 : dest = gimple_call_arg (call, 1);
1072 0 : len = gimple_call_arg (call, 2);
1073 0 : break;
1074 :
1075 : /* (dest, src, n) style memops. */
1076 1250 : case BUILT_IN_MEMCPY:
1077 1250 : case BUILT_IN_MEMCPY_CHK:
1078 1250 : case BUILT_IN_MEMMOVE:
1079 1250 : case BUILT_IN_MEMMOVE_CHK:
1080 1250 : case BUILT_IN_MEMPCPY:
1081 1250 : case BUILT_IN_MEMPCPY_CHK:
1082 1250 : dest = gimple_call_arg (call, 0);
1083 1250 : source0 = gimple_call_arg (call, 1);
1084 1250 : len = gimple_call_arg (call, 2);
1085 1250 : break;
1086 :
1087 : /* (dest, n) style memops. */
1088 0 : case BUILT_IN_BZERO:
1089 0 : dest = gimple_call_arg (call, 0);
1090 0 : len = gimple_call_arg (call, 1);
1091 0 : break;
1092 :
1093 : /* (dest, x, n) style memops*/
1094 388 : case BUILT_IN_MEMSET:
1095 388 : case BUILT_IN_MEMSET_CHK:
1096 388 : dest = gimple_call_arg (call, 0);
1097 388 : len = gimple_call_arg (call, 2);
1098 388 : break;
1099 :
1100 104 : case BUILT_IN_STRLEN:
1101 : /* Special case strlen here since its length is taken from its return
1102 : value.
1103 :
1104 : The approach taken by the sanitizers is to check a memory access
1105 : before it's taken. For ASAN strlen is intercepted by libasan, so no
1106 : check is inserted by the compiler.
1107 :
1108 : This function still returns `true` and provides a length to the rest
1109 : of the ASAN pass in order to record what areas have been checked,
1110 : avoiding superfluous checks later on.
1111 :
1112 : HWASAN does not intercept any of these internal functions.
1113 : This means that checks for memory accesses must be inserted by the
1114 : compiler.
1115 : strlen is a special case, because we can tell the length from the
1116 : return of the function, but that is not known until after the function
1117 : has returned.
1118 :
1119 : Hence we can't check the memory access before it happens.
1120 : We could check the memory access after it has already happened, but
1121 : for now we choose to just ignore `strlen` calls.
1122 : This decision was simply made because that means the special case is
1123 : limited to this one case of this one function. */
1124 104 : if (hwassist_sanitize_p ())
1125 : return false;
1126 72 : source0 = gimple_call_arg (call, 0);
1127 72 : len = gimple_call_lhs (call);
1128 72 : break;
1129 :
1130 410 : case BUILT_IN_STACK_RESTORE:
1131 410 : handle_builtin_stack_restore (call, iter);
1132 410 : break;
1133 :
1134 398 : CASE_BUILT_IN_ALLOCA:
1135 398 : handle_builtin_alloca (call, iter);
1136 398 : break;
1137 : /* And now the __atomic* and __sync builtins.
1138 : These are handled differently from the classical memory
1139 : access builtins above. */
1140 :
1141 0 : case BUILT_IN_ATOMIC_LOAD_1:
1142 0 : is_store = false;
1143 : /* FALLTHRU */
1144 0 : case BUILT_IN_SYNC_FETCH_AND_ADD_1:
1145 0 : case BUILT_IN_SYNC_FETCH_AND_SUB_1:
1146 0 : case BUILT_IN_SYNC_FETCH_AND_OR_1:
1147 0 : case BUILT_IN_SYNC_FETCH_AND_AND_1:
1148 0 : case BUILT_IN_SYNC_FETCH_AND_XOR_1:
1149 0 : case BUILT_IN_SYNC_FETCH_AND_NAND_1:
1150 0 : case BUILT_IN_SYNC_ADD_AND_FETCH_1:
1151 0 : case BUILT_IN_SYNC_SUB_AND_FETCH_1:
1152 0 : case BUILT_IN_SYNC_OR_AND_FETCH_1:
1153 0 : case BUILT_IN_SYNC_AND_AND_FETCH_1:
1154 0 : case BUILT_IN_SYNC_XOR_AND_FETCH_1:
1155 0 : case BUILT_IN_SYNC_NAND_AND_FETCH_1:
1156 0 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1:
1157 0 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1:
1158 0 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
1159 0 : case BUILT_IN_SYNC_LOCK_RELEASE_1:
1160 0 : case BUILT_IN_ATOMIC_EXCHANGE_1:
1161 0 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1:
1162 0 : case BUILT_IN_ATOMIC_STORE_1:
1163 0 : case BUILT_IN_ATOMIC_ADD_FETCH_1:
1164 0 : case BUILT_IN_ATOMIC_SUB_FETCH_1:
1165 0 : case BUILT_IN_ATOMIC_AND_FETCH_1:
1166 0 : case BUILT_IN_ATOMIC_NAND_FETCH_1:
1167 0 : case BUILT_IN_ATOMIC_XOR_FETCH_1:
1168 0 : case BUILT_IN_ATOMIC_OR_FETCH_1:
1169 0 : case BUILT_IN_ATOMIC_FETCH_ADD_1:
1170 0 : case BUILT_IN_ATOMIC_FETCH_SUB_1:
1171 0 : case BUILT_IN_ATOMIC_FETCH_AND_1:
1172 0 : case BUILT_IN_ATOMIC_FETCH_NAND_1:
1173 0 : case BUILT_IN_ATOMIC_FETCH_XOR_1:
1174 0 : case BUILT_IN_ATOMIC_FETCH_OR_1:
1175 0 : access_size = 1;
1176 0 : goto do_atomic;
1177 :
1178 0 : case BUILT_IN_ATOMIC_LOAD_2:
1179 0 : is_store = false;
1180 : /* FALLTHRU */
1181 0 : case BUILT_IN_SYNC_FETCH_AND_ADD_2:
1182 0 : case BUILT_IN_SYNC_FETCH_AND_SUB_2:
1183 0 : case BUILT_IN_SYNC_FETCH_AND_OR_2:
1184 0 : case BUILT_IN_SYNC_FETCH_AND_AND_2:
1185 0 : case BUILT_IN_SYNC_FETCH_AND_XOR_2:
1186 0 : case BUILT_IN_SYNC_FETCH_AND_NAND_2:
1187 0 : case BUILT_IN_SYNC_ADD_AND_FETCH_2:
1188 0 : case BUILT_IN_SYNC_SUB_AND_FETCH_2:
1189 0 : case BUILT_IN_SYNC_OR_AND_FETCH_2:
1190 0 : case BUILT_IN_SYNC_AND_AND_FETCH_2:
1191 0 : case BUILT_IN_SYNC_XOR_AND_FETCH_2:
1192 0 : case BUILT_IN_SYNC_NAND_AND_FETCH_2:
1193 0 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2:
1194 0 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2:
1195 0 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
1196 0 : case BUILT_IN_SYNC_LOCK_RELEASE_2:
1197 0 : case BUILT_IN_ATOMIC_EXCHANGE_2:
1198 0 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2:
1199 0 : case BUILT_IN_ATOMIC_STORE_2:
1200 0 : case BUILT_IN_ATOMIC_ADD_FETCH_2:
1201 0 : case BUILT_IN_ATOMIC_SUB_FETCH_2:
1202 0 : case BUILT_IN_ATOMIC_AND_FETCH_2:
1203 0 : case BUILT_IN_ATOMIC_NAND_FETCH_2:
1204 0 : case BUILT_IN_ATOMIC_XOR_FETCH_2:
1205 0 : case BUILT_IN_ATOMIC_OR_FETCH_2:
1206 0 : case BUILT_IN_ATOMIC_FETCH_ADD_2:
1207 0 : case BUILT_IN_ATOMIC_FETCH_SUB_2:
1208 0 : case BUILT_IN_ATOMIC_FETCH_AND_2:
1209 0 : case BUILT_IN_ATOMIC_FETCH_NAND_2:
1210 0 : case BUILT_IN_ATOMIC_FETCH_XOR_2:
1211 0 : case BUILT_IN_ATOMIC_FETCH_OR_2:
1212 0 : access_size = 2;
1213 0 : goto do_atomic;
1214 :
1215 0 : case BUILT_IN_ATOMIC_LOAD_4:
1216 0 : is_store = false;
1217 : /* FALLTHRU */
1218 56 : case BUILT_IN_SYNC_FETCH_AND_ADD_4:
1219 56 : case BUILT_IN_SYNC_FETCH_AND_SUB_4:
1220 56 : case BUILT_IN_SYNC_FETCH_AND_OR_4:
1221 56 : case BUILT_IN_SYNC_FETCH_AND_AND_4:
1222 56 : case BUILT_IN_SYNC_FETCH_AND_XOR_4:
1223 56 : case BUILT_IN_SYNC_FETCH_AND_NAND_4:
1224 56 : case BUILT_IN_SYNC_ADD_AND_FETCH_4:
1225 56 : case BUILT_IN_SYNC_SUB_AND_FETCH_4:
1226 56 : case BUILT_IN_SYNC_OR_AND_FETCH_4:
1227 56 : case BUILT_IN_SYNC_AND_AND_FETCH_4:
1228 56 : case BUILT_IN_SYNC_XOR_AND_FETCH_4:
1229 56 : case BUILT_IN_SYNC_NAND_AND_FETCH_4:
1230 56 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4:
1231 56 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4:
1232 56 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
1233 56 : case BUILT_IN_SYNC_LOCK_RELEASE_4:
1234 56 : case BUILT_IN_ATOMIC_EXCHANGE_4:
1235 56 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4:
1236 56 : case BUILT_IN_ATOMIC_STORE_4:
1237 56 : case BUILT_IN_ATOMIC_ADD_FETCH_4:
1238 56 : case BUILT_IN_ATOMIC_SUB_FETCH_4:
1239 56 : case BUILT_IN_ATOMIC_AND_FETCH_4:
1240 56 : case BUILT_IN_ATOMIC_NAND_FETCH_4:
1241 56 : case BUILT_IN_ATOMIC_XOR_FETCH_4:
1242 56 : case BUILT_IN_ATOMIC_OR_FETCH_4:
1243 56 : case BUILT_IN_ATOMIC_FETCH_ADD_4:
1244 56 : case BUILT_IN_ATOMIC_FETCH_SUB_4:
1245 56 : case BUILT_IN_ATOMIC_FETCH_AND_4:
1246 56 : case BUILT_IN_ATOMIC_FETCH_NAND_4:
1247 56 : case BUILT_IN_ATOMIC_FETCH_XOR_4:
1248 56 : case BUILT_IN_ATOMIC_FETCH_OR_4:
1249 56 : access_size = 4;
1250 56 : goto do_atomic;
1251 :
1252 0 : case BUILT_IN_ATOMIC_LOAD_8:
1253 0 : is_store = false;
1254 : /* FALLTHRU */
1255 0 : case BUILT_IN_SYNC_FETCH_AND_ADD_8:
1256 0 : case BUILT_IN_SYNC_FETCH_AND_SUB_8:
1257 0 : case BUILT_IN_SYNC_FETCH_AND_OR_8:
1258 0 : case BUILT_IN_SYNC_FETCH_AND_AND_8:
1259 0 : case BUILT_IN_SYNC_FETCH_AND_XOR_8:
1260 0 : case BUILT_IN_SYNC_FETCH_AND_NAND_8:
1261 0 : case BUILT_IN_SYNC_ADD_AND_FETCH_8:
1262 0 : case BUILT_IN_SYNC_SUB_AND_FETCH_8:
1263 0 : case BUILT_IN_SYNC_OR_AND_FETCH_8:
1264 0 : case BUILT_IN_SYNC_AND_AND_FETCH_8:
1265 0 : case BUILT_IN_SYNC_XOR_AND_FETCH_8:
1266 0 : case BUILT_IN_SYNC_NAND_AND_FETCH_8:
1267 0 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8:
1268 0 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8:
1269 0 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_8:
1270 0 : case BUILT_IN_SYNC_LOCK_RELEASE_8:
1271 0 : case BUILT_IN_ATOMIC_EXCHANGE_8:
1272 0 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8:
1273 0 : case BUILT_IN_ATOMIC_STORE_8:
1274 0 : case BUILT_IN_ATOMIC_ADD_FETCH_8:
1275 0 : case BUILT_IN_ATOMIC_SUB_FETCH_8:
1276 0 : case BUILT_IN_ATOMIC_AND_FETCH_8:
1277 0 : case BUILT_IN_ATOMIC_NAND_FETCH_8:
1278 0 : case BUILT_IN_ATOMIC_XOR_FETCH_8:
1279 0 : case BUILT_IN_ATOMIC_OR_FETCH_8:
1280 0 : case BUILT_IN_ATOMIC_FETCH_ADD_8:
1281 0 : case BUILT_IN_ATOMIC_FETCH_SUB_8:
1282 0 : case BUILT_IN_ATOMIC_FETCH_AND_8:
1283 0 : case BUILT_IN_ATOMIC_FETCH_NAND_8:
1284 0 : case BUILT_IN_ATOMIC_FETCH_XOR_8:
1285 0 : case BUILT_IN_ATOMIC_FETCH_OR_8:
1286 0 : access_size = 8;
1287 0 : goto do_atomic;
1288 :
1289 0 : case BUILT_IN_ATOMIC_LOAD_16:
1290 0 : is_store = false;
1291 : /* FALLTHRU */
1292 : case BUILT_IN_SYNC_FETCH_AND_ADD_16:
1293 : case BUILT_IN_SYNC_FETCH_AND_SUB_16:
1294 : case BUILT_IN_SYNC_FETCH_AND_OR_16:
1295 : case BUILT_IN_SYNC_FETCH_AND_AND_16:
1296 : case BUILT_IN_SYNC_FETCH_AND_XOR_16:
1297 : case BUILT_IN_SYNC_FETCH_AND_NAND_16:
1298 : case BUILT_IN_SYNC_ADD_AND_FETCH_16:
1299 : case BUILT_IN_SYNC_SUB_AND_FETCH_16:
1300 : case BUILT_IN_SYNC_OR_AND_FETCH_16:
1301 : case BUILT_IN_SYNC_AND_AND_FETCH_16:
1302 : case BUILT_IN_SYNC_XOR_AND_FETCH_16:
1303 : case BUILT_IN_SYNC_NAND_AND_FETCH_16:
1304 : case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16:
1305 : case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16:
1306 : case BUILT_IN_SYNC_LOCK_TEST_AND_SET_16:
1307 : case BUILT_IN_SYNC_LOCK_RELEASE_16:
1308 : case BUILT_IN_ATOMIC_EXCHANGE_16:
1309 : case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16:
1310 : case BUILT_IN_ATOMIC_STORE_16:
1311 : case BUILT_IN_ATOMIC_ADD_FETCH_16:
1312 : case BUILT_IN_ATOMIC_SUB_FETCH_16:
1313 : case BUILT_IN_ATOMIC_AND_FETCH_16:
1314 : case BUILT_IN_ATOMIC_NAND_FETCH_16:
1315 : case BUILT_IN_ATOMIC_XOR_FETCH_16:
1316 : case BUILT_IN_ATOMIC_OR_FETCH_16:
1317 : case BUILT_IN_ATOMIC_FETCH_ADD_16:
1318 : case BUILT_IN_ATOMIC_FETCH_SUB_16:
1319 : case BUILT_IN_ATOMIC_FETCH_AND_16:
1320 : case BUILT_IN_ATOMIC_FETCH_NAND_16:
1321 : case BUILT_IN_ATOMIC_FETCH_XOR_16:
1322 : case BUILT_IN_ATOMIC_FETCH_OR_16:
1323 : access_size = 16;
1324 : /* FALLTHRU */
1325 56 : do_atomic:
1326 56 : {
1327 56 : dest = gimple_call_arg (call, 0);
1328 : /* DEST represents the address of a memory location.
1329 : instrument_derefs wants the memory location, so lets
1330 : dereference the address DEST before handing it to
1331 : instrument_derefs. */
1332 112 : tree type = build_nonstandard_integer_type (access_size
1333 56 : * BITS_PER_UNIT, 1);
1334 56 : dest = build2 (MEM_REF, type, dest,
1335 : build_int_cst (build_pointer_type (char_type_node), 0));
1336 56 : break;
1337 : }
1338 :
1339 : default:
1340 : /* The other builtins memory access are not instrumented in this
1341 : function because they either don't have any length parameter,
1342 : or their length parameter is just a limit. */
1343 : break;
1344 : }
1345 :
1346 2686 : if (len != NULL_TREE)
1347 : {
1348 1822 : if (source0 != NULL_TREE)
1349 : {
1350 1434 : src0->start = source0;
1351 1434 : src0->access_size = access_size;
1352 1434 : *src0_len = len;
1353 1434 : *src0_is_store = false;
1354 : }
1355 :
1356 1822 : if (source1 != NULL_TREE)
1357 : {
1358 112 : src1->start = source1;
1359 112 : src1->access_size = access_size;
1360 112 : *src1_len = len;
1361 112 : *src1_is_store = false;
1362 : }
1363 :
1364 1822 : if (dest != NULL_TREE)
1365 : {
1366 1638 : dst->start = dest;
1367 1638 : dst->access_size = access_size;
1368 1638 : *dst_len = len;
1369 1638 : *dst_is_store = true;
1370 : }
1371 :
1372 : got_reference_p = true;
1373 : }
1374 6952 : else if (dest)
1375 : {
1376 56 : dst->start = dest;
1377 56 : dst->access_size = access_size;
1378 56 : *dst_len = NULL_TREE;
1379 56 : *dst_is_store = is_store;
1380 56 : *dest_is_deref = true;
1381 56 : got_reference_p = true;
1382 : }
1383 :
1384 : return got_reference_p;
1385 : }
1386 :
1387 : /* Return true iff a given gimple statement has been instrumented.
1388 : Note that the statement is "defined" by the memory references it
1389 : contains. */
1390 :
1391 : static bool
1392 170118 : has_stmt_been_instrumented_p (gimple *stmt)
1393 : {
1394 170118 : if (gimple_assign_single_p (stmt))
1395 : {
1396 30131 : bool r_is_store;
1397 30131 : asan_mem_ref r;
1398 30131 : asan_mem_ref_init (&r, NULL, 1);
1399 :
1400 30131 : if (get_mem_ref_of_assignment (as_a <gassign *> (stmt), &r,
1401 : &r_is_store))
1402 : {
1403 26625 : if (!has_mem_ref_been_instrumented (&r))
1404 26625 : return false;
1405 1021 : if (r_is_store && gimple_assign_load_p (stmt))
1406 : {
1407 5 : asan_mem_ref src;
1408 5 : asan_mem_ref_init (&src, NULL, 1);
1409 5 : src.start = gimple_assign_rhs1 (stmt);
1410 5 : src.access_size = int_size_in_bytes (TREE_TYPE (src.start));
1411 5 : if (!has_mem_ref_been_instrumented (&src))
1412 : return false;
1413 : }
1414 1016 : return true;
1415 : }
1416 : }
1417 139987 : else if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
1418 : {
1419 4421 : asan_mem_ref src0, src1, dest;
1420 4421 : asan_mem_ref_init (&src0, NULL, 1);
1421 4421 : asan_mem_ref_init (&src1, NULL, 1);
1422 4421 : asan_mem_ref_init (&dest, NULL, 1);
1423 :
1424 4421 : tree src0_len = NULL_TREE, src1_len = NULL_TREE, dest_len = NULL_TREE;
1425 4421 : bool src0_is_store = false, src1_is_store = false,
1426 : dest_is_store = false, dest_is_deref = false, intercepted_p = true;
1427 4421 : if (get_mem_refs_of_builtin_call (as_a <gcall *> (stmt),
1428 : &src0, &src0_len, &src0_is_store,
1429 : &src1, &src1_len, &src1_is_store,
1430 : &dest, &dest_len, &dest_is_store,
1431 : &dest_is_deref, &intercepted_p))
1432 : {
1433 951 : if (src0.start != NULL_TREE
1434 951 : && !has_mem_ref_been_instrumented (&src0, src0_len))
1435 951 : return false;
1436 :
1437 240 : if (src1.start != NULL_TREE
1438 240 : && !has_mem_ref_been_instrumented (&src1, src1_len))
1439 : return false;
1440 :
1441 240 : if (dest.start != NULL_TREE
1442 240 : && !has_mem_ref_been_instrumented (&dest, dest_len))
1443 228 : return false;
1444 :
1445 : return true;
1446 : }
1447 : }
1448 135566 : else if (is_gimple_call (stmt)
1449 18367 : && gimple_store_p (stmt)
1450 135854 : && (gimple_call_builtin_p (stmt)
1451 288 : || gimple_call_internal_p (stmt)
1452 287 : || !aggregate_value_p (TREE_TYPE (gimple_call_lhs (stmt)),
1453 287 : gimple_call_fntype (stmt))))
1454 : {
1455 62 : asan_mem_ref r;
1456 62 : asan_mem_ref_init (&r, NULL, 1);
1457 :
1458 62 : r.start = gimple_call_lhs (stmt);
1459 62 : r.access_size = int_size_in_bytes (TREE_TYPE (r.start));
1460 62 : return has_mem_ref_been_instrumented (&r);
1461 : }
1462 :
1463 : return false;
1464 : }
1465 :
1466 : /* Insert a memory reference into the hash table. */
1467 :
1468 : static void
1469 37498 : update_mem_ref_hash_table (tree ref, HOST_WIDE_INT access_size)
1470 : {
1471 37498 : hash_table<asan_mem_ref_hasher> *ht = get_mem_ref_hash_table ();
1472 :
1473 37498 : asan_mem_ref r;
1474 37498 : asan_mem_ref_init (&r, ref, access_size);
1475 :
1476 37498 : asan_mem_ref **slot = ht->find_slot (&r, INSERT);
1477 37498 : if (*slot == NULL || (*slot)->access_size < access_size)
1478 37486 : *slot = asan_mem_ref_new (ref, access_size);
1479 37498 : }
1480 :
1481 : /* Initialize shadow_ptr_types array. */
1482 :
1483 : static void
1484 2481 : asan_init_shadow_ptr_types (void)
1485 : {
1486 2481 : asan_shadow_set = new_alias_set ();
1487 2481 : tree types[3] = { signed_char_type_node, short_integer_type_node,
1488 2481 : integer_type_node };
1489 :
1490 9924 : for (unsigned i = 0; i < 3; i++)
1491 : {
1492 7443 : shadow_ptr_types[i] = build_distinct_type_copy (types[i]);
1493 7443 : TYPE_ALIAS_SET (shadow_ptr_types[i]) = asan_shadow_set;
1494 7443 : shadow_ptr_types[i] = build_pointer_type (shadow_ptr_types[i]);
1495 : }
1496 :
1497 2481 : initialize_sanitizer_builtins ();
1498 2481 : }
1499 :
1500 : /* Create ADDR_EXPR of STRING_CST with the PP pretty printer text. */
1501 :
1502 : static tree
1503 12318 : asan_pp_string (pretty_printer *pp)
1504 : {
1505 12318 : const char *buf = pp_formatted_text (pp);
1506 12318 : size_t len = strlen (buf);
1507 12318 : tree ret = build_string (len + 1, buf);
1508 24636 : TREE_TYPE (ret)
1509 12318 : = build_array_type (TREE_TYPE (shadow_ptr_types[0]),
1510 12318 : build_index_type (size_int (len)));
1511 12318 : TREE_READONLY (ret) = 1;
1512 12318 : TREE_STATIC (ret) = 1;
1513 12318 : return build1 (ADDR_EXPR, shadow_ptr_types[0], ret);
1514 : }
1515 :
1516 : /* Clear shadow memory at SHADOW_MEM, LEN bytes. Can't call a library call here
1517 : though. */
1518 :
1519 : static void
1520 2396 : asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len)
1521 : {
1522 2396 : rtx_insn *insn, *insns, *jump;
1523 2396 : rtx_code_label *top_label;
1524 2396 : rtx end, addr, tmp;
1525 :
1526 2396 : gcc_assert ((len & 3) == 0);
1527 2396 : start_sequence ();
1528 2396 : clear_storage (shadow_mem, GEN_INT (len), BLOCK_OP_NORMAL);
1529 2396 : insns = end_sequence ();
1530 8592 : for (insn = insns; insn; insn = NEXT_INSN (insn))
1531 3813 : if (CALL_P (insn))
1532 : break;
1533 2396 : if (insn == NULL_RTX)
1534 : {
1535 2383 : emit_insn (insns);
1536 2383 : return;
1537 : }
1538 :
1539 13 : top_label = gen_label_rtx ();
1540 13 : addr = copy_to_mode_reg (Pmode, XEXP (shadow_mem, 0));
1541 13 : shadow_mem = adjust_automodify_address (shadow_mem, SImode, addr, 0);
1542 13 : end = force_reg (Pmode, plus_constant (Pmode, addr, len));
1543 13 : emit_label (top_label);
1544 :
1545 13 : emit_move_insn (shadow_mem, const0_rtx);
1546 13 : tmp = expand_simple_binop (Pmode, PLUS, addr, gen_int_mode (4, Pmode), addr,
1547 : true, OPTAB_LIB_WIDEN);
1548 13 : if (tmp != addr)
1549 0 : emit_move_insn (addr, tmp);
1550 13 : emit_cmp_and_jump_insns (addr, end, LT, NULL_RTX, Pmode, true, top_label);
1551 13 : jump = get_last_insn ();
1552 13 : gcc_assert (JUMP_P (jump));
1553 13 : add_reg_br_prob_note (jump,
1554 26 : profile_probability::guessed_always ()
1555 : .apply_scale (80, 100));
1556 : }
1557 :
1558 : void
1559 6345 : asan_function_start (void)
1560 : {
1561 6345 : ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LASANPC", current_function_funcdef_no);
1562 6345 : }
1563 :
1564 : /* Return number of shadow bytes that are occupied by a local variable
1565 : of SIZE bytes. */
1566 :
1567 : static unsigned HOST_WIDE_INT
1568 2096 : shadow_mem_size (unsigned HOST_WIDE_INT size)
1569 : {
1570 : /* It must be possible to align stack variables to granularity
1571 : of shadow memory. */
1572 2096 : gcc_assert (BITS_PER_UNIT
1573 : * ASAN_SHADOW_GRANULARITY <= MAX_SUPPORTED_STACK_ALIGNMENT);
1574 :
1575 2096 : return ROUND_UP (size, ASAN_SHADOW_GRANULARITY) / ASAN_SHADOW_GRANULARITY;
1576 : }
1577 :
1578 : /* Always emit 4 bytes at a time. */
1579 : #define RZ_BUFFER_SIZE 4
1580 :
1581 : /* ASAN redzone buffer container that handles emission of shadow bytes. */
1582 3442 : class asan_redzone_buffer
1583 : {
1584 : public:
1585 : /* Constructor. */
1586 1721 : asan_redzone_buffer (rtx shadow_mem, HOST_WIDE_INT prev_offset):
1587 1721 : m_shadow_mem (shadow_mem), m_prev_offset (prev_offset),
1588 1721 : m_original_offset (prev_offset), m_shadow_bytes (RZ_BUFFER_SIZE)
1589 : {}
1590 :
1591 : /* Emit VALUE shadow byte at a given OFFSET. */
1592 : void emit_redzone_byte (HOST_WIDE_INT offset, unsigned char value);
1593 :
1594 : /* Emit RTX emission of the content of the buffer. */
1595 : void flush_redzone_payload (void);
1596 :
1597 : private:
1598 : /* Flush if the content of the buffer is full
1599 : (equal to RZ_BUFFER_SIZE). */
1600 : void flush_if_full (void);
1601 :
1602 : /* Memory where we last emitted a redzone payload. */
1603 : rtx m_shadow_mem;
1604 :
1605 : /* Relative offset where we last emitted a redzone payload. */
1606 : HOST_WIDE_INT m_prev_offset;
1607 :
1608 : /* Relative original offset. Used for checking only. */
1609 : HOST_WIDE_INT m_original_offset;
1610 :
1611 : public:
1612 : /* Buffer with redzone payload. */
1613 : auto_vec<unsigned char> m_shadow_bytes;
1614 : };
1615 :
1616 : /* Emit VALUE shadow byte at a given OFFSET. */
1617 :
1618 : void
1619 22769 : asan_redzone_buffer::emit_redzone_byte (HOST_WIDE_INT offset,
1620 : unsigned char value)
1621 : {
1622 22769 : gcc_assert ((offset & (ASAN_SHADOW_GRANULARITY - 1)) == 0);
1623 22769 : gcc_assert (offset >= m_prev_offset);
1624 :
1625 22769 : HOST_WIDE_INT off
1626 22769 : = m_prev_offset + ASAN_SHADOW_GRANULARITY * m_shadow_bytes.length ();
1627 22769 : if (off == offset)
1628 : /* Consecutive shadow memory byte. */;
1629 4719 : else if (offset < m_prev_offset + (HOST_WIDE_INT) (ASAN_SHADOW_GRANULARITY
1630 : * RZ_BUFFER_SIZE)
1631 4719 : && !m_shadow_bytes.is_empty ())
1632 : {
1633 : /* Shadow memory byte with a small gap. */
1634 68 : for (; off < offset; off += ASAN_SHADOW_GRANULARITY)
1635 34 : m_shadow_bytes.safe_push (0);
1636 : }
1637 : else
1638 : {
1639 4685 : if (!m_shadow_bytes.is_empty ())
1640 358 : flush_redzone_payload ();
1641 :
1642 : /* Maybe start earlier in order to use aligned store. */
1643 4685 : HOST_WIDE_INT align = (offset - m_prev_offset) % ASAN_RED_ZONE_SIZE;
1644 4685 : if (align)
1645 : {
1646 1284 : offset -= align;
1647 3389 : for (unsigned i = 0; i < align / BITS_PER_UNIT; i++)
1648 2105 : m_shadow_bytes.safe_push (0);
1649 : }
1650 :
1651 : /* Adjust m_prev_offset and m_shadow_mem. */
1652 4685 : HOST_WIDE_INT diff = offset - m_prev_offset;
1653 4685 : m_shadow_mem = adjust_address (m_shadow_mem, VOIDmode,
1654 : diff >> ASAN_SHADOW_SHIFT);
1655 4685 : m_prev_offset = offset;
1656 : }
1657 22769 : m_shadow_bytes.safe_push (value);
1658 22769 : flush_if_full ();
1659 22769 : }
1660 :
1661 : /* Emit RTX emission of the content of the buffer. */
1662 :
1663 : void
1664 6406 : asan_redzone_buffer::flush_redzone_payload (void)
1665 : {
1666 6406 : gcc_assert (WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN);
1667 :
1668 6406 : if (m_shadow_bytes.is_empty ())
1669 6406 : return;
1670 :
1671 : /* Be sure we always emit to an aligned address. */
1672 6406 : gcc_assert (((m_prev_offset - m_original_offset)
1673 : & (ASAN_RED_ZONE_SIZE - 1)) == 0);
1674 :
1675 : /* Fill it to RZ_BUFFER_SIZE bytes with zeros if needed. */
1676 : unsigned l = m_shadow_bytes.length ();
1677 13528 : for (unsigned i = 0; i <= RZ_BUFFER_SIZE - l; i++)
1678 7122 : m_shadow_bytes.safe_push (0);
1679 :
1680 6406 : if (dump_file && (dump_flags & TDF_DETAILS))
1681 0 : fprintf (dump_file,
1682 : "Flushing rzbuffer at offset %" PRId64 " with: ", m_prev_offset);
1683 :
1684 6406 : unsigned HOST_WIDE_INT val = 0;
1685 32030 : for (unsigned i = 0; i < RZ_BUFFER_SIZE; i++)
1686 : {
1687 25624 : unsigned char v
1688 25624 : = m_shadow_bytes[BYTES_BIG_ENDIAN ? RZ_BUFFER_SIZE - i - 1 : i];
1689 25624 : val |= (unsigned HOST_WIDE_INT)v << (BITS_PER_UNIT * i);
1690 25624 : if (dump_file && (dump_flags & TDF_DETAILS))
1691 0 : fprintf (dump_file, "%02x ", v);
1692 : }
1693 :
1694 6406 : if (dump_file && (dump_flags & TDF_DETAILS))
1695 0 : fprintf (dump_file, "\n");
1696 :
1697 6406 : rtx c = gen_int_mode (val, SImode);
1698 6406 : m_shadow_mem = adjust_address (m_shadow_mem, SImode, 0);
1699 6406 : emit_move_insn (m_shadow_mem, c);
1700 6406 : m_shadow_bytes.truncate (0);
1701 : }
1702 :
1703 : /* Flush if the content of the buffer is full
1704 : (equal to RZ_BUFFER_SIZE). */
1705 :
1706 : void
1707 22769 : asan_redzone_buffer::flush_if_full (void)
1708 : {
1709 22769 : if (m_shadow_bytes.length () == RZ_BUFFER_SIZE)
1710 6048 : flush_redzone_payload ();
1711 22769 : }
1712 :
1713 :
1714 : /* HWAddressSanitizer (hwasan) is a probabilistic method for detecting
1715 : out-of-bounds and use-after-free bugs.
1716 : Read more:
1717 : http://code.google.com/p/address-sanitizer/
1718 :
1719 : Similar to AddressSanitizer (asan) it consists of two parts: the
1720 : instrumentation module in this file, and a run-time library.
1721 :
1722 : The instrumentation module adds a run-time check before every memory insn in
1723 : the same manner as asan (see the block comment for AddressSanitizer above).
1724 : Currently, hwasan only adds out-of-line instrumentation, where each check is
1725 : implemented as a function call to the run-time library. Hence a check for a
1726 : load of N bytes from address X would be implemented with a function call to
1727 : __hwasan_loadN(X), and checking a store of N bytes from address X would be
1728 : implemented with a function call to __hwasan_storeN(X).
1729 :
1730 : The main difference between hwasan and asan is in the information stored to
1731 : help this checking. Both sanitizers use a shadow memory area which stores
1732 : data recording the state of main memory at a corresponding address.
1733 :
1734 : For hwasan, each 16 byte granule in main memory has a corresponding 1 byte
1735 : in shadow memory. This shadow address can be calculated with equation:
1736 : (addr >> log_2(HWASAN_TAG_GRANULE_SIZE))
1737 : + __hwasan_shadow_memory_dynamic_address;
1738 : The conversion between real and shadow memory for asan is given in the block
1739 : comment at the top of this file.
1740 : The description of how this shadow memory is laid out for asan is in the
1741 : block comment at the top of this file, here we describe how this shadow
1742 : memory is used for hwasan.
1743 :
1744 : For hwasan, each variable is assigned a byte-sized 'tag'. The extent of
1745 : the shadow memory for that variable is filled with the assigned tag, and
1746 : every pointer referencing that variable has its top byte set to the same
1747 : tag. The run-time library redefines malloc so that every allocation returns
1748 : a tagged pointer and tags the corresponding shadow memory with the same tag.
1749 :
1750 : On each pointer dereference the tag found in the pointer is compared to the
1751 : tag found in the shadow memory corresponding to the accessed memory address.
1752 : If these tags are found to differ then this memory access is judged to be
1753 : invalid and a report is generated.
1754 :
1755 : This method of bug detection is not perfect -- it can not catch every bad
1756 : access -- but catches them probabilistically instead. There is always the
1757 : possibility that an invalid memory access will happen to access memory
1758 : tagged with the same tag as the pointer that this access used.
1759 : The chances of this are approx. 0.4% for any two uncorrelated objects.
1760 :
1761 : Random tag generation can mitigate this problem by decreasing the
1762 : probability that an invalid access will be missed in the same manner over
1763 : multiple runs. i.e. if two objects are tagged the same in one run of the
1764 : binary they are unlikely to be tagged the same in the next run.
1765 : Both heap and stack allocated objects have random tags by default.
1766 :
1767 : [16 byte granule implications]
1768 : Since the shadow memory only has a resolution on real memory of 16 bytes,
1769 : invalid accesses that are within the same 16 byte granule as a valid
1770 : address will not be caught.
1771 :
1772 : There is a "short-granule" feature in the runtime library which does catch
1773 : such accesses, but this feature is not implemented for stack objects (since
1774 : stack objects are allocated and tagged by compiler instrumentation, and
1775 : this feature has not yet been implemented in GCC instrumentation).
1776 :
1777 : Another outcome of this 16 byte resolution is that each tagged object must
1778 : be 16 byte aligned. If two objects were to share any 16 byte granule in
1779 : memory, then they both would have to be given the same tag, and invalid
1780 : accesses to one using a pointer to the other would be undetectable.
1781 :
1782 : [Compiler instrumentation]
1783 : Compiler instrumentation ensures that two adjacent buffers on the stack are
1784 : given different tags, this means an access to one buffer using a pointer
1785 : generated from the other (e.g. through buffer overrun) will have mismatched
1786 : tags and be caught by hwasan.
1787 :
1788 : We don't randomly tag every object on the stack, since that would require
1789 : keeping many registers to record each tag. Instead we randomly generate a
1790 : tag for each function frame, and each new stack object uses a tag offset
1791 : from that frame tag.
1792 : i.e. each object is tagged as RFT + offset, where RFT is the "random frame
1793 : tag" generated for this frame.
1794 : This means that randomisation does not peturb the difference between tags
1795 : on tagged stack objects within a frame, but this is mitigated by the fact
1796 : that objects with the same tag within a frame are very far apart
1797 : (approx. 2^HWASAN_TAG_SIZE objects apart).
1798 :
1799 : As a demonstration, using the same example program as in the asan block
1800 : comment above:
1801 :
1802 : int
1803 : foo ()
1804 : {
1805 : char a[24] = {0};
1806 : int b[2] = {0};
1807 :
1808 : a[5] = 1;
1809 : b[1] = 2;
1810 :
1811 : return a[5] + b[1];
1812 : }
1813 :
1814 : On AArch64 the stack will be ordered as follows for the above function:
1815 :
1816 : Slot 1/ [24 bytes for variable 'a']
1817 : Slot 2/ [8 bytes padding for alignment]
1818 : Slot 3/ [8 bytes for variable 'b']
1819 : Slot 4/ [8 bytes padding for alignment]
1820 :
1821 : (The padding is there to ensure 16 byte alignment as described in the 16
1822 : byte granule implications).
1823 :
1824 : While the shadow memory will be ordered as follows:
1825 :
1826 : - 2 bytes (representing 32 bytes in real memory) tagged with RFT + 1.
1827 : - 1 byte (representing 16 bytes in real memory) tagged with RFT + 2.
1828 :
1829 : And any pointer to "a" will have the tag RFT + 1, and any pointer to "b"
1830 : will have the tag RFT + 2.
1831 :
1832 : [Top Byte Ignore requirements]
1833 : Hwasan requires the ability to store an 8 bit tag in every pointer. There
1834 : is no instrumentation done to remove this tag from pointers before
1835 : dereferencing, which means the hardware must ignore this tag during memory
1836 : accesses.
1837 :
1838 : Architectures where this feature is available should indicate this using
1839 : the TARGET_MEMTAG_CAN_TAG_ADDRESSES hook.
1840 :
1841 : [Stack requires cleanup on unwinding]
1842 : During normal operation of a hwasan sanitized program more space in the
1843 : shadow memory becomes tagged as the stack grows. As the stack shrinks this
1844 : shadow memory space must become untagged. If it is not untagged then when
1845 : the stack grows again (during other function calls later on in the program)
1846 : objects on the stack that are usually not tagged (e.g. parameters passed on
1847 : the stack) can be placed in memory whose shadow space is tagged with
1848 : something else, and accesses can cause false positive reports.
1849 :
1850 : Hence we place untagging code on every epilogue of functions which tag some
1851 : stack objects.
1852 :
1853 : Moreover, the run-time library intercepts longjmp & setjmp to untag when
1854 : the stack is unwound this way.
1855 :
1856 : C++ exceptions are not yet handled, which means this sanitizer can not
1857 : handle C++ code that throws exceptions -- it will give false positives
1858 : after an exception has been thrown. The implementation that the hwasan
1859 : library has for handling these relies on the frame pointer being after any
1860 : local variables. This is not generally the case for GCC. */
1861 :
1862 :
1863 : /* Returns whether we are tagging pointers and checking those tags on memory
1864 : access. */
1865 : bool
1866 30100309 : hwasan_sanitize_p ()
1867 : {
1868 30100309 : return sanitize_flags_p (SANITIZE_HWADDRESS);
1869 : }
1870 :
1871 : /* Are we tagging the stack? */
1872 : bool
1873 28226321 : hwasan_sanitize_stack_p ()
1874 : {
1875 28226321 : return (hwasan_sanitize_p () && param_hwasan_instrument_stack);
1876 : }
1877 :
1878 : /* Are we tagging alloca objects? */
1879 : bool
1880 1516125 : hwasan_sanitize_allocas_p (void)
1881 : {
1882 1516125 : return (hwasan_sanitize_stack_p () && param_hwasan_instrument_allocas);
1883 : }
1884 :
1885 : /* Should we instrument reads? */
1886 : bool
1887 370 : hwasan_instrument_reads (void)
1888 : {
1889 370 : return (hwasan_sanitize_p () && param_hwasan_instrument_reads);
1890 : }
1891 :
1892 : /* Should we instrument writes? */
1893 : bool
1894 212 : hwasan_instrument_writes (void)
1895 : {
1896 212 : return (hwasan_sanitize_p () && param_hwasan_instrument_writes);
1897 : }
1898 :
1899 : /* Should we instrument builtin calls? */
1900 : bool
1901 94 : hwasan_memintrin (void)
1902 : {
1903 94 : return (hwasan_sanitize_p () && param_hwasan_instrument_mem_intrinsics);
1904 : }
1905 :
1906 : /* MEMoryTAGging sanitizer (MEMTAG) uses a hardware based capability known as
1907 : memory tagging to detect memory safety vulnerabilities. Similar to HWASAN,
1908 : it is also a probabilistic method.
1909 :
1910 : MEMTAG relies on the optional extension in armv8.5a known as MTE (Memory
1911 : Tagging Extension). The extension is available in AArch64 only and
1912 : introduces two types of tags:
1913 : - Logical Address Tag - bits 56-59 (TARGET_MEMTAG_TAG_BITSIZE) of the
1914 : virtual address.
1915 : - Allocation Tag - 4 bits for each tag granule (TARGET_MEMTAG_GRANULE_SIZE
1916 : set to 16 bytes), stored separately.
1917 : Load / store instructions raise an exception if tags differ, thereby
1918 : providing a faster way (than HWASAN) to detect memory safety issues.
1919 : Further, new instructions are available in MTE to manipulate (generate,
1920 : update address with) tags. Load / store instructions with SP base register
1921 : and immediate offset do not check tags.
1922 :
1923 : PS: Currently, MEMTAG sanitizer is capable of stack (variable / memory)
1924 : tagging only.
1925 :
1926 : In general, detecting stack-related memory bugs requires the compiler to:
1927 : - ensure that each tag granule is only used by one variable at a time.
1928 : This includes alloca.
1929 : - Tag/Color: put tags into each stack variable pointer.
1930 : - Untag: the function epilogue will retag the memory.
1931 :
1932 : MEMTAG sanitizer is based off the HWASAN sanitizer implementation
1933 : internally. Similar to HWASAN:
1934 : - Assigning an independently random tag to each variable is carried out by
1935 : keeping a tagged base pointer. A tagged base pointer allows addressing
1936 : variables with (addr offset, tag offset).
1937 : */
1938 :
1939 : /* Returns whether we are tagging pointers and checking those tags on memory
1940 : access. */
1941 : bool
1942 3114263 : memtag_sanitize_p ()
1943 : {
1944 3114263 : return sanitize_flags_p (SANITIZE_MEMTAG);
1945 : }
1946 :
1947 : /* Are we tagging the stack? */
1948 : bool
1949 26692579 : memtag_sanitize_stack_p ()
1950 : {
1951 26692579 : return (sanitize_flags_p (SANITIZE_MEMTAG_STACK));
1952 : }
1953 :
1954 : /* Are we tagging alloca objects? */
1955 : bool
1956 404 : memtag_sanitize_allocas_p (void)
1957 : {
1958 404 : return (memtag_sanitize_stack_p () && param_memtag_instrument_allocas);
1959 : }
1960 :
1961 : /* Are we taggin mem intrinsics? */
1962 : bool
1963 24 : memtag_memintrin (void)
1964 : {
1965 24 : return (memtag_sanitize_p () && param_memtag_instrument_mem_intrinsics);
1966 : }
1967 :
1968 : /* Returns whether we are tagging pointers and checking those tags on memory
1969 : access. */
1970 : bool
1971 90719 : hwassist_sanitize_p ()
1972 : {
1973 90719 : return (hwasan_sanitize_p () || memtag_sanitize_p ());
1974 : }
1975 :
1976 : /* Are we tagging stack objects for hwasan or memtag? */
1977 : bool
1978 26696523 : hwassist_sanitize_stack_p ()
1979 : {
1980 26696523 : return (hwasan_sanitize_stack_p () || memtag_sanitize_stack_p ());
1981 : }
1982 :
1983 : /* Insert code to protect stack vars. The prologue sequence should be emitted
1984 : directly, epilogue sequence returned. BASE is the register holding the
1985 : stack base, against which OFFSETS array offsets are relative to, OFFSETS
1986 : array contains pairs of offsets in reverse order, always the end offset
1987 : of some gap that needs protection followed by starting offset,
1988 : and DECLS is an array of representative decls for each var partition.
1989 : LENGTH is the length of the OFFSETS array, DECLS array is LENGTH / 2 - 1
1990 : elements long (OFFSETS include gap before the first variable as well
1991 : as gaps after each stack variable). PBASE is, if non-NULL, some pseudo
1992 : register which stack vars DECL_RTLs are based on. Either BASE should be
1993 : assigned to PBASE, when not doing use after return protection, or
1994 : corresponding address based on __asan_stack_malloc* return value. */
1995 :
1996 : rtx_insn *
1997 1721 : asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
1998 : HOST_WIDE_INT *offsets, tree *decls, int length)
1999 : {
2000 1721 : rtx shadow_base, shadow_mem, ret, mem, orig_base;
2001 1721 : rtx_code_label *lab;
2002 1721 : rtx_insn *insns;
2003 1721 : char buf[32];
2004 1721 : HOST_WIDE_INT base_offset = offsets[length - 1];
2005 1721 : HOST_WIDE_INT base_align_bias = 0, offset, prev_offset;
2006 1721 : HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset;
2007 1721 : HOST_WIDE_INT last_offset, last_size, last_size_aligned;
2008 1721 : int l;
2009 1721 : unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
2010 1721 : tree str_cst, decl, id;
2011 1721 : int use_after_return_class = -1;
2012 :
2013 : /* Don't emit anything when doing error recovery, the assertions
2014 : might fail e.g. if a function had a frame offset overflow. */
2015 1721 : if (seen_error ())
2016 : return NULL;
2017 :
2018 1721 : if (shadow_ptr_types[0] == NULL_TREE)
2019 0 : asan_init_shadow_ptr_types ();
2020 :
2021 1721 : expanded_location cfun_xloc
2022 1721 : = expand_location (DECL_SOURCE_LOCATION (current_function_decl));
2023 :
2024 : /* First of all, prepare the description string. */
2025 1721 : pretty_printer asan_pp;
2026 :
2027 1721 : pp_decimal_int (&asan_pp, length / 2 - 1);
2028 1721 : pp_space (&asan_pp);
2029 5026 : for (l = length - 2; l; l -= 2)
2030 : {
2031 3305 : tree decl = decls[l / 2 - 1];
2032 3305 : pp_wide_integer (&asan_pp, offsets[l] - base_offset);
2033 3305 : pp_space (&asan_pp);
2034 3305 : pp_wide_integer (&asan_pp, offsets[l - 1] - offsets[l]);
2035 3305 : pp_space (&asan_pp);
2036 :
2037 3305 : expanded_location xloc
2038 3305 : = expand_location (DECL_SOURCE_LOCATION (decl));
2039 3305 : char location[32];
2040 :
2041 3305 : if (xloc.file == cfun_xloc.file)
2042 3081 : sprintf (location, ":%d", xloc.line);
2043 : else
2044 224 : location[0] = '\0';
2045 :
2046 3305 : if (DECL_P (decl) && DECL_NAME (decl))
2047 : {
2048 2757 : unsigned idlen
2049 2757 : = IDENTIFIER_LENGTH (DECL_NAME (decl)) + strlen (location);
2050 2757 : pp_decimal_int (&asan_pp, idlen);
2051 2757 : pp_space (&asan_pp);
2052 2757 : pp_tree_identifier (&asan_pp, DECL_NAME (decl));
2053 2757 : pp_string (&asan_pp, location);
2054 : }
2055 : else
2056 548 : pp_string (&asan_pp, "9 <unknown>");
2057 :
2058 3305 : if (l > 2)
2059 1584 : pp_space (&asan_pp);
2060 : }
2061 1721 : str_cst = asan_pp_string (&asan_pp);
2062 :
2063 3382 : gcc_checking_assert (offsets[0] == (crtl->stack_protect_guard
2064 : ? -ASAN_RED_ZONE_SIZE : 0));
2065 : /* Emit the prologue sequence. */
2066 1721 : if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase
2067 1690 : && param_asan_use_after_return)
2068 : {
2069 1656 : HOST_WIDE_INT adjusted_frame_size = asan_frame_size;
2070 : /* The stack protector guard is allocated at the top of the frame
2071 : and cfgexpand.cc then uses align_frame_offset (ASAN_RED_ZONE_SIZE);
2072 : while in that case we can still use asan_frame_size, we need to take
2073 : that into account when computing base_align_bias. */
2074 1656 : if (alignb > ASAN_RED_ZONE_SIZE && crtl->stack_protect_guard)
2075 28 : adjusted_frame_size += ASAN_RED_ZONE_SIZE;
2076 1656 : use_after_return_class = floor_log2 (asan_frame_size - 1) - 5;
2077 : /* __asan_stack_malloc_N guarantees alignment
2078 : N < 6 ? (64 << N) : 4096 bytes. */
2079 1656 : if (alignb > (use_after_return_class < 6
2080 1656 : ? (64U << use_after_return_class) : 4096U))
2081 : use_after_return_class = -1;
2082 1656 : else if (alignb > ASAN_RED_ZONE_SIZE
2083 54 : && (adjusted_frame_size & (alignb - 1)))
2084 : {
2085 28 : base_align_bias
2086 28 : = ((adjusted_frame_size + alignb - 1)
2087 28 : & ~(alignb - HOST_WIDE_INT_1)) - adjusted_frame_size;
2088 28 : use_after_return_class
2089 28 : = floor_log2 (asan_frame_size + base_align_bias - 1) - 5;
2090 28 : if (use_after_return_class > 10)
2091 : {
2092 65 : base_align_bias = 0;
2093 65 : use_after_return_class = -1;
2094 : }
2095 : }
2096 : }
2097 :
2098 : /* Align base if target is STRICT_ALIGNMENT. */
2099 1721 : if (STRICT_ALIGNMENT)
2100 : {
2101 : const HOST_WIDE_INT align
2102 : = (GET_MODE_ALIGNMENT (SImode) / BITS_PER_UNIT) << ASAN_SHADOW_SHIFT;
2103 : base = expand_binop (Pmode, and_optab, base, gen_int_mode (-align, Pmode),
2104 : NULL_RTX, 1, OPTAB_DIRECT);
2105 : }
2106 :
2107 1721 : if (use_after_return_class == -1 && pbase)
2108 65 : emit_move_insn (pbase, base);
2109 :
2110 1721 : base = expand_binop (Pmode, add_optab, base,
2111 1721 : gen_int_mode (base_offset - base_align_bias, Pmode),
2112 : NULL_RTX, 1, OPTAB_DIRECT);
2113 1721 : orig_base = NULL_RTX;
2114 1721 : if (use_after_return_class != -1)
2115 : {
2116 1656 : if (asan_detect_stack_use_after_return == NULL_TREE)
2117 : {
2118 1209 : id = get_identifier ("__asan_option_detect_stack_use_after_return");
2119 1209 : decl = build_decl (BUILTINS_LOCATION, VAR_DECL, id,
2120 : integer_type_node);
2121 1209 : SET_DECL_ASSEMBLER_NAME (decl, id);
2122 1209 : TREE_ADDRESSABLE (decl) = 1;
2123 1209 : DECL_ARTIFICIAL (decl) = 1;
2124 1209 : DECL_IGNORED_P (decl) = 1;
2125 1209 : DECL_EXTERNAL (decl) = 1;
2126 1209 : TREE_STATIC (decl) = 1;
2127 1209 : TREE_PUBLIC (decl) = 1;
2128 1209 : TREE_USED (decl) = 1;
2129 1209 : asan_detect_stack_use_after_return = decl;
2130 : }
2131 1656 : orig_base = gen_reg_rtx (Pmode);
2132 1656 : emit_move_insn (orig_base, base);
2133 1656 : ret = expand_normal (asan_detect_stack_use_after_return);
2134 1656 : lab = gen_label_rtx ();
2135 1656 : emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
2136 : VOIDmode, 0, lab,
2137 : profile_probability::very_likely ());
2138 1656 : snprintf (buf, sizeof buf, "__asan_stack_malloc_%d",
2139 : use_after_return_class);
2140 1656 : ret = init_one_libfunc (buf);
2141 1656 : ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
2142 : GEN_INT (asan_frame_size
2143 : + base_align_bias),
2144 1656 : TYPE_MODE (pointer_sized_int_node));
2145 : /* __asan_stack_malloc_[n] returns a pointer to fake stack if succeeded
2146 : and NULL otherwise. Check RET value is NULL here and jump over the
2147 : BASE reassignment in this case. Otherwise, reassign BASE to RET. */
2148 1656 : emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX,
2149 : VOIDmode, 0, lab,
2150 : profile_probability:: very_unlikely ());
2151 1656 : ret = convert_memory_address (Pmode, ret);
2152 1656 : emit_move_insn (base, ret);
2153 1656 : emit_label (lab);
2154 1656 : emit_move_insn (pbase, expand_binop (Pmode, add_optab, base,
2155 : gen_int_mode (base_align_bias
2156 1656 : - base_offset, Pmode),
2157 : NULL_RTX, 1, OPTAB_DIRECT));
2158 : }
2159 1721 : mem = gen_rtx_MEM (ptr_mode, base);
2160 1721 : mem = adjust_address (mem, VOIDmode, base_align_bias);
2161 1721 : emit_move_insn (mem, gen_int_mode (ASAN_STACK_FRAME_MAGIC, ptr_mode));
2162 3442 : mem = adjust_address (mem, VOIDmode, GET_MODE_SIZE (ptr_mode));
2163 1721 : emit_move_insn (mem, expand_normal (str_cst));
2164 3442 : mem = adjust_address (mem, VOIDmode, GET_MODE_SIZE (ptr_mode));
2165 1721 : ASM_GENERATE_INTERNAL_LABEL (buf, "LASANPC", current_function_funcdef_no);
2166 1721 : id = get_identifier (buf);
2167 1721 : decl = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
2168 : VAR_DECL, id, char_type_node);
2169 1721 : SET_DECL_ASSEMBLER_NAME (decl, id);
2170 1721 : TREE_ADDRESSABLE (decl) = 1;
2171 1721 : TREE_READONLY (decl) = 1;
2172 1721 : DECL_ARTIFICIAL (decl) = 1;
2173 1721 : DECL_IGNORED_P (decl) = 1;
2174 1721 : TREE_STATIC (decl) = 1;
2175 1721 : TREE_PUBLIC (decl) = 0;
2176 1721 : TREE_USED (decl) = 1;
2177 1721 : DECL_INITIAL (decl) = decl;
2178 1721 : TREE_ASM_WRITTEN (decl) = 1;
2179 1721 : TREE_ASM_WRITTEN (id) = 1;
2180 1721 : DECL_ALIGN_RAW (decl) = DECL_ALIGN_RAW (current_function_decl);
2181 1721 : emit_move_insn (mem, expand_normal (build_fold_addr_expr (decl)));
2182 1721 : shadow_base = expand_binop (Pmode, lshr_optab, base,
2183 1721 : gen_int_shift_amount (Pmode, ASAN_SHADOW_SHIFT),
2184 : NULL_RTX, 1, OPTAB_DIRECT);
2185 1721 : if (asan_dynamic_shadow_offset_p ())
2186 : {
2187 0 : ret = expand_normal (get_asan_shadow_memory_dynamic_address_decl ());
2188 0 : shadow_base
2189 0 : = expand_simple_binop (Pmode, PLUS, shadow_base, ret, NULL_RTX,
2190 : /* unsignedp = */ 1, OPTAB_WIDEN);
2191 0 : shadow_base = plus_constant (Pmode, shadow_base,
2192 0 : (base_align_bias >> ASAN_SHADOW_SHIFT));
2193 : }
2194 : else
2195 : {
2196 1721 : shadow_base = plus_constant (Pmode, shadow_base,
2197 1721 : asan_shadow_offset ()
2198 1721 : + (base_align_bias >> ASAN_SHADOW_SHIFT));
2199 : }
2200 1721 : gcc_assert (asan_shadow_set != -1
2201 : && (ASAN_RED_ZONE_SIZE >> ASAN_SHADOW_SHIFT) == 4);
2202 1721 : shadow_mem = gen_rtx_MEM (SImode, shadow_base);
2203 1721 : set_mem_alias_set (shadow_mem, asan_shadow_set);
2204 1721 : if (STRICT_ALIGNMENT)
2205 : set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
2206 1721 : prev_offset = base_offset;
2207 :
2208 1721 : asan_redzone_buffer rz_buffer (shadow_mem, prev_offset);
2209 8468 : for (l = length; l; l -= 2)
2210 : {
2211 5026 : if (l == 2)
2212 1721 : cur_shadow_byte = ASAN_STACK_MAGIC_RIGHT;
2213 5026 : offset = offsets[l - 1];
2214 :
2215 5026 : bool extra_byte = (offset - base_offset) & (ASAN_SHADOW_GRANULARITY - 1);
2216 : /* If a red-zone is not aligned to ASAN_SHADOW_GRANULARITY then
2217 : the previous stack variable has size % ASAN_SHADOW_GRANULARITY != 0.
2218 : In that case we have to emit one extra byte that will describe
2219 : how many bytes (our of ASAN_SHADOW_GRANULARITY) can be accessed. */
2220 5026 : if (extra_byte)
2221 : {
2222 1498 : HOST_WIDE_INT aoff
2223 1498 : = base_offset + ((offset - base_offset)
2224 1498 : & ~(ASAN_SHADOW_GRANULARITY - HOST_WIDE_INT_1));
2225 1498 : rz_buffer.emit_redzone_byte (aoff, offset - aoff);
2226 1498 : offset = aoff + ASAN_SHADOW_GRANULARITY;
2227 : }
2228 :
2229 : /* Calculate size of red zone payload. */
2230 26297 : while (offset < offsets[l - 2])
2231 : {
2232 21271 : rz_buffer.emit_redzone_byte (offset, cur_shadow_byte);
2233 21271 : offset += ASAN_SHADOW_GRANULARITY;
2234 : }
2235 :
2236 5026 : cur_shadow_byte = ASAN_STACK_MAGIC_MIDDLE;
2237 : }
2238 :
2239 : /* As the automatic variables are aligned to
2240 : ASAN_RED_ZONE_SIZE / ASAN_SHADOW_GRANULARITY, the buffer should be
2241 : flushed here. */
2242 1721 : gcc_assert (rz_buffer.m_shadow_bytes.is_empty ());
2243 :
2244 1721 : do_pending_stack_adjust ();
2245 :
2246 : /* Construct epilogue sequence. */
2247 1721 : start_sequence ();
2248 :
2249 1721 : lab = NULL;
2250 1721 : if (use_after_return_class != -1)
2251 : {
2252 1656 : rtx_code_label *lab2 = gen_label_rtx ();
2253 1656 : char c = (char) ASAN_STACK_MAGIC_USE_AFTER_RET;
2254 1656 : emit_cmp_and_jump_insns (orig_base, base, EQ, NULL_RTX,
2255 : VOIDmode, 0, lab2,
2256 : profile_probability::very_likely ());
2257 1656 : shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
2258 1656 : set_mem_alias_set (shadow_mem, asan_shadow_set);
2259 1656 : mem = gen_rtx_MEM (ptr_mode, base);
2260 1656 : mem = adjust_address (mem, VOIDmode, base_align_bias);
2261 1656 : emit_move_insn (mem, gen_int_mode (ASAN_STACK_RETIRED_MAGIC, ptr_mode));
2262 1656 : unsigned HOST_WIDE_INT sz = asan_frame_size >> ASAN_SHADOW_SHIFT;
2263 1656 : bool asan_stack_free_emitted_p = false;
2264 1656 : if (use_after_return_class < 5
2265 1656 : && can_store_by_pieces (sz, builtin_memset_read_str, &c,
2266 : BITS_PER_UNIT, true))
2267 : /* Emit memset (ShadowBase, kAsanStackAfterReturnMagic, ShadowSize). */
2268 1531 : store_by_pieces (shadow_mem, sz, builtin_memset_read_str, &c,
2269 : BITS_PER_UNIT, true, RETURN_BEGIN);
2270 125 : else if (use_after_return_class >= 5
2271 142 : || !set_storage_via_setmem (shadow_mem,
2272 : GEN_INT (sz),
2273 17 : gen_int_mode (c, QImode),
2274 : BITS_PER_UNIT, BITS_PER_UNIT,
2275 : -1, sz, sz, sz))
2276 : {
2277 108 : snprintf (buf, sizeof buf, "__asan_stack_free_%d",
2278 : use_after_return_class);
2279 108 : ret = init_one_libfunc (buf);
2280 108 : rtx addr = convert_memory_address (ptr_mode, base);
2281 108 : rtx orig_addr = convert_memory_address (ptr_mode, orig_base);
2282 216 : emit_library_call (ret, LCT_NORMAL, ptr_mode, addr, ptr_mode,
2283 : GEN_INT (asan_frame_size + base_align_bias),
2284 108 : TYPE_MODE (pointer_sized_int_node),
2285 : orig_addr, ptr_mode);
2286 108 : asan_stack_free_emitted_p = true;
2287 : }
2288 1656 : if (!asan_stack_free_emitted_p)
2289 : {
2290 : /* Emit **SavedFlagPtr (FakeStack, class_id) = 0. */
2291 1548 : unsigned HOST_WIDE_INT offset = (1 << (use_after_return_class + 6));
2292 1548 : offset -= GET_MODE_SIZE (ptr_mode);
2293 1548 : mem = gen_rtx_MEM (ptr_mode, base);
2294 1548 : mem = adjust_address (mem, ptr_mode, offset);
2295 1548 : rtx addr = gen_reg_rtx (ptr_mode);
2296 1548 : emit_move_insn (addr, mem);
2297 1548 : addr = convert_memory_address (Pmode, addr);
2298 1548 : mem = gen_rtx_MEM (QImode, addr);
2299 1548 : emit_move_insn (mem, const0_rtx);
2300 : }
2301 1656 : lab = gen_label_rtx ();
2302 1656 : emit_jump (lab);
2303 1656 : emit_label (lab2);
2304 : }
2305 :
2306 1721 : shadow_mem = gen_rtx_MEM (BLKmode, shadow_base);
2307 1721 : set_mem_alias_set (shadow_mem, asan_shadow_set);
2308 :
2309 1721 : if (STRICT_ALIGNMENT)
2310 : set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
2311 :
2312 1721 : prev_offset = base_offset;
2313 1721 : last_offset = base_offset;
2314 1721 : last_size = 0;
2315 1721 : last_size_aligned = 0;
2316 8468 : for (l = length; l; l -= 2)
2317 : {
2318 5026 : offset = base_offset + ((offsets[l - 1] - base_offset)
2319 5026 : & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
2320 5026 : if (last_offset + last_size_aligned < offset)
2321 : {
2322 675 : shadow_mem = adjust_address (shadow_mem, VOIDmode,
2323 : (last_offset - prev_offset)
2324 : >> ASAN_SHADOW_SHIFT);
2325 675 : prev_offset = last_offset;
2326 675 : asan_clear_shadow (shadow_mem, last_size_aligned >> ASAN_SHADOW_SHIFT);
2327 675 : last_offset = offset;
2328 675 : last_size = 0;
2329 : }
2330 : else
2331 4351 : last_size = offset - last_offset;
2332 5026 : last_size += base_offset + ((offsets[l - 2] - base_offset)
2333 5026 : & ~(ASAN_MIN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
2334 5026 : - offset;
2335 :
2336 : /* Unpoison shadow memory that corresponds to a variable that is
2337 : is subject of use-after-return sanitization. */
2338 5026 : if (l > 2)
2339 : {
2340 3305 : decl = decls[l / 2 - 2];
2341 3305 : if (asan_handled_variables != NULL
2342 3305 : && asan_handled_variables->contains (decl))
2343 : {
2344 871 : HOST_WIDE_INT size = offsets[l - 3] - offsets[l - 2];
2345 871 : if (dump_file && (dump_flags & TDF_DETAILS))
2346 : {
2347 0 : const char *n = (DECL_NAME (decl)
2348 0 : ? IDENTIFIER_POINTER (DECL_NAME (decl))
2349 0 : : "<unknown>");
2350 0 : fprintf (dump_file, "Unpoisoning shadow stack for variable: "
2351 : "%s (%" PRId64 " B)\n", n, size);
2352 : }
2353 :
2354 871 : last_size += size & ~(ASAN_MIN_RED_ZONE_SIZE - HOST_WIDE_INT_1);
2355 : }
2356 : }
2357 5026 : last_size_aligned
2358 5026 : = ((last_size + (ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
2359 : & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
2360 : }
2361 1721 : if (last_size_aligned)
2362 : {
2363 1721 : shadow_mem = adjust_address (shadow_mem, VOIDmode,
2364 : (last_offset - prev_offset)
2365 : >> ASAN_SHADOW_SHIFT);
2366 1721 : asan_clear_shadow (shadow_mem, last_size_aligned >> ASAN_SHADOW_SHIFT);
2367 : }
2368 :
2369 : /* Clean-up set with instrumented stack variables. */
2370 2108 : delete asan_handled_variables;
2371 1721 : asan_handled_variables = NULL;
2372 1816 : delete asan_used_labels;
2373 1721 : asan_used_labels = NULL;
2374 :
2375 1721 : do_pending_stack_adjust ();
2376 1721 : if (lab)
2377 1656 : emit_label (lab);
2378 :
2379 1721 : insns = end_sequence ();
2380 1721 : return insns;
2381 1721 : }
2382 :
2383 : /* Emit __asan_allocas_unpoison (top, bot) call. The BASE parameter corresponds
2384 : to BOT argument, for TOP virtual_stack_dynamic_rtx is used. NEW_SEQUENCE
2385 : indicates whether we're emitting new instructions sequence or not. */
2386 :
2387 : rtx_insn *
2388 178 : asan_emit_allocas_unpoison (rtx top, rtx bot, rtx_insn *before)
2389 : {
2390 178 : if (before)
2391 38 : push_to_sequence (before);
2392 : else
2393 140 : start_sequence ();
2394 178 : rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
2395 178 : top = convert_memory_address (ptr_mode, top);
2396 178 : bot = convert_memory_address (ptr_mode, bot);
2397 178 : emit_library_call (ret, LCT_NORMAL, ptr_mode,
2398 : top, ptr_mode, bot, ptr_mode);
2399 :
2400 178 : do_pending_stack_adjust ();
2401 178 : return end_sequence ();
2402 : }
2403 :
2404 : /* Return true if DECL, a global var, might be overridden and needs
2405 : therefore a local alias. */
2406 :
2407 : static bool
2408 4158 : asan_needs_local_alias (tree decl)
2409 : {
2410 4158 : return DECL_WEAK (decl) || !targetm.binds_local_p (decl);
2411 : }
2412 :
2413 : /* Return true if DECL, a global var, is an artificial ODR indicator symbol
2414 : therefore doesn't need protection. */
2415 :
2416 : static bool
2417 8659 : is_odr_indicator (tree decl)
2418 : {
2419 8659 : return (DECL_ARTIFICIAL (decl)
2420 8659 : && lookup_attribute ("asan odr indicator", DECL_ATTRIBUTES (decl)));
2421 : }
2422 :
2423 : /* Return true if DECL is a VAR_DECL that should be protected
2424 : by Address Sanitizer, by appending a red zone with protected
2425 : shadow memory after it and aligning it to at least
2426 : ASAN_RED_ZONE_SIZE bytes. */
2427 :
2428 : bool
2429 22850 : asan_protect_global (tree decl, bool ignore_decl_rtl_set_p)
2430 : {
2431 22850 : if (!param_asan_globals)
2432 : return false;
2433 :
2434 22687 : rtx rtl, symbol;
2435 :
2436 22687 : if (TREE_CODE (decl) == STRING_CST)
2437 : {
2438 : /* Instrument all STRING_CSTs except those created
2439 : by asan_pp_string here. */
2440 13577 : if (shadow_ptr_types[0] != NULL_TREE
2441 13543 : && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2442 27120 : && TREE_TYPE (TREE_TYPE (decl)) == TREE_TYPE (shadow_ptr_types[0]))
2443 : return false;
2444 6822 : return true;
2445 : }
2446 9110 : if (!VAR_P (decl)
2447 : /* TLS vars aren't statically protectable. */
2448 9110 : || DECL_THREAD_LOCAL_P (decl)
2449 : /* Externs will be protected elsewhere. */
2450 9104 : || DECL_EXTERNAL (decl)
2451 : /* PR sanitizer/81697: For architectures that use section anchors first
2452 : call to asan_protect_global may occur before DECL_RTL (decl) is set.
2453 : We should ignore DECL_RTL_SET_P then, because otherwise the first call
2454 : to asan_protect_global will return FALSE and the following calls on the
2455 : same decl after setting DECL_RTL (decl) will return TRUE and we'll end
2456 : up with inconsistency at runtime. */
2457 9104 : || (!DECL_RTL_SET_P (decl) && !ignore_decl_rtl_set_p)
2458 : /* Comdat vars pose an ABI problem, we can't know if
2459 : the var that is selected by the linker will have
2460 : padding or not. */
2461 9092 : || DECL_ONE_ONLY (decl)
2462 : /* Similarly for common vars. People can use -fno-common.
2463 : Note: Linux kernel is built with -fno-common, so we do instrument
2464 : globals there even if it is C. */
2465 8809 : || (DECL_COMMON (decl) && TREE_PUBLIC (decl))
2466 : /* Don't protect if using user section, often vars placed
2467 : into user section from multiple TUs are then assumed
2468 : to be an array of such vars, putting padding in there
2469 : breaks this assumption. */
2470 8809 : || (DECL_SECTION_NAME (decl) != NULL
2471 270 : && !symtab_node::get (decl)->implicit_section
2472 270 : && !section_sanitized_p (DECL_SECTION_NAME (decl)))
2473 : /* Don't protect variables in non-generic address-space. */
2474 8719 : || !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)))
2475 8717 : || DECL_SIZE (decl) == 0
2476 8717 : || ASAN_RED_ZONE_SIZE * BITS_PER_UNIT > MAX_OFILE_ALIGNMENT
2477 8717 : || TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST
2478 8717 : || !valid_constant_size_p (DECL_SIZE_UNIT (decl))
2479 8717 : || DECL_ALIGN_UNIT (decl) > 2 * ASAN_RED_ZONE_SIZE
2480 8659 : || TREE_TYPE (decl) == ubsan_get_source_location_type ()
2481 17769 : || is_odr_indicator (decl))
2482 : return false;
2483 :
2484 8659 : if (!ignore_decl_rtl_set_p || DECL_RTL_SET_P (decl))
2485 : {
2486 :
2487 8659 : rtl = DECL_RTL (decl);
2488 8659 : if (!MEM_P (rtl) || GET_CODE (XEXP (rtl, 0)) != SYMBOL_REF)
2489 : return false;
2490 8659 : symbol = XEXP (rtl, 0);
2491 :
2492 8659 : if (CONSTANT_POOL_ADDRESS_P (symbol)
2493 8659 : || TREE_CONSTANT_POOL_ADDRESS_P (symbol))
2494 : return false;
2495 : }
2496 :
2497 8659 : if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
2498 0 : return false;
2499 :
2500 : if (!TARGET_SUPPORTS_ALIASES && asan_needs_local_alias (decl))
2501 : return false;
2502 :
2503 : return true;
2504 : }
2505 :
2506 : /* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16,_n}.
2507 : IS_STORE is either 1 (for a store) or 0 (for a load). */
2508 :
2509 : static tree
2510 18927 : report_error_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
2511 : int *nargs)
2512 : {
2513 18927 : gcc_assert (!hwassist_sanitize_p ());
2514 :
2515 18927 : static enum built_in_function report[2][2][6]
2516 : = { { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2,
2517 : BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8,
2518 : BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N },
2519 : { BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2,
2520 : BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8,
2521 : BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } },
2522 : { { BUILT_IN_ASAN_REPORT_LOAD1_NOABORT,
2523 : BUILT_IN_ASAN_REPORT_LOAD2_NOABORT,
2524 : BUILT_IN_ASAN_REPORT_LOAD4_NOABORT,
2525 : BUILT_IN_ASAN_REPORT_LOAD8_NOABORT,
2526 : BUILT_IN_ASAN_REPORT_LOAD16_NOABORT,
2527 : BUILT_IN_ASAN_REPORT_LOAD_N_NOABORT },
2528 : { BUILT_IN_ASAN_REPORT_STORE1_NOABORT,
2529 : BUILT_IN_ASAN_REPORT_STORE2_NOABORT,
2530 : BUILT_IN_ASAN_REPORT_STORE4_NOABORT,
2531 : BUILT_IN_ASAN_REPORT_STORE8_NOABORT,
2532 : BUILT_IN_ASAN_REPORT_STORE16_NOABORT,
2533 : BUILT_IN_ASAN_REPORT_STORE_N_NOABORT } } };
2534 18927 : if (size_in_bytes == -1)
2535 : {
2536 1008 : *nargs = 2;
2537 1008 : return builtin_decl_implicit (report[recover_p][is_store][5]);
2538 : }
2539 17919 : int size_log2 = exact_log2 (size_in_bytes);
2540 17919 : if (size_log2 == -1 || size_log2 >= 5)
2541 : {
2542 28 : *nargs = 2;
2543 28 : return builtin_decl_implicit (report[recover_p][is_store][5]);
2544 : }
2545 17891 : *nargs = 1;
2546 17891 : return builtin_decl_implicit (report[recover_p][is_store][size_log2]);
2547 : }
2548 :
2549 : /* Construct a function tree for __asan_{load,store}{1,2,4,8,16,_n}.
2550 : IS_STORE is either 1 (for a store) or 0 (for a load). */
2551 :
2552 : static tree
2553 103 : check_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
2554 : int *nargs)
2555 : {
2556 103 : static enum built_in_function check[2][2][6]
2557 : = { { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2,
2558 : BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8,
2559 : BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN },
2560 : { BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2,
2561 : BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8,
2562 : BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } },
2563 : { { BUILT_IN_ASAN_LOAD1_NOABORT,
2564 : BUILT_IN_ASAN_LOAD2_NOABORT,
2565 : BUILT_IN_ASAN_LOAD4_NOABORT,
2566 : BUILT_IN_ASAN_LOAD8_NOABORT,
2567 : BUILT_IN_ASAN_LOAD16_NOABORT,
2568 : BUILT_IN_ASAN_LOADN_NOABORT },
2569 : { BUILT_IN_ASAN_STORE1_NOABORT,
2570 : BUILT_IN_ASAN_STORE2_NOABORT,
2571 : BUILT_IN_ASAN_STORE4_NOABORT,
2572 : BUILT_IN_ASAN_STORE8_NOABORT,
2573 : BUILT_IN_ASAN_STORE16_NOABORT,
2574 : BUILT_IN_ASAN_STOREN_NOABORT } } };
2575 103 : if (size_in_bytes == -1)
2576 : {
2577 28 : *nargs = 2;
2578 28 : return builtin_decl_implicit (check[recover_p][is_store][5]);
2579 : }
2580 75 : *nargs = 1;
2581 75 : int size_log2 = exact_log2 (size_in_bytes);
2582 75 : return builtin_decl_implicit (check[recover_p][is_store][size_log2]);
2583 : }
2584 :
2585 : /* Split the current basic block and create a condition statement
2586 : insertion point right before or after the statement pointed to by
2587 : ITER. Return an iterator to the point at which the caller might
2588 : safely insert the condition statement.
2589 :
2590 : THEN_BLOCK must be set to the address of an uninitialized instance
2591 : of basic_block. The function will then set *THEN_BLOCK to the
2592 : 'then block' of the condition statement to be inserted by the
2593 : caller.
2594 :
2595 : If CREATE_THEN_FALLTHRU_EDGE is false, no edge will be created from
2596 : *THEN_BLOCK to *FALLTHROUGH_BLOCK.
2597 :
2598 : Similarly, the function will set *FALLTRHOUGH_BLOCK to the 'else
2599 : block' of the condition statement to be inserted by the caller.
2600 :
2601 : Note that *FALLTHROUGH_BLOCK is a new block that contains the
2602 : statements starting from *ITER, and *THEN_BLOCK is a new empty
2603 : block.
2604 :
2605 : *ITER is adjusted to point to always point to the first statement
2606 : of the basic block * FALLTHROUGH_BLOCK. That statement is the
2607 : same as what ITER was pointing to prior to calling this function,
2608 : if BEFORE_P is true; otherwise, it is its following statement. */
2609 :
2610 : gimple_stmt_iterator
2611 23123 : create_cond_insert_point (gimple_stmt_iterator *iter,
2612 : bool before_p,
2613 : bool then_more_likely_p,
2614 : bool create_then_fallthru_edge,
2615 : basic_block *then_block,
2616 : basic_block *fallthrough_block)
2617 : {
2618 23123 : gimple_stmt_iterator gsi = *iter;
2619 :
2620 23123 : if (!gsi_end_p (gsi) && before_p)
2621 1275 : gsi_prev (&gsi);
2622 :
2623 23123 : basic_block cur_bb = gsi_bb (*iter);
2624 :
2625 23123 : edge e = split_block (cur_bb, gsi_stmt (gsi));
2626 :
2627 : /* Get a hold on the 'condition block', the 'then block' and the
2628 : 'else block'. */
2629 23123 : basic_block cond_bb = e->src;
2630 23123 : basic_block fallthru_bb = e->dest;
2631 23123 : basic_block then_bb = create_empty_bb (cond_bb);
2632 23123 : if (current_loops)
2633 : {
2634 23123 : add_bb_to_loop (then_bb, cond_bb->loop_father);
2635 23123 : loops_state_set (LOOPS_NEED_FIXUP);
2636 : }
2637 :
2638 : /* Set up the newly created 'then block'. */
2639 23123 : e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2640 23123 : profile_probability fallthrough_probability
2641 : = then_more_likely_p
2642 23123 : ? profile_probability::very_unlikely ()
2643 23123 : : profile_probability::very_likely ();
2644 23123 : e->probability = fallthrough_probability.invert ();
2645 23123 : then_bb->count = e->count ();
2646 23123 : if (create_then_fallthru_edge)
2647 4377 : make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
2648 :
2649 : /* Set up the fallthrough basic block. */
2650 23123 : e = find_edge (cond_bb, fallthru_bb);
2651 23123 : e->flags = EDGE_FALSE_VALUE;
2652 23123 : e->probability = fallthrough_probability;
2653 :
2654 : /* Update dominance info for the newly created then_bb; note that
2655 : fallthru_bb's dominance info has already been updated by
2656 : split_bock. */
2657 23123 : if (dom_info_available_p (CDI_DOMINATORS))
2658 21676 : set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
2659 :
2660 23123 : *then_block = then_bb;
2661 23123 : *fallthrough_block = fallthru_bb;
2662 23123 : *iter = gsi_start_bb (fallthru_bb);
2663 :
2664 23123 : return gsi_last_bb (cond_bb);
2665 : }
2666 :
2667 : /* Insert an if condition followed by a 'then block' right before the
2668 : statement pointed to by ITER. The fallthrough block -- which is the
2669 : else block of the condition as well as the destination of the
2670 : outcoming edge of the 'then block' -- starts with the statement
2671 : pointed to by ITER.
2672 :
2673 : COND is the condition of the if.
2674 :
2675 : If THEN_MORE_LIKELY_P is true, the probability of the edge to the
2676 : 'then block' is higher than the probability of the edge to the
2677 : fallthrough block.
2678 :
2679 : Upon completion of the function, *THEN_BB is set to the newly
2680 : inserted 'then block' and similarly, *FALLTHROUGH_BB is set to the
2681 : fallthrough block.
2682 :
2683 : *ITER is adjusted to still point to the same statement it was
2684 : pointing to initially. */
2685 :
2686 : static void
2687 0 : insert_if_then_before_iter (gcond *cond,
2688 : gimple_stmt_iterator *iter,
2689 : bool then_more_likely_p,
2690 : basic_block *then_bb,
2691 : basic_block *fallthrough_bb)
2692 : {
2693 0 : gimple_stmt_iterator cond_insert_point =
2694 0 : create_cond_insert_point (iter,
2695 : /*before_p=*/true,
2696 : then_more_likely_p,
2697 : /*create_then_fallthru_edge=*/true,
2698 : then_bb,
2699 : fallthrough_bb);
2700 0 : gsi_insert_after (&cond_insert_point, cond, GSI_NEW_STMT);
2701 0 : }
2702 :
2703 : /* Build (base_addr >> ASAN_SHADOW_SHIFT) + asan_shadow_offset ().
2704 : If RETURN_ADDRESS is set to true, return memory location instead
2705 : of a value in the shadow memory. */
2706 :
2707 : static tree
2708 21972 : build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
2709 : tree base_addr, tree shadow_ptr_type,
2710 : bool return_address = false)
2711 : {
2712 21972 : tree t, uintptr_type = TREE_TYPE (base_addr);
2713 21972 : tree shadow_type = TREE_TYPE (shadow_ptr_type);
2714 21972 : gimple *g;
2715 :
2716 21972 : t = build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT);
2717 21972 : g = gimple_build_assign (make_ssa_name (uintptr_type), RSHIFT_EXPR,
2718 : base_addr, t);
2719 21972 : gimple_set_location (g, location);
2720 21972 : gsi_insert_after (gsi, g, GSI_NEW_STMT);
2721 :
2722 21972 : if (asan_dynamic_shadow_offset_p ())
2723 0 : t = asan_local_shadow_memory_dynamic_address;
2724 : else
2725 21972 : t = build_int_cst (uintptr_type, asan_shadow_offset ());
2726 21972 : g = gimple_build_assign (make_ssa_name (uintptr_type), PLUS_EXPR,
2727 : gimple_assign_lhs (g), t);
2728 21972 : gimple_set_location (g, location);
2729 21972 : gsi_insert_after (gsi, g, GSI_NEW_STMT);
2730 :
2731 21972 : g = gimple_build_assign (make_ssa_name (shadow_ptr_type), NOP_EXPR,
2732 : gimple_assign_lhs (g));
2733 21972 : gimple_set_location (g, location);
2734 21972 : gsi_insert_after (gsi, g, GSI_NEW_STMT);
2735 :
2736 21972 : if (!return_address)
2737 : {
2738 19876 : t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g),
2739 : build_int_cst (shadow_ptr_type, 0));
2740 19876 : g = gimple_build_assign (make_ssa_name (shadow_type), MEM_REF, t);
2741 19876 : gimple_set_location (g, location);
2742 19876 : gsi_insert_after (gsi, g, GSI_NEW_STMT);
2743 : }
2744 :
2745 21972 : return gimple_assign_lhs (g);
2746 : }
2747 :
2748 : /* BASE can already be an SSA_NAME; in that case, do not create a
2749 : new SSA_NAME for it. */
2750 :
2751 : static tree
2752 18556 : maybe_create_ssa_name (location_t loc, tree base, gimple_stmt_iterator *iter,
2753 : bool before_p)
2754 : {
2755 18556 : STRIP_USELESS_TYPE_CONVERSION (base);
2756 18556 : if (TREE_CODE (base) == SSA_NAME)
2757 : return base;
2758 16469 : gimple *g = gimple_build_assign (make_ssa_name (TREE_TYPE (base)), base);
2759 16469 : gimple_set_location (g, loc);
2760 16469 : if (before_p)
2761 16469 : gsi_safe_insert_before (iter, g);
2762 : else
2763 0 : gsi_insert_after (iter, g, GSI_NEW_STMT);
2764 16469 : return gimple_assign_lhs (g);
2765 : }
2766 :
2767 : /* LEN can already have necessary size and precision;
2768 : in that case, do not create a new variable. */
2769 :
2770 : tree
2771 0 : maybe_cast_to_ptrmode (location_t loc, tree len, gimple_stmt_iterator *iter,
2772 : bool before_p)
2773 : {
2774 0 : if (ptrofftype_p (len))
2775 : return len;
2776 0 : gimple *g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
2777 : NOP_EXPR, len);
2778 0 : gimple_set_location (g, loc);
2779 0 : if (before_p)
2780 0 : gsi_safe_insert_before (iter, g);
2781 : else
2782 0 : gsi_insert_after (iter, g, GSI_NEW_STMT);
2783 0 : return gimple_assign_lhs (g);
2784 : }
2785 :
2786 : /* Instrument the memory access instruction BASE. Insert new
2787 : statements before or after ITER.
2788 :
2789 : Note that the memory access represented by BASE can be either an
2790 : SSA_NAME, or a non-SSA expression. LOCATION is the source code
2791 : location. IS_STORE is TRUE for a store, FALSE for a load.
2792 : BEFORE_P is TRUE for inserting the instrumentation code before
2793 : ITER, FALSE for inserting it after ITER. IS_SCALAR_ACCESS is TRUE
2794 : for a scalar memory access and FALSE for memory region access.
2795 : NON_ZERO_P is TRUE if memory region is guaranteed to have non-zero
2796 : length. ALIGN tells alignment of accessed memory object.
2797 :
2798 : START_INSTRUMENTED and END_INSTRUMENTED are TRUE if start/end of
2799 : memory region have already been instrumented.
2800 :
2801 : If BEFORE_P is TRUE, *ITER is arranged to still point to the
2802 : statement it was pointing to prior to calling this function,
2803 : otherwise, it points to the statement logically following it. */
2804 :
2805 : static void
2806 18556 : build_check_stmt (location_t loc, tree base, tree len,
2807 : HOST_WIDE_INT size_in_bytes, gimple_stmt_iterator *iter,
2808 : bool is_non_zero_len, bool before_p, bool is_store,
2809 : bool is_scalar_access, unsigned int align = 0)
2810 : {
2811 18556 : gimple *g;
2812 :
2813 18556 : gcc_assert (!(size_in_bytes > 0 && !is_non_zero_len));
2814 18556 : gcc_assert (size_in_bytes == -1 || size_in_bytes >= 1);
2815 :
2816 18556 : base = unshare_expr (base);
2817 18556 : base = maybe_create_ssa_name (loc, base, iter, before_p);
2818 :
2819 18556 : if (len)
2820 : {
2821 0 : len = unshare_expr (len);
2822 0 : len = maybe_cast_to_ptrmode (loc, len, iter, before_p);
2823 : }
2824 : else
2825 : {
2826 18556 : gcc_assert (size_in_bytes != -1);
2827 18556 : len = build_int_cst (pointer_sized_int_node, size_in_bytes);
2828 : }
2829 :
2830 18556 : if (size_in_bytes > 1)
2831 : {
2832 15811 : if ((size_in_bytes & (size_in_bytes - 1)) != 0
2833 15497 : || size_in_bytes > 16)
2834 : is_scalar_access = false;
2835 15134 : else if (align && align < size_in_bytes * BITS_PER_UNIT)
2836 : {
2837 : /* On non-strict alignment targets, if
2838 : 16-byte access is just 8-byte aligned,
2839 : this will result in misaligned shadow
2840 : memory 2 byte load, but otherwise can
2841 : be handled using one read. */
2842 282 : if (size_in_bytes != 16
2843 : || STRICT_ALIGNMENT
2844 149 : || align < 8 * BITS_PER_UNIT)
2845 18556 : is_scalar_access = false;
2846 : }
2847 : }
2848 :
2849 18556 : HOST_WIDE_INT flags = 0;
2850 18556 : if (is_store)
2851 9383 : flags |= ASAN_CHECK_STORE;
2852 18556 : if (is_non_zero_len)
2853 18556 : flags |= ASAN_CHECK_NON_ZERO_LEN;
2854 18556 : if (is_scalar_access)
2855 17737 : flags |= ASAN_CHECK_SCALAR_ACCESS;
2856 :
2857 18556 : enum internal_fn fn = hwassist_sanitize_p ()
2858 18556 : ? IFN_HWASAN_CHECK
2859 18180 : : IFN_ASAN_CHECK;
2860 :
2861 18556 : g = gimple_build_call_internal (fn, 4,
2862 18556 : build_int_cst (integer_type_node, flags),
2863 : base, len,
2864 : build_int_cst (integer_type_node,
2865 18556 : align / BITS_PER_UNIT));
2866 18556 : gimple_set_location (g, loc);
2867 18556 : if (before_p)
2868 18556 : gsi_safe_insert_before (iter, g);
2869 : else
2870 : {
2871 0 : gsi_insert_after (iter, g, GSI_NEW_STMT);
2872 0 : gsi_next (iter);
2873 : }
2874 18556 : }
2875 :
2876 : /* If T represents a memory access, add instrumentation code before ITER.
2877 : LOCATION is source code location.
2878 : IS_STORE is either TRUE (for a store) or FALSE (for a load). */
2879 :
2880 : static void
2881 26425 : instrument_derefs (gimple_stmt_iterator *iter, tree t,
2882 : location_t location, bool is_store)
2883 : {
2884 26425 : if (is_store && !(asan_instrument_writes () || hwasan_instrument_writes ()))
2885 7772 : return;
2886 26383 : if (!is_store && !(asan_instrument_reads () || hwasan_instrument_reads ()))
2887 : return;
2888 :
2889 26327 : tree type, base;
2890 26327 : HOST_WIDE_INT size_in_bytes;
2891 26327 : if (location == UNKNOWN_LOCATION)
2892 377 : location = EXPR_LOCATION (t);
2893 :
2894 26327 : type = TREE_TYPE (t);
2895 26327 : switch (TREE_CODE (t))
2896 : {
2897 26135 : case ARRAY_REF:
2898 26135 : case COMPONENT_REF:
2899 26135 : case INDIRECT_REF:
2900 26135 : case MEM_REF:
2901 26135 : case VAR_DECL:
2902 26135 : case BIT_FIELD_REF:
2903 26135 : break;
2904 : /* FALLTHRU */
2905 : default:
2906 : return;
2907 : }
2908 :
2909 26135 : size_in_bytes = int_size_in_bytes (type);
2910 26135 : if (size_in_bytes <= 0)
2911 : return;
2912 :
2913 26135 : poly_int64 bitsize, bitpos;
2914 26135 : tree offset;
2915 26135 : machine_mode mode;
2916 26135 : int unsignedp, reversep, volatilep = 0;
2917 26135 : tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
2918 : &unsignedp, &reversep, &volatilep);
2919 :
2920 26135 : if (TREE_CODE (t) == COMPONENT_REF
2921 26135 : && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
2922 : {
2923 72 : tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
2924 72 : instrument_derefs (iter, build3 (COMPONENT_REF, TREE_TYPE (repr),
2925 72 : TREE_OPERAND (t, 0), repr,
2926 72 : TREE_OPERAND (t, 2)),
2927 : location, is_store);
2928 72 : return;
2929 : }
2930 :
2931 26063 : if (!multiple_p (bitpos, BITS_PER_UNIT)
2932 26063 : || maybe_ne (bitsize, size_in_bytes * BITS_PER_UNIT))
2933 : return;
2934 :
2935 26063 : if (VAR_P (inner) && DECL_HARD_REGISTER (inner))
2936 : return;
2937 :
2938 : /* Accesses to non-generic address-spaces should not be instrumented. */
2939 26057 : if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (inner))))
2940 : return;
2941 :
2942 26047 : poly_int64 decl_size;
2943 26047 : if ((VAR_P (inner)
2944 11086 : || (TREE_CODE (inner) == RESULT_DECL
2945 145 : && !aggregate_value_p (inner, current_function_decl)))
2946 14961 : && offset == NULL_TREE
2947 14371 : && DECL_SIZE (inner)
2948 14371 : && poly_int_tree_p (DECL_SIZE (inner), &decl_size)
2949 52094 : && known_subrange_p (bitpos, bitsize, 0, decl_size))
2950 : {
2951 14352 : if (VAR_P (inner) && DECL_THREAD_LOCAL_P (inner))
2952 : return;
2953 : /* If we're not sanitizing globals and we can tell statically that this
2954 : access is inside a global variable, then there's no point adding
2955 : instrumentation to check the access. N.b. hwasan currently never
2956 : sanitizes globals. */
2957 28528 : if ((hwassist_sanitize_p () || !param_asan_globals)
2958 14430 : && is_global_var (inner))
2959 : return;
2960 14166 : if (!TREE_STATIC (inner))
2961 : {
2962 : /* Automatic vars in the current function will be always
2963 : accessible. */
2964 9285 : if (decl_function_context (inner) == current_function_decl
2965 9285 : && (!asan_sanitize_use_after_scope ()
2966 8493 : || !TREE_ADDRESSABLE (inner)))
2967 : return;
2968 : }
2969 : /* Always instrument external vars, they might be dynamically
2970 : initialized. */
2971 4881 : else if (!DECL_EXTERNAL (inner))
2972 : {
2973 : /* For static vars if they are known not to be dynamically
2974 : initialized, they will be always accessible. */
2975 4872 : varpool_node *vnode = varpool_node::get (inner);
2976 4872 : if (vnode && !vnode->dynamically_initialized)
2977 : return;
2978 : }
2979 : }
2980 :
2981 18653 : if (DECL_P (inner)
2982 7738 : && decl_function_context (inner) == current_function_decl
2983 25697 : && !TREE_ADDRESSABLE (inner))
2984 110 : mark_addressable (inner);
2985 :
2986 18653 : base = build_fold_addr_expr (t);
2987 18653 : if (!has_mem_ref_been_instrumented (base, size_in_bytes))
2988 : {
2989 18556 : unsigned int align = get_object_alignment (t);
2990 18556 : build_check_stmt (location, base, NULL_TREE, size_in_bytes, iter,
2991 : /*is_non_zero_len*/size_in_bytes > 0, /*before_p=*/true,
2992 : is_store, /*is_scalar_access*/true, align);
2993 18556 : update_mem_ref_hash_table (base, size_in_bytes);
2994 18556 : update_mem_ref_hash_table (t, size_in_bytes);
2995 : }
2996 :
2997 : }
2998 :
2999 : /* Insert a memory reference into the hash table if access length
3000 : can be determined in compile time. */
3001 :
3002 : static void
3003 1574 : maybe_update_mem_ref_hash_table (tree base, tree len)
3004 : {
3005 1640 : if (!POINTER_TYPE_P (TREE_TYPE (base))
3006 1640 : || !INTEGRAL_TYPE_P (TREE_TYPE (len)))
3007 : return;
3008 :
3009 1574 : HOST_WIDE_INT size_in_bytes = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
3010 :
3011 386 : if (size_in_bytes != -1)
3012 386 : update_mem_ref_hash_table (base, size_in_bytes);
3013 : }
3014 :
3015 : /* Instrument an access to a contiguous memory region that starts at
3016 : the address pointed to by BASE, over a length of LEN (expressed in
3017 : the sizeof (*BASE) bytes). ITER points to the instruction before
3018 : which the instrumentation instructions must be inserted. LOCATION
3019 : is the source location that the instrumentation instructions must
3020 : have. If IS_STORE is true, then the memory access is a store;
3021 : otherwise, it's a load. */
3022 :
3023 : static void
3024 0 : instrument_mem_region_access (tree base, tree len,
3025 : gimple_stmt_iterator *iter,
3026 : location_t location, bool is_store)
3027 : {
3028 0 : if (!POINTER_TYPE_P (TREE_TYPE (base))
3029 0 : || !INTEGRAL_TYPE_P (TREE_TYPE (len))
3030 0 : || integer_zerop (len))
3031 : return;
3032 :
3033 0 : HOST_WIDE_INT size_in_bytes = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
3034 :
3035 0 : if ((size_in_bytes == -1)
3036 0 : || !has_mem_ref_been_instrumented (base, size_in_bytes))
3037 : {
3038 0 : build_check_stmt (location, base, len, size_in_bytes, iter,
3039 : /*is_non_zero_len*/size_in_bytes > 0, /*before_p*/true,
3040 : is_store, /*is_scalar_access*/false, /*align*/0);
3041 : }
3042 :
3043 0 : maybe_update_mem_ref_hash_table (base, len);
3044 0 : *iter = gsi_for_stmt (gsi_stmt (*iter));
3045 : }
3046 :
3047 : /* Instrument the call to a built-in memory access function that is
3048 : pointed to by the iterator ITER.
3049 :
3050 : Upon completion, return TRUE iff *ITER has been advanced to the
3051 : statement following the one it was originally pointing to. */
3052 :
3053 : static bool
3054 4409 : instrument_builtin_call (gimple_stmt_iterator *iter)
3055 : {
3056 4433 : if (!(asan_memintrin () || hwasan_memintrin ()
3057 24 : || memtag_memintrin ()))
3058 : return false;
3059 :
3060 4385 : bool iter_advanced_p = false;
3061 4385 : gcall *call = as_a <gcall *> (gsi_stmt (*iter));
3062 :
3063 4385 : gcc_checking_assert (gimple_call_builtin_p (call, BUILT_IN_NORMAL));
3064 :
3065 4385 : location_t loc = gimple_location (call);
3066 :
3067 4385 : asan_mem_ref src0, src1, dest;
3068 4385 : asan_mem_ref_init (&src0, NULL, 1);
3069 4385 : asan_mem_ref_init (&src1, NULL, 1);
3070 4385 : asan_mem_ref_init (&dest, NULL, 1);
3071 :
3072 4385 : tree src0_len = NULL_TREE, src1_len = NULL_TREE, dest_len = NULL_TREE;
3073 4385 : bool src0_is_store = false, src1_is_store = false, dest_is_store = false,
3074 4385 : dest_is_deref = false, intercepted_p = true;
3075 :
3076 4385 : if (get_mem_refs_of_builtin_call (call,
3077 : &src0, &src0_len, &src0_is_store,
3078 : &src1, &src1_len, &src1_is_store,
3079 : &dest, &dest_len, &dest_is_store,
3080 : &dest_is_deref, &intercepted_p, iter))
3081 : {
3082 927 : if (dest_is_deref)
3083 : {
3084 28 : instrument_derefs (iter, dest.start, loc, dest_is_store);
3085 28 : gsi_next (iter);
3086 28 : iter_advanced_p = true;
3087 : }
3088 899 : else if (!intercepted_p
3089 0 : && (src0_len || src1_len || dest_len))
3090 : {
3091 0 : if (src0.start != NULL_TREE)
3092 0 : instrument_mem_region_access (src0.start, src0_len,
3093 : iter, loc, /*is_store=*/false);
3094 0 : if (src1.start != NULL_TREE)
3095 0 : instrument_mem_region_access (src1.start, src1_len,
3096 : iter, loc, /*is_store=*/false);
3097 0 : if (dest.start != NULL_TREE)
3098 0 : instrument_mem_region_access (dest.start, dest_len,
3099 : iter, loc, /*is_store=*/true);
3100 :
3101 0 : *iter = gsi_for_stmt (call);
3102 0 : gsi_next (iter);
3103 0 : iter_advanced_p = true;
3104 : }
3105 : else
3106 : {
3107 899 : if (src0.start != NULL_TREE)
3108 711 : maybe_update_mem_ref_hash_table (src0.start, src0_len);
3109 899 : if (src1.start != NULL_TREE)
3110 50 : maybe_update_mem_ref_hash_table (src1.start, src1_len);
3111 899 : if (dest.start != NULL_TREE)
3112 813 : maybe_update_mem_ref_hash_table (dest.start, dest_len);
3113 : }
3114 : }
3115 : return iter_advanced_p;
3116 : }
3117 :
3118 : /* Instrument the assignment statement ITER if it is subject to
3119 : instrumentation. Return TRUE iff instrumentation actually
3120 : happened. In that case, the iterator ITER is advanced to the next
3121 : logical expression following the one initially pointed to by ITER,
3122 : and the relevant memory reference that which access has been
3123 : instrumented is added to the memory references hash table. */
3124 :
3125 : static bool
3126 28150 : maybe_instrument_assignment (gimple_stmt_iterator *iter)
3127 : {
3128 28150 : gimple *s = gsi_stmt (*iter);
3129 :
3130 28150 : gcc_assert (gimple_assign_single_p (s));
3131 :
3132 28150 : tree ref_expr = NULL_TREE;
3133 28150 : bool is_store, is_instrumented = false;
3134 :
3135 28150 : if (gimple_store_p (s))
3136 : {
3137 12594 : ref_expr = gimple_assign_lhs (s);
3138 12594 : is_store = true;
3139 12594 : instrument_derefs (iter, ref_expr,
3140 : gimple_location (s),
3141 : is_store);
3142 12594 : is_instrumented = true;
3143 : }
3144 :
3145 28150 : if (gimple_assign_load_p (s))
3146 : {
3147 13570 : ref_expr = gimple_assign_rhs1 (s);
3148 13570 : is_store = false;
3149 13570 : instrument_derefs (iter, ref_expr,
3150 : gimple_location (s),
3151 : is_store);
3152 13570 : is_instrumented = true;
3153 : }
3154 :
3155 28150 : if (is_instrumented)
3156 25609 : gsi_next (iter);
3157 :
3158 28150 : return is_instrumented;
3159 : }
3160 :
3161 : /* Instrument the function call pointed to by the iterator ITER, if it
3162 : is subject to instrumentation. At the moment, the only function
3163 : calls that are instrumented are some built-in functions that access
3164 : memory. Look at instrument_builtin_call to learn more.
3165 :
3166 : Upon completion return TRUE iff *ITER was advanced to the statement
3167 : following the one it was originally pointing to. */
3168 :
3169 : static bool
3170 22776 : maybe_instrument_call (gimple_stmt_iterator *iter)
3171 : {
3172 22776 : gimple *stmt = gsi_stmt (*iter);
3173 22776 : bool is_builtin = gimple_call_builtin_p (stmt, BUILT_IN_NORMAL);
3174 :
3175 22776 : if (is_builtin && instrument_builtin_call (iter))
3176 : return true;
3177 :
3178 22748 : if (gimple_call_noreturn_p (stmt))
3179 : {
3180 1136 : if (is_builtin)
3181 : {
3182 320 : tree callee = gimple_call_fndecl (stmt);
3183 320 : switch (DECL_FUNCTION_CODE (callee))
3184 : {
3185 : case BUILT_IN_UNREACHABLE:
3186 : case BUILT_IN_UNREACHABLE_TRAP:
3187 : case BUILT_IN_TRAP:
3188 : case BUILT_IN_ASAN_REPORT_LOAD1:
3189 : case BUILT_IN_ASAN_REPORT_LOAD2:
3190 : case BUILT_IN_ASAN_REPORT_LOAD4:
3191 : case BUILT_IN_ASAN_REPORT_LOAD8:
3192 : case BUILT_IN_ASAN_REPORT_LOAD16:
3193 : case BUILT_IN_ASAN_REPORT_LOAD_N:
3194 : case BUILT_IN_ASAN_REPORT_STORE1:
3195 : case BUILT_IN_ASAN_REPORT_STORE2:
3196 : case BUILT_IN_ASAN_REPORT_STORE4:
3197 : case BUILT_IN_ASAN_REPORT_STORE8:
3198 : case BUILT_IN_ASAN_REPORT_STORE16:
3199 : case BUILT_IN_ASAN_REPORT_STORE_N:
3200 : /* Don't instrument these. */
3201 : return false;
3202 : default:
3203 : break;
3204 : }
3205 : }
3206 956 : if (gimple_call_internal_p (stmt, IFN_ABNORMAL_DISPATCHER))
3207 : /* Don't instrument this. */
3208 : return false;
3209 : /* If a function does not return, then we must handle clearing up the
3210 : shadow stack accordingly. For ASAN we can simply set the entire stack
3211 : to "valid" for accesses by setting the shadow space to 0 and all
3212 : accesses will pass checks. That means that some bad accesses may be
3213 : missed, but we will not report any false positives.
3214 :
3215 : This is not possible for HWASAN. Since there is no "always valid" tag
3216 : we can not set any space to "always valid". If we were to clear the
3217 : entire shadow stack then code resuming from `longjmp` or a caught
3218 : exception would trigger false positives when correctly accessing
3219 : variables on the stack. Hence we need to handle things like
3220 : `longjmp`, thread exit, and exceptions in a different way. These
3221 : problems must be handled externally to the compiler, e.g. in the
3222 : language runtime. */
3223 871 : if (! hwassist_sanitize_p ())
3224 : {
3225 837 : tree decl = builtin_decl_implicit (BUILT_IN_ASAN_HANDLE_NO_RETURN);
3226 837 : gimple *g = gimple_build_call (decl, 0);
3227 837 : gimple_set_location (g, gimple_location (stmt));
3228 837 : gsi_safe_insert_before (iter, g);
3229 : }
3230 : }
3231 :
3232 22483 : bool instrumented = false;
3233 22483 : if (gimple_store_p (stmt)
3234 22483 : && (gimple_call_builtin_p (stmt)
3235 288 : || gimple_call_internal_p (stmt)
3236 287 : || !aggregate_value_p (TREE_TYPE (gimple_call_lhs (stmt)),
3237 287 : gimple_call_fntype (stmt))))
3238 : {
3239 62 : tree ref_expr = gimple_call_lhs (stmt);
3240 62 : instrument_derefs (iter, ref_expr,
3241 : gimple_location (stmt),
3242 : /*is_store=*/true);
3243 :
3244 62 : instrumented = true;
3245 : }
3246 :
3247 : /* Walk through gimple_call arguments and check them id needed. */
3248 22483 : unsigned args_num = gimple_call_num_args (stmt);
3249 92916 : for (unsigned i = 0; i < args_num; ++i)
3250 : {
3251 47950 : tree arg = gimple_call_arg (stmt, i);
3252 : /* If ARG is not a non-aggregate register variable, compiler in general
3253 : creates temporary for it and pass it as argument to gimple call.
3254 : But in some cases, e.g. when we pass by value a small structure that
3255 : fits to register, compiler can avoid extra overhead by pulling out
3256 : these temporaries. In this case, we should check the argument. */
3257 47950 : if (!is_gimple_reg (arg) && !is_gimple_min_invariant (arg))
3258 : {
3259 99 : instrument_derefs (iter, arg,
3260 : gimple_location (stmt),
3261 : /*is_store=*/false);
3262 99 : instrumented = true;
3263 : }
3264 : }
3265 22483 : if (instrumented)
3266 155 : gsi_next (iter);
3267 : return instrumented;
3268 : }
3269 :
3270 : /* Walk each instruction of all basic block and instrument those that
3271 : represent memory references: loads, stores, or function calls.
3272 : In a given basic block, this function avoids instrumenting memory
3273 : references that have already been instrumented. */
3274 :
3275 : static void
3276 6572 : transform_statements (void)
3277 : {
3278 6572 : basic_block bb, last_bb = NULL;
3279 6572 : gimple_stmt_iterator i;
3280 6572 : int saved_last_basic_block = last_basic_block_for_fn (cfun);
3281 :
3282 38074 : FOR_EACH_BB_FN (bb, cfun)
3283 : {
3284 31502 : basic_block prev_bb = bb;
3285 :
3286 31502 : if (bb->index >= saved_last_basic_block) continue;
3287 :
3288 : /* Flush the mem ref hash table, if current bb doesn't have
3289 : exactly one predecessor, or if that predecessor (skipping
3290 : over asan created basic blocks) isn't the last processed
3291 : basic block. Thus we effectively flush on extended basic
3292 : block boundaries. */
3293 31500 : while (single_pred_p (prev_bb))
3294 : {
3295 25551 : prev_bb = single_pred (prev_bb);
3296 25551 : if (prev_bb->index < saved_last_basic_block)
3297 : break;
3298 : }
3299 31494 : if (prev_bb != last_bb)
3300 21242 : empty_mem_ref_hash_table ();
3301 31494 : last_bb = bb;
3302 :
3303 233106 : for (i = gsi_start_bb (bb); !gsi_end_p (i);)
3304 : {
3305 170118 : gimple *s = gsi_stmt (i);
3306 :
3307 170118 : if (has_stmt_been_instrumented_p (s))
3308 1028 : gsi_next (&i);
3309 169090 : else if (gimple_assign_single_p (s)
3310 29115 : && !gimple_clobber_p (s)
3311 197240 : && maybe_instrument_assignment (&i))
3312 : /* Nothing to do as maybe_instrument_assignment advanced
3313 : the iterator I. */;
3314 143481 : else if (is_gimple_call (s) && maybe_instrument_call (&i))
3315 : /* Nothing to do as maybe_instrument_call
3316 : advanced the iterator I. */;
3317 : else
3318 : {
3319 : /* No instrumentation happened.
3320 :
3321 : If the current instruction is a function call that
3322 : might free something, let's forget about the memory
3323 : references that got instrumented. Otherwise we might
3324 : miss some instrumentation opportunities. Do the same
3325 : for a ASAN_MARK poisoning internal function. */
3326 143298 : if (is_gimple_call (s)
3327 143298 : && (!nonfreeing_call_p (s)
3328 6524 : || asan_mark_p (s, ASAN_MARK_POISON)))
3329 16069 : empty_mem_ref_hash_table ();
3330 :
3331 143298 : gsi_next (&i);
3332 : }
3333 : }
3334 : }
3335 6572 : free_mem_ref_resources ();
3336 6572 : }
3337 :
3338 : /* Build
3339 : __asan_before_dynamic_init (module_name)
3340 : or
3341 : __asan_after_dynamic_init ()
3342 : call. */
3343 :
3344 : tree
3345 42 : asan_dynamic_init_call (bool after_p)
3346 : {
3347 42 : if (shadow_ptr_types[0] == NULL_TREE)
3348 21 : asan_init_shadow_ptr_types ();
3349 :
3350 63 : tree fn = builtin_decl_implicit (after_p
3351 : ? BUILT_IN_ASAN_AFTER_DYNAMIC_INIT
3352 : : BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT);
3353 42 : tree module_name_cst = NULL_TREE;
3354 42 : if (!after_p)
3355 : {
3356 21 : pretty_printer module_name_pp;
3357 21 : pp_string (&module_name_pp, main_input_filename);
3358 :
3359 21 : module_name_cst = asan_pp_string (&module_name_pp);
3360 21 : module_name_cst = fold_convert (const_ptr_type_node,
3361 : module_name_cst);
3362 21 : }
3363 :
3364 42 : return build_call_expr (fn, after_p ? 0 : 1, module_name_cst);
3365 : }
3366 :
3367 : /* Build
3368 : struct __asan_global
3369 : {
3370 : const void *__beg;
3371 : uptr __size;
3372 : uptr __size_with_redzone;
3373 : const void *__name;
3374 : const void *__module_name;
3375 : uptr __has_dynamic_init;
3376 : __asan_global_source_location *__location;
3377 : char *__odr_indicator;
3378 : } type. */
3379 :
3380 : static tree
3381 1092 : asan_global_struct (void)
3382 : {
3383 1092 : static const char *field_names[]
3384 : = { "__beg", "__size", "__size_with_redzone",
3385 : "__name", "__module_name", "__has_dynamic_init", "__location",
3386 : "__odr_indicator" };
3387 1092 : tree fields[ARRAY_SIZE (field_names)], ret;
3388 1092 : unsigned i;
3389 :
3390 1092 : ret = make_node (RECORD_TYPE);
3391 10920 : for (i = 0; i < ARRAY_SIZE (field_names); i++)
3392 : {
3393 8736 : fields[i]
3394 8736 : = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
3395 : get_identifier (field_names[i]),
3396 8736 : (i == 0 || i == 3) ? const_ptr_type_node
3397 : : pointer_sized_int_node);
3398 8736 : DECL_CONTEXT (fields[i]) = ret;
3399 8736 : if (i)
3400 7644 : DECL_CHAIN (fields[i - 1]) = fields[i];
3401 : }
3402 1092 : tree type_decl = build_decl (input_location, TYPE_DECL,
3403 : get_identifier ("__asan_global"), ret);
3404 1092 : DECL_IGNORED_P (type_decl) = 1;
3405 1092 : DECL_ARTIFICIAL (type_decl) = 1;
3406 1092 : TYPE_FIELDS (ret) = fields[0];
3407 1092 : TYPE_NAME (ret) = type_decl;
3408 1092 : TYPE_STUB_DECL (ret) = type_decl;
3409 1092 : TYPE_ARTIFICIAL (ret) = 1;
3410 1092 : layout_type (ret);
3411 1092 : return ret;
3412 : }
3413 :
3414 : /* Create and return odr indicator symbol for DECL.
3415 : TYPE is __asan_global struct type as returned by asan_global_struct. */
3416 :
3417 : static tree
3418 1266 : create_odr_indicator (tree decl, tree type)
3419 : {
3420 1266 : char *name;
3421 1266 : tree uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type)));
3422 1266 : tree decl_name
3423 1266 : = (HAS_DECL_ASSEMBLER_NAME_P (decl) ? DECL_ASSEMBLER_NAME (decl)
3424 0 : : DECL_NAME (decl));
3425 : /* DECL_NAME theoretically might be NULL. Bail out with 0 in this case. */
3426 1266 : if (decl_name == NULL_TREE)
3427 0 : return build_int_cst (uptr, 0);
3428 1266 : const char *dname = IDENTIFIER_POINTER (decl_name);
3429 1266 : if (HAS_DECL_ASSEMBLER_NAME_P (decl))
3430 1266 : dname = targetm.strip_name_encoding (dname);
3431 1266 : size_t len = strlen (dname) + sizeof ("__odr_asan_");
3432 1266 : name = XALLOCAVEC (char, len);
3433 1266 : snprintf (name, len, "__odr_asan_%s", dname);
3434 : #ifndef NO_DOT_IN_LABEL
3435 1266 : name[sizeof ("__odr_asan") - 1] = '.';
3436 : #elif !defined(NO_DOLLAR_IN_LABEL)
3437 : name[sizeof ("__odr_asan") - 1] = '$';
3438 : #endif
3439 1266 : tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (name),
3440 : char_type_node);
3441 1266 : TREE_ADDRESSABLE (var) = 1;
3442 1266 : TREE_READONLY (var) = 0;
3443 1266 : TREE_THIS_VOLATILE (var) = 1;
3444 1266 : DECL_ARTIFICIAL (var) = 1;
3445 1266 : DECL_IGNORED_P (var) = 1;
3446 1266 : TREE_STATIC (var) = 1;
3447 1266 : TREE_PUBLIC (var) = 1;
3448 1266 : DECL_VISIBILITY (var) = DECL_VISIBILITY (decl);
3449 1266 : DECL_VISIBILITY_SPECIFIED (var) = DECL_VISIBILITY_SPECIFIED (decl);
3450 :
3451 1266 : TREE_USED (var) = 1;
3452 1266 : tree ctor = build_constructor_va (TREE_TYPE (var), 1, NULL_TREE,
3453 : build_int_cst (unsigned_type_node, 0));
3454 1266 : TREE_CONSTANT (ctor) = 1;
3455 1266 : TREE_STATIC (ctor) = 1;
3456 1266 : DECL_INITIAL (var) = ctor;
3457 1266 : DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("asan odr indicator"),
3458 1266 : NULL, DECL_ATTRIBUTES (var));
3459 1266 : make_decl_rtl (var);
3460 1266 : varpool_node::finalize_decl (var);
3461 1266 : return fold_convert (uptr, build_fold_addr_expr (var));
3462 : }
3463 :
3464 : /* Return true if DECL, a global var, might be overridden and needs
3465 : an additional odr indicator symbol. */
3466 :
3467 : static bool
3468 4158 : asan_needs_odr_indicator_p (tree decl)
3469 : {
3470 : /* Don't emit ODR indicators for kernel because:
3471 : a) Kernel is written in C thus doesn't need ODR indicators.
3472 : b) Some kernel code may have assumptions about symbols containing specific
3473 : patterns in their names. Since ODR indicators contain original names
3474 : of symbols they are emitted for, these assumptions would be broken for
3475 : ODR indicator symbols. */
3476 4158 : return (!(flag_sanitize & SANITIZE_KERNEL_ADDRESS)
3477 4158 : && !DECL_ARTIFICIAL (decl)
3478 1678 : && !DECL_WEAK (decl)
3479 5836 : && TREE_PUBLIC (decl));
3480 : }
3481 :
3482 : /* Append description of a single global DECL into vector V.
3483 : TYPE is __asan_global struct type as returned by asan_global_struct. */
3484 :
3485 : static void
3486 4158 : asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
3487 : {
3488 4158 : tree init, uptr = TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type)));
3489 4158 : unsigned HOST_WIDE_INT size;
3490 4158 : tree str_cst, module_name_cst, refdecl = decl;
3491 4158 : vec<constructor_elt, va_gc> *vinner = NULL;
3492 :
3493 4158 : pretty_printer asan_pp, module_name_pp;
3494 :
3495 4158 : if (DECL_NAME (decl))
3496 4158 : pp_tree_identifier (&asan_pp, DECL_NAME (decl));
3497 : else
3498 0 : pp_string (&asan_pp, "<unknown>");
3499 4158 : str_cst = asan_pp_string (&asan_pp);
3500 :
3501 4158 : if (!in_lto_p)
3502 3734 : pp_string (&module_name_pp, main_input_filename);
3503 : else
3504 : {
3505 424 : const_tree tu = get_ultimate_context ((const_tree)decl);
3506 424 : if (tu != NULL_TREE)
3507 291 : pp_string (&module_name_pp, IDENTIFIER_POINTER (DECL_NAME (tu)));
3508 : else
3509 133 : pp_string (&module_name_pp, aux_base_name);
3510 : }
3511 :
3512 4158 : module_name_cst = asan_pp_string (&module_name_pp);
3513 :
3514 4158 : if (asan_needs_local_alias (decl))
3515 : {
3516 0 : char buf[20];
3517 0 : ASM_GENERATE_INTERNAL_LABEL (buf, "LASAN", vec_safe_length (v) + 1);
3518 0 : refdecl = build_decl (DECL_SOURCE_LOCATION (decl),
3519 0 : VAR_DECL, get_identifier (buf), TREE_TYPE (decl));
3520 0 : TREE_ADDRESSABLE (refdecl) = TREE_ADDRESSABLE (decl);
3521 0 : TREE_READONLY (refdecl) = TREE_READONLY (decl);
3522 0 : TREE_THIS_VOLATILE (refdecl) = TREE_THIS_VOLATILE (decl);
3523 0 : DECL_NOT_GIMPLE_REG_P (refdecl) = DECL_NOT_GIMPLE_REG_P (decl);
3524 0 : DECL_ARTIFICIAL (refdecl) = DECL_ARTIFICIAL (decl);
3525 0 : DECL_IGNORED_P (refdecl) = DECL_IGNORED_P (decl);
3526 0 : TREE_STATIC (refdecl) = 1;
3527 0 : TREE_PUBLIC (refdecl) = 0;
3528 0 : TREE_USED (refdecl) = 1;
3529 0 : assemble_alias (refdecl, DECL_ASSEMBLER_NAME (decl));
3530 : }
3531 :
3532 4158 : tree odr_indicator_ptr
3533 4158 : = (asan_needs_odr_indicator_p (decl) ? create_odr_indicator (decl, type)
3534 2892 : : build_int_cst (uptr, 0));
3535 4158 : CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
3536 : fold_convert (const_ptr_type_node,
3537 : build_fold_addr_expr (refdecl)));
3538 4158 : size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
3539 4158 : CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size));
3540 4158 : size += asan_red_zone_size (size);
3541 4158 : CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, size));
3542 4158 : CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
3543 : fold_convert (const_ptr_type_node, str_cst));
3544 4158 : CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
3545 : fold_convert (const_ptr_type_node, module_name_cst));
3546 4158 : varpool_node *vnode = varpool_node::get (decl);
3547 4158 : int has_dynamic_init = 0;
3548 : /* FIXME: Enable initialization order fiasco detection in LTO mode once
3549 : proper fix for PR 79061 will be applied. */
3550 4158 : if (!in_lto_p)
3551 3734 : has_dynamic_init = vnode ? vnode->dynamically_initialized : 0;
3552 4158 : CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE,
3553 : build_int_cst (uptr, has_dynamic_init));
3554 4158 : tree locptr = NULL_TREE;
3555 4158 : location_t loc = DECL_SOURCE_LOCATION (decl);
3556 4158 : expanded_location xloc = expand_location (loc);
3557 4158 : if (xloc.file != NULL)
3558 : {
3559 2260 : static int lasanloccnt = 0;
3560 2260 : char buf[25];
3561 2260 : ASM_GENERATE_INTERNAL_LABEL (buf, "LASANLOC", ++lasanloccnt);
3562 2260 : tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (buf),
3563 : ubsan_get_source_location_type ());
3564 2260 : TREE_STATIC (var) = 1;
3565 2260 : TREE_PUBLIC (var) = 0;
3566 2260 : DECL_ARTIFICIAL (var) = 1;
3567 2260 : DECL_IGNORED_P (var) = 1;
3568 2260 : pretty_printer filename_pp;
3569 2260 : pp_string (&filename_pp, xloc.file);
3570 2260 : tree str = asan_pp_string (&filename_pp);
3571 2260 : tree ctor = build_constructor_va (TREE_TYPE (var), 3,
3572 : NULL_TREE, str, NULL_TREE,
3573 : build_int_cst (unsigned_type_node,
3574 2260 : xloc.line), NULL_TREE,
3575 : build_int_cst (unsigned_type_node,
3576 2260 : xloc.column));
3577 2260 : TREE_CONSTANT (ctor) = 1;
3578 2260 : TREE_STATIC (ctor) = 1;
3579 2260 : DECL_INITIAL (var) = ctor;
3580 2260 : varpool_node::finalize_decl (var);
3581 2260 : locptr = fold_convert (uptr, build_fold_addr_expr (var));
3582 2260 : }
3583 : else
3584 1898 : locptr = build_int_cst (uptr, 0);
3585 4158 : CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, locptr);
3586 4158 : CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, odr_indicator_ptr);
3587 4158 : init = build_constructor (type, vinner);
3588 4158 : CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
3589 4158 : }
3590 :
3591 : /* Initialize sanitizer.def builtins if the FE hasn't initialized them. */
3592 : void
3593 38222 : initialize_sanitizer_builtins (void)
3594 : {
3595 38222 : tree decl;
3596 :
3597 38222 : if (builtin_decl_implicit_p (BUILT_IN_ASAN_INIT))
3598 38130 : return;
3599 :
3600 92 : tree ptrmode_type = (*lang_hooks.types.type_for_mode) (ptr_mode, 0);
3601 92 : tree BT_FN_VOID = build_function_type_list (void_type_node, NULL_TREE);
3602 92 : tree BT_FN_VOID_PTR
3603 92 : = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
3604 92 : tree BT_FN_VOID_CONST_PTR
3605 92 : = build_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE);
3606 92 : tree BT_FN_VOID_PTR_PTR
3607 92 : = build_function_type_list (void_type_node, ptr_type_node,
3608 : ptr_type_node, NULL_TREE);
3609 92 : tree BT_FN_VOID_PTR_PTR_PTR
3610 92 : = build_function_type_list (void_type_node, ptr_type_node,
3611 : ptr_type_node, ptr_type_node, NULL_TREE);
3612 92 : tree BT_FN_VOID_PTR_PTRMODE
3613 92 : = build_function_type_list (void_type_node, ptr_type_node,
3614 : ptrmode_type, NULL_TREE);
3615 92 : tree BT_FN_VOID_INT
3616 92 : = build_function_type_list (void_type_node, integer_type_node, NULL_TREE);
3617 92 : tree BT_FN_SIZE_CONST_PTR_INT
3618 92 : = build_function_type_list (size_type_node, const_ptr_type_node,
3619 : integer_type_node, NULL_TREE);
3620 :
3621 92 : tree BT_FN_VOID_UINT8_UINT8
3622 92 : = build_function_type_list (void_type_node, unsigned_char_type_node,
3623 : unsigned_char_type_node, NULL_TREE);
3624 92 : tree BT_FN_VOID_UINT16_UINT16
3625 92 : = build_function_type_list (void_type_node, uint16_type_node,
3626 : uint16_type_node, NULL_TREE);
3627 92 : tree BT_FN_VOID_UINT32_UINT32
3628 92 : = build_function_type_list (void_type_node, uint32_type_node,
3629 : uint32_type_node, NULL_TREE);
3630 92 : tree BT_FN_VOID_UINT64_UINT64
3631 92 : = build_function_type_list (void_type_node, uint64_type_node,
3632 : uint64_type_node, NULL_TREE);
3633 92 : tree BT_FN_VOID_FLOAT_FLOAT
3634 92 : = build_function_type_list (void_type_node, float_type_node,
3635 : float_type_node, NULL_TREE);
3636 92 : tree BT_FN_VOID_DOUBLE_DOUBLE
3637 92 : = build_function_type_list (void_type_node, double_type_node,
3638 : double_type_node, NULL_TREE);
3639 92 : tree BT_FN_VOID_UINT64_PTR
3640 92 : = build_function_type_list (void_type_node, uint64_type_node,
3641 : ptr_type_node, NULL_TREE);
3642 :
3643 92 : tree BT_FN_PTR_CONST_PTR_UINT8
3644 92 : = build_function_type_list (ptr_type_node, const_ptr_type_node,
3645 : unsigned_char_type_node, NULL_TREE);
3646 92 : tree BT_FN_VOID_PTR_UINT8_PTRMODE
3647 92 : = build_function_type_list (void_type_node, ptr_type_node,
3648 : unsigned_char_type_node,
3649 : ptrmode_type, NULL_TREE);
3650 :
3651 92 : tree BT_FN_BOOL_VPTR_PTR_IX_INT_INT[5];
3652 92 : tree BT_FN_IX_CONST_VPTR_INT[5];
3653 92 : tree BT_FN_IX_VPTR_IX_INT[5];
3654 92 : tree BT_FN_VOID_VPTR_IX_INT[5];
3655 92 : tree vptr
3656 92 : = build_pointer_type (build_qualified_type (void_type_node,
3657 : TYPE_QUAL_VOLATILE));
3658 92 : tree cvptr
3659 92 : = build_pointer_type (build_qualified_type (void_type_node,
3660 : TYPE_QUAL_VOLATILE
3661 : |TYPE_QUAL_CONST));
3662 92 : tree boolt
3663 92 : = lang_hooks.types.type_for_size (BOOL_TYPE_SIZE, 1);
3664 92 : int i;
3665 644 : for (i = 0; i < 5; i++)
3666 : {
3667 460 : tree ix = build_nonstandard_integer_type (BITS_PER_UNIT * (1 << i), 1);
3668 460 : BT_FN_BOOL_VPTR_PTR_IX_INT_INT[i]
3669 460 : = build_function_type_list (boolt, vptr, ptr_type_node, ix,
3670 : integer_type_node, integer_type_node,
3671 : NULL_TREE);
3672 460 : BT_FN_IX_CONST_VPTR_INT[i]
3673 460 : = build_function_type_list (ix, cvptr, integer_type_node, NULL_TREE);
3674 460 : BT_FN_IX_VPTR_IX_INT[i]
3675 460 : = build_function_type_list (ix, vptr, ix, integer_type_node,
3676 : NULL_TREE);
3677 460 : BT_FN_VOID_VPTR_IX_INT[i]
3678 460 : = build_function_type_list (void_type_node, vptr, ix,
3679 : integer_type_node, NULL_TREE);
3680 : }
3681 : #define BT_FN_BOOL_VPTR_PTR_I1_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[0]
3682 : #define BT_FN_I1_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[0]
3683 : #define BT_FN_I1_VPTR_I1_INT BT_FN_IX_VPTR_IX_INT[0]
3684 : #define BT_FN_VOID_VPTR_I1_INT BT_FN_VOID_VPTR_IX_INT[0]
3685 : #define BT_FN_BOOL_VPTR_PTR_I2_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[1]
3686 : #define BT_FN_I2_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[1]
3687 : #define BT_FN_I2_VPTR_I2_INT BT_FN_IX_VPTR_IX_INT[1]
3688 : #define BT_FN_VOID_VPTR_I2_INT BT_FN_VOID_VPTR_IX_INT[1]
3689 : #define BT_FN_BOOL_VPTR_PTR_I4_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[2]
3690 : #define BT_FN_I4_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[2]
3691 : #define BT_FN_I4_VPTR_I4_INT BT_FN_IX_VPTR_IX_INT[2]
3692 : #define BT_FN_VOID_VPTR_I4_INT BT_FN_VOID_VPTR_IX_INT[2]
3693 : #define BT_FN_BOOL_VPTR_PTR_I8_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[3]
3694 : #define BT_FN_I8_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[3]
3695 : #define BT_FN_I8_VPTR_I8_INT BT_FN_IX_VPTR_IX_INT[3]
3696 : #define BT_FN_VOID_VPTR_I8_INT BT_FN_VOID_VPTR_IX_INT[3]
3697 : #define BT_FN_BOOL_VPTR_PTR_I16_INT_INT BT_FN_BOOL_VPTR_PTR_IX_INT_INT[4]
3698 : #define BT_FN_I16_CONST_VPTR_INT BT_FN_IX_CONST_VPTR_INT[4]
3699 : #define BT_FN_I16_VPTR_I16_INT BT_FN_IX_VPTR_IX_INT[4]
3700 : #define BT_FN_VOID_VPTR_I16_INT BT_FN_VOID_VPTR_IX_INT[4]
3701 : #undef ATTR_NOTHROW_LIST
3702 : #define ATTR_NOTHROW_LIST ECF_NOTHROW
3703 : #undef ATTR_NOTHROW_LEAF_LIST
3704 : #define ATTR_NOTHROW_LEAF_LIST ECF_NOTHROW | ECF_LEAF
3705 : #undef ATTR_TMPURE_NOTHROW_LEAF_LIST
3706 : #define ATTR_TMPURE_NOTHROW_LEAF_LIST ECF_TM_PURE | ATTR_NOTHROW_LEAF_LIST
3707 : #undef ATTR_NORETURN_NOTHROW_LEAF_LIST
3708 : #define ATTR_NORETURN_NOTHROW_LEAF_LIST ECF_NORETURN | ATTR_NOTHROW_LEAF_LIST
3709 : #undef ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST
3710 : #define ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST \
3711 : ECF_CONST | ATTR_NORETURN_NOTHROW_LEAF_LIST
3712 : #undef ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST
3713 : #define ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST \
3714 : ECF_TM_PURE | ATTR_NORETURN_NOTHROW_LEAF_LIST
3715 : #undef ATTR_COLD_NOTHROW_LEAF_LIST
3716 : #define ATTR_COLD_NOTHROW_LEAF_LIST \
3717 : /* ECF_COLD missing */ ATTR_NOTHROW_LEAF_LIST
3718 : #undef ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST
3719 : #define ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST \
3720 : /* ECF_COLD missing */ ATTR_NORETURN_NOTHROW_LEAF_LIST
3721 : #undef ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST
3722 : #define ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST \
3723 : /* ECF_COLD missing */ ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST
3724 : #undef ATTR_PURE_NOTHROW_LEAF_LIST
3725 : #define ATTR_PURE_NOTHROW_LEAF_LIST ECF_PURE | ATTR_NOTHROW_LEAF_LIST
3726 : #undef DEF_BUILTIN_STUB
3727 : #define DEF_BUILTIN_STUB(ENUM, NAME)
3728 : #undef DEF_SANITIZER_BUILTIN_1
3729 : #define DEF_SANITIZER_BUILTIN_1(ENUM, NAME, TYPE, ATTRS) \
3730 : do { \
3731 : decl = add_builtin_function ("__builtin_" NAME, TYPE, ENUM, \
3732 : BUILT_IN_NORMAL, NAME, NULL_TREE); \
3733 : set_call_expr_flags (decl, ATTRS); \
3734 : set_builtin_decl (ENUM, decl, true); \
3735 : } while (0)
3736 : #undef DEF_SANITIZER_BUILTIN
3737 : #define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
3738 : DEF_SANITIZER_BUILTIN_1 (ENUM, NAME, TYPE, ATTRS);
3739 :
3740 : #include "sanitizer.def"
3741 :
3742 : /* -fsanitize=object-size uses __builtin_dynamic_object_size and
3743 : __builtin_object_size, but they might not be available for e.g. Fortran at
3744 : this point. We use DEF_SANITIZER_BUILTIN here only as a convenience
3745 : macro. */
3746 92 : if (flag_sanitize & SANITIZE_OBJECT_SIZE)
3747 : {
3748 21 : if (!builtin_decl_implicit_p (BUILT_IN_OBJECT_SIZE))
3749 15 : DEF_SANITIZER_BUILTIN_1 (BUILT_IN_OBJECT_SIZE, "object_size",
3750 : BT_FN_SIZE_CONST_PTR_INT,
3751 : ATTR_PURE_NOTHROW_LEAF_LIST);
3752 113 : if (!builtin_decl_implicit_p (BUILT_IN_DYNAMIC_OBJECT_SIZE))
3753 15 : DEF_SANITIZER_BUILTIN_1 (BUILT_IN_DYNAMIC_OBJECT_SIZE,
3754 : "dynamic_object_size",
3755 : BT_FN_SIZE_CONST_PTR_INT,
3756 : ATTR_PURE_NOTHROW_LEAF_LIST);
3757 : }
3758 :
3759 : #undef DEF_SANITIZER_BUILTIN_1
3760 : #undef DEF_SANITIZER_BUILTIN
3761 : #undef DEF_BUILTIN_STUB
3762 : }
3763 :
3764 : /* Called via htab_traverse. Count number of emitted
3765 : STRING_CSTs in the constant hash table. */
3766 :
3767 : int
3768 3402 : count_string_csts (constant_descriptor_tree **slot,
3769 : unsigned HOST_WIDE_INT *data)
3770 : {
3771 3402 : struct constant_descriptor_tree *desc = *slot;
3772 3402 : if (TREE_CODE (desc->value) == STRING_CST
3773 3368 : && TREE_ASM_WRITTEN (desc->value)
3774 6770 : && asan_protect_global (desc->value))
3775 1698 : ++*data;
3776 3402 : return 1;
3777 : }
3778 :
3779 : /* Helper structure to pass two parameters to
3780 : add_string_csts. */
3781 :
3782 : struct asan_add_string_csts_data
3783 : {
3784 : tree type;
3785 : vec<constructor_elt, va_gc> *v;
3786 : };
3787 :
3788 : /* Called via hash_table::traverse. Call asan_add_global
3789 : on emitted STRING_CSTs from the constant hash table. */
3790 :
3791 : int
3792 3479 : add_string_csts (constant_descriptor_tree **slot,
3793 : asan_add_string_csts_data *aascd)
3794 : {
3795 3479 : struct constant_descriptor_tree *desc = *slot;
3796 3479 : if (TREE_CODE (desc->value) == STRING_CST
3797 3452 : && TREE_ASM_WRITTEN (desc->value)
3798 6931 : && asan_protect_global (desc->value))
3799 : {
3800 1698 : asan_add_global (SYMBOL_REF_DECL (XEXP (desc->rtl, 0)),
3801 : aascd->type, aascd->v);
3802 : }
3803 3479 : return 1;
3804 : }
3805 :
3806 : /* Needs to be GTY(()), because cgraph_build_static_cdtor may
3807 : invoke ggc_collect. */
3808 : static GTY(()) tree asan_ctor_statements;
3809 :
3810 : /* Module-level instrumentation.
3811 : - Insert __asan_init_vN() into the list of CTORs.
3812 : - TODO: insert redzones around globals.
3813 : */
3814 :
3815 : void
3816 2478 : asan_finish_file (void)
3817 : {
3818 2478 : varpool_node *vnode;
3819 2478 : unsigned HOST_WIDE_INT gcount = 0;
3820 :
3821 2478 : if (shadow_ptr_types[0] == NULL_TREE)
3822 111 : asan_init_shadow_ptr_types ();
3823 : /* Avoid instrumenting code in the asan ctors/dtors.
3824 : We don't need to insert padding after the description strings,
3825 : nor after .LASAN* array. */
3826 2478 : flag_sanitize &= ~SANITIZE_ADDRESS;
3827 :
3828 : /* For user-space we want asan constructors to run first.
3829 : Linux kernel does not support priorities other than default, and the only
3830 : other user of constructors is coverage. So we run with the default
3831 : priority. */
3832 126 : int priority = flag_sanitize & SANITIZE_USER_ADDRESS
3833 2478 : ? MAX_RESERVED_INIT_PRIORITY - 1 : DEFAULT_INIT_PRIORITY;
3834 :
3835 2478 : if (flag_sanitize & SANITIZE_USER_ADDRESS)
3836 : {
3837 2352 : tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT);
3838 2352 : append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
3839 2352 : fn = builtin_decl_implicit (BUILT_IN_ASAN_VERSION_MISMATCH_CHECK);
3840 2352 : append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements);
3841 : }
3842 5157 : FOR_EACH_DEFINED_VARIABLE (vnode)
3843 2679 : if (TREE_ASM_WRITTEN (vnode->decl)
3844 2679 : && asan_protect_global (vnode->decl))
3845 2460 : ++gcount;
3846 2478 : hash_table<tree_descriptor_hasher> *const_desc_htab = constant_pool_htab ();
3847 2478 : const_desc_htab->traverse<unsigned HOST_WIDE_INT *, count_string_csts>
3848 5880 : (&gcount);
3849 2478 : if (gcount)
3850 : {
3851 1092 : tree type = asan_global_struct (), var, ctor;
3852 1092 : tree dtor_statements = NULL_TREE;
3853 1092 : vec<constructor_elt, va_gc> *v;
3854 1092 : char buf[20];
3855 :
3856 1092 : type = build_array_type_nelts (type, gcount);
3857 1092 : ASM_GENERATE_INTERNAL_LABEL (buf, "LASAN", 0);
3858 1092 : var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (buf),
3859 : type);
3860 1092 : TREE_STATIC (var) = 1;
3861 1092 : TREE_PUBLIC (var) = 0;
3862 1092 : DECL_ARTIFICIAL (var) = 1;
3863 1092 : DECL_IGNORED_P (var) = 1;
3864 1092 : vec_alloc (v, gcount);
3865 3689 : FOR_EACH_DEFINED_VARIABLE (vnode)
3866 2597 : if (TREE_ASM_WRITTEN (vnode->decl)
3867 2597 : && asan_protect_global (vnode->decl))
3868 2460 : asan_add_global (vnode->decl, TREE_TYPE (type), v);
3869 1092 : struct asan_add_string_csts_data aascd;
3870 1092 : aascd.type = TREE_TYPE (type);
3871 1092 : aascd.v = v;
3872 1092 : const_desc_htab->traverse<asan_add_string_csts_data *, add_string_csts>
3873 4571 : (&aascd);
3874 1092 : ctor = build_constructor (type, v);
3875 1092 : TREE_CONSTANT (ctor) = 1;
3876 1092 : TREE_STATIC (ctor) = 1;
3877 1092 : DECL_INITIAL (var) = ctor;
3878 1092 : SET_DECL_ALIGN (var, MAX (DECL_ALIGN (var),
3879 : ASAN_SHADOW_GRANULARITY * BITS_PER_UNIT));
3880 :
3881 1092 : varpool_node::finalize_decl (var);
3882 :
3883 1092 : tree fn = builtin_decl_implicit (BUILT_IN_ASAN_REGISTER_GLOBALS);
3884 1092 : tree gcount_tree = build_int_cst (pointer_sized_int_node, gcount);
3885 1092 : append_to_statement_list (build_call_expr (fn, 2,
3886 : build_fold_addr_expr (var),
3887 : gcount_tree),
3888 : &asan_ctor_statements);
3889 :
3890 1092 : fn = builtin_decl_implicit (BUILT_IN_ASAN_UNREGISTER_GLOBALS);
3891 1092 : append_to_statement_list (build_call_expr (fn, 2,
3892 : build_fold_addr_expr (var),
3893 : gcount_tree),
3894 : &dtor_statements);
3895 1092 : cgraph_build_static_cdtor ('D', dtor_statements, priority);
3896 : }
3897 2478 : if (asan_ctor_statements)
3898 2352 : cgraph_build_static_cdtor ('I', asan_ctor_statements, priority);
3899 2478 : flag_sanitize |= SANITIZE_ADDRESS;
3900 2478 : }
3901 :
3902 : /* Poison or unpoison (depending on IS_CLOBBER variable) shadow memory based
3903 : on SHADOW address. Newly added statements will be added to ITER with
3904 : given location LOC. We mark SIZE bytes in shadow memory, where
3905 : LAST_CHUNK_SIZE is greater than zero in situation where we are at the
3906 : end of a variable. */
3907 :
3908 : static void
3909 2193 : asan_store_shadow_bytes (gimple_stmt_iterator *iter, location_t loc,
3910 : tree shadow,
3911 : unsigned HOST_WIDE_INT base_addr_offset,
3912 : bool is_clobber, unsigned size,
3913 : unsigned last_chunk_size)
3914 : {
3915 2193 : tree shadow_ptr_type;
3916 :
3917 2193 : switch (size)
3918 : {
3919 1422 : case 1:
3920 1422 : shadow_ptr_type = shadow_ptr_types[0];
3921 1422 : break;
3922 272 : case 2:
3923 272 : shadow_ptr_type = shadow_ptr_types[1];
3924 272 : break;
3925 499 : case 4:
3926 499 : shadow_ptr_type = shadow_ptr_types[2];
3927 499 : break;
3928 0 : default:
3929 0 : gcc_unreachable ();
3930 : }
3931 :
3932 2193 : unsigned char c = (char) is_clobber ? ASAN_STACK_MAGIC_USE_AFTER_SCOPE : 0;
3933 2193 : unsigned HOST_WIDE_INT val = 0;
3934 2193 : unsigned last_pos = size;
3935 2193 : if (last_chunk_size && !is_clobber)
3936 322 : last_pos = BYTES_BIG_ENDIAN ? 0 : size - 1;
3937 6155 : for (unsigned i = 0; i < size; ++i)
3938 : {
3939 3962 : unsigned char shadow_c = c;
3940 3962 : if (i == last_pos)
3941 322 : shadow_c = last_chunk_size;
3942 3962 : val |= (unsigned HOST_WIDE_INT) shadow_c << (BITS_PER_UNIT * i);
3943 : }
3944 :
3945 : /* Handle last chunk in unpoisoning. */
3946 2193 : tree magic = build_int_cst (TREE_TYPE (shadow_ptr_type), val);
3947 :
3948 2193 : tree dest = build2 (MEM_REF, TREE_TYPE (shadow_ptr_type), shadow,
3949 2193 : build_int_cst (shadow_ptr_type, base_addr_offset));
3950 :
3951 2193 : gimple *g = gimple_build_assign (dest, magic);
3952 2193 : gimple_set_location (g, loc);
3953 2193 : gsi_insert_after (iter, g, GSI_NEW_STMT);
3954 2193 : }
3955 :
3956 : /* Expand the ASAN_MARK builtins. */
3957 :
3958 : bool
3959 2149 : asan_expand_mark_ifn (gimple_stmt_iterator *iter)
3960 : {
3961 2149 : gimple *g = gsi_stmt (*iter);
3962 2149 : location_t loc = gimple_location (g);
3963 2149 : HOST_WIDE_INT flag = tree_to_shwi (gimple_call_arg (g, 0));
3964 2149 : bool is_poison = ((asan_mark_flags)flag) == ASAN_MARK_POISON;
3965 :
3966 2149 : tree base = gimple_call_arg (g, 1);
3967 2149 : gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
3968 2149 : tree decl = TREE_OPERAND (base, 0);
3969 :
3970 : /* For a nested function, we can have: ASAN_MARK (2, &FRAME.2.fp_input, 4) */
3971 2149 : if (TREE_CODE (decl) == COMPONENT_REF
3972 2149 : && DECL_NONLOCAL_FRAME (TREE_OPERAND (decl, 0)))
3973 1 : decl = TREE_OPERAND (decl, 0);
3974 :
3975 2149 : gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
3976 :
3977 2149 : if (hwassist_sanitize_p ())
3978 : {
3979 0 : gcc_assert (param_hwasan_instrument_stack);
3980 0 : gimple_seq stmts = NULL;
3981 : /* Here we swap ASAN_MARK calls for HWASAN_MARK.
3982 : This is because we are using the approach of using ASAN_MARK as a
3983 : synonym until here.
3984 : That approach means we don't yet have to duplicate all the special
3985 : cases for ASAN_MARK and ASAN_POISON with the exact same handling but
3986 : called HWASAN_MARK etc.
3987 :
3988 : N.b. __asan_poison_stack_memory (which implements ASAN_MARK for ASAN)
3989 : rounds the size up to its shadow memory granularity, while
3990 : __hwasan_tag_memory (which implements the same for HWASAN) does not.
3991 : Hence we emit HWASAN_MARK with an aligned size unlike ASAN_MARK. */
3992 0 : tree len = gimple_call_arg (g, 2);
3993 0 : tree new_len = gimple_build_round_up (&stmts, loc, size_type_node, len,
3994 0 : HWASAN_TAG_GRANULE_SIZE);
3995 0 : gimple_build (&stmts, loc, CFN_HWASAN_MARK,
3996 : void_type_node, gimple_call_arg (g, 0),
3997 : base, new_len);
3998 0 : gsi_replace_with_seq (iter, stmts, true);
3999 0 : return false;
4000 : }
4001 :
4002 2149 : if (is_poison)
4003 : {
4004 1412 : if (asan_handled_variables == NULL)
4005 387 : asan_handled_variables = new hash_set<tree> (16);
4006 1412 : asan_handled_variables->add (decl);
4007 : }
4008 2149 : tree len = gimple_call_arg (g, 2);
4009 :
4010 2149 : gcc_assert (poly_int_tree_p (len));
4011 :
4012 2149 : g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
4013 : NOP_EXPR, base);
4014 2149 : gimple_set_location (g, loc);
4015 2149 : gsi_replace (iter, g, false);
4016 2149 : tree base_addr = gimple_assign_lhs (g);
4017 :
4018 : /* Generate direct emission if size_in_bytes is small. */
4019 2149 : unsigned threshold = param_use_after_scope_direct_emission_threshold;
4020 2149 : if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) <= threshold)
4021 : {
4022 2096 : unsigned HOST_WIDE_INT size_in_bytes = tree_to_uhwi (len);
4023 2096 : const unsigned HOST_WIDE_INT shadow_size
4024 2096 : = shadow_mem_size (size_in_bytes);
4025 2096 : const unsigned int shadow_align
4026 2096 : = (get_pointer_alignment (base) / BITS_PER_UNIT) >> ASAN_SHADOW_SHIFT;
4027 :
4028 2096 : tree shadow = build_shadow_mem_access (iter, loc, base_addr,
4029 : shadow_ptr_types[0], true);
4030 :
4031 6385 : for (unsigned HOST_WIDE_INT offset = 0; offset < shadow_size;)
4032 : {
4033 2193 : unsigned size = 1;
4034 2193 : if (shadow_size - offset >= 4
4035 : && (!STRICT_ALIGNMENT || shadow_align >= 4))
4036 : size = 4;
4037 1694 : else if (shadow_size - offset >= 2
4038 : && (!STRICT_ALIGNMENT || shadow_align >= 2))
4039 272 : size = 2;
4040 :
4041 2193 : unsigned HOST_WIDE_INT last_chunk_size = 0;
4042 2193 : unsigned HOST_WIDE_INT s = (offset + size) * ASAN_SHADOW_GRANULARITY;
4043 2193 : if (s > size_in_bytes)
4044 1152 : last_chunk_size = ASAN_SHADOW_GRANULARITY - (s - size_in_bytes);
4045 :
4046 2193 : asan_store_shadow_bytes (iter, loc, shadow, offset, is_poison,
4047 : size, last_chunk_size);
4048 2193 : offset += size;
4049 : }
4050 : }
4051 : else
4052 : {
4053 53 : g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
4054 : NOP_EXPR, len);
4055 53 : gimple_set_location (g, loc);
4056 53 : gsi_safe_insert_before (iter, g);
4057 53 : tree sz_arg = gimple_assign_lhs (g);
4058 :
4059 53 : tree fun
4060 71 : = builtin_decl_implicit (is_poison ? BUILT_IN_ASAN_POISON_STACK_MEMORY
4061 : : BUILT_IN_ASAN_UNPOISON_STACK_MEMORY);
4062 53 : g = gimple_build_call (fun, 2, base_addr, sz_arg);
4063 53 : gimple_set_location (g, loc);
4064 53 : gsi_insert_after (iter, g, GSI_NEW_STMT);
4065 : }
4066 :
4067 : return false;
4068 : }
4069 :
4070 : /* Expand the ASAN_{LOAD,STORE} builtins. */
4071 :
4072 : bool
4073 18971 : asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
4074 : {
4075 18971 : gcc_assert (!hwassist_sanitize_p ());
4076 18971 : gimple *g = gsi_stmt (*iter);
4077 18971 : location_t loc = gimple_location (g);
4078 18971 : bool recover_p;
4079 18971 : if (flag_sanitize & SANITIZE_USER_ADDRESS)
4080 18926 : recover_p = (flag_sanitize_recover & SANITIZE_USER_ADDRESS) != 0;
4081 : else
4082 45 : recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
4083 :
4084 18971 : HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0));
4085 18971 : gcc_assert (flags < ASAN_CHECK_LAST);
4086 18971 : bool is_scalar_access = (flags & ASAN_CHECK_SCALAR_ACCESS) != 0;
4087 18971 : bool is_store = (flags & ASAN_CHECK_STORE) != 0;
4088 18971 : bool is_non_zero_len = (flags & ASAN_CHECK_NON_ZERO_LEN) != 0;
4089 :
4090 18971 : tree base = gimple_call_arg (g, 1);
4091 18971 : tree len = gimple_call_arg (g, 2);
4092 18971 : HOST_WIDE_INT align = tree_to_shwi (gimple_call_arg (g, 3));
4093 :
4094 36906 : HOST_WIDE_INT size_in_bytes
4095 18971 : = is_scalar_access && tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1;
4096 :
4097 18971 : if (use_calls)
4098 : {
4099 : /* Instrument using callbacks. */
4100 103 : gimple *g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
4101 : NOP_EXPR, base);
4102 103 : gimple_set_location (g, loc);
4103 103 : gsi_insert_before (iter, g, GSI_SAME_STMT);
4104 103 : tree base_addr = gimple_assign_lhs (g);
4105 :
4106 103 : int nargs;
4107 103 : tree fun = check_func (is_store, recover_p, size_in_bytes, &nargs);
4108 103 : if (nargs == 1)
4109 75 : g = gimple_build_call (fun, 1, base_addr);
4110 : else
4111 : {
4112 28 : gcc_assert (nargs == 2);
4113 28 : g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
4114 : NOP_EXPR, len);
4115 28 : gimple_set_location (g, loc);
4116 28 : gsi_insert_before (iter, g, GSI_SAME_STMT);
4117 28 : tree sz_arg = gimple_assign_lhs (g);
4118 28 : g = gimple_build_call (fun, nargs, base_addr, sz_arg);
4119 : }
4120 103 : gimple_set_location (g, loc);
4121 103 : gsi_replace (iter, g, false);
4122 103 : return false;
4123 : }
4124 :
4125 18868 : HOST_WIDE_INT real_size_in_bytes = size_in_bytes == -1 ? 1 : size_in_bytes;
4126 :
4127 17860 : tree shadow_ptr_type = shadow_ptr_types[real_size_in_bytes == 16 ? 1 : 0];
4128 18868 : tree shadow_type = TREE_TYPE (shadow_ptr_type);
4129 :
4130 18868 : gimple_stmt_iterator gsi = *iter;
4131 :
4132 18868 : if (!is_non_zero_len)
4133 : {
4134 : /* So, the length of the memory area to asan-protect is
4135 : non-constant. Let's guard the generated instrumentation code
4136 : like:
4137 :
4138 : if (len != 0)
4139 : {
4140 : //asan instrumentation code goes here.
4141 : }
4142 : // fallthrough instructions, starting with *ITER. */
4143 :
4144 0 : g = gimple_build_cond (NE_EXPR,
4145 : len,
4146 0 : build_int_cst (TREE_TYPE (len), 0),
4147 : NULL_TREE, NULL_TREE);
4148 0 : gimple_set_location (g, loc);
4149 :
4150 0 : basic_block then_bb, fallthrough_bb;
4151 0 : insert_if_then_before_iter (as_a <gcond *> (g), iter,
4152 : /*then_more_likely_p=*/true,
4153 : &then_bb, &fallthrough_bb);
4154 : /* Note that fallthrough_bb starts with the statement that was
4155 : pointed to by ITER. */
4156 :
4157 : /* The 'then block' of the 'if (len != 0) condition is where
4158 : we'll generate the asan instrumentation code now. */
4159 0 : gsi = gsi_last_bb (then_bb);
4160 : }
4161 :
4162 : /* Get an iterator on the point where we can add the condition
4163 : statement for the instrumentation. */
4164 18868 : basic_block then_bb, else_bb;
4165 18868 : gsi = create_cond_insert_point (&gsi, /*before_p*/false,
4166 : /*then_more_likely_p=*/false,
4167 : /*create_then_fallthru_edge*/recover_p,
4168 : &then_bb,
4169 : &else_bb);
4170 :
4171 18868 : g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
4172 : NOP_EXPR, base);
4173 18868 : gimple_set_location (g, loc);
4174 18868 : gsi_insert_before (&gsi, g, GSI_NEW_STMT);
4175 18868 : tree base_addr = gimple_assign_lhs (g);
4176 :
4177 18868 : tree t = NULL_TREE;
4178 18868 : if (real_size_in_bytes >= 8)
4179 : {
4180 12244 : tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
4181 : shadow_ptr_type);
4182 12244 : t = shadow;
4183 : }
4184 : else
4185 : {
4186 : /* Slow path for 1, 2 and 4 byte accesses. */
4187 : /* Test (shadow != 0)
4188 : & ((base_addr & 7) + (real_size_in_bytes - 1)) >= shadow). */
4189 6624 : tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
4190 : shadow_ptr_type);
4191 6624 : gimple *shadow_test = build_assign (NE_EXPR, shadow, 0);
4192 6624 : gimple_seq seq = NULL;
4193 6624 : gimple_seq_add_stmt (&seq, shadow_test);
4194 : /* Aligned (>= 8 bytes) can test just
4195 : (real_size_in_bytes - 1 >= shadow), as base_addr & 7 is known
4196 : to be 0. */
4197 6624 : if (align < 8)
4198 : {
4199 4660 : gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
4200 : base_addr, 7));
4201 4660 : gimple_seq_add_stmt (&seq,
4202 9320 : build_type_cast (shadow_type,
4203 : gimple_seq_last (seq)));
4204 4660 : if (real_size_in_bytes > 1)
4205 1862 : gimple_seq_add_stmt (&seq,
4206 1862 : build_assign (PLUS_EXPR,
4207 : gimple_seq_last (seq),
4208 1862 : real_size_in_bytes - 1));
4209 9320 : t = gimple_assign_lhs (gimple_seq_last_stmt (seq));
4210 : }
4211 : else
4212 1964 : t = build_int_cst (shadow_type, real_size_in_bytes - 1);
4213 6624 : gimple_seq_add_stmt (&seq, build_assign (GE_EXPR, t, shadow));
4214 13248 : gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
4215 : gimple_seq_last (seq)));
4216 13248 : t = gimple_assign_lhs (gimple_seq_last (seq));
4217 6624 : gimple_seq_set_location (seq, loc);
4218 6624 : gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
4219 :
4220 : /* For non-constant, misaligned or otherwise weird access sizes,
4221 : check first and last byte. */
4222 6624 : if (size_in_bytes == -1)
4223 : {
4224 1008 : g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
4225 : MINUS_EXPR, len,
4226 : build_int_cst (pointer_sized_int_node, 1));
4227 1008 : gimple_set_location (g, loc);
4228 1008 : gsi_insert_after (&gsi, g, GSI_NEW_STMT);
4229 1008 : tree last = gimple_assign_lhs (g);
4230 1008 : g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
4231 : PLUS_EXPR, base_addr, last);
4232 1008 : gimple_set_location (g, loc);
4233 1008 : gsi_insert_after (&gsi, g, GSI_NEW_STMT);
4234 1008 : tree base_end_addr = gimple_assign_lhs (g);
4235 :
4236 1008 : tree shadow = build_shadow_mem_access (&gsi, loc, base_end_addr,
4237 : shadow_ptr_type);
4238 1008 : gimple *shadow_test = build_assign (NE_EXPR, shadow, 0);
4239 1008 : gimple_seq seq = NULL;
4240 1008 : gimple_seq_add_stmt (&seq, shadow_test);
4241 1008 : gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
4242 : base_end_addr, 7));
4243 2016 : gimple_seq_add_stmt (&seq, build_type_cast (shadow_type,
4244 : gimple_seq_last (seq)));
4245 2016 : gimple_seq_add_stmt (&seq, build_assign (GE_EXPR,
4246 : gimple_seq_last (seq),
4247 : shadow));
4248 2016 : gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test,
4249 : gimple_seq_last (seq)));
4250 2016 : gimple_seq_add_stmt (&seq, build_assign (BIT_IOR_EXPR, t,
4251 : gimple_seq_last (seq)));
4252 2016 : t = gimple_assign_lhs (gimple_seq_last (seq));
4253 1008 : gimple_seq_set_location (seq, loc);
4254 1008 : gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
4255 : }
4256 : }
4257 :
4258 18868 : g = gimple_build_cond (NE_EXPR, t, build_int_cst (TREE_TYPE (t), 0),
4259 : NULL_TREE, NULL_TREE);
4260 18868 : gimple_set_location (g, loc);
4261 18868 : gsi_insert_after (&gsi, g, GSI_NEW_STMT);
4262 :
4263 : /* Generate call to the run-time library (e.g. __asan_report_load8). */
4264 18868 : gsi = gsi_start_bb (then_bb);
4265 18868 : int nargs;
4266 18868 : tree fun = report_error_func (is_store, recover_p, size_in_bytes, &nargs);
4267 18868 : g = gimple_build_call (fun, nargs, base_addr, len);
4268 18868 : gimple_set_location (g, loc);
4269 18868 : gsi_insert_after (&gsi, g, GSI_NEW_STMT);
4270 :
4271 18868 : gsi_remove (iter, true);
4272 18868 : *iter = gsi_start_bb (else_bb);
4273 :
4274 18868 : return true;
4275 : }
4276 :
4277 : /* Create ASAN shadow variable for a VAR_DECL which has been rewritten
4278 : into SSA. Already seen VAR_DECLs are stored in SHADOW_VARS_MAPPING. */
4279 :
4280 : static tree
4281 59 : create_asan_shadow_var (tree var_decl,
4282 : hash_map<tree, tree> &shadow_vars_mapping)
4283 : {
4284 59 : tree *slot = shadow_vars_mapping.get (var_decl);
4285 59 : if (slot == NULL)
4286 : {
4287 59 : tree shadow_var = copy_node (var_decl);
4288 :
4289 59 : copy_body_data id;
4290 59 : memset (&id, 0, sizeof (copy_body_data));
4291 59 : id.src_fn = id.dst_fn = current_function_decl;
4292 59 : copy_decl_for_dup_finish (&id, var_decl, shadow_var);
4293 :
4294 59 : DECL_ARTIFICIAL (shadow_var) = 1;
4295 59 : DECL_IGNORED_P (shadow_var) = 1;
4296 59 : DECL_SEEN_IN_BIND_EXPR_P (shadow_var) = 0;
4297 59 : gimple_add_tmp_var (shadow_var);
4298 :
4299 59 : shadow_vars_mapping.put (var_decl, shadow_var);
4300 59 : return shadow_var;
4301 : }
4302 : else
4303 0 : return *slot;
4304 : }
4305 :
4306 : /* Expand ASAN_POISON ifn. */
4307 :
4308 : bool
4309 64 : asan_expand_poison_ifn (gimple_stmt_iterator *iter,
4310 : bool *need_commit_edge_insert,
4311 : hash_map<tree, tree> &shadow_vars_mapping)
4312 : {
4313 64 : gimple *g = gsi_stmt (*iter);
4314 64 : tree poisoned_var = gimple_call_lhs (g);
4315 64 : if (!poisoned_var || has_zero_uses (poisoned_var))
4316 : {
4317 5 : gsi_remove (iter, true);
4318 5 : return true;
4319 : }
4320 :
4321 59 : if (SSA_NAME_VAR (poisoned_var) == NULL_TREE)
4322 0 : SET_SSA_NAME_VAR_OR_IDENTIFIER (poisoned_var,
4323 : create_tmp_var (TREE_TYPE (poisoned_var)));
4324 :
4325 59 : tree shadow_var = create_asan_shadow_var (SSA_NAME_VAR (poisoned_var),
4326 : shadow_vars_mapping);
4327 :
4328 59 : bool recover_p;
4329 59 : if (flag_sanitize & SANITIZE_USER_ADDRESS)
4330 59 : recover_p = (flag_sanitize_recover & SANITIZE_USER_ADDRESS) != 0;
4331 : else
4332 0 : recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_ADDRESS) != 0;
4333 59 : tree size = DECL_SIZE_UNIT (shadow_var);
4334 59 : gimple *poison_call
4335 59 : = gimple_build_call_internal (IFN_ASAN_MARK, 3,
4336 : build_int_cst (integer_type_node,
4337 : ASAN_MARK_POISON),
4338 : build_fold_addr_expr (shadow_var), size);
4339 :
4340 59 : gimple *use;
4341 59 : imm_use_iterator imm_iter;
4342 177 : FOR_EACH_IMM_USE_STMT (use, imm_iter, poisoned_var)
4343 : {
4344 118 : if (is_gimple_debug (use))
4345 59 : continue;
4346 :
4347 59 : int nargs;
4348 59 : bool store_p = gimple_call_internal_p (use, IFN_ASAN_POISON_USE);
4349 59 : gcall *call;
4350 59 : if (hwassist_sanitize_p ())
4351 : {
4352 0 : tree fun = builtin_decl_implicit (BUILT_IN_HWASAN_TAG_MISMATCH4);
4353 : /* NOTE: hwasan has no __hwasan_report_* functions like asan does.
4354 : We use __hwasan_tag_mismatch4 with arguments that tell it the
4355 : size of access and load to report all tag mismatches.
4356 :
4357 : The arguments to this function are:
4358 : Address of invalid access.
4359 : Bitfield containing information about the access
4360 : (access_info)
4361 : Pointer to a frame of registers
4362 : (for use in printing the contents of registers in a dump)
4363 : Not used yet -- to be used by inline instrumentation.
4364 : Size of access.
4365 :
4366 : The access_info bitfield encodes the following pieces of
4367 : information:
4368 : - Is this a store or load?
4369 : access_info & 0x10 => store
4370 : - Should the program continue after reporting the error?
4371 : access_info & 0x20 => recover
4372 : - What size access is this (not used here since we can always
4373 : pass the size in the last argument)
4374 :
4375 : if (access_info & 0xf == 0xf)
4376 : size is taken from last argument.
4377 : else
4378 : size == 1 << (access_info & 0xf)
4379 :
4380 : The last argument contains the size of the access iff the
4381 : access_info size indicator is 0xf (we always use this argument
4382 : rather than storing the size in the access_info bitfield).
4383 :
4384 : See the function definition `__hwasan_tag_mismatch4` in
4385 : libsanitizer/hwasan for the full definition.
4386 : */
4387 0 : unsigned access_info = (0x20 * recover_p)
4388 0 : + (0x10 * store_p)
4389 0 : + (0xf);
4390 0 : call = gimple_build_call (fun, 4,
4391 : build_fold_addr_expr (shadow_var),
4392 : build_int_cst (pointer_sized_int_node,
4393 0 : access_info),
4394 : build_int_cst (pointer_sized_int_node, 0),
4395 : size);
4396 : }
4397 : else
4398 : {
4399 59 : tree fun = report_error_func (store_p, recover_p, tree_to_uhwi (size),
4400 : &nargs);
4401 59 : tree ptrmode_type
4402 59 : = (nargs == 2 ? (*lang_hooks.types.type_for_mode) (ptr_mode, 0)
4403 : : NULL_TREE);
4404 87 : call = gimple_build_call (fun, nargs,
4405 : build_fold_addr_expr (shadow_var),
4406 : nargs == 2
4407 28 : ? fold_convert (ptrmode_type, size)
4408 : : NULL_TREE);
4409 : }
4410 59 : gimple_set_location (call, gimple_location (use));
4411 59 : gimple *call_to_insert = call;
4412 :
4413 : /* The USE can be a gimple PHI node. If so, insert the call on
4414 : all edges leading to the PHI node. */
4415 59 : if (is_a <gphi *> (use))
4416 : {
4417 : gphi *phi = dyn_cast<gphi *> (use);
4418 20 : for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
4419 15 : if (gimple_phi_arg_def (phi, i) == poisoned_var)
4420 : {
4421 5 : edge e = gimple_phi_arg_edge (phi, i);
4422 :
4423 : /* Do not insert on an edge we can't split. */
4424 5 : if (e->flags & EDGE_ABNORMAL)
4425 5 : continue;
4426 :
4427 0 : if (call_to_insert == NULL)
4428 0 : call_to_insert = gimple_copy (call);
4429 :
4430 0 : gsi_insert_seq_on_edge (e, call_to_insert);
4431 0 : *need_commit_edge_insert = true;
4432 0 : call_to_insert = NULL;
4433 : }
4434 : }
4435 : else
4436 : {
4437 54 : gimple_stmt_iterator gsi = gsi_for_stmt (use);
4438 54 : if (store_p)
4439 18 : gsi_replace (&gsi, call, true);
4440 : else
4441 36 : gsi_insert_before (&gsi, call, GSI_NEW_STMT);
4442 : }
4443 59 : }
4444 :
4445 59 : SSA_NAME_IS_DEFAULT_DEF (poisoned_var) = true;
4446 59 : SSA_NAME_DEF_STMT (poisoned_var) = gimple_build_nop ();
4447 59 : gsi_replace (iter, poison_call, false);
4448 :
4449 59 : return true;
4450 : }
4451 :
4452 : /* Instrument the current function. */
4453 :
4454 : static unsigned int
4455 6572 : asan_instrument (void)
4456 : {
4457 6572 : if (hwassist_sanitize_p ())
4458 : {
4459 448 : initialize_sanitizer_builtins ();
4460 448 : transform_statements ();
4461 448 : return 0;
4462 : }
4463 :
4464 6124 : if (shadow_ptr_types[0] == NULL_TREE)
4465 2349 : asan_init_shadow_ptr_types ();
4466 6124 : transform_statements ();
4467 6124 : last_alloca_addr = NULL_TREE;
4468 6124 : return 0;
4469 : }
4470 :
4471 : static bool
4472 1516027 : gate_asan (void)
4473 : {
4474 453231 : return sanitize_flags_p (SANITIZE_ADDRESS);
4475 : }
4476 :
4477 : namespace {
4478 :
4479 : const pass_data pass_data_asan =
4480 : {
4481 : GIMPLE_PASS, /* type */
4482 : "asan", /* name */
4483 : OPTGROUP_NONE, /* optinfo_flags */
4484 : TV_NONE, /* tv_id */
4485 : ( PROP_ssa | PROP_cfg | PROP_gimple_leh ), /* properties_required */
4486 : 0, /* properties_provided */
4487 : 0, /* properties_destroyed */
4488 : 0, /* todo_flags_start */
4489 : TODO_update_ssa, /* todo_flags_finish */
4490 : };
4491 :
4492 : class pass_asan : public gimple_opt_pass
4493 : {
4494 : public:
4495 588392 : pass_asan (gcc::context *ctxt)
4496 1176784 : : gimple_opt_pass (pass_data_asan, ctxt)
4497 : {}
4498 :
4499 : /* opt_pass methods: */
4500 294196 : opt_pass * clone () final override { return new pass_asan (m_ctxt); }
4501 1062796 : bool gate (function *) final override
4502 : {
4503 1062796 : return gate_asan () || gate_hwasan () || gate_memtag ();
4504 : }
4505 5181 : unsigned int execute (function *) final override
4506 : {
4507 5181 : return asan_instrument ();
4508 : }
4509 :
4510 : }; // class pass_asan
4511 :
4512 : } // anon namespace
4513 :
4514 : gimple_opt_pass *
4515 294196 : make_pass_asan (gcc::context *ctxt)
4516 : {
4517 294196 : return new pass_asan (ctxt);
4518 : }
4519 :
4520 : namespace {
4521 :
4522 : const pass_data pass_data_asan_O0 =
4523 : {
4524 : GIMPLE_PASS, /* type */
4525 : "asan0", /* name */
4526 : OPTGROUP_NONE, /* optinfo_flags */
4527 : TV_NONE, /* tv_id */
4528 : ( PROP_ssa | PROP_cfg | PROP_gimple_leh ), /* properties_required */
4529 : 0, /* properties_provided */
4530 : 0, /* properties_destroyed */
4531 : 0, /* todo_flags_start */
4532 : TODO_update_ssa, /* todo_flags_finish */
4533 : };
4534 :
4535 : class pass_asan_O0 : public gimple_opt_pass
4536 : {
4537 : public:
4538 294196 : pass_asan_O0 (gcc::context *ctxt)
4539 588392 : : gimple_opt_pass (pass_data_asan_O0, ctxt)
4540 : {}
4541 :
4542 : /* opt_pass methods: */
4543 1515908 : bool gate (function *) final override
4544 : {
4545 1969139 : return !optimize && (gate_asan () || gate_hwasan () || gate_memtag ());
4546 : }
4547 1391 : unsigned int execute (function *) final override
4548 : {
4549 1391 : return asan_instrument ();
4550 : }
4551 :
4552 : }; // class pass_asan_O0
4553 :
4554 : } // anon namespace
4555 :
4556 : gimple_opt_pass *
4557 294196 : make_pass_asan_O0 (gcc::context *ctxt)
4558 : {
4559 294196 : return new pass_asan_O0 (ctxt);
4560 : }
4561 :
4562 : /* HWASAN */
4563 :
4564 : /* For stack tagging:
4565 :
4566 : Return the offset from the frame base tag that the "next" expanded object
4567 : should have. */
4568 : uint8_t
4569 176 : hwasan_current_frame_tag ()
4570 : {
4571 176 : return hwasan_frame_tag_offset;
4572 : }
4573 :
4574 : /* For stack tagging:
4575 :
4576 : Return the 'base pointer' for this function. If that base pointer has not
4577 : yet been created then we create a register to hold it and record the insns
4578 : to initialize the register in `hwasan_frame_base_init_seq` for later
4579 : emission. */
4580 : rtx
4581 88 : hwasan_frame_base ()
4582 : {
4583 88 : if (! hwasan_frame_base_ptr)
4584 : {
4585 62 : start_sequence ();
4586 62 : hwasan_frame_base_ptr
4587 62 : = force_reg (Pmode,
4588 62 : targetm.memtag.insert_random_tag (virtual_stack_vars_rtx,
4589 : NULL_RTX));
4590 62 : hwasan_frame_base_init_seq = end_sequence ();
4591 : }
4592 :
4593 88 : return hwasan_frame_base_ptr;
4594 : }
4595 :
4596 : /* For stack tagging:
4597 :
4598 : Check whether this RTX is a standard pointer addressing the base of the
4599 : stack variables for this frame. Returns true if the RTX is either
4600 : virtual_stack_vars_rtx or hwasan_frame_base_ptr. */
4601 : bool
4602 2028824 : stack_vars_base_reg_p (rtx base)
4603 : {
4604 2028824 : return base == virtual_stack_vars_rtx || base == hwasan_frame_base_ptr;
4605 : }
4606 :
4607 : /* For stack tagging:
4608 :
4609 : Emit frame base initialisation.
4610 : If hwasan_frame_base has been used before here then
4611 : hwasan_frame_base_init_seq contains the sequence of instructions to
4612 : initialize it. This must be put just before the hwasan prologue, so we emit
4613 : the insns before parm_birth_insn (which will point to the first instruction
4614 : of the hwasan prologue if it exists).
4615 :
4616 : We update `parm_birth_insn` to point to the start of this initialisation
4617 : since that represents the end of the initialisation done by
4618 : expand_function_{start,end} functions and we want to maintain that. */
4619 : void
4620 364 : hwasan_maybe_emit_frame_base_init ()
4621 : {
4622 364 : if (! hwasan_frame_base_init_seq)
4623 : return;
4624 16 : emit_insn_before (hwasan_frame_base_init_seq, parm_birth_insn);
4625 16 : parm_birth_insn = hwasan_frame_base_init_seq;
4626 : }
4627 :
4628 : /* Record a compile-time constant size stack variable that HWASAN will need to
4629 : tag. This record of the range of a stack variable will be used by
4630 : `hwasan_emit_prologue` to emit the RTL at the start of each frame which will
4631 : set tags in the shadow memory according to the assigned tag for each object.
4632 :
4633 : The range that the object spans in stack space should be described by the
4634 : bounds `untagged_base + nearest_offset` and
4635 : `untagged_base + farthest_offset`.
4636 : `tagged_base` is the base address which contains the "base frame tag" for
4637 : this frame, and from which the value to address this object with will be
4638 : calculated.
4639 :
4640 : We record the `untagged_base` since the functions in the hwasan library we
4641 : use to tag memory take pointers without a tag. */
4642 : void
4643 88 : hwasan_record_stack_var (rtx untagged_base, rtx tagged_base,
4644 : poly_int64 nearest_offset, poly_int64 farthest_offset)
4645 : {
4646 88 : hwasan_stack_var cur_var;
4647 88 : cur_var.untagged_base = untagged_base;
4648 88 : cur_var.tagged_base = tagged_base;
4649 88 : cur_var.nearest_offset = nearest_offset;
4650 88 : cur_var.farthest_offset = farthest_offset;
4651 88 : cur_var.tag_offset = hwasan_current_frame_tag ();
4652 :
4653 88 : hwasan_tagged_stack_vars.safe_push (cur_var);
4654 88 : }
4655 :
4656 : /* Return the RTX representing the farthest extent of the statically allocated
4657 : stack objects for this frame. If hwasan_frame_base_ptr has not been
4658 : initialized then we are not storing any static variables on the stack in
4659 : this frame. In this case we return NULL_RTX to represent that.
4660 :
4661 : Otherwise simply return virtual_stack_vars_rtx + frame_offset. */
4662 : rtx
4663 364 : hwasan_get_frame_extent ()
4664 : {
4665 364 : return (hwasan_frame_base_ptr
4666 364 : ? plus_constant (Pmode, virtual_stack_vars_rtx, frame_offset)
4667 364 : : NULL_RTX);
4668 : }
4669 :
4670 : /* For stack tagging:
4671 :
4672 : Increment the frame tag offset modulo the size a tag can represent. */
4673 : void
4674 88 : hwasan_increment_frame_tag ()
4675 : {
4676 88 : uint8_t tag_bits = HWASAN_TAG_SIZE;
4677 88 : gcc_assert (HWASAN_TAG_SIZE
4678 : <= sizeof (hwasan_frame_tag_offset) * CHAR_BIT);
4679 88 : hwasan_frame_tag_offset = (hwasan_frame_tag_offset + 1) % (1 << tag_bits);
4680 : /* The "background tag" of the stack is zero by definition.
4681 : This is the tag that objects like parameters passed on the stack and
4682 : spilled registers are given. It is handy to avoid this tag for objects
4683 : whose tags we decide ourselves, partly to ensure that buffer overruns
4684 : can't affect these important variables (e.g. saved link register, saved
4685 : stack pointer etc) and partly to make debugging easier (everything with a
4686 : tag of zero is space allocated automatically by the compiler).
4687 :
4688 : This is not feasible when using random frame tags (the default
4689 : configuration for hwasan) since the tag for the given frame is randomly
4690 : chosen at runtime. In order to avoid any tags matching the stack
4691 : background we would need to decide tag offsets at runtime instead of
4692 : compile time (and pay the resulting performance cost).
4693 :
4694 : When not using random base tags for each frame (i.e. when compiled with
4695 : `--param hwasan-random-frame-tag=0`) the base tag for each frame is zero.
4696 : This means the tag that each object gets is equal to the
4697 : hwasan_frame_tag_offset used in determining it.
4698 : When this is the case we *can* ensure no object gets the tag of zero by
4699 : simply ensuring no object has the hwasan_frame_tag_offset of zero.
4700 :
4701 : There is the extra complication that we only record the
4702 : hwasan_frame_tag_offset here (which is the offset from the tag stored in
4703 : the stack pointer). In the kernel, the tag in the stack pointer is 0xff
4704 : rather than zero. This does not cause problems since tags of 0xff are
4705 : never checked in the kernel. As mentioned at the beginning of this
4706 : comment the background tag of the stack is zero by definition, which means
4707 : that for the kernel we should skip offsets of both 0 and 1 from the stack
4708 : pointer. Avoiding the offset of 0 ensures we use a tag which will be
4709 : checked, avoiding the offset of 1 ensures we use a tag that is not the
4710 : same as the background. */
4711 88 : if (hwasan_frame_tag_offset == 0 && ! param_hwasan_random_frame_tag)
4712 0 : hwasan_frame_tag_offset += 1;
4713 16 : if (hwasan_frame_tag_offset == 1 && ! param_hwasan_random_frame_tag
4714 88 : && sanitize_flags_p (SANITIZE_KERNEL_HWADDRESS))
4715 0 : hwasan_frame_tag_offset += 1;
4716 88 : }
4717 :
4718 : /* Clear internal state for the next function.
4719 : This function is called before variables on the stack get expanded, in
4720 : `init_vars_expansion`. */
4721 : void
4722 1108 : hwasan_record_frame_init ()
4723 : {
4724 1108 : delete asan_used_labels;
4725 1108 : asan_used_labels = NULL;
4726 :
4727 : /* If this isn't the case then some stack variable was recorded *before*
4728 : hwasan_record_frame_init is called, yet *after* the hwasan prologue for
4729 : the previous frame was emitted. Such stack variables would not have
4730 : their shadow stack filled in. */
4731 1108 : gcc_assert (hwasan_tagged_stack_vars.is_empty ());
4732 1108 : hwasan_frame_base_ptr = NULL_RTX;
4733 1108 : hwasan_frame_base_init_seq = NULL;
4734 :
4735 : /* When not using a random frame tag we can avoid the background stack
4736 : color which gives the user a little better debug output upon a crash.
4737 : Meanwhile, when using a random frame tag it will be nice to avoid adding
4738 : tags for the first object since that is unnecessary extra work.
4739 : Hence set the initial hwasan_frame_tag_offset to be 0 if using a random
4740 : frame tag and 1 otherwise.
4741 :
4742 : As described in hwasan_increment_frame_tag, in the kernel the stack
4743 : pointer has the tag 0xff. That means that to avoid 0xff and 0 (the tag
4744 : which the kernel does not check and the background tag respectively) we
4745 : start with a tag offset of 2. */
4746 2066 : hwasan_frame_tag_offset = param_hwasan_random_frame_tag
4747 : ? 0
4748 958 : : sanitize_flags_p (SANITIZE_KERNEL_HWADDRESS) ? 2 : 1;
4749 1108 : }
4750 :
4751 : /* For stack tagging:
4752 : (Emits HWASAN equivalent of what is emitted by
4753 : `asan_emit_stack_protection`).
4754 :
4755 : Emits the extra prologue code to set the shadow stack as required for HWASAN
4756 : stack instrumentation.
4757 :
4758 : Uses the vector of recorded stack variables hwasan_tagged_stack_vars. When
4759 : this function has completed hwasan_tagged_stack_vars is empty and all
4760 : objects it had pointed to are deallocated. */
4761 : void
4762 364 : hwasan_emit_prologue ()
4763 : {
4764 : /* We need untagged base pointers since libhwasan only accepts untagged
4765 : pointers in __hwasan_tag_memory. We need the tagged base pointer to obtain
4766 : the base tag for an offset. */
4767 :
4768 364 : if (hwasan_tagged_stack_vars.is_empty ())
4769 364 : return;
4770 :
4771 62 : poly_int64 bot = 0, top = 0;
4772 150 : for (hwasan_stack_var &cur : hwasan_tagged_stack_vars)
4773 : {
4774 88 : poly_int64 nearest = cur.nearest_offset;
4775 88 : poly_int64 farthest = cur.farthest_offset;
4776 :
4777 88 : if (known_ge (nearest, farthest))
4778 : {
4779 : top = nearest;
4780 : bot = farthest;
4781 : }
4782 : else
4783 : {
4784 : /* Given how these values are calculated, one must be known greater
4785 : than the other. */
4786 0 : gcc_assert (known_le (nearest, farthest));
4787 0 : top = farthest;
4788 0 : bot = nearest;
4789 : }
4790 88 : poly_int64 size = (top - bot);
4791 :
4792 : /* Assert the edge of each variable is aligned to the HWASAN tag granule
4793 : size. */
4794 176 : gcc_assert (multiple_p (top, HWASAN_TAG_GRANULE_SIZE));
4795 176 : gcc_assert (multiple_p (bot, HWASAN_TAG_GRANULE_SIZE));
4796 176 : gcc_assert (multiple_p (size, HWASAN_TAG_GRANULE_SIZE));
4797 :
4798 88 : rtx base_tag = targetm.memtag.extract_tag (cur.tagged_base, NULL_RTX);
4799 :
4800 88 : rtx bottom = convert_memory_address (ptr_mode,
4801 : plus_constant (Pmode,
4802 : cur.untagged_base,
4803 : bot));
4804 88 : if (memtag_sanitize_p ())
4805 : {
4806 0 : expand_operand ops[3];
4807 0 : rtx tagged_addr = gen_reg_rtx (ptr_mode);
4808 :
4809 : /* Check if the required target instructions are present. */
4810 0 : gcc_assert (targetm.have_compose_tag ());
4811 0 : gcc_assert (targetm.have_tag_memory ());
4812 :
4813 : /* The AArch64 has addg/subg instructions which are working directly
4814 : on a tagged pointer. */
4815 0 : create_output_operand (&ops[0], tagged_addr, ptr_mode);
4816 0 : create_input_operand (&ops[1], base_tag, ptr_mode);
4817 0 : create_integer_operand (&ops[2], cur.tag_offset);
4818 0 : expand_insn (targetm.code_for_compose_tag, 3, ops);
4819 :
4820 0 : emit_insn (targetm.gen_tag_memory (bottom, tagged_addr,
4821 : gen_int_mode (size, ptr_mode)));
4822 : }
4823 : else
4824 : {
4825 88 : rtx fn = init_one_libfunc ("__hwasan_tag_memory");
4826 88 : rtx tag = plus_constant (QImode, base_tag, cur.tag_offset);
4827 88 : tag = hwasan_truncate_to_tag_size (tag, NULL_RTX);
4828 88 : emit_library_call (fn, LCT_NORMAL, VOIDmode,
4829 : bottom, ptr_mode,
4830 : tag, QImode,
4831 : gen_int_mode (size, ptr_mode), ptr_mode);
4832 : }
4833 : }
4834 : /* Clear the stack vars, we've emitted the prologue for them all now. */
4835 62 : hwasan_tagged_stack_vars.truncate (0);
4836 : }
4837 :
4838 : /* For stack tagging:
4839 :
4840 : Return RTL insns to clear the tags between DYNAMIC and VARS pointers
4841 : into the stack. These instructions should be emitted at the end of
4842 : every function.
4843 :
4844 : If `dynamic` is NULL_RTX then no insns are returned. */
4845 : rtx_insn *
4846 364 : hwasan_emit_untag_frame (rtx dynamic, rtx vars)
4847 : {
4848 364 : if (! dynamic)
4849 : return NULL;
4850 :
4851 62 : start_sequence ();
4852 :
4853 62 : dynamic = convert_memory_address (ptr_mode, dynamic);
4854 62 : vars = convert_memory_address (ptr_mode, vars);
4855 :
4856 62 : rtx top_rtx;
4857 62 : rtx bot_rtx;
4858 62 : if (FRAME_GROWS_DOWNWARD)
4859 : {
4860 62 : top_rtx = vars;
4861 62 : bot_rtx = dynamic;
4862 : }
4863 : else
4864 : {
4865 : top_rtx = dynamic;
4866 : bot_rtx = vars;
4867 : }
4868 :
4869 62 : rtx size_rtx = simplify_gen_binary (MINUS, ptr_mode, top_rtx, bot_rtx);
4870 62 : if (!CONST_INT_P (size_rtx))
4871 0 : size_rtx = force_reg (ptr_mode, size_rtx);
4872 :
4873 62 : if (memtag_sanitize_p ())
4874 0 : emit_insn (targetm.gen_tag_memory (bot_rtx, HWASAN_STACK_BACKGROUND,
4875 : size_rtx));
4876 : else
4877 : {
4878 62 : rtx fn = init_one_libfunc ("__hwasan_tag_memory");
4879 62 : emit_library_call (fn, LCT_NORMAL, VOIDmode,
4880 : bot_rtx, ptr_mode,
4881 : HWASAN_STACK_BACKGROUND, QImode,
4882 : size_rtx, ptr_mode);
4883 : }
4884 :
4885 62 : do_pending_stack_adjust ();
4886 62 : return end_sequence ();
4887 : }
4888 :
4889 : /* Needs to be GTY(()), because cgraph_build_static_cdtor may
4890 : invoke ggc_collect. */
4891 : static GTY(()) tree hwasan_ctor_statements;
4892 :
4893 : /* Insert module initialization into this TU. This initialization calls the
4894 : initialization code for libhwasan. */
4895 : void
4896 250 : hwasan_finish_file (void)
4897 : {
4898 : /* Do not emit constructor initialization for the kernel.
4899 : (the kernel has its own initialization already). */
4900 250 : if (flag_sanitize & SANITIZE_KERNEL_HWADDRESS)
4901 : return;
4902 :
4903 236 : initialize_sanitizer_builtins ();
4904 :
4905 : /* Avoid instrumenting code in the hwasan constructors/destructors. */
4906 236 : flag_sanitize &= ~SANITIZE_HWADDRESS;
4907 236 : int priority = MAX_RESERVED_INIT_PRIORITY - 1;
4908 236 : tree fn = builtin_decl_implicit (BUILT_IN_HWASAN_INIT);
4909 236 : append_to_statement_list (build_call_expr (fn, 0), &hwasan_ctor_statements);
4910 236 : cgraph_build_static_cdtor ('I', hwasan_ctor_statements, priority);
4911 236 : flag_sanitize |= SANITIZE_HWADDRESS;
4912 : }
4913 :
4914 : /* For stack tagging:
4915 :
4916 : Truncate `tag` to the number of bits that a tag uses (i.e. to
4917 : HWASAN_TAG_SIZE). Store the result in `target` if it's convenient. */
4918 : rtx
4919 88 : hwasan_truncate_to_tag_size (rtx tag, rtx target)
4920 : {
4921 88 : gcc_assert (GET_MODE (tag) == QImode);
4922 88 : if (HWASAN_TAG_SIZE != GET_MODE_PRECISION (QImode))
4923 : {
4924 88 : gcc_assert (GET_MODE_PRECISION (QImode) > HWASAN_TAG_SIZE);
4925 88 : rtx mask = gen_int_mode ((HOST_WIDE_INT_1U << HWASAN_TAG_SIZE) - 1,
4926 : QImode);
4927 88 : tag = expand_simple_binop (QImode, AND, tag, mask, target,
4928 : /* unsignedp = */1, OPTAB_WIDEN);
4929 88 : gcc_assert (tag);
4930 : }
4931 88 : return tag;
4932 : }
4933 :
4934 : /* Construct a function tree for __hwasan_{load,store}{1,2,4,8,16,_n}.
4935 : IS_STORE is either 1 (for a store) or 0 (for a load). */
4936 : static combined_fn
4937 376 : hwasan_check_func (bool is_store, bool recover_p, HOST_WIDE_INT size_in_bytes,
4938 : int *nargs)
4939 : {
4940 376 : static enum built_in_function check[2][2][6]
4941 : = { { { BUILT_IN_HWASAN_LOAD1, BUILT_IN_HWASAN_LOAD2,
4942 : BUILT_IN_HWASAN_LOAD4, BUILT_IN_HWASAN_LOAD8,
4943 : BUILT_IN_HWASAN_LOAD16, BUILT_IN_HWASAN_LOADN },
4944 : { BUILT_IN_HWASAN_STORE1, BUILT_IN_HWASAN_STORE2,
4945 : BUILT_IN_HWASAN_STORE4, BUILT_IN_HWASAN_STORE8,
4946 : BUILT_IN_HWASAN_STORE16, BUILT_IN_HWASAN_STOREN } },
4947 : { { BUILT_IN_HWASAN_LOAD1_NOABORT,
4948 : BUILT_IN_HWASAN_LOAD2_NOABORT,
4949 : BUILT_IN_HWASAN_LOAD4_NOABORT,
4950 : BUILT_IN_HWASAN_LOAD8_NOABORT,
4951 : BUILT_IN_HWASAN_LOAD16_NOABORT,
4952 : BUILT_IN_HWASAN_LOADN_NOABORT },
4953 : { BUILT_IN_HWASAN_STORE1_NOABORT,
4954 : BUILT_IN_HWASAN_STORE2_NOABORT,
4955 : BUILT_IN_HWASAN_STORE4_NOABORT,
4956 : BUILT_IN_HWASAN_STORE8_NOABORT,
4957 : BUILT_IN_HWASAN_STORE16_NOABORT,
4958 : BUILT_IN_HWASAN_STOREN_NOABORT } } };
4959 376 : if (size_in_bytes == -1)
4960 : {
4961 0 : *nargs = 2;
4962 0 : return as_combined_fn (check[recover_p][is_store][5]);
4963 : }
4964 376 : *nargs = 1;
4965 376 : int size_log2 = exact_log2 (size_in_bytes);
4966 376 : gcc_assert (size_log2 >= 0 && size_log2 <= 5);
4967 376 : return as_combined_fn (check[recover_p][is_store][size_log2]);
4968 : }
4969 :
4970 : /* Expand the HWASAN_{LOAD,STORE} builtins. */
4971 : bool
4972 376 : hwasan_expand_check_ifn (gimple_stmt_iterator *iter, bool)
4973 : {
4974 376 : gimple *g = gsi_stmt (*iter);
4975 376 : location_t loc = gimple_location (g);
4976 376 : bool recover_p;
4977 376 : if (flag_sanitize & SANITIZE_USER_HWADDRESS)
4978 316 : recover_p = (flag_sanitize_recover & SANITIZE_USER_HWADDRESS) != 0;
4979 : else
4980 60 : recover_p = (flag_sanitize_recover & SANITIZE_KERNEL_HWADDRESS) != 0;
4981 :
4982 376 : HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0));
4983 376 : gcc_assert (flags < ASAN_CHECK_LAST);
4984 376 : bool is_scalar_access = (flags & ASAN_CHECK_SCALAR_ACCESS) != 0;
4985 376 : bool is_store = (flags & ASAN_CHECK_STORE) != 0;
4986 376 : bool is_non_zero_len = (flags & ASAN_CHECK_NON_ZERO_LEN) != 0;
4987 :
4988 376 : tree base = gimple_call_arg (g, 1);
4989 376 : tree len = gimple_call_arg (g, 2);
4990 :
4991 : /* `align` is unused for HWASAN_CHECK, but we pass the argument anyway
4992 : since that way the arguments match ASAN_CHECK. */
4993 : /* HOST_WIDE_INT align = tree_to_shwi (gimple_call_arg (g, 3)); */
4994 :
4995 1128 : unsigned HOST_WIDE_INT size_in_bytes
4996 376 : = is_scalar_access ? tree_to_shwi (len) : -1;
4997 :
4998 376 : gimple_stmt_iterator gsi = *iter;
4999 :
5000 376 : if (!is_non_zero_len)
5001 : {
5002 : /* So, the length of the memory area to hwasan-protect is
5003 : non-constant. Let's guard the generated instrumentation code
5004 : like:
5005 :
5006 : if (len != 0)
5007 : {
5008 : // hwasan instrumentation code goes here.
5009 : }
5010 : // fallthrough instructions, starting with *ITER. */
5011 :
5012 0 : g = gimple_build_cond (NE_EXPR,
5013 : len,
5014 0 : build_int_cst (TREE_TYPE (len), 0),
5015 : NULL_TREE, NULL_TREE);
5016 0 : gimple_set_location (g, loc);
5017 :
5018 0 : basic_block then_bb, fallthrough_bb;
5019 0 : insert_if_then_before_iter (as_a <gcond *> (g), iter,
5020 : /*then_more_likely_p=*/true,
5021 : &then_bb, &fallthrough_bb);
5022 : /* Note that fallthrough_bb starts with the statement that was
5023 : pointed to by ITER. */
5024 :
5025 : /* The 'then block' of the 'if (len != 0) condition is where
5026 : we'll generate the hwasan instrumentation code now. */
5027 0 : gsi = gsi_last_bb (then_bb);
5028 : }
5029 :
5030 376 : gimple_seq stmts = NULL;
5031 376 : tree base_addr = gimple_build (&stmts, loc, NOP_EXPR,
5032 : pointer_sized_int_node, base);
5033 :
5034 376 : int nargs = 0;
5035 376 : combined_fn fn
5036 376 : = hwasan_check_func (is_store, recover_p, size_in_bytes, &nargs);
5037 376 : if (nargs == 1)
5038 376 : gimple_build (&stmts, loc, fn, void_type_node, base_addr);
5039 : else
5040 : {
5041 0 : gcc_assert (nargs == 2);
5042 0 : tree sz_arg = gimple_build (&stmts, loc, NOP_EXPR,
5043 : pointer_sized_int_node, len);
5044 0 : gimple_build (&stmts, loc, fn, void_type_node, base_addr, sz_arg);
5045 : }
5046 :
5047 376 : gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
5048 376 : gsi_remove (iter, true);
5049 376 : *iter = gsi;
5050 376 : return false;
5051 : }
5052 :
5053 : /* For stack tagging:
5054 :
5055 : Dummy: the HWASAN_MARK internal function should only ever be in the code
5056 : after the sanopt pass. */
5057 : bool
5058 0 : hwasan_expand_mark_ifn (gimple_stmt_iterator *)
5059 : {
5060 0 : gcc_unreachable ();
5061 : }
5062 :
5063 : bool
5064 1747190 : gate_hwasan ()
5065 : {
5066 1747190 : return hwasan_sanitize_p ();
5067 : }
5068 :
5069 : bool
5070 1509455 : gate_memtag ()
5071 : {
5072 1509455 : return memtag_sanitize_p ();
5073 : }
5074 :
5075 : #include "gt-asan.h"
|