]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ubsan.c
dojump.h: New header file.
[thirdparty/gcc.git] / gcc / ubsan.c
1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2015 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.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 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "hash-set.h"
25 #include "machmode.h"
26 #include "vec.h"
27 #include "double-int.h"
28 #include "input.h"
29 #include "alias.h"
30 #include "symtab.h"
31 #include "options.h"
32 #include "wide-int.h"
33 #include "inchash.h"
34 #include "tree.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
37 #include "stringpool.h"
38 #include "predict.h"
39 #include "dominance.h"
40 #include "cfg.h"
41 #include "cfganal.h"
42 #include "basic-block.h"
43 #include "hash-map.h"
44 #include "is-a.h"
45 #include "plugin-api.h"
46 #include "tm.h"
47 #include "hard-reg-set.h"
48 #include "function.h"
49 #include "ipa-ref.h"
50 #include "cgraph.h"
51 #include "tree-pass.h"
52 #include "tree-ssa-alias.h"
53 #include "tree-pretty-print.h"
54 #include "internal-fn.h"
55 #include "gimple-expr.h"
56 #include "gimple.h"
57 #include "gimple-iterator.h"
58 #include "gimple-ssa.h"
59 #include "gimple-walk.h"
60 #include "output.h"
61 #include "tm_p.h"
62 #include "toplev.h"
63 #include "cfgloop.h"
64 #include "ubsan.h"
65 #include "c-family/c-common.h"
66 #include "rtl.h"
67 #include "hashtab.h"
68 #include "flags.h"
69 #include "statistics.h"
70 #include "real.h"
71 #include "fixed-value.h"
72 #include "insn-config.h"
73 #include "expmed.h"
74 #include "dojump.h"
75 #include "explow.h"
76 #include "calls.h"
77 #include "emit-rtl.h"
78 #include "varasm.h"
79 #include "stmt.h"
80 #include "expr.h"
81 #include "tree-ssanames.h"
82 #include "asan.h"
83 #include "gimplify-me.h"
84 #include "intl.h"
85 #include "realmpfr.h"
86 #include "dfp.h"
87 #include "builtins.h"
88 #include "tree-object-size.h"
89 #include "tree-eh.h"
90
91 /* Map from a tree to a VAR_DECL tree. */
92
93 struct GTY((for_user)) tree_type_map {
94 struct tree_map_base type;
95 tree decl;
96 };
97
98 struct tree_type_map_cache_hasher : ggc_cache_hasher<tree_type_map *>
99 {
100 static inline hashval_t
101 hash (tree_type_map *t)
102 {
103 return TYPE_UID (t->type.from);
104 }
105
106 static inline bool
107 equal (tree_type_map *a, tree_type_map *b)
108 {
109 return a->type.from == b->type.from;
110 }
111
112 static void
113 handle_cache_entry (tree_type_map *&m)
114 {
115 extern void gt_ggc_mx (tree_type_map *&);
116 if (m == HTAB_EMPTY_ENTRY || m == HTAB_DELETED_ENTRY)
117 return;
118 else if (ggc_marked_p (m->type.from))
119 gt_ggc_mx (m);
120 else
121 m = static_cast<tree_type_map *> (HTAB_DELETED_ENTRY);
122 }
123 };
124
125 static GTY ((cache))
126 hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
127
128 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
129
130 static tree
131 decl_for_type_lookup (tree type)
132 {
133 /* If the hash table is not initialized yet, create it now. */
134 if (decl_tree_for_type == NULL)
135 {
136 decl_tree_for_type
137 = hash_table<tree_type_map_cache_hasher>::create_ggc (10);
138 /* That also means we don't have to bother with the lookup. */
139 return NULL_TREE;
140 }
141
142 struct tree_type_map *h, in;
143 in.type.from = type;
144
145 h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
146 return h ? h->decl : NULL_TREE;
147 }
148
149 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
150
151 static void
152 decl_for_type_insert (tree type, tree decl)
153 {
154 struct tree_type_map *h;
155
156 h = ggc_alloc<tree_type_map> ();
157 h->type.from = type;
158 h->decl = decl;
159 *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
160 }
161
162 /* Helper routine, which encodes a value in the pointer_sized_int_node.
163 Arguments with precision <= POINTER_SIZE are passed directly,
164 the rest is passed by reference. T is a value we are to encode.
165 IN_EXPAND_P is true if this function is called during expansion. */
166
167 tree
168 ubsan_encode_value (tree t, bool in_expand_p)
169 {
170 tree type = TREE_TYPE (t);
171 const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
172 if (bitsize <= POINTER_SIZE)
173 switch (TREE_CODE (type))
174 {
175 case BOOLEAN_TYPE:
176 case ENUMERAL_TYPE:
177 case INTEGER_TYPE:
178 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
179 case REAL_TYPE:
180 {
181 tree itype = build_nonstandard_integer_type (bitsize, true);
182 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
183 return fold_convert (pointer_sized_int_node, t);
184 }
185 default:
186 gcc_unreachable ();
187 }
188 else
189 {
190 if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
191 {
192 /* The reason for this is that we don't want to pessimize
193 code by making vars unnecessarily addressable. */
194 tree var = create_tmp_var (type);
195 tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
196 if (in_expand_p)
197 {
198 rtx mem
199 = assign_stack_temp_for_type (TYPE_MODE (type),
200 GET_MODE_SIZE (TYPE_MODE (type)),
201 type);
202 SET_DECL_RTL (var, mem);
203 expand_assignment (var, t, false);
204 return build_fold_addr_expr (var);
205 }
206 t = build_fold_addr_expr (var);
207 return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
208 }
209 else
210 return build_fold_addr_expr (t);
211 }
212 }
213
214 /* Cached ubsan_get_type_descriptor_type () return value. */
215 static GTY(()) tree ubsan_type_descriptor_type;
216
217 /* Build
218 struct __ubsan_type_descriptor
219 {
220 unsigned short __typekind;
221 unsigned short __typeinfo;
222 char __typename[];
223 }
224 type. */
225
226 static tree
227 ubsan_get_type_descriptor_type (void)
228 {
229 static const char *field_names[3]
230 = { "__typekind", "__typeinfo", "__typename" };
231 tree fields[3], ret;
232
233 if (ubsan_type_descriptor_type)
234 return ubsan_type_descriptor_type;
235
236 tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
237 tree flex_arr_type = build_array_type (char_type_node, itype);
238
239 ret = make_node (RECORD_TYPE);
240 for (int i = 0; i < 3; i++)
241 {
242 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
243 get_identifier (field_names[i]),
244 (i == 2) ? flex_arr_type
245 : short_unsigned_type_node);
246 DECL_CONTEXT (fields[i]) = ret;
247 if (i)
248 DECL_CHAIN (fields[i - 1]) = fields[i];
249 }
250 tree type_decl = build_decl (input_location, TYPE_DECL,
251 get_identifier ("__ubsan_type_descriptor"),
252 ret);
253 DECL_IGNORED_P (type_decl) = 1;
254 DECL_ARTIFICIAL (type_decl) = 1;
255 TYPE_FIELDS (ret) = fields[0];
256 TYPE_NAME (ret) = type_decl;
257 TYPE_STUB_DECL (ret) = type_decl;
258 layout_type (ret);
259 ubsan_type_descriptor_type = ret;
260 return ret;
261 }
262
263 /* Cached ubsan_get_source_location_type () return value. */
264 static GTY(()) tree ubsan_source_location_type;
265
266 /* Build
267 struct __ubsan_source_location
268 {
269 const char *__filename;
270 unsigned int __line;
271 unsigned int __column;
272 }
273 type. */
274
275 tree
276 ubsan_get_source_location_type (void)
277 {
278 static const char *field_names[3]
279 = { "__filename", "__line", "__column" };
280 tree fields[3], ret;
281 if (ubsan_source_location_type)
282 return ubsan_source_location_type;
283
284 tree const_char_type = build_qualified_type (char_type_node,
285 TYPE_QUAL_CONST);
286
287 ret = make_node (RECORD_TYPE);
288 for (int i = 0; i < 3; i++)
289 {
290 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
291 get_identifier (field_names[i]),
292 (i == 0) ? build_pointer_type (const_char_type)
293 : unsigned_type_node);
294 DECL_CONTEXT (fields[i]) = ret;
295 if (i)
296 DECL_CHAIN (fields[i - 1]) = fields[i];
297 }
298 tree type_decl = build_decl (input_location, TYPE_DECL,
299 get_identifier ("__ubsan_source_location"),
300 ret);
301 DECL_IGNORED_P (type_decl) = 1;
302 DECL_ARTIFICIAL (type_decl) = 1;
303 TYPE_FIELDS (ret) = fields[0];
304 TYPE_NAME (ret) = type_decl;
305 TYPE_STUB_DECL (ret) = type_decl;
306 layout_type (ret);
307 ubsan_source_location_type = ret;
308 return ret;
309 }
310
311 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
312 type with its fields filled from a location_t LOC. */
313
314 static tree
315 ubsan_source_location (location_t loc)
316 {
317 expanded_location xloc;
318 tree type = ubsan_get_source_location_type ();
319
320 xloc = expand_location (loc);
321 tree str;
322 if (xloc.file == NULL)
323 {
324 str = build_int_cst (ptr_type_node, 0);
325 xloc.line = 0;
326 xloc.column = 0;
327 }
328 else
329 {
330 /* Fill in the values from LOC. */
331 size_t len = strlen (xloc.file);
332 str = build_string (len + 1, xloc.file);
333 TREE_TYPE (str) = build_array_type (char_type_node,
334 build_index_type (size_int (len)));
335 TREE_READONLY (str) = 1;
336 TREE_STATIC (str) = 1;
337 str = build_fold_addr_expr (str);
338 }
339 tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
340 build_int_cst (unsigned_type_node,
341 xloc.line), NULL_TREE,
342 build_int_cst (unsigned_type_node,
343 xloc.column));
344 TREE_CONSTANT (ctor) = 1;
345 TREE_STATIC (ctor) = 1;
346
347 return ctor;
348 }
349
350 /* This routine returns a magic number for TYPE. */
351
352 static unsigned short
353 get_ubsan_type_info_for_type (tree type)
354 {
355 gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type)));
356 if (TREE_CODE (type) == REAL_TYPE)
357 return tree_to_uhwi (TYPE_SIZE (type));
358 else if (INTEGRAL_TYPE_P (type))
359 {
360 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
361 gcc_assert (prec != -1);
362 return (prec << 1) | !TYPE_UNSIGNED (type);
363 }
364 else
365 return 0;
366 }
367
368 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
369 descriptor. It first looks into the hash table; if not found,
370 create the VAR_DECL, put it into the hash table and return the
371 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
372 an enum controlling how we want to print the type. */
373
374 tree
375 ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
376 {
377 /* See through any typedefs. */
378 type = TYPE_MAIN_VARIANT (type);
379
380 tree decl = decl_for_type_lookup (type);
381 /* It is possible that some of the earlier created DECLs were found
382 unused, in that case they weren't emitted and varpool_node::get
383 returns NULL node on them. But now we really need them. Thus,
384 renew them here. */
385 if (decl != NULL_TREE && varpool_node::get (decl))
386 return build_fold_addr_expr (decl);
387
388 tree dtype = ubsan_get_type_descriptor_type ();
389 tree type2 = type;
390 const char *tname = NULL;
391 char *pretty_name;
392 unsigned char deref_depth = 0;
393 unsigned short tkind, tinfo;
394
395 /* Get the name of the type, or the name of the pointer type. */
396 if (pstyle == UBSAN_PRINT_POINTER)
397 {
398 gcc_assert (POINTER_TYPE_P (type));
399 type2 = TREE_TYPE (type);
400
401 /* Remove any '*' operators from TYPE. */
402 while (POINTER_TYPE_P (type2))
403 deref_depth++, type2 = TREE_TYPE (type2);
404
405 if (TREE_CODE (type2) == METHOD_TYPE)
406 type2 = TYPE_METHOD_BASETYPE (type2);
407 }
408
409 /* If an array, get its type. */
410 type2 = strip_array_types (type2);
411
412 if (pstyle == UBSAN_PRINT_ARRAY)
413 {
414 while (POINTER_TYPE_P (type2))
415 deref_depth++, type2 = TREE_TYPE (type2);
416 }
417
418 if (TYPE_NAME (type2) != NULL)
419 {
420 if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
421 tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
422 else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
423 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
424 }
425
426 if (tname == NULL)
427 /* We weren't able to determine the type name. */
428 tname = "<unknown>";
429
430 /* Decorate the type name with '', '*', "struct", or "union". */
431 pretty_name = (char *) alloca (strlen (tname) + 16 + deref_depth);
432 if (pstyle == UBSAN_PRINT_POINTER)
433 {
434 int pos = sprintf (pretty_name, "'%s%s%s%s%s%s%s",
435 TYPE_VOLATILE (type2) ? "volatile " : "",
436 TYPE_READONLY (type2) ? "const " : "",
437 TYPE_RESTRICT (type2) ? "restrict " : "",
438 TYPE_ATOMIC (type2) ? "_Atomic " : "",
439 TREE_CODE (type2) == RECORD_TYPE
440 ? "struct "
441 : TREE_CODE (type2) == UNION_TYPE
442 ? "union " : "", tname,
443 deref_depth == 0 ? "" : " ");
444 while (deref_depth-- > 0)
445 pretty_name[pos++] = '*';
446 pretty_name[pos++] = '\'';
447 pretty_name[pos] = '\0';
448 }
449 else if (pstyle == UBSAN_PRINT_ARRAY)
450 {
451 /* Pretty print the array dimensions. */
452 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
453 tree t = type;
454 int pos = sprintf (pretty_name, "'%s ", tname);
455 while (deref_depth-- > 0)
456 pretty_name[pos++] = '*';
457 while (TREE_CODE (t) == ARRAY_TYPE)
458 {
459 pretty_name[pos++] = '[';
460 tree dom = TYPE_DOMAIN (t);
461 if (dom && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
462 pos += sprintf (&pretty_name[pos], HOST_WIDE_INT_PRINT_DEC,
463 tree_to_uhwi (TYPE_MAX_VALUE (dom)) + 1);
464 else
465 /* ??? We can't determine the variable name; print VLA unspec. */
466 pretty_name[pos++] = '*';
467 pretty_name[pos++] = ']';
468 t = TREE_TYPE (t);
469 }
470 pretty_name[pos++] = '\'';
471 pretty_name[pos] = '\0';
472
473 /* Save the tree with stripped types. */
474 type = t;
475 }
476 else
477 sprintf (pretty_name, "'%s'", tname);
478
479 switch (TREE_CODE (type))
480 {
481 case BOOLEAN_TYPE:
482 case ENUMERAL_TYPE:
483 case INTEGER_TYPE:
484 tkind = 0x0000;
485 break;
486 case REAL_TYPE:
487 /* FIXME: libubsan right now only supports float, double and
488 long double type formats. */
489 if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
490 || TYPE_MODE (type) == TYPE_MODE (double_type_node)
491 || TYPE_MODE (type) == TYPE_MODE (long_double_type_node))
492 tkind = 0x0001;
493 else
494 tkind = 0xffff;
495 break;
496 default:
497 tkind = 0xffff;
498 break;
499 }
500 tinfo = get_ubsan_type_info_for_type (type);
501
502 /* Create a new VAR_DECL of type descriptor. */
503 char tmp_name[32];
504 static unsigned int type_var_id_num;
505 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", type_var_id_num++);
506 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
507 dtype);
508 TREE_STATIC (decl) = 1;
509 TREE_PUBLIC (decl) = 0;
510 DECL_ARTIFICIAL (decl) = 1;
511 DECL_IGNORED_P (decl) = 1;
512 DECL_EXTERNAL (decl) = 0;
513
514 size_t len = strlen (pretty_name);
515 tree str = build_string (len + 1, pretty_name);
516 TREE_TYPE (str) = build_array_type (char_type_node,
517 build_index_type (size_int (len)));
518 TREE_READONLY (str) = 1;
519 TREE_STATIC (str) = 1;
520 tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
521 build_int_cst (short_unsigned_type_node,
522 tkind), NULL_TREE,
523 build_int_cst (short_unsigned_type_node,
524 tinfo), NULL_TREE, str);
525 TREE_CONSTANT (ctor) = 1;
526 TREE_STATIC (ctor) = 1;
527 DECL_INITIAL (decl) = ctor;
528 varpool_node::finalize_decl (decl);
529
530 /* Save the VAR_DECL into the hash table. */
531 decl_for_type_insert (type, decl);
532
533 return build_fold_addr_expr (decl);
534 }
535
536 /* Create a structure for the ubsan library. NAME is a name of the new
537 structure. LOCCNT is number of locations, PLOC points to array of
538 locations. The arguments in ... are of __ubsan_type_descriptor type
539 and there are at most two of them, followed by NULL_TREE, followed
540 by optional extra arguments and another NULL_TREE. */
541
542 tree
543 ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
544 {
545 va_list args;
546 tree ret, t;
547 tree fields[6];
548 vec<tree, va_gc> *saved_args = NULL;
549 size_t i = 0;
550 int j;
551
552 /* Firstly, create a pointer to type descriptor type. */
553 tree td_type = ubsan_get_type_descriptor_type ();
554 td_type = build_pointer_type (td_type);
555
556 /* Create the structure type. */
557 ret = make_node (RECORD_TYPE);
558 for (j = 0; j < loccnt; j++)
559 {
560 gcc_checking_assert (i < 2);
561 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
562 ubsan_get_source_location_type ());
563 DECL_CONTEXT (fields[i]) = ret;
564 if (i)
565 DECL_CHAIN (fields[i - 1]) = fields[i];
566 i++;
567 }
568
569 va_start (args, ploc);
570 for (t = va_arg (args, tree); t != NULL_TREE;
571 i++, t = va_arg (args, tree))
572 {
573 gcc_checking_assert (i < 4);
574 /* Save the tree arguments for later use. */
575 vec_safe_push (saved_args, t);
576 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
577 td_type);
578 DECL_CONTEXT (fields[i]) = ret;
579 if (i)
580 DECL_CHAIN (fields[i - 1]) = fields[i];
581 }
582
583 for (t = va_arg (args, tree); t != NULL_TREE;
584 i++, t = va_arg (args, tree))
585 {
586 gcc_checking_assert (i < 6);
587 /* Save the tree arguments for later use. */
588 vec_safe_push (saved_args, t);
589 fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
590 TREE_TYPE (t));
591 DECL_CONTEXT (fields[i]) = ret;
592 if (i)
593 DECL_CHAIN (fields[i - 1]) = fields[i];
594 }
595 va_end (args);
596
597 tree type_decl = build_decl (input_location, TYPE_DECL,
598 get_identifier (name), ret);
599 DECL_IGNORED_P (type_decl) = 1;
600 DECL_ARTIFICIAL (type_decl) = 1;
601 TYPE_FIELDS (ret) = fields[0];
602 TYPE_NAME (ret) = type_decl;
603 TYPE_STUB_DECL (ret) = type_decl;
604 layout_type (ret);
605
606 /* Now, fill in the type. */
607 char tmp_name[32];
608 static unsigned int ubsan_var_id_num;
609 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_var_id_num++);
610 tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
611 ret);
612 TREE_STATIC (var) = 1;
613 TREE_PUBLIC (var) = 0;
614 DECL_ARTIFICIAL (var) = 1;
615 DECL_IGNORED_P (var) = 1;
616 DECL_EXTERNAL (var) = 0;
617
618 vec<constructor_elt, va_gc> *v;
619 vec_alloc (v, i);
620 tree ctor = build_constructor (ret, v);
621
622 /* If desirable, set the __ubsan_source_location element. */
623 for (j = 0; j < loccnt; j++)
624 {
625 location_t loc = LOCATION_LOCUS (ploc[j]);
626 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
627 }
628
629 size_t nelts = vec_safe_length (saved_args);
630 for (i = 0; i < nelts; i++)
631 {
632 t = (*saved_args)[i];
633 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
634 }
635
636 TREE_CONSTANT (ctor) = 1;
637 TREE_STATIC (ctor) = 1;
638 DECL_INITIAL (var) = ctor;
639 varpool_node::finalize_decl (var);
640
641 return var;
642 }
643
644 /* Instrument the __builtin_unreachable call. We just call the libubsan
645 routine instead. */
646
647 bool
648 ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
649 {
650 gimple g;
651 location_t loc = gimple_location (gsi_stmt (*gsi));
652
653 if (flag_sanitize_undefined_trap_on_error)
654 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
655 else
656 {
657 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
658 NULL_TREE, NULL_TREE);
659 data = build_fold_addr_expr_loc (loc, data);
660 tree fn
661 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
662 g = gimple_build_call (fn, 1, data);
663 }
664 gimple_set_location (g, loc);
665 gsi_replace (gsi, g, false);
666 return false;
667 }
668
669 /* Return true if T is a call to a libubsan routine. */
670
671 bool
672 is_ubsan_builtin_p (tree t)
673 {
674 return TREE_CODE (t) == FUNCTION_DECL
675 && DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
676 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
677 "__builtin___ubsan_", 18) == 0;
678 }
679
680 /* Expand the UBSAN_BOUNDS special builtin function. */
681
682 bool
683 ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
684 {
685 gimple stmt = gsi_stmt (*gsi);
686 location_t loc = gimple_location (stmt);
687 gcc_assert (gimple_call_num_args (stmt) == 3);
688
689 /* Pick up the arguments of the UBSAN_BOUNDS call. */
690 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
691 tree index = gimple_call_arg (stmt, 1);
692 tree orig_index_type = TREE_TYPE (index);
693 tree bound = gimple_call_arg (stmt, 2);
694
695 gimple_stmt_iterator gsi_orig = *gsi;
696
697 /* Create condition "if (index > bound)". */
698 basic_block then_bb, fallthru_bb;
699 gimple_stmt_iterator cond_insert_point
700 = create_cond_insert_point (gsi, false, false, true,
701 &then_bb, &fallthru_bb);
702 index = fold_convert (TREE_TYPE (bound), index);
703 index = force_gimple_operand_gsi (&cond_insert_point, index,
704 true, NULL_TREE,
705 false, GSI_NEW_STMT);
706 gimple g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
707 gimple_set_location (g, loc);
708 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
709
710 /* Generate __ubsan_handle_out_of_bounds call. */
711 *gsi = gsi_after_labels (then_bb);
712 if (flag_sanitize_undefined_trap_on_error)
713 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
714 else
715 {
716 tree data
717 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
718 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
719 ubsan_type_descriptor (orig_index_type),
720 NULL_TREE, NULL_TREE);
721 data = build_fold_addr_expr_loc (loc, data);
722 enum built_in_function bcode
723 = (flag_sanitize_recover & SANITIZE_BOUNDS)
724 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
725 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
726 tree fn = builtin_decl_explicit (bcode);
727 tree val = force_gimple_operand_gsi (gsi, ubsan_encode_value (index),
728 true, NULL_TREE, true,
729 GSI_SAME_STMT);
730 g = gimple_build_call (fn, 2, data, val);
731 }
732 gimple_set_location (g, loc);
733 gsi_insert_before (gsi, g, GSI_SAME_STMT);
734
735 /* Get rid of the UBSAN_BOUNDS call from the IR. */
736 unlink_stmt_vdef (stmt);
737 gsi_remove (&gsi_orig, true);
738
739 /* Point GSI to next logical statement. */
740 *gsi = gsi_start_bb (fallthru_bb);
741 return true;
742 }
743
744 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
745 argument which is a constant, because the middle-end treats pointer
746 conversions as useless and therefore the type of the first argument
747 could be changed to any other pointer type. */
748
749 bool
750 ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
751 {
752 gimple_stmt_iterator gsi = *gsip;
753 gimple stmt = gsi_stmt (gsi);
754 location_t loc = gimple_location (stmt);
755 gcc_assert (gimple_call_num_args (stmt) == 3);
756 tree ptr = gimple_call_arg (stmt, 0);
757 tree ckind = gimple_call_arg (stmt, 1);
758 tree align = gimple_call_arg (stmt, 2);
759 tree check_align = NULL_TREE;
760 bool check_null;
761
762 basic_block cur_bb = gsi_bb (gsi);
763
764 gimple g;
765 if (!integer_zerop (align))
766 {
767 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
768 if (compare_tree_int (align, ptralign) == 1)
769 {
770 check_align = make_ssa_name (pointer_sized_int_node);
771 g = gimple_build_assign (check_align, NOP_EXPR, ptr);
772 gimple_set_location (g, loc);
773 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
774 }
775 }
776 check_null = (flag_sanitize & SANITIZE_NULL) != 0;
777
778 if (check_align == NULL_TREE && !check_null)
779 {
780 gsi_remove (gsip, true);
781 /* Unlink the UBSAN_NULLs vops before replacing it. */
782 unlink_stmt_vdef (stmt);
783 return true;
784 }
785
786 /* Split the original block holding the pointer dereference. */
787 edge e = split_block (cur_bb, stmt);
788
789 /* Get a hold on the 'condition block', the 'then block' and the
790 'else block'. */
791 basic_block cond_bb = e->src;
792 basic_block fallthru_bb = e->dest;
793 basic_block then_bb = create_empty_bb (cond_bb);
794 add_bb_to_loop (then_bb, cond_bb->loop_father);
795 loops_state_set (LOOPS_NEED_FIXUP);
796
797 /* Make an edge coming from the 'cond block' into the 'then block';
798 this edge is unlikely taken, so set up the probability accordingly. */
799 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
800 e->probability = PROB_VERY_UNLIKELY;
801
802 /* Connect 'then block' with the 'else block'. This is needed
803 as the ubsan routines we call in the 'then block' are not noreturn.
804 The 'then block' only has one outcoming edge. */
805 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
806
807 /* Set up the fallthrough basic block. */
808 e = find_edge (cond_bb, fallthru_bb);
809 e->flags = EDGE_FALSE_VALUE;
810 e->count = cond_bb->count;
811 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
812
813 /* Update dominance info for the newly created then_bb; note that
814 fallthru_bb's dominance info has already been updated by
815 split_block. */
816 if (dom_info_available_p (CDI_DOMINATORS))
817 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
818
819 /* Put the ubsan builtin call into the newly created BB. */
820 if (flag_sanitize_undefined_trap_on_error)
821 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
822 else
823 {
824 enum built_in_function bcode
825 = (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
826 | (check_null ? SANITIZE_NULL : 0)))
827 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
828 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
829 tree fn = builtin_decl_implicit (bcode);
830 tree data
831 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
832 ubsan_type_descriptor (TREE_TYPE (ckind),
833 UBSAN_PRINT_POINTER),
834 NULL_TREE,
835 align,
836 fold_convert (unsigned_char_type_node, ckind),
837 NULL_TREE);
838 data = build_fold_addr_expr_loc (loc, data);
839 g = gimple_build_call (fn, 2, data,
840 check_align ? check_align
841 : build_zero_cst (pointer_sized_int_node));
842 }
843 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
844 gimple_set_location (g, loc);
845 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
846
847 /* Unlink the UBSAN_NULLs vops before replacing it. */
848 unlink_stmt_vdef (stmt);
849
850 if (check_null)
851 {
852 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
853 NULL_TREE, NULL_TREE);
854 gimple_set_location (g, loc);
855
856 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
857 gsi_replace (&gsi, g, false);
858 }
859
860 if (check_align)
861 {
862 if (check_null)
863 {
864 /* Split the block with the condition again. */
865 e = split_block (cond_bb, stmt);
866 basic_block cond1_bb = e->src;
867 basic_block cond2_bb = e->dest;
868
869 /* Make an edge coming from the 'cond1 block' into the 'then block';
870 this edge is unlikely taken, so set up the probability
871 accordingly. */
872 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
873 e->probability = PROB_VERY_UNLIKELY;
874
875 /* Set up the fallthrough basic block. */
876 e = find_edge (cond1_bb, cond2_bb);
877 e->flags = EDGE_FALSE_VALUE;
878 e->count = cond1_bb->count;
879 e->probability = REG_BR_PROB_BASE - PROB_VERY_UNLIKELY;
880
881 /* Update dominance info. */
882 if (dom_info_available_p (CDI_DOMINATORS))
883 {
884 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
885 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
886 }
887
888 gsi2 = gsi_start_bb (cond2_bb);
889 }
890
891 tree mask = build_int_cst (pointer_sized_int_node,
892 tree_to_uhwi (align) - 1);
893 g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
894 BIT_AND_EXPR, check_align, mask);
895 gimple_set_location (g, loc);
896 if (check_null)
897 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
898 else
899 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
900
901 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
902 build_int_cst (pointer_sized_int_node, 0),
903 NULL_TREE, NULL_TREE);
904 gimple_set_location (g, loc);
905 if (check_null)
906 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
907 else
908 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
909 gsi_replace (&gsi, g, false);
910 }
911 return false;
912 }
913
914 /* Expand UBSAN_OBJECT_SIZE internal call. */
915
916 bool
917 ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
918 {
919 gimple stmt = gsi_stmt (*gsi);
920 location_t loc = gimple_location (stmt);
921 gcc_assert (gimple_call_num_args (stmt) == 4);
922
923 tree ptr = gimple_call_arg (stmt, 0);
924 tree offset = gimple_call_arg (stmt, 1);
925 tree size = gimple_call_arg (stmt, 2);
926 tree ckind = gimple_call_arg (stmt, 3);
927 gimple_stmt_iterator gsi_orig = *gsi;
928 gimple g;
929
930 /* See if we can discard the check. */
931 if (TREE_CODE (size) != INTEGER_CST
932 || integer_all_onesp (size))
933 /* Yes, __builtin_object_size couldn't determine the
934 object size. */;
935 else
936 {
937 /* if (offset > objsize) */
938 basic_block then_bb, fallthru_bb;
939 gimple_stmt_iterator cond_insert_point
940 = create_cond_insert_point (gsi, false, false, true,
941 &then_bb, &fallthru_bb);
942 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
943 gimple_set_location (g, loc);
944 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
945
946 /* Generate __ubsan_handle_type_mismatch call. */
947 *gsi = gsi_after_labels (then_bb);
948 if (flag_sanitize_undefined_trap_on_error)
949 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
950 else
951 {
952 tree data
953 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
954 ubsan_type_descriptor (TREE_TYPE (ptr),
955 UBSAN_PRINT_POINTER),
956 NULL_TREE,
957 build_zero_cst (pointer_sized_int_node),
958 ckind,
959 NULL_TREE);
960 data = build_fold_addr_expr_loc (loc, data);
961 enum built_in_function bcode
962 = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
963 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
964 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT;
965 tree p = make_ssa_name (pointer_sized_int_node);
966 g = gimple_build_assign (p, NOP_EXPR, ptr);
967 gimple_set_location (g, loc);
968 gsi_insert_before (gsi, g, GSI_SAME_STMT);
969 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
970 }
971 gimple_set_location (g, loc);
972 gsi_insert_before (gsi, g, GSI_SAME_STMT);
973
974 /* Point GSI to next logical statement. */
975 *gsi = gsi_start_bb (fallthru_bb);
976 }
977
978 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
979 unlink_stmt_vdef (stmt);
980 gsi_remove (&gsi_orig, true);
981 return gsi_end_p (*gsi);
982 }
983
984 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
985 whether the pointer is on the left hand side of the assignment. */
986
987 static void
988 instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
989 bool is_lhs)
990 {
991 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
992 unsigned int align = 0;
993 if (flag_sanitize & SANITIZE_ALIGNMENT)
994 {
995 align = min_align_of_type (TREE_TYPE (base));
996 if (align <= 1)
997 align = 0;
998 }
999 if (align == 0 && (flag_sanitize & SANITIZE_NULL) == 0)
1000 return;
1001 tree t = TREE_OPERAND (base, 0);
1002 if (!POINTER_TYPE_P (TREE_TYPE (t)))
1003 return;
1004 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && mem != base)
1005 ikind = UBSAN_MEMBER_ACCESS;
1006 tree kind = build_int_cst (TREE_TYPE (t), ikind);
1007 tree alignt = build_int_cst (pointer_sized_int_node, align);
1008 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1009 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1010 gsi_insert_before (iter, g, GSI_SAME_STMT);
1011 }
1012
1013 /* Perform the pointer instrumentation. */
1014
1015 static void
1016 instrument_null (gimple_stmt_iterator gsi, bool is_lhs)
1017 {
1018 gimple stmt = gsi_stmt (gsi);
1019 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1020 tree base = get_base_address (t);
1021 const enum tree_code code = TREE_CODE (base);
1022 if (code == MEM_REF
1023 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1024 instrument_mem_ref (t, base, &gsi, is_lhs);
1025 }
1026
1027 /* Build an ubsan builtin call for the signed-integer-overflow
1028 sanitization. CODE says what kind of builtin are we building,
1029 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1030 are operands of the binary operation. */
1031
1032 tree
1033 ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1034 tree op0, tree op1)
1035 {
1036 if (flag_sanitize_undefined_trap_on_error)
1037 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1038
1039 tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1040 ubsan_type_descriptor (lhstype), NULL_TREE,
1041 NULL_TREE);
1042 enum built_in_function fn_code;
1043
1044 switch (code)
1045 {
1046 case PLUS_EXPR:
1047 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1048 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1049 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1050 break;
1051 case MINUS_EXPR:
1052 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1053 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1054 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1055 break;
1056 case MULT_EXPR:
1057 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1058 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1059 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1060 break;
1061 case NEGATE_EXPR:
1062 fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1063 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1064 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1065 break;
1066 default:
1067 gcc_unreachable ();
1068 }
1069 tree fn = builtin_decl_explicit (fn_code);
1070 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1071 build_fold_addr_expr_loc (loc, data),
1072 ubsan_encode_value (op0, true),
1073 op1 ? ubsan_encode_value (op1, true)
1074 : NULL_TREE);
1075 }
1076
1077 /* Perform the signed integer instrumentation. GSI is the iterator
1078 pointing at statement we are trying to instrument. */
1079
1080 static void
1081 instrument_si_overflow (gimple_stmt_iterator gsi)
1082 {
1083 gimple stmt = gsi_stmt (gsi);
1084 tree_code code = gimple_assign_rhs_code (stmt);
1085 tree lhs = gimple_assign_lhs (stmt);
1086 tree lhstype = TREE_TYPE (lhs);
1087 tree a, b;
1088 gimple g;
1089
1090 /* If this is not a signed operation, don't instrument anything here.
1091 Also punt on bit-fields. */
1092 if (!INTEGRAL_TYPE_P (lhstype)
1093 || TYPE_OVERFLOW_WRAPS (lhstype)
1094 || GET_MODE_BITSIZE (TYPE_MODE (lhstype)) != TYPE_PRECISION (lhstype))
1095 return;
1096
1097 switch (code)
1098 {
1099 case MINUS_EXPR:
1100 case PLUS_EXPR:
1101 case MULT_EXPR:
1102 /* Transform
1103 i = u {+,-,*} 5;
1104 into
1105 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1106 a = gimple_assign_rhs1 (stmt);
1107 b = gimple_assign_rhs2 (stmt);
1108 g = gimple_build_call_internal (code == PLUS_EXPR
1109 ? IFN_UBSAN_CHECK_ADD
1110 : code == MINUS_EXPR
1111 ? IFN_UBSAN_CHECK_SUB
1112 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1113 gimple_call_set_lhs (g, lhs);
1114 gsi_replace (&gsi, g, false);
1115 break;
1116 case NEGATE_EXPR:
1117 /* Represent i = -u;
1118 as
1119 i = UBSAN_CHECK_SUB (0, u); */
1120 a = build_int_cst (lhstype, 0);
1121 b = gimple_assign_rhs1 (stmt);
1122 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1123 gimple_call_set_lhs (g, lhs);
1124 gsi_replace (&gsi, g, false);
1125 break;
1126 case ABS_EXPR:
1127 /* Transform i = ABS_EXPR<u>;
1128 into
1129 _N = UBSAN_CHECK_SUB (0, u);
1130 i = ABS_EXPR<_N>; */
1131 a = build_int_cst (lhstype, 0);
1132 b = gimple_assign_rhs1 (stmt);
1133 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1134 a = make_ssa_name (lhstype);
1135 gimple_call_set_lhs (g, a);
1136 gimple_set_location (g, gimple_location (stmt));
1137 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1138 gimple_assign_set_rhs1 (stmt, a);
1139 update_stmt (stmt);
1140 break;
1141 default:
1142 break;
1143 }
1144 }
1145
1146 /* Instrument loads from (non-bitfield) bool and C++ enum values
1147 to check if the memory value is outside of the range of the valid
1148 type values. */
1149
1150 static void
1151 instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1152 {
1153 gimple stmt = gsi_stmt (*gsi);
1154 tree rhs = gimple_assign_rhs1 (stmt);
1155 tree type = TREE_TYPE (rhs);
1156 tree minv = NULL_TREE, maxv = NULL_TREE;
1157
1158 if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
1159 {
1160 minv = boolean_false_node;
1161 maxv = boolean_true_node;
1162 }
1163 else if (TREE_CODE (type) == ENUMERAL_TYPE
1164 && (flag_sanitize & SANITIZE_ENUM)
1165 && TREE_TYPE (type) != NULL_TREE
1166 && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1167 && (TYPE_PRECISION (TREE_TYPE (type))
1168 < GET_MODE_PRECISION (TYPE_MODE (type))))
1169 {
1170 minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1171 maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1172 }
1173 else
1174 return;
1175
1176 int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
1177 HOST_WIDE_INT bitsize, bitpos;
1178 tree offset;
1179 machine_mode mode;
1180 int volatilep = 0, unsignedp = 0;
1181 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1182 &unsignedp, &volatilep, false);
1183 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1184
1185 if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
1186 || (bitpos % modebitsize) != 0
1187 || bitsize != modebitsize
1188 || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
1189 || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1190 return;
1191
1192 bool can_throw = stmt_could_throw_p (stmt);
1193 location_t loc = gimple_location (stmt);
1194 tree lhs = gimple_assign_lhs (stmt);
1195 tree ptype = build_pointer_type (TREE_TYPE (rhs));
1196 tree atype = reference_alias_ptr_type (rhs);
1197 gimple g = gimple_build_assign (make_ssa_name (ptype),
1198 build_fold_addr_expr (rhs));
1199 gimple_set_location (g, loc);
1200 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1201 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1202 build_int_cst (atype, 0));
1203 tree urhs = make_ssa_name (utype);
1204 if (can_throw)
1205 {
1206 gimple_assign_set_lhs (stmt, urhs);
1207 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1208 gimple_set_location (g, loc);
1209 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1210 gsi_insert_on_edge_immediate (e, g);
1211 gimple_assign_set_rhs_from_tree (gsi, mem);
1212 update_stmt (stmt);
1213 *gsi = gsi_for_stmt (g);
1214 g = stmt;
1215 }
1216 else
1217 {
1218 g = gimple_build_assign (urhs, mem);
1219 gimple_set_location (g, loc);
1220 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1221 }
1222 minv = fold_convert (utype, minv);
1223 maxv = fold_convert (utype, maxv);
1224 if (!integer_zerop (minv))
1225 {
1226 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1227 gimple_set_location (g, loc);
1228 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1229 }
1230
1231 gimple_stmt_iterator gsi2 = *gsi;
1232 basic_block then_bb, fallthru_bb;
1233 *gsi = create_cond_insert_point (gsi, true, false, true,
1234 &then_bb, &fallthru_bb);
1235 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1236 int_const_binop (MINUS_EXPR, maxv, minv),
1237 NULL_TREE, NULL_TREE);
1238 gimple_set_location (g, loc);
1239 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1240
1241 if (!can_throw)
1242 {
1243 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1244 update_stmt (stmt);
1245 }
1246
1247 gsi2 = gsi_after_labels (then_bb);
1248 if (flag_sanitize_undefined_trap_on_error)
1249 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1250 else
1251 {
1252 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1253 ubsan_type_descriptor (type), NULL_TREE,
1254 NULL_TREE);
1255 data = build_fold_addr_expr_loc (loc, data);
1256 enum built_in_function bcode
1257 = (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1258 ? SANITIZE_BOOL : SANITIZE_ENUM))
1259 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1260 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1261 tree fn = builtin_decl_explicit (bcode);
1262
1263 tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
1264 true, NULL_TREE, true,
1265 GSI_SAME_STMT);
1266 g = gimple_build_call (fn, 2, data, val);
1267 }
1268 gimple_set_location (g, loc);
1269 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1270 *gsi = gsi_for_stmt (stmt);
1271 }
1272
1273 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1274 destination, EXPR is floating-point expression. ARG is what to pass
1275 the libubsan call as value, often EXPR itself. */
1276
1277 tree
1278 ubsan_instrument_float_cast (location_t loc, tree type, tree expr, tree arg)
1279 {
1280 tree expr_type = TREE_TYPE (expr);
1281 tree t, tt, fn, min, max;
1282 machine_mode mode = TYPE_MODE (expr_type);
1283 int prec = TYPE_PRECISION (type);
1284 bool uns_p = TYPE_UNSIGNED (type);
1285
1286 /* Float to integer conversion first truncates toward zero, so
1287 even signed char c = 127.875f; is not problematic.
1288 Therefore, we should complain only if EXPR is unordered or smaller
1289 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1290 TYPE_MAX_VALUE + 1.0. */
1291 if (REAL_MODE_FORMAT (mode)->b == 2)
1292 {
1293 /* For maximum, TYPE_MAX_VALUE might not be representable
1294 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1295 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1296 either representable or infinity. */
1297 REAL_VALUE_TYPE maxval = dconst1;
1298 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1299 real_convert (&maxval, mode, &maxval);
1300 max = build_real (expr_type, maxval);
1301
1302 /* For unsigned, assume -1.0 is always representable. */
1303 if (uns_p)
1304 min = build_minus_one_cst (expr_type);
1305 else
1306 {
1307 /* TYPE_MIN_VALUE is generally representable (or -inf),
1308 but TYPE_MIN_VALUE - 1.0 might not be. */
1309 REAL_VALUE_TYPE minval = dconstm1, minval2;
1310 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1311 real_convert (&minval, mode, &minval);
1312 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1313 real_convert (&minval2, mode, &minval2);
1314 if (real_compare (EQ_EXPR, &minval, &minval2)
1315 && !real_isinf (&minval))
1316 {
1317 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1318 rounds to TYPE_MIN_VALUE, we need to subtract
1319 more. As REAL_MODE_FORMAT (mode)->p is the number
1320 of base digits, we want to subtract a number that
1321 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1322 times smaller than minval. */
1323 minval2 = dconst1;
1324 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1325 SET_REAL_EXP (&minval2,
1326 REAL_EXP (&minval2) + prec - 1
1327 - REAL_MODE_FORMAT (mode)->p + 1);
1328 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1329 real_convert (&minval2, mode, &minval2);
1330 }
1331 min = build_real (expr_type, minval2);
1332 }
1333 }
1334 else if (REAL_MODE_FORMAT (mode)->b == 10)
1335 {
1336 /* For _Decimal128 up to 34 decimal digits, - sign,
1337 dot, e, exponent. */
1338 char buf[64];
1339 mpfr_t m;
1340 int p = REAL_MODE_FORMAT (mode)->p;
1341 REAL_VALUE_TYPE maxval, minval;
1342
1343 /* Use mpfr_snprintf rounding to compute the smallest
1344 representable decimal number greater or equal than
1345 1 << (prec - !uns_p). */
1346 mpfr_init2 (m, prec + 2);
1347 mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1348 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1349 decimal_real_from_string (&maxval, buf);
1350 max = build_real (expr_type, maxval);
1351
1352 /* For unsigned, assume -1.0 is always representable. */
1353 if (uns_p)
1354 min = build_minus_one_cst (expr_type);
1355 else
1356 {
1357 /* Use mpfr_snprintf rounding to compute the largest
1358 representable decimal number less or equal than
1359 (-1 << (prec - 1)) - 1. */
1360 mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1361 mpfr_sub_ui (m, m, 1, GMP_RNDN);
1362 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1363 decimal_real_from_string (&minval, buf);
1364 min = build_real (expr_type, minval);
1365 }
1366 mpfr_clear (m);
1367 }
1368 else
1369 return NULL_TREE;
1370
1371 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1372 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1373 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1374 if (integer_zerop (t))
1375 return NULL_TREE;
1376
1377 if (flag_sanitize_undefined_trap_on_error)
1378 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1379 else
1380 {
1381 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1382 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", 0,
1383 NULL, ubsan_type_descriptor (expr_type),
1384 ubsan_type_descriptor (type), NULL_TREE,
1385 NULL_TREE);
1386 enum built_in_function bcode
1387 = (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1388 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1389 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1390 fn = builtin_decl_explicit (bcode);
1391 fn = build_call_expr_loc (loc, fn, 2,
1392 build_fold_addr_expr_loc (loc, data),
1393 ubsan_encode_value (arg, false));
1394 }
1395
1396 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1397 }
1398
1399 /* Instrument values passed to function arguments with nonnull attribute. */
1400
1401 static void
1402 instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1403 {
1404 gimple stmt = gsi_stmt (*gsi);
1405 location_t loc[2];
1406 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1407 while for nonnull sanitization it is clear. */
1408 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1409 flag_delete_null_pointer_checks = 1;
1410 loc[0] = gimple_location (stmt);
1411 loc[1] = UNKNOWN_LOCATION;
1412 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1413 {
1414 tree arg = gimple_call_arg (stmt, i);
1415 if (POINTER_TYPE_P (TREE_TYPE (arg))
1416 && infer_nonnull_range (stmt, arg, false, true))
1417 {
1418 gimple g;
1419 if (!is_gimple_val (arg))
1420 {
1421 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1422 gimple_set_location (g, loc[0]);
1423 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1424 arg = gimple_assign_lhs (g);
1425 }
1426
1427 basic_block then_bb, fallthru_bb;
1428 *gsi = create_cond_insert_point (gsi, true, false, true,
1429 &then_bb, &fallthru_bb);
1430 g = gimple_build_cond (EQ_EXPR, arg,
1431 build_zero_cst (TREE_TYPE (arg)),
1432 NULL_TREE, NULL_TREE);
1433 gimple_set_location (g, loc[0]);
1434 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1435
1436 *gsi = gsi_after_labels (then_bb);
1437 if (flag_sanitize_undefined_trap_on_error)
1438 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1439 else
1440 {
1441 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1442 2, loc, NULL_TREE,
1443 build_int_cst (integer_type_node,
1444 i + 1),
1445 NULL_TREE);
1446 data = build_fold_addr_expr_loc (loc[0], data);
1447 enum built_in_function bcode
1448 = (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1449 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1450 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1451 tree fn = builtin_decl_explicit (bcode);
1452
1453 g = gimple_build_call (fn, 1, data);
1454 }
1455 gimple_set_location (g, loc[0]);
1456 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1457 }
1458 *gsi = gsi_for_stmt (stmt);
1459 }
1460 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1461 }
1462
1463 /* Instrument returns in functions with returns_nonnull attribute. */
1464
1465 static void
1466 instrument_nonnull_return (gimple_stmt_iterator *gsi)
1467 {
1468 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
1469 location_t loc[2];
1470 tree arg = gimple_return_retval (stmt);
1471 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1472 while for nonnull return sanitization it is clear. */
1473 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1474 flag_delete_null_pointer_checks = 1;
1475 loc[0] = gimple_location (stmt);
1476 loc[1] = UNKNOWN_LOCATION;
1477 if (arg
1478 && POINTER_TYPE_P (TREE_TYPE (arg))
1479 && is_gimple_val (arg)
1480 && infer_nonnull_range (stmt, arg, false, true))
1481 {
1482 basic_block then_bb, fallthru_bb;
1483 *gsi = create_cond_insert_point (gsi, true, false, true,
1484 &then_bb, &fallthru_bb);
1485 gimple g = gimple_build_cond (EQ_EXPR, arg,
1486 build_zero_cst (TREE_TYPE (arg)),
1487 NULL_TREE, NULL_TREE);
1488 gimple_set_location (g, loc[0]);
1489 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1490
1491 *gsi = gsi_after_labels (then_bb);
1492 if (flag_sanitize_undefined_trap_on_error)
1493 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1494 else
1495 {
1496 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
1497 2, loc, NULL_TREE, NULL_TREE);
1498 data = build_fold_addr_expr_loc (loc[0], data);
1499 enum built_in_function bcode
1500 = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1501 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN
1502 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT;
1503 tree fn = builtin_decl_explicit (bcode);
1504
1505 g = gimple_build_call (fn, 1, data);
1506 }
1507 gimple_set_location (g, loc[0]);
1508 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1509 *gsi = gsi_for_stmt (stmt);
1510 }
1511 flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1512 }
1513
1514 /* Instrument memory references. Here we check whether the pointer
1515 points to an out-of-bounds location. */
1516
1517 static void
1518 instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
1519 {
1520 gimple stmt = gsi_stmt (*gsi);
1521 location_t loc = gimple_location (stmt);
1522 tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt);
1523 tree type;
1524 tree index = NULL_TREE;
1525 HOST_WIDE_INT size_in_bytes;
1526
1527 type = TREE_TYPE (t);
1528 if (VOID_TYPE_P (type))
1529 return;
1530
1531 switch (TREE_CODE (t))
1532 {
1533 case COMPONENT_REF:
1534 if (TREE_CODE (t) == COMPONENT_REF
1535 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
1536 {
1537 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
1538 t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
1539 repr, NULL_TREE);
1540 }
1541 break;
1542 case ARRAY_REF:
1543 index = TREE_OPERAND (t, 1);
1544 break;
1545 case INDIRECT_REF:
1546 case MEM_REF:
1547 case VAR_DECL:
1548 case PARM_DECL:
1549 case RESULT_DECL:
1550 break;
1551 default:
1552 return;
1553 }
1554
1555 size_in_bytes = int_size_in_bytes (type);
1556 if (size_in_bytes <= 0)
1557 return;
1558
1559 HOST_WIDE_INT bitsize, bitpos;
1560 tree offset;
1561 machine_mode mode;
1562 int volatilep = 0, unsignedp = 0;
1563 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1564 &unsignedp, &volatilep, false);
1565
1566 if (bitpos % BITS_PER_UNIT != 0
1567 || bitsize != size_in_bytes * BITS_PER_UNIT)
1568 return;
1569
1570 bool decl_p = DECL_P (inner);
1571 tree base;
1572 if (decl_p)
1573 base = inner;
1574 else if (TREE_CODE (inner) == MEM_REF)
1575 base = TREE_OPERAND (inner, 0);
1576 else
1577 return;
1578 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
1579
1580 while (TREE_CODE (base) == SSA_NAME)
1581 {
1582 gimple def_stmt = SSA_NAME_DEF_STMT (base);
1583 if (gimple_assign_ssa_name_copy_p (def_stmt)
1584 || (gimple_assign_cast_p (def_stmt)
1585 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
1586 || (is_gimple_assign (def_stmt)
1587 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
1588 {
1589 tree rhs1 = gimple_assign_rhs1 (def_stmt);
1590 if (TREE_CODE (rhs1) == SSA_NAME
1591 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
1592 break;
1593 else
1594 base = rhs1;
1595 }
1596 else
1597 break;
1598 }
1599
1600 if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1601 return;
1602
1603 tree sizet;
1604 tree base_addr = base;
1605 if (decl_p)
1606 base_addr = build1 (ADDR_EXPR,
1607 build_pointer_type (TREE_TYPE (base)), base);
1608 unsigned HOST_WIDE_INT size = compute_builtin_object_size (base_addr, 0);
1609 if (size != (unsigned HOST_WIDE_INT) -1)
1610 sizet = build_int_cst (sizetype, size);
1611 else if (optimize)
1612 {
1613 if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
1614 loc = input_location;
1615 /* Generate __builtin_object_size call. */
1616 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
1617 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
1618 integer_zero_node);
1619 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
1620 GSI_SAME_STMT);
1621 }
1622 else
1623 return;
1624
1625 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
1626 call. */
1627 /* ptr + sizeof (*ptr) - base */
1628 t = fold_build2 (MINUS_EXPR, sizetype,
1629 fold_convert (pointer_sized_int_node, ptr),
1630 fold_convert (pointer_sized_int_node, base_addr));
1631 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
1632
1633 /* Perhaps we can omit the check. */
1634 if (TREE_CODE (t) == INTEGER_CST
1635 && TREE_CODE (sizet) == INTEGER_CST
1636 && tree_int_cst_le (t, sizet))
1637 return;
1638
1639 if (index != NULL_TREE
1640 && TREE_CODE (index) == SSA_NAME
1641 && TREE_CODE (sizet) == INTEGER_CST)
1642 {
1643 gimple def = SSA_NAME_DEF_STMT (index);
1644 if (is_gimple_assign (def)
1645 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
1646 && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
1647 {
1648 tree cst = gimple_assign_rhs2 (def);
1649 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
1650 TYPE_SIZE_UNIT (type));
1651 if (tree_int_cst_sgn (cst) >= 0
1652 && tree_int_cst_lt (cst, sz))
1653 return;
1654 }
1655 }
1656
1657 /* Nope. Emit the check. */
1658 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1659 GSI_SAME_STMT);
1660 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
1661 GSI_SAME_STMT);
1662 tree ckind = build_int_cst (unsigned_char_type_node,
1663 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
1664 gimple g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
1665 ptr, t, sizet, ckind);
1666 gimple_set_location (g, loc);
1667 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1668 }
1669
1670 /* True if we want to play UBSan games in the current function. */
1671
1672 bool
1673 do_ubsan_in_current_function ()
1674 {
1675 return (current_function_decl != NULL_TREE
1676 && !lookup_attribute ("no_sanitize_undefined",
1677 DECL_ATTRIBUTES (current_function_decl)));
1678 }
1679
1680 namespace {
1681
1682 const pass_data pass_data_ubsan =
1683 {
1684 GIMPLE_PASS, /* type */
1685 "ubsan", /* name */
1686 OPTGROUP_NONE, /* optinfo_flags */
1687 TV_TREE_UBSAN, /* tv_id */
1688 ( PROP_cfg | PROP_ssa ), /* properties_required */
1689 0, /* properties_provided */
1690 0, /* properties_destroyed */
1691 0, /* todo_flags_start */
1692 TODO_update_ssa, /* todo_flags_finish */
1693 };
1694
1695 class pass_ubsan : public gimple_opt_pass
1696 {
1697 public:
1698 pass_ubsan (gcc::context *ctxt)
1699 : gimple_opt_pass (pass_data_ubsan, ctxt)
1700 {}
1701
1702 /* opt_pass methods: */
1703 virtual bool gate (function *)
1704 {
1705 return flag_sanitize & (SANITIZE_NULL | SANITIZE_SI_OVERFLOW
1706 | SANITIZE_BOOL | SANITIZE_ENUM
1707 | SANITIZE_ALIGNMENT
1708 | SANITIZE_NONNULL_ATTRIBUTE
1709 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
1710 | SANITIZE_OBJECT_SIZE)
1711 && do_ubsan_in_current_function ();
1712 }
1713
1714 virtual unsigned int execute (function *);
1715
1716 }; // class pass_ubsan
1717
1718 unsigned int
1719 pass_ubsan::execute (function *fun)
1720 {
1721 basic_block bb;
1722 gimple_stmt_iterator gsi;
1723
1724 initialize_sanitizer_builtins ();
1725
1726 FOR_EACH_BB_FN (bb, fun)
1727 {
1728 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
1729 {
1730 gimple stmt = gsi_stmt (gsi);
1731 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
1732 {
1733 gsi_next (&gsi);
1734 continue;
1735 }
1736
1737 if ((flag_sanitize & SANITIZE_SI_OVERFLOW)
1738 && is_gimple_assign (stmt))
1739 instrument_si_overflow (gsi);
1740
1741 if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1742 {
1743 if (gimple_store_p (stmt))
1744 instrument_null (gsi, true);
1745 if (gimple_assign_load_p (stmt))
1746 instrument_null (gsi, false);
1747 }
1748
1749 if (flag_sanitize & (SANITIZE_BOOL | SANITIZE_ENUM)
1750 && gimple_assign_load_p (stmt))
1751 {
1752 instrument_bool_enum_load (&gsi);
1753 bb = gimple_bb (stmt);
1754 }
1755
1756 if ((flag_sanitize & SANITIZE_NONNULL_ATTRIBUTE)
1757 && is_gimple_call (stmt)
1758 && !gimple_call_internal_p (stmt))
1759 {
1760 instrument_nonnull_arg (&gsi);
1761 bb = gimple_bb (stmt);
1762 }
1763
1764 if ((flag_sanitize & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
1765 && gimple_code (stmt) == GIMPLE_RETURN)
1766 {
1767 instrument_nonnull_return (&gsi);
1768 bb = gimple_bb (stmt);
1769 }
1770
1771 if (flag_sanitize & SANITIZE_OBJECT_SIZE)
1772 {
1773 if (gimple_store_p (stmt))
1774 instrument_object_size (&gsi, true);
1775 if (gimple_assign_load_p (stmt))
1776 instrument_object_size (&gsi, false);
1777 }
1778
1779 gsi_next (&gsi);
1780 }
1781 }
1782 return 0;
1783 }
1784
1785 } // anon namespace
1786
1787 gimple_opt_pass *
1788 make_pass_ubsan (gcc::context *ctxt)
1789 {
1790 return new pass_ubsan (ctxt);
1791 }
1792
1793 #include "gt-ubsan.h"