except.c: Use rtx_sequence
[official-gcc.git] / gcc / ubsan.c
blob0dbb104d2e8885a646f37a7823d530759f1ce640
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2014 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
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.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "stor-layout.h"
26 #include "stringpool.h"
27 #include "cgraph.h"
28 #include "tree-pass.h"
29 #include "tree-ssa-alias.h"
30 #include "tree-pretty-print.h"
31 #include "internal-fn.h"
32 #include "gimple-expr.h"
33 #include "gimple.h"
34 #include "gimple-iterator.h"
35 #include "gimple-ssa.h"
36 #include "gimple-walk.h"
37 #include "hashtab.h"
38 #include "output.h"
39 #include "tm_p.h"
40 #include "toplev.h"
41 #include "cfgloop.h"
42 #include "ubsan.h"
43 #include "c-family/c-common.h"
44 #include "rtl.h"
45 #include "expr.h"
46 #include "tree-ssanames.h"
47 #include "asan.h"
48 #include "gimplify-me.h"
49 #include "intl.h"
50 #include "realmpfr.h"
51 #include "dfp.h"
52 #include "builtins.h"
54 /* Map from a tree to a VAR_DECL tree. */
56 struct GTY(()) tree_type_map {
57 struct tree_map_base type;
58 tree decl;
61 #define tree_type_map_eq tree_map_base_eq
62 #define tree_type_map_marked_p tree_map_base_marked_p
64 /* Hash from a tree in a tree_type_map. */
66 unsigned int
67 tree_type_map_hash (const void *item)
69 return TYPE_UID (((const struct tree_type_map *)item)->type.from);
72 static GTY ((if_marked ("tree_type_map_marked_p"), param_is (struct tree_type_map)))
73 htab_t decl_tree_for_type;
75 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
77 static tree
78 decl_for_type_lookup (tree type)
80 /* If the hash table is not initialized yet, create it now. */
81 if (decl_tree_for_type == NULL)
83 decl_tree_for_type = htab_create_ggc (10, tree_type_map_hash,
84 tree_type_map_eq, 0);
85 /* That also means we don't have to bother with the lookup. */
86 return NULL_TREE;
89 struct tree_type_map *h, in;
90 in.type.from = type;
92 h = (struct tree_type_map *)
93 htab_find_with_hash (decl_tree_for_type, &in, TYPE_UID (type));
94 return h ? h->decl : NULL_TREE;
97 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
99 static void
100 decl_for_type_insert (tree type, tree decl)
102 struct tree_type_map *h;
103 void **slot;
105 h = ggc_alloc<tree_type_map> ();
106 h->type.from = type;
107 h->decl = decl;
108 slot = htab_find_slot_with_hash (decl_tree_for_type, h, TYPE_UID (type),
109 INSERT);
110 *(struct tree_type_map **) slot = h;
113 /* Helper routine, which encodes a value in the pointer_sized_int_node.
114 Arguments with precision <= POINTER_SIZE are passed directly,
115 the rest is passed by reference. T is a value we are to encode.
116 IN_EXPAND_P is true if this function is called during expansion. */
118 tree
119 ubsan_encode_value (tree t, bool in_expand_p)
121 tree type = TREE_TYPE (t);
122 const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
123 if (bitsize <= POINTER_SIZE)
124 switch (TREE_CODE (type))
126 case BOOLEAN_TYPE:
127 case ENUMERAL_TYPE:
128 case INTEGER_TYPE:
129 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
130 case REAL_TYPE:
132 tree itype = build_nonstandard_integer_type (bitsize, true);
133 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
134 return fold_convert (pointer_sized_int_node, t);
136 default:
137 gcc_unreachable ();
139 else
141 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
143 /* The reason for this is that we don't want to pessimize
144 code by making vars unnecessarily addressable. */
145 tree var = create_tmp_var (type, NULL);
146 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
147 if (in_expand_p)
149 rtx mem
150 = assign_stack_temp_for_type (TYPE_MODE (type),
151 GET_MODE_SIZE (TYPE_MODE (type)),
152 type);
153 SET_DECL_RTL (var, mem);
154 expand_assignment (var, t, false);
155 return build_fold_addr_expr (var);
157 t = build_fold_addr_expr (var);
158 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
160 else
161 return build_fold_addr_expr (t);
165 /* Build
166 struct __ubsan_type_descriptor
168 unsigned short __typekind;
169 unsigned short __typeinfo;
170 char __typename[];
172 type. */
174 static tree
175 ubsan_type_descriptor_type (void)
177 static const char *field_names[3]
178 = { "__typekind", "__typeinfo", "__typename" };
179 tree fields[3], ret;
180 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
181 tree flex_arr_type = build_array_type (char_type_node, itype);
183 ret = make_node (RECORD_TYPE);
184 for (int i = 0; i < 3; i++)
186 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
187 get_identifier (field_names[i]),
188 (i == 2) ? flex_arr_type
189 : short_unsigned_type_node);
190 DECL_CONTEXT (fields[i]) = ret;
191 if (i)
192 DECL_CHAIN (fields[i - 1]) = fields[i];
194 TYPE_FIELDS (ret) = fields[0];
195 TYPE_NAME (ret) = get_identifier ("__ubsan_type_descriptor");
196 layout_type (ret);
197 return ret;
200 /* Build
201 struct __ubsan_source_location
203 const char *__filename;
204 unsigned int __line;
205 unsigned int __column;
207 type. */
209 static tree
210 ubsan_source_location_type (void)
212 static const char *field_names[3]
213 = { "__filename", "__line", "__column" };
214 tree fields[3], ret;
215 tree const_char_type = build_qualified_type (char_type_node,
216 TYPE_QUAL_CONST);
218 ret = make_node (RECORD_TYPE);
219 for (int i = 0; i < 3; i++)
221 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
222 get_identifier (field_names[i]),
223 (i == 0) ? build_pointer_type (const_char_type)
224 : unsigned_type_node);
225 DECL_CONTEXT (fields[i]) = ret;
226 if (i)
227 DECL_CHAIN (fields[i - 1]) = fields[i];
229 TYPE_FIELDS (ret) = fields[0];
230 TYPE_NAME (ret) = get_identifier ("__ubsan_source_location");
231 layout_type (ret);
232 return ret;
235 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
236 type with its fields filled from a location_t LOC. */
238 static tree
239 ubsan_source_location (location_t loc)
241 expanded_location xloc;
242 tree type = ubsan_source_location_type ();
244 xloc = expand_location (loc);
245 if (xloc.file == NULL)
246 xloc.file = "<unknown>";
248 /* Fill in the values from LOC. */
249 size_t len = strlen (xloc.file);
250 tree str = build_string (len + 1, xloc.file);
251 TREE_TYPE (str) = build_array_type (char_type_node,
252 build_index_type (size_int (len)));
253 TREE_READONLY (str) = 1;
254 TREE_STATIC (str) = 1;
255 str = build_fold_addr_expr (str);
256 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
257 build_int_cst (unsigned_type_node,
258 xloc.line), NULL_TREE,
259 build_int_cst (unsigned_type_node,
260 xloc.column));
261 TREE_CONSTANT (ctor) = 1;
262 TREE_STATIC (ctor) = 1;
264 return ctor;
267 /* This routine returns a magic number for TYPE. */
269 static unsigned short
270 get_ubsan_type_info_for_type (tree type)
272 gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type)));
273 if (TREE_CODE (type) == REAL_TYPE)
274 return tree_to_uhwi (TYPE_SIZE (type));
275 else if (INTEGRAL_TYPE_P (type))
277 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
278 gcc_assert (prec != -1);
279 return (prec << 1) | !TYPE_UNSIGNED (type);
281 else
282 return 0;
285 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
286 descriptor. It first looks into the hash table; if not found,
287 create the VAR_DECL, put it into the hash table and return the
288 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
289 an enum controlling how we want to print the type. */
291 tree
292 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
294 /* See through any typedefs. */
295 type = TYPE_MAIN_VARIANT (type);
297 tree decl = decl_for_type_lookup (type);
298 /* It is possible that some of the earlier created DECLs were found
299 unused, in that case they weren't emitted and varpool_node::get
300 returns NULL node on them. But now we really need them. Thus,
301 renew them here. */
302 if (decl != NULL_TREE && varpool_node::get (decl))
303 return build_fold_addr_expr (decl);
305 tree dtype = ubsan_type_descriptor_type ();
306 tree type2 = type;
307 const char *tname = NULL;
308 char *pretty_name;
309 unsigned char deref_depth = 0;
310 unsigned short tkind, tinfo;
312 /* Get the name of the type, or the name of the pointer type. */
313 if (pstyle == UBSAN_PRINT_POINTER)
315 gcc_assert (POINTER_TYPE_P (type));
316 type2 = TREE_TYPE (type);
318 /* Remove any '*' operators from TYPE. */
319 while (POINTER_TYPE_P (type2))
320 deref_depth++, type2 = TREE_TYPE (type2);
322 if (TREE_CODE (type2) == METHOD_TYPE)
323 type2 = TYPE_METHOD_BASETYPE (type2);
326 /* If an array, get its type. */
327 type2 = strip_array_types (type2);
329 if (pstyle == UBSAN_PRINT_ARRAY)
331 while (POINTER_TYPE_P (type2))
332 deref_depth++, type2 = TREE_TYPE (type2);
335 if (TYPE_NAME (type2) != NULL)
337 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
338 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
339 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
340 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
343 if (tname == NULL)
344 /* We weren't able to determine the type name. */
345 tname = "<unknown>";
347 /* Decorate the type name with '', '*', "struct", or "union". */
348 pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth);
349 if (pstyle == UBSAN_PRINT_POINTER)
351 int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s",
352 TYPE_VOLATILE (type2) ? "volatile " : "",
353 TYPE_READONLY (type2) ? "const " : "",
354 TYPE_RESTRICT (type2) ? "restrict " : "",
355 TYPE_ATOMIC (type2) ? "_Atomic " : "",
356 TREE_CODE (type2) == RECORD_TYPE
357 ? "struct "
358 : TREE_CODE (type2) == UNION_TYPE
359 ? "union " : "", tname,
360 deref_depth == 0 ? "" : " ");
361 while (deref_depth-- > 0)
362 pretty_name[pos++] = '*';
363 pretty_name[pos++] = '\'';
364 pretty_name[pos] = '\0';
366 else if (pstyle == UBSAN_PRINT_ARRAY)
368 /* Pretty print the array dimensions. */
369 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
370 tree t = type;
371 int pos = sprintf (pretty_name, "'%s ", tname);
372 while (deref_depth-- > 0)
373 pretty_name[pos++] = '*';
374 while (TREE_CODE (t) == ARRAY_TYPE)
376 pretty_name[pos++] = '[';
377 tree dom = TYPE_DOMAIN (t);
378 if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
379 pos += sprintf (&pretty_name[pos], HOST_WIDE_INT_PRINT_DEC,
380 tree_to_shwi (TYPE_MAX_VALUE (dom)) + 1);
381 else
382 /* ??? We can't determine the variable name; print VLA unspec. */
383 pretty_name[pos++] = '*';
384 pretty_name[pos++] = ']';
385 t = TREE_TYPE (t);
387 pretty_name[pos++] = '\'';
388 pretty_name[pos] = '\0';
390 /* Save the tree with stripped types. */
391 type = t;
393 else
394 sprintf (pretty_name, "'%s'", tname);
396 switch (TREE_CODE (type))
398 case BOOLEAN_TYPE:
399 case ENUMERAL_TYPE:
400 case INTEGER_TYPE:
401 tkind = 0x0000;
402 break;
403 case REAL_TYPE:
404 /* FIXME: libubsan right now only supports float, double and
405 long double type formats. */
406 if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
407 || TYPE_MODE (type) == TYPE_MODE (double_type_node)
408 || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
409 tkind = 0x0001;
410 else
411 tkind = 0xffff;
412 break;
413 default:
414 tkind = 0xffff;
415 break;
417 tinfo = get_ubsan_type_info_for_type (type);
419 /* Create a new VAR_DECL of type descriptor. */
420 char tmp_name[32];
421 static unsigned int type_var_id_num;
422 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
423 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
424 dtype);
425 TREE_STATIC (decl) = 1;
426 TREE_PUBLIC (decl) = 0;
427 DECL_ARTIFICIAL (decl) = 1;
428 DECL_IGNORED_P (decl) = 1;
429 DECL_EXTERNAL (decl) = 0;
431 size_t len = strlen (pretty_name);
432 tree str = build_string (len + 1, pretty_name);
433 TREE_TYPE (str) = build_array_type (char_type_node,
434 build_index_type (size_int (len)));
435 TREE_READONLY (str) = 1;
436 TREE_STATIC (str) = 1;
437 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
438 build_int_cst (short_unsigned_type_node,
439 tkind), NULL_TREE,
440 build_int_cst (short_unsigned_type_node,
441 tinfo), NULL_TREE, str);
442 TREE_CONSTANT (ctor) = 1;
443 TREE_STATIC (ctor) = 1;
444 DECL_INITIAL (decl) = ctor;
445 varpool_node::finalize_decl (decl);
447 /* Save the VAR_DECL into the hash table. */
448 decl_for_type_insert (type, decl);
450 return build_fold_addr_expr (decl);
453 /* Create a structure for the ubsan library. NAME is a name of the new
454 structure. The arguments in ... are of __ubsan_type_descriptor type
455 and there are at most two of them. MISMATCH are data used by ubsan
456 pointer checking. */
458 tree
459 ubsan_create_data (const char *name, const location_t *ploc,
460 const struct ubsan_mismatch_data *mismatch, ...)
462 va_list args;
463 tree ret, t;
464 tree fields[5];
465 vec<tree, va_gc> *saved_args = NULL;
466 size_t i = 0;
467 location_t loc = UNKNOWN_LOCATION;
469 /* Firstly, create a pointer to type descriptor type. */
470 tree td_type = ubsan_type_descriptor_type ();
471 TYPE_READONLY (td_type) = 1;
472 td_type = build_pointer_type (td_type);
474 /* Create the structure type. */
475 ret = make_node (RECORD_TYPE);
476 if (ploc != NULL)
478 loc = LOCATION_LOCUS (*ploc);
479 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
480 ubsan_source_location_type ());
481 DECL_CONTEXT (fields[i]) = ret;
482 i++;
485 va_start (args, mismatch);
486 for (t = va_arg (args, tree); t != NULL_TREE;
487 i++, t = va_arg (args, tree))
489 gcc_checking_assert (i < 3);
490 /* Save the tree arguments for later use. */
491 vec_safe_push (saved_args, t);
492 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
493 td_type);
494 DECL_CONTEXT (fields[i]) = ret;
495 if (i)
496 DECL_CHAIN (fields[i - 1]) = fields[i];
498 va_end (args);
500 if (mismatch != NULL)
502 /* We have to add two more decls. */
503 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
504 pointer_sized_int_node);
505 DECL_CONTEXT (fields[i]) = ret;
506 DECL_CHAIN (fields[i - 1]) = fields[i];
507 i++;
509 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
510 unsigned_char_type_node);
511 DECL_CONTEXT (fields[i]) = ret;
512 DECL_CHAIN (fields[i - 1]) = fields[i];
513 i++;
516 TYPE_FIELDS (ret) = fields[0];
517 TYPE_NAME (ret) = get_identifier (name);
518 layout_type (ret);
520 /* Now, fill in the type. */
521 char tmp_name[32];
522 static unsigned int ubsan_var_id_num;
523 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
524 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
525 ret);
526 TREE_STATIC (var) = 1;
527 TREE_PUBLIC (var) = 0;
528 DECL_ARTIFICIAL (var) = 1;
529 DECL_IGNORED_P (var) = 1;
530 DECL_EXTERNAL (var) = 0;
532 vec<constructor_elt, va_gc> *v;
533 vec_alloc (v, i);
534 tree ctor = build_constructor (ret, v);
536 /* If desirable, set the __ubsan_source_location element. */
537 if (ploc != NULL)
538 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
540 size_t nelts = vec_safe_length (saved_args);
541 for (i = 0; i < nelts; i++)
543 t = (*saved_args)[i];
544 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
547 if (mismatch != NULL)
549 /* Append the pointer data. */
550 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, mismatch->align);
551 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, mismatch->ckind);
554 TREE_CONSTANT (ctor) = 1;
555 TREE_STATIC (ctor) = 1;
556 DECL_INITIAL (var) = ctor;
557 varpool_node::finalize_decl (var);
559 return var;
562 /* Instrument the __builtin_unreachable call. We just call the libubsan
563 routine instead. */
565 tree
566 ubsan_instrument_unreachable (location_t loc)
568 if (flag_sanitize_undefined_trap_on_error)
569 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
571 initialize_sanitizer_builtins ();
572 tree data = ubsan_create_data ("__ubsan_unreachable_data", &loc, NULL,
573 NULL_TREE);
574 tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
575 return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data));
578 /* Return true if T is a call to a libubsan routine. */
580 bool
581 is_ubsan_builtin_p (tree t)
583 return TREE_CODE (t) == FUNCTION_DECL
584 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
585 "__builtin___ubsan_", 18) == 0;
588 /* Expand the UBSAN_BOUNDS special builtin function. */
590 bool
591 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
593 gimple stmt = gsi_stmt (*gsi);
594 location_t loc = gimple_location (stmt);
595 gcc_assert (gimple_call_num_args (stmt) == 3);
597 /* Pick up the arguments of the UBSAN_BOUNDS call. */
598 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
599 tree index = gimple_call_arg (stmt, 1);
600 tree orig_index_type = TREE_TYPE (index);
601 tree bound = gimple_call_arg (stmt, 2);
603 gimple_stmt_iterator gsi_orig = *gsi;
605 /* Create condition "if (index > bound)". */
606 basic_block then_bb, fallthru_bb;
607 gimple_stmt_iterator cond_insert_point
608 = create_cond_insert_point (gsi, 0/*before_p*/, false, true,
609 &then_bb, &fallthru_bb);
610 index = fold_convert (TREE_TYPE (bound), index);
611 index = force_gimple_operand_gsi (&cond_insert_point, index,
612 true/*simple_p*/, NULL_TREE,
613 false/*before*/, GSI_NEW_STMT);
614 gimple g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
615 gimple_set_location (g, loc);
616 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
618 /* Generate __ubsan_handle_out_of_bounds call. */
619 *gsi = gsi_after_labels (then_bb);
620 if (flag_sanitize_undefined_trap_on_error)
621 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
622 else
624 tree data
625 = ubsan_create_data ("__ubsan_out_of_bounds_data", &loc, NULL,
626 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
627 ubsan_type_descriptor (orig_index_type),
628 NULL_TREE);
629 data = build_fold_addr_expr_loc (loc, data);
630 enum built_in_function bcode
631 = flag_sanitize_recover
632 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
633 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
634 tree fn = builtin_decl_explicit (bcode);
635 tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
636 true, NULL_TREE, true,
637 GSI_SAME_STMT);
638 g = gimple_build_call (fn, 2, data, val);
640 gimple_set_location (g, loc);
641 gsi_insert_before (gsi, g, GSI_SAME_STMT);
643 /* Get rid of the UBSAN_BOUNDS call from the IR. */
644 unlink_stmt_vdef (stmt);
645 gsi_remove (&gsi_orig, true);
647 /* Point GSI to next logical statement. */
648 *gsi = gsi_start_bb (fallthru_bb);
649 return true;
652 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
653 argument which is a constant, because the middle-end treats pointer
654 conversions as useless and therefore the type of the first argument
655 could be changed to any other pointer type. */
657 bool
658 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
660 gimple_stmt_iterator gsi = *gsip;
661 gimple stmt = gsi_stmt (gsi);
662 location_t loc = gimple_location (stmt);
663 gcc_assert (gimple_call_num_args (stmt) == 3);
664 tree ptr = gimple_call_arg (stmt, 0);
665 tree ckind = gimple_call_arg (stmt, 1);
666 tree align = gimple_call_arg (stmt, 2);
667 tree check_align = NULL_TREE;
668 bool check_null;
670 basic_block cur_bb = gsi_bb (gsi);
672 gimple g;
673 if (!integer_zerop (align))
675 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
676 if (compare_tree_int (align, ptralign) == 1)
678 check_align = make_ssa_name (pointer_sized_int_node, NULL);
679 g = gimple_build_assign_with_ops (NOP_EXPR, check_align,
680 ptr, NULL_TREE);
681 gimple_set_location (g, loc);
682 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
685 check_null = (flag_sanitize & SANITIZE_NULL) != 0;
687 if (check_align == NULL_TREE && !check_null)
689 gsi_remove (gsip, true);
690 /* Unlink the UBSAN_NULLs vops before replacing it. */
691 unlink_stmt_vdef (stmt);
692 return true;
695 /* Split the original block holding the pointer dereference. */
696 edge e = split_block (cur_bb, stmt);
698 /* Get a hold on the 'condition block', the 'then block' and the
699 'else block'. */
700 basic_block cond_bb = e->src;
701 basic_block fallthru_bb = e->dest;
702 basic_block then_bb = create_empty_bb (cond_bb);
703 add_bb_to_loop (then_bb, cond_bb->loop_father);
704 loops_state_set (LOOPS_NEED_FIXUP);
706 /* Make an edge coming from the 'cond block' into the 'then block';
707 this edge is unlikely taken, so set up the probability accordingly. */
708 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
709 e->probability = PROB_VERY_UNLIKELY;
711 /* Connect 'then block' with the 'else block'. This is needed
712 as the ubsan routines we call in the 'then block' are not noreturn.
713 The 'then block' only has one outcoming edge. */
714 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
716 /* Set up the fallthrough basic block. */
717 e = find_edge (cond_bb, fallthru_bb);
718 e->flags = EDGE_FALSE_VALUE;
719 e->count = cond_bb->count;
720 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
722 /* Update dominance info for the newly created then_bb; note that
723 fallthru_bb's dominance info has already been updated by
724 split_block. */
725 if (dom_info_available_p (CDI_DOMINATORS))
726 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
728 /* Put the ubsan builtin call into the newly created BB. */
729 if (flag_sanitize_undefined_trap_on_error)
730 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
731 else
733 enum built_in_function bcode
734 = flag_sanitize_recover
735 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
736 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
737 tree fn = builtin_decl_implicit (bcode);
738 const struct ubsan_mismatch_data m
739 = { align, fold_convert (unsigned_char_type_node, ckind) };
740 tree data
741 = ubsan_create_data ("__ubsan_null_data", &loc, &m,
742 ubsan_type_descriptor (TREE_TYPE (ckind),
743 UBSAN_PRINT_POINTER),
744 NULL_TREE);
745 data = build_fold_addr_expr_loc (loc, data);
746 g = gimple_build_call (fn, 2, data,
747 check_align ? check_align
748 : build_zero_cst (pointer_sized_int_node));
750 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
751 gimple_set_location (g, loc);
752 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
754 /* Unlink the UBSAN_NULLs vops before replacing it. */
755 unlink_stmt_vdef (stmt);
757 if (check_null)
759 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
760 NULL_TREE, NULL_TREE);
761 gimple_set_location (g, loc);
763 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
764 gsi_replace (&gsi, g, false);
767 if (check_align)
769 if (check_null)
771 /* Split the block with the condition again. */
772 e = split_block (cond_bb, stmt);
773 basic_block cond1_bb = e->src;
774 basic_block cond2_bb = e->dest;
776 /* Make an edge coming from the 'cond1 block' into the 'then block';
777 this edge is unlikely taken, so set up the probability
778 accordingly. */
779 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
780 e->probability = PROB_VERY_UNLIKELY;
782 /* Set up the fallthrough basic block. */
783 e = find_edge (cond1_bb, cond2_bb);
784 e->flags = EDGE_FALSE_VALUE;
785 e->count = cond1_bb->count;
786 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
788 /* Update dominance info. */
789 if (dom_info_available_p (CDI_DOMINATORS))
791 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
792 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
795 gsi2 = gsi_start_bb (cond2_bb);
798 tree mask = build_int_cst (pointer_sized_int_node,
799 tree_to_uhwi (align) - 1);
800 g = gimple_build_assign_with_ops (BIT_AND_EXPR,
801 make_ssa_name (pointer_sized_int_node,
802 NULL),
803 check_align, mask);
804 gimple_set_location (g, loc);
805 if (check_null)
806 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
807 else
808 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
810 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
811 build_int_cst (pointer_sized_int_node, 0),
812 NULL_TREE, NULL_TREE);
813 gimple_set_location (g, loc);
814 if (check_null)
815 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
816 else
817 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
818 gsi_replace (&gsi, g, false);
820 return false;
823 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
824 whether the pointer is on the left hand side of the assignment. */
826 static void
827 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
828 bool is_lhs)
830 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
831 unsigned int align = 0;
832 if (flag_sanitize & SANITIZE_ALIGNMENT)
834 align = min_align_of_type (TREE_TYPE (base));
835 if (align <= 1)
836 align = 0;
838 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
839 return;
840 tree t = TREE_OPERAND (base, 0);
841 if (!POINTER_TYPE_P (TREE_TYPE (t)))
842 return;
843 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && mem != base)
844 ikind = UBSAN_MEMBER_ACCESS;
845 tree kind = build_int_cst (TREE_TYPE (t), ikind);
846 tree alignt = build_int_cst (pointer_sized_int_node, align);
847 gimple g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
848 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
849 gsi_insert_before (iter, g, GSI_SAME_STMT);
852 /* Perform the pointer instrumentation. */
854 static void
855 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
857 gimple stmt = gsi_stmt (gsi);
858 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
859 tree base = get_base_address (t);
860 const enum tree_code code = TREE_CODE (base);
861 if (code == MEM_REF
862 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
863 instrument_mem_ref (t, base, &gsi, is_lhs);
866 /* Build an ubsan builtin call for the signed-integer-overflow
867 sanitization. CODE says what kind of builtin are we building,
868 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
869 are operands of the binary operation. */
871 tree
872 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
873 tree op0, tree op1)
875 if (flag_sanitize_undefined_trap_on_error)
876 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
878 tree data = ubsan_create_data ("__ubsan_overflow_data", &loc, NULL,
879 ubsan_type_descriptor (lhstype), NULL_TREE);
880 enum built_in_function fn_code;
882 switch (code)
884 case PLUS_EXPR:
885 fn_code = flag_sanitize_recover
886 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
887 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
888 break;
889 case MINUS_EXPR:
890 fn_code = flag_sanitize_recover
891 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
892 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
893 break;
894 case MULT_EXPR:
895 fn_code = flag_sanitize_recover
896 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
897 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
898 break;
899 case NEGATE_EXPR:
900 fn_code = flag_sanitize_recover
901 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
902 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
903 break;
904 default:
905 gcc_unreachable ();
907 tree fn = builtin_decl_explicit (fn_code);
908 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
909 build_fold_addr_expr_loc (loc, data),
910 ubsan_encode_value (op0, true),
911 op1 ? ubsan_encode_value (op1, true)
912 : NULL_TREE);
915 /* Perform the signed integer instrumentation. GSI is the iterator
916 pointing at statement we are trying to instrument. */
918 static void
919 instrument_si_overflow (gimple_stmt_iterator gsi)
921 gimple stmt = gsi_stmt (gsi);
922 tree_code code = gimple_assign_rhs_code (stmt);
923 tree lhs = gimple_assign_lhs (stmt);
924 tree lhstype = TREE_TYPE (lhs);
925 tree a, b;
926 gimple g;
928 /* If this is not a signed operation, don't instrument anything here.
929 Also punt on bit-fields. */
930 if (!INTEGRAL_TYPE_P (lhstype)
931 || TYPE_OVERFLOW_WRAPS (lhstype)
932 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
933 return;
935 switch (code)
937 case MINUS_EXPR:
938 case PLUS_EXPR:
939 case MULT_EXPR:
940 /* Transform
941 i = u {+,-,*} 5;
942 into
943 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
944 a = gimple_assign_rhs1 (stmt);
945 b = gimple_assign_rhs2 (stmt);
946 g = gimple_build_call_internal (code == PLUS_EXPR
947 ? IFN_UBSAN_CHECK_ADD
948 : code == MINUS_EXPR
949 ? IFN_UBSAN_CHECK_SUB
950 : IFN_UBSAN_CHECK_MUL, 2, a, b);
951 gimple_call_set_lhs (g, lhs);
952 gsi_replace (&gsi, g, false);
953 break;
954 case NEGATE_EXPR:
955 /* Represent i = -u;
957 i = UBSAN_CHECK_SUB (0, u); */
958 a = build_int_cst (lhstype, 0);
959 b = gimple_assign_rhs1 (stmt);
960 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
961 gimple_call_set_lhs (g, lhs);
962 gsi_replace (&gsi, g, false);
963 break;
964 case ABS_EXPR:
965 /* Transform i = ABS_EXPR<u>;
966 into
967 _N = UBSAN_CHECK_SUB (0, u);
968 i = ABS_EXPR<_N>; */
969 a = build_int_cst (lhstype, 0);
970 b = gimple_assign_rhs1 (stmt);
971 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
972 a = make_ssa_name (lhstype, NULL);
973 gimple_call_set_lhs (g, a);
974 gimple_set_location (g, gimple_location (stmt));
975 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
976 gimple_assign_set_rhs1 (stmt, a);
977 update_stmt (stmt);
978 break;
979 default:
980 break;
984 /* Instrument loads from (non-bitfield) bool and C++ enum values
985 to check if the memory value is outside of the range of the valid
986 type values. */
988 static void
989 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
991 gimple stmt = gsi_stmt (*gsi);
992 tree rhs = gimple_assign_rhs1 (stmt);
993 tree type = TREE_TYPE (rhs);
994 tree minv = NULL_TREE, maxv = NULL_TREE;
996 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
998 minv = boolean_false_node;
999 maxv = boolean_true_node;
1001 else if (TREE_CODE (type) == ENUMERAL_TYPE
1002 && (flag_sanitize & SANITIZE_ENUM)
1003 && TREE_TYPE (type) != NULL_TREE
1004 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1005 && (TYPE_PRECISION (TREE_TYPE (type))
1006 < GET_MODE_PRECISION (TYPE_MODE (type))))
1008 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1009 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1011 else
1012 return;
1014 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1015 HOST_WIDE_INT bitsize, bitpos;
1016 tree offset;
1017 enum machine_mode mode;
1018 int volatilep = 0, unsignedp = 0;
1019 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1020 &unsignedp, &volatilep, false);
1021 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1023 if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
1024 || (bitpos % modebitsize) != 0
1025 || bitsize != modebitsize
1026 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1027 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1028 return;
1030 location_t loc = gimple_location (stmt);
1031 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1032 tree atype = reference_alias_ptr_type (rhs);
1033 gimple g = gimple_build_assign (make_ssa_name (ptype, NULL),
1034 build_fold_addr_expr (rhs));
1035 gimple_set_location (g, loc);
1036 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1037 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1038 build_int_cst (atype, 0));
1039 tree urhs = make_ssa_name (utype, NULL);
1040 g = gimple_build_assign (urhs, mem);
1041 gimple_set_location (g, loc);
1042 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1043 minv = fold_convert (utype, minv);
1044 maxv = fold_convert (utype, maxv);
1045 if (!integer_zerop (minv))
1047 g = gimple_build_assign_with_ops (MINUS_EXPR,
1048 make_ssa_name (utype, NULL),
1049 urhs, minv);
1050 gimple_set_location (g, loc);
1051 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1054 gimple_stmt_iterator gsi2 = *gsi;
1055 basic_block then_bb, fallthru_bb;
1056 *gsi = create_cond_insert_point (gsi, true, false, true,
1057 &then_bb, &fallthru_bb);
1058 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1059 int_const_binop (MINUS_EXPR, maxv, minv),
1060 NULL_TREE, NULL_TREE);
1061 gimple_set_location (g, loc);
1062 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1064 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs, NULL_TREE);
1065 update_stmt (stmt);
1067 gsi2 = gsi_after_labels (then_bb);
1068 if (flag_sanitize_undefined_trap_on_error)
1069 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1070 else
1072 tree data = ubsan_create_data ("__ubsan_invalid_value_data", &loc, NULL,
1073 ubsan_type_descriptor (type), NULL_TREE);
1074 data = build_fold_addr_expr_loc (loc, data);
1075 enum built_in_function bcode
1076 = flag_sanitize_recover
1077 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1078 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1079 tree fn = builtin_decl_explicit (bcode);
1081 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1082 true, NULL_TREE, true,
1083 GSI_SAME_STMT);
1084 g = gimple_build_call (fn, 2, data, val);
1086 gimple_set_location (g, loc);
1087 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1090 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1091 destination, EXPR is floating-point expression. */
1093 tree
1094 ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1096 tree expr_type = TREE_TYPE (expr);
1097 tree t, tt, fn, min, max;
1098 enum machine_mode mode = TYPE_MODE (expr_type);
1099 int prec = TYPE_PRECISION (type);
1100 bool uns_p = TYPE_UNSIGNED (type);
1102 /* Float to integer conversion first truncates toward zero, so
1103 even signed char c = 127.875f; is not problematic.
1104 Therefore, we should complain only if EXPR is unordered or smaller
1105 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1106 TYPE_MAX_VALUE + 1.0. */
1107 if (REAL_MODE_FORMAT (mode)->b == 2)
1109 /* For maximum, TYPE_MAX_VALUE might not be representable
1110 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1111 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1112 either representable or infinity. */
1113 REAL_VALUE_TYPE maxval = dconst1;
1114 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1115 real_convert (&maxval, mode, &maxval);
1116 max = build_real (expr_type, maxval);
1118 /* For unsigned, assume -1.0 is always representable. */
1119 if (uns_p)
1120 min = build_minus_one_cst (expr_type);
1121 else
1123 /* TYPE_MIN_VALUE is generally representable (or -inf),
1124 but TYPE_MIN_VALUE - 1.0 might not be. */
1125 REAL_VALUE_TYPE minval = dconstm1, minval2;
1126 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1127 real_convert (&minval, mode, &minval);
1128 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1129 real_convert (&minval2, mode, &minval2);
1130 if (real_compare (EQ_EXPR, &minval, &minval2)
1131 && !real_isinf (&minval))
1133 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1134 rounds to TYPE_MIN_VALUE, we need to subtract
1135 more. As REAL_MODE_FORMAT (mode)->p is the number
1136 of base digits, we want to subtract a number that
1137 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1138 times smaller than minval. */
1139 minval2 = dconst1;
1140 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1141 SET_REAL_EXP (&minval2,
1142 REAL_EXP (&minval2) + prec - 1
1143 - REAL_MODE_FORMAT (mode)->p + 1);
1144 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1145 real_convert (&minval2, mode, &minval2);
1147 min = build_real (expr_type, minval2);
1150 else if (REAL_MODE_FORMAT (mode)->b == 10)
1152 /* For _Decimal128 up to 34 decimal digits, - sign,
1153 dot, e, exponent. */
1154 char buf[64];
1155 mpfr_t m;
1156 int p = REAL_MODE_FORMAT (mode)->p;
1157 REAL_VALUE_TYPE maxval, minval;
1159 /* Use mpfr_snprintf rounding to compute the smallest
1160 representable decimal number greater or equal than
1161 1 << (prec - !uns_p). */
1162 mpfr_init2 (m, prec + 2);
1163 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1164 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1165 decimal_real_from_string (&maxval, buf);
1166 max = build_real (expr_type, maxval);
1168 /* For unsigned, assume -1.0 is always representable. */
1169 if (uns_p)
1170 min = build_minus_one_cst (expr_type);
1171 else
1173 /* Use mpfr_snprintf rounding to compute the largest
1174 representable decimal number less or equal than
1175 (-1 << (prec - 1)) - 1. */
1176 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1177 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1178 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1179 decimal_real_from_string (&minval, buf);
1180 min = build_real (expr_type, minval);
1182 mpfr_clear (m);
1184 else
1185 return NULL_TREE;
1187 if (flag_sanitize_undefined_trap_on_error)
1188 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1189 else
1191 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1192 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", NULL,
1193 NULL, ubsan_type_descriptor (expr_type),
1194 ubsan_type_descriptor (type), NULL_TREE);
1195 enum built_in_function bcode
1196 = flag_sanitize_recover
1197 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1198 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1199 fn = builtin_decl_explicit (bcode);
1200 fn = build_call_expr_loc (loc, fn, 2,
1201 build_fold_addr_expr_loc (loc, data),
1202 ubsan_encode_value (expr, false));
1205 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1206 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1207 return fold_build3 (COND_EXPR, void_type_node,
1208 fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt),
1209 fn, integer_zero_node);
1212 namespace {
1214 const pass_data pass_data_ubsan =
1216 GIMPLE_PASS, /* type */
1217 "ubsan", /* name */
1218 OPTGROUP_NONE, /* optinfo_flags */
1219 TV_TREE_UBSAN, /* tv_id */
1220 ( PROP_cfg | PROP_ssa ), /* properties_required */
1221 0, /* properties_provided */
1222 0, /* properties_destroyed */
1223 0, /* todo_flags_start */
1224 TODO_update_ssa, /* todo_flags_finish */
1227 class pass_ubsan : public gimple_opt_pass
1229 public:
1230 pass_ubsan (gcc::context *ctxt)
1231 : gimple_opt_pass (pass_data_ubsan, ctxt)
1234 /* opt_pass methods: */
1235 virtual bool gate (function *)
1237 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
1238 | SANITIZE_BOOL | SANITIZE_ENUM
1239 | SANITIZE_ALIGNMENT)
1240 && current_function_decl != NULL_TREE
1241 && !lookup_attribute ("no_sanitize_undefined",
1242 DECL_ATTRIBUTES (current_function_decl));
1245 virtual unsigned int execute (function *);
1247 }; // class pass_ubsan
1249 unsigned int
1250 pass_ubsan::execute (function *fun)
1252 basic_block bb;
1253 gimple_stmt_iterator gsi;
1255 initialize_sanitizer_builtins ();
1257 FOR_EACH_BB_FN (bb, fun)
1259 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1261 gimple stmt = gsi_stmt (gsi);
1262 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1264 gsi_next (&gsi);
1265 continue;
1268 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1269 && is_gimple_assign (stmt))
1270 instrument_si_overflow (gsi);
1272 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1274 if (gimple_store_p (stmt))
1275 instrument_null (gsi, true);
1276 if (gimple_assign_load_p (stmt))
1277 instrument_null (gsi, false);
1280 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1281 && gimple_assign_load_p (stmt))
1282 instrument_bool_enum_load (&gsi);
1284 gsi_next (&gsi);
1287 return 0;
1290 } // anon namespace
1292 gimple_opt_pass *
1293 make_pass_ubsan (gcc::context *ctxt)
1295 return new pass_ubsan (ctxt);
1298 #include "gt-ubsan.h"