1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2017 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"
53 /* Map from a tree to a VAR_DECL tree. */
55 struct GTY((for_user
)) tree_type_map
{
56 struct tree_map_base type
;
60 struct tree_type_map_cache_hasher
: ggc_cache_ptr_hash
<tree_type_map
>
62 static inline hashval_t
63 hash (tree_type_map
*t
)
65 return TYPE_UID (t
->type
.from
);
69 equal (tree_type_map
*a
, tree_type_map
*b
)
71 return a
->type
.from
== b
->type
.from
;
75 keep_cache_entry (tree_type_map
*&m
)
77 return ggc_marked_p (m
->type
.from
);
82 hash_table
<tree_type_map_cache_hasher
> *decl_tree_for_type
;
84 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
87 decl_for_type_lookup (tree type
)
89 /* If the hash table is not initialized yet, create it now. */
90 if (decl_tree_for_type
== NULL
)
93 = hash_table
<tree_type_map_cache_hasher
>::create_ggc (10);
94 /* That also means we don't have to bother with the lookup. */
98 struct tree_type_map
*h
, in
;
101 h
= decl_tree_for_type
->find_with_hash (&in
, TYPE_UID (type
));
102 return h
? h
->decl
: NULL_TREE
;
105 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
108 decl_for_type_insert (tree type
, tree decl
)
110 struct tree_type_map
*h
;
112 h
= ggc_alloc
<tree_type_map
> ();
115 *decl_tree_for_type
->find_slot_with_hash (h
, TYPE_UID (type
), INSERT
) = h
;
118 /* Helper routine, which encodes a value in the pointer_sized_int_node.
119 Arguments with precision <= POINTER_SIZE are passed directly,
120 the rest is passed by reference. T is a value we are to encode.
121 PHASE determines when this function is called. */
124 ubsan_encode_value (tree t
, enum ubsan_encode_value_phase phase
)
126 tree type
= TREE_TYPE (t
);
127 scalar_mode mode
= SCALAR_TYPE_MODE (type
);
128 const unsigned int bitsize
= GET_MODE_BITSIZE (mode
);
129 if (bitsize
<= POINTER_SIZE
)
130 switch (TREE_CODE (type
))
135 return fold_build1 (NOP_EXPR
, pointer_sized_int_node
, t
);
138 tree itype
= build_nonstandard_integer_type (bitsize
, true);
139 t
= fold_build1 (VIEW_CONVERT_EXPR
, itype
, t
);
140 return fold_convert (pointer_sized_int_node
, t
);
147 if (!DECL_P (t
) || !TREE_ADDRESSABLE (t
))
149 /* The reason for this is that we don't want to pessimize
150 code by making vars unnecessarily addressable. */
152 if (phase
!= UBSAN_ENCODE_VALUE_GENERIC
)
154 var
= create_tmp_var (type
);
155 mark_addressable (var
);
159 var
= create_tmp_var_raw (type
);
160 TREE_ADDRESSABLE (var
) = 1;
161 DECL_CONTEXT (var
) = current_function_decl
;
163 if (phase
== UBSAN_ENCODE_VALUE_RTL
)
165 rtx mem
= assign_stack_temp_for_type (mode
, GET_MODE_SIZE (mode
),
167 SET_DECL_RTL (var
, mem
);
168 expand_assignment (var
, t
, false);
169 return build_fold_addr_expr (var
);
171 if (phase
!= UBSAN_ENCODE_VALUE_GENERIC
)
173 tree tem
= build2 (MODIFY_EXPR
, void_type_node
, var
, t
);
174 t
= build_fold_addr_expr (var
);
175 return build2 (COMPOUND_EXPR
, TREE_TYPE (t
), tem
, t
);
179 var
= build4 (TARGET_EXPR
, type
, var
, t
, NULL_TREE
, NULL_TREE
);
180 return build_fold_addr_expr (var
);
184 return build_fold_addr_expr (t
);
188 /* Cached ubsan_get_type_descriptor_type () return value. */
189 static GTY(()) tree ubsan_type_descriptor_type
;
192 struct __ubsan_type_descriptor
194 unsigned short __typekind;
195 unsigned short __typeinfo;
201 ubsan_get_type_descriptor_type (void)
203 static const char *field_names
[3]
204 = { "__typekind", "__typeinfo", "__typename" };
207 if (ubsan_type_descriptor_type
)
208 return ubsan_type_descriptor_type
;
210 tree itype
= build_range_type (sizetype
, size_zero_node
, NULL_TREE
);
211 tree flex_arr_type
= build_array_type (char_type_node
, itype
);
213 ret
= make_node (RECORD_TYPE
);
214 for (int i
= 0; i
< 3; i
++)
216 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
217 get_identifier (field_names
[i
]),
218 (i
== 2) ? flex_arr_type
219 : short_unsigned_type_node
);
220 DECL_CONTEXT (fields
[i
]) = ret
;
222 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
224 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
225 get_identifier ("__ubsan_type_descriptor"),
227 DECL_IGNORED_P (type_decl
) = 1;
228 DECL_ARTIFICIAL (type_decl
) = 1;
229 TYPE_FIELDS (ret
) = fields
[0];
230 TYPE_NAME (ret
) = type_decl
;
231 TYPE_STUB_DECL (ret
) = type_decl
;
233 ubsan_type_descriptor_type
= ret
;
237 /* Cached ubsan_get_source_location_type () return value. */
238 static GTY(()) tree ubsan_source_location_type
;
241 struct __ubsan_source_location
243 const char *__filename;
245 unsigned int __column;
250 ubsan_get_source_location_type (void)
252 static const char *field_names
[3]
253 = { "__filename", "__line", "__column" };
255 if (ubsan_source_location_type
)
256 return ubsan_source_location_type
;
258 tree const_char_type
= build_qualified_type (char_type_node
,
261 ret
= make_node (RECORD_TYPE
);
262 for (int i
= 0; i
< 3; i
++)
264 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
265 get_identifier (field_names
[i
]),
266 (i
== 0) ? build_pointer_type (const_char_type
)
267 : unsigned_type_node
);
268 DECL_CONTEXT (fields
[i
]) = ret
;
270 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
272 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
273 get_identifier ("__ubsan_source_location"),
275 DECL_IGNORED_P (type_decl
) = 1;
276 DECL_ARTIFICIAL (type_decl
) = 1;
277 TYPE_FIELDS (ret
) = fields
[0];
278 TYPE_NAME (ret
) = type_decl
;
279 TYPE_STUB_DECL (ret
) = type_decl
;
281 ubsan_source_location_type
= ret
;
285 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
286 type with its fields filled from a location_t LOC. */
289 ubsan_source_location (location_t loc
)
291 expanded_location xloc
;
292 tree type
= ubsan_get_source_location_type ();
294 xloc
= expand_location (loc
);
296 if (xloc
.file
== NULL
)
298 str
= build_int_cst (ptr_type_node
, 0);
304 /* Fill in the values from LOC. */
305 size_t len
= strlen (xloc
.file
) + 1;
306 str
= build_string (len
, xloc
.file
);
307 TREE_TYPE (str
) = build_array_type_nelts (char_type_node
, len
);
308 TREE_READONLY (str
) = 1;
309 TREE_STATIC (str
) = 1;
310 str
= build_fold_addr_expr (str
);
312 tree ctor
= build_constructor_va (type
, 3, NULL_TREE
, str
, NULL_TREE
,
313 build_int_cst (unsigned_type_node
,
314 xloc
.line
), NULL_TREE
,
315 build_int_cst (unsigned_type_node
,
317 TREE_CONSTANT (ctor
) = 1;
318 TREE_STATIC (ctor
) = 1;
323 /* This routine returns a magic number for TYPE. */
325 static unsigned short
326 get_ubsan_type_info_for_type (tree type
)
328 if (TREE_CODE (type
) == REAL_TYPE
)
329 return tree_to_uhwi (TYPE_SIZE (type
));
330 else if (INTEGRAL_TYPE_P (type
))
332 int prec
= exact_log2 (tree_to_uhwi (TYPE_SIZE (type
)));
333 gcc_assert (prec
!= -1);
334 return (prec
<< 1) | !TYPE_UNSIGNED (type
);
340 /* Counters for internal labels. ubsan_ids[0] for Lubsan_type,
341 ubsan_ids[1] for Lubsan_data labels. */
342 static GTY(()) unsigned int ubsan_ids
[2];
344 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
345 descriptor. It first looks into the hash table; if not found,
346 create the VAR_DECL, put it into the hash table and return the
347 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
348 an enum controlling how we want to print the type. */
351 ubsan_type_descriptor (tree type
, enum ubsan_print_style pstyle
)
353 /* See through any typedefs. */
354 type
= TYPE_MAIN_VARIANT (type
);
356 tree decl
= decl_for_type_lookup (type
);
357 /* It is possible that some of the earlier created DECLs were found
358 unused, in that case they weren't emitted and varpool_node::get
359 returns NULL node on them. But now we really need them. Thus,
361 if (decl
!= NULL_TREE
&& varpool_node::get (decl
))
362 return build_fold_addr_expr (decl
);
364 tree dtype
= ubsan_get_type_descriptor_type ();
366 const char *tname
= NULL
;
367 pretty_printer pretty_name
;
368 unsigned char deref_depth
= 0;
369 unsigned short tkind
, tinfo
;
371 /* Get the name of the type, or the name of the pointer type. */
372 if (pstyle
== UBSAN_PRINT_POINTER
)
374 gcc_assert (POINTER_TYPE_P (type
));
375 type2
= TREE_TYPE (type
);
377 /* Remove any '*' operators from TYPE. */
378 while (POINTER_TYPE_P (type2
))
379 deref_depth
++, type2
= TREE_TYPE (type2
);
381 if (TREE_CODE (type2
) == METHOD_TYPE
)
382 type2
= TYPE_METHOD_BASETYPE (type2
);
385 /* If an array, get its type. */
386 type2
= strip_array_types (type2
);
388 if (pstyle
== UBSAN_PRINT_ARRAY
)
390 while (POINTER_TYPE_P (type2
))
391 deref_depth
++, type2
= TREE_TYPE (type2
);
394 if (TYPE_NAME (type2
) != NULL
)
396 if (TREE_CODE (TYPE_NAME (type2
)) == IDENTIFIER_NODE
)
397 tname
= IDENTIFIER_POINTER (TYPE_NAME (type2
));
398 else if (DECL_NAME (TYPE_NAME (type2
)) != NULL
)
399 tname
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2
)));
403 /* We weren't able to determine the type name. */
407 if (pstyle
== UBSAN_PRINT_POINTER
)
409 pp_printf (&pretty_name
, "'%s%s%s%s%s%s%s",
410 TYPE_VOLATILE (type2
) ? "volatile " : "",
411 TYPE_READONLY (type2
) ? "const " : "",
412 TYPE_RESTRICT (type2
) ? "restrict " : "",
413 TYPE_ATOMIC (type2
) ? "_Atomic " : "",
414 TREE_CODE (type2
) == RECORD_TYPE
416 : TREE_CODE (type2
) == UNION_TYPE
417 ? "union " : "", tname
,
418 deref_depth
== 0 ? "" : " ");
419 while (deref_depth
-- > 0)
420 pp_star (&pretty_name
);
421 pp_quote (&pretty_name
);
423 else if (pstyle
== UBSAN_PRINT_ARRAY
)
425 /* Pretty print the array dimensions. */
426 gcc_assert (TREE_CODE (type
) == ARRAY_TYPE
);
428 pp_printf (&pretty_name
, "'%s ", tname
);
429 while (deref_depth
-- > 0)
430 pp_star (&pretty_name
);
431 while (TREE_CODE (t
) == ARRAY_TYPE
)
433 pp_left_bracket (&pretty_name
);
434 tree dom
= TYPE_DOMAIN (t
);
436 && TYPE_MAX_VALUE (dom
) != NULL_TREE
437 && TREE_CODE (TYPE_MAX_VALUE (dom
)) == INTEGER_CST
)
439 unsigned HOST_WIDE_INT m
;
440 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom
))
441 && (m
= tree_to_uhwi (TYPE_MAX_VALUE (dom
))) + 1 != 0)
442 pp_unsigned_wide_integer (&pretty_name
, m
+ 1);
444 pp_wide_int (&pretty_name
,
445 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom
)), 1),
446 TYPE_SIGN (TREE_TYPE (dom
)));
449 /* ??? We can't determine the variable name; print VLA unspec. */
450 pp_star (&pretty_name
);
451 pp_right_bracket (&pretty_name
);
454 pp_quote (&pretty_name
);
456 /* Save the tree with stripped types. */
460 pp_printf (&pretty_name
, "'%s'", tname
);
462 switch (TREE_CODE (eltype
))
470 /* FIXME: libubsan right now only supports float, double and
471 long double type formats. */
472 if (TYPE_MODE (eltype
) == TYPE_MODE (float_type_node
)
473 || TYPE_MODE (eltype
) == TYPE_MODE (double_type_node
)
474 || TYPE_MODE (eltype
) == TYPE_MODE (long_double_type_node
))
483 tinfo
= get_ubsan_type_info_for_type (eltype
);
485 /* Create a new VAR_DECL of type descriptor. */
486 const char *tmp
= pp_formatted_text (&pretty_name
);
487 size_t len
= strlen (tmp
) + 1;
488 tree str
= build_string (len
, tmp
);
489 TREE_TYPE (str
) = build_array_type_nelts (char_type_node
, len
);
490 TREE_READONLY (str
) = 1;
491 TREE_STATIC (str
) = 1;
494 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_type", ubsan_ids
[0]++);
495 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
497 TREE_STATIC (decl
) = 1;
498 TREE_PUBLIC (decl
) = 0;
499 DECL_ARTIFICIAL (decl
) = 1;
500 DECL_IGNORED_P (decl
) = 1;
501 DECL_EXTERNAL (decl
) = 0;
503 = size_binop (PLUS_EXPR
, DECL_SIZE (decl
), TYPE_SIZE (TREE_TYPE (str
)));
504 DECL_SIZE_UNIT (decl
)
505 = size_binop (PLUS_EXPR
, DECL_SIZE_UNIT (decl
),
506 TYPE_SIZE_UNIT (TREE_TYPE (str
)));
508 tree ctor
= build_constructor_va (dtype
, 3, NULL_TREE
,
509 build_int_cst (short_unsigned_type_node
,
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
);
518 /* Save the VAR_DECL into the hash table. */
519 decl_for_type_insert (type
, decl
);
521 return build_fold_addr_expr (decl
);
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. */
531 ubsan_create_data (const char *name
, int loccnt
, const location_t
*ploc
, ...)
536 vec
<tree
, va_gc
> *saved_args
= NULL
;
540 /* It is possible that PCH zapped table with definitions of sanitizer
541 builtins. Reinitialize them if needed. */
542 initialize_sanitizer_builtins ();
544 /* Firstly, create a pointer to type descriptor type. */
545 tree td_type
= ubsan_get_type_descriptor_type ();
546 td_type
= build_pointer_type (td_type
);
548 /* Create the structure type. */
549 ret
= make_node (RECORD_TYPE
);
550 for (j
= 0; j
< loccnt
; j
++)
552 gcc_checking_assert (i
< 2);
553 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
554 ubsan_get_source_location_type ());
555 DECL_CONTEXT (fields
[i
]) = ret
;
557 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
561 va_start (args
, ploc
);
562 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
563 i
++, t
= va_arg (args
, tree
))
565 gcc_checking_assert (i
< 4);
566 /* Save the tree arguments for later use. */
567 vec_safe_push (saved_args
, t
);
568 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
570 DECL_CONTEXT (fields
[i
]) = ret
;
572 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
575 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
576 i
++, t
= va_arg (args
, tree
))
578 gcc_checking_assert (i
< 6);
579 /* Save the tree arguments for later use. */
580 vec_safe_push (saved_args
, t
);
581 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
583 DECL_CONTEXT (fields
[i
]) = ret
;
585 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
589 tree type_decl
= build_decl (input_location
, TYPE_DECL
,
590 get_identifier (name
), ret
);
591 DECL_IGNORED_P (type_decl
) = 1;
592 DECL_ARTIFICIAL (type_decl
) = 1;
593 TYPE_FIELDS (ret
) = fields
[0];
594 TYPE_NAME (ret
) = type_decl
;
595 TYPE_STUB_DECL (ret
) = type_decl
;
598 /* Now, fill in the type. */
600 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_data", ubsan_ids
[1]++);
601 tree var
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
603 TREE_STATIC (var
) = 1;
604 TREE_PUBLIC (var
) = 0;
605 DECL_ARTIFICIAL (var
) = 1;
606 DECL_IGNORED_P (var
) = 1;
607 DECL_EXTERNAL (var
) = 0;
609 vec
<constructor_elt
, va_gc
> *v
;
611 tree ctor
= build_constructor (ret
, v
);
613 /* If desirable, set the __ubsan_source_location element. */
614 for (j
= 0; j
< loccnt
; j
++)
616 location_t loc
= LOCATION_LOCUS (ploc
[j
]);
617 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, ubsan_source_location (loc
));
620 size_t nelts
= vec_safe_length (saved_args
);
621 for (i
= 0; i
< nelts
; i
++)
623 t
= (*saved_args
)[i
];
624 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, t
);
627 TREE_CONSTANT (ctor
) = 1;
628 TREE_STATIC (ctor
) = 1;
629 DECL_INITIAL (var
) = ctor
;
630 varpool_node::finalize_decl (var
);
635 /* Instrument the __builtin_unreachable call. We just call the libubsan
639 ubsan_instrument_unreachable (gimple_stmt_iterator
*gsi
)
642 location_t loc
= gimple_location (gsi_stmt (*gsi
));
644 if (flag_sanitize_undefined_trap_on_error
)
645 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
648 tree data
= ubsan_create_data ("__ubsan_unreachable_data", 1, &loc
,
649 NULL_TREE
, NULL_TREE
);
650 data
= build_fold_addr_expr_loc (loc
, data
);
652 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE
);
653 g
= gimple_build_call (fn
, 1, data
);
655 gimple_set_location (g
, loc
);
656 gsi_replace (gsi
, g
, false);
660 /* Return true if T is a call to a libubsan routine. */
663 is_ubsan_builtin_p (tree t
)
665 return TREE_CODE (t
) == FUNCTION_DECL
666 && DECL_BUILT_IN_CLASS (t
) == BUILT_IN_NORMAL
667 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t
)),
668 "__builtin___ubsan_", 18) == 0;
671 /* Create a callgraph edge for statement STMT. */
674 ubsan_create_edge (gimple
*stmt
)
676 gcall
*call_stmt
= dyn_cast
<gcall
*> (stmt
);
677 basic_block bb
= gimple_bb (stmt
);
678 cgraph_node
*node
= cgraph_node::get (current_function_decl
);
679 tree decl
= gimple_call_fndecl (call_stmt
);
681 node
->create_edge (cgraph_node::get_create (decl
), call_stmt
, bb
->count
);
684 /* Expand the UBSAN_BOUNDS special builtin function. */
687 ubsan_expand_bounds_ifn (gimple_stmt_iterator
*gsi
)
689 gimple
*stmt
= gsi_stmt (*gsi
);
690 location_t loc
= gimple_location (stmt
);
691 gcc_assert (gimple_call_num_args (stmt
) == 3);
693 /* Pick up the arguments of the UBSAN_BOUNDS call. */
694 tree type
= TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt
, 0)));
695 tree index
= gimple_call_arg (stmt
, 1);
696 tree orig_index
= index
;
697 tree bound
= gimple_call_arg (stmt
, 2);
699 gimple_stmt_iterator gsi_orig
= *gsi
;
701 /* Create condition "if (index > bound)". */
702 basic_block then_bb
, fallthru_bb
;
703 gimple_stmt_iterator cond_insert_point
704 = create_cond_insert_point (gsi
, false, false, true,
705 &then_bb
, &fallthru_bb
);
706 index
= fold_convert (TREE_TYPE (bound
), index
);
707 index
= force_gimple_operand_gsi (&cond_insert_point
, index
,
709 false, GSI_NEW_STMT
);
710 gimple
*g
= gimple_build_cond (GT_EXPR
, index
, bound
, NULL_TREE
, NULL_TREE
);
711 gimple_set_location (g
, loc
);
712 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
714 /* Generate __ubsan_handle_out_of_bounds call. */
715 *gsi
= gsi_after_labels (then_bb
);
716 if (flag_sanitize_undefined_trap_on_error
)
717 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
721 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc
,
722 ubsan_type_descriptor (type
, UBSAN_PRINT_ARRAY
),
723 ubsan_type_descriptor (TREE_TYPE (orig_index
)),
724 NULL_TREE
, NULL_TREE
);
725 data
= build_fold_addr_expr_loc (loc
, data
);
726 enum built_in_function bcode
727 = (flag_sanitize_recover
& SANITIZE_BOUNDS
)
728 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
729 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT
;
730 tree fn
= builtin_decl_explicit (bcode
);
731 tree val
= ubsan_encode_value (orig_index
, UBSAN_ENCODE_VALUE_GIMPLE
);
732 val
= force_gimple_operand_gsi (gsi
, val
, true, NULL_TREE
, true,
734 g
= gimple_build_call (fn
, 2, data
, val
);
736 gimple_set_location (g
, loc
);
737 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
739 /* Get rid of the UBSAN_BOUNDS call from the IR. */
740 unlink_stmt_vdef (stmt
);
741 gsi_remove (&gsi_orig
, true);
743 /* Point GSI to next logical statement. */
744 *gsi
= gsi_start_bb (fallthru_bb
);
748 /* Expand UBSAN_NULL internal call. The type is kept on the ckind
749 argument which is a constant, because the middle-end treats pointer
750 conversions as useless and therefore the type of the first argument
751 could be changed to any other pointer type. */
754 ubsan_expand_null_ifn (gimple_stmt_iterator
*gsip
)
756 gimple_stmt_iterator gsi
= *gsip
;
757 gimple
*stmt
= gsi_stmt (gsi
);
758 location_t loc
= gimple_location (stmt
);
759 gcc_assert (gimple_call_num_args (stmt
) == 3);
760 tree ptr
= gimple_call_arg (stmt
, 0);
761 tree ckind
= gimple_call_arg (stmt
, 1);
762 tree align
= gimple_call_arg (stmt
, 2);
763 tree check_align
= NULL_TREE
;
766 basic_block cur_bb
= gsi_bb (gsi
);
769 if (!integer_zerop (align
))
771 unsigned int ptralign
= get_pointer_alignment (ptr
) / BITS_PER_UNIT
;
772 if (compare_tree_int (align
, ptralign
) == 1)
774 check_align
= make_ssa_name (pointer_sized_int_node
);
775 g
= gimple_build_assign (check_align
, NOP_EXPR
, ptr
);
776 gimple_set_location (g
, loc
);
777 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
780 check_null
= sanitize_flags_p (SANITIZE_NULL
);
782 if (check_align
== NULL_TREE
&& !check_null
)
784 gsi_remove (gsip
, true);
785 /* Unlink the UBSAN_NULLs vops before replacing it. */
786 unlink_stmt_vdef (stmt
);
790 /* Split the original block holding the pointer dereference. */
791 edge e
= split_block (cur_bb
, stmt
);
793 /* Get a hold on the 'condition block', the 'then block' and the
795 basic_block cond_bb
= e
->src
;
796 basic_block fallthru_bb
= e
->dest
;
797 basic_block then_bb
= create_empty_bb (cond_bb
);
798 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
799 loops_state_set (LOOPS_NEED_FIXUP
);
801 /* Make an edge coming from the 'cond block' into the 'then block';
802 this edge is unlikely taken, so set up the probability accordingly. */
803 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
804 e
->probability
= profile_probability::very_unlikely ();
805 then_bb
->count
= e
->count ();
807 /* Connect 'then block' with the 'else block'. This is needed
808 as the ubsan routines we call in the 'then block' are not noreturn.
809 The 'then block' only has one outcoming edge. */
810 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
812 /* Set up the fallthrough basic block. */
813 e
= find_edge (cond_bb
, fallthru_bb
);
814 e
->flags
= EDGE_FALSE_VALUE
;
815 e
->probability
= profile_probability::very_likely ();
817 /* Update dominance info for the newly created then_bb; note that
818 fallthru_bb's dominance info has already been updated by
820 if (dom_info_available_p (CDI_DOMINATORS
))
821 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
823 /* Put the ubsan builtin call into the newly created BB. */
824 if (flag_sanitize_undefined_trap_on_error
)
825 g
= gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP
), 0);
828 enum built_in_function bcode
829 = (flag_sanitize_recover
& ((check_align
? SANITIZE_ALIGNMENT
: 0)
830 | (check_null
? SANITIZE_NULL
: 0)))
831 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
832 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT
;
833 tree fn
= builtin_decl_implicit (bcode
);
834 int align_log
= tree_log2 (align
);
836 = ubsan_create_data ("__ubsan_null_data", 1, &loc
,
837 ubsan_type_descriptor (TREE_TYPE (ckind
),
838 UBSAN_PRINT_POINTER
),
840 build_int_cst (unsigned_char_type_node
,
842 fold_convert (unsigned_char_type_node
, ckind
),
844 data
= build_fold_addr_expr_loc (loc
, data
);
845 g
= gimple_build_call (fn
, 2, data
,
846 check_align
? check_align
847 : build_zero_cst (pointer_sized_int_node
));
849 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
850 gimple_set_location (g
, loc
);
851 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
853 /* Unlink the UBSAN_NULLs vops before replacing it. */
854 unlink_stmt_vdef (stmt
);
858 g
= gimple_build_cond (EQ_EXPR
, ptr
, build_int_cst (TREE_TYPE (ptr
), 0),
859 NULL_TREE
, NULL_TREE
);
860 gimple_set_location (g
, loc
);
862 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
863 gsi_replace (&gsi
, g
, false);
871 /* Split the block with the condition again. */
872 e
= split_block (cond_bb
, stmt
);
873 basic_block cond1_bb
= e
->src
;
874 basic_block cond2_bb
= e
->dest
;
876 /* Make an edge coming from the 'cond1 block' into the 'then block';
877 this edge is unlikely taken, so set up the probability
879 e
= make_edge (cond1_bb
, then_bb
, EDGE_TRUE_VALUE
);
880 e
->probability
= profile_probability::very_unlikely ();
882 /* Set up the fallthrough basic block. */
883 e
= find_edge (cond1_bb
, cond2_bb
);
884 e
->flags
= EDGE_FALSE_VALUE
;
885 e
->probability
= profile_probability::very_likely ();
887 /* Update dominance info. */
888 if (dom_info_available_p (CDI_DOMINATORS
))
890 set_immediate_dominator (CDI_DOMINATORS
, fallthru_bb
, cond1_bb
);
891 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond1_bb
);
894 gsi2
= gsi_start_bb (cond2_bb
);
897 tree mask
= build_int_cst (pointer_sized_int_node
,
898 tree_to_uhwi (align
) - 1);
899 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
900 BIT_AND_EXPR
, check_align
, mask
);
901 gimple_set_location (g
, loc
);
903 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
905 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
907 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
),
908 build_int_cst (pointer_sized_int_node
, 0),
909 NULL_TREE
, NULL_TREE
);
910 gimple_set_location (g
, loc
);
912 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
914 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
915 gsi_replace (&gsi
, g
, false);
920 #define OBJSZ_MAX_OFFSET (1024 * 16)
922 /* Expand UBSAN_OBJECT_SIZE internal call. */
925 ubsan_expand_objsize_ifn (gimple_stmt_iterator
*gsi
)
927 gimple
*stmt
= gsi_stmt (*gsi
);
928 location_t loc
= gimple_location (stmt
);
929 gcc_assert (gimple_call_num_args (stmt
) == 4);
931 tree ptr
= gimple_call_arg (stmt
, 0);
932 tree offset
= gimple_call_arg (stmt
, 1);
933 tree size
= gimple_call_arg (stmt
, 2);
934 tree ckind
= gimple_call_arg (stmt
, 3);
935 gimple_stmt_iterator gsi_orig
= *gsi
;
938 /* See if we can discard the check. */
939 if (TREE_CODE (size
) != INTEGER_CST
940 || integer_all_onesp (size
))
941 /* Yes, __builtin_object_size couldn't determine the
943 else if (TREE_CODE (offset
) == INTEGER_CST
944 && wi::to_widest (offset
) >= -OBJSZ_MAX_OFFSET
945 && wi::to_widest (offset
) <= -1)
946 /* The offset is in range [-16K, -1]. */;
949 /* if (offset > objsize) */
950 basic_block then_bb
, fallthru_bb
;
951 gimple_stmt_iterator cond_insert_point
952 = create_cond_insert_point (gsi
, false, false, true,
953 &then_bb
, &fallthru_bb
);
954 g
= gimple_build_cond (GT_EXPR
, offset
, size
, NULL_TREE
, NULL_TREE
);
955 gimple_set_location (g
, loc
);
956 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
958 /* If the offset is small enough, we don't need the second
960 if (TREE_CODE (offset
) == INTEGER_CST
961 && wi::to_widest (offset
) >= 0
962 && wi::to_widest (offset
) <= OBJSZ_MAX_OFFSET
)
963 *gsi
= gsi_after_labels (then_bb
);
966 /* Don't issue run-time error if (ptr > ptr + offset). That
967 may happen when computing a POINTER_PLUS_EXPR. */
968 basic_block then2_bb
, fallthru2_bb
;
970 gimple_stmt_iterator gsi2
= gsi_after_labels (then_bb
);
971 cond_insert_point
= create_cond_insert_point (&gsi2
, false, false,
974 /* Convert the pointer to an integer type. */
975 tree p
= make_ssa_name (pointer_sized_int_node
);
976 g
= gimple_build_assign (p
, NOP_EXPR
, ptr
);
977 gimple_set_location (g
, loc
);
978 gsi_insert_before (&cond_insert_point
, g
, GSI_NEW_STMT
);
979 p
= gimple_assign_lhs (g
);
980 /* Compute ptr + offset. */
981 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
982 PLUS_EXPR
, p
, offset
);
983 gimple_set_location (g
, loc
);
984 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
985 /* Now build the conditional and put it into the IR. */
986 g
= gimple_build_cond (LE_EXPR
, p
, gimple_assign_lhs (g
),
987 NULL_TREE
, NULL_TREE
);
988 gimple_set_location (g
, loc
);
989 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
990 *gsi
= gsi_after_labels (then2_bb
);
993 /* Generate __ubsan_handle_type_mismatch call. */
994 if (flag_sanitize_undefined_trap_on_error
)
995 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
999 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc
,
1000 ubsan_type_descriptor (TREE_TYPE (ptr
),
1001 UBSAN_PRINT_POINTER
),
1003 build_zero_cst (unsigned_char_type_node
),
1006 data
= build_fold_addr_expr_loc (loc
, data
);
1007 enum built_in_function bcode
1008 = (flag_sanitize_recover
& SANITIZE_OBJECT_SIZE
)
1009 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
1010 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT
;
1011 tree p
= make_ssa_name (pointer_sized_int_node
);
1012 g
= gimple_build_assign (p
, NOP_EXPR
, ptr
);
1013 gimple_set_location (g
, loc
);
1014 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1015 g
= gimple_build_call (builtin_decl_explicit (bcode
), 2, data
, p
);
1017 gimple_set_location (g
, loc
);
1018 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1020 /* Point GSI to next logical statement. */
1021 *gsi
= gsi_start_bb (fallthru_bb
);
1023 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1024 unlink_stmt_vdef (stmt
);
1025 gsi_remove (&gsi_orig
, true);
1029 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1030 unlink_stmt_vdef (stmt
);
1031 gsi_remove (gsi
, true);
1035 /* Expand UBSAN_PTR internal call. */
1038 ubsan_expand_ptr_ifn (gimple_stmt_iterator
*gsip
)
1040 gimple_stmt_iterator gsi
= *gsip
;
1041 gimple
*stmt
= gsi_stmt (gsi
);
1042 location_t loc
= gimple_location (stmt
);
1043 gcc_assert (gimple_call_num_args (stmt
) == 2);
1044 tree ptr
= gimple_call_arg (stmt
, 0);
1045 tree off
= gimple_call_arg (stmt
, 1);
1047 if (integer_zerop (off
))
1049 gsi_remove (gsip
, true);
1050 unlink_stmt_vdef (stmt
);
1054 basic_block cur_bb
= gsi_bb (gsi
);
1055 tree ptrplusoff
= make_ssa_name (pointer_sized_int_node
);
1056 tree ptri
= make_ssa_name (pointer_sized_int_node
);
1057 int pos_neg
= get_range_pos_neg (off
);
1059 /* Split the original block holding the pointer dereference. */
1060 edge e
= split_block (cur_bb
, stmt
);
1062 /* Get a hold on the 'condition block', the 'then block' and the
1064 basic_block cond_bb
= e
->src
;
1065 basic_block fallthru_bb
= e
->dest
;
1066 basic_block then_bb
= create_empty_bb (cond_bb
);
1067 basic_block cond_pos_bb
= NULL
, cond_neg_bb
= NULL
;
1068 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
1069 loops_state_set (LOOPS_NEED_FIXUP
);
1071 /* Set up the fallthrough basic block. */
1072 e
->flags
= EDGE_FALSE_VALUE
;
1075 e
->probability
= profile_probability::very_likely ();
1077 /* Connect 'then block' with the 'else block'. This is needed
1078 as the ubsan routines we call in the 'then block' are not noreturn.
1079 The 'then block' only has one outcoming edge. */
1080 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
1082 /* Make an edge coming from the 'cond block' into the 'then block';
1083 this edge is unlikely taken, so set up the probability
1085 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
1086 e
->probability
= profile_probability::very_unlikely ();
1087 then_bb
->count
= e
->count ();
1091 e
->probability
= profile_probability::even ();
1093 e
= split_block (fallthru_bb
, (gimple
*) NULL
);
1094 cond_neg_bb
= e
->src
;
1095 fallthru_bb
= e
->dest
;
1096 e
->probability
= profile_probability::very_likely ();
1097 e
->flags
= EDGE_FALSE_VALUE
;
1099 e
= make_edge (cond_neg_bb
, then_bb
, EDGE_TRUE_VALUE
);
1100 e
->probability
= profile_probability::very_unlikely ();
1101 then_bb
->count
= e
->count ();
1103 cond_pos_bb
= create_empty_bb (cond_bb
);
1104 add_bb_to_loop (cond_pos_bb
, cond_bb
->loop_father
);
1106 e
= make_edge (cond_bb
, cond_pos_bb
, EDGE_TRUE_VALUE
);
1107 e
->probability
= profile_probability::even ();
1108 cond_pos_bb
->count
= e
->count ();
1110 e
= make_edge (cond_pos_bb
, then_bb
, EDGE_TRUE_VALUE
);
1111 e
->probability
= profile_probability::very_unlikely ();
1113 e
= make_edge (cond_pos_bb
, fallthru_bb
, EDGE_FALSE_VALUE
);
1114 e
->probability
= profile_probability::very_likely ();
1116 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
1119 gimple
*g
= gimple_build_assign (ptri
, NOP_EXPR
, ptr
);
1120 gimple_set_location (g
, loc
);
1121 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1122 g
= gimple_build_assign (ptrplusoff
, PLUS_EXPR
, ptri
, off
);
1123 gimple_set_location (g
, loc
);
1124 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1126 /* Update dominance info for the newly created then_bb; note that
1127 fallthru_bb's dominance info has already been updated by
1129 if (dom_info_available_p (CDI_DOMINATORS
))
1131 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
1134 set_immediate_dominator (CDI_DOMINATORS
, cond_pos_bb
, cond_bb
);
1135 set_immediate_dominator (CDI_DOMINATORS
, fallthru_bb
, cond_bb
);
1139 /* Put the ubsan builtin call into the newly created BB. */
1140 if (flag_sanitize_undefined_trap_on_error
)
1141 g
= gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP
), 0);
1144 enum built_in_function bcode
1145 = (flag_sanitize_recover
& SANITIZE_POINTER_OVERFLOW
)
1146 ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
1147 : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT
;
1148 tree fn
= builtin_decl_implicit (bcode
);
1150 = ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc
,
1151 NULL_TREE
, NULL_TREE
);
1152 data
= build_fold_addr_expr_loc (loc
, data
);
1153 g
= gimple_build_call (fn
, 3, data
, ptr
, ptrplusoff
);
1155 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
1156 gimple_set_location (g
, loc
);
1157 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
1159 /* Unlink the UBSAN_PTRs vops before replacing it. */
1160 unlink_stmt_vdef (stmt
);
1162 if (TREE_CODE (off
) == INTEGER_CST
)
1163 g
= gimple_build_cond (wi::neg_p (wi::to_wide (off
)) ? LT_EXPR
: GE_EXPR
,
1164 ptri
, fold_build1 (NEGATE_EXPR
, sizetype
, off
),
1165 NULL_TREE
, NULL_TREE
);
1166 else if (pos_neg
!= 3)
1167 g
= gimple_build_cond (pos_neg
== 1 ? LT_EXPR
: GT_EXPR
,
1168 ptrplusoff
, ptri
, NULL_TREE
, NULL_TREE
);
1171 gsi2
= gsi_start_bb (cond_pos_bb
);
1172 g
= gimple_build_cond (LT_EXPR
, ptrplusoff
, ptri
, NULL_TREE
, NULL_TREE
);
1173 gimple_set_location (g
, loc
);
1174 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
1176 gsi2
= gsi_start_bb (cond_neg_bb
);
1177 g
= gimple_build_cond (GT_EXPR
, ptrplusoff
, ptri
, NULL_TREE
, NULL_TREE
);
1178 gimple_set_location (g
, loc
);
1179 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
1181 gimple_seq seq
= NULL
;
1182 tree t
= gimple_build (&seq
, loc
, NOP_EXPR
, ssizetype
, off
);
1183 t
= gimple_build (&seq
, loc
, GE_EXPR
, boolean_type_node
,
1185 gsi_insert_seq_before (&gsi
, seq
, GSI_SAME_STMT
);
1186 g
= gimple_build_cond (NE_EXPR
, t
, boolean_false_node
,
1187 NULL_TREE
, NULL_TREE
);
1189 gimple_set_location (g
, loc
);
1190 /* Replace the UBSAN_PTR with a GIMPLE_COND stmt. */
1191 gsi_replace (&gsi
, g
, false);
1196 /* Cached __ubsan_vptr_type_cache decl. */
1197 static GTY(()) tree ubsan_vptr_type_cache_decl
;
1199 /* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1200 argument which is a constant, because the middle-end treats pointer
1201 conversions as useless and therefore the type of the first argument
1202 could be changed to any other pointer type. */
1205 ubsan_expand_vptr_ifn (gimple_stmt_iterator
*gsip
)
1207 gimple_stmt_iterator gsi
= *gsip
;
1208 gimple
*stmt
= gsi_stmt (gsi
);
1209 location_t loc
= gimple_location (stmt
);
1210 gcc_assert (gimple_call_num_args (stmt
) == 5);
1211 tree op
= gimple_call_arg (stmt
, 0);
1212 tree vptr
= gimple_call_arg (stmt
, 1);
1213 tree str_hash
= gimple_call_arg (stmt
, 2);
1214 tree ti_decl_addr
= gimple_call_arg (stmt
, 3);
1215 tree ckind_tree
= gimple_call_arg (stmt
, 4);
1216 ubsan_null_ckind ckind
= (ubsan_null_ckind
) tree_to_uhwi (ckind_tree
);
1217 tree type
= TREE_TYPE (TREE_TYPE (ckind_tree
));
1219 basic_block fallthru_bb
= NULL
;
1221 if (ckind
== UBSAN_DOWNCAST_POINTER
)
1223 /* Guard everything with if (op != NULL) { ... }. */
1224 basic_block then_bb
;
1225 gimple_stmt_iterator cond_insert_point
1226 = create_cond_insert_point (gsip
, false, false, true,
1227 &then_bb
, &fallthru_bb
);
1228 g
= gimple_build_cond (NE_EXPR
, op
, build_zero_cst (TREE_TYPE (op
)),
1229 NULL_TREE
, NULL_TREE
);
1230 gimple_set_location (g
, loc
);
1231 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1232 *gsip
= gsi_after_labels (then_bb
);
1233 gsi_remove (&gsi
, false);
1234 gsi_insert_before (gsip
, stmt
, GSI_NEW_STMT
);
1238 tree htype
= TREE_TYPE (str_hash
);
1239 tree cst
= wide_int_to_tree (htype
,
1240 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1242 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1244 gimple_set_location (g
, loc
);
1245 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1246 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1247 gimple_assign_lhs (g
), cst
);
1248 gimple_set_location (g
, loc
);
1249 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1250 tree t1
= gimple_assign_lhs (g
);
1251 g
= gimple_build_assign (make_ssa_name (htype
), LSHIFT_EXPR
,
1252 t1
, build_int_cst (integer_type_node
, 47));
1253 gimple_set_location (g
, loc
);
1254 tree t2
= gimple_assign_lhs (g
);
1255 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1256 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1258 gimple_set_location (g
, loc
);
1259 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1260 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1261 t2
, gimple_assign_lhs (g
));
1262 gimple_set_location (g
, loc
);
1263 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1264 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1265 gimple_assign_lhs (g
), cst
);
1266 gimple_set_location (g
, loc
);
1267 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1268 tree t3
= gimple_assign_lhs (g
);
1269 g
= gimple_build_assign (make_ssa_name (htype
), LSHIFT_EXPR
,
1270 t3
, build_int_cst (integer_type_node
, 47));
1271 gimple_set_location (g
, loc
);
1272 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1273 g
= gimple_build_assign (make_ssa_name (htype
), BIT_XOR_EXPR
,
1274 t3
, gimple_assign_lhs (g
));
1275 gimple_set_location (g
, loc
);
1276 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1277 g
= gimple_build_assign (make_ssa_name (htype
), MULT_EXPR
,
1278 gimple_assign_lhs (g
), cst
);
1279 gimple_set_location (g
, loc
);
1280 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1281 if (!useless_type_conversion_p (pointer_sized_int_node
, htype
))
1283 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1284 NOP_EXPR
, gimple_assign_lhs (g
));
1285 gimple_set_location (g
, loc
);
1286 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1288 tree hash
= gimple_assign_lhs (g
);
1290 if (ubsan_vptr_type_cache_decl
== NULL_TREE
)
1292 tree atype
= build_array_type_nelts (pointer_sized_int_node
, 128);
1293 tree array
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
1294 get_identifier ("__ubsan_vptr_type_cache"),
1296 DECL_ARTIFICIAL (array
) = 1;
1297 DECL_IGNORED_P (array
) = 1;
1298 TREE_PUBLIC (array
) = 1;
1299 TREE_STATIC (array
) = 1;
1300 DECL_EXTERNAL (array
) = 1;
1301 DECL_VISIBILITY (array
) = VISIBILITY_DEFAULT
;
1302 DECL_VISIBILITY_SPECIFIED (array
) = 1;
1303 varpool_node::finalize_decl (array
);
1304 ubsan_vptr_type_cache_decl
= array
;
1307 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1309 build_int_cst (pointer_sized_int_node
, 127));
1310 gimple_set_location (g
, loc
);
1311 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1313 tree c
= build4_loc (loc
, ARRAY_REF
, pointer_sized_int_node
,
1314 ubsan_vptr_type_cache_decl
, gimple_assign_lhs (g
),
1315 NULL_TREE
, NULL_TREE
);
1316 g
= gimple_build_assign (make_ssa_name (pointer_sized_int_node
),
1318 gimple_set_location (g
, loc
);
1319 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1321 basic_block then_bb
, fallthru2_bb
;
1322 gimple_stmt_iterator cond_insert_point
1323 = create_cond_insert_point (gsip
, false, false, true,
1324 &then_bb
, &fallthru2_bb
);
1325 g
= gimple_build_cond (NE_EXPR
, gimple_assign_lhs (g
), hash
,
1326 NULL_TREE
, NULL_TREE
);
1327 gimple_set_location (g
, loc
);
1328 gsi_insert_after (&cond_insert_point
, g
, GSI_NEW_STMT
);
1329 *gsip
= gsi_after_labels (then_bb
);
1330 if (fallthru_bb
== NULL
)
1331 fallthru_bb
= fallthru2_bb
;
1334 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc
,
1335 ubsan_type_descriptor (type
), NULL_TREE
, ti_decl_addr
,
1336 build_int_cst (unsigned_char_type_node
, ckind
),
1338 data
= build_fold_addr_expr_loc (loc
, data
);
1339 enum built_in_function bcode
1340 = (flag_sanitize_recover
& SANITIZE_VPTR
)
1341 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1342 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT
;
1344 g
= gimple_build_call (builtin_decl_explicit (bcode
), 3, data
, op
, hash
);
1345 gimple_set_location (g
, loc
);
1346 gsi_insert_before (gsip
, g
, GSI_SAME_STMT
);
1348 /* Point GSI to next logical statement. */
1349 *gsip
= gsi_start_bb (fallthru_bb
);
1351 /* Get rid of the UBSAN_VPTR call from the IR. */
1352 unlink_stmt_vdef (stmt
);
1353 gsi_remove (&gsi
, true);
1357 /* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1358 whether the pointer is on the left hand side of the assignment. */
1361 instrument_mem_ref (tree mem
, tree base
, gimple_stmt_iterator
*iter
,
1364 enum ubsan_null_ckind ikind
= is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
;
1365 unsigned int align
= 0;
1366 if (sanitize_flags_p (SANITIZE_ALIGNMENT
))
1368 align
= min_align_of_type (TREE_TYPE (base
));
1372 if (align
== 0 && !sanitize_flags_p (SANITIZE_NULL
))
1374 tree t
= TREE_OPERAND (base
, 0);
1375 if (!POINTER_TYPE_P (TREE_TYPE (t
)))
1377 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base
)) && mem
!= base
)
1378 ikind
= UBSAN_MEMBER_ACCESS
;
1379 tree kind
= build_int_cst (build_pointer_type (TREE_TYPE (base
)), ikind
);
1380 tree alignt
= build_int_cst (pointer_sized_int_node
, align
);
1381 gcall
*g
= gimple_build_call_internal (IFN_UBSAN_NULL
, 3, t
, kind
, alignt
);
1382 gimple_set_location (g
, gimple_location (gsi_stmt (*iter
)));
1383 gsi_insert_before (iter
, g
, GSI_SAME_STMT
);
1386 /* Perform the pointer instrumentation. */
1389 instrument_null (gimple_stmt_iterator gsi
, tree t
, bool is_lhs
)
1391 /* Handle also e.g. &s->i. */
1392 if (TREE_CODE (t
) == ADDR_EXPR
)
1393 t
= TREE_OPERAND (t
, 0);
1394 tree base
= get_base_address (t
);
1395 if (base
!= NULL_TREE
1396 && TREE_CODE (base
) == MEM_REF
1397 && TREE_CODE (TREE_OPERAND (base
, 0)) == SSA_NAME
)
1398 instrument_mem_ref (t
, base
, &gsi
, is_lhs
);
1401 /* Instrument pointer arithmetics PTR p+ OFF. */
1404 instrument_pointer_overflow (gimple_stmt_iterator
*gsi
, tree ptr
, tree off
)
1406 if (TYPE_PRECISION (sizetype
) != POINTER_SIZE
)
1408 gcall
*g
= gimple_build_call_internal (IFN_UBSAN_PTR
, 2, ptr
, off
);
1409 gimple_set_location (g
, gimple_location (gsi_stmt (*gsi
)));
1410 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1413 /* Instrument pointer arithmetics if any. */
1416 maybe_instrument_pointer_overflow (gimple_stmt_iterator
*gsi
, tree t
)
1418 if (TYPE_PRECISION (sizetype
) != POINTER_SIZE
)
1421 /* Handle also e.g. &s->i. */
1422 if (TREE_CODE (t
) == ADDR_EXPR
)
1423 t
= TREE_OPERAND (t
, 0);
1425 if (!handled_component_p (t
) && TREE_CODE (t
) != MEM_REF
)
1428 HOST_WIDE_INT bitsize
, bitpos
, bytepos
;
1431 int volatilep
= 0, reversep
, unsignedp
= 0;
1432 tree inner
= get_inner_reference (t
, &bitsize
, &bitpos
, &offset
, &mode
,
1433 &unsignedp
, &reversep
, &volatilep
);
1434 tree moff
= NULL_TREE
;
1436 bool decl_p
= DECL_P (inner
);
1440 if (DECL_REGISTER (inner
))
1443 /* If BASE is a fixed size automatic variable or
1444 global variable defined in the current TU and bitpos
1445 fits, don't instrument anything. */
1446 if (offset
== NULL_TREE
1449 || TREE_CODE (base
) == PARM_DECL
1450 || TREE_CODE (base
) == RESULT_DECL
)
1452 && TREE_CODE (DECL_SIZE (base
)) == INTEGER_CST
1453 && compare_tree_int (DECL_SIZE (base
), bitpos
) >= 0
1454 && (!is_global_var (base
) || decl_binds_to_current_def_p (base
)))
1457 else if (TREE_CODE (inner
) == MEM_REF
)
1459 base
= TREE_OPERAND (inner
, 0);
1460 if (TREE_CODE (base
) == ADDR_EXPR
1461 && DECL_P (TREE_OPERAND (base
, 0))
1462 && !TREE_ADDRESSABLE (TREE_OPERAND (base
, 0))
1463 && !is_global_var (TREE_OPERAND (base
, 0)))
1465 moff
= TREE_OPERAND (inner
, 1);
1466 if (integer_zerop (moff
))
1472 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
1474 bytepos
= bitpos
/ BITS_PER_UNIT
;
1475 if (offset
== NULL_TREE
&& bytepos
== 0 && moff
== NULL_TREE
)
1478 tree base_addr
= base
;
1480 base_addr
= build1 (ADDR_EXPR
,
1481 build_pointer_type (TREE_TYPE (base
)), base
);
1486 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (t
), t
,
1487 build_int_cst (TREE_TYPE (t
), bytepos
));
1489 t
= size_int (bytepos
);
1494 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (t
), t
,
1495 fold_convert (TREE_TYPE (t
), moff
));
1497 t
= fold_convert (sizetype
, moff
);
1499 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
1501 base_addr
= force_gimple_operand_gsi (gsi
, base_addr
, true, NULL_TREE
, true,
1503 instrument_pointer_overflow (gsi
, base_addr
, t
);
1506 /* Build an ubsan builtin call for the signed-integer-overflow
1507 sanitization. CODE says what kind of builtin are we building,
1508 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1509 are operands of the binary operation. */
1512 ubsan_build_overflow_builtin (tree_code code
, location_t loc
, tree lhstype
,
1513 tree op0
, tree op1
, tree
*datap
)
1515 if (flag_sanitize_undefined_trap_on_error
)
1516 return build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1519 if (datap
&& *datap
)
1522 data
= ubsan_create_data ("__ubsan_overflow_data", 1, &loc
,
1523 ubsan_type_descriptor (lhstype
), NULL_TREE
,
1527 enum built_in_function fn_code
;
1532 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1533 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1534 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT
;
1537 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1538 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1539 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT
;
1542 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1543 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1544 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT
;
1547 fn_code
= (flag_sanitize_recover
& SANITIZE_SI_OVERFLOW
)
1548 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1549 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT
;
1554 tree fn
= builtin_decl_explicit (fn_code
);
1555 return build_call_expr_loc (loc
, fn
, 2 + (code
!= NEGATE_EXPR
),
1556 build_fold_addr_expr_loc (loc
, data
),
1557 ubsan_encode_value (op0
, UBSAN_ENCODE_VALUE_RTL
),
1559 ? ubsan_encode_value (op1
,
1560 UBSAN_ENCODE_VALUE_RTL
)
1564 /* Perform the signed integer instrumentation. GSI is the iterator
1565 pointing at statement we are trying to instrument. */
1568 instrument_si_overflow (gimple_stmt_iterator gsi
)
1570 gimple
*stmt
= gsi_stmt (gsi
);
1571 tree_code code
= gimple_assign_rhs_code (stmt
);
1572 tree lhs
= gimple_assign_lhs (stmt
);
1573 tree lhstype
= TREE_TYPE (lhs
);
1574 tree lhsinner
= VECTOR_TYPE_P (lhstype
) ? TREE_TYPE (lhstype
) : lhstype
;
1578 /* If this is not a signed operation, don't instrument anything here.
1579 Also punt on bit-fields. */
1580 if (!INTEGRAL_TYPE_P (lhsinner
)
1581 || TYPE_OVERFLOW_WRAPS (lhsinner
)
1582 || GET_MODE_BITSIZE (TYPE_MODE (lhsinner
)) != TYPE_PRECISION (lhsinner
))
1593 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1594 a
= gimple_assign_rhs1 (stmt
);
1595 b
= gimple_assign_rhs2 (stmt
);
1596 g
= gimple_build_call_internal (code
== PLUS_EXPR
1597 ? IFN_UBSAN_CHECK_ADD
1598 : code
== MINUS_EXPR
1599 ? IFN_UBSAN_CHECK_SUB
1600 : IFN_UBSAN_CHECK_MUL
, 2, a
, b
);
1601 gimple_call_set_lhs (g
, lhs
);
1602 gsi_replace (&gsi
, g
, true);
1605 /* Represent i = -u;
1607 i = UBSAN_CHECK_SUB (0, u); */
1608 a
= build_zero_cst (lhstype
);
1609 b
= gimple_assign_rhs1 (stmt
);
1610 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1611 gimple_call_set_lhs (g
, lhs
);
1612 gsi_replace (&gsi
, g
, true);
1615 /* Transform i = ABS_EXPR<u>;
1617 _N = UBSAN_CHECK_SUB (0, u);
1618 i = ABS_EXPR<_N>; */
1619 a
= build_zero_cst (lhstype
);
1620 b
= gimple_assign_rhs1 (stmt
);
1621 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
1622 a
= make_ssa_name (lhstype
);
1623 gimple_call_set_lhs (g
, a
);
1624 gimple_set_location (g
, gimple_location (stmt
));
1625 gsi_insert_before (&gsi
, g
, GSI_SAME_STMT
);
1626 gimple_assign_set_rhs1 (stmt
, a
);
1634 /* Instrument loads from (non-bitfield) bool and C++ enum values
1635 to check if the memory value is outside of the range of the valid
1639 instrument_bool_enum_load (gimple_stmt_iterator
*gsi
)
1641 gimple
*stmt
= gsi_stmt (*gsi
);
1642 tree rhs
= gimple_assign_rhs1 (stmt
);
1643 tree type
= TREE_TYPE (rhs
);
1644 tree minv
= NULL_TREE
, maxv
= NULL_TREE
;
1646 if (TREE_CODE (type
) == BOOLEAN_TYPE
1647 && sanitize_flags_p (SANITIZE_BOOL
))
1649 minv
= boolean_false_node
;
1650 maxv
= boolean_true_node
;
1652 else if (TREE_CODE (type
) == ENUMERAL_TYPE
1653 && sanitize_flags_p (SANITIZE_ENUM
)
1654 && TREE_TYPE (type
) != NULL_TREE
1655 && TREE_CODE (TREE_TYPE (type
)) == INTEGER_TYPE
1656 && (TYPE_PRECISION (TREE_TYPE (type
))
1657 < GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (type
))))
1659 minv
= TYPE_MIN_VALUE (TREE_TYPE (type
));
1660 maxv
= TYPE_MAX_VALUE (TREE_TYPE (type
));
1665 int modebitsize
= GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type
));
1666 HOST_WIDE_INT bitsize
, bitpos
;
1669 int volatilep
= 0, reversep
, unsignedp
= 0;
1670 tree base
= get_inner_reference (rhs
, &bitsize
, &bitpos
, &offset
, &mode
,
1671 &unsignedp
, &reversep
, &volatilep
);
1672 tree utype
= build_nonstandard_integer_type (modebitsize
, 1);
1674 if ((VAR_P (base
) && DECL_HARD_REGISTER (base
))
1675 || (bitpos
% modebitsize
) != 0
1676 || bitsize
!= modebitsize
1677 || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (utype
)) != modebitsize
1678 || TREE_CODE (gimple_assign_lhs (stmt
)) != SSA_NAME
)
1681 bool ends_bb
= stmt_ends_bb_p (stmt
);
1682 location_t loc
= gimple_location (stmt
);
1683 tree lhs
= gimple_assign_lhs (stmt
);
1684 tree ptype
= build_pointer_type (TREE_TYPE (rhs
));
1685 tree atype
= reference_alias_ptr_type (rhs
);
1686 gimple
*g
= gimple_build_assign (make_ssa_name (ptype
),
1687 build_fold_addr_expr (rhs
));
1688 gimple_set_location (g
, loc
);
1689 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1690 tree mem
= build2 (MEM_REF
, utype
, gimple_assign_lhs (g
),
1691 build_int_cst (atype
, 0));
1692 tree urhs
= make_ssa_name (utype
);
1695 gimple_assign_set_lhs (stmt
, urhs
);
1696 g
= gimple_build_assign (lhs
, NOP_EXPR
, urhs
);
1697 gimple_set_location (g
, loc
);
1698 edge e
= find_fallthru_edge (gimple_bb (stmt
)->succs
);
1699 gsi_insert_on_edge_immediate (e
, g
);
1700 gimple_assign_set_rhs_from_tree (gsi
, mem
);
1702 *gsi
= gsi_for_stmt (g
);
1707 g
= gimple_build_assign (urhs
, mem
);
1708 gimple_set_location (g
, loc
);
1709 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1711 minv
= fold_convert (utype
, minv
);
1712 maxv
= fold_convert (utype
, maxv
);
1713 if (!integer_zerop (minv
))
1715 g
= gimple_build_assign (make_ssa_name (utype
), MINUS_EXPR
, urhs
, minv
);
1716 gimple_set_location (g
, loc
);
1717 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1720 gimple_stmt_iterator gsi2
= *gsi
;
1721 basic_block then_bb
, fallthru_bb
;
1722 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1723 &then_bb
, &fallthru_bb
);
1724 g
= gimple_build_cond (GT_EXPR
, gimple_assign_lhs (g
),
1725 int_const_binop (MINUS_EXPR
, maxv
, minv
),
1726 NULL_TREE
, NULL_TREE
);
1727 gimple_set_location (g
, loc
);
1728 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1732 gimple_assign_set_rhs_with_ops (&gsi2
, NOP_EXPR
, urhs
);
1736 gsi2
= gsi_after_labels (then_bb
);
1737 if (flag_sanitize_undefined_trap_on_error
)
1738 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1741 tree data
= ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc
,
1742 ubsan_type_descriptor (type
), NULL_TREE
,
1744 data
= build_fold_addr_expr_loc (loc
, data
);
1745 enum built_in_function bcode
1746 = (flag_sanitize_recover
& (TREE_CODE (type
) == BOOLEAN_TYPE
1747 ? SANITIZE_BOOL
: SANITIZE_ENUM
))
1748 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1749 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT
;
1750 tree fn
= builtin_decl_explicit (bcode
);
1752 tree val
= ubsan_encode_value (urhs
, UBSAN_ENCODE_VALUE_GIMPLE
);
1753 val
= force_gimple_operand_gsi (&gsi2
, val
, true, NULL_TREE
, true,
1755 g
= gimple_build_call (fn
, 2, data
, val
);
1757 gimple_set_location (g
, loc
);
1758 gsi_insert_before (&gsi2
, g
, GSI_SAME_STMT
);
1759 ubsan_create_edge (g
);
1760 *gsi
= gsi_for_stmt (stmt
);
1763 /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1764 new style handlers. Libubsan uses heuristics to destinguish between old and
1765 new styles and relies on these properties for filename:
1767 a) Location's filename must not be NULL.
1768 b) Location's filename must not be equal to "".
1769 c) Location's filename must not be equal to "\1".
1770 d) First two bytes of filename must not contain '\xff' symbol. */
1773 ubsan_use_new_style_p (location_t loc
)
1775 if (loc
== UNKNOWN_LOCATION
)
1778 expanded_location xloc
= expand_location (loc
);
1779 if (xloc
.file
== NULL
|| strncmp (xloc
.file
, "\1", 2) == 0
1780 || xloc
.file
[0] == '\0' || xloc
.file
[0] == '\xff'
1781 || xloc
.file
[1] == '\xff')
1787 /* Instrument float point-to-integer conversion. TYPE is an integer type of
1788 destination, EXPR is floating-point expression. */
1791 ubsan_instrument_float_cast (location_t loc
, tree type
, tree expr
)
1793 tree expr_type
= TREE_TYPE (expr
);
1794 tree t
, tt
, fn
, min
, max
;
1795 machine_mode mode
= TYPE_MODE (expr_type
);
1796 int prec
= TYPE_PRECISION (type
);
1797 bool uns_p
= TYPE_UNSIGNED (type
);
1798 if (loc
== UNKNOWN_LOCATION
)
1799 loc
= input_location
;
1801 /* Float to integer conversion first truncates toward zero, so
1802 even signed char c = 127.875f; is not problematic.
1803 Therefore, we should complain only if EXPR is unordered or smaller
1804 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1805 TYPE_MAX_VALUE + 1.0. */
1806 if (REAL_MODE_FORMAT (mode
)->b
== 2)
1808 /* For maximum, TYPE_MAX_VALUE might not be representable
1809 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1810 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1811 either representable or infinity. */
1812 REAL_VALUE_TYPE maxval
= dconst1
;
1813 SET_REAL_EXP (&maxval
, REAL_EXP (&maxval
) + prec
- !uns_p
);
1814 real_convert (&maxval
, mode
, &maxval
);
1815 max
= build_real (expr_type
, maxval
);
1817 /* For unsigned, assume -1.0 is always representable. */
1819 min
= build_minus_one_cst (expr_type
);
1822 /* TYPE_MIN_VALUE is generally representable (or -inf),
1823 but TYPE_MIN_VALUE - 1.0 might not be. */
1824 REAL_VALUE_TYPE minval
= dconstm1
, minval2
;
1825 SET_REAL_EXP (&minval
, REAL_EXP (&minval
) + prec
- 1);
1826 real_convert (&minval
, mode
, &minval
);
1827 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &dconst1
);
1828 real_convert (&minval2
, mode
, &minval2
);
1829 if (real_compare (EQ_EXPR
, &minval
, &minval2
)
1830 && !real_isinf (&minval
))
1832 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1833 rounds to TYPE_MIN_VALUE, we need to subtract
1834 more. As REAL_MODE_FORMAT (mode)->p is the number
1835 of base digits, we want to subtract a number that
1836 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1837 times smaller than minval. */
1839 gcc_assert (prec
> REAL_MODE_FORMAT (mode
)->p
);
1840 SET_REAL_EXP (&minval2
,
1841 REAL_EXP (&minval2
) + prec
- 1
1842 - REAL_MODE_FORMAT (mode
)->p
+ 1);
1843 real_arithmetic (&minval2
, MINUS_EXPR
, &minval
, &minval2
);
1844 real_convert (&minval2
, mode
, &minval2
);
1846 min
= build_real (expr_type
, minval2
);
1849 else if (REAL_MODE_FORMAT (mode
)->b
== 10)
1851 /* For _Decimal128 up to 34 decimal digits, - sign,
1852 dot, e, exponent. */
1855 int p
= REAL_MODE_FORMAT (mode
)->p
;
1856 REAL_VALUE_TYPE maxval
, minval
;
1858 /* Use mpfr_snprintf rounding to compute the smallest
1859 representable decimal number greater or equal than
1860 1 << (prec - !uns_p). */
1861 mpfr_init2 (m
, prec
+ 2);
1862 mpfr_set_ui_2exp (m
, 1, prec
- !uns_p
, GMP_RNDN
);
1863 mpfr_snprintf (buf
, sizeof buf
, "%.*RUe", p
- 1, m
);
1864 decimal_real_from_string (&maxval
, buf
);
1865 max
= build_real (expr_type
, maxval
);
1867 /* For unsigned, assume -1.0 is always representable. */
1869 min
= build_minus_one_cst (expr_type
);
1872 /* Use mpfr_snprintf rounding to compute the largest
1873 representable decimal number less or equal than
1874 (-1 << (prec - 1)) - 1. */
1875 mpfr_set_si_2exp (m
, -1, prec
- 1, GMP_RNDN
);
1876 mpfr_sub_ui (m
, m
, 1, GMP_RNDN
);
1877 mpfr_snprintf (buf
, sizeof buf
, "%.*RDe", p
- 1, m
);
1878 decimal_real_from_string (&minval
, buf
);
1879 min
= build_real (expr_type
, minval
);
1886 t
= fold_build2 (UNLE_EXPR
, boolean_type_node
, expr
, min
);
1887 tt
= fold_build2 (UNGE_EXPR
, boolean_type_node
, expr
, max
);
1888 t
= fold_build2 (TRUTH_OR_EXPR
, boolean_type_node
, t
, tt
);
1889 if (integer_zerop (t
))
1892 if (flag_sanitize_undefined_trap_on_error
)
1893 fn
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1896 location_t
*loc_ptr
= NULL
;
1897 unsigned num_locations
= 0;
1898 /* Figure out if we can propagate location to ubsan_data and use new
1899 style handlers in libubsan. */
1900 if (ubsan_use_new_style_p (loc
))
1905 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1906 tree data
= ubsan_create_data ("__ubsan_float_cast_overflow_data",
1907 num_locations
, loc_ptr
,
1908 ubsan_type_descriptor (expr_type
),
1909 ubsan_type_descriptor (type
), NULL_TREE
,
1911 enum built_in_function bcode
1912 = (flag_sanitize_recover
& SANITIZE_FLOAT_CAST
)
1913 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1914 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT
;
1915 fn
= builtin_decl_explicit (bcode
);
1916 fn
= build_call_expr_loc (loc
, fn
, 2,
1917 build_fold_addr_expr_loc (loc
, data
),
1918 ubsan_encode_value (expr
));
1921 return fold_build3 (COND_EXPR
, void_type_node
, t
, fn
, integer_zero_node
);
1924 /* Instrument values passed to function arguments with nonnull attribute. */
1927 instrument_nonnull_arg (gimple_stmt_iterator
*gsi
)
1929 gimple
*stmt
= gsi_stmt (*gsi
);
1931 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1932 while for nonnull sanitization it is clear. */
1933 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
1934 flag_delete_null_pointer_checks
= 1;
1935 loc
[0] = gimple_location (stmt
);
1936 loc
[1] = UNKNOWN_LOCATION
;
1937 for (unsigned int i
= 0; i
< gimple_call_num_args (stmt
); i
++)
1939 tree arg
= gimple_call_arg (stmt
, i
);
1940 if (POINTER_TYPE_P (TREE_TYPE (arg
))
1941 && infer_nonnull_range_by_attribute (stmt
, arg
))
1944 if (!is_gimple_val (arg
))
1946 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
)), arg
);
1947 gimple_set_location (g
, loc
[0]);
1948 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1949 arg
= gimple_assign_lhs (g
);
1952 basic_block then_bb
, fallthru_bb
;
1953 *gsi
= create_cond_insert_point (gsi
, true, false, true,
1954 &then_bb
, &fallthru_bb
);
1955 g
= gimple_build_cond (EQ_EXPR
, arg
,
1956 build_zero_cst (TREE_TYPE (arg
)),
1957 NULL_TREE
, NULL_TREE
);
1958 gimple_set_location (g
, loc
[0]);
1959 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
1961 *gsi
= gsi_after_labels (then_bb
);
1962 if (flag_sanitize_undefined_trap_on_error
)
1963 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1966 tree data
= ubsan_create_data ("__ubsan_nonnull_arg_data",
1968 build_int_cst (integer_type_node
,
1971 data
= build_fold_addr_expr_loc (loc
[0], data
);
1972 enum built_in_function bcode
1973 = (flag_sanitize_recover
& SANITIZE_NONNULL_ATTRIBUTE
)
1974 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1975 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT
;
1976 tree fn
= builtin_decl_explicit (bcode
);
1978 g
= gimple_build_call (fn
, 1, data
);
1980 gimple_set_location (g
, loc
[0]);
1981 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
1982 ubsan_create_edge (g
);
1984 *gsi
= gsi_for_stmt (stmt
);
1986 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
1989 /* Instrument returns in functions with returns_nonnull attribute. */
1992 instrument_nonnull_return (gimple_stmt_iterator
*gsi
)
1994 greturn
*stmt
= as_a
<greturn
*> (gsi_stmt (*gsi
));
1996 tree arg
= gimple_return_retval (stmt
);
1997 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1998 while for nonnull return sanitization it is clear. */
1999 int save_flag_delete_null_pointer_checks
= flag_delete_null_pointer_checks
;
2000 flag_delete_null_pointer_checks
= 1;
2001 loc
[0] = gimple_location (stmt
);
2002 loc
[1] = UNKNOWN_LOCATION
;
2004 && POINTER_TYPE_P (TREE_TYPE (arg
))
2005 && is_gimple_val (arg
)
2006 && infer_nonnull_range_by_attribute (stmt
, arg
))
2008 basic_block then_bb
, fallthru_bb
;
2009 *gsi
= create_cond_insert_point (gsi
, true, false, true,
2010 &then_bb
, &fallthru_bb
);
2011 gimple
*g
= gimple_build_cond (EQ_EXPR
, arg
,
2012 build_zero_cst (TREE_TYPE (arg
)),
2013 NULL_TREE
, NULL_TREE
);
2014 gimple_set_location (g
, loc
[0]);
2015 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
2017 *gsi
= gsi_after_labels (then_bb
);
2018 if (flag_sanitize_undefined_trap_on_error
)
2019 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2022 tree data
= ubsan_create_data ("__ubsan_nonnull_return_data",
2023 1, &loc
[1], NULL_TREE
, NULL_TREE
);
2024 data
= build_fold_addr_expr_loc (loc
[0], data
);
2025 tree data2
= ubsan_create_data ("__ubsan_nonnull_return_data",
2026 1, &loc
[0], NULL_TREE
, NULL_TREE
);
2027 data2
= build_fold_addr_expr_loc (loc
[0], data2
);
2028 enum built_in_function bcode
2029 = (flag_sanitize_recover
& SANITIZE_RETURNS_NONNULL_ATTRIBUTE
)
2030 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1
2031 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT
;
2032 tree fn
= builtin_decl_explicit (bcode
);
2034 g
= gimple_build_call (fn
, 2, data
, data2
);
2036 gimple_set_location (g
, loc
[0]);
2037 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2038 ubsan_create_edge (g
);
2039 *gsi
= gsi_for_stmt (stmt
);
2041 flag_delete_null_pointer_checks
= save_flag_delete_null_pointer_checks
;
2044 /* Instrument memory references. Here we check whether the pointer
2045 points to an out-of-bounds location. */
2048 instrument_object_size (gimple_stmt_iterator
*gsi
, tree t
, bool is_lhs
)
2050 gimple
*stmt
= gsi_stmt (*gsi
);
2051 location_t loc
= gimple_location (stmt
);
2053 tree index
= NULL_TREE
;
2054 HOST_WIDE_INT size_in_bytes
;
2056 type
= TREE_TYPE (t
);
2057 if (VOID_TYPE_P (type
))
2060 switch (TREE_CODE (t
))
2063 if (TREE_CODE (t
) == COMPONENT_REF
2064 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1)) != NULL_TREE
)
2066 tree repr
= DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t
, 1));
2067 t
= build3 (COMPONENT_REF
, TREE_TYPE (repr
), TREE_OPERAND (t
, 0),
2068 repr
, TREE_OPERAND (t
, 2));
2072 index
= TREE_OPERAND (t
, 1);
2084 size_in_bytes
= int_size_in_bytes (type
);
2085 if (size_in_bytes
<= 0)
2088 HOST_WIDE_INT bitsize
, bitpos
;
2091 int volatilep
= 0, reversep
, unsignedp
= 0;
2092 tree inner
= get_inner_reference (t
, &bitsize
, &bitpos
, &offset
, &mode
,
2093 &unsignedp
, &reversep
, &volatilep
);
2095 if (bitpos
% BITS_PER_UNIT
!= 0
2096 || bitsize
!= size_in_bytes
* BITS_PER_UNIT
)
2099 bool decl_p
= DECL_P (inner
);
2103 if (DECL_REGISTER (inner
))
2107 else if (TREE_CODE (inner
) == MEM_REF
)
2108 base
= TREE_OPERAND (inner
, 0);
2111 tree ptr
= build1 (ADDR_EXPR
, build_pointer_type (TREE_TYPE (t
)), t
);
2113 while (TREE_CODE (base
) == SSA_NAME
)
2115 gimple
*def_stmt
= SSA_NAME_DEF_STMT (base
);
2116 if (gimple_assign_ssa_name_copy_p (def_stmt
)
2117 || (gimple_assign_cast_p (def_stmt
)
2118 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt
))))
2119 || (is_gimple_assign (def_stmt
)
2120 && gimple_assign_rhs_code (def_stmt
) == POINTER_PLUS_EXPR
))
2122 tree rhs1
= gimple_assign_rhs1 (def_stmt
);
2123 if (TREE_CODE (rhs1
) == SSA_NAME
2124 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1
))
2133 if (!POINTER_TYPE_P (TREE_TYPE (base
)) && !DECL_P (base
))
2137 tree base_addr
= base
;
2138 gimple
*bos_stmt
= NULL
;
2140 base_addr
= build1 (ADDR_EXPR
,
2141 build_pointer_type (TREE_TYPE (base
)), base
);
2142 unsigned HOST_WIDE_INT size
;
2143 if (compute_builtin_object_size (base_addr
, 0, &size
))
2144 sizet
= build_int_cst (sizetype
, size
);
2147 if (LOCATION_LOCUS (loc
) == UNKNOWN_LOCATION
)
2148 loc
= input_location
;
2149 /* Generate __builtin_object_size call. */
2150 sizet
= builtin_decl_explicit (BUILT_IN_OBJECT_SIZE
);
2151 sizet
= build_call_expr_loc (loc
, sizet
, 2, base_addr
,
2153 sizet
= force_gimple_operand_gsi (gsi
, sizet
, false, NULL_TREE
, true,
2155 /* If the call above didn't end up being an integer constant, go one
2156 statement back and get the __builtin_object_size stmt. Save it,
2157 we might need it later. */
2158 if (SSA_VAR_P (sizet
))
2161 bos_stmt
= gsi_stmt (*gsi
);
2163 /* Move on to where we were. */
2170 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
2172 /* ptr + sizeof (*ptr) - base */
2173 t
= fold_build2 (MINUS_EXPR
, sizetype
,
2174 fold_convert (pointer_sized_int_node
, ptr
),
2175 fold_convert (pointer_sized_int_node
, base_addr
));
2176 t
= fold_build2 (PLUS_EXPR
, sizetype
, t
, TYPE_SIZE_UNIT (type
));
2178 /* Perhaps we can omit the check. */
2179 if (TREE_CODE (t
) == INTEGER_CST
2180 && TREE_CODE (sizet
) == INTEGER_CST
2181 && tree_int_cst_le (t
, sizet
))
2184 if (index
!= NULL_TREE
2185 && TREE_CODE (index
) == SSA_NAME
2186 && TREE_CODE (sizet
) == INTEGER_CST
)
2188 gimple
*def
= SSA_NAME_DEF_STMT (index
);
2189 if (is_gimple_assign (def
)
2190 && gimple_assign_rhs_code (def
) == BIT_AND_EXPR
2191 && TREE_CODE (gimple_assign_rhs2 (def
)) == INTEGER_CST
)
2193 tree cst
= gimple_assign_rhs2 (def
);
2194 tree sz
= fold_build2 (EXACT_DIV_EXPR
, sizetype
, sizet
,
2195 TYPE_SIZE_UNIT (type
));
2196 if (tree_int_cst_sgn (cst
) >= 0
2197 && tree_int_cst_lt (cst
, sz
))
2202 if (bos_stmt
&& gimple_call_builtin_p (bos_stmt
, BUILT_IN_OBJECT_SIZE
))
2203 ubsan_create_edge (bos_stmt
);
2205 /* We have to emit the check. */
2206 t
= force_gimple_operand_gsi (gsi
, t
, true, NULL_TREE
, true,
2208 ptr
= force_gimple_operand_gsi (gsi
, ptr
, true, NULL_TREE
, true,
2210 tree ckind
= build_int_cst (unsigned_char_type_node
,
2211 is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
);
2212 gimple
*g
= gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE
, 4,
2213 ptr
, t
, sizet
, ckind
);
2214 gimple_set_location (g
, loc
);
2215 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2218 /* Instrument values passed to builtin functions. */
2221 instrument_builtin (gimple_stmt_iterator
*gsi
)
2223 gimple
*stmt
= gsi_stmt (*gsi
);
2224 location_t loc
= gimple_location (stmt
);
2226 enum built_in_function fcode
2227 = DECL_FUNCTION_CODE (gimple_call_fndecl (stmt
));
2231 CASE_INT_FN (BUILT_IN_CLZ
):
2234 CASE_INT_FN (BUILT_IN_CTZ
):
2235 arg
= gimple_call_arg (stmt
, 0);
2236 if (!integer_nonzerop (arg
))
2239 if (!is_gimple_val (arg
))
2241 g
= gimple_build_assign (make_ssa_name (TREE_TYPE (arg
)), arg
);
2242 gimple_set_location (g
, loc
);
2243 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2244 arg
= gimple_assign_lhs (g
);
2247 basic_block then_bb
, fallthru_bb
;
2248 *gsi
= create_cond_insert_point (gsi
, true, false, true,
2249 &then_bb
, &fallthru_bb
);
2250 g
= gimple_build_cond (EQ_EXPR
, arg
,
2251 build_zero_cst (TREE_TYPE (arg
)),
2252 NULL_TREE
, NULL_TREE
);
2253 gimple_set_location (g
, loc
);
2254 gsi_insert_after (gsi
, g
, GSI_NEW_STMT
);
2256 *gsi
= gsi_after_labels (then_bb
);
2257 if (flag_sanitize_undefined_trap_on_error
)
2258 g
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2261 tree t
= build_int_cst (unsigned_char_type_node
, kind
);
2262 tree data
= ubsan_create_data ("__ubsan_builtin_data",
2263 1, &loc
, NULL_TREE
, t
, NULL_TREE
);
2264 data
= build_fold_addr_expr_loc (loc
, data
);
2265 enum built_in_function bcode
2266 = (flag_sanitize_recover
& SANITIZE_BUILTIN
)
2267 ? BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN
2268 : BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN_ABORT
;
2269 tree fn
= builtin_decl_explicit (bcode
);
2271 g
= gimple_build_call (fn
, 1, data
);
2273 gimple_set_location (g
, loc
);
2274 gsi_insert_before (gsi
, g
, GSI_SAME_STMT
);
2275 ubsan_create_edge (g
);
2277 *gsi
= gsi_for_stmt (stmt
);
2286 const pass_data pass_data_ubsan
=
2288 GIMPLE_PASS
, /* type */
2290 OPTGROUP_NONE
, /* optinfo_flags */
2291 TV_TREE_UBSAN
, /* tv_id */
2292 ( PROP_cfg
| PROP_ssa
), /* properties_required */
2293 0, /* properties_provided */
2294 0, /* properties_destroyed */
2295 0, /* todo_flags_start */
2296 TODO_update_ssa
, /* todo_flags_finish */
2299 class pass_ubsan
: public gimple_opt_pass
2302 pass_ubsan (gcc::context
*ctxt
)
2303 : gimple_opt_pass (pass_data_ubsan
, ctxt
)
2306 /* opt_pass methods: */
2307 virtual bool gate (function
*)
2309 return sanitize_flags_p ((SANITIZE_NULL
| SANITIZE_SI_OVERFLOW
2310 | SANITIZE_BOOL
| SANITIZE_ENUM
2311 | SANITIZE_ALIGNMENT
2312 | SANITIZE_NONNULL_ATTRIBUTE
2313 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
2314 | SANITIZE_OBJECT_SIZE
2315 | SANITIZE_POINTER_OVERFLOW
2316 | SANITIZE_BUILTIN
));
2319 virtual unsigned int execute (function
*);
2321 }; // class pass_ubsan
2324 pass_ubsan::execute (function
*fun
)
2327 gimple_stmt_iterator gsi
;
2328 unsigned int ret
= 0;
2330 initialize_sanitizer_builtins ();
2332 FOR_EACH_BB_FN (bb
, fun
)
2334 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
2336 gimple
*stmt
= gsi_stmt (gsi
);
2337 if (is_gimple_debug (stmt
) || gimple_clobber_p (stmt
))
2343 if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW
, fun
->decl
))
2344 && is_gimple_assign (stmt
))
2345 instrument_si_overflow (gsi
);
2347 if (sanitize_flags_p (SANITIZE_NULL
| SANITIZE_ALIGNMENT
, fun
->decl
))
2349 if (gimple_store_p (stmt
))
2350 instrument_null (gsi
, gimple_get_lhs (stmt
), true);
2351 if (gimple_assign_single_p (stmt
))
2352 instrument_null (gsi
, gimple_assign_rhs1 (stmt
), false);
2353 if (is_gimple_call (stmt
))
2355 unsigned args_num
= gimple_call_num_args (stmt
);
2356 for (unsigned i
= 0; i
< args_num
; ++i
)
2358 tree arg
= gimple_call_arg (stmt
, i
);
2359 if (is_gimple_reg (arg
) || is_gimple_min_invariant (arg
))
2361 instrument_null (gsi
, arg
, false);
2366 if (sanitize_flags_p (SANITIZE_BOOL
| SANITIZE_ENUM
, fun
->decl
)
2367 && gimple_assign_load_p (stmt
))
2369 instrument_bool_enum_load (&gsi
);
2370 bb
= gimple_bb (stmt
);
2373 if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE
, fun
->decl
)
2374 && is_gimple_call (stmt
)
2375 && !gimple_call_internal_p (stmt
))
2377 instrument_nonnull_arg (&gsi
);
2378 bb
= gimple_bb (stmt
);
2381 if (sanitize_flags_p (SANITIZE_BUILTIN
, fun
->decl
)
2382 && gimple_call_builtin_p (stmt
, BUILT_IN_NORMAL
))
2384 instrument_builtin (&gsi
);
2385 bb
= gimple_bb (stmt
);
2388 if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE
, fun
->decl
)
2389 && gimple_code (stmt
) == GIMPLE_RETURN
)
2391 instrument_nonnull_return (&gsi
);
2392 bb
= gimple_bb (stmt
);
2395 if (sanitize_flags_p (SANITIZE_OBJECT_SIZE
, fun
->decl
))
2397 if (gimple_store_p (stmt
))
2398 instrument_object_size (&gsi
, gimple_get_lhs (stmt
), true);
2399 if (gimple_assign_load_p (stmt
))
2400 instrument_object_size (&gsi
, gimple_assign_rhs1 (stmt
),
2402 if (is_gimple_call (stmt
))
2404 unsigned args_num
= gimple_call_num_args (stmt
);
2405 for (unsigned i
= 0; i
< args_num
; ++i
)
2407 tree arg
= gimple_call_arg (stmt
, i
);
2408 if (is_gimple_reg (arg
) || is_gimple_min_invariant (arg
))
2410 instrument_object_size (&gsi
, arg
, false);
2415 if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW
, fun
->decl
))
2417 if (is_gimple_assign (stmt
)
2418 && gimple_assign_rhs_code (stmt
) == POINTER_PLUS_EXPR
)
2419 instrument_pointer_overflow (&gsi
,
2420 gimple_assign_rhs1 (stmt
),
2421 gimple_assign_rhs2 (stmt
));
2422 if (gimple_store_p (stmt
))
2423 maybe_instrument_pointer_overflow (&gsi
,
2424 gimple_get_lhs (stmt
));
2425 if (gimple_assign_single_p (stmt
))
2426 maybe_instrument_pointer_overflow (&gsi
,
2427 gimple_assign_rhs1 (stmt
));
2428 if (is_gimple_call (stmt
))
2430 unsigned args_num
= gimple_call_num_args (stmt
);
2431 for (unsigned i
= 0; i
< args_num
; ++i
)
2433 tree arg
= gimple_call_arg (stmt
, i
);
2434 if (is_gimple_reg (arg
))
2436 maybe_instrument_pointer_overflow (&gsi
, arg
);
2443 if (gimple_purge_dead_eh_edges (bb
))
2444 ret
= TODO_cleanup_cfg
;
2452 make_pass_ubsan (gcc::context
*ctxt
)
2454 return new pass_ubsan (ctxt
);
2457 #include "gt-ubsan.h"