1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2023 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
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
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/>. */
23 #include "coretypes.h"
26 #include "c-family/c-common.h"
29 #include "tree-pass.h"
34 #include "tree-pretty-print.h"
35 #include "stor-layout.h"
37 #include "gimple-iterator.h"
42 #include "stringpool.h"
45 #include "gimplify-me.h"
48 #include "tree-object-size.h"
50 #include "gimple-fold.h"
54 #include "langhooks.h"
56 /* Map from a tree to a VAR_DECL tree. */
58 struct GTY((for_user
)) tree_type_map
{
59 struct tree_map_base type
;
63 struct tree_type_map_cache_hasher
: ggc_cache_ptr_hash
<tree_type_map
>
65 static inline hashval_t
66 hash (tree_type_map
*t
)
68 return TYPE_UID (t
->type
.from
);
72 equal (tree_type_map
*a
, tree_type_map
*b
)
74 return a
->type
.from
== b
->type
.from
;
78 keep_cache_entry (tree_type_map
*&m
)
80 return ggc_marked_p (m
->type
.from
);
85 hash_table
<tree_type_map_cache_hasher
> *decl_tree_for_type
;
87 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
90 decl_for_type_lookup (tree type
)
92 /* If the hash table is not initialized yet, create it now. */
93 if (decl_tree_for_type
== NULL
)
96 = hash_table
<tree_type_map_cache_hasher
>::create_ggc (10);
97 /* That also means we don't have to bother with the lookup. */
101 struct tree_type_map
*h
, in
;
104 h
= decl_tree_for_type
->find_with_hash (&in
, TYPE_UID (type
));
105 return h
? h
->decl
: NULL_TREE
;
108 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
111 decl_for_type_insert (tree type
, tree decl
)
113 struct tree_type_map
*h
;
115 h
= ggc_alloc
<tree_type_map
> ();
118 *decl_tree_for_type
->find_slot_with_hash (h
, TYPE_UID (type
), INSERT
) = h
;
121 /* Helper routine, which encodes a value in the pointer_sized_int_node.
122 Arguments with precision <= POINTER_SIZE are passed directly,
123 the rest is passed by reference. T is a value we are to encode.
124 PHASE determines when this function is called. */
127 ubsan_encode_value (tree t
, enum ubsan_encode_value_phase phase
)
129 tree type
= TREE_TYPE (t
);
130 if (TREE_CODE (type
) == BITINT_TYPE
)
132 if (TYPE_PRECISION (type
) <= POINTER_SIZE
)
134 type
= pointer_sized_int_node
;
135 t
= fold_build1 (NOP_EXPR
, type
, t
);
139 scalar_int_mode arith_mode
140 = (targetm
.scalar_mode_supported_p (TImode
) ? TImode
: DImode
);
141 if (TYPE_PRECISION (type
) > GET_MODE_PRECISION (arith_mode
))
142 return build_zero_cst (pointer_sized_int_node
);
144 = build_nonstandard_integer_type (GET_MODE_PRECISION (arith_mode
),
145 TYPE_UNSIGNED (type
));
146 t
= fold_build1 (NOP_EXPR
, type
, t
);
149 scalar_mode mode
= SCALAR_TYPE_MODE (type
);
150 const unsigned int bitsize
= GET_MODE_BITSIZE (mode
);
151 if (bitsize
<= POINTER_SIZE
)
152 switch (TREE_CODE (type
))
157 return fold_build1 (NOP_EXPR
, pointer_sized_int_node
, t
);
160 tree itype
= build_nonstandard_integer_type (bitsize
, true);
161 t
= fold_build1 (VIEW_CONVERT_EXPR
, itype
, t
);
162 return fold_convert (pointer_sized_int_node
, t
);
169 if (!DECL_P (t
) || !TREE_ADDRESSABLE (t
))
171 /* The reason for this is that we don't want to pessimize
172 code by making vars unnecessarily addressable. */
174 if (phase
!= UBSAN_ENCODE_VALUE_GENERIC
)
176 var
= create_tmp_var (type
);
177 mark_addressable (var
);
181 var
= create_tmp_var_raw (type
);
182 TREE_ADDRESSABLE (var
) = 1;
183 DECL_CONTEXT (var
) = current_function_decl
;
185 if (phase
== UBSAN_ENCODE_VALUE_RTL
)
187 rtx mem
= assign_stack_temp_for_type (mode
, GET_MODE_SIZE (mode
),
189 SET_DECL_RTL (var
, mem
);
190 expand_assignment (var
, t
, false);
191 return build_fold_addr_expr (var
);
193 if (phase
!= UBSAN_ENCODE_VALUE_GENERIC
)
195 tree tem
= build2 (MODIFY_EXPR
, void_type_node
, var
, t
);
196 t
= build_fold_addr_expr (var
);
197 return build2 (COMPOUND_EXPR
, TREE_TYPE (t
), tem
, t
);
201 var
= build4 (TARGET_EXPR
, type
, var
, t
, NULL_TREE
, NULL_TREE
);
202 return build_fold_addr_expr (var
);
206 return build_fold_addr_expr (t
);
210 /* Cached ubsan_get_type_descriptor_type () return value. */
211 static GTY(()) tree ubsan_type_descriptor_type
;
214 struct __ubsan_type_descriptor
216 unsigned short __typekind;
217 unsigned short __typeinfo;
223 ubsan_get_type_descriptor_type (void)
225 static const char *field_names
[3]
226 = { "__typekind", "__typeinfo", "__typename" };
229 if (ubsan_type_descriptor_type
)
230 return ubsan_type_descriptor_type
;
232 tree itype
= build_range_type (sizetype
, size_zero_node
, NULL_TREE
);
233 tree flex_arr_type
= build_array_type (char_type_node
, itype
);
235 ret
= make_node (RECORD_TYPE
);
236 for (int i
= 0; i
< 3; i
++)
238 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
239 get_identifier (field_names
[i
]),
240 (i
== 2) ? flex_arr_type
241 : short_unsigned_type_node
);
242 DECL_CONTEXT (fields
[i
]) = ret
;
244 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
246 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
247 get_identifier ("__ubsan_type_descriptor"),
249 DECL_IGNORED_P (type_decl
) = 1;
250 DECL_ARTIFICIAL (type_decl
) = 1;
251 TYPE_FIELDS (ret
) = fields
[0];
252 TYPE_NAME (ret
) = type_decl
;
253 TYPE_STUB_DECL (ret
) = type_decl
;
254 TYPE_ARTIFICIAL (ret
) = 1;
256 ubsan_type_descriptor_type
= ret
;
260 /* Cached ubsan_get_source_location_type () return value. */
261 static GTY(()) tree ubsan_source_location_type
;
264 struct __ubsan_source_location
266 const char *__filename;
268 unsigned int __column;
273 ubsan_get_source_location_type (void)
275 static const char *field_names
[3]
276 = { "__filename", "__line", "__column" };
278 if (ubsan_source_location_type
)
279 return ubsan_source_location_type
;
281 tree const_char_type
= build_qualified_type (char_type_node
,
284 ret
= make_node (RECORD_TYPE
);
285 for (int i
= 0; i
< 3; i
++)
287 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
288 get_identifier (field_names
[i
]),
289 (i
== 0) ? build_pointer_type (const_char_type
)
290 : unsigned_type_node
);
291 DECL_CONTEXT (fields
[i
]) = ret
;
293 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
295 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
296 get_identifier ("__ubsan_source_location"),
298 DECL_IGNORED_P (type_decl
) = 1;
299 DECL_ARTIFICIAL (type_decl
) = 1;
300 TYPE_FIELDS (ret
) = fields
[0];
301 TYPE_NAME (ret
) = type_decl
;
302 TYPE_STUB_DECL (ret
) = type_decl
;
303 TYPE_ARTIFICIAL (ret
) = 1;
305 ubsan_source_location_type
= ret
;
309 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
310 type with its fields filled from a location_t LOC. */
313 ubsan_source_location (location_t loc
)
315 expanded_location xloc
;
316 tree type
= ubsan_get_source_location_type ();
318 xloc
= expand_location (loc
);
320 if (xloc
.file
== NULL
)
322 str
= build_int_cst (ptr_type_node
, 0);
328 /* Fill in the values from LOC. */
329 size_t len
= strlen (xloc
.file
) + 1;
330 str
= build_string (len
, xloc
.file
);
331 TREE_TYPE (str
) = build_array_type_nelts (char_type_node
, len
);
332 TREE_READONLY (str
) = 1;
333 TREE_STATIC (str
) = 1;
334 str
= build_fold_addr_expr (str
);
336 tree ctor
= build_constructor_va (type
, 3, NULL_TREE
, str
, NULL_TREE
,
337 build_int_cst (unsigned_type_node
,
338 xloc
.line
), NULL_TREE
,
339 build_int_cst (unsigned_type_node
,
341 TREE_CONSTANT (ctor
) = 1;
342 TREE_STATIC (ctor
) = 1;
347 /* This routine returns a magic number for TYPE. */
349 static unsigned short
350 get_ubsan_type_info_for_type (tree type
)
352 if (SCALAR_FLOAT_TYPE_P (type
))
353 return tree_to_uhwi (TYPE_SIZE (type
));
354 else if (INTEGRAL_TYPE_P (type
))
356 int prec
= exact_log2 (tree_to_uhwi (TYPE_SIZE (type
)));
357 gcc_assert (prec
!= -1);
358 return (prec
<< 1) | !TYPE_UNSIGNED (type
);
364 /* Counters for internal labels. ubsan_ids[0] for Lubsan_type,
365 ubsan_ids[1] for Lubsan_data labels. */
366 static GTY(()) unsigned int ubsan_ids
[2];
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. */
375 ubsan_type_descriptor (tree type
, enum ubsan_print_style pstyle
)
377 /* See through any typedefs. */
378 type
= TYPE_MAIN_VARIANT (type
);
380 if (pstyle
== UBSAN_PRINT_FORCE_INT
)
382 /* Temporary hack for -fsanitize=shift with _BitInt(129) and more.
383 libubsan crashes if it is not TK_Integer type. */
384 if (TREE_CODE (type
) == BITINT_TYPE
)
386 scalar_int_mode arith_mode
387 = (targetm
.scalar_mode_supported_p (TImode
)
389 if (TYPE_PRECISION (type
) > GET_MODE_PRECISION (arith_mode
))
390 type3
= build_qualified_type (type
, TYPE_QUAL_CONST
);
393 pstyle
= UBSAN_PRINT_NORMAL
;
396 tree decl
= decl_for_type_lookup (type3
);
397 /* It is possible that some of the earlier created DECLs were found
398 unused, in that case they weren't emitted and varpool_node::get
399 returns NULL node on them. But now we really need them. Thus,
401 if (decl
!= NULL_TREE
&& varpool_node::get (decl
))
403 return build_fold_addr_expr (decl
);
406 tree dtype
= ubsan_get_type_descriptor_type ();
408 const char *tname
= NULL
;
409 pretty_printer pretty_name
;
410 unsigned char deref_depth
= 0;
411 unsigned short tkind
, tinfo
;
412 char tname_bitint
[sizeof ("unsigned _BitInt(2147483647)")];
414 /* Get the name of the type, or the name of the pointer type. */
415 if (pstyle
== UBSAN_PRINT_POINTER
)
417 gcc_assert (POINTER_TYPE_P (type
));
418 type2
= TREE_TYPE (type
);
420 /* Remove any '*' operators from TYPE. */
421 while (POINTER_TYPE_P (type2
))
422 deref_depth
++, type2
= TREE_TYPE (type2
);
424 if (TREE_CODE (type2
) == METHOD_TYPE
)
425 type2
= TYPE_METHOD_BASETYPE (type2
);
428 /* If an array, get its type. */
429 type2
= strip_array_types (type2
);
431 if (pstyle
== UBSAN_PRINT_ARRAY
)
433 while (POINTER_TYPE_P (type2
))
434 deref_depth
++, type2
= TREE_TYPE (type2
);
437 if (TYPE_NAME (type2
) != NULL
)
439 if (TREE_CODE (TYPE_NAME (type2
)) == IDENTIFIER_NODE
)
440 tname
= IDENTIFIER_POINTER (TYPE_NAME (type2
));
441 else if (DECL_NAME (TYPE_NAME (type2
)) != NULL
)
442 tname
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2
)));
447 if (TREE_CODE (type2
) == BITINT_TYPE
)
449 snprintf (tname_bitint
, sizeof (tname_bitint
),
450 "%s_BitInt(%d)", TYPE_UNSIGNED (type2
) ? "unsigned " : "",
451 TYPE_PRECISION (type2
));
452 tname
= tname_bitint
;
455 /* We weren't able to determine the type name. */
459 pp_quote (&pretty_name
);
462 if (pstyle
== UBSAN_PRINT_POINTER
)
464 pp_printf (&pretty_name
, "%s%s%s%s%s%s%s",
465 TYPE_VOLATILE (type2
) ? "volatile " : "",
466 TYPE_READONLY (type2
) ? "const " : "",
467 TYPE_RESTRICT (type2
) ? "restrict " : "",
468 TYPE_ATOMIC (type2
) ? "_Atomic " : "",
469 TREE_CODE (type2
) == RECORD_TYPE
471 : TREE_CODE (type2
) == UNION_TYPE
472 ? "union " : "", tname
,
473 deref_depth
== 0 ? "" : " ");
474 while (deref_depth
-- > 0)
475 pp_star (&pretty_name
);
477 else if (pstyle
== UBSAN_PRINT_ARRAY
)
479 /* Pretty print the array dimensions. */
480 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
482 pp_string (&pretty_name
, tname
);
483 pp_space (&pretty_name
);
484 while (deref_depth
-- > 0)
485 pp_star (&pretty_name
);
486 while (TREE_CODE (t
) == ARRAY_TYPE
)
488 pp_left_bracket (&pretty_name
);
489 tree dom
= TYPE_DOMAIN (t
);
491 && TYPE_MAX_VALUE (dom
) != NULL_TREE
492 && TREE_CODE (TYPE_MAX_VALUE (dom
)) == INTEGER_CST
)
494 unsigned HOST_WIDE_INT m
;
495 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom
))
496 && (m
= tree_to_uhwi (TYPE_MAX_VALUE (dom
))) + 1 != 0)
497 pp_unsigned_wide_integer (&pretty_name
, m
+ 1);
499 pp_wide_int (&pretty_name
,
500 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom
)), 1),
501 TYPE_SIGN (TREE_TYPE (dom
)));
504 /* ??? We can't determine the variable name; print VLA unspec. */
505 pp_star (&pretty_name
);
506 pp_right_bracket (&pretty_name
);
510 /* Save the tree with stripped types. */
514 pp_string (&pretty_name
, tname
);
516 pp_quote (&pretty_name
);
518 switch (TREE_CODE (eltype
))
527 /* FIXME: libubsan right now only supports _BitInts which
528 fit into DImode or TImode. */
529 scalar_int_mode arith_mode
= (targetm
.scalar_mode_supported_p (TImode
)
531 if (TYPE_PRECISION (eltype
) <= GET_MODE_PRECISION (arith_mode
))
538 /* FIXME: libubsan right now only supports float, double and
539 long double type formats. */
540 if (TYPE_MODE (eltype
) == TYPE_MODE (float_type_node
)
541 || TYPE_MODE (eltype
) == TYPE_MODE (double_type_node
)
542 || TYPE_MODE (eltype
) == TYPE_MODE (long_double_type_node
))
551 tinfo
= tkind
== 0xffff ? 0 : get_ubsan_type_info_for_type (eltype
);
553 if (pstyle
== UBSAN_PRINT_FORCE_INT
)
556 scalar_int_mode arith_mode
= (targetm
.scalar_mode_supported_p (TImode
)
558 tree t
= lang_hooks
.types
.type_for_mode (arith_mode
,
559 TYPE_UNSIGNED (eltype
));
560 tinfo
= get_ubsan_type_info_for_type (t
);
563 /* Create a new VAR_DECL of type descriptor. */
564 const char *tmp
= pp_formatted_text (&pretty_name
);
565 size_t len
= strlen (tmp
) + 1;
566 tree str
= build_string (len
, tmp
);
567 TREE_TYPE (str
) = build_array_type_nelts (char_type_node
, len
);
568 TREE_READONLY (str
) = 1;
569 TREE_STATIC (str
) = 1;
572 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_type", ubsan_ids
[0]++);
573 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
575 TREE_STATIC (decl
) = 1;
576 TREE_PUBLIC (decl
) = 0;
577 DECL_ARTIFICIAL (decl
) = 1;
578 DECL_IGNORED_P (decl
) = 1;
579 DECL_EXTERNAL (decl
) = 0;
581 = size_binop (PLUS_EXPR
, DECL_SIZE (decl
), TYPE_SIZE (TREE_TYPE (str
)));
582 DECL_SIZE_UNIT (decl
)
583 = size_binop (PLUS_EXPR
, DECL_SIZE_UNIT (decl
),
584 TYPE_SIZE_UNIT (TREE_TYPE (str
)));
586 tree ctor
= build_constructor_va (dtype
, 3, NULL_TREE
,
587 build_int_cst (short_unsigned_type_node
,
589 build_int_cst (short_unsigned_type_node
,
590 tinfo
), NULL_TREE
, str
);
591 TREE_CONSTANT (ctor
) = 1;
592 TREE_STATIC (ctor
) = 1;
593 DECL_INITIAL (decl
) = ctor
;
594 varpool_node::finalize_decl (decl
);
596 /* Save the VAR_DECL into the hash table. */
597 decl_for_type_insert (type3
, decl
);
599 return build_fold_addr_expr (decl
);
602 /* Create a structure for the ubsan library. NAME is a name of the new
603 structure. LOCCNT is number of locations, PLOC points to array of
604 locations. The arguments in ... are of __ubsan_type_descriptor type
605 and there are at most two of them, followed by NULL_TREE, followed
606 by optional extra arguments and another NULL_TREE. */
609 ubsan_create_data (const char *name
, int loccnt
, const location_t
*ploc
, ...)
614 vec
<tree
, va_gc
> *saved_args
= NULL
;
618 /* It is possible that PCH zapped table with definitions of sanitizer
619 builtins. Reinitialize them if needed. */
620 initialize_sanitizer_builtins ();
622 /* Firstly, create a pointer to type descriptor type. */
623 tree td_type
= ubsan_get_type_descriptor_type ();
624 td_type
= build_pointer_type (td_type
);
626 /* Create the structure type. */
627 ret
= make_node (RECORD_TYPE
);
628 for (j
= 0; j
< loccnt
; j
++)
630 gcc_checking_assert (i
< 2);
631 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
632 ubsan_get_source_location_type ());
633 DECL_CONTEXT (fields
[i
]) = ret
;
635 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
639 va_start (args
, ploc
);
640 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
641 i
++, t
= va_arg (args
, tree
))
643 gcc_checking_assert (i
< 4);
644 /* Save the tree arguments for later use. */
645 vec_safe_push (saved_args
, t
);
646 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
648 DECL_CONTEXT (fields
[i
]) = ret
;
650 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
653 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
654 i
++, t
= va_arg (args
, tree
))
656 gcc_checking_assert (i
< 6);
657 /* Save the tree arguments for later use. */
658 vec_safe_push (saved_args
, t
);
659 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
661 DECL_CONTEXT (fields
[i
]) = ret
;
663 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
667 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
668 get_identifier (name
), ret
);
669 DECL_IGNORED_P (type_decl
) = 1;
670 DECL_ARTIFICIAL (type_decl
) = 1;
671 TYPE_FIELDS (ret
) = fields
[0];
672 TYPE_NAME (ret
) = type_decl
;
673 TYPE_STUB_DECL (ret
) = type_decl
;
674 TYPE_ARTIFICIAL (ret
) = 1;
677 /* Now, fill in the type. */
679 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_data", ubsan_ids
[1]++);
680 tree var
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
682 TREE_STATIC (var
) = 1;
683 TREE_PUBLIC (var
) = 0;
684 DECL_ARTIFICIAL (var
) = 1;
685 DECL_IGNORED_P (var
) = 1;
686 DECL_EXTERNAL (var
) = 0;
688 vec
<constructor_elt
, va_gc
> *v
;
690 tree ctor
= build_constructor (ret
, v
);
692 /* If desirable, set the __ubsan_source_location element. */
693 for (j
= 0; j
< loccnt
; j
++)
695 location_t loc
= LOCATION_LOCUS (ploc
[j
]);
696 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, ubsan_source_location (loc
));
699 size_t nelts
= vec_safe_length (saved_args
);
700 for (i
= 0; i
< nelts
; i
++)
702 t
= (*saved_args
)[i
];
703 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, t
);
706 TREE_CONSTANT (ctor
) = 1;
707 TREE_STATIC (ctor
) = 1;
708 DECL_INITIAL (var
) = ctor
;
709 varpool_node::finalize_decl (var
);
714 /* Shared between *build_builtin_unreachable. */
717 sanitize_unreachable_fn (tree
*data
, location_t loc
)
720 bool san
= sanitize_flags_p (SANITIZE_UNREACHABLE
);
722 ? (flag_sanitize_trap
& SANITIZE_UNREACHABLE
)
723 : flag_unreachable_traps
)
725 fn
= builtin_decl_explicit (BUILT_IN_UNREACHABLE_TRAP
);
730 /* Call ubsan_create_data first as it initializes SANITIZER built-ins. */
731 *data
= ubsan_create_data ("__ubsan_unreachable_data", 1, &loc
,
732 NULL_TREE
, NULL_TREE
);
733 fn
= builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE
);
734 *data
= build_fold_addr_expr_loc (loc
, *data
);
738 fn
= builtin_decl_explicit (BUILT_IN_UNREACHABLE
);
744 /* Rewrite a gcall to __builtin_unreachable for -fsanitize=unreachable. Called
745 by the sanopt pass. */
748 ubsan_instrument_unreachable (gimple_stmt_iterator
*gsi
)
750 location_t loc
= gimple_location (gsi_stmt (*gsi
));
751 gimple
*g
= gimple_build_builtin_unreachable (loc
);
752 gsi_replace (gsi
, g
, false);
756 /* Return true if T is a call to a libubsan routine. */
759 is_ubsan_builtin_p (tree t
)
761 return TREE_CODE (t
) == FUNCTION_DECL
762 && fndecl_built_in_p (t
, BUILT_IN_NORMAL
)
763 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t
)),
764 "__builtin___ubsan_", 18) == 0;
767 /* Create a callgraph edge for statement STMT. */
770 ubsan_create_edge (gimple
*stmt
)
772 gcall
*call_stmt
= dyn_cast
<gcall
*> (stmt
);
773 basic_block bb
= gimple_bb (stmt
);
774 cgraph_node
*node
= cgraph_node::get (current_function_decl
);
775 tree decl
= gimple_call_fndecl (call_stmt
);
777 node
->create_edge (cgraph_node::get_create (decl
), call_stmt
, bb
->count
);
780 /* Expand the UBSAN_BOUNDS special builtin function. */
783 ubsan_expand_bounds_ifn (gimple_stmt_iterator
*gsi
)
785 gimple
*stmt
= gsi_stmt (*gsi
);
786 location_t loc
= gimple_location (stmt
);
787 gcc_assert (gimple_call_num_args (stmt
) == 3);
789 /* Pick up the arguments of the UBSAN_BOUNDS call. */
790 tree type
= TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt
, 0)));
791 tree index
= gimple_call_arg (stmt
, 1);
792 tree orig_index
= index
;
793 tree bound
= gimple_call_arg (stmt
, 2);
795 gimple_stmt_iterator gsi_orig
= *gsi
;
797 /* Create condition "if (index >= bound)". */
798 basic_block then_bb
, fallthru_bb
;
799 gimple_stmt_iterator cond_insert_point
800 = create_cond_insert_point (gsi
, false, false, true,
801 &then_bb
, &fallthru_bb
);
802 index
= fold_convert (TREE_TYPE (bound
), index
);
803 index
= force_gimple_operand_gsi (&cond_insert_point
, index
,
805 false, GSI_NEW_STMT
);
806 gimple
*g
= gimple_build_cond (GE_EXPR
, index
, bound
, NULL_TREE
, NULL_TREE
);
807 gimple_set_location (g
, loc
);
808 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
810 /* Generate __ubsan_handle_out_of_bounds call. */
811 *gsi
= gsi_after_labels (then_bb
);
812 if (flag_sanitize_trap
& SANITIZE_BOUNDS
)
813 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
817 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc
,
818 ubsan_type_descriptor (type
, UBSAN_PRINT_ARRAY
),
819 ubsan_type_descriptor (TREE_TYPE (orig_index
)),
820 NULL_TREE
, NULL_TREE
);
821 data
= build_fold_addr_expr_loc (loc
, data
);
822 enum built_in_function bcode
823 = (flag_sanitize_recover
& SANITIZE_BOUNDS
)
824 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
825 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT
;
826 tree fn
= builtin_decl_explicit (bcode
);
827 tree val
= ubsan_encode_value (orig_index
, UBSAN_ENCODE_VALUE_GIMPLE
);
828 val
= force_gimple_operand_gsi (gsi
, val
, true, NULL_TREE
, true,
830 g
= gimple_build_call (fn
, 2, data
, val
);
832 gimple_set_location (g
, loc
);
833 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
835 /* Get rid of the UBSAN_BOUNDS call from the IR. */
836 unlink_stmt_vdef (stmt
);
837 gsi_remove (&gsi_orig
, true);
839 /* Point GSI to next logical statement. */
840 *gsi
= gsi_start_bb (fallthru_bb
);
844 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
845 argument which is a constant, because the middle-end treats pointer
846 conversions as useless and therefore the type of the first argument
847 could be changed to any other pointer type. */
850 ubsan_expand_null_ifn (gimple_stmt_iterator
*gsip
)
852 gimple_stmt_iterator gsi
= *gsip
;
853 gimple
*stmt
= gsi_stmt (gsi
);
854 location_t loc
= gimple_location (stmt
);
855 gcc_assert (gimple_call_num_args (stmt
) == 3);
856 tree ptr
= gimple_call_arg (stmt
, 0);
857 tree ckind
= gimple_call_arg (stmt
, 1);
858 tree align
= gimple_call_arg (stmt
, 2);
859 tree check_align
= NULL_TREE
;
862 basic_block cur_bb
= gsi_bb (gsi
);
865 if (!integer_zerop (align
))
867 unsigned int ptralign
= get_pointer_alignment (ptr
) / BITS_PER_UNIT
;
868 if (compare_tree_int (align
, ptralign
) == 1)
870 check_align
= make_ssa_name (pointer_sized_int_node
);
871 g
= gimple_build_assign (check_align
, NOP_EXPR
, ptr
);
872 gimple_set_location (g
, loc
);
873 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
876 check_null
= sanitize_flags_p (SANITIZE_NULL
);
878 if (check_align
== NULL_TREE
&& !check_null
)
880 gsi_remove (gsip
, true);
881 /* Unlink the UBSAN_NULLs vops before replacing it. */
882 unlink_stmt_vdef (stmt
);
886 /* Split the original block holding the pointer dereference. */
887 edge e
= split_block (cur_bb
, stmt
);
889 /* Get a hold on the 'condition block', the 'then block' and the
891 basic_block cond_bb
= e
->src
;
892 basic_block fallthru_bb
= e
->dest
;
893 basic_block then_bb
= create_empty_bb (cond_bb
);
894 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
895 loops_state_set (LOOPS_NEED_FIXUP
);
897 /* Make an edge coming from the 'cond block' into the 'then block';
898 this edge is unlikely taken, so set up the probability accordingly. */
899 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
900 e
->probability
= profile_probability::very_unlikely ();
901 then_bb
->count
= e
->count ();
903 /* Connect 'then block' with the 'else block'. This is needed
904 as the ubsan routines we call in the 'then block' are not noreturn.
905 The 'then block' only has one outcoming edge. */
906 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
908 /* Set up the fallthrough basic block. */
909 e
= find_edge (cond_bb
, fallthru_bb
);
910 e
->flags
= EDGE_FALSE_VALUE
;
911 e
->probability
= profile_probability::very_likely ();
913 /* Update dominance info for the newly created then_bb; note that
914 fallthru_bb's dominance info has already been updated by
916 if (dom_info_available_p (CDI_DOMINATORS
))
917 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
919 /* Put the ubsan builtin call into the newly created BB. */
920 if (flag_sanitize_trap
& ((check_align
? SANITIZE_ALIGNMENT
+ 0 : 0)
921 | (check_null
? SANITIZE_NULL
+ 0 : 0)))
922 g
= gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP
), 0);
925 enum built_in_function bcode
926 = (flag_sanitize_recover
& ((check_align
? SANITIZE_ALIGNMENT
+ 0 : 0)
927 | (check_null
? SANITIZE_NULL
+ 0 : 0)))
928 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
929 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT
;
930 tree fn
= builtin_decl_implicit (bcode
);
931 int align_log
= tree_log2 (align
);
933 = ubsan_create_data ("__ubsan_null_data", 1, &loc
,
934 ubsan_type_descriptor (TREE_TYPE (ckind
),
935 UBSAN_PRINT_POINTER
),
937 build_int_cst (unsigned_char_type_node
,
939 fold_convert (unsigned_char_type_node
, ckind
),
941 data
= build_fold_addr_expr_loc (loc
, data
);
942 g
= gimple_build_call (fn
, 2, data
,
943 check_align
? check_align
944 : build_zero_cst (pointer_sized_int_node
));
946 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
947 gimple_set_location (g
, loc
);
948 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
950 /* Unlink the UBSAN_NULLs vops before replacing it. */
951 unlink_stmt_vdef (stmt
);
955 g
= gimple_build_cond (EQ_EXPR
, ptr
, build_int_cst (TREE_TYPE (ptr
), 0),
956 NULL_TREE
, NULL_TREE
);
957 gimple_set_location (g
, loc
);
959 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
960 gsi_replace (&gsi
, g
, false);
968 /* Split the block with the condition again. */
969 e
= split_block (cond_bb
, stmt
);
970 basic_block cond1_bb
= e
->src
;
971 basic_block cond2_bb
= e
->dest
;
973 /* Make an edge coming from the 'cond1 block' into the 'then block';
974 this edge is unlikely taken, so set up the probability
976 e
= make_edge (cond1_bb
, then_bb
, EDGE_TRUE_VALUE
);
977 e
->probability
= profile_probability::very_unlikely ();
979 /* Set up the fallthrough basic block. */
980 e
= find_edge (cond1_bb
, cond2_bb
);
981 e
->flags
= EDGE_FALSE_VALUE
;
982 e
->probability
= profile_probability::very_likely ();
984 /* Update dominance info. */
985 if (dom_info_available_p (CDI_DOMINATORS
))
987 set_immediate_dominator (CDI_DOMINATORS
, fallthru_bb
, cond1_bb
);
988 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond1_bb
);
991 gsi2
= gsi_start_bb (cond2_bb
);
994 tree mask
= build_int_cst (pointer_sized_int_node
,
995 tree_to_uhwi (align
) - 1);
996 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
997 BIT_AND_EXPR
, check_align
, mask
);
998 gimple_set_location (g
, loc
);
1000 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
1002 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1004 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
),
1005 build_int_cst (pointer_sized_int_node
, 0),
1006 NULL_TREE
, NULL_TREE
);
1007 gimple_set_location (g
, loc
);
1009 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
1011 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
1012 gsi_replace (&gsi
, g
, false);
1017 #define OBJSZ_MAX_OFFSET (1024 * 16)
1019 /* Expand UBSAN_OBJECT_SIZE internal call. */
1022 ubsan_expand_objsize_ifn (gimple_stmt_iterator
*gsi
)
1024 gimple
*stmt
= gsi_stmt (*gsi
);
1025 location_t loc
= gimple_location (stmt
);
1026 gcc_assert (gimple_call_num_args (stmt
) == 4);
1028 tree ptr
= gimple_call_arg (stmt
, 0);
1029 tree offset
= gimple_call_arg (stmt
, 1);
1030 tree size
= gimple_call_arg (stmt
, 2);
1031 tree ckind
= gimple_call_arg (stmt
, 3);
1032 gimple_stmt_iterator gsi_orig
= *gsi
;
1035 /* See if we can discard the check. */
1036 if (TREE_CODE (size
) == INTEGER_CST
1037 && integer_all_onesp (size
))
1038 /* Yes, __builtin_object_size couldn't determine the
1040 else if (TREE_CODE (offset
) == INTEGER_CST
1041 && wi::to_widest (offset
) >= -OBJSZ_MAX_OFFSET
1042 && wi::to_widest (offset
) <= -1)
1043 /* The offset is in range [-16K, -1]. */;
1046 /* if (offset > objsize) */
1047 basic_block then_bb
, fallthru_bb
;
1048 gimple_stmt_iterator cond_insert_point
1049 = create_cond_insert_point (gsi
, false, false, true,
1050 &then_bb
, &fallthru_bb
);
1051 g
= gimple_build_cond (GT_EXPR
, offset
, size
, NULL_TREE
, NULL_TREE
);
1052 gimple_set_location (g
, loc
);
1053 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1055 /* If the offset is small enough, we don't need the second
1057 if (TREE_CODE (offset
) == INTEGER_CST
1058 && wi::to_widest (offset
) >= 0
1059 && wi::to_widest (offset
) <= OBJSZ_MAX_OFFSET
)
1060 *gsi
= gsi_after_labels (then_bb
);
1063 /* Don't issue run-time error if (ptr > ptr + offset). That
1064 may happen when computing a POINTER_PLUS_EXPR. */
1065 basic_block then2_bb
, fallthru2_bb
;
1067 gimple_stmt_iterator gsi2
= gsi_after_labels (then_bb
);
1068 cond_insert_point
= create_cond_insert_point (&gsi2
, false, false,
1071 /* Convert the pointer to an integer type. */
1072 tree p
= make_ssa_name (pointer_sized_int_node
);
1073 g
= gimple_build_assign (p
, NOP_EXPR
, ptr
);
1074 gimple_set_location (g
, loc
);
1075 gsi_insert_before (&cond_insert_point
, g
, GSI_NEW_STMT
);
1076 p
= gimple_assign_lhs (g
);
1077 /* Compute ptr + offset. */
1078 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1079 PLUS_EXPR
, p
, offset
);
1080 gimple_set_location (g
, loc
);
1081 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1082 /* Now build the conditional and put it into the IR. */
1083 g
= gimple_build_cond (LE_EXPR
, p
, gimple_assign_lhs (g
),
1084 NULL_TREE
, NULL_TREE
);
1085 gimple_set_location (g
, loc
);
1086 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1087 *gsi
= gsi_after_labels (then2_bb
);
1090 /* Generate __ubsan_handle_type_mismatch call. */
1091 if (flag_sanitize_trap
& SANITIZE_OBJECT_SIZE
)
1092 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1096 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc
,
1097 ubsan_type_descriptor (TREE_TYPE (ptr
),
1098 UBSAN_PRINT_POINTER
),
1100 build_zero_cst (unsigned_char_type_node
),
1103 data
= build_fold_addr_expr_loc (loc
, data
);
1104 enum built_in_function bcode
1105 = (flag_sanitize_recover
& SANITIZE_OBJECT_SIZE
)
1106 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
1107 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT
;
1108 tree p
= make_ssa_name (pointer_sized_int_node
);
1109 g
= gimple_build_assign (p
, NOP_EXPR
, ptr
);
1110 gimple_set_location (g
, loc
);
1111 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1112 g
= gimple_build_call (builtin_decl_explicit (bcode
), 2, data
, p
);
1114 gimple_set_location (g
, loc
);
1115 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1117 /* Point GSI to next logical statement. */
1118 *gsi
= gsi_start_bb (fallthru_bb
);
1120 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1121 unlink_stmt_vdef (stmt
);
1122 gsi_remove (&gsi_orig
, true);
1126 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1127 unlink_stmt_vdef (stmt
);
1128 gsi_remove (gsi
, true);
1132 /* Expand UBSAN_PTR internal call. */
1135 ubsan_expand_ptr_ifn (gimple_stmt_iterator
*gsip
)
1137 gimple_stmt_iterator gsi
= *gsip
;
1138 gimple
*stmt
= gsi_stmt (gsi
);
1139 location_t loc
= gimple_location (stmt
);
1140 gcc_assert (gimple_call_num_args (stmt
) == 2);
1141 tree ptr
= gimple_call_arg (stmt
, 0);
1142 tree off
= gimple_call_arg (stmt
, 1);
1144 if (integer_zerop (off
))
1146 gsi_remove (gsip
, true);
1147 unlink_stmt_vdef (stmt
);
1151 basic_block cur_bb
= gsi_bb (gsi
);
1152 tree ptrplusoff
= make_ssa_name (pointer_sized_int_node
);
1153 tree ptri
= make_ssa_name (pointer_sized_int_node
);
1154 int pos_neg
= get_range_pos_neg (off
);
1156 /* Split the original block holding the pointer dereference. */
1157 edge e
= split_block (cur_bb
, stmt
);
1159 /* Get a hold on the 'condition block', the 'then block' and the
1161 basic_block cond_bb
= e
->src
;
1162 basic_block fallthru_bb
= e
->dest
;
1163 basic_block then_bb
= create_empty_bb (cond_bb
);
1164 basic_block cond_pos_bb
= NULL
, cond_neg_bb
= NULL
;
1165 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
1166 loops_state_set (LOOPS_NEED_FIXUP
);
1168 /* Set up the fallthrough basic block. */
1169 e
->flags
= EDGE_FALSE_VALUE
;
1172 e
->probability
= profile_probability::very_likely ();
1174 /* Connect 'then block' with the 'else block'. This is needed
1175 as the ubsan routines we call in the 'then block' are not noreturn.
1176 The 'then block' only has one outcoming edge. */
1177 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
1179 /* Make an edge coming from the 'cond block' into the 'then block';
1180 this edge is unlikely taken, so set up the probability
1182 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
1183 e
->probability
= profile_probability::very_unlikely ();
1184 then_bb
->count
= e
->count ();
1188 e
->probability
= profile_probability::even ();
1190 e
= split_block (fallthru_bb
, (gimple
*) NULL
);
1191 cond_neg_bb
= e
->src
;
1192 fallthru_bb
= e
->dest
;
1193 e
->probability
= profile_probability::very_likely ();
1194 e
->flags
= EDGE_FALSE_VALUE
;
1196 e
= make_edge (cond_neg_bb
, then_bb
, EDGE_TRUE_VALUE
);
1197 e
->probability
= profile_probability::very_unlikely ();
1198 then_bb
->count
= e
->count ();
1200 cond_pos_bb
= create_empty_bb (cond_bb
);
1201 add_bb_to_loop (cond_pos_bb
, cond_bb
->loop_father
);
1203 e
= make_edge (cond_bb
, cond_pos_bb
, EDGE_TRUE_VALUE
);
1204 e
->probability
= profile_probability::even ();
1205 cond_pos_bb
->count
= e
->count ();
1207 e
= make_edge (cond_pos_bb
, then_bb
, EDGE_TRUE_VALUE
);
1208 e
->probability
= profile_probability::very_unlikely ();
1210 e
= make_edge (cond_pos_bb
, fallthru_bb
, EDGE_FALSE_VALUE
);
1211 e
->probability
= profile_probability::very_likely ();
1213 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
1216 gimple
*g
= gimple_build_assign (ptri
, NOP_EXPR
, ptr
);
1217 gimple_set_location (g
, loc
);
1218 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1219 g
= gimple_build_assign (ptrplusoff
, PLUS_EXPR
, ptri
, off
);
1220 gimple_set_location (g
, loc
);
1221 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1223 /* Update dominance info for the newly created then_bb; note that
1224 fallthru_bb's dominance info has already been updated by
1226 if (dom_info_available_p (CDI_DOMINATORS
))
1228 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
1231 set_immediate_dominator (CDI_DOMINATORS
, cond_pos_bb
, cond_bb
);
1232 set_immediate_dominator (CDI_DOMINATORS
, fallthru_bb
, cond_bb
);
1236 /* Put the ubsan builtin call into the newly created BB. */
1237 if (flag_sanitize_trap
& SANITIZE_POINTER_OVERFLOW
)
1238 g
= gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP
), 0);
1241 enum built_in_function bcode
1242 = (flag_sanitize_recover
& SANITIZE_POINTER_OVERFLOW
)
1243 ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
1244 : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT
;
1245 tree fn
= builtin_decl_implicit (bcode
);
1247 = ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc
,
1248 NULL_TREE
, NULL_TREE
);
1249 data
= build_fold_addr_expr_loc (loc
, data
);
1250 g
= gimple_build_call (fn
, 3, data
, ptr
, ptrplusoff
);
1252 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
1253 gimple_set_location (g
, loc
);
1254 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
1256 /* Unlink the UBSAN_PTRs vops before replacing it. */
1257 unlink_stmt_vdef (stmt
);
1259 if (TREE_CODE (off
) == INTEGER_CST
)
1260 g
= gimple_build_cond (wi::neg_p (wi::to_wide (off
)) ? LT_EXPR
: GE_EXPR
,
1261 ptri
, fold_build1 (NEGATE_EXPR
, sizetype
, off
),
1262 NULL_TREE
, NULL_TREE
);
1263 else if (pos_neg
!= 3)
1264 g
= gimple_build_cond (pos_neg
== 1 ? LT_EXPR
: GT_EXPR
,
1265 ptrplusoff
, ptri
, NULL_TREE
, NULL_TREE
);
1268 gsi2
= gsi_start_bb (cond_pos_bb
);
1269 g
= gimple_build_cond (LT_EXPR
, ptrplusoff
, ptri
, NULL_TREE
, NULL_TREE
);
1270 gimple_set_location (g
, loc
);
1271 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
1273 gsi2
= gsi_start_bb (cond_neg_bb
);
1274 g
= gimple_build_cond (GT_EXPR
, ptrplusoff
, ptri
, NULL_TREE
, NULL_TREE
);
1275 gimple_set_location (g
, loc
);
1276 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
1278 tree t
= gimple_build (&gsi
, true, GSI_SAME_STMT
,
1279 loc
, NOP_EXPR
, ssizetype
, off
);
1280 g
= gimple_build_cond (GE_EXPR
, t
, ssize_int (0),
1281 NULL_TREE
, NULL_TREE
);
1283 gimple_set_location (g
, loc
);
1284 /* Replace the UBSAN_PTR with a GIMPLE_COND stmt. */
1285 gsi_replace (&gsi
, g
, false);
1290 /* Cached __ubsan_vptr_type_cache decl. */
1291 static GTY(()) tree ubsan_vptr_type_cache_decl
;
1293 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1294 argument which is a constant, because the middle-end treats pointer
1295 conversions as useless and therefore the type of the first argument
1296 could be changed to any other pointer type. */
1299 ubsan_expand_vptr_ifn (gimple_stmt_iterator
*gsip
)
1301 gimple_stmt_iterator gsi
= *gsip
;
1302 gimple
*stmt
= gsi_stmt (gsi
);
1303 location_t loc
= gimple_location (stmt
);
1304 gcc_assert (gimple_call_num_args (stmt
) == 5);
1305 tree op
= gimple_call_arg (stmt
, 0);
1306 tree vptr
= gimple_call_arg (stmt
, 1);
1307 tree str_hash
= gimple_call_arg (stmt
, 2);
1308 tree ti_decl_addr
= gimple_call_arg (stmt
, 3);
1309 tree ckind_tree
= gimple_call_arg (stmt
, 4);
1310 ubsan_null_ckind ckind
= (ubsan_null_ckind
) tree_to_uhwi (ckind_tree
);
1311 tree type
= TREE_TYPE (TREE_TYPE (ckind_tree
));
1313 basic_block fallthru_bb
= NULL
;
1315 if (ckind
== UBSAN_DOWNCAST_POINTER
)
1317 /* Guard everything with if (op != NULL) { ... }. */
1318 basic_block then_bb
;
1319 gimple_stmt_iterator cond_insert_point
1320 = create_cond_insert_point (gsip
, false, false, true,
1321 &then_bb
, &fallthru_bb
);
1322 g
= gimple_build_cond (NE_EXPR
, op
, build_zero_cst (TREE_TYPE (op
)),
1323 NULL_TREE
, NULL_TREE
);
1324 gimple_set_location (g
, loc
);
1325 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1326 *gsip
= gsi_after_labels (then_bb
);
1327 gsi_remove (&gsi
, false);
1328 gsi_insert_before (gsip
, stmt
, GSI_NEW_STMT
);
1332 tree htype
= TREE_TYPE (str_hash
);
1333 tree cst
= wide_int_to_tree (htype
,
1334 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1336 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1338 gimple_set_location (g
, loc
);
1339 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1340 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1341 gimple_assign_lhs (g
), cst
);
1342 gimple_set_location (g
, loc
);
1343 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1344 tree t1
= gimple_assign_lhs (g
);
1345 g
= gimple_build_assign (make_ssa_name (htype
), LSHIFT_EXPR
,
1346 t1
, build_int_cst (integer_type_node
, 47));
1347 gimple_set_location (g
, loc
);
1348 tree t2
= gimple_assign_lhs (g
);
1349 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1350 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1352 gimple_set_location (g
, loc
);
1353 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1354 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1355 t2
, gimple_assign_lhs (g
));
1356 gimple_set_location (g
, loc
);
1357 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1358 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1359 gimple_assign_lhs (g
), cst
);
1360 gimple_set_location (g
, loc
);
1361 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1362 tree t3
= gimple_assign_lhs (g
);
1363 g
= gimple_build_assign (make_ssa_name (htype
), LSHIFT_EXPR
,
1364 t3
, build_int_cst (integer_type_node
, 47));
1365 gimple_set_location (g
, loc
);
1366 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1367 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1368 t3
, gimple_assign_lhs (g
));
1369 gimple_set_location (g
, loc
);
1370 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1371 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1372 gimple_assign_lhs (g
), cst
);
1373 gimple_set_location (g
, loc
);
1374 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1375 if (!useless_type_conversion_p (pointer_sized_int_node
, htype
))
1377 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1378 NOP_EXPR
, gimple_assign_lhs (g
));
1379 gimple_set_location (g
, loc
);
1380 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1382 tree hash
= gimple_assign_lhs (g
);
1384 if (ubsan_vptr_type_cache_decl
== NULL_TREE
)
1386 tree atype
= build_array_type_nelts (pointer_sized_int_node
, 128);
1387 tree array
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
1388 get_identifier ("__ubsan_vptr_type_cache"),
1390 DECL_ARTIFICIAL (array
) = 1;
1391 DECL_IGNORED_P (array
) = 1;
1392 TREE_PUBLIC (array
) = 1;
1393 TREE_STATIC (array
) = 1;
1394 DECL_EXTERNAL (array
) = 1;
1395 DECL_VISIBILITY (array
) = VISIBILITY_DEFAULT
;
1396 DECL_VISIBILITY_SPECIFIED (array
) = 1;
1397 varpool_node::finalize_decl (array
);
1398 ubsan_vptr_type_cache_decl
= array
;
1401 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1403 build_int_cst (pointer_sized_int_node
, 127));
1404 gimple_set_location (g
, loc
);
1405 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1407 tree c
= build4_loc (loc
, ARRAY_REF
, pointer_sized_int_node
,
1408 ubsan_vptr_type_cache_decl
, gimple_assign_lhs (g
),
1409 NULL_TREE
, NULL_TREE
);
1410 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1412 gimple_set_location (g
, loc
);
1413 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1415 basic_block then_bb
, fallthru2_bb
;
1416 gimple_stmt_iterator cond_insert_point
1417 = create_cond_insert_point (gsip
, false, false, true,
1418 &then_bb
, &fallthru2_bb
);
1419 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
), hash
,
1420 NULL_TREE
, NULL_TREE
);
1421 gimple_set_location (g
, loc
);
1422 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1423 *gsip
= gsi_after_labels (then_bb
);
1424 if (fallthru_bb
== NULL
)
1425 fallthru_bb
= fallthru2_bb
;
1428 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc
,
1429 ubsan_type_descriptor (type
), NULL_TREE
, ti_decl_addr
,
1430 build_int_cst (unsigned_char_type_node
, ckind
),
1432 data
= build_fold_addr_expr_loc (loc
, data
);
1433 enum built_in_function bcode
1434 = (flag_sanitize_recover
& SANITIZE_VPTR
)
1435 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1436 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT
;
1438 g
= gimple_build_call (builtin_decl_explicit (bcode
), 3, data
, op
, hash
);
1439 gimple_set_location (g
, loc
);
1440 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1442 /* Point GSI to next logical statement. */
1443 *gsip
= gsi_start_bb (fallthru_bb
);
1445 /* Get rid of the UBSAN_VPTR call from the IR. */
1446 unlink_stmt_vdef (stmt
);
1447 gsi_remove (&gsi
, true);
1451 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1452 whether the pointer is on the left hand side of the assignment. */
1455 instrument_mem_ref (tree mem
, tree base
, gimple_stmt_iterator
*iter
,
1458 enum ubsan_null_ckind ikind
= is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
;
1459 unsigned int align
= 0;
1460 if (sanitize_flags_p (SANITIZE_ALIGNMENT
))
1462 align
= min_align_of_type (TREE_TYPE (base
));
1466 if (align
== 0 && !sanitize_flags_p (SANITIZE_NULL
))
1468 tree t
= TREE_OPERAND (base
, 0);
1469 if (!POINTER_TYPE_P (TREE_TYPE (t
)))
1471 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base
)) && mem
!= base
)
1472 ikind
= UBSAN_MEMBER_ACCESS
;
1473 tree kind
= build_int_cst (build_pointer_type (TREE_TYPE (base
)), ikind
);
1474 tree alignt
= build_int_cst (pointer_sized_int_node
, align
);
1475 gcall
*g
= gimple_build_call_internal (IFN_UBSAN_NULL
, 3, t
, kind
, alignt
);
1476 gimple_set_location (g
, gimple_location (gsi_stmt (*iter
)));
1477 gsi_insert_before (iter
, g
, GSI_SAME_STMT
);
1480 /* Perform the pointer instrumentation. */
1483 instrument_null (gimple_stmt_iterator gsi
, tree t
, bool is_lhs
)
1485 /* Handle also e.g. &s->i. */
1486 if (TREE_CODE (t
) == ADDR_EXPR
)
1487 t
= TREE_OPERAND (t
, 0);
1488 tree base
= get_base_address (t
);
1489 if (base
!= NULL_TREE
1490 && TREE_CODE (base
) == MEM_REF
1491 && TREE_CODE (TREE_OPERAND (base
, 0)) == SSA_NAME
)
1492 instrument_mem_ref (t
, base
, &gsi
, is_lhs
);
1495 /* Instrument pointer arithmetics PTR p+ OFF. */
1498 instrument_pointer_overflow (gimple_stmt_iterator
*gsi
, tree ptr
, tree off
)
1500 if (TYPE_PRECISION (sizetype
) != POINTER_SIZE
)
1502 gcall
*g
= gimple_build_call_internal (IFN_UBSAN_PTR
, 2, ptr
, off
);
1503 gimple_set_location (g
, gimple_location (gsi_stmt (*gsi
)));
1504 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1507 /* Instrument pointer arithmetics if any. */
1510 maybe_instrument_pointer_overflow (gimple_stmt_iterator
*gsi
, tree t
)
1512 if (TYPE_PRECISION (sizetype
) != POINTER_SIZE
)
1515 /* Handle also e.g. &s->i. */
1516 if (TREE_CODE (t
) == ADDR_EXPR
)
1517 t
= TREE_OPERAND (t
, 0);
1519 if (!handled_component_p (t
) && TREE_CODE (t
) != MEM_REF
)
1522 poly_int64 bitsize
, bitpos
, bytepos
;
1525 int volatilep
= 0, reversep
, unsignedp
= 0;
1526 tree inner
= get_inner_reference (t
, &bitsize
, &bitpos
, &offset
, &mode
,
1527 &unsignedp
, &reversep
, &volatilep
);
1528 tree moff
= NULL_TREE
;
1530 bool decl_p
= DECL_P (inner
);
1535 || TREE_CODE (inner
) == PARM_DECL
1536 || TREE_CODE (inner
) == RESULT_DECL
)
1537 && DECL_REGISTER (inner
))
1540 /* If BASE is a fixed size automatic variable or
1541 global variable defined in the current TU and bitpos
1542 fits, don't instrument anything. */
1543 poly_int64 base_size
;
1544 if (offset
== NULL_TREE
1545 && maybe_ne (bitpos
, 0)
1547 || TREE_CODE (base
) == PARM_DECL
1548 || TREE_CODE (base
) == RESULT_DECL
)
1549 && poly_int_tree_p (DECL_SIZE (base
), &base_size
)
1550 && known_ge (base_size
, bitpos
)
1551 && (!is_global_var (base
) || decl_binds_to_current_def_p (base
)))
1554 else if (TREE_CODE (inner
) == MEM_REF
)
1556 base
= TREE_OPERAND (inner
, 0);
1557 if (TREE_CODE (base
) == ADDR_EXPR
1558 && DECL_P (TREE_OPERAND (base
, 0))
1559 && !TREE_ADDRESSABLE (TREE_OPERAND (base
, 0))
1560 && !is_global_var (TREE_OPERAND (base
, 0)))
1562 moff
= TREE_OPERAND (inner
, 1);
1563 if (integer_zerop (moff
))
1569 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
1571 bytepos
= bits_to_bytes_round_down (bitpos
);
1572 if (offset
== NULL_TREE
&& known_eq (bytepos
, 0) && moff
== NULL_TREE
)
1575 tree base_addr
= base
;
1577 base_addr
= build1 (ADDR_EXPR
,
1578 build_pointer_type (TREE_TYPE (base
)), base
);
1580 if (maybe_ne (bytepos
, 0))
1583 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (t
), t
,
1584 build_int_cst (TREE_TYPE (t
), bytepos
));
1586 t
= size_int (bytepos
);
1591 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (t
), t
,
1592 fold_convert (TREE_TYPE (t
), moff
));
1594 t
= fold_convert (sizetype
, moff
);
1596 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
1598 base_addr
= force_gimple_operand_gsi (gsi
, base_addr
, true, NULL_TREE
, true,
1600 instrument_pointer_overflow (gsi
, base_addr
, t
);
1603 /* Build an ubsan builtin call for the signed-integer-overflow
1604 sanitization. CODE says what kind of builtin are we building,
1605 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1606 are operands of the binary operation. */
1609 ubsan_build_overflow_builtin (tree_code code
, location_t loc
, tree lhstype
,
1610 tree op0
, tree op1
, tree
*datap
)
1612 if (flag_sanitize_trap
& SANITIZE_SI_OVERFLOW
)
1613 return build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1616 if (datap
&& *datap
)
1619 data
= ubsan_create_data ("__ubsan_overflow_data", 1, &loc
,
1620 ubsan_type_descriptor (lhstype
), NULL_TREE
,
1624 enum built_in_function fn_code
;
1629 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1630 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1631 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT
;
1634 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1635 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1636 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT
;
1639 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1640 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1641 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT
;
1644 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1645 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1646 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT
;
1651 tree fn
= builtin_decl_explicit (fn_code
);
1652 return build_call_expr_loc (loc
, fn
, 2 + (code
!= NEGATE_EXPR
),
1653 build_fold_addr_expr_loc (loc
, data
),
1654 ubsan_encode_value (op0
, UBSAN_ENCODE_VALUE_RTL
),
1656 ? ubsan_encode_value (op1
,
1657 UBSAN_ENCODE_VALUE_RTL
)
1661 /* Perform the signed integer instrumentation. GSI is the iterator
1662 pointing at statement we are trying to instrument. */
1665 instrument_si_overflow (gimple_stmt_iterator gsi
)
1667 gimple
*stmt
= gsi_stmt (gsi
);
1668 tree_code code
= gimple_assign_rhs_code (stmt
);
1669 tree lhs
= gimple_assign_lhs (stmt
);
1670 tree lhstype
= TREE_TYPE (lhs
);
1671 tree lhsinner
= VECTOR_TYPE_P (lhstype
) ? TREE_TYPE (lhstype
) : lhstype
;
1675 /* If this is not a signed operation, don't instrument anything here.
1676 Also punt on bit-fields. */
1677 if (!INTEGRAL_TYPE_P (lhsinner
)
1678 || TYPE_OVERFLOW_WRAPS (lhsinner
)
1679 || (TREE_CODE (lhsinner
) != BITINT_TYPE
1680 && maybe_ne (GET_MODE_BITSIZE (TYPE_MODE (lhsinner
)),
1681 TYPE_PRECISION (lhsinner
))))
1692 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1693 a
= gimple_assign_rhs1 (stmt
);
1694 b
= gimple_assign_rhs2 (stmt
);
1695 g
= gimple_build_call_internal (code
== PLUS_EXPR
1696 ? IFN_UBSAN_CHECK_ADD
1697 : code
== MINUS_EXPR
1698 ? IFN_UBSAN_CHECK_SUB
1699 : IFN_UBSAN_CHECK_MUL
, 2, a
, b
);
1700 gimple_call_set_lhs (g
, lhs
);
1701 gsi_replace (&gsi
, g
, true);
1704 /* Represent i = -u;
1706 i = UBSAN_CHECK_SUB (0, u); */
1707 a
= build_zero_cst (lhstype
);
1708 b
= gimple_assign_rhs1 (stmt
);
1709 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1710 gimple_call_set_lhs (g
, lhs
);
1711 gsi_replace (&gsi
, g
, true);
1714 /* Transform i = ABS_EXPR<u>;
1716 _N = UBSAN_CHECK_SUB (0, u);
1717 i = ABS_EXPR<_N>; */
1718 a
= build_zero_cst (lhstype
);
1719 b
= gimple_assign_rhs1 (stmt
);
1720 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1721 a
= make_ssa_name (lhstype
);
1722 gimple_call_set_lhs (g
, a
);
1723 gimple_set_location (g
, gimple_location (stmt
));
1724 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1725 gimple_assign_set_rhs1 (stmt
, a
);
1733 /* Instrument loads from (non-bitfield) bool and C++ enum values
1734 to check if the memory value is outside of the range of the valid
1738 instrument_bool_enum_load (gimple_stmt_iterator
*gsi
)
1740 gimple
*stmt
= gsi_stmt (*gsi
);
1741 tree rhs
= gimple_assign_rhs1 (stmt
);
1742 tree type
= TREE_TYPE (rhs
);
1743 tree minv
= NULL_TREE
, maxv
= NULL_TREE
;
1745 if (TREE_CODE (type
) == BOOLEAN_TYPE
1746 && sanitize_flags_p (SANITIZE_BOOL
))
1748 minv
= boolean_false_node
;
1749 maxv
= boolean_true_node
;
1751 else if (TREE_CODE (type
) == ENUMERAL_TYPE
1752 && sanitize_flags_p (SANITIZE_ENUM
)
1753 && TREE_TYPE (type
) != NULL_TREE
1754 && TREE_CODE (TREE_TYPE (type
)) == INTEGER_TYPE
1755 && (TYPE_PRECISION (TREE_TYPE (type
))
1756 < GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (type
))))
1758 minv
= TYPE_MIN_VALUE (TREE_TYPE (type
));
1759 maxv
= TYPE_MAX_VALUE (TREE_TYPE (type
));
1764 int modebitsize
= GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type
));
1765 poly_int64 bitsize
, bitpos
;
1768 int volatilep
= 0, reversep
, unsignedp
= 0;
1769 tree base
= get_inner_reference (rhs
, &bitsize
, &bitpos
, &offset
, &mode
,
1770 &unsignedp
, &reversep
, &volatilep
);
1771 tree utype
= build_nonstandard_integer_type (modebitsize
, 1);
1773 if ((VAR_P (base
) && DECL_HARD_REGISTER (base
))
1774 || !multiple_p (bitpos
, modebitsize
)
1775 || maybe_ne (bitsize
, modebitsize
)
1776 || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (utype
)) != modebitsize
1777 || TREE_CODE (gimple_assign_lhs (stmt
)) != SSA_NAME
)
1780 bool ends_bb
= stmt_ends_bb_p (stmt
);
1781 location_t loc
= gimple_location (stmt
);
1782 tree lhs
= gimple_assign_lhs (stmt
);
1783 tree ptype
= build_pointer_type (TREE_TYPE (rhs
));
1784 tree atype
= reference_alias_ptr_type (rhs
);
1785 gimple
*g
= gimple_build_assign (make_ssa_name (ptype
),
1786 build_fold_addr_expr (rhs
));
1787 gimple_set_location (g
, loc
);
1788 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1789 tree mem
= build2 (MEM_REF
, utype
, gimple_assign_lhs (g
),
1790 build_int_cst (atype
, 0));
1791 tree urhs
= make_ssa_name (utype
);
1794 gimple_assign_set_lhs (stmt
, urhs
);
1795 g
= gimple_build_assign (lhs
, NOP_EXPR
, urhs
);
1796 gimple_set_location (g
, loc
);
1797 edge e
= find_fallthru_edge (gimple_bb (stmt
)->succs
);
1798 gsi_insert_on_edge_immediate (e
, g
);
1799 gimple_assign_set_rhs_from_tree (gsi
, mem
);
1801 *gsi
= gsi_for_stmt (g
);
1806 g
= gimple_build_assign (urhs
, mem
);
1807 gimple_set_location (g
, loc
);
1808 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1810 minv
= fold_convert (utype
, minv
);
1811 maxv
= fold_convert (utype
, maxv
);
1812 if (!integer_zerop (minv
))
1814 g
= gimple_build_assign (make_ssa_name (utype
), MINUS_EXPR
, urhs
, minv
);
1815 gimple_set_location (g
, loc
);
1816 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1819 gimple_stmt_iterator gsi2
= *gsi
;
1820 basic_block then_bb
, fallthru_bb
;
1821 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1822 &then_bb
, &fallthru_bb
);
1823 g
= gimple_build_cond (GT_EXPR
, gimple_assign_lhs (g
),
1824 int_const_binop (MINUS_EXPR
, maxv
, minv
),
1825 NULL_TREE
, NULL_TREE
);
1826 gimple_set_location (g
, loc
);
1827 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1831 gimple_assign_set_rhs_with_ops (&gsi2
, NOP_EXPR
, urhs
);
1835 gsi2
= gsi_after_labels (then_bb
);
1836 if (flag_sanitize_trap
& (TREE_CODE (type
) == BOOLEAN_TYPE
1837 ? SANITIZE_BOOL
: SANITIZE_ENUM
))
1838 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1841 tree data
= ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc
,
1842 ubsan_type_descriptor (type
), NULL_TREE
,
1844 data
= build_fold_addr_expr_loc (loc
, data
);
1845 enum built_in_function bcode
1846 = (flag_sanitize_recover
& (TREE_CODE (type
) == BOOLEAN_TYPE
1847 ? SANITIZE_BOOL
: SANITIZE_ENUM
))
1848 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1849 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT
;
1850 tree fn
= builtin_decl_explicit (bcode
);
1852 tree val
= ubsan_encode_value (urhs
, UBSAN_ENCODE_VALUE_GIMPLE
);
1853 val
= force_gimple_operand_gsi (&gsi2
, val
, true, NULL_TREE
, true,
1855 g
= gimple_build_call (fn
, 2, data
, val
);
1857 gimple_set_location (g
, loc
);
1858 gsi_insert_before (&gsi2
, g
, GSI_SAME_STMT
);
1859 ubsan_create_edge (g
);
1860 *gsi
= gsi_for_stmt (stmt
);
1863 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1864 new style handlers. Libubsan uses heuristics to destinguish between old and
1865 new styles and relies on these properties for filename:
1867 a) Location's filename must not be NULL.
1868 b) Location's filename must not be equal to "".
1869 c) Location's filename must not be equal to "\1".
1870 d) First two bytes of filename must not contain '\xff' symbol. */
1873 ubsan_use_new_style_p (location_t loc
)
1875 if (loc
== UNKNOWN_LOCATION
)
1878 expanded_location xloc
= expand_location (loc
);
1879 if (xloc
.file
== NULL
|| startswith (xloc
.file
, "\1")
1880 || xloc
.file
[0] == '\0' || xloc
.file
[0] == '\xff'
1881 || xloc
.file
[1] == '\xff')
1887 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1888 destination, EXPR is floating-point expression. */
1891 ubsan_instrument_float_cast (location_t loc
, tree type
, tree expr
)
1893 tree expr_type
= TREE_TYPE (expr
);
1894 tree t
, tt
, fn
, min
, max
;
1895 machine_mode mode
= TYPE_MODE (expr_type
);
1896 int prec
= TYPE_PRECISION (type
);
1897 bool uns_p
= TYPE_UNSIGNED (type
);
1898 if (loc
== UNKNOWN_LOCATION
)
1899 loc
= input_location
;
1901 /* Float to integer conversion first truncates toward zero, so
1902 even signed char c = 127.875f; is not problematic.
1903 Therefore, we should complain only if EXPR is unordered or smaller
1904 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1905 TYPE_MAX_VALUE + 1.0. */
1906 if (REAL_MODE_FORMAT (mode
)->b
== 2)
1908 /* For maximum, TYPE_MAX_VALUE might not be representable
1909 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1910 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1911 either representable or infinity. */
1912 REAL_VALUE_TYPE maxval
= dconst1
;
1913 SET_REAL_EXP (&maxval
, REAL_EXP (&maxval
) + prec
- !uns_p
);
1914 real_convert (&maxval
, mode
, &maxval
);
1915 max
= build_real (expr_type
, maxval
);
1917 /* For unsigned, assume -1.0 is always representable. */
1919 min
= build_minus_one_cst (expr_type
);
1922 /* TYPE_MIN_VALUE is generally representable (or -inf),
1923 but TYPE_MIN_VALUE - 1.0 might not be. */
1924 REAL_VALUE_TYPE minval
= dconstm1
, minval2
;
1925 SET_REAL_EXP (&minval
, REAL_EXP (&minval
) + prec
- 1);
1926 real_convert (&minval
, mode
, &minval
);
1927 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &dconst1
);
1928 real_convert (&minval2
, mode
, &minval2
);
1929 if (real_compare (EQ_EXPR
, &minval
, &minval2
)
1930 && !real_isinf (&minval
))
1932 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1933 rounds to TYPE_MIN_VALUE, we need to subtract
1934 more. As REAL_MODE_FORMAT (mode)->p is the number
1935 of base digits, we want to subtract a number that
1936 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1937 times smaller than minval. */
1939 gcc_assert (prec
> REAL_MODE_FORMAT (mode
)->p
);
1940 SET_REAL_EXP (&minval2
,
1941 REAL_EXP (&minval2
) + prec
- 1
1942 - REAL_MODE_FORMAT (mode
)->p
+ 1);
1943 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &minval2
);
1944 real_convert (&minval2
, mode
, &minval2
);
1946 min
= build_real (expr_type
, minval2
);
1949 else if (REAL_MODE_FORMAT (mode
)->b
== 10)
1951 /* For _Decimal128 up to 34 decimal digits, - sign,
1952 dot, e, exponent. */
1954 int p
= REAL_MODE_FORMAT (mode
)->p
;
1955 REAL_VALUE_TYPE maxval
, minval
;
1957 /* Use mpfr_snprintf rounding to compute the smallest
1958 representable decimal number greater or equal than
1959 1 << (prec - !uns_p). */
1960 auto_mpfr
m (prec
+ 2);
1961 mpfr_set_ui_2exp (m
, 1, prec
- !uns_p
, MPFR_RNDN
);
1962 mpfr_snprintf (buf
, sizeof buf
, "%.*RUe", p
- 1, (mpfr_srcptr
) m
);
1963 decimal_real_from_string (&maxval
, buf
);
1964 max
= build_real (expr_type
, maxval
);
1966 /* For unsigned, assume -1.0 is always representable. */
1968 min
= build_minus_one_cst (expr_type
);
1971 /* Use mpfr_snprintf rounding to compute the largest
1972 representable decimal number less or equal than
1973 (-1 << (prec - 1)) - 1. */
1974 mpfr_set_si_2exp (m
, -1, prec
- 1, MPFR_RNDN
);
1975 mpfr_sub_ui (m
, m
, 1, MPFR_RNDN
);
1976 mpfr_snprintf (buf
, sizeof buf
, "%.*RDe", p
- 1, (mpfr_srcptr
) m
);
1977 decimal_real_from_string (&minval
, buf
);
1978 min
= build_real (expr_type
, minval
);
1984 if (HONOR_NANS (mode
))
1986 t
= fold_build2 (UNLE_EXPR
, boolean_type_node
, expr
, min
);
1987 tt
= fold_build2 (UNGE_EXPR
, boolean_type_node
, expr
, max
);
1991 t
= fold_build2 (LE_EXPR
, boolean_type_node
, expr
, min
);
1992 tt
= fold_build2 (GE_EXPR
, boolean_type_node
, expr
, max
);
1994 t
= fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
, tt
);
1995 if (integer_zerop (t
))
1998 if (flag_sanitize_trap
& SANITIZE_FLOAT_CAST
)
1999 fn
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2002 location_t
*loc_ptr
= NULL
;
2003 unsigned num_locations
= 0;
2004 /* Figure out if we can propagate location to ubsan_data and use new
2005 style handlers in libubsan. */
2006 if (ubsan_use_new_style_p (loc
))
2011 /* Create the __ubsan_handle_float_cast_overflow fn call. */
2012 tree data
= ubsan_create_data ("__ubsan_float_cast_overflow_data",
2013 num_locations
, loc_ptr
,
2014 ubsan_type_descriptor (expr_type
),
2015 ubsan_type_descriptor (type
), NULL_TREE
,
2017 enum built_in_function bcode
2018 = (flag_sanitize_recover
& SANITIZE_FLOAT_CAST
)
2019 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
2020 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT
;
2021 fn
= builtin_decl_explicit (bcode
);
2022 fn
= build_call_expr_loc (loc
, fn
, 2,
2023 build_fold_addr_expr_loc (loc
, data
),
2024 ubsan_encode_value (expr
));
2027 return fold_build3 (COND_EXPR
, void_type_node
, t
, fn
, integer_zero_node
);
2030 /* Instrument values passed to function arguments with nonnull attribute. */
2033 instrument_nonnull_arg (gimple_stmt_iterator
*gsi
)
2035 gimple
*stmt
= gsi_stmt (*gsi
);
2037 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
2038 while for nonnull sanitization it is clear. */
2039 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
2040 flag_delete_null_pointer_checks
= 1;
2041 loc
[0] = gimple_location (stmt
);
2042 loc
[1] = UNKNOWN_LOCATION
;
2043 for (unsigned int i
= 0; i
< gimple_call_num_args (stmt
); i
++)
2045 tree arg
= gimple_call_arg (stmt
, i
);
2046 if (POINTER_TYPE_P (TREE_TYPE (arg
))
2047 && infer_nonnull_range_by_attribute (stmt
, arg
))
2050 if (!is_gimple_val (arg
))
2052 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
)), arg
);
2053 gimple_set_location (g
, loc
[0]);
2054 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2055 arg
= gimple_assign_lhs (g
);
2058 basic_block then_bb
, fallthru_bb
;
2059 *gsi
= create_cond_insert_point (gsi
, true, false, true,
2060 &then_bb
, &fallthru_bb
);
2061 g
= gimple_build_cond (EQ_EXPR
, arg
,
2062 build_zero_cst (TREE_TYPE (arg
)),
2063 NULL_TREE
, NULL_TREE
);
2064 gimple_set_location (g
, loc
[0]);
2065 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
2067 *gsi
= gsi_after_labels (then_bb
);
2068 if (flag_sanitize_trap
& SANITIZE_NONNULL_ATTRIBUTE
)
2069 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2072 tree data
= ubsan_create_data ("__ubsan_nonnull_arg_data",
2074 build_int_cst (integer_type_node
,
2077 data
= build_fold_addr_expr_loc (loc
[0], data
);
2078 enum built_in_function bcode
2079 = (flag_sanitize_recover
& SANITIZE_NONNULL_ATTRIBUTE
)
2080 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
2081 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT
;
2082 tree fn
= builtin_decl_explicit (bcode
);
2084 g
= gimple_build_call (fn
, 1, data
);
2086 gimple_set_location (g
, loc
[0]);
2087 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2088 ubsan_create_edge (g
);
2090 *gsi
= gsi_for_stmt (stmt
);
2092 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
2095 /* Instrument returns in functions with returns_nonnull attribute. */
2098 instrument_nonnull_return (gimple_stmt_iterator
*gsi
)
2100 greturn
*stmt
= as_a
<greturn
*> (gsi_stmt (*gsi
));
2102 tree arg
= gimple_return_retval (stmt
);
2103 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
2104 while for nonnull return sanitization it is clear. */
2105 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
2106 flag_delete_null_pointer_checks
= 1;
2107 loc
[0] = gimple_location (stmt
);
2108 loc
[1] = UNKNOWN_LOCATION
;
2110 && POINTER_TYPE_P (TREE_TYPE (arg
))
2111 && is_gimple_val (arg
)
2112 && infer_nonnull_range_by_attribute (stmt
, arg
))
2114 basic_block then_bb
, fallthru_bb
;
2115 *gsi
= create_cond_insert_point (gsi
, true, false, true,
2116 &then_bb
, &fallthru_bb
);
2117 gimple
*g
= gimple_build_cond (EQ_EXPR
, arg
,
2118 build_zero_cst (TREE_TYPE (arg
)),
2119 NULL_TREE
, NULL_TREE
);
2120 gimple_set_location (g
, loc
[0]);
2121 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
2123 *gsi
= gsi_after_labels (then_bb
);
2124 if (flag_sanitize_trap
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
2125 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2128 tree data
= ubsan_create_data ("__ubsan_nonnull_return_data",
2129 1, &loc
[1], NULL_TREE
, NULL_TREE
);
2130 data
= build_fold_addr_expr_loc (loc
[0], data
);
2131 tree data2
= ubsan_create_data ("__ubsan_nonnull_return_data",
2132 1, &loc
[0], NULL_TREE
, NULL_TREE
);
2133 data2
= build_fold_addr_expr_loc (loc
[0], data2
);
2134 enum built_in_function bcode
2135 = (flag_sanitize_recover
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
2136 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1
2137 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT
;
2138 tree fn
= builtin_decl_explicit (bcode
);
2140 g
= gimple_build_call (fn
, 2, data
, data2
);
2142 gimple_set_location (g
, loc
[0]);
2143 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2144 ubsan_create_edge (g
);
2145 *gsi
= gsi_for_stmt (stmt
);
2147 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
2150 /* Instrument memory references. Here we check whether the pointer
2151 points to an out-of-bounds location. */
2154 instrument_object_size (gimple_stmt_iterator
*gsi
, tree t
, bool is_lhs
)
2156 gimple
*stmt
= gsi_stmt (*gsi
);
2157 location_t loc
= gimple_location (stmt
);
2159 tree index
= NULL_TREE
;
2160 HOST_WIDE_INT size_in_bytes
;
2162 type
= TREE_TYPE (t
);
2163 if (VOID_TYPE_P (type
))
2166 switch (TREE_CODE (t
))
2169 if (TREE_CODE (t
) == COMPONENT_REF
2170 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1)) != NULL_TREE
)
2172 tree repr
= DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1));
2173 t
= build3 (COMPONENT_REF
, TREE_TYPE (repr
), TREE_OPERAND (t
, 0),
2174 repr
, TREE_OPERAND (t
, 2));
2178 index
= TREE_OPERAND (t
, 1);
2190 size_in_bytes
= int_size_in_bytes (type
);
2191 if (size_in_bytes
<= 0)
2194 poly_int64 bitsize
, bitpos
;
2197 int volatilep
= 0, reversep
, unsignedp
= 0;
2198 tree inner
= get_inner_reference (t
, &bitsize
, &bitpos
, &offset
, &mode
,
2199 &unsignedp
, &reversep
, &volatilep
);
2201 if (!multiple_p (bitpos
, BITS_PER_UNIT
)
2202 || maybe_ne (bitsize
, size_in_bytes
* BITS_PER_UNIT
))
2205 bool decl_p
= DECL_P (inner
);
2210 || TREE_CODE (inner
) == PARM_DECL
2211 || TREE_CODE (inner
) == RESULT_DECL
)
2212 && DECL_REGISTER (inner
))
2214 if (t
== inner
&& !is_global_var (t
))
2218 else if (TREE_CODE (inner
) == MEM_REF
)
2219 base
= TREE_OPERAND (inner
, 0);
2222 tree ptr
= build1 (ADDR_EXPR
, build_pointer_type (TREE_TYPE (t
)), t
);
2224 while (TREE_CODE (base
) == SSA_NAME
)
2226 gimple
*def_stmt
= SSA_NAME_DEF_STMT (base
);
2227 if (gimple_assign_ssa_name_copy_p (def_stmt
)
2228 || (gimple_assign_cast_p (def_stmt
)
2229 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt
))))
2230 || (is_gimple_assign (def_stmt
)
2231 && gimple_assign_rhs_code (def_stmt
) == POINTER_PLUS_EXPR
))
2233 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
2234 if (TREE_CODE (rhs1
) == SSA_NAME
2235 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1
))
2244 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
2248 tree base_addr
= base
;
2249 gimple
*bos_stmt
= NULL
;
2251 base_addr
= build1 (ADDR_EXPR
,
2252 build_pointer_type (TREE_TYPE (base
)), base
);
2253 if (compute_builtin_object_size (base_addr
, OST_DYNAMIC
, &sizet
))
2257 if (LOCATION_LOCUS (loc
) == UNKNOWN_LOCATION
)
2258 loc
= input_location
;
2259 /* Generate __builtin_dynamic_object_size call. */
2260 sizet
= builtin_decl_explicit (BUILT_IN_DYNAMIC_OBJECT_SIZE
);
2261 sizet
= build_call_expr_loc (loc
, sizet
, 2, base_addr
,
2263 sizet
= force_gimple_operand_gsi (gsi
, sizet
, false, NULL_TREE
, true,
2265 /* If the call above didn't end up being an integer constant, go one
2266 statement back and get the __builtin_object_size stmt. Save it,
2267 we might need it later. */
2268 if (SSA_VAR_P (sizet
))
2271 bos_stmt
= gsi_stmt (*gsi
);
2273 /* Move on to where we were. */
2280 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
2282 /* ptr + sizeof (*ptr) - base */
2283 t
= fold_build2 (MINUS_EXPR
, sizetype
,
2284 fold_convert (pointer_sized_int_node
, ptr
),
2285 fold_convert (pointer_sized_int_node
, base_addr
));
2286 t
= fold_build2 (PLUS_EXPR
, sizetype
, t
, TYPE_SIZE_UNIT (type
));
2288 /* Perhaps we can omit the check. */
2289 if (TREE_CODE (t
) == INTEGER_CST
2290 && TREE_CODE (sizet
) == INTEGER_CST
2291 && tree_int_cst_le (t
, sizet
))
2294 if (index
!= NULL_TREE
2295 && TREE_CODE (index
) == SSA_NAME
2296 && TREE_CODE (sizet
) == INTEGER_CST
)
2298 gimple
*def
= SSA_NAME_DEF_STMT (index
);
2299 if (is_gimple_assign (def
)
2300 && gimple_assign_rhs_code (def
) == BIT_AND_EXPR
2301 && TREE_CODE (gimple_assign_rhs2 (def
)) == INTEGER_CST
)
2303 tree cst
= gimple_assign_rhs2 (def
);
2304 tree sz
= fold_build2 (EXACT_DIV_EXPR
, sizetype
, sizet
,
2305 TYPE_SIZE_UNIT (type
));
2306 if (tree_int_cst_sgn (cst
) >= 0
2307 && tree_int_cst_lt (cst
, sz
))
2313 && decl_function_context (base
) == current_function_decl
2314 && !TREE_ADDRESSABLE (base
))
2315 mark_addressable (base
);
2318 && gimple_call_builtin_p (bos_stmt
, BUILT_IN_DYNAMIC_OBJECT_SIZE
))
2319 ubsan_create_edge (bos_stmt
);
2321 /* We have to emit the check. */
2322 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
2324 ptr
= force_gimple_operand_gsi (gsi
, ptr
, true, NULL_TREE
, true,
2326 tree ckind
= build_int_cst (unsigned_char_type_node
,
2327 is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
);
2328 gimple
*g
= gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE
, 4,
2329 ptr
, t
, sizet
, ckind
);
2330 gimple_set_location (g
, loc
);
2331 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2334 /* Instrument values passed to builtin functions. */
2337 instrument_builtin (gimple_stmt_iterator
*gsi
)
2339 gimple
*stmt
= gsi_stmt (*gsi
);
2340 location_t loc
= gimple_location (stmt
);
2342 enum built_in_function fcode
2343 = DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
));
2347 CASE_INT_FN (BUILT_IN_CLZ
):
2350 CASE_INT_FN (BUILT_IN_CTZ
):
2351 arg
= gimple_call_arg (stmt
, 0);
2352 if (!integer_nonzerop (arg
))
2355 if (!is_gimple_val (arg
))
2357 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
)), arg
);
2358 gimple_set_location (g
, loc
);
2359 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2360 arg
= gimple_assign_lhs (g
);
2363 basic_block then_bb
, fallthru_bb
;
2364 *gsi
= create_cond_insert_point (gsi
, true, false, true,
2365 &then_bb
, &fallthru_bb
);
2366 g
= gimple_build_cond (EQ_EXPR
, arg
,
2367 build_zero_cst (TREE_TYPE (arg
)),
2368 NULL_TREE
, NULL_TREE
);
2369 gimple_set_location (g
, loc
);
2370 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
2372 *gsi
= gsi_after_labels (then_bb
);
2373 if (flag_sanitize_trap
& SANITIZE_BUILTIN
)
2374 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2377 tree t
= build_int_cst (unsigned_char_type_node
, kind
);
2378 tree data
= ubsan_create_data ("__ubsan_builtin_data",
2379 1, &loc
, NULL_TREE
, t
, NULL_TREE
);
2380 data
= build_fold_addr_expr_loc (loc
, data
);
2381 enum built_in_function bcode
2382 = (flag_sanitize_recover
& SANITIZE_BUILTIN
)
2383 ? BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN
2384 : BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN_ABORT
;
2385 tree fn
= builtin_decl_explicit (bcode
);
2387 g
= gimple_build_call (fn
, 1, data
);
2389 gimple_set_location (g
, loc
);
2390 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2391 ubsan_create_edge (g
);
2393 *gsi
= gsi_for_stmt (stmt
);
2402 const pass_data pass_data_ubsan
=
2404 GIMPLE_PASS
, /* type */
2406 OPTGROUP_NONE
, /* optinfo_flags */
2407 TV_TREE_UBSAN
, /* tv_id */
2408 ( PROP_cfg
| PROP_ssa
), /* properties_required */
2409 0, /* properties_provided */
2410 0, /* properties_destroyed */
2411 0, /* todo_flags_start */
2412 TODO_update_ssa
, /* todo_flags_finish */
2415 class pass_ubsan
: public gimple_opt_pass
2418 pass_ubsan (gcc::context
*ctxt
)
2419 : gimple_opt_pass (pass_data_ubsan
, ctxt
)
2422 /* opt_pass methods: */
2423 bool gate (function
*) final override
2425 return sanitize_flags_p ((SANITIZE_NULL
| SANITIZE_SI_OVERFLOW
2426 | SANITIZE_BOOL
| SANITIZE_ENUM
2427 | SANITIZE_ALIGNMENT
2428 | SANITIZE_NONNULL_ATTRIBUTE
2429 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
2430 | SANITIZE_OBJECT_SIZE
2431 | SANITIZE_POINTER_OVERFLOW
2432 | SANITIZE_BUILTIN
));
2435 unsigned int execute (function
*) final override
;
2437 }; // class pass_ubsan
2440 pass_ubsan::execute (function
*fun
)
2443 gimple_stmt_iterator gsi
;
2444 unsigned int ret
= 0;
2446 initialize_sanitizer_builtins ();
2448 FOR_EACH_BB_FN (bb
, fun
)
2450 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
2452 gimple
*stmt
= gsi_stmt (gsi
);
2453 if (is_gimple_debug (stmt
) || gimple_clobber_p (stmt
))
2459 if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW
, fun
->decl
))
2460 && is_gimple_assign (stmt
))
2461 instrument_si_overflow (gsi
);
2463 if (sanitize_flags_p (SANITIZE_NULL
| SANITIZE_ALIGNMENT
, fun
->decl
))
2465 if (gimple_store_p (stmt
))
2466 instrument_null (gsi
, gimple_get_lhs (stmt
), true);
2467 if (gimple_assign_single_p (stmt
))
2468 instrument_null (gsi
, gimple_assign_rhs1 (stmt
), false);
2469 if (is_gimple_call (stmt
))
2471 unsigned args_num
= gimple_call_num_args (stmt
);
2472 for (unsigned i
= 0; i
< args_num
; ++i
)
2474 tree arg
= gimple_call_arg (stmt
, i
);
2475 if (is_gimple_reg (arg
) || is_gimple_min_invariant (arg
))
2477 instrument_null (gsi
, arg
, false);
2482 if (sanitize_flags_p (SANITIZE_BOOL
| SANITIZE_ENUM
, fun
->decl
)
2483 && gimple_assign_load_p (stmt
))
2485 instrument_bool_enum_load (&gsi
);
2486 bb
= gimple_bb (stmt
);
2489 if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE
, fun
->decl
)
2490 && is_gimple_call (stmt
)
2491 && !gimple_call_internal_p (stmt
))
2493 instrument_nonnull_arg (&gsi
);
2494 bb
= gimple_bb (stmt
);
2497 if (sanitize_flags_p (SANITIZE_BUILTIN
, fun
->decl
)
2498 && gimple_call_builtin_p (stmt
, BUILT_IN_NORMAL
))
2500 instrument_builtin (&gsi
);
2501 bb
= gimple_bb (stmt
);
2504 if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE
, fun
->decl
)
2505 && gimple_code (stmt
) == GIMPLE_RETURN
)
2507 instrument_nonnull_return (&gsi
);
2508 bb
= gimple_bb (stmt
);
2511 if (sanitize_flags_p (SANITIZE_OBJECT_SIZE
, fun
->decl
))
2513 if (gimple_store_p (stmt
))
2514 instrument_object_size (&gsi
, gimple_get_lhs (stmt
), true);
2515 if (gimple_assign_load_p (stmt
))
2516 instrument_object_size (&gsi
, gimple_assign_rhs1 (stmt
),
2518 if (is_gimple_call (stmt
))
2520 unsigned args_num
= gimple_call_num_args (stmt
);
2521 for (unsigned i
= 0; i
< args_num
; ++i
)
2523 tree arg
= gimple_call_arg (stmt
, i
);
2524 if (is_gimple_reg (arg
) || is_gimple_min_invariant (arg
))
2526 instrument_object_size (&gsi
, arg
, false);
2531 if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW
, fun
->decl
))
2533 if (is_gimple_assign (stmt
)
2534 && gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
2535 instrument_pointer_overflow (&gsi
,
2536 gimple_assign_rhs1 (stmt
),
2537 gimple_assign_rhs2 (stmt
));
2538 if (gimple_store_p (stmt
))
2539 maybe_instrument_pointer_overflow (&gsi
,
2540 gimple_get_lhs (stmt
));
2541 if (gimple_assign_single_p (stmt
))
2542 maybe_instrument_pointer_overflow (&gsi
,
2543 gimple_assign_rhs1 (stmt
));
2544 if (is_gimple_call (stmt
))
2546 unsigned args_num
= gimple_call_num_args (stmt
);
2547 for (unsigned i
= 0; i
< args_num
; ++i
)
2549 tree arg
= gimple_call_arg (stmt
, i
);
2550 if (is_gimple_reg (arg
))
2552 maybe_instrument_pointer_overflow (&gsi
, arg
);
2559 if (gimple_purge_dead_eh_edges (bb
))
2560 ret
= TODO_cleanup_cfg
;
2568 make_pass_ubsan (gcc::context
*ctxt
)
2570 return new pass_ubsan (ctxt
);
2573 #include "gt-ubsan.h"