1 /* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013 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"
25 #include "stor-layout.h"
26 #include "stringpool.h"
28 #include "tree-pass.h"
29 #include "tree-ssa-alias.h"
30 #include "tree-pretty-print.h"
31 #include "internal-fn.h"
32 #include "gimple-expr.h"
34 #include "gimple-iterator.h"
35 #include "gimple-ssa.h"
36 #include "gimple-walk.h"
43 #include "c-family/c-common.h"
47 /* Map from a tree to a VAR_DECL tree. */
49 struct GTY(()) tree_type_map
{
50 struct tree_map_base type
;
54 #define tree_type_map_eq tree_map_base_eq
55 #define tree_type_map_marked_p tree_map_base_marked_p
57 /* Hash from a tree in a tree_type_map. */
60 tree_type_map_hash (const void *item
)
62 return TYPE_UID (((const struct tree_type_map
*)item
)->type
.from
);
65 static GTY ((if_marked ("tree_type_map_marked_p"), param_is (struct tree_type_map
)))
66 htab_t decl_tree_for_type
;
68 /* Lookup a VAR_DECL for TYPE, and return it if we find one. */
71 decl_for_type_lookup (tree type
)
73 /* If the hash table is not initialized yet, create it now. */
74 if (decl_tree_for_type
== NULL
)
76 decl_tree_for_type
= htab_create_ggc (10, tree_type_map_hash
,
78 /* That also means we don't have to bother with the lookup. */
82 struct tree_type_map
*h
, in
;
85 h
= (struct tree_type_map
*)
86 htab_find_with_hash (decl_tree_for_type
, &in
, TYPE_UID (type
));
87 return h
? h
->decl
: NULL_TREE
;
90 /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
93 decl_for_type_insert (tree type
, tree decl
)
95 struct tree_type_map
*h
;
98 h
= ggc_alloc_tree_type_map ();
101 slot
= htab_find_slot_with_hash (decl_tree_for_type
, h
, TYPE_UID (type
),
103 *(struct tree_type_map
**) slot
= h
;
106 /* Helper routine, which encodes a value in the pointer_sized_int_node.
107 Arguments with precision <= POINTER_SIZE are passed directly,
108 the rest is passed by reference. T is a value we are to encode.
109 IN_EXPAND_P is true if this function is called during expansion. */
112 ubsan_encode_value (tree t
, bool in_expand_p
)
114 tree type
= TREE_TYPE (t
);
115 const unsigned int bitsize
= GET_MODE_BITSIZE (TYPE_MODE (type
));
116 if (bitsize
<= POINTER_SIZE
)
117 switch (TREE_CODE (type
))
122 return fold_build1 (NOP_EXPR
, pointer_sized_int_node
, t
);
125 tree itype
= build_nonstandard_integer_type (bitsize
, true);
126 t
= fold_build1 (VIEW_CONVERT_EXPR
, itype
, t
);
127 return fold_convert (pointer_sized_int_node
, t
);
134 if (!DECL_P (t
) || !TREE_ADDRESSABLE (t
))
136 /* The reason for this is that we don't want to pessimize
137 code by making vars unnecessarily addressable. */
138 tree var
= create_tmp_var (type
, NULL
);
139 tree tem
= build2 (MODIFY_EXPR
, void_type_node
, var
, t
);
143 = assign_stack_temp_for_type (TYPE_MODE (type
),
144 GET_MODE_SIZE (TYPE_MODE (type
)),
146 SET_DECL_RTL (var
, mem
);
147 expand_assignment (var
, t
, false);
148 return build_fold_addr_expr (var
);
150 t
= build_fold_addr_expr (var
);
151 return build2 (COMPOUND_EXPR
, TREE_TYPE (t
), tem
, t
);
154 return build_fold_addr_expr (t
);
159 struct __ubsan_type_descriptor
161 unsigned short __typekind;
162 unsigned short __typeinfo;
168 ubsan_type_descriptor_type (void)
170 static const char *field_names
[3]
171 = { "__typekind", "__typeinfo", "__typename" };
173 tree itype
= build_range_type (sizetype
, size_zero_node
, NULL_TREE
);
174 tree flex_arr_type
= build_array_type (char_type_node
, itype
);
176 ret
= make_node (RECORD_TYPE
);
177 for (int i
= 0; i
< 3; i
++)
179 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
180 get_identifier (field_names
[i
]),
181 (i
== 2) ? flex_arr_type
182 : short_unsigned_type_node
);
183 DECL_CONTEXT (fields
[i
]) = ret
;
185 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
187 TYPE_FIELDS (ret
) = fields
[0];
188 TYPE_NAME (ret
) = get_identifier ("__ubsan_type_descriptor");
194 struct __ubsan_source_location
196 const char *__filename;
198 unsigned int __column;
203 ubsan_source_location_type (void)
205 static const char *field_names
[3]
206 = { "__filename", "__line", "__column" };
208 tree const_char_type
= build_qualified_type (char_type_node
,
211 ret
= make_node (RECORD_TYPE
);
212 for (int i
= 0; i
< 3; i
++)
214 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
,
215 get_identifier (field_names
[i
]),
216 (i
== 0) ? build_pointer_type (const_char_type
)
217 : unsigned_type_node
);
218 DECL_CONTEXT (fields
[i
]) = ret
;
220 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
222 TYPE_FIELDS (ret
) = fields
[0];
223 TYPE_NAME (ret
) = get_identifier ("__ubsan_source_location");
228 /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
229 type with its fields filled from a location_t LOC. */
232 ubsan_source_location (location_t loc
)
234 expanded_location xloc
;
235 tree type
= ubsan_source_location_type ();
237 xloc
= expand_location (loc
);
239 /* Fill in the values from LOC. */
240 size_t len
= strlen (xloc
.file
);
241 tree str
= build_string (len
+ 1, xloc
.file
);
242 TREE_TYPE (str
) = build_array_type (char_type_node
,
243 build_index_type (size_int (len
)));
244 TREE_READONLY (str
) = 1;
245 TREE_STATIC (str
) = 1;
246 str
= build_fold_addr_expr (str
);
247 tree ctor
= build_constructor_va (type
, 3, NULL_TREE
, str
, NULL_TREE
,
248 build_int_cst (unsigned_type_node
,
249 xloc
.line
), NULL_TREE
,
250 build_int_cst (unsigned_type_node
,
252 TREE_CONSTANT (ctor
) = 1;
253 TREE_STATIC (ctor
) = 1;
258 /* This routine returns a magic number for TYPE. */
260 static unsigned short
261 get_ubsan_type_info_for_type (tree type
)
263 gcc_assert (TYPE_SIZE (type
) && tree_fits_uhwi_p (TYPE_SIZE (type
)));
264 int prec
= exact_log2 (tree_to_uhwi (TYPE_SIZE (type
)));
265 gcc_assert (prec
!= -1);
266 return (prec
<< 1) | !TYPE_UNSIGNED (type
);
269 /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
270 descriptor. It first looks into the hash table; if not found,
271 create the VAR_DECL, put it into the hash table and return the
272 ADDR_EXPR of it. TYPE describes a particular type. WANT_POINTER_TYPE_P
273 means whether we are interested in the pointer type and not the pointer
277 ubsan_type_descriptor (tree type
, bool want_pointer_type_p
)
279 /* See through any typedefs. */
280 type
= TYPE_MAIN_VARIANT (type
);
282 tree decl
= decl_for_type_lookup (type
);
283 /* It is possible that some of the earlier created DECLs were found
284 unused, in that case they weren't emitted and varpool_get_node
285 returns NULL node on them. But now we really need them. Thus,
287 if (decl
!= NULL_TREE
&& varpool_get_node (decl
))
288 return build_fold_addr_expr (decl
);
290 tree dtype
= ubsan_type_descriptor_type ();
292 const char *tname
= NULL
;
294 unsigned char deref_depth
= 0;
295 unsigned short tkind
, tinfo
;
297 /* Get the name of the type, or the name of the pointer type. */
298 if (want_pointer_type_p
)
300 gcc_assert (POINTER_TYPE_P (type
));
301 type2
= TREE_TYPE (type
);
303 /* Remove any '*' operators from TYPE. */
304 while (POINTER_TYPE_P (type2
))
305 deref_depth
++, type2
= TREE_TYPE (type2
);
307 if (TREE_CODE (type2
) == METHOD_TYPE
)
308 type2
= TYPE_METHOD_BASETYPE (type2
);
311 if (TYPE_NAME (type2
) != NULL
)
313 if (TREE_CODE (TYPE_NAME (type2
)) == IDENTIFIER_NODE
)
314 tname
= IDENTIFIER_POINTER (TYPE_NAME (type2
));
316 tname
= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2
)));
320 /* We weren't able to determine the type name. */
323 /* Decorate the type name with '', '*', "struct", or "union". */
324 pretty_name
= (char *) alloca (strlen (tname
) + 16 + deref_depth
);
325 if (want_pointer_type_p
)
327 int pos
= sprintf (pretty_name
, "'%s%s%s%s%s%s%s",
328 TYPE_VOLATILE (type2
) ? "volatile " : "",
329 TYPE_READONLY (type2
) ? "const " : "",
330 TYPE_RESTRICT (type2
) ? "restrict " : "",
331 TYPE_ATOMIC (type2
) ? "_Atomic " : "",
332 TREE_CODE (type2
) == RECORD_TYPE
334 : TREE_CODE (type2
) == UNION_TYPE
335 ? "union " : "", tname
,
336 deref_depth
== 0 ? "" : " ");
337 while (deref_depth
-- > 0)
338 pretty_name
[pos
++] = '*';
339 pretty_name
[pos
++] = '\'';
340 pretty_name
[pos
] = '\0';
343 sprintf (pretty_name
, "'%s'", tname
);
345 switch (TREE_CODE (type
))
357 tinfo
= get_ubsan_type_info_for_type (type
);
359 /* Create a new VAR_DECL of type descriptor. */
361 static unsigned int type_var_id_num
;
362 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_type", type_var_id_num
++);
363 decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
365 TREE_STATIC (decl
) = 1;
366 TREE_PUBLIC (decl
) = 0;
367 DECL_ARTIFICIAL (decl
) = 1;
368 DECL_IGNORED_P (decl
) = 1;
369 DECL_EXTERNAL (decl
) = 0;
371 size_t len
= strlen (pretty_name
);
372 tree str
= build_string (len
+ 1, pretty_name
);
373 TREE_TYPE (str
) = build_array_type (char_type_node
,
374 build_index_type (size_int (len
)));
375 TREE_READONLY (str
) = 1;
376 TREE_STATIC (str
) = 1;
377 tree ctor
= build_constructor_va (dtype
, 3, NULL_TREE
,
378 build_int_cst (short_unsigned_type_node
,
380 build_int_cst (short_unsigned_type_node
,
381 tinfo
), NULL_TREE
, str
);
382 TREE_CONSTANT (ctor
) = 1;
383 TREE_STATIC (ctor
) = 1;
384 DECL_INITIAL (decl
) = ctor
;
385 rest_of_decl_compilation (decl
, 1, 0);
387 /* Save the VAR_DECL into the hash table. */
388 decl_for_type_insert (type
, decl
);
390 return build_fold_addr_expr (decl
);
393 /* Create a structure for the ubsan library. NAME is a name of the new
394 structure. The arguments in ... are of __ubsan_type_descriptor type
395 and there are at most two of them. MISMATCH are data used by ubsan
399 ubsan_create_data (const char *name
, location_t loc
,
400 const struct ubsan_mismatch_data
*mismatch
, ...)
405 vec
<tree
, va_gc
> *saved_args
= NULL
;
408 /* Firstly, create a pointer to type descriptor type. */
409 tree td_type
= ubsan_type_descriptor_type ();
410 TYPE_READONLY (td_type
) = 1;
411 td_type
= build_pointer_type (td_type
);
412 loc
= LOCATION_LOCUS (loc
);
414 /* Create the structure type. */
415 ret
= make_node (RECORD_TYPE
);
416 if (loc
!= UNKNOWN_LOCATION
)
418 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
419 ubsan_source_location_type ());
420 DECL_CONTEXT (fields
[i
]) = ret
;
424 va_start (args
, mismatch
);
425 for (t
= va_arg (args
, tree
); t
!= NULL_TREE
;
426 i
++, t
= va_arg (args
, tree
))
428 gcc_checking_assert (i
< 3);
429 /* Save the tree arguments for later use. */
430 vec_safe_push (saved_args
, t
);
431 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
433 DECL_CONTEXT (fields
[i
]) = ret
;
435 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
439 if (mismatch
!= NULL
)
441 /* We have to add two more decls. */
442 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
443 pointer_sized_int_node
);
444 DECL_CONTEXT (fields
[i
]) = ret
;
445 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
448 fields
[i
] = build_decl (UNKNOWN_LOCATION
, FIELD_DECL
, NULL_TREE
,
449 unsigned_char_type_node
);
450 DECL_CONTEXT (fields
[i
]) = ret
;
451 DECL_CHAIN (fields
[i
- 1]) = fields
[i
];
455 TYPE_FIELDS (ret
) = fields
[0];
456 TYPE_NAME (ret
) = get_identifier (name
);
459 /* Now, fill in the type. */
461 static unsigned int ubsan_var_id_num
;
462 ASM_GENERATE_INTERNAL_LABEL (tmp_name
, "Lubsan_data", ubsan_var_id_num
++);
463 tree var
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
, get_identifier (tmp_name
),
465 TREE_STATIC (var
) = 1;
466 TREE_PUBLIC (var
) = 0;
467 DECL_ARTIFICIAL (var
) = 1;
468 DECL_IGNORED_P (var
) = 1;
469 DECL_EXTERNAL (var
) = 0;
471 vec
<constructor_elt
, va_gc
> *v
;
473 tree ctor
= build_constructor (ret
, v
);
475 /* If desirable, set the __ubsan_source_location element. */
476 if (loc
!= UNKNOWN_LOCATION
)
477 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, ubsan_source_location (loc
));
479 size_t nelts
= vec_safe_length (saved_args
);
480 for (i
= 0; i
< nelts
; i
++)
482 t
= (*saved_args
)[i
];
483 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, t
);
486 if (mismatch
!= NULL
)
488 /* Append the pointer data. */
489 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, mismatch
->align
);
490 CONSTRUCTOR_APPEND_ELT (v
, NULL_TREE
, mismatch
->ckind
);
493 TREE_CONSTANT (ctor
) = 1;
494 TREE_STATIC (ctor
) = 1;
495 DECL_INITIAL (var
) = ctor
;
496 rest_of_decl_compilation (var
, 1, 0);
501 /* Instrument the __builtin_unreachable call. We just call the libubsan
505 ubsan_instrument_unreachable (location_t loc
)
507 tree data
= ubsan_create_data ("__ubsan_unreachable_data", loc
, NULL
,
509 tree t
= builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE
);
510 return build_call_expr_loc (loc
, t
, 1, build_fold_addr_expr_loc (loc
, data
));
513 /* Return true if T is a call to a libubsan routine. */
516 is_ubsan_builtin_p (tree t
)
518 gcc_checking_assert (TREE_CODE (t
) == FUNCTION_DECL
);
519 return strncmp (IDENTIFIER_POINTER (DECL_NAME (t
)),
520 "__builtin___ubsan_", 18) == 0;
523 /* Expand UBSAN_NULL internal call. */
526 ubsan_expand_null_ifn (gimple_stmt_iterator gsi
)
528 gimple stmt
= gsi_stmt (gsi
);
529 location_t loc
= gimple_location (stmt
);
530 gcc_assert (gimple_call_num_args (stmt
) == 2);
531 tree ptr
= gimple_call_arg (stmt
, 0);
532 tree ckind
= gimple_call_arg (stmt
, 1);
534 basic_block cur_bb
= gsi_bb (gsi
);
536 /* Split the original block holding the pointer dereference. */
537 edge e
= split_block (cur_bb
, stmt
);
539 /* Get a hold on the 'condition block', the 'then block' and the
541 basic_block cond_bb
= e
->src
;
542 basic_block fallthru_bb
= e
->dest
;
543 basic_block then_bb
= create_empty_bb (cond_bb
);
546 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
547 loops_state_set (LOOPS_NEED_FIXUP
);
550 /* Make an edge coming from the 'cond block' into the 'then block';
551 this edge is unlikely taken, so set up the probability accordingly. */
552 e
= make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
553 e
->probability
= PROB_VERY_UNLIKELY
;
555 /* Connect 'then block' with the 'else block'. This is needed
556 as the ubsan routines we call in the 'then block' are not noreturn.
557 The 'then block' only has one outcoming edge. */
558 make_single_succ_edge (then_bb
, fallthru_bb
, EDGE_FALLTHRU
);
560 /* Set up the fallthrough basic block. */
561 e
= find_edge (cond_bb
, fallthru_bb
);
562 e
->flags
= EDGE_FALSE_VALUE
;
563 e
->count
= cond_bb
->count
;
564 e
->probability
= REG_BR_PROB_BASE
- PROB_VERY_UNLIKELY
;
566 /* Update dominance info for the newly created then_bb; note that
567 fallthru_bb's dominance info has already been updated by
569 if (dom_info_available_p (CDI_DOMINATORS
))
570 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
572 /* Put the ubsan builtin call into the newly created BB. */
573 tree fn
= builtin_decl_implicit (BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH
);
574 const struct ubsan_mismatch_data m
575 = { build_zero_cst (pointer_sized_int_node
), ckind
};
576 tree data
= ubsan_create_data ("__ubsan_null_data",
578 ubsan_type_descriptor (TREE_TYPE (ptr
), true),
580 data
= build_fold_addr_expr_loc (loc
, data
);
581 gimple g
= gimple_build_call (fn
, 2, data
,
582 build_zero_cst (pointer_sized_int_node
));
583 gimple_set_location (g
, loc
);
584 gimple_stmt_iterator gsi2
= gsi_start_bb (then_bb
);
585 gsi_insert_after (&gsi2
, g
, GSI_NEW_STMT
);
587 /* Unlink the UBSAN_NULLs vops before replacing it. */
588 unlink_stmt_vdef (stmt
);
590 g
= gimple_build_cond (EQ_EXPR
, ptr
, build_int_cst (TREE_TYPE (ptr
), 0),
591 NULL_TREE
, NULL_TREE
);
592 gimple_set_location (g
, loc
);
594 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
595 gsi_replace (&gsi
, g
, false);
598 /* Instrument a member call. We check whether 'this' is NULL. */
601 instrument_member_call (gimple_stmt_iterator
*iter
)
603 tree this_parm
= gimple_call_arg (gsi_stmt (*iter
), 0);
604 tree kind
= build_int_cst (unsigned_char_type_node
, UBSAN_MEMBER_CALL
);
605 gimple g
= gimple_build_call_internal (IFN_UBSAN_NULL
, 2, this_parm
, kind
);
606 gimple_set_location (g
, gimple_location (gsi_stmt (*iter
)));
607 gsi_insert_before (iter
, g
, GSI_SAME_STMT
);
610 /* Instrument a memory reference. T is the pointer, IS_LHS says
611 whether the pointer is on the left hand side of the assignment. */
614 instrument_mem_ref (tree t
, gimple_stmt_iterator
*iter
, bool is_lhs
)
616 enum ubsan_null_ckind ikind
= is_lhs
? UBSAN_STORE_OF
: UBSAN_LOAD_OF
;
617 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (t
))))
618 ikind
= UBSAN_MEMBER_ACCESS
;
619 tree kind
= build_int_cst (unsigned_char_type_node
, ikind
);
620 gimple g
= gimple_build_call_internal (IFN_UBSAN_NULL
, 2, t
, kind
);
621 gimple_set_location (g
, gimple_location (gsi_stmt (*iter
)));
622 gsi_insert_before (iter
, g
, GSI_SAME_STMT
);
625 /* Perform the pointer instrumentation. */
628 instrument_null (gimple_stmt_iterator gsi
, bool is_lhs
)
630 gimple stmt
= gsi_stmt (gsi
);
631 tree t
= is_lhs
? gimple_get_lhs (stmt
) : gimple_assign_rhs1 (stmt
);
632 t
= get_base_address (t
);
633 const enum tree_code code
= TREE_CODE (t
);
635 && TREE_CODE (TREE_OPERAND (t
, 0)) == SSA_NAME
)
636 instrument_mem_ref (TREE_OPERAND (t
, 0), &gsi
, is_lhs
);
637 else if (code
== ADDR_EXPR
638 && POINTER_TYPE_P (TREE_TYPE (t
))
639 && TREE_CODE (TREE_TYPE (TREE_TYPE (t
))) == METHOD_TYPE
)
640 instrument_member_call (&gsi
);
643 /* Build an ubsan builtin call for the signed-integer-overflow
644 sanitization. CODE says what kind of builtin are we building,
645 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
646 are operands of the binary operation. */
649 ubsan_build_overflow_builtin (tree_code code
, location_t loc
, tree lhstype
,
652 tree data
= ubsan_create_data ("__ubsan_overflow_data", loc
, NULL
,
653 ubsan_type_descriptor (lhstype
, false),
655 enum built_in_function fn_code
;
660 fn_code
= BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
;
663 fn_code
= BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
;
666 fn_code
= BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
;
669 fn_code
= BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
;
674 tree fn
= builtin_decl_explicit (fn_code
);
675 return build_call_expr_loc (loc
, fn
, 2 + (code
!= NEGATE_EXPR
),
676 build_fold_addr_expr_loc (loc
, data
),
677 ubsan_encode_value (op0
, true),
678 op1
? ubsan_encode_value (op1
, true)
682 /* Perform the signed integer instrumentation. GSI is the iterator
683 pointing at statement we are trying to instrument. */
686 instrument_si_overflow (gimple_stmt_iterator gsi
)
688 gimple stmt
= gsi_stmt (gsi
);
689 tree_code code
= gimple_assign_rhs_code (stmt
);
690 tree lhs
= gimple_assign_lhs (stmt
);
691 tree lhstype
= TREE_TYPE (lhs
);
695 /* If this is not a signed operation, don't instrument anything here.
696 Also punt on bit-fields. */
697 if (!INTEGRAL_TYPE_P (lhstype
)
698 || TYPE_OVERFLOW_WRAPS (lhstype
)
699 || GET_MODE_BITSIZE (TYPE_MODE (lhstype
)) != TYPE_PRECISION (lhstype
))
710 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
711 a
= gimple_assign_rhs1 (stmt
);
712 b
= gimple_assign_rhs2 (stmt
);
713 g
= gimple_build_call_internal (code
== PLUS_EXPR
714 ? IFN_UBSAN_CHECK_ADD
716 ? IFN_UBSAN_CHECK_SUB
717 : IFN_UBSAN_CHECK_MUL
, 2, a
, b
);
718 gimple_call_set_lhs (g
, lhs
);
719 gsi_replace (&gsi
, g
, false);
724 i = UBSAN_CHECK_SUB (0, u); */
725 a
= build_int_cst (lhstype
, 0);
726 b
= gimple_assign_rhs1 (stmt
);
727 g
= gimple_build_call_internal (IFN_UBSAN_CHECK_SUB
, 2, a
, b
);
728 gimple_call_set_lhs (g
, lhs
);
729 gsi_replace (&gsi
, g
, false);
736 /* Gate and execute functions for ubsan pass. */
742 gimple_stmt_iterator gsi
;
746 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
);)
748 gimple stmt
= gsi_stmt (gsi
);
749 if (is_gimple_debug (stmt
) || gimple_clobber_p (stmt
))
755 if ((flag_sanitize
& SANITIZE_SI_OVERFLOW
)
756 && is_gimple_assign (stmt
))
757 instrument_si_overflow (gsi
);
759 if (flag_sanitize
& SANITIZE_NULL
)
761 if (gimple_store_p (stmt
))
762 instrument_null (gsi
, true);
763 if (gimple_assign_load_p (stmt
))
764 instrument_null (gsi
, false);
776 return flag_sanitize
& (SANITIZE_NULL
| SANITIZE_SI_OVERFLOW
);
781 const pass_data pass_data_ubsan
=
783 GIMPLE_PASS
, /* type */
785 OPTGROUP_NONE
, /* optinfo_flags */
787 true, /* has_execute */
788 TV_TREE_UBSAN
, /* tv_id */
789 ( PROP_cfg
| PROP_ssa
), /* properties_required */
790 0, /* properties_provided */
791 0, /* properties_destroyed */
792 0, /* todo_flags_start */
793 TODO_update_ssa
, /* todo_flags_finish */
796 class pass_ubsan
: public gimple_opt_pass
799 pass_ubsan (gcc::context
*ctxt
)
800 : gimple_opt_pass (pass_data_ubsan
, ctxt
)
803 /* opt_pass methods: */
804 bool gate () { return gate_ubsan (); }
805 unsigned int execute () { return ubsan_pass (); }
807 }; // class pass_ubsan
812 make_pass_ubsan (gcc::context
*ctxt
)
814 return new pass_ubsan (ctxt
);
817 #include "gt-ubsan.h"