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