xref: /dflybsd-src/contrib/gcc-8.0/gcc/ubsan.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* UndefinedBehaviorSanitizer, undefined behavior detector.
2*38fd1498Szrj    Copyright (C) 2013-2018 Free Software Foundation, Inc.
3*38fd1498Szrj    Contributed by Marek Polacek <polacek@redhat.com>
4*38fd1498Szrj 
5*38fd1498Szrj This file is part of GCC.
6*38fd1498Szrj 
7*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
8*38fd1498Szrj the terms of the GNU General Public License as published by the Free
9*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
10*38fd1498Szrj version.
11*38fd1498Szrj 
12*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15*38fd1498Szrj for more details.
16*38fd1498Szrj 
17*38fd1498Szrj You should have received a copy of the GNU General Public License
18*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
19*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
20*38fd1498Szrj 
21*38fd1498Szrj #include "config.h"
22*38fd1498Szrj #include "system.h"
23*38fd1498Szrj #include "coretypes.h"
24*38fd1498Szrj #include "backend.h"
25*38fd1498Szrj #include "rtl.h"
26*38fd1498Szrj #include "c-family/c-common.h"
27*38fd1498Szrj #include "gimple.h"
28*38fd1498Szrj #include "cfghooks.h"
29*38fd1498Szrj #include "tree-pass.h"
30*38fd1498Szrj #include "memmodel.h"
31*38fd1498Szrj #include "tm_p.h"
32*38fd1498Szrj #include "ssa.h"
33*38fd1498Szrj #include "cgraph.h"
34*38fd1498Szrj #include "tree-pretty-print.h"
35*38fd1498Szrj #include "stor-layout.h"
36*38fd1498Szrj #include "cfganal.h"
37*38fd1498Szrj #include "gimple-iterator.h"
38*38fd1498Szrj #include "output.h"
39*38fd1498Szrj #include "cfgloop.h"
40*38fd1498Szrj #include "ubsan.h"
41*38fd1498Szrj #include "expr.h"
42*38fd1498Szrj #include "stringpool.h"
43*38fd1498Szrj #include "attribs.h"
44*38fd1498Szrj #include "asan.h"
45*38fd1498Szrj #include "gimplify-me.h"
46*38fd1498Szrj #include "dfp.h"
47*38fd1498Szrj #include "builtins.h"
48*38fd1498Szrj #include "tree-object-size.h"
49*38fd1498Szrj #include "tree-cfg.h"
50*38fd1498Szrj #include "gimple-fold.h"
51*38fd1498Szrj #include "varasm.h"
52*38fd1498Szrj 
53*38fd1498Szrj /* Map from a tree to a VAR_DECL tree.  */
54*38fd1498Szrj 
55*38fd1498Szrj struct GTY((for_user)) tree_type_map {
56*38fd1498Szrj   struct tree_map_base type;
57*38fd1498Szrj   tree decl;
58*38fd1498Szrj };
59*38fd1498Szrj 
60*38fd1498Szrj struct tree_type_map_cache_hasher : ggc_cache_ptr_hash<tree_type_map>
61*38fd1498Szrj {
62*38fd1498Szrj   static inline hashval_t
hashtree_type_map_cache_hasher63*38fd1498Szrj   hash (tree_type_map *t)
64*38fd1498Szrj   {
65*38fd1498Szrj     return TYPE_UID (t->type.from);
66*38fd1498Szrj   }
67*38fd1498Szrj 
68*38fd1498Szrj   static inline bool
equaltree_type_map_cache_hasher69*38fd1498Szrj   equal (tree_type_map *a, tree_type_map *b)
70*38fd1498Szrj   {
71*38fd1498Szrj     return a->type.from == b->type.from;
72*38fd1498Szrj   }
73*38fd1498Szrj 
74*38fd1498Szrj   static int
keep_cache_entrytree_type_map_cache_hasher75*38fd1498Szrj   keep_cache_entry (tree_type_map *&m)
76*38fd1498Szrj   {
77*38fd1498Szrj     return ggc_marked_p (m->type.from);
78*38fd1498Szrj   }
79*38fd1498Szrj };
80*38fd1498Szrj 
81*38fd1498Szrj static GTY ((cache))
82*38fd1498Szrj      hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
83*38fd1498Szrj 
84*38fd1498Szrj /* Lookup a VAR_DECL for TYPE, and return it if we find one.  */
85*38fd1498Szrj 
86*38fd1498Szrj static tree
decl_for_type_lookup(tree type)87*38fd1498Szrj decl_for_type_lookup (tree type)
88*38fd1498Szrj {
89*38fd1498Szrj   /* If the hash table is not initialized yet, create it now.  */
90*38fd1498Szrj   if (decl_tree_for_type == NULL)
91*38fd1498Szrj     {
92*38fd1498Szrj       decl_tree_for_type
93*38fd1498Szrj 	= hash_table<tree_type_map_cache_hasher>::create_ggc (10);
94*38fd1498Szrj       /* That also means we don't have to bother with the lookup.  */
95*38fd1498Szrj       return NULL_TREE;
96*38fd1498Szrj     }
97*38fd1498Szrj 
98*38fd1498Szrj   struct tree_type_map *h, in;
99*38fd1498Szrj   in.type.from = type;
100*38fd1498Szrj 
101*38fd1498Szrj   h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
102*38fd1498Szrj   return h ? h->decl : NULL_TREE;
103*38fd1498Szrj }
104*38fd1498Szrj 
105*38fd1498Szrj /* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable.  */
106*38fd1498Szrj 
107*38fd1498Szrj static void
decl_for_type_insert(tree type,tree decl)108*38fd1498Szrj decl_for_type_insert (tree type, tree decl)
109*38fd1498Szrj {
110*38fd1498Szrj   struct tree_type_map *h;
111*38fd1498Szrj 
112*38fd1498Szrj   h = ggc_alloc<tree_type_map> ();
113*38fd1498Szrj   h->type.from = type;
114*38fd1498Szrj   h->decl = decl;
115*38fd1498Szrj   *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
116*38fd1498Szrj }
117*38fd1498Szrj 
118*38fd1498Szrj /* Helper routine, which encodes a value in the pointer_sized_int_node.
119*38fd1498Szrj    Arguments with precision <= POINTER_SIZE are passed directly,
120*38fd1498Szrj    the rest is passed by reference.  T is a value we are to encode.
121*38fd1498Szrj    PHASE determines when this function is called.  */
122*38fd1498Szrj 
123*38fd1498Szrj tree
ubsan_encode_value(tree t,enum ubsan_encode_value_phase phase)124*38fd1498Szrj ubsan_encode_value (tree t, enum ubsan_encode_value_phase phase)
125*38fd1498Szrj {
126*38fd1498Szrj   tree type = TREE_TYPE (t);
127*38fd1498Szrj   scalar_mode mode = SCALAR_TYPE_MODE (type);
128*38fd1498Szrj   const unsigned int bitsize = GET_MODE_BITSIZE (mode);
129*38fd1498Szrj   if (bitsize <= POINTER_SIZE)
130*38fd1498Szrj     switch (TREE_CODE (type))
131*38fd1498Szrj       {
132*38fd1498Szrj       case BOOLEAN_TYPE:
133*38fd1498Szrj       case ENUMERAL_TYPE:
134*38fd1498Szrj       case INTEGER_TYPE:
135*38fd1498Szrj 	return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
136*38fd1498Szrj       case REAL_TYPE:
137*38fd1498Szrj 	{
138*38fd1498Szrj 	  tree itype = build_nonstandard_integer_type (bitsize, true);
139*38fd1498Szrj 	  t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
140*38fd1498Szrj 	  return fold_convert (pointer_sized_int_node, t);
141*38fd1498Szrj 	}
142*38fd1498Szrj       default:
143*38fd1498Szrj 	gcc_unreachable ();
144*38fd1498Szrj       }
145*38fd1498Szrj   else
146*38fd1498Szrj     {
147*38fd1498Szrj       if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
148*38fd1498Szrj 	{
149*38fd1498Szrj 	  /* The reason for this is that we don't want to pessimize
150*38fd1498Szrj 	     code by making vars unnecessarily addressable.  */
151*38fd1498Szrj 	  tree var;
152*38fd1498Szrj 	  if (phase != UBSAN_ENCODE_VALUE_GENERIC)
153*38fd1498Szrj 	    {
154*38fd1498Szrj 	      var = create_tmp_var (type);
155*38fd1498Szrj 	      mark_addressable (var);
156*38fd1498Szrj 	    }
157*38fd1498Szrj 	  else
158*38fd1498Szrj 	    {
159*38fd1498Szrj 	      var = create_tmp_var_raw (type);
160*38fd1498Szrj 	      TREE_ADDRESSABLE (var) = 1;
161*38fd1498Szrj 	      DECL_CONTEXT (var) = current_function_decl;
162*38fd1498Szrj 	    }
163*38fd1498Szrj 	  if (phase == UBSAN_ENCODE_VALUE_RTL)
164*38fd1498Szrj 	    {
165*38fd1498Szrj 	      rtx mem = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
166*38fd1498Szrj 						    type);
167*38fd1498Szrj 	      SET_DECL_RTL (var, mem);
168*38fd1498Szrj 	      expand_assignment (var, t, false);
169*38fd1498Szrj 	      return build_fold_addr_expr (var);
170*38fd1498Szrj 	    }
171*38fd1498Szrj 	  if (phase != UBSAN_ENCODE_VALUE_GENERIC)
172*38fd1498Szrj 	    {
173*38fd1498Szrj 	      tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
174*38fd1498Szrj 	      t = build_fold_addr_expr (var);
175*38fd1498Szrj 	      return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
176*38fd1498Szrj 	    }
177*38fd1498Szrj 	  else
178*38fd1498Szrj 	    {
179*38fd1498Szrj 	      var = build4 (TARGET_EXPR, type, var, t, NULL_TREE, NULL_TREE);
180*38fd1498Szrj 	      return build_fold_addr_expr (var);
181*38fd1498Szrj 	    }
182*38fd1498Szrj 	}
183*38fd1498Szrj       else
184*38fd1498Szrj 	return build_fold_addr_expr (t);
185*38fd1498Szrj     }
186*38fd1498Szrj }
187*38fd1498Szrj 
188*38fd1498Szrj /* Cached ubsan_get_type_descriptor_type () return value.  */
189*38fd1498Szrj static GTY(()) tree ubsan_type_descriptor_type;
190*38fd1498Szrj 
191*38fd1498Szrj /* Build
192*38fd1498Szrj    struct __ubsan_type_descriptor
193*38fd1498Szrj    {
194*38fd1498Szrj      unsigned short __typekind;
195*38fd1498Szrj      unsigned short __typeinfo;
196*38fd1498Szrj      char __typename[];
197*38fd1498Szrj    }
198*38fd1498Szrj    type.  */
199*38fd1498Szrj 
200*38fd1498Szrj static tree
ubsan_get_type_descriptor_type(void)201*38fd1498Szrj ubsan_get_type_descriptor_type (void)
202*38fd1498Szrj {
203*38fd1498Szrj   static const char *field_names[3]
204*38fd1498Szrj     = { "__typekind", "__typeinfo", "__typename" };
205*38fd1498Szrj   tree fields[3], ret;
206*38fd1498Szrj 
207*38fd1498Szrj   if (ubsan_type_descriptor_type)
208*38fd1498Szrj     return ubsan_type_descriptor_type;
209*38fd1498Szrj 
210*38fd1498Szrj   tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
211*38fd1498Szrj   tree flex_arr_type = build_array_type (char_type_node, itype);
212*38fd1498Szrj 
213*38fd1498Szrj   ret = make_node (RECORD_TYPE);
214*38fd1498Szrj   for (int i = 0; i < 3; i++)
215*38fd1498Szrj     {
216*38fd1498Szrj       fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
217*38fd1498Szrj 			      get_identifier (field_names[i]),
218*38fd1498Szrj 			      (i == 2) ? flex_arr_type
219*38fd1498Szrj 			      : short_unsigned_type_node);
220*38fd1498Szrj       DECL_CONTEXT (fields[i]) = ret;
221*38fd1498Szrj       if (i)
222*38fd1498Szrj 	DECL_CHAIN (fields[i - 1]) = fields[i];
223*38fd1498Szrj     }
224*38fd1498Szrj   tree type_decl = build_decl (input_location, TYPE_DECL,
225*38fd1498Szrj 			       get_identifier ("__ubsan_type_descriptor"),
226*38fd1498Szrj 			       ret);
227*38fd1498Szrj   DECL_IGNORED_P (type_decl) = 1;
228*38fd1498Szrj   DECL_ARTIFICIAL (type_decl) = 1;
229*38fd1498Szrj   TYPE_FIELDS (ret) = fields[0];
230*38fd1498Szrj   TYPE_NAME (ret) = type_decl;
231*38fd1498Szrj   TYPE_STUB_DECL (ret) = type_decl;
232*38fd1498Szrj   layout_type (ret);
233*38fd1498Szrj   ubsan_type_descriptor_type = ret;
234*38fd1498Szrj   return ret;
235*38fd1498Szrj }
236*38fd1498Szrj 
237*38fd1498Szrj /* Cached ubsan_get_source_location_type () return value.  */
238*38fd1498Szrj static GTY(()) tree ubsan_source_location_type;
239*38fd1498Szrj 
240*38fd1498Szrj /* Build
241*38fd1498Szrj    struct __ubsan_source_location
242*38fd1498Szrj    {
243*38fd1498Szrj      const char *__filename;
244*38fd1498Szrj      unsigned int __line;
245*38fd1498Szrj      unsigned int __column;
246*38fd1498Szrj    }
247*38fd1498Szrj    type.  */
248*38fd1498Szrj 
249*38fd1498Szrj tree
ubsan_get_source_location_type(void)250*38fd1498Szrj ubsan_get_source_location_type (void)
251*38fd1498Szrj {
252*38fd1498Szrj   static const char *field_names[3]
253*38fd1498Szrj     = { "__filename", "__line", "__column" };
254*38fd1498Szrj   tree fields[3], ret;
255*38fd1498Szrj   if (ubsan_source_location_type)
256*38fd1498Szrj     return ubsan_source_location_type;
257*38fd1498Szrj 
258*38fd1498Szrj   tree const_char_type = build_qualified_type (char_type_node,
259*38fd1498Szrj 					       TYPE_QUAL_CONST);
260*38fd1498Szrj 
261*38fd1498Szrj   ret = make_node (RECORD_TYPE);
262*38fd1498Szrj   for (int i = 0; i < 3; i++)
263*38fd1498Szrj     {
264*38fd1498Szrj       fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
265*38fd1498Szrj 			      get_identifier (field_names[i]),
266*38fd1498Szrj 			      (i == 0) ? build_pointer_type (const_char_type)
267*38fd1498Szrj 			      : unsigned_type_node);
268*38fd1498Szrj       DECL_CONTEXT (fields[i]) = ret;
269*38fd1498Szrj       if (i)
270*38fd1498Szrj 	DECL_CHAIN (fields[i - 1]) = fields[i];
271*38fd1498Szrj     }
272*38fd1498Szrj   tree type_decl = build_decl (input_location, TYPE_DECL,
273*38fd1498Szrj 			       get_identifier ("__ubsan_source_location"),
274*38fd1498Szrj 			       ret);
275*38fd1498Szrj   DECL_IGNORED_P (type_decl) = 1;
276*38fd1498Szrj   DECL_ARTIFICIAL (type_decl) = 1;
277*38fd1498Szrj   TYPE_FIELDS (ret) = fields[0];
278*38fd1498Szrj   TYPE_NAME (ret) = type_decl;
279*38fd1498Szrj   TYPE_STUB_DECL (ret) = type_decl;
280*38fd1498Szrj   layout_type (ret);
281*38fd1498Szrj   ubsan_source_location_type = ret;
282*38fd1498Szrj   return ret;
283*38fd1498Szrj }
284*38fd1498Szrj 
285*38fd1498Szrj /* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
286*38fd1498Szrj    type with its fields filled from a location_t LOC.  */
287*38fd1498Szrj 
288*38fd1498Szrj static tree
ubsan_source_location(location_t loc)289*38fd1498Szrj ubsan_source_location (location_t loc)
290*38fd1498Szrj {
291*38fd1498Szrj   expanded_location xloc;
292*38fd1498Szrj   tree type = ubsan_get_source_location_type ();
293*38fd1498Szrj 
294*38fd1498Szrj   xloc = expand_location (loc);
295*38fd1498Szrj   tree str;
296*38fd1498Szrj   if (xloc.file == NULL)
297*38fd1498Szrj     {
298*38fd1498Szrj       str = build_int_cst (ptr_type_node, 0);
299*38fd1498Szrj       xloc.line = 0;
300*38fd1498Szrj       xloc.column = 0;
301*38fd1498Szrj     }
302*38fd1498Szrj   else
303*38fd1498Szrj     {
304*38fd1498Szrj       /* Fill in the values from LOC.  */
305*38fd1498Szrj       size_t len = strlen (xloc.file) + 1;
306*38fd1498Szrj       str = build_string (len, xloc.file);
307*38fd1498Szrj       TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
308*38fd1498Szrj       TREE_READONLY (str) = 1;
309*38fd1498Szrj       TREE_STATIC (str) = 1;
310*38fd1498Szrj       str = build_fold_addr_expr (str);
311*38fd1498Szrj     }
312*38fd1498Szrj   tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE,
313*38fd1498Szrj 				    build_int_cst (unsigned_type_node,
314*38fd1498Szrj 						   xloc.line), NULL_TREE,
315*38fd1498Szrj 				    build_int_cst (unsigned_type_node,
316*38fd1498Szrj 						   xloc.column));
317*38fd1498Szrj   TREE_CONSTANT (ctor) = 1;
318*38fd1498Szrj   TREE_STATIC (ctor) = 1;
319*38fd1498Szrj 
320*38fd1498Szrj   return ctor;
321*38fd1498Szrj }
322*38fd1498Szrj 
323*38fd1498Szrj /* This routine returns a magic number for TYPE.  */
324*38fd1498Szrj 
325*38fd1498Szrj static unsigned short
get_ubsan_type_info_for_type(tree type)326*38fd1498Szrj get_ubsan_type_info_for_type (tree type)
327*38fd1498Szrj {
328*38fd1498Szrj   if (TREE_CODE (type) == REAL_TYPE)
329*38fd1498Szrj     return tree_to_uhwi (TYPE_SIZE (type));
330*38fd1498Szrj   else if (INTEGRAL_TYPE_P (type))
331*38fd1498Szrj     {
332*38fd1498Szrj       int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)));
333*38fd1498Szrj       gcc_assert (prec != -1);
334*38fd1498Szrj       return (prec << 1) | !TYPE_UNSIGNED (type);
335*38fd1498Szrj     }
336*38fd1498Szrj   else
337*38fd1498Szrj     return 0;
338*38fd1498Szrj }
339*38fd1498Szrj 
340*38fd1498Szrj /* Counters for internal labels.  ubsan_ids[0] for Lubsan_type,
341*38fd1498Szrj    ubsan_ids[1] for Lubsan_data labels.  */
342*38fd1498Szrj static GTY(()) unsigned int ubsan_ids[2];
343*38fd1498Szrj 
344*38fd1498Szrj /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
345*38fd1498Szrj    descriptor.  It first looks into the hash table; if not found,
346*38fd1498Szrj    create the VAR_DECL, put it into the hash table and return the
347*38fd1498Szrj    ADDR_EXPR of it.  TYPE describes a particular type.  PSTYLE is
348*38fd1498Szrj    an enum controlling how we want to print the type.  */
349*38fd1498Szrj 
350*38fd1498Szrj tree
ubsan_type_descriptor(tree type,enum ubsan_print_style pstyle)351*38fd1498Szrj ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
352*38fd1498Szrj {
353*38fd1498Szrj   /* See through any typedefs.  */
354*38fd1498Szrj   type = TYPE_MAIN_VARIANT (type);
355*38fd1498Szrj 
356*38fd1498Szrj   tree decl = decl_for_type_lookup (type);
357*38fd1498Szrj   /* It is possible that some of the earlier created DECLs were found
358*38fd1498Szrj      unused, in that case they weren't emitted and varpool_node::get
359*38fd1498Szrj      returns NULL node on them.  But now we really need them.  Thus,
360*38fd1498Szrj      renew them here.  */
361*38fd1498Szrj   if (decl != NULL_TREE && varpool_node::get (decl))
362*38fd1498Szrj     return build_fold_addr_expr (decl);
363*38fd1498Szrj 
364*38fd1498Szrj   tree dtype = ubsan_get_type_descriptor_type ();
365*38fd1498Szrj   tree type2 = type;
366*38fd1498Szrj   const char *tname = NULL;
367*38fd1498Szrj   pretty_printer pretty_name;
368*38fd1498Szrj   unsigned char deref_depth = 0;
369*38fd1498Szrj   unsigned short tkind, tinfo;
370*38fd1498Szrj 
371*38fd1498Szrj   /* Get the name of the type, or the name of the pointer type.  */
372*38fd1498Szrj   if (pstyle == UBSAN_PRINT_POINTER)
373*38fd1498Szrj     {
374*38fd1498Szrj       gcc_assert (POINTER_TYPE_P (type));
375*38fd1498Szrj       type2 = TREE_TYPE (type);
376*38fd1498Szrj 
377*38fd1498Szrj       /* Remove any '*' operators from TYPE.  */
378*38fd1498Szrj       while (POINTER_TYPE_P (type2))
379*38fd1498Szrj         deref_depth++, type2 = TREE_TYPE (type2);
380*38fd1498Szrj 
381*38fd1498Szrj       if (TREE_CODE (type2) == METHOD_TYPE)
382*38fd1498Szrj         type2 = TYPE_METHOD_BASETYPE (type2);
383*38fd1498Szrj     }
384*38fd1498Szrj 
385*38fd1498Szrj   /* If an array, get its type.  */
386*38fd1498Szrj   type2 = strip_array_types (type2);
387*38fd1498Szrj 
388*38fd1498Szrj   if (pstyle == UBSAN_PRINT_ARRAY)
389*38fd1498Szrj     {
390*38fd1498Szrj       while (POINTER_TYPE_P (type2))
391*38fd1498Szrj         deref_depth++, type2 = TREE_TYPE (type2);
392*38fd1498Szrj     }
393*38fd1498Szrj 
394*38fd1498Szrj   if (TYPE_NAME (type2) != NULL)
395*38fd1498Szrj     {
396*38fd1498Szrj       if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE)
397*38fd1498Szrj 	tname = IDENTIFIER_POINTER (TYPE_NAME (type2));
398*38fd1498Szrj       else if (DECL_NAME (TYPE_NAME (type2)) != NULL)
399*38fd1498Szrj 	tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)));
400*38fd1498Szrj     }
401*38fd1498Szrj 
402*38fd1498Szrj   if (tname == NULL)
403*38fd1498Szrj     /* We weren't able to determine the type name.  */
404*38fd1498Szrj     tname = "<unknown>";
405*38fd1498Szrj 
406*38fd1498Szrj   tree eltype = type;
407*38fd1498Szrj   if (pstyle == UBSAN_PRINT_POINTER)
408*38fd1498Szrj     {
409*38fd1498Szrj       pp_printf (&pretty_name, "'%s%s%s%s%s%s%s",
410*38fd1498Szrj 		 TYPE_VOLATILE (type2) ? "volatile " : "",
411*38fd1498Szrj 		 TYPE_READONLY (type2) ? "const " : "",
412*38fd1498Szrj 		 TYPE_RESTRICT (type2) ? "restrict " : "",
413*38fd1498Szrj 		 TYPE_ATOMIC (type2) ? "_Atomic " : "",
414*38fd1498Szrj 		 TREE_CODE (type2) == RECORD_TYPE
415*38fd1498Szrj 		 ? "struct "
416*38fd1498Szrj 		 : TREE_CODE (type2) == UNION_TYPE
417*38fd1498Szrj 		   ? "union " : "", tname,
418*38fd1498Szrj 		 deref_depth == 0 ? "" : " ");
419*38fd1498Szrj       while (deref_depth-- > 0)
420*38fd1498Szrj 	pp_star (&pretty_name);
421*38fd1498Szrj       pp_quote (&pretty_name);
422*38fd1498Szrj     }
423*38fd1498Szrj   else if (pstyle == UBSAN_PRINT_ARRAY)
424*38fd1498Szrj     {
425*38fd1498Szrj       /* Pretty print the array dimensions.  */
426*38fd1498Szrj       gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
427*38fd1498Szrj       tree t = type;
428*38fd1498Szrj       pp_printf (&pretty_name, "'%s ", tname);
429*38fd1498Szrj       while (deref_depth-- > 0)
430*38fd1498Szrj 	pp_star (&pretty_name);
431*38fd1498Szrj       while (TREE_CODE (t) == ARRAY_TYPE)
432*38fd1498Szrj 	{
433*38fd1498Szrj 	  pp_left_bracket (&pretty_name);
434*38fd1498Szrj 	  tree dom = TYPE_DOMAIN (t);
435*38fd1498Szrj 	  if (dom != NULL_TREE
436*38fd1498Szrj 	      && TYPE_MAX_VALUE (dom) != NULL_TREE
437*38fd1498Szrj 	      && TREE_CODE (TYPE_MAX_VALUE (dom)) == INTEGER_CST)
438*38fd1498Szrj 	    {
439*38fd1498Szrj 	      unsigned HOST_WIDE_INT m;
440*38fd1498Szrj 	      if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom))
441*38fd1498Szrj 		  && (m = tree_to_uhwi (TYPE_MAX_VALUE (dom))) + 1 != 0)
442*38fd1498Szrj 		pp_unsigned_wide_integer (&pretty_name, m + 1);
443*38fd1498Szrj 	      else
444*38fd1498Szrj 		pp_wide_int (&pretty_name,
445*38fd1498Szrj 			     wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),
446*38fd1498Szrj 			     TYPE_SIGN (TREE_TYPE (dom)));
447*38fd1498Szrj 	    }
448*38fd1498Szrj 	  else
449*38fd1498Szrj 	    /* ??? We can't determine the variable name; print VLA unspec.  */
450*38fd1498Szrj 	    pp_star (&pretty_name);
451*38fd1498Szrj 	  pp_right_bracket (&pretty_name);
452*38fd1498Szrj 	  t = TREE_TYPE (t);
453*38fd1498Szrj 	}
454*38fd1498Szrj       pp_quote (&pretty_name);
455*38fd1498Szrj 
456*38fd1498Szrj       /* Save the tree with stripped types.  */
457*38fd1498Szrj       eltype = t;
458*38fd1498Szrj     }
459*38fd1498Szrj   else
460*38fd1498Szrj     pp_printf (&pretty_name, "'%s'", tname);
461*38fd1498Szrj 
462*38fd1498Szrj   switch (TREE_CODE (eltype))
463*38fd1498Szrj     {
464*38fd1498Szrj     case BOOLEAN_TYPE:
465*38fd1498Szrj     case ENUMERAL_TYPE:
466*38fd1498Szrj     case INTEGER_TYPE:
467*38fd1498Szrj       tkind = 0x0000;
468*38fd1498Szrj       break;
469*38fd1498Szrj     case REAL_TYPE:
470*38fd1498Szrj       /* FIXME: libubsan right now only supports float, double and
471*38fd1498Szrj 	 long double type formats.  */
472*38fd1498Szrj       if (TYPE_MODE (eltype) == TYPE_MODE (float_type_node)
473*38fd1498Szrj 	  || TYPE_MODE (eltype) == TYPE_MODE (double_type_node)
474*38fd1498Szrj 	  || TYPE_MODE (eltype) == TYPE_MODE (long_double_type_node))
475*38fd1498Szrj 	tkind = 0x0001;
476*38fd1498Szrj       else
477*38fd1498Szrj 	tkind = 0xffff;
478*38fd1498Szrj       break;
479*38fd1498Szrj     default:
480*38fd1498Szrj       tkind = 0xffff;
481*38fd1498Szrj       break;
482*38fd1498Szrj     }
483*38fd1498Szrj   tinfo = get_ubsan_type_info_for_type (eltype);
484*38fd1498Szrj 
485*38fd1498Szrj   /* Create a new VAR_DECL of type descriptor.  */
486*38fd1498Szrj   const char *tmp = pp_formatted_text (&pretty_name);
487*38fd1498Szrj   size_t len = strlen (tmp) + 1;
488*38fd1498Szrj   tree str = build_string (len, tmp);
489*38fd1498Szrj   TREE_TYPE (str) = build_array_type_nelts (char_type_node, len);
490*38fd1498Szrj   TREE_READONLY (str) = 1;
491*38fd1498Szrj   TREE_STATIC (str) = 1;
492*38fd1498Szrj 
493*38fd1498Szrj   char tmp_name[32];
494*38fd1498Szrj   ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", ubsan_ids[0]++);
495*38fd1498Szrj   decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
496*38fd1498Szrj 		     dtype);
497*38fd1498Szrj   TREE_STATIC (decl) = 1;
498*38fd1498Szrj   TREE_PUBLIC (decl) = 0;
499*38fd1498Szrj   DECL_ARTIFICIAL (decl) = 1;
500*38fd1498Szrj   DECL_IGNORED_P (decl) = 1;
501*38fd1498Szrj   DECL_EXTERNAL (decl) = 0;
502*38fd1498Szrj   DECL_SIZE (decl)
503*38fd1498Szrj     = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (TREE_TYPE (str)));
504*38fd1498Szrj   DECL_SIZE_UNIT (decl)
505*38fd1498Szrj     = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
506*38fd1498Szrj 		  TYPE_SIZE_UNIT (TREE_TYPE (str)));
507*38fd1498Szrj 
508*38fd1498Szrj   tree ctor = build_constructor_va (dtype, 3, NULL_TREE,
509*38fd1498Szrj 				    build_int_cst (short_unsigned_type_node,
510*38fd1498Szrj 						   tkind), NULL_TREE,
511*38fd1498Szrj 				    build_int_cst (short_unsigned_type_node,
512*38fd1498Szrj 						   tinfo), NULL_TREE, str);
513*38fd1498Szrj   TREE_CONSTANT (ctor) = 1;
514*38fd1498Szrj   TREE_STATIC (ctor) = 1;
515*38fd1498Szrj   DECL_INITIAL (decl) = ctor;
516*38fd1498Szrj   varpool_node::finalize_decl (decl);
517*38fd1498Szrj 
518*38fd1498Szrj   /* Save the VAR_DECL into the hash table.  */
519*38fd1498Szrj   decl_for_type_insert (type, decl);
520*38fd1498Szrj 
521*38fd1498Szrj   return build_fold_addr_expr (decl);
522*38fd1498Szrj }
523*38fd1498Szrj 
524*38fd1498Szrj /* Create a structure for the ubsan library.  NAME is a name of the new
525*38fd1498Szrj    structure.  LOCCNT is number of locations, PLOC points to array of
526*38fd1498Szrj    locations.  The arguments in ... are of __ubsan_type_descriptor type
527*38fd1498Szrj    and there are at most two of them, followed by NULL_TREE, followed
528*38fd1498Szrj    by optional extra arguments and another NULL_TREE.  */
529*38fd1498Szrj 
530*38fd1498Szrj tree
ubsan_create_data(const char * name,int loccnt,const location_t * ploc,...)531*38fd1498Szrj ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
532*38fd1498Szrj {
533*38fd1498Szrj   va_list args;
534*38fd1498Szrj   tree ret, t;
535*38fd1498Szrj   tree fields[6];
536*38fd1498Szrj   vec<tree, va_gc> *saved_args = NULL;
537*38fd1498Szrj   size_t i = 0;
538*38fd1498Szrj   int j;
539*38fd1498Szrj 
540*38fd1498Szrj   /* It is possible that PCH zapped table with definitions of sanitizer
541*38fd1498Szrj      builtins.  Reinitialize them if needed.  */
542*38fd1498Szrj   initialize_sanitizer_builtins ();
543*38fd1498Szrj 
544*38fd1498Szrj   /* Firstly, create a pointer to type descriptor type.  */
545*38fd1498Szrj   tree td_type = ubsan_get_type_descriptor_type ();
546*38fd1498Szrj   td_type = build_pointer_type (td_type);
547*38fd1498Szrj 
548*38fd1498Szrj   /* Create the structure type.  */
549*38fd1498Szrj   ret = make_node (RECORD_TYPE);
550*38fd1498Szrj   for (j = 0; j < loccnt; j++)
551*38fd1498Szrj     {
552*38fd1498Szrj       gcc_checking_assert (i < 2);
553*38fd1498Szrj       fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
554*38fd1498Szrj 			      ubsan_get_source_location_type ());
555*38fd1498Szrj       DECL_CONTEXT (fields[i]) = ret;
556*38fd1498Szrj       if (i)
557*38fd1498Szrj 	DECL_CHAIN (fields[i - 1]) = fields[i];
558*38fd1498Szrj       i++;
559*38fd1498Szrj     }
560*38fd1498Szrj 
561*38fd1498Szrj   va_start (args, ploc);
562*38fd1498Szrj   for (t = va_arg (args, tree); t != NULL_TREE;
563*38fd1498Szrj        i++, t = va_arg (args, tree))
564*38fd1498Szrj     {
565*38fd1498Szrj       gcc_checking_assert (i < 4);
566*38fd1498Szrj       /* Save the tree arguments for later use.  */
567*38fd1498Szrj       vec_safe_push (saved_args, t);
568*38fd1498Szrj       fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
569*38fd1498Szrj 			      td_type);
570*38fd1498Szrj       DECL_CONTEXT (fields[i]) = ret;
571*38fd1498Szrj       if (i)
572*38fd1498Szrj 	DECL_CHAIN (fields[i - 1]) = fields[i];
573*38fd1498Szrj     }
574*38fd1498Szrj 
575*38fd1498Szrj   for (t = va_arg (args, tree); t != NULL_TREE;
576*38fd1498Szrj        i++, t = va_arg (args, tree))
577*38fd1498Szrj     {
578*38fd1498Szrj       gcc_checking_assert (i < 6);
579*38fd1498Szrj       /* Save the tree arguments for later use.  */
580*38fd1498Szrj       vec_safe_push (saved_args, t);
581*38fd1498Szrj       fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
582*38fd1498Szrj 			      TREE_TYPE (t));
583*38fd1498Szrj       DECL_CONTEXT (fields[i]) = ret;
584*38fd1498Szrj       if (i)
585*38fd1498Szrj 	DECL_CHAIN (fields[i - 1]) = fields[i];
586*38fd1498Szrj     }
587*38fd1498Szrj   va_end (args);
588*38fd1498Szrj 
589*38fd1498Szrj   tree type_decl = build_decl (input_location, TYPE_DECL,
590*38fd1498Szrj 			       get_identifier (name), ret);
591*38fd1498Szrj   DECL_IGNORED_P (type_decl) = 1;
592*38fd1498Szrj   DECL_ARTIFICIAL (type_decl) = 1;
593*38fd1498Szrj   TYPE_FIELDS (ret) = fields[0];
594*38fd1498Szrj   TYPE_NAME (ret) = type_decl;
595*38fd1498Szrj   TYPE_STUB_DECL (ret) = type_decl;
596*38fd1498Szrj   layout_type (ret);
597*38fd1498Szrj 
598*38fd1498Szrj   /* Now, fill in the type.  */
599*38fd1498Szrj   char tmp_name[32];
600*38fd1498Szrj   ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_ids[1]++);
601*38fd1498Szrj   tree var = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (tmp_name),
602*38fd1498Szrj 			 ret);
603*38fd1498Szrj   TREE_STATIC (var) = 1;
604*38fd1498Szrj   TREE_PUBLIC (var) = 0;
605*38fd1498Szrj   DECL_ARTIFICIAL (var) = 1;
606*38fd1498Szrj   DECL_IGNORED_P (var) = 1;
607*38fd1498Szrj   DECL_EXTERNAL (var) = 0;
608*38fd1498Szrj 
609*38fd1498Szrj   vec<constructor_elt, va_gc> *v;
610*38fd1498Szrj   vec_alloc (v, i);
611*38fd1498Szrj   tree ctor = build_constructor (ret, v);
612*38fd1498Szrj 
613*38fd1498Szrj   /* If desirable, set the __ubsan_source_location element.  */
614*38fd1498Szrj   for (j = 0; j < loccnt; j++)
615*38fd1498Szrj     {
616*38fd1498Szrj       location_t loc = LOCATION_LOCUS (ploc[j]);
617*38fd1498Szrj       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc));
618*38fd1498Szrj     }
619*38fd1498Szrj 
620*38fd1498Szrj   size_t nelts = vec_safe_length (saved_args);
621*38fd1498Szrj   for (i = 0; i < nelts; i++)
622*38fd1498Szrj     {
623*38fd1498Szrj       t = (*saved_args)[i];
624*38fd1498Szrj       CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
625*38fd1498Szrj     }
626*38fd1498Szrj 
627*38fd1498Szrj   TREE_CONSTANT (ctor) = 1;
628*38fd1498Szrj   TREE_STATIC (ctor) = 1;
629*38fd1498Szrj   DECL_INITIAL (var) = ctor;
630*38fd1498Szrj   varpool_node::finalize_decl (var);
631*38fd1498Szrj 
632*38fd1498Szrj   return var;
633*38fd1498Szrj }
634*38fd1498Szrj 
635*38fd1498Szrj /* Instrument the __builtin_unreachable call.  We just call the libubsan
636*38fd1498Szrj    routine instead.  */
637*38fd1498Szrj 
638*38fd1498Szrj bool
ubsan_instrument_unreachable(gimple_stmt_iterator * gsi)639*38fd1498Szrj ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
640*38fd1498Szrj {
641*38fd1498Szrj   gimple *g;
642*38fd1498Szrj   location_t loc = gimple_location (gsi_stmt (*gsi));
643*38fd1498Szrj 
644*38fd1498Szrj   if (flag_sanitize_undefined_trap_on_error)
645*38fd1498Szrj     g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
646*38fd1498Szrj   else
647*38fd1498Szrj     {
648*38fd1498Szrj       tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
649*38fd1498Szrj 				     NULL_TREE, NULL_TREE);
650*38fd1498Szrj       data = build_fold_addr_expr_loc (loc, data);
651*38fd1498Szrj       tree fn
652*38fd1498Szrj 	= builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
653*38fd1498Szrj       g = gimple_build_call (fn, 1, data);
654*38fd1498Szrj     }
655*38fd1498Szrj   gimple_set_location (g, loc);
656*38fd1498Szrj   gsi_replace (gsi, g, false);
657*38fd1498Szrj   return false;
658*38fd1498Szrj }
659*38fd1498Szrj 
660*38fd1498Szrj /* Return true if T is a call to a libubsan routine.  */
661*38fd1498Szrj 
662*38fd1498Szrj bool
is_ubsan_builtin_p(tree t)663*38fd1498Szrj is_ubsan_builtin_p (tree t)
664*38fd1498Szrj {
665*38fd1498Szrj   return TREE_CODE (t) == FUNCTION_DECL
666*38fd1498Szrj 	 && DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
667*38fd1498Szrj 	 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t)),
668*38fd1498Szrj 		     "__builtin___ubsan_", 18) == 0;
669*38fd1498Szrj }
670*38fd1498Szrj 
671*38fd1498Szrj /* Create a callgraph edge for statement STMT.  */
672*38fd1498Szrj 
673*38fd1498Szrj static void
ubsan_create_edge(gimple * stmt)674*38fd1498Szrj ubsan_create_edge (gimple *stmt)
675*38fd1498Szrj {
676*38fd1498Szrj   gcall *call_stmt = dyn_cast <gcall *> (stmt);
677*38fd1498Szrj   basic_block bb = gimple_bb (stmt);
678*38fd1498Szrj   cgraph_node *node = cgraph_node::get (current_function_decl);
679*38fd1498Szrj   tree decl = gimple_call_fndecl (call_stmt);
680*38fd1498Szrj   if (decl)
681*38fd1498Szrj     node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count);
682*38fd1498Szrj }
683*38fd1498Szrj 
684*38fd1498Szrj /* Expand the UBSAN_BOUNDS special builtin function.  */
685*38fd1498Szrj 
686*38fd1498Szrj bool
ubsan_expand_bounds_ifn(gimple_stmt_iterator * gsi)687*38fd1498Szrj ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
688*38fd1498Szrj {
689*38fd1498Szrj   gimple *stmt = gsi_stmt (*gsi);
690*38fd1498Szrj   location_t loc = gimple_location (stmt);
691*38fd1498Szrj   gcc_assert (gimple_call_num_args (stmt) == 3);
692*38fd1498Szrj 
693*38fd1498Szrj   /* Pick up the arguments of the UBSAN_BOUNDS call.  */
694*38fd1498Szrj   tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)));
695*38fd1498Szrj   tree index = gimple_call_arg (stmt, 1);
696*38fd1498Szrj   tree orig_index = index;
697*38fd1498Szrj   tree bound = gimple_call_arg (stmt, 2);
698*38fd1498Szrj 
699*38fd1498Szrj   gimple_stmt_iterator gsi_orig = *gsi;
700*38fd1498Szrj 
701*38fd1498Szrj   /* Create condition "if (index > bound)".  */
702*38fd1498Szrj   basic_block then_bb, fallthru_bb;
703*38fd1498Szrj   gimple_stmt_iterator cond_insert_point
704*38fd1498Szrj     = create_cond_insert_point (gsi, false, false, true,
705*38fd1498Szrj 				&then_bb, &fallthru_bb);
706*38fd1498Szrj   index = fold_convert (TREE_TYPE (bound), index);
707*38fd1498Szrj   index = force_gimple_operand_gsi (&cond_insert_point, index,
708*38fd1498Szrj 				    true, NULL_TREE,
709*38fd1498Szrj 				    false, GSI_NEW_STMT);
710*38fd1498Szrj   gimple *g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE, NULL_TREE);
711*38fd1498Szrj   gimple_set_location (g, loc);
712*38fd1498Szrj   gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
713*38fd1498Szrj 
714*38fd1498Szrj   /* Generate __ubsan_handle_out_of_bounds call.  */
715*38fd1498Szrj   *gsi = gsi_after_labels (then_bb);
716*38fd1498Szrj   if (flag_sanitize_undefined_trap_on_error)
717*38fd1498Szrj     g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
718*38fd1498Szrj   else
719*38fd1498Szrj     {
720*38fd1498Szrj       tree data
721*38fd1498Szrj 	= ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
722*38fd1498Szrj 			     ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
723*38fd1498Szrj 			     ubsan_type_descriptor (TREE_TYPE (orig_index)),
724*38fd1498Szrj 			     NULL_TREE, NULL_TREE);
725*38fd1498Szrj       data = build_fold_addr_expr_loc (loc, data);
726*38fd1498Szrj       enum built_in_function bcode
727*38fd1498Szrj 	= (flag_sanitize_recover & SANITIZE_BOUNDS)
728*38fd1498Szrj 	  ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
729*38fd1498Szrj 	  : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
730*38fd1498Szrj       tree fn = builtin_decl_explicit (bcode);
731*38fd1498Szrj       tree val = ubsan_encode_value (orig_index, UBSAN_ENCODE_VALUE_GIMPLE);
732*38fd1498Szrj       val = force_gimple_operand_gsi (gsi, val, true, NULL_TREE, true,
733*38fd1498Szrj 				      GSI_SAME_STMT);
734*38fd1498Szrj       g = gimple_build_call (fn, 2, data, val);
735*38fd1498Szrj     }
736*38fd1498Szrj   gimple_set_location (g, loc);
737*38fd1498Szrj   gsi_insert_before (gsi, g, GSI_SAME_STMT);
738*38fd1498Szrj 
739*38fd1498Szrj   /* Get rid of the UBSAN_BOUNDS call from the IR.  */
740*38fd1498Szrj   unlink_stmt_vdef (stmt);
741*38fd1498Szrj   gsi_remove (&gsi_orig, true);
742*38fd1498Szrj 
743*38fd1498Szrj   /* Point GSI to next logical statement.  */
744*38fd1498Szrj   *gsi = gsi_start_bb (fallthru_bb);
745*38fd1498Szrj   return true;
746*38fd1498Szrj }
747*38fd1498Szrj 
748*38fd1498Szrj /* Expand UBSAN_NULL internal call.  The type is kept on the ckind
749*38fd1498Szrj    argument which is a constant, because the middle-end treats pointer
750*38fd1498Szrj    conversions as useless and therefore the type of the first argument
751*38fd1498Szrj    could be changed to any other pointer type.  */
752*38fd1498Szrj 
753*38fd1498Szrj bool
ubsan_expand_null_ifn(gimple_stmt_iterator * gsip)754*38fd1498Szrj ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
755*38fd1498Szrj {
756*38fd1498Szrj   gimple_stmt_iterator gsi = *gsip;
757*38fd1498Szrj   gimple *stmt = gsi_stmt (gsi);
758*38fd1498Szrj   location_t loc = gimple_location (stmt);
759*38fd1498Szrj   gcc_assert (gimple_call_num_args (stmt) == 3);
760*38fd1498Szrj   tree ptr = gimple_call_arg (stmt, 0);
761*38fd1498Szrj   tree ckind = gimple_call_arg (stmt, 1);
762*38fd1498Szrj   tree align = gimple_call_arg (stmt, 2);
763*38fd1498Szrj   tree check_align = NULL_TREE;
764*38fd1498Szrj   bool check_null;
765*38fd1498Szrj 
766*38fd1498Szrj   basic_block cur_bb = gsi_bb (gsi);
767*38fd1498Szrj 
768*38fd1498Szrj   gimple *g;
769*38fd1498Szrj   if (!integer_zerop (align))
770*38fd1498Szrj     {
771*38fd1498Szrj       unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT;
772*38fd1498Szrj       if (compare_tree_int (align, ptralign) == 1)
773*38fd1498Szrj 	{
774*38fd1498Szrj 	  check_align = make_ssa_name (pointer_sized_int_node);
775*38fd1498Szrj 	  g = gimple_build_assign (check_align, NOP_EXPR, ptr);
776*38fd1498Szrj 	  gimple_set_location (g, loc);
777*38fd1498Szrj 	  gsi_insert_before (&gsi, g, GSI_SAME_STMT);
778*38fd1498Szrj 	}
779*38fd1498Szrj     }
780*38fd1498Szrj   check_null = sanitize_flags_p (SANITIZE_NULL);
781*38fd1498Szrj 
782*38fd1498Szrj   if (check_align == NULL_TREE && !check_null)
783*38fd1498Szrj     {
784*38fd1498Szrj       gsi_remove (gsip, true);
785*38fd1498Szrj       /* Unlink the UBSAN_NULLs vops before replacing it.  */
786*38fd1498Szrj       unlink_stmt_vdef (stmt);
787*38fd1498Szrj       return true;
788*38fd1498Szrj     }
789*38fd1498Szrj 
790*38fd1498Szrj   /* Split the original block holding the pointer dereference.  */
791*38fd1498Szrj   edge e = split_block (cur_bb, stmt);
792*38fd1498Szrj 
793*38fd1498Szrj   /* Get a hold on the 'condition block', the 'then block' and the
794*38fd1498Szrj      'else block'.  */
795*38fd1498Szrj   basic_block cond_bb = e->src;
796*38fd1498Szrj   basic_block fallthru_bb = e->dest;
797*38fd1498Szrj   basic_block then_bb = create_empty_bb (cond_bb);
798*38fd1498Szrj   add_bb_to_loop (then_bb, cond_bb->loop_father);
799*38fd1498Szrj   loops_state_set (LOOPS_NEED_FIXUP);
800*38fd1498Szrj 
801*38fd1498Szrj   /* Make an edge coming from the 'cond block' into the 'then block';
802*38fd1498Szrj      this edge is unlikely taken, so set up the probability accordingly.  */
803*38fd1498Szrj   e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
804*38fd1498Szrj   e->probability = profile_probability::very_unlikely ();
805*38fd1498Szrj   then_bb->count = e->count ();
806*38fd1498Szrj 
807*38fd1498Szrj   /* Connect 'then block' with the 'else block'.  This is needed
808*38fd1498Szrj      as the ubsan routines we call in the 'then block' are not noreturn.
809*38fd1498Szrj      The 'then block' only has one outcoming edge.  */
810*38fd1498Szrj   make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
811*38fd1498Szrj 
812*38fd1498Szrj   /* Set up the fallthrough basic block.  */
813*38fd1498Szrj   e = find_edge (cond_bb, fallthru_bb);
814*38fd1498Szrj   e->flags = EDGE_FALSE_VALUE;
815*38fd1498Szrj   e->probability = profile_probability::very_likely ();
816*38fd1498Szrj 
817*38fd1498Szrj   /* Update dominance info for the newly created then_bb; note that
818*38fd1498Szrj      fallthru_bb's dominance info has already been updated by
819*38fd1498Szrj      split_block.  */
820*38fd1498Szrj   if (dom_info_available_p (CDI_DOMINATORS))
821*38fd1498Szrj     set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
822*38fd1498Szrj 
823*38fd1498Szrj   /* Put the ubsan builtin call into the newly created BB.  */
824*38fd1498Szrj   if (flag_sanitize_undefined_trap_on_error)
825*38fd1498Szrj     g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
826*38fd1498Szrj   else
827*38fd1498Szrj     {
828*38fd1498Szrj       enum built_in_function bcode
829*38fd1498Szrj 	= (flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
830*38fd1498Szrj 				    | (check_null ? SANITIZE_NULL : 0)))
831*38fd1498Szrj 	  ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
832*38fd1498Szrj 	  : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT;
833*38fd1498Szrj       tree fn = builtin_decl_implicit (bcode);
834*38fd1498Szrj       int align_log = tree_log2 (align);
835*38fd1498Szrj       tree data
836*38fd1498Szrj 	= ubsan_create_data ("__ubsan_null_data", 1, &loc,
837*38fd1498Szrj 			     ubsan_type_descriptor (TREE_TYPE (ckind),
838*38fd1498Szrj 						    UBSAN_PRINT_POINTER),
839*38fd1498Szrj 			     NULL_TREE,
840*38fd1498Szrj 			     build_int_cst (unsigned_char_type_node,
841*38fd1498Szrj 					    MAX (align_log, 0)),
842*38fd1498Szrj 			     fold_convert (unsigned_char_type_node, ckind),
843*38fd1498Szrj 			     NULL_TREE);
844*38fd1498Szrj       data = build_fold_addr_expr_loc (loc, data);
845*38fd1498Szrj       g = gimple_build_call (fn, 2, data,
846*38fd1498Szrj 			     check_align ? check_align
847*38fd1498Szrj 			     : build_zero_cst (pointer_sized_int_node));
848*38fd1498Szrj     }
849*38fd1498Szrj   gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
850*38fd1498Szrj   gimple_set_location (g, loc);
851*38fd1498Szrj   gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
852*38fd1498Szrj 
853*38fd1498Szrj   /* Unlink the UBSAN_NULLs vops before replacing it.  */
854*38fd1498Szrj   unlink_stmt_vdef (stmt);
855*38fd1498Szrj 
856*38fd1498Szrj   if (check_null)
857*38fd1498Szrj     {
858*38fd1498Szrj       g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr), 0),
859*38fd1498Szrj 			     NULL_TREE, NULL_TREE);
860*38fd1498Szrj       gimple_set_location (g, loc);
861*38fd1498Szrj 
862*38fd1498Szrj       /* Replace the UBSAN_NULL with a GIMPLE_COND stmt.  */
863*38fd1498Szrj       gsi_replace (&gsi, g, false);
864*38fd1498Szrj       stmt = g;
865*38fd1498Szrj     }
866*38fd1498Szrj 
867*38fd1498Szrj   if (check_align)
868*38fd1498Szrj     {
869*38fd1498Szrj       if (check_null)
870*38fd1498Szrj 	{
871*38fd1498Szrj 	  /* Split the block with the condition again.  */
872*38fd1498Szrj 	  e = split_block (cond_bb, stmt);
873*38fd1498Szrj 	  basic_block cond1_bb = e->src;
874*38fd1498Szrj 	  basic_block cond2_bb = e->dest;
875*38fd1498Szrj 
876*38fd1498Szrj 	  /* Make an edge coming from the 'cond1 block' into the 'then block';
877*38fd1498Szrj 	     this edge is unlikely taken, so set up the probability
878*38fd1498Szrj 	     accordingly.  */
879*38fd1498Szrj 	  e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
880*38fd1498Szrj 	  e->probability = profile_probability::very_unlikely ();
881*38fd1498Szrj 
882*38fd1498Szrj 	  /* Set up the fallthrough basic block.  */
883*38fd1498Szrj 	  e = find_edge (cond1_bb, cond2_bb);
884*38fd1498Szrj 	  e->flags = EDGE_FALSE_VALUE;
885*38fd1498Szrj 	  e->probability = profile_probability::very_likely ();
886*38fd1498Szrj 
887*38fd1498Szrj 	  /* Update dominance info.  */
888*38fd1498Szrj 	  if (dom_info_available_p (CDI_DOMINATORS))
889*38fd1498Szrj 	    {
890*38fd1498Szrj 	      set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
891*38fd1498Szrj 	      set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
892*38fd1498Szrj 	    }
893*38fd1498Szrj 
894*38fd1498Szrj 	  gsi2 = gsi_start_bb (cond2_bb);
895*38fd1498Szrj 	}
896*38fd1498Szrj 
897*38fd1498Szrj       tree mask = build_int_cst (pointer_sized_int_node,
898*38fd1498Szrj 				 tree_to_uhwi (align) - 1);
899*38fd1498Szrj       g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
900*38fd1498Szrj 			       BIT_AND_EXPR, check_align, mask);
901*38fd1498Szrj       gimple_set_location (g, loc);
902*38fd1498Szrj       if (check_null)
903*38fd1498Szrj 	gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
904*38fd1498Szrj       else
905*38fd1498Szrj 	gsi_insert_before (&gsi, g, GSI_SAME_STMT);
906*38fd1498Szrj 
907*38fd1498Szrj       g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
908*38fd1498Szrj 			     build_int_cst (pointer_sized_int_node, 0),
909*38fd1498Szrj 			     NULL_TREE, NULL_TREE);
910*38fd1498Szrj       gimple_set_location (g, loc);
911*38fd1498Szrj       if (check_null)
912*38fd1498Szrj 	gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
913*38fd1498Szrj       else
914*38fd1498Szrj 	/* Replace the UBSAN_NULL with a GIMPLE_COND stmt.  */
915*38fd1498Szrj 	gsi_replace (&gsi, g, false);
916*38fd1498Szrj     }
917*38fd1498Szrj   return false;
918*38fd1498Szrj }
919*38fd1498Szrj 
920*38fd1498Szrj #define OBJSZ_MAX_OFFSET (1024 * 16)
921*38fd1498Szrj 
922*38fd1498Szrj /* Expand UBSAN_OBJECT_SIZE internal call.  */
923*38fd1498Szrj 
924*38fd1498Szrj bool
ubsan_expand_objsize_ifn(gimple_stmt_iterator * gsi)925*38fd1498Szrj ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
926*38fd1498Szrj {
927*38fd1498Szrj   gimple *stmt = gsi_stmt (*gsi);
928*38fd1498Szrj   location_t loc = gimple_location (stmt);
929*38fd1498Szrj   gcc_assert (gimple_call_num_args (stmt) == 4);
930*38fd1498Szrj 
931*38fd1498Szrj   tree ptr = gimple_call_arg (stmt, 0);
932*38fd1498Szrj   tree offset = gimple_call_arg (stmt, 1);
933*38fd1498Szrj   tree size = gimple_call_arg (stmt, 2);
934*38fd1498Szrj   tree ckind = gimple_call_arg (stmt, 3);
935*38fd1498Szrj   gimple_stmt_iterator gsi_orig = *gsi;
936*38fd1498Szrj   gimple *g;
937*38fd1498Szrj 
938*38fd1498Szrj   /* See if we can discard the check.  */
939*38fd1498Szrj   if (TREE_CODE (size) != INTEGER_CST
940*38fd1498Szrj       || integer_all_onesp (size))
941*38fd1498Szrj     /* Yes, __builtin_object_size couldn't determine the
942*38fd1498Szrj        object size.  */;
943*38fd1498Szrj   else if (TREE_CODE (offset) == INTEGER_CST
944*38fd1498Szrj 	   && wi::to_widest (offset) >= -OBJSZ_MAX_OFFSET
945*38fd1498Szrj 	   && wi::to_widest (offset) <= -1)
946*38fd1498Szrj     /* The offset is in range [-16K, -1].  */;
947*38fd1498Szrj   else
948*38fd1498Szrj     {
949*38fd1498Szrj       /* if (offset > objsize) */
950*38fd1498Szrj       basic_block then_bb, fallthru_bb;
951*38fd1498Szrj       gimple_stmt_iterator cond_insert_point
952*38fd1498Szrj 	= create_cond_insert_point (gsi, false, false, true,
953*38fd1498Szrj 				    &then_bb, &fallthru_bb);
954*38fd1498Szrj       g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE, NULL_TREE);
955*38fd1498Szrj       gimple_set_location (g, loc);
956*38fd1498Szrj       gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
957*38fd1498Szrj 
958*38fd1498Szrj       /* If the offset is small enough, we don't need the second
959*38fd1498Szrj 	 run-time check.  */
960*38fd1498Szrj       if (TREE_CODE (offset) == INTEGER_CST
961*38fd1498Szrj 	  && wi::to_widest (offset) >= 0
962*38fd1498Szrj 	  && wi::to_widest (offset) <= OBJSZ_MAX_OFFSET)
963*38fd1498Szrj 	*gsi = gsi_after_labels (then_bb);
964*38fd1498Szrj       else
965*38fd1498Szrj 	{
966*38fd1498Szrj 	  /* Don't issue run-time error if (ptr > ptr + offset).  That
967*38fd1498Szrj 	     may happen when computing a POINTER_PLUS_EXPR.  */
968*38fd1498Szrj 	  basic_block then2_bb, fallthru2_bb;
969*38fd1498Szrj 
970*38fd1498Szrj 	  gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
971*38fd1498Szrj 	  cond_insert_point = create_cond_insert_point (&gsi2, false, false,
972*38fd1498Szrj 							true, &then2_bb,
973*38fd1498Szrj 							&fallthru2_bb);
974*38fd1498Szrj 	  /* Convert the pointer to an integer type.  */
975*38fd1498Szrj 	  tree p = make_ssa_name (pointer_sized_int_node);
976*38fd1498Szrj 	  g = gimple_build_assign (p, NOP_EXPR, ptr);
977*38fd1498Szrj 	  gimple_set_location (g, loc);
978*38fd1498Szrj 	  gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
979*38fd1498Szrj 	  p = gimple_assign_lhs (g);
980*38fd1498Szrj 	  /* Compute ptr + offset.  */
981*38fd1498Szrj 	  g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
982*38fd1498Szrj 				   PLUS_EXPR, p, offset);
983*38fd1498Szrj 	  gimple_set_location (g, loc);
984*38fd1498Szrj 	  gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
985*38fd1498Szrj 	  /* Now build the conditional and put it into the IR.  */
986*38fd1498Szrj 	  g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
987*38fd1498Szrj 				 NULL_TREE, NULL_TREE);
988*38fd1498Szrj 	  gimple_set_location (g, loc);
989*38fd1498Szrj 	  gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
990*38fd1498Szrj 	  *gsi = gsi_after_labels (then2_bb);
991*38fd1498Szrj 	}
992*38fd1498Szrj 
993*38fd1498Szrj       /* Generate __ubsan_handle_type_mismatch call.  */
994*38fd1498Szrj       if (flag_sanitize_undefined_trap_on_error)
995*38fd1498Szrj 	g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
996*38fd1498Szrj       else
997*38fd1498Szrj 	{
998*38fd1498Szrj 	  tree data
999*38fd1498Szrj 	    = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
1000*38fd1498Szrj 				 ubsan_type_descriptor (TREE_TYPE (ptr),
1001*38fd1498Szrj 							UBSAN_PRINT_POINTER),
1002*38fd1498Szrj 				 NULL_TREE,
1003*38fd1498Szrj 				 build_zero_cst (unsigned_char_type_node),
1004*38fd1498Szrj 				 ckind,
1005*38fd1498Szrj 				 NULL_TREE);
1006*38fd1498Szrj 	  data = build_fold_addr_expr_loc (loc, data);
1007*38fd1498Szrj 	  enum built_in_function bcode
1008*38fd1498Szrj 	    = (flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
1009*38fd1498Szrj 	      ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
1010*38fd1498Szrj 	      : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT;
1011*38fd1498Szrj 	  tree p = make_ssa_name (pointer_sized_int_node);
1012*38fd1498Szrj 	  g = gimple_build_assign (p, NOP_EXPR, ptr);
1013*38fd1498Szrj 	  gimple_set_location (g, loc);
1014*38fd1498Szrj 	  gsi_insert_before (gsi, g, GSI_SAME_STMT);
1015*38fd1498Szrj 	  g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
1016*38fd1498Szrj 	}
1017*38fd1498Szrj       gimple_set_location (g, loc);
1018*38fd1498Szrj       gsi_insert_before (gsi, g, GSI_SAME_STMT);
1019*38fd1498Szrj 
1020*38fd1498Szrj       /* Point GSI to next logical statement.  */
1021*38fd1498Szrj       *gsi = gsi_start_bb (fallthru_bb);
1022*38fd1498Szrj 
1023*38fd1498Szrj       /* Get rid of the UBSAN_OBJECT_SIZE call from the IR.  */
1024*38fd1498Szrj       unlink_stmt_vdef (stmt);
1025*38fd1498Szrj       gsi_remove (&gsi_orig, true);
1026*38fd1498Szrj       return true;
1027*38fd1498Szrj     }
1028*38fd1498Szrj 
1029*38fd1498Szrj   /* Get rid of the UBSAN_OBJECT_SIZE call from the IR.  */
1030*38fd1498Szrj   unlink_stmt_vdef (stmt);
1031*38fd1498Szrj   gsi_remove (gsi, true);
1032*38fd1498Szrj   return true;
1033*38fd1498Szrj }
1034*38fd1498Szrj 
1035*38fd1498Szrj /* Expand UBSAN_PTR internal call.  */
1036*38fd1498Szrj 
1037*38fd1498Szrj bool
ubsan_expand_ptr_ifn(gimple_stmt_iterator * gsip)1038*38fd1498Szrj ubsan_expand_ptr_ifn (gimple_stmt_iterator *gsip)
1039*38fd1498Szrj {
1040*38fd1498Szrj   gimple_stmt_iterator gsi = *gsip;
1041*38fd1498Szrj   gimple *stmt = gsi_stmt (gsi);
1042*38fd1498Szrj   location_t loc = gimple_location (stmt);
1043*38fd1498Szrj   gcc_assert (gimple_call_num_args (stmt) == 2);
1044*38fd1498Szrj   tree ptr = gimple_call_arg (stmt, 0);
1045*38fd1498Szrj   tree off = gimple_call_arg (stmt, 1);
1046*38fd1498Szrj 
1047*38fd1498Szrj   if (integer_zerop (off))
1048*38fd1498Szrj     {
1049*38fd1498Szrj       gsi_remove (gsip, true);
1050*38fd1498Szrj       unlink_stmt_vdef (stmt);
1051*38fd1498Szrj       return true;
1052*38fd1498Szrj     }
1053*38fd1498Szrj 
1054*38fd1498Szrj   basic_block cur_bb = gsi_bb (gsi);
1055*38fd1498Szrj   tree ptrplusoff = make_ssa_name (pointer_sized_int_node);
1056*38fd1498Szrj   tree ptri = make_ssa_name (pointer_sized_int_node);
1057*38fd1498Szrj   int pos_neg = get_range_pos_neg (off);
1058*38fd1498Szrj 
1059*38fd1498Szrj   /* Split the original block holding the pointer dereference.  */
1060*38fd1498Szrj   edge e = split_block (cur_bb, stmt);
1061*38fd1498Szrj 
1062*38fd1498Szrj   /* Get a hold on the 'condition block', the 'then block' and the
1063*38fd1498Szrj      'else block'.  */
1064*38fd1498Szrj   basic_block cond_bb = e->src;
1065*38fd1498Szrj   basic_block fallthru_bb = e->dest;
1066*38fd1498Szrj   basic_block then_bb = create_empty_bb (cond_bb);
1067*38fd1498Szrj   basic_block cond_pos_bb = NULL, cond_neg_bb = NULL;
1068*38fd1498Szrj   add_bb_to_loop (then_bb, cond_bb->loop_father);
1069*38fd1498Szrj   loops_state_set (LOOPS_NEED_FIXUP);
1070*38fd1498Szrj 
1071*38fd1498Szrj   /* Set up the fallthrough basic block.  */
1072*38fd1498Szrj   e->flags = EDGE_FALSE_VALUE;
1073*38fd1498Szrj   if (pos_neg != 3)
1074*38fd1498Szrj     {
1075*38fd1498Szrj       e->probability = profile_probability::very_likely ();
1076*38fd1498Szrj 
1077*38fd1498Szrj       /* Connect 'then block' with the 'else block'.  This is needed
1078*38fd1498Szrj 	 as the ubsan routines we call in the 'then block' are not noreturn.
1079*38fd1498Szrj 	 The 'then block' only has one outcoming edge.  */
1080*38fd1498Szrj       make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1081*38fd1498Szrj 
1082*38fd1498Szrj       /* Make an edge coming from the 'cond block' into the 'then block';
1083*38fd1498Szrj 	 this edge is unlikely taken, so set up the probability
1084*38fd1498Szrj 	 accordingly.  */
1085*38fd1498Szrj       e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
1086*38fd1498Szrj       e->probability = profile_probability::very_unlikely ();
1087*38fd1498Szrj       then_bb->count = e->count ();
1088*38fd1498Szrj     }
1089*38fd1498Szrj   else
1090*38fd1498Szrj     {
1091*38fd1498Szrj       e->probability = profile_probability::even ();
1092*38fd1498Szrj 
1093*38fd1498Szrj       e = split_block (fallthru_bb, (gimple *) NULL);
1094*38fd1498Szrj       cond_neg_bb = e->src;
1095*38fd1498Szrj       fallthru_bb = e->dest;
1096*38fd1498Szrj       e->probability = profile_probability::very_likely ();
1097*38fd1498Szrj       e->flags = EDGE_FALSE_VALUE;
1098*38fd1498Szrj 
1099*38fd1498Szrj       e = make_edge (cond_neg_bb, then_bb, EDGE_TRUE_VALUE);
1100*38fd1498Szrj       e->probability = profile_probability::very_unlikely ();
1101*38fd1498Szrj       then_bb->count = e->count ();
1102*38fd1498Szrj 
1103*38fd1498Szrj       cond_pos_bb = create_empty_bb (cond_bb);
1104*38fd1498Szrj       add_bb_to_loop (cond_pos_bb, cond_bb->loop_father);
1105*38fd1498Szrj 
1106*38fd1498Szrj       e = make_edge (cond_bb, cond_pos_bb, EDGE_TRUE_VALUE);
1107*38fd1498Szrj       e->probability = profile_probability::even ();
1108*38fd1498Szrj       cond_pos_bb->count = e->count ();
1109*38fd1498Szrj 
1110*38fd1498Szrj       e = make_edge (cond_pos_bb, then_bb, EDGE_TRUE_VALUE);
1111*38fd1498Szrj       e->probability = profile_probability::very_unlikely ();
1112*38fd1498Szrj 
1113*38fd1498Szrj       e = make_edge (cond_pos_bb, fallthru_bb, EDGE_FALSE_VALUE);
1114*38fd1498Szrj       e->probability = profile_probability::very_likely ();
1115*38fd1498Szrj 
1116*38fd1498Szrj       make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1117*38fd1498Szrj     }
1118*38fd1498Szrj 
1119*38fd1498Szrj   gimple *g = gimple_build_assign (ptri, NOP_EXPR, ptr);
1120*38fd1498Szrj   gimple_set_location (g, loc);
1121*38fd1498Szrj   gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1122*38fd1498Szrj   g = gimple_build_assign (ptrplusoff, PLUS_EXPR, ptri, off);
1123*38fd1498Szrj   gimple_set_location (g, loc);
1124*38fd1498Szrj   gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1125*38fd1498Szrj 
1126*38fd1498Szrj   /* Update dominance info for the newly created then_bb; note that
1127*38fd1498Szrj      fallthru_bb's dominance info has already been updated by
1128*38fd1498Szrj      split_block.  */
1129*38fd1498Szrj   if (dom_info_available_p (CDI_DOMINATORS))
1130*38fd1498Szrj     {
1131*38fd1498Szrj       set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
1132*38fd1498Szrj       if (pos_neg == 3)
1133*38fd1498Szrj 	{
1134*38fd1498Szrj 	  set_immediate_dominator (CDI_DOMINATORS, cond_pos_bb, cond_bb);
1135*38fd1498Szrj 	  set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond_bb);
1136*38fd1498Szrj 	}
1137*38fd1498Szrj     }
1138*38fd1498Szrj 
1139*38fd1498Szrj   /* Put the ubsan builtin call into the newly created BB.  */
1140*38fd1498Szrj   if (flag_sanitize_undefined_trap_on_error)
1141*38fd1498Szrj     g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
1142*38fd1498Szrj   else
1143*38fd1498Szrj     {
1144*38fd1498Szrj       enum built_in_function bcode
1145*38fd1498Szrj 	= (flag_sanitize_recover & SANITIZE_POINTER_OVERFLOW)
1146*38fd1498Szrj 	  ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
1147*38fd1498Szrj 	  : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT;
1148*38fd1498Szrj       tree fn = builtin_decl_implicit (bcode);
1149*38fd1498Szrj       tree data
1150*38fd1498Szrj 	= ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc,
1151*38fd1498Szrj 			     NULL_TREE, NULL_TREE);
1152*38fd1498Szrj       data = build_fold_addr_expr_loc (loc, data);
1153*38fd1498Szrj       g = gimple_build_call (fn, 3, data, ptr, ptrplusoff);
1154*38fd1498Szrj     }
1155*38fd1498Szrj   gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
1156*38fd1498Szrj   gimple_set_location (g, loc);
1157*38fd1498Szrj   gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1158*38fd1498Szrj 
1159*38fd1498Szrj   /* Unlink the UBSAN_PTRs vops before replacing it.  */
1160*38fd1498Szrj   unlink_stmt_vdef (stmt);
1161*38fd1498Szrj 
1162*38fd1498Szrj   if (TREE_CODE (off) == INTEGER_CST)
1163*38fd1498Szrj     g = gimple_build_cond (wi::neg_p (wi::to_wide (off)) ? LT_EXPR : GE_EXPR,
1164*38fd1498Szrj 			   ptri, fold_build1 (NEGATE_EXPR, sizetype, off),
1165*38fd1498Szrj 			   NULL_TREE, NULL_TREE);
1166*38fd1498Szrj   else if (pos_neg != 3)
1167*38fd1498Szrj     g = gimple_build_cond (pos_neg == 1 ? LT_EXPR : GT_EXPR,
1168*38fd1498Szrj 			   ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1169*38fd1498Szrj   else
1170*38fd1498Szrj     {
1171*38fd1498Szrj       gsi2 = gsi_start_bb (cond_pos_bb);
1172*38fd1498Szrj       g = gimple_build_cond (LT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1173*38fd1498Szrj       gimple_set_location (g, loc);
1174*38fd1498Szrj       gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1175*38fd1498Szrj 
1176*38fd1498Szrj       gsi2 = gsi_start_bb (cond_neg_bb);
1177*38fd1498Szrj       g = gimple_build_cond (GT_EXPR, ptrplusoff, ptri, NULL_TREE, NULL_TREE);
1178*38fd1498Szrj       gimple_set_location (g, loc);
1179*38fd1498Szrj       gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1180*38fd1498Szrj 
1181*38fd1498Szrj       gimple_seq seq = NULL;
1182*38fd1498Szrj       tree t = gimple_build (&seq, loc, NOP_EXPR, ssizetype, off);
1183*38fd1498Szrj       t = gimple_build (&seq, loc, GE_EXPR, boolean_type_node,
1184*38fd1498Szrj 			t, ssize_int (0));
1185*38fd1498Szrj       gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
1186*38fd1498Szrj       g = gimple_build_cond (NE_EXPR, t, boolean_false_node,
1187*38fd1498Szrj 			     NULL_TREE, NULL_TREE);
1188*38fd1498Szrj     }
1189*38fd1498Szrj   gimple_set_location (g, loc);
1190*38fd1498Szrj   /* Replace the UBSAN_PTR with a GIMPLE_COND stmt.  */
1191*38fd1498Szrj   gsi_replace (&gsi, g, false);
1192*38fd1498Szrj   return false;
1193*38fd1498Szrj }
1194*38fd1498Szrj 
1195*38fd1498Szrj 
1196*38fd1498Szrj /* Cached __ubsan_vptr_type_cache decl.  */
1197*38fd1498Szrj static GTY(()) tree ubsan_vptr_type_cache_decl;
1198*38fd1498Szrj 
1199*38fd1498Szrj /* Expand UBSAN_VPTR internal call.  The type is kept on the ckind
1200*38fd1498Szrj    argument which is a constant, because the middle-end treats pointer
1201*38fd1498Szrj    conversions as useless and therefore the type of the first argument
1202*38fd1498Szrj    could be changed to any other pointer type.  */
1203*38fd1498Szrj 
1204*38fd1498Szrj bool
ubsan_expand_vptr_ifn(gimple_stmt_iterator * gsip)1205*38fd1498Szrj ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
1206*38fd1498Szrj {
1207*38fd1498Szrj   gimple_stmt_iterator gsi = *gsip;
1208*38fd1498Szrj   gimple *stmt = gsi_stmt (gsi);
1209*38fd1498Szrj   location_t loc = gimple_location (stmt);
1210*38fd1498Szrj   gcc_assert (gimple_call_num_args (stmt) == 5);
1211*38fd1498Szrj   tree op = gimple_call_arg (stmt, 0);
1212*38fd1498Szrj   tree vptr = gimple_call_arg (stmt, 1);
1213*38fd1498Szrj   tree str_hash = gimple_call_arg (stmt, 2);
1214*38fd1498Szrj   tree ti_decl_addr = gimple_call_arg (stmt, 3);
1215*38fd1498Szrj   tree ckind_tree = gimple_call_arg (stmt, 4);
1216*38fd1498Szrj   ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1217*38fd1498Szrj   tree type = TREE_TYPE (TREE_TYPE (ckind_tree));
1218*38fd1498Szrj   gimple *g;
1219*38fd1498Szrj   basic_block fallthru_bb = NULL;
1220*38fd1498Szrj 
1221*38fd1498Szrj   if (ckind == UBSAN_DOWNCAST_POINTER)
1222*38fd1498Szrj     {
1223*38fd1498Szrj       /* Guard everything with if (op != NULL) { ... }.  */
1224*38fd1498Szrj       basic_block then_bb;
1225*38fd1498Szrj       gimple_stmt_iterator cond_insert_point
1226*38fd1498Szrj 	= create_cond_insert_point (gsip, false, false, true,
1227*38fd1498Szrj 				    &then_bb, &fallthru_bb);
1228*38fd1498Szrj       g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)),
1229*38fd1498Szrj 			     NULL_TREE, NULL_TREE);
1230*38fd1498Szrj       gimple_set_location (g, loc);
1231*38fd1498Szrj       gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1232*38fd1498Szrj       *gsip = gsi_after_labels (then_bb);
1233*38fd1498Szrj       gsi_remove (&gsi, false);
1234*38fd1498Szrj       gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1235*38fd1498Szrj       gsi = *gsip;
1236*38fd1498Szrj     }
1237*38fd1498Szrj 
1238*38fd1498Szrj   tree htype = TREE_TYPE (str_hash);
1239*38fd1498Szrj   tree cst = wide_int_to_tree (htype,
1240*38fd1498Szrj 			       wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1241*38fd1498Szrj 			       | 0xeb382d69, 64));
1242*38fd1498Szrj   g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1243*38fd1498Szrj 			   vptr, str_hash);
1244*38fd1498Szrj   gimple_set_location (g, loc);
1245*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1246*38fd1498Szrj   g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1247*38fd1498Szrj 			   gimple_assign_lhs (g), cst);
1248*38fd1498Szrj   gimple_set_location (g, loc);
1249*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1250*38fd1498Szrj   tree t1 = gimple_assign_lhs (g);
1251*38fd1498Szrj   g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1252*38fd1498Szrj 			   t1, build_int_cst (integer_type_node, 47));
1253*38fd1498Szrj   gimple_set_location (g, loc);
1254*38fd1498Szrj   tree t2 = gimple_assign_lhs (g);
1255*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1256*38fd1498Szrj   g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1257*38fd1498Szrj 			   vptr, t1);
1258*38fd1498Szrj   gimple_set_location (g, loc);
1259*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1260*38fd1498Szrj   g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1261*38fd1498Szrj 			   t2, gimple_assign_lhs (g));
1262*38fd1498Szrj   gimple_set_location (g, loc);
1263*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1264*38fd1498Szrj   g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1265*38fd1498Szrj 			   gimple_assign_lhs (g), cst);
1266*38fd1498Szrj   gimple_set_location (g, loc);
1267*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1268*38fd1498Szrj   tree t3 = gimple_assign_lhs (g);
1269*38fd1498Szrj   g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1270*38fd1498Szrj 			   t3, build_int_cst (integer_type_node, 47));
1271*38fd1498Szrj   gimple_set_location (g, loc);
1272*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1273*38fd1498Szrj   g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1274*38fd1498Szrj 			   t3, gimple_assign_lhs (g));
1275*38fd1498Szrj   gimple_set_location (g, loc);
1276*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1277*38fd1498Szrj   g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1278*38fd1498Szrj 			   gimple_assign_lhs (g), cst);
1279*38fd1498Szrj   gimple_set_location (g, loc);
1280*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1281*38fd1498Szrj   if (!useless_type_conversion_p (pointer_sized_int_node, htype))
1282*38fd1498Szrj     {
1283*38fd1498Szrj       g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1284*38fd1498Szrj 			       NOP_EXPR, gimple_assign_lhs (g));
1285*38fd1498Szrj       gimple_set_location (g, loc);
1286*38fd1498Szrj       gsi_insert_before (gsip, g, GSI_SAME_STMT);
1287*38fd1498Szrj     }
1288*38fd1498Szrj   tree hash = gimple_assign_lhs (g);
1289*38fd1498Szrj 
1290*38fd1498Szrj   if (ubsan_vptr_type_cache_decl == NULL_TREE)
1291*38fd1498Szrj     {
1292*38fd1498Szrj       tree atype = build_array_type_nelts (pointer_sized_int_node, 128);
1293*38fd1498Szrj       tree array = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1294*38fd1498Szrj 			       get_identifier ("__ubsan_vptr_type_cache"),
1295*38fd1498Szrj 			       atype);
1296*38fd1498Szrj       DECL_ARTIFICIAL (array) = 1;
1297*38fd1498Szrj       DECL_IGNORED_P (array) = 1;
1298*38fd1498Szrj       TREE_PUBLIC (array) = 1;
1299*38fd1498Szrj       TREE_STATIC (array) = 1;
1300*38fd1498Szrj       DECL_EXTERNAL (array) = 1;
1301*38fd1498Szrj       DECL_VISIBILITY (array) = VISIBILITY_DEFAULT;
1302*38fd1498Szrj       DECL_VISIBILITY_SPECIFIED (array) = 1;
1303*38fd1498Szrj       varpool_node::finalize_decl (array);
1304*38fd1498Szrj       ubsan_vptr_type_cache_decl = array;
1305*38fd1498Szrj    }
1306*38fd1498Szrj 
1307*38fd1498Szrj   g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1308*38fd1498Szrj 			   BIT_AND_EXPR, hash,
1309*38fd1498Szrj 			   build_int_cst (pointer_sized_int_node, 127));
1310*38fd1498Szrj   gimple_set_location (g, loc);
1311*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1312*38fd1498Szrj 
1313*38fd1498Szrj   tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_node,
1314*38fd1498Szrj 		       ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1315*38fd1498Szrj 		       NULL_TREE, NULL_TREE);
1316*38fd1498Szrj   g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
1317*38fd1498Szrj 			   ARRAY_REF, c);
1318*38fd1498Szrj   gimple_set_location (g, loc);
1319*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1320*38fd1498Szrj 
1321*38fd1498Szrj   basic_block then_bb, fallthru2_bb;
1322*38fd1498Szrj   gimple_stmt_iterator cond_insert_point
1323*38fd1498Szrj     = create_cond_insert_point (gsip, false, false, true,
1324*38fd1498Szrj 				&then_bb, &fallthru2_bb);
1325*38fd1498Szrj   g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1326*38fd1498Szrj 			 NULL_TREE, NULL_TREE);
1327*38fd1498Szrj   gimple_set_location (g, loc);
1328*38fd1498Szrj   gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1329*38fd1498Szrj   *gsip = gsi_after_labels (then_bb);
1330*38fd1498Szrj   if (fallthru_bb == NULL)
1331*38fd1498Szrj     fallthru_bb = fallthru2_bb;
1332*38fd1498Szrj 
1333*38fd1498Szrj   tree data
1334*38fd1498Szrj     = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1335*38fd1498Szrj 			 ubsan_type_descriptor (type), NULL_TREE, ti_decl_addr,
1336*38fd1498Szrj 			 build_int_cst (unsigned_char_type_node, ckind),
1337*38fd1498Szrj 			 NULL_TREE);
1338*38fd1498Szrj   data = build_fold_addr_expr_loc (loc, data);
1339*38fd1498Szrj   enum built_in_function bcode
1340*38fd1498Szrj     = (flag_sanitize_recover & SANITIZE_VPTR)
1341*38fd1498Szrj       ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1342*38fd1498Szrj       : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1343*38fd1498Szrj 
1344*38fd1498Szrj   g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1345*38fd1498Szrj   gimple_set_location (g, loc);
1346*38fd1498Szrj   gsi_insert_before (gsip, g, GSI_SAME_STMT);
1347*38fd1498Szrj 
1348*38fd1498Szrj   /* Point GSI to next logical statement.  */
1349*38fd1498Szrj   *gsip = gsi_start_bb (fallthru_bb);
1350*38fd1498Szrj 
1351*38fd1498Szrj   /* Get rid of the UBSAN_VPTR call from the IR.  */
1352*38fd1498Szrj   unlink_stmt_vdef (stmt);
1353*38fd1498Szrj   gsi_remove (&gsi, true);
1354*38fd1498Szrj   return true;
1355*38fd1498Szrj }
1356*38fd1498Szrj 
1357*38fd1498Szrj /* Instrument a memory reference.  BASE is the base of MEM, IS_LHS says
1358*38fd1498Szrj    whether the pointer is on the left hand side of the assignment.  */
1359*38fd1498Szrj 
1360*38fd1498Szrj static void
instrument_mem_ref(tree mem,tree base,gimple_stmt_iterator * iter,bool is_lhs)1361*38fd1498Szrj instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1362*38fd1498Szrj 		    bool is_lhs)
1363*38fd1498Szrj {
1364*38fd1498Szrj   enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1365*38fd1498Szrj   unsigned int align = 0;
1366*38fd1498Szrj   if (sanitize_flags_p (SANITIZE_ALIGNMENT))
1367*38fd1498Szrj     {
1368*38fd1498Szrj       align = min_align_of_type (TREE_TYPE (base));
1369*38fd1498Szrj       if (align <= 1)
1370*38fd1498Szrj 	align = 0;
1371*38fd1498Szrj     }
1372*38fd1498Szrj   if (align == 0 && !sanitize_flags_p (SANITIZE_NULL))
1373*38fd1498Szrj     return;
1374*38fd1498Szrj   tree t = TREE_OPERAND (base, 0);
1375*38fd1498Szrj   if (!POINTER_TYPE_P (TREE_TYPE (t)))
1376*38fd1498Szrj     return;
1377*38fd1498Szrj   if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base)) && mem != base)
1378*38fd1498Szrj     ikind = UBSAN_MEMBER_ACCESS;
1379*38fd1498Szrj   tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)), ikind);
1380*38fd1498Szrj   tree alignt = build_int_cst (pointer_sized_int_node, align);
1381*38fd1498Szrj   gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1382*38fd1498Szrj   gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1383*38fd1498Szrj   gsi_insert_before (iter, g, GSI_SAME_STMT);
1384*38fd1498Szrj }
1385*38fd1498Szrj 
1386*38fd1498Szrj /* Perform the pointer instrumentation.  */
1387*38fd1498Szrj 
1388*38fd1498Szrj static void
instrument_null(gimple_stmt_iterator gsi,tree t,bool is_lhs)1389*38fd1498Szrj instrument_null (gimple_stmt_iterator gsi, tree t, bool is_lhs)
1390*38fd1498Szrj {
1391*38fd1498Szrj   /* Handle also e.g. &s->i.  */
1392*38fd1498Szrj   if (TREE_CODE (t) == ADDR_EXPR)
1393*38fd1498Szrj     t = TREE_OPERAND (t, 0);
1394*38fd1498Szrj   tree base = get_base_address (t);
1395*38fd1498Szrj   if (base != NULL_TREE
1396*38fd1498Szrj       && TREE_CODE (base) == MEM_REF
1397*38fd1498Szrj       && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
1398*38fd1498Szrj     instrument_mem_ref (t, base, &gsi, is_lhs);
1399*38fd1498Szrj }
1400*38fd1498Szrj 
1401*38fd1498Szrj /* Instrument pointer arithmetics PTR p+ OFF.  */
1402*38fd1498Szrj 
1403*38fd1498Szrj static void
instrument_pointer_overflow(gimple_stmt_iterator * gsi,tree ptr,tree off)1404*38fd1498Szrj instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree ptr, tree off)
1405*38fd1498Szrj {
1406*38fd1498Szrj   if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1407*38fd1498Szrj     return;
1408*38fd1498Szrj   gcall *g = gimple_build_call_internal (IFN_UBSAN_PTR, 2, ptr, off);
1409*38fd1498Szrj   gimple_set_location (g, gimple_location (gsi_stmt (*gsi)));
1410*38fd1498Szrj   gsi_insert_before (gsi, g, GSI_SAME_STMT);
1411*38fd1498Szrj }
1412*38fd1498Szrj 
1413*38fd1498Szrj /* Instrument pointer arithmetics if any.  */
1414*38fd1498Szrj 
1415*38fd1498Szrj static void
maybe_instrument_pointer_overflow(gimple_stmt_iterator * gsi,tree t)1416*38fd1498Szrj maybe_instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree t)
1417*38fd1498Szrj {
1418*38fd1498Szrj   if (TYPE_PRECISION (sizetype) != POINTER_SIZE)
1419*38fd1498Szrj     return;
1420*38fd1498Szrj 
1421*38fd1498Szrj   /* Handle also e.g. &s->i.  */
1422*38fd1498Szrj   if (TREE_CODE (t) == ADDR_EXPR)
1423*38fd1498Szrj     t = TREE_OPERAND (t, 0);
1424*38fd1498Szrj 
1425*38fd1498Szrj   if (!handled_component_p (t) && TREE_CODE (t) != MEM_REF)
1426*38fd1498Szrj     return;
1427*38fd1498Szrj 
1428*38fd1498Szrj   poly_int64 bitsize, bitpos, bytepos;
1429*38fd1498Szrj   tree offset;
1430*38fd1498Szrj   machine_mode mode;
1431*38fd1498Szrj   int volatilep = 0, reversep, unsignedp = 0;
1432*38fd1498Szrj   tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1433*38fd1498Szrj 				    &unsignedp, &reversep, &volatilep);
1434*38fd1498Szrj   tree moff = NULL_TREE;
1435*38fd1498Szrj 
1436*38fd1498Szrj   bool decl_p = DECL_P (inner);
1437*38fd1498Szrj   tree base;
1438*38fd1498Szrj   if (decl_p)
1439*38fd1498Szrj     {
1440*38fd1498Szrj       if (DECL_REGISTER (inner))
1441*38fd1498Szrj 	return;
1442*38fd1498Szrj       base = inner;
1443*38fd1498Szrj       /* If BASE is a fixed size automatic variable or
1444*38fd1498Szrj 	 global variable defined in the current TU and bitpos
1445*38fd1498Szrj 	 fits, don't instrument anything.  */
1446*38fd1498Szrj       poly_int64 base_size;
1447*38fd1498Szrj       if (offset == NULL_TREE
1448*38fd1498Szrj 	  && maybe_ne (bitpos, 0)
1449*38fd1498Szrj 	  && (VAR_P (base)
1450*38fd1498Szrj 	      || TREE_CODE (base) == PARM_DECL
1451*38fd1498Szrj 	      || TREE_CODE (base) == RESULT_DECL)
1452*38fd1498Szrj 	  && poly_int_tree_p (DECL_SIZE (base), &base_size)
1453*38fd1498Szrj 	  && known_ge (base_size, bitpos)
1454*38fd1498Szrj 	  && (!is_global_var (base) || decl_binds_to_current_def_p (base)))
1455*38fd1498Szrj 	return;
1456*38fd1498Szrj     }
1457*38fd1498Szrj   else if (TREE_CODE (inner) == MEM_REF)
1458*38fd1498Szrj     {
1459*38fd1498Szrj       base = TREE_OPERAND (inner, 0);
1460*38fd1498Szrj       if (TREE_CODE (base) == ADDR_EXPR
1461*38fd1498Szrj 	  && DECL_P (TREE_OPERAND (base, 0))
1462*38fd1498Szrj 	  && !TREE_ADDRESSABLE (TREE_OPERAND (base, 0))
1463*38fd1498Szrj 	  && !is_global_var (TREE_OPERAND (base, 0)))
1464*38fd1498Szrj 	return;
1465*38fd1498Szrj       moff = TREE_OPERAND (inner, 1);
1466*38fd1498Szrj       if (integer_zerop (moff))
1467*38fd1498Szrj 	moff = NULL_TREE;
1468*38fd1498Szrj     }
1469*38fd1498Szrj   else
1470*38fd1498Szrj     return;
1471*38fd1498Szrj 
1472*38fd1498Szrj   if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
1473*38fd1498Szrj     return;
1474*38fd1498Szrj   bytepos = bits_to_bytes_round_down (bitpos);
1475*38fd1498Szrj   if (offset == NULL_TREE && known_eq (bytepos, 0) && moff == NULL_TREE)
1476*38fd1498Szrj     return;
1477*38fd1498Szrj 
1478*38fd1498Szrj   tree base_addr = base;
1479*38fd1498Szrj   if (decl_p)
1480*38fd1498Szrj     base_addr = build1 (ADDR_EXPR,
1481*38fd1498Szrj 			build_pointer_type (TREE_TYPE (base)), base);
1482*38fd1498Szrj   t = offset;
1483*38fd1498Szrj   if (maybe_ne (bytepos, 0))
1484*38fd1498Szrj     {
1485*38fd1498Szrj       if (t)
1486*38fd1498Szrj 	t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1487*38fd1498Szrj 			 build_int_cst (TREE_TYPE (t), bytepos));
1488*38fd1498Szrj       else
1489*38fd1498Szrj 	t = size_int (bytepos);
1490*38fd1498Szrj     }
1491*38fd1498Szrj   if (moff)
1492*38fd1498Szrj     {
1493*38fd1498Szrj       if (t)
1494*38fd1498Szrj 	t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,
1495*38fd1498Szrj 			 fold_convert (TREE_TYPE (t), moff));
1496*38fd1498Szrj       else
1497*38fd1498Szrj 	t = fold_convert (sizetype, moff);
1498*38fd1498Szrj     }
1499*38fd1498Szrj   t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
1500*38fd1498Szrj 				GSI_SAME_STMT);
1501*38fd1498Szrj   base_addr = force_gimple_operand_gsi (gsi, base_addr, true, NULL_TREE, true,
1502*38fd1498Szrj 					GSI_SAME_STMT);
1503*38fd1498Szrj   instrument_pointer_overflow (gsi, base_addr, t);
1504*38fd1498Szrj }
1505*38fd1498Szrj 
1506*38fd1498Szrj /* Build an ubsan builtin call for the signed-integer-overflow
1507*38fd1498Szrj    sanitization.  CODE says what kind of builtin are we building,
1508*38fd1498Szrj    LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1509*38fd1498Szrj    are operands of the binary operation.  */
1510*38fd1498Szrj 
1511*38fd1498Szrj tree
ubsan_build_overflow_builtin(tree_code code,location_t loc,tree lhstype,tree op0,tree op1,tree * datap)1512*38fd1498Szrj ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1513*38fd1498Szrj 			      tree op0, tree op1, tree *datap)
1514*38fd1498Szrj {
1515*38fd1498Szrj   if (flag_sanitize_undefined_trap_on_error)
1516*38fd1498Szrj     return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1517*38fd1498Szrj 
1518*38fd1498Szrj   tree data;
1519*38fd1498Szrj   if (datap && *datap)
1520*38fd1498Szrj     data = *datap;
1521*38fd1498Szrj   else
1522*38fd1498Szrj     data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1523*38fd1498Szrj 			      ubsan_type_descriptor (lhstype), NULL_TREE,
1524*38fd1498Szrj 			      NULL_TREE);
1525*38fd1498Szrj   if (datap)
1526*38fd1498Szrj     *datap = data;
1527*38fd1498Szrj   enum built_in_function fn_code;
1528*38fd1498Szrj 
1529*38fd1498Szrj   switch (code)
1530*38fd1498Szrj     {
1531*38fd1498Szrj     case PLUS_EXPR:
1532*38fd1498Szrj       fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1533*38fd1498Szrj 		? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1534*38fd1498Szrj 		: BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1535*38fd1498Szrj       break;
1536*38fd1498Szrj     case MINUS_EXPR:
1537*38fd1498Szrj       fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1538*38fd1498Szrj 		? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1539*38fd1498Szrj 		: BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1540*38fd1498Szrj       break;
1541*38fd1498Szrj     case MULT_EXPR:
1542*38fd1498Szrj       fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1543*38fd1498Szrj 		? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1544*38fd1498Szrj 		: BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1545*38fd1498Szrj       break;
1546*38fd1498Szrj     case NEGATE_EXPR:
1547*38fd1498Szrj       fn_code = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1548*38fd1498Szrj 		? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1549*38fd1498Szrj 		: BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1550*38fd1498Szrj       break;
1551*38fd1498Szrj     default:
1552*38fd1498Szrj       gcc_unreachable ();
1553*38fd1498Szrj     }
1554*38fd1498Szrj   tree fn = builtin_decl_explicit (fn_code);
1555*38fd1498Szrj   return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1556*38fd1498Szrj 			      build_fold_addr_expr_loc (loc, data),
1557*38fd1498Szrj 			      ubsan_encode_value (op0, UBSAN_ENCODE_VALUE_RTL),
1558*38fd1498Szrj 			      op1
1559*38fd1498Szrj 			      ? ubsan_encode_value (op1,
1560*38fd1498Szrj 						    UBSAN_ENCODE_VALUE_RTL)
1561*38fd1498Szrj 			      : NULL_TREE);
1562*38fd1498Szrj }
1563*38fd1498Szrj 
1564*38fd1498Szrj /* Perform the signed integer instrumentation.  GSI is the iterator
1565*38fd1498Szrj    pointing at statement we are trying to instrument.  */
1566*38fd1498Szrj 
1567*38fd1498Szrj static void
instrument_si_overflow(gimple_stmt_iterator gsi)1568*38fd1498Szrj instrument_si_overflow (gimple_stmt_iterator gsi)
1569*38fd1498Szrj {
1570*38fd1498Szrj   gimple *stmt = gsi_stmt (gsi);
1571*38fd1498Szrj   tree_code code = gimple_assign_rhs_code (stmt);
1572*38fd1498Szrj   tree lhs = gimple_assign_lhs (stmt);
1573*38fd1498Szrj   tree lhstype = TREE_TYPE (lhs);
1574*38fd1498Szrj   tree lhsinner = VECTOR_TYPE_P (lhstype) ? TREE_TYPE (lhstype) : lhstype;
1575*38fd1498Szrj   tree a, b;
1576*38fd1498Szrj   gimple *g;
1577*38fd1498Szrj 
1578*38fd1498Szrj   /* If this is not a signed operation, don't instrument anything here.
1579*38fd1498Szrj      Also punt on bit-fields.  */
1580*38fd1498Szrj   if (!INTEGRAL_TYPE_P (lhsinner)
1581*38fd1498Szrj       || TYPE_OVERFLOW_WRAPS (lhsinner)
1582*38fd1498Szrj       || maybe_ne (GET_MODE_BITSIZE (TYPE_MODE (lhsinner)),
1583*38fd1498Szrj 		   TYPE_PRECISION (lhsinner)))
1584*38fd1498Szrj     return;
1585*38fd1498Szrj 
1586*38fd1498Szrj   switch (code)
1587*38fd1498Szrj     {
1588*38fd1498Szrj     case MINUS_EXPR:
1589*38fd1498Szrj     case PLUS_EXPR:
1590*38fd1498Szrj     case MULT_EXPR:
1591*38fd1498Szrj       /* Transform
1592*38fd1498Szrj 	 i = u {+,-,*} 5;
1593*38fd1498Szrj 	 into
1594*38fd1498Szrj 	 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5);  */
1595*38fd1498Szrj       a = gimple_assign_rhs1 (stmt);
1596*38fd1498Szrj       b = gimple_assign_rhs2 (stmt);
1597*38fd1498Szrj       g = gimple_build_call_internal (code == PLUS_EXPR
1598*38fd1498Szrj 				      ? IFN_UBSAN_CHECK_ADD
1599*38fd1498Szrj 				      : code == MINUS_EXPR
1600*38fd1498Szrj 				      ? IFN_UBSAN_CHECK_SUB
1601*38fd1498Szrj 				      : IFN_UBSAN_CHECK_MUL, 2, a, b);
1602*38fd1498Szrj       gimple_call_set_lhs (g, lhs);
1603*38fd1498Szrj       gsi_replace (&gsi, g, true);
1604*38fd1498Szrj       break;
1605*38fd1498Szrj     case NEGATE_EXPR:
1606*38fd1498Szrj       /* Represent i = -u;
1607*38fd1498Szrj 	 as
1608*38fd1498Szrj 	 i = UBSAN_CHECK_SUB (0, u);  */
1609*38fd1498Szrj       a = build_zero_cst (lhstype);
1610*38fd1498Szrj       b = gimple_assign_rhs1 (stmt);
1611*38fd1498Szrj       g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1612*38fd1498Szrj       gimple_call_set_lhs (g, lhs);
1613*38fd1498Szrj       gsi_replace (&gsi, g, true);
1614*38fd1498Szrj       break;
1615*38fd1498Szrj     case ABS_EXPR:
1616*38fd1498Szrj       /* Transform i = ABS_EXPR<u>;
1617*38fd1498Szrj 	 into
1618*38fd1498Szrj 	 _N = UBSAN_CHECK_SUB (0, u);
1619*38fd1498Szrj 	 i = ABS_EXPR<_N>;  */
1620*38fd1498Szrj       a = build_zero_cst (lhstype);
1621*38fd1498Szrj       b = gimple_assign_rhs1 (stmt);
1622*38fd1498Szrj       g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1623*38fd1498Szrj       a = make_ssa_name (lhstype);
1624*38fd1498Szrj       gimple_call_set_lhs (g, a);
1625*38fd1498Szrj       gimple_set_location (g, gimple_location (stmt));
1626*38fd1498Szrj       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1627*38fd1498Szrj       gimple_assign_set_rhs1 (stmt, a);
1628*38fd1498Szrj       update_stmt (stmt);
1629*38fd1498Szrj       break;
1630*38fd1498Szrj     default:
1631*38fd1498Szrj       break;
1632*38fd1498Szrj     }
1633*38fd1498Szrj }
1634*38fd1498Szrj 
1635*38fd1498Szrj /* Instrument loads from (non-bitfield) bool and C++ enum values
1636*38fd1498Szrj    to check if the memory value is outside of the range of the valid
1637*38fd1498Szrj    type values.  */
1638*38fd1498Szrj 
1639*38fd1498Szrj static void
instrument_bool_enum_load(gimple_stmt_iterator * gsi)1640*38fd1498Szrj instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1641*38fd1498Szrj {
1642*38fd1498Szrj   gimple *stmt = gsi_stmt (*gsi);
1643*38fd1498Szrj   tree rhs = gimple_assign_rhs1 (stmt);
1644*38fd1498Szrj   tree type = TREE_TYPE (rhs);
1645*38fd1498Szrj   tree minv = NULL_TREE, maxv = NULL_TREE;
1646*38fd1498Szrj 
1647*38fd1498Szrj   if (TREE_CODE (type) == BOOLEAN_TYPE
1648*38fd1498Szrj       && sanitize_flags_p (SANITIZE_BOOL))
1649*38fd1498Szrj     {
1650*38fd1498Szrj       minv = boolean_false_node;
1651*38fd1498Szrj       maxv = boolean_true_node;
1652*38fd1498Szrj     }
1653*38fd1498Szrj   else if (TREE_CODE (type) == ENUMERAL_TYPE
1654*38fd1498Szrj 	   && sanitize_flags_p (SANITIZE_ENUM)
1655*38fd1498Szrj 	   && TREE_TYPE (type) != NULL_TREE
1656*38fd1498Szrj 	   && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
1657*38fd1498Szrj 	   && (TYPE_PRECISION (TREE_TYPE (type))
1658*38fd1498Szrj 	       < GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (type))))
1659*38fd1498Szrj     {
1660*38fd1498Szrj       minv = TYPE_MIN_VALUE (TREE_TYPE (type));
1661*38fd1498Szrj       maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
1662*38fd1498Szrj     }
1663*38fd1498Szrj   else
1664*38fd1498Szrj     return;
1665*38fd1498Szrj 
1666*38fd1498Szrj   int modebitsize = GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type));
1667*38fd1498Szrj   poly_int64 bitsize, bitpos;
1668*38fd1498Szrj   tree offset;
1669*38fd1498Szrj   machine_mode mode;
1670*38fd1498Szrj   int volatilep = 0, reversep, unsignedp = 0;
1671*38fd1498Szrj   tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1672*38fd1498Szrj 				   &unsignedp, &reversep, &volatilep);
1673*38fd1498Szrj   tree utype = build_nonstandard_integer_type (modebitsize, 1);
1674*38fd1498Szrj 
1675*38fd1498Szrj   if ((VAR_P (base) && DECL_HARD_REGISTER (base))
1676*38fd1498Szrj       || !multiple_p (bitpos, modebitsize)
1677*38fd1498Szrj       || maybe_ne (bitsize, modebitsize)
1678*38fd1498Szrj       || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (utype)) != modebitsize
1679*38fd1498Szrj       || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
1680*38fd1498Szrj     return;
1681*38fd1498Szrj 
1682*38fd1498Szrj   bool ends_bb = stmt_ends_bb_p (stmt);
1683*38fd1498Szrj   location_t loc = gimple_location (stmt);
1684*38fd1498Szrj   tree lhs = gimple_assign_lhs (stmt);
1685*38fd1498Szrj   tree ptype = build_pointer_type (TREE_TYPE (rhs));
1686*38fd1498Szrj   tree atype = reference_alias_ptr_type (rhs);
1687*38fd1498Szrj   gimple *g = gimple_build_assign (make_ssa_name (ptype),
1688*38fd1498Szrj 				  build_fold_addr_expr (rhs));
1689*38fd1498Szrj   gimple_set_location (g, loc);
1690*38fd1498Szrj   gsi_insert_before (gsi, g, GSI_SAME_STMT);
1691*38fd1498Szrj   tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1692*38fd1498Szrj 		     build_int_cst (atype, 0));
1693*38fd1498Szrj   tree urhs = make_ssa_name (utype);
1694*38fd1498Szrj   if (ends_bb)
1695*38fd1498Szrj     {
1696*38fd1498Szrj       gimple_assign_set_lhs (stmt, urhs);
1697*38fd1498Szrj       g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1698*38fd1498Szrj       gimple_set_location (g, loc);
1699*38fd1498Szrj       edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1700*38fd1498Szrj       gsi_insert_on_edge_immediate (e, g);
1701*38fd1498Szrj       gimple_assign_set_rhs_from_tree (gsi, mem);
1702*38fd1498Szrj       update_stmt (stmt);
1703*38fd1498Szrj       *gsi = gsi_for_stmt (g);
1704*38fd1498Szrj       g = stmt;
1705*38fd1498Szrj     }
1706*38fd1498Szrj   else
1707*38fd1498Szrj     {
1708*38fd1498Szrj       g = gimple_build_assign (urhs, mem);
1709*38fd1498Szrj       gimple_set_location (g, loc);
1710*38fd1498Szrj       gsi_insert_before (gsi, g, GSI_SAME_STMT);
1711*38fd1498Szrj     }
1712*38fd1498Szrj   minv = fold_convert (utype, minv);
1713*38fd1498Szrj   maxv = fold_convert (utype, maxv);
1714*38fd1498Szrj   if (!integer_zerop (minv))
1715*38fd1498Szrj     {
1716*38fd1498Szrj       g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1717*38fd1498Szrj       gimple_set_location (g, loc);
1718*38fd1498Szrj       gsi_insert_before (gsi, g, GSI_SAME_STMT);
1719*38fd1498Szrj     }
1720*38fd1498Szrj 
1721*38fd1498Szrj   gimple_stmt_iterator gsi2 = *gsi;
1722*38fd1498Szrj   basic_block then_bb, fallthru_bb;
1723*38fd1498Szrj   *gsi = create_cond_insert_point (gsi, true, false, true,
1724*38fd1498Szrj 				   &then_bb, &fallthru_bb);
1725*38fd1498Szrj   g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1726*38fd1498Szrj 			 int_const_binop (MINUS_EXPR, maxv, minv),
1727*38fd1498Szrj 			 NULL_TREE, NULL_TREE);
1728*38fd1498Szrj   gimple_set_location (g, loc);
1729*38fd1498Szrj   gsi_insert_after (gsi, g, GSI_NEW_STMT);
1730*38fd1498Szrj 
1731*38fd1498Szrj   if (!ends_bb)
1732*38fd1498Szrj     {
1733*38fd1498Szrj       gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1734*38fd1498Szrj       update_stmt (stmt);
1735*38fd1498Szrj     }
1736*38fd1498Szrj 
1737*38fd1498Szrj   gsi2 = gsi_after_labels (then_bb);
1738*38fd1498Szrj   if (flag_sanitize_undefined_trap_on_error)
1739*38fd1498Szrj     g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1740*38fd1498Szrj   else
1741*38fd1498Szrj     {
1742*38fd1498Szrj       tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1743*38fd1498Szrj 				     ubsan_type_descriptor (type), NULL_TREE,
1744*38fd1498Szrj 				     NULL_TREE);
1745*38fd1498Szrj       data = build_fold_addr_expr_loc (loc, data);
1746*38fd1498Szrj       enum built_in_function bcode
1747*38fd1498Szrj 	= (flag_sanitize_recover & (TREE_CODE (type) == BOOLEAN_TYPE
1748*38fd1498Szrj 				    ? SANITIZE_BOOL : SANITIZE_ENUM))
1749*38fd1498Szrj 	  ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1750*38fd1498Szrj 	  : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1751*38fd1498Szrj       tree fn = builtin_decl_explicit (bcode);
1752*38fd1498Szrj 
1753*38fd1498Szrj       tree val = ubsan_encode_value (urhs, UBSAN_ENCODE_VALUE_GIMPLE);
1754*38fd1498Szrj       val = force_gimple_operand_gsi (&gsi2, val, true, NULL_TREE, true,
1755*38fd1498Szrj 				      GSI_SAME_STMT);
1756*38fd1498Szrj       g = gimple_build_call (fn, 2, data, val);
1757*38fd1498Szrj     }
1758*38fd1498Szrj   gimple_set_location (g, loc);
1759*38fd1498Szrj   gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1760*38fd1498Szrj   ubsan_create_edge (g);
1761*38fd1498Szrj   *gsi = gsi_for_stmt (stmt);
1762*38fd1498Szrj }
1763*38fd1498Szrj 
1764*38fd1498Szrj /* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1765*38fd1498Szrj    new style handlers.  Libubsan uses heuristics to destinguish between old and
1766*38fd1498Szrj    new styles and relies on these properties for filename:
1767*38fd1498Szrj 
1768*38fd1498Szrj    a) Location's filename must not be NULL.
1769*38fd1498Szrj    b) Location's filename must not be equal to "".
1770*38fd1498Szrj    c) Location's filename must not be equal to "\1".
1771*38fd1498Szrj    d) First two bytes of filename must not contain '\xff' symbol.  */
1772*38fd1498Szrj 
1773*38fd1498Szrj static bool
ubsan_use_new_style_p(location_t loc)1774*38fd1498Szrj ubsan_use_new_style_p (location_t loc)
1775*38fd1498Szrj {
1776*38fd1498Szrj   if (loc == UNKNOWN_LOCATION)
1777*38fd1498Szrj     return false;
1778*38fd1498Szrj 
1779*38fd1498Szrj   expanded_location xloc = expand_location (loc);
1780*38fd1498Szrj   if (xloc.file == NULL || strncmp (xloc.file, "\1", 2) == 0
1781*38fd1498Szrj       || xloc.file[0] == '\0' || xloc.file[0] == '\xff'
1782*38fd1498Szrj       || xloc.file[1] == '\xff')
1783*38fd1498Szrj     return false;
1784*38fd1498Szrj 
1785*38fd1498Szrj   return true;
1786*38fd1498Szrj }
1787*38fd1498Szrj 
1788*38fd1498Szrj /* Instrument float point-to-integer conversion.  TYPE is an integer type of
1789*38fd1498Szrj    destination, EXPR is floating-point expression.  */
1790*38fd1498Szrj 
1791*38fd1498Szrj tree
ubsan_instrument_float_cast(location_t loc,tree type,tree expr)1792*38fd1498Szrj ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1793*38fd1498Szrj {
1794*38fd1498Szrj   tree expr_type = TREE_TYPE (expr);
1795*38fd1498Szrj   tree t, tt, fn, min, max;
1796*38fd1498Szrj   machine_mode mode = TYPE_MODE (expr_type);
1797*38fd1498Szrj   int prec = TYPE_PRECISION (type);
1798*38fd1498Szrj   bool uns_p = TYPE_UNSIGNED (type);
1799*38fd1498Szrj   if (loc == UNKNOWN_LOCATION)
1800*38fd1498Szrj     loc = input_location;
1801*38fd1498Szrj 
1802*38fd1498Szrj   /* Float to integer conversion first truncates toward zero, so
1803*38fd1498Szrj      even signed char c = 127.875f; is not problematic.
1804*38fd1498Szrj      Therefore, we should complain only if EXPR is unordered or smaller
1805*38fd1498Szrj      or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1806*38fd1498Szrj      TYPE_MAX_VALUE + 1.0.  */
1807*38fd1498Szrj   if (REAL_MODE_FORMAT (mode)->b == 2)
1808*38fd1498Szrj     {
1809*38fd1498Szrj       /* For maximum, TYPE_MAX_VALUE might not be representable
1810*38fd1498Szrj 	 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1811*38fd1498Szrj 	 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1812*38fd1498Szrj 	 either representable or infinity.  */
1813*38fd1498Szrj       REAL_VALUE_TYPE maxval = dconst1;
1814*38fd1498Szrj       SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p);
1815*38fd1498Szrj       real_convert (&maxval, mode, &maxval);
1816*38fd1498Szrj       max = build_real (expr_type, maxval);
1817*38fd1498Szrj 
1818*38fd1498Szrj       /* For unsigned, assume -1.0 is always representable.  */
1819*38fd1498Szrj       if (uns_p)
1820*38fd1498Szrj 	min = build_minus_one_cst (expr_type);
1821*38fd1498Szrj       else
1822*38fd1498Szrj 	{
1823*38fd1498Szrj 	  /* TYPE_MIN_VALUE is generally representable (or -inf),
1824*38fd1498Szrj 	     but TYPE_MIN_VALUE - 1.0 might not be.  */
1825*38fd1498Szrj 	  REAL_VALUE_TYPE minval = dconstm1, minval2;
1826*38fd1498Szrj 	  SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1);
1827*38fd1498Szrj 	  real_convert (&minval, mode, &minval);
1828*38fd1498Szrj 	  real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1829*38fd1498Szrj 	  real_convert (&minval2, mode, &minval2);
1830*38fd1498Szrj 	  if (real_compare (EQ_EXPR, &minval, &minval2)
1831*38fd1498Szrj 	      && !real_isinf (&minval))
1832*38fd1498Szrj 	    {
1833*38fd1498Szrj 	      /* If TYPE_MIN_VALUE - 1.0 is not representable and
1834*38fd1498Szrj 		 rounds to TYPE_MIN_VALUE, we need to subtract
1835*38fd1498Szrj 		 more.  As REAL_MODE_FORMAT (mode)->p is the number
1836*38fd1498Szrj 		 of base digits, we want to subtract a number that
1837*38fd1498Szrj 		 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1838*38fd1498Szrj 		 times smaller than minval.  */
1839*38fd1498Szrj 	      minval2 = dconst1;
1840*38fd1498Szrj 	      gcc_assert (prec > REAL_MODE_FORMAT (mode)->p);
1841*38fd1498Szrj 	      SET_REAL_EXP (&minval2,
1842*38fd1498Szrj 			    REAL_EXP (&minval2) + prec - 1
1843*38fd1498Szrj 			    - REAL_MODE_FORMAT (mode)->p + 1);
1844*38fd1498Szrj 	      real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1845*38fd1498Szrj 	      real_convert (&minval2, mode, &minval2);
1846*38fd1498Szrj 	    }
1847*38fd1498Szrj 	  min = build_real (expr_type, minval2);
1848*38fd1498Szrj 	}
1849*38fd1498Szrj     }
1850*38fd1498Szrj   else if (REAL_MODE_FORMAT (mode)->b == 10)
1851*38fd1498Szrj     {
1852*38fd1498Szrj       /* For _Decimal128 up to 34 decimal digits, - sign,
1853*38fd1498Szrj 	 dot, e, exponent.  */
1854*38fd1498Szrj       char buf[64];
1855*38fd1498Szrj       mpfr_t m;
1856*38fd1498Szrj       int p = REAL_MODE_FORMAT (mode)->p;
1857*38fd1498Szrj       REAL_VALUE_TYPE maxval, minval;
1858*38fd1498Szrj 
1859*38fd1498Szrj       /* Use mpfr_snprintf rounding to compute the smallest
1860*38fd1498Szrj 	 representable decimal number greater or equal than
1861*38fd1498Szrj 	 1 << (prec - !uns_p).  */
1862*38fd1498Szrj       mpfr_init2 (m, prec + 2);
1863*38fd1498Szrj       mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
1864*38fd1498Szrj       mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1865*38fd1498Szrj       decimal_real_from_string (&maxval, buf);
1866*38fd1498Szrj       max = build_real (expr_type, maxval);
1867*38fd1498Szrj 
1868*38fd1498Szrj       /* For unsigned, assume -1.0 is always representable.  */
1869*38fd1498Szrj       if (uns_p)
1870*38fd1498Szrj 	min = build_minus_one_cst (expr_type);
1871*38fd1498Szrj       else
1872*38fd1498Szrj 	{
1873*38fd1498Szrj 	  /* Use mpfr_snprintf rounding to compute the largest
1874*38fd1498Szrj 	     representable decimal number less or equal than
1875*38fd1498Szrj 	     (-1 << (prec - 1)) - 1.  */
1876*38fd1498Szrj 	  mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
1877*38fd1498Szrj 	  mpfr_sub_ui (m, m, 1, GMP_RNDN);
1878*38fd1498Szrj 	  mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1879*38fd1498Szrj 	  decimal_real_from_string (&minval, buf);
1880*38fd1498Szrj 	  min = build_real (expr_type, minval);
1881*38fd1498Szrj 	}
1882*38fd1498Szrj       mpfr_clear (m);
1883*38fd1498Szrj     }
1884*38fd1498Szrj   else
1885*38fd1498Szrj     return NULL_TREE;
1886*38fd1498Szrj 
1887*38fd1498Szrj   t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min);
1888*38fd1498Szrj   tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max);
1889*38fd1498Szrj   t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt);
1890*38fd1498Szrj   if (integer_zerop (t))
1891*38fd1498Szrj     return NULL_TREE;
1892*38fd1498Szrj 
1893*38fd1498Szrj   if (flag_sanitize_undefined_trap_on_error)
1894*38fd1498Szrj     fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1895*38fd1498Szrj   else
1896*38fd1498Szrj     {
1897*38fd1498Szrj       location_t *loc_ptr = NULL;
1898*38fd1498Szrj       unsigned num_locations = 0;
1899*38fd1498Szrj       /* Figure out if we can propagate location to ubsan_data and use new
1900*38fd1498Szrj          style handlers in libubsan.  */
1901*38fd1498Szrj       if (ubsan_use_new_style_p (loc))
1902*38fd1498Szrj 	{
1903*38fd1498Szrj 	  loc_ptr = &loc;
1904*38fd1498Szrj 	  num_locations = 1;
1905*38fd1498Szrj 	}
1906*38fd1498Szrj       /* Create the __ubsan_handle_float_cast_overflow fn call.  */
1907*38fd1498Szrj       tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data",
1908*38fd1498Szrj 				     num_locations, loc_ptr,
1909*38fd1498Szrj 				     ubsan_type_descriptor (expr_type),
1910*38fd1498Szrj 				     ubsan_type_descriptor (type), NULL_TREE,
1911*38fd1498Szrj 				     NULL_TREE);
1912*38fd1498Szrj       enum built_in_function bcode
1913*38fd1498Szrj 	= (flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1914*38fd1498Szrj 	  ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1915*38fd1498Szrj 	  : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1916*38fd1498Szrj       fn = builtin_decl_explicit (bcode);
1917*38fd1498Szrj       fn = build_call_expr_loc (loc, fn, 2,
1918*38fd1498Szrj 				build_fold_addr_expr_loc (loc, data),
1919*38fd1498Szrj 				ubsan_encode_value (expr));
1920*38fd1498Szrj     }
1921*38fd1498Szrj 
1922*38fd1498Szrj   return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node);
1923*38fd1498Szrj }
1924*38fd1498Szrj 
1925*38fd1498Szrj /* Instrument values passed to function arguments with nonnull attribute.  */
1926*38fd1498Szrj 
1927*38fd1498Szrj static void
instrument_nonnull_arg(gimple_stmt_iterator * gsi)1928*38fd1498Szrj instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1929*38fd1498Szrj {
1930*38fd1498Szrj   gimple *stmt = gsi_stmt (*gsi);
1931*38fd1498Szrj   location_t loc[2];
1932*38fd1498Szrj   /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1933*38fd1498Szrj      while for nonnull sanitization it is clear.  */
1934*38fd1498Szrj   int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
1935*38fd1498Szrj   flag_delete_null_pointer_checks = 1;
1936*38fd1498Szrj   loc[0] = gimple_location (stmt);
1937*38fd1498Szrj   loc[1] = UNKNOWN_LOCATION;
1938*38fd1498Szrj   for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1939*38fd1498Szrj     {
1940*38fd1498Szrj       tree arg = gimple_call_arg (stmt, i);
1941*38fd1498Szrj       if (POINTER_TYPE_P (TREE_TYPE (arg))
1942*38fd1498Szrj 	  && infer_nonnull_range_by_attribute (stmt, arg))
1943*38fd1498Szrj 	{
1944*38fd1498Szrj 	  gimple *g;
1945*38fd1498Szrj 	  if (!is_gimple_val (arg))
1946*38fd1498Szrj 	    {
1947*38fd1498Szrj 	      g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1948*38fd1498Szrj 	      gimple_set_location (g, loc[0]);
1949*38fd1498Szrj 	      gsi_insert_before (gsi, g, GSI_SAME_STMT);
1950*38fd1498Szrj 	      arg = gimple_assign_lhs (g);
1951*38fd1498Szrj 	    }
1952*38fd1498Szrj 
1953*38fd1498Szrj 	  basic_block then_bb, fallthru_bb;
1954*38fd1498Szrj 	  *gsi = create_cond_insert_point (gsi, true, false, true,
1955*38fd1498Szrj 					   &then_bb, &fallthru_bb);
1956*38fd1498Szrj 	  g = gimple_build_cond (EQ_EXPR, arg,
1957*38fd1498Szrj 				 build_zero_cst (TREE_TYPE (arg)),
1958*38fd1498Szrj 				 NULL_TREE, NULL_TREE);
1959*38fd1498Szrj 	  gimple_set_location (g, loc[0]);
1960*38fd1498Szrj 	  gsi_insert_after (gsi, g, GSI_NEW_STMT);
1961*38fd1498Szrj 
1962*38fd1498Szrj 	  *gsi = gsi_after_labels (then_bb);
1963*38fd1498Szrj 	  if (flag_sanitize_undefined_trap_on_error)
1964*38fd1498Szrj 	    g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1965*38fd1498Szrj 	  else
1966*38fd1498Szrj 	    {
1967*38fd1498Szrj 	      tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1968*38fd1498Szrj 					     2, loc, NULL_TREE,
1969*38fd1498Szrj 					     build_int_cst (integer_type_node,
1970*38fd1498Szrj 							    i + 1),
1971*38fd1498Szrj 					     NULL_TREE);
1972*38fd1498Szrj 	      data = build_fold_addr_expr_loc (loc[0], data);
1973*38fd1498Szrj 	      enum built_in_function bcode
1974*38fd1498Szrj 		= (flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1975*38fd1498Szrj 		  ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1976*38fd1498Szrj 		  : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1977*38fd1498Szrj 	      tree fn = builtin_decl_explicit (bcode);
1978*38fd1498Szrj 
1979*38fd1498Szrj 	      g = gimple_build_call (fn, 1, data);
1980*38fd1498Szrj 	    }
1981*38fd1498Szrj 	  gimple_set_location (g, loc[0]);
1982*38fd1498Szrj 	  gsi_insert_before (gsi, g, GSI_SAME_STMT);
1983*38fd1498Szrj 	  ubsan_create_edge (g);
1984*38fd1498Szrj 	}
1985*38fd1498Szrj       *gsi = gsi_for_stmt (stmt);
1986*38fd1498Szrj     }
1987*38fd1498Szrj   flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1988*38fd1498Szrj }
1989*38fd1498Szrj 
1990*38fd1498Szrj /* Instrument returns in functions with returns_nonnull attribute.  */
1991*38fd1498Szrj 
1992*38fd1498Szrj static void
instrument_nonnull_return(gimple_stmt_iterator * gsi)1993*38fd1498Szrj instrument_nonnull_return (gimple_stmt_iterator *gsi)
1994*38fd1498Szrj {
1995*38fd1498Szrj   greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
1996*38fd1498Szrj   location_t loc[2];
1997*38fd1498Szrj   tree arg = gimple_return_retval (stmt);
1998*38fd1498Szrj   /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1999*38fd1498Szrj      while for nonnull return sanitization it is clear.  */
2000*38fd1498Szrj   int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
2001*38fd1498Szrj   flag_delete_null_pointer_checks = 1;
2002*38fd1498Szrj   loc[0] = gimple_location (stmt);
2003*38fd1498Szrj   loc[1] = UNKNOWN_LOCATION;
2004*38fd1498Szrj   if (arg
2005*38fd1498Szrj       && POINTER_TYPE_P (TREE_TYPE (arg))
2006*38fd1498Szrj       && is_gimple_val (arg)
2007*38fd1498Szrj       && infer_nonnull_range_by_attribute (stmt, arg))
2008*38fd1498Szrj     {
2009*38fd1498Szrj       basic_block then_bb, fallthru_bb;
2010*38fd1498Szrj       *gsi = create_cond_insert_point (gsi, true, false, true,
2011*38fd1498Szrj 				       &then_bb, &fallthru_bb);
2012*38fd1498Szrj       gimple *g = gimple_build_cond (EQ_EXPR, arg,
2013*38fd1498Szrj 				    build_zero_cst (TREE_TYPE (arg)),
2014*38fd1498Szrj 				    NULL_TREE, NULL_TREE);
2015*38fd1498Szrj       gimple_set_location (g, loc[0]);
2016*38fd1498Szrj       gsi_insert_after (gsi, g, GSI_NEW_STMT);
2017*38fd1498Szrj 
2018*38fd1498Szrj       *gsi = gsi_after_labels (then_bb);
2019*38fd1498Szrj       if (flag_sanitize_undefined_trap_on_error)
2020*38fd1498Szrj 	g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2021*38fd1498Szrj       else
2022*38fd1498Szrj 	{
2023*38fd1498Szrj 	  tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
2024*38fd1498Szrj 					 1, &loc[1], NULL_TREE, NULL_TREE);
2025*38fd1498Szrj 	  data = build_fold_addr_expr_loc (loc[0], data);
2026*38fd1498Szrj 	  tree data2 = ubsan_create_data ("__ubsan_nonnull_return_data",
2027*38fd1498Szrj 					  1, &loc[0], NULL_TREE, NULL_TREE);
2028*38fd1498Szrj 	  data2 = build_fold_addr_expr_loc (loc[0], data2);
2029*38fd1498Szrj 	  enum built_in_function bcode
2030*38fd1498Szrj 	    = (flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2031*38fd1498Szrj 	      ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1
2032*38fd1498Szrj 	      : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT;
2033*38fd1498Szrj 	  tree fn = builtin_decl_explicit (bcode);
2034*38fd1498Szrj 
2035*38fd1498Szrj 	  g = gimple_build_call (fn, 2, data, data2);
2036*38fd1498Szrj 	}
2037*38fd1498Szrj       gimple_set_location (g, loc[0]);
2038*38fd1498Szrj       gsi_insert_before (gsi, g, GSI_SAME_STMT);
2039*38fd1498Szrj       ubsan_create_edge (g);
2040*38fd1498Szrj       *gsi = gsi_for_stmt (stmt);
2041*38fd1498Szrj     }
2042*38fd1498Szrj   flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
2043*38fd1498Szrj }
2044*38fd1498Szrj 
2045*38fd1498Szrj /* Instrument memory references.  Here we check whether the pointer
2046*38fd1498Szrj    points to an out-of-bounds location.  */
2047*38fd1498Szrj 
2048*38fd1498Szrj static void
instrument_object_size(gimple_stmt_iterator * gsi,tree t,bool is_lhs)2049*38fd1498Szrj instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs)
2050*38fd1498Szrj {
2051*38fd1498Szrj   gimple *stmt = gsi_stmt (*gsi);
2052*38fd1498Szrj   location_t loc = gimple_location (stmt);
2053*38fd1498Szrj   tree type;
2054*38fd1498Szrj   tree index = NULL_TREE;
2055*38fd1498Szrj   HOST_WIDE_INT size_in_bytes;
2056*38fd1498Szrj 
2057*38fd1498Szrj   type = TREE_TYPE (t);
2058*38fd1498Szrj   if (VOID_TYPE_P (type))
2059*38fd1498Szrj     return;
2060*38fd1498Szrj 
2061*38fd1498Szrj   switch (TREE_CODE (t))
2062*38fd1498Szrj     {
2063*38fd1498Szrj     case COMPONENT_REF:
2064*38fd1498Szrj       if (TREE_CODE (t) == COMPONENT_REF
2065*38fd1498Szrj 	  && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
2066*38fd1498Szrj 	{
2067*38fd1498Szrj 	  tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
2068*38fd1498Szrj 	  t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
2069*38fd1498Szrj 		      repr, TREE_OPERAND (t, 2));
2070*38fd1498Szrj 	}
2071*38fd1498Szrj       break;
2072*38fd1498Szrj     case ARRAY_REF:
2073*38fd1498Szrj       index = TREE_OPERAND (t, 1);
2074*38fd1498Szrj       break;
2075*38fd1498Szrj     case INDIRECT_REF:
2076*38fd1498Szrj     case MEM_REF:
2077*38fd1498Szrj     case VAR_DECL:
2078*38fd1498Szrj     case PARM_DECL:
2079*38fd1498Szrj     case RESULT_DECL:
2080*38fd1498Szrj       break;
2081*38fd1498Szrj     default:
2082*38fd1498Szrj       return;
2083*38fd1498Szrj     }
2084*38fd1498Szrj 
2085*38fd1498Szrj   size_in_bytes = int_size_in_bytes (type);
2086*38fd1498Szrj   if (size_in_bytes <= 0)
2087*38fd1498Szrj     return;
2088*38fd1498Szrj 
2089*38fd1498Szrj   poly_int64 bitsize, bitpos;
2090*38fd1498Szrj   tree offset;
2091*38fd1498Szrj   machine_mode mode;
2092*38fd1498Szrj   int volatilep = 0, reversep, unsignedp = 0;
2093*38fd1498Szrj   tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
2094*38fd1498Szrj 				    &unsignedp, &reversep, &volatilep);
2095*38fd1498Szrj 
2096*38fd1498Szrj   if (!multiple_p (bitpos, BITS_PER_UNIT)
2097*38fd1498Szrj       || maybe_ne (bitsize, size_in_bytes * BITS_PER_UNIT))
2098*38fd1498Szrj     return;
2099*38fd1498Szrj 
2100*38fd1498Szrj   bool decl_p = DECL_P (inner);
2101*38fd1498Szrj   tree base;
2102*38fd1498Szrj   if (decl_p)
2103*38fd1498Szrj     {
2104*38fd1498Szrj       if (DECL_REGISTER (inner))
2105*38fd1498Szrj 	return;
2106*38fd1498Szrj       base = inner;
2107*38fd1498Szrj     }
2108*38fd1498Szrj   else if (TREE_CODE (inner) == MEM_REF)
2109*38fd1498Szrj     base = TREE_OPERAND (inner, 0);
2110*38fd1498Szrj   else
2111*38fd1498Szrj     return;
2112*38fd1498Szrj   tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
2113*38fd1498Szrj 
2114*38fd1498Szrj   while (TREE_CODE (base) == SSA_NAME)
2115*38fd1498Szrj     {
2116*38fd1498Szrj       gimple *def_stmt = SSA_NAME_DEF_STMT (base);
2117*38fd1498Szrj       if (gimple_assign_ssa_name_copy_p (def_stmt)
2118*38fd1498Szrj 	  || (gimple_assign_cast_p (def_stmt)
2119*38fd1498Szrj 	      && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
2120*38fd1498Szrj 	  || (is_gimple_assign (def_stmt)
2121*38fd1498Szrj 	      && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
2122*38fd1498Szrj 	{
2123*38fd1498Szrj 	  tree rhs1 = gimple_assign_rhs1 (def_stmt);
2124*38fd1498Szrj 	  if (TREE_CODE (rhs1) == SSA_NAME
2125*38fd1498Szrj 	      && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
2126*38fd1498Szrj 	    break;
2127*38fd1498Szrj 	  else
2128*38fd1498Szrj 	    base = rhs1;
2129*38fd1498Szrj 	}
2130*38fd1498Szrj       else
2131*38fd1498Szrj 	break;
2132*38fd1498Szrj     }
2133*38fd1498Szrj 
2134*38fd1498Szrj   if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
2135*38fd1498Szrj     return;
2136*38fd1498Szrj 
2137*38fd1498Szrj   tree sizet;
2138*38fd1498Szrj   tree base_addr = base;
2139*38fd1498Szrj   gimple *bos_stmt = NULL;
2140*38fd1498Szrj   if (decl_p)
2141*38fd1498Szrj     base_addr = build1 (ADDR_EXPR,
2142*38fd1498Szrj 			build_pointer_type (TREE_TYPE (base)), base);
2143*38fd1498Szrj   unsigned HOST_WIDE_INT size;
2144*38fd1498Szrj   if (compute_builtin_object_size (base_addr, 0, &size))
2145*38fd1498Szrj     sizet = build_int_cst (sizetype, size);
2146*38fd1498Szrj   else if (optimize)
2147*38fd1498Szrj     {
2148*38fd1498Szrj       if (LOCATION_LOCUS (loc) == UNKNOWN_LOCATION)
2149*38fd1498Szrj 	loc = input_location;
2150*38fd1498Szrj       /* Generate __builtin_object_size call.  */
2151*38fd1498Szrj       sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
2152*38fd1498Szrj       sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
2153*38fd1498Szrj 				   integer_zero_node);
2154*38fd1498Szrj       sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
2155*38fd1498Szrj 					GSI_SAME_STMT);
2156*38fd1498Szrj       /* If the call above didn't end up being an integer constant, go one
2157*38fd1498Szrj 	 statement back and get the __builtin_object_size stmt.  Save it,
2158*38fd1498Szrj 	 we might need it later.  */
2159*38fd1498Szrj       if (SSA_VAR_P (sizet))
2160*38fd1498Szrj 	{
2161*38fd1498Szrj 	  gsi_prev (gsi);
2162*38fd1498Szrj 	  bos_stmt = gsi_stmt (*gsi);
2163*38fd1498Szrj 
2164*38fd1498Szrj 	  /* Move on to where we were.  */
2165*38fd1498Szrj 	  gsi_next (gsi);
2166*38fd1498Szrj 	}
2167*38fd1498Szrj     }
2168*38fd1498Szrj   else
2169*38fd1498Szrj     return;
2170*38fd1498Szrj 
2171*38fd1498Szrj   /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
2172*38fd1498Szrj      call.  */
2173*38fd1498Szrj   /* ptr + sizeof (*ptr) - base */
2174*38fd1498Szrj   t = fold_build2 (MINUS_EXPR, sizetype,
2175*38fd1498Szrj 		   fold_convert (pointer_sized_int_node, ptr),
2176*38fd1498Szrj 		   fold_convert (pointer_sized_int_node, base_addr));
2177*38fd1498Szrj   t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
2178*38fd1498Szrj 
2179*38fd1498Szrj   /* Perhaps we can omit the check.  */
2180*38fd1498Szrj   if (TREE_CODE (t) == INTEGER_CST
2181*38fd1498Szrj       && TREE_CODE (sizet) == INTEGER_CST
2182*38fd1498Szrj       && tree_int_cst_le (t, sizet))
2183*38fd1498Szrj     return;
2184*38fd1498Szrj 
2185*38fd1498Szrj   if (index != NULL_TREE
2186*38fd1498Szrj       && TREE_CODE (index) == SSA_NAME
2187*38fd1498Szrj       && TREE_CODE (sizet) == INTEGER_CST)
2188*38fd1498Szrj     {
2189*38fd1498Szrj       gimple *def = SSA_NAME_DEF_STMT (index);
2190*38fd1498Szrj       if (is_gimple_assign (def)
2191*38fd1498Szrj 	  && gimple_assign_rhs_code (def) == BIT_AND_EXPR
2192*38fd1498Szrj 	  && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
2193*38fd1498Szrj 	{
2194*38fd1498Szrj 	  tree cst = gimple_assign_rhs2 (def);
2195*38fd1498Szrj 	  tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,
2196*38fd1498Szrj 				 TYPE_SIZE_UNIT (type));
2197*38fd1498Szrj 	  if (tree_int_cst_sgn (cst) >= 0
2198*38fd1498Szrj 	      && tree_int_cst_lt (cst, sz))
2199*38fd1498Szrj 	    return;
2200*38fd1498Szrj 	}
2201*38fd1498Szrj     }
2202*38fd1498Szrj 
2203*38fd1498Szrj   if (bos_stmt && gimple_call_builtin_p (bos_stmt, BUILT_IN_OBJECT_SIZE))
2204*38fd1498Szrj     ubsan_create_edge (bos_stmt);
2205*38fd1498Szrj 
2206*38fd1498Szrj   /* We have to emit the check.  */
2207*38fd1498Szrj   t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE, true,
2208*38fd1498Szrj 				GSI_SAME_STMT);
2209*38fd1498Szrj   ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE, true,
2210*38fd1498Szrj 				  GSI_SAME_STMT);
2211*38fd1498Szrj   tree ckind = build_int_cst (unsigned_char_type_node,
2212*38fd1498Szrj 			      is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
2213*38fd1498Szrj   gimple *g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
2214*38fd1498Szrj 					 ptr, t, sizet, ckind);
2215*38fd1498Szrj   gimple_set_location (g, loc);
2216*38fd1498Szrj   gsi_insert_before (gsi, g, GSI_SAME_STMT);
2217*38fd1498Szrj }
2218*38fd1498Szrj 
2219*38fd1498Szrj /* Instrument values passed to builtin functions.  */
2220*38fd1498Szrj 
2221*38fd1498Szrj static void
instrument_builtin(gimple_stmt_iterator * gsi)2222*38fd1498Szrj instrument_builtin (gimple_stmt_iterator *gsi)
2223*38fd1498Szrj {
2224*38fd1498Szrj   gimple *stmt = gsi_stmt (*gsi);
2225*38fd1498Szrj   location_t loc = gimple_location (stmt);
2226*38fd1498Szrj   tree arg;
2227*38fd1498Szrj   enum built_in_function fcode
2228*38fd1498Szrj     = DECL_FUNCTION_CODE (gimple_call_fndecl (stmt));
2229*38fd1498Szrj   int kind = 0;
2230*38fd1498Szrj   switch (fcode)
2231*38fd1498Szrj     {
2232*38fd1498Szrj     CASE_INT_FN (BUILT_IN_CLZ):
2233*38fd1498Szrj       kind = 1;
2234*38fd1498Szrj       gcc_fallthrough ();
2235*38fd1498Szrj     CASE_INT_FN (BUILT_IN_CTZ):
2236*38fd1498Szrj       arg = gimple_call_arg (stmt, 0);
2237*38fd1498Szrj       if (!integer_nonzerop (arg))
2238*38fd1498Szrj 	{
2239*38fd1498Szrj 	  gimple *g;
2240*38fd1498Szrj 	  if (!is_gimple_val (arg))
2241*38fd1498Szrj 	    {
2242*38fd1498Szrj 	      g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
2243*38fd1498Szrj 	      gimple_set_location (g, loc);
2244*38fd1498Szrj 	      gsi_insert_before (gsi, g, GSI_SAME_STMT);
2245*38fd1498Szrj 	      arg = gimple_assign_lhs (g);
2246*38fd1498Szrj 	    }
2247*38fd1498Szrj 
2248*38fd1498Szrj 	  basic_block then_bb, fallthru_bb;
2249*38fd1498Szrj 	  *gsi = create_cond_insert_point (gsi, true, false, true,
2250*38fd1498Szrj 					   &then_bb, &fallthru_bb);
2251*38fd1498Szrj 	  g = gimple_build_cond (EQ_EXPR, arg,
2252*38fd1498Szrj 				 build_zero_cst (TREE_TYPE (arg)),
2253*38fd1498Szrj 				 NULL_TREE, NULL_TREE);
2254*38fd1498Szrj 	  gimple_set_location (g, loc);
2255*38fd1498Szrj 	  gsi_insert_after (gsi, g, GSI_NEW_STMT);
2256*38fd1498Szrj 
2257*38fd1498Szrj 	  *gsi = gsi_after_labels (then_bb);
2258*38fd1498Szrj 	  if (flag_sanitize_undefined_trap_on_error)
2259*38fd1498Szrj 	    g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2260*38fd1498Szrj 	  else
2261*38fd1498Szrj 	    {
2262*38fd1498Szrj 	      tree t = build_int_cst (unsigned_char_type_node, kind);
2263*38fd1498Szrj 	      tree data = ubsan_create_data ("__ubsan_builtin_data",
2264*38fd1498Szrj 					     1, &loc, NULL_TREE, t, NULL_TREE);
2265*38fd1498Szrj 	      data = build_fold_addr_expr_loc (loc, data);
2266*38fd1498Szrj 	      enum built_in_function bcode
2267*38fd1498Szrj 		= (flag_sanitize_recover & SANITIZE_BUILTIN)
2268*38fd1498Szrj 		  ? BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN
2269*38fd1498Szrj 		  : BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN_ABORT;
2270*38fd1498Szrj 	      tree fn = builtin_decl_explicit (bcode);
2271*38fd1498Szrj 
2272*38fd1498Szrj 	      g = gimple_build_call (fn, 1, data);
2273*38fd1498Szrj 	    }
2274*38fd1498Szrj 	  gimple_set_location (g, loc);
2275*38fd1498Szrj 	  gsi_insert_before (gsi, g, GSI_SAME_STMT);
2276*38fd1498Szrj 	  ubsan_create_edge (g);
2277*38fd1498Szrj 	}
2278*38fd1498Szrj       *gsi = gsi_for_stmt (stmt);
2279*38fd1498Szrj       break;
2280*38fd1498Szrj     default:
2281*38fd1498Szrj       break;
2282*38fd1498Szrj     }
2283*38fd1498Szrj }
2284*38fd1498Szrj 
2285*38fd1498Szrj namespace {
2286*38fd1498Szrj 
2287*38fd1498Szrj const pass_data pass_data_ubsan =
2288*38fd1498Szrj {
2289*38fd1498Szrj   GIMPLE_PASS, /* type */
2290*38fd1498Szrj   "ubsan", /* name */
2291*38fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
2292*38fd1498Szrj   TV_TREE_UBSAN, /* tv_id */
2293*38fd1498Szrj   ( PROP_cfg | PROP_ssa ), /* properties_required */
2294*38fd1498Szrj   0, /* properties_provided */
2295*38fd1498Szrj   0, /* properties_destroyed */
2296*38fd1498Szrj   0, /* todo_flags_start */
2297*38fd1498Szrj   TODO_update_ssa, /* todo_flags_finish */
2298*38fd1498Szrj };
2299*38fd1498Szrj 
2300*38fd1498Szrj class pass_ubsan : public gimple_opt_pass
2301*38fd1498Szrj {
2302*38fd1498Szrj public:
pass_ubsan(gcc::context * ctxt)2303*38fd1498Szrj   pass_ubsan (gcc::context *ctxt)
2304*38fd1498Szrj     : gimple_opt_pass (pass_data_ubsan, ctxt)
2305*38fd1498Szrj   {}
2306*38fd1498Szrj 
2307*38fd1498Szrj   /* opt_pass methods: */
gate(function *)2308*38fd1498Szrj   virtual bool gate (function *)
2309*38fd1498Szrj     {
2310*38fd1498Szrj       return sanitize_flags_p ((SANITIZE_NULL | SANITIZE_SI_OVERFLOW
2311*38fd1498Szrj 				| SANITIZE_BOOL | SANITIZE_ENUM
2312*38fd1498Szrj 				| SANITIZE_ALIGNMENT
2313*38fd1498Szrj 				| SANITIZE_NONNULL_ATTRIBUTE
2314*38fd1498Szrj 				| SANITIZE_RETURNS_NONNULL_ATTRIBUTE
2315*38fd1498Szrj 				| SANITIZE_OBJECT_SIZE
2316*38fd1498Szrj 				| SANITIZE_POINTER_OVERFLOW
2317*38fd1498Szrj 				| SANITIZE_BUILTIN));
2318*38fd1498Szrj     }
2319*38fd1498Szrj 
2320*38fd1498Szrj   virtual unsigned int execute (function *);
2321*38fd1498Szrj 
2322*38fd1498Szrj }; // class pass_ubsan
2323*38fd1498Szrj 
2324*38fd1498Szrj unsigned int
execute(function * fun)2325*38fd1498Szrj pass_ubsan::execute (function *fun)
2326*38fd1498Szrj {
2327*38fd1498Szrj   basic_block bb;
2328*38fd1498Szrj   gimple_stmt_iterator gsi;
2329*38fd1498Szrj   unsigned int ret = 0;
2330*38fd1498Szrj 
2331*38fd1498Szrj   initialize_sanitizer_builtins ();
2332*38fd1498Szrj 
2333*38fd1498Szrj   FOR_EACH_BB_FN (bb, fun)
2334*38fd1498Szrj     {
2335*38fd1498Szrj       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
2336*38fd1498Szrj 	{
2337*38fd1498Szrj 	  gimple *stmt = gsi_stmt (gsi);
2338*38fd1498Szrj 	  if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
2339*38fd1498Szrj 	    {
2340*38fd1498Szrj 	      gsi_next (&gsi);
2341*38fd1498Szrj 	      continue;
2342*38fd1498Szrj 	    }
2343*38fd1498Szrj 
2344*38fd1498Szrj 	  if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW, fun->decl))
2345*38fd1498Szrj 	      && is_gimple_assign (stmt))
2346*38fd1498Szrj 	    instrument_si_overflow (gsi);
2347*38fd1498Szrj 
2348*38fd1498Szrj 	  if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT, fun->decl))
2349*38fd1498Szrj 	    {
2350*38fd1498Szrj 	      if (gimple_store_p (stmt))
2351*38fd1498Szrj 		instrument_null (gsi, gimple_get_lhs (stmt), true);
2352*38fd1498Szrj 	      if (gimple_assign_single_p (stmt))
2353*38fd1498Szrj 		instrument_null (gsi, gimple_assign_rhs1 (stmt), false);
2354*38fd1498Szrj 	      if (is_gimple_call (stmt))
2355*38fd1498Szrj 		{
2356*38fd1498Szrj 		  unsigned args_num = gimple_call_num_args (stmt);
2357*38fd1498Szrj 		  for (unsigned i = 0; i < args_num; ++i)
2358*38fd1498Szrj 		    {
2359*38fd1498Szrj 		      tree arg = gimple_call_arg (stmt, i);
2360*38fd1498Szrj 		      if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2361*38fd1498Szrj 			continue;
2362*38fd1498Szrj 		      instrument_null (gsi, arg, false);
2363*38fd1498Szrj 		    }
2364*38fd1498Szrj 		}
2365*38fd1498Szrj 	    }
2366*38fd1498Szrj 
2367*38fd1498Szrj 	  if (sanitize_flags_p (SANITIZE_BOOL | SANITIZE_ENUM, fun->decl)
2368*38fd1498Szrj 	      && gimple_assign_load_p (stmt))
2369*38fd1498Szrj 	    {
2370*38fd1498Szrj 	      instrument_bool_enum_load (&gsi);
2371*38fd1498Szrj 	      bb = gimple_bb (stmt);
2372*38fd1498Szrj 	    }
2373*38fd1498Szrj 
2374*38fd1498Szrj 	  if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE, fun->decl)
2375*38fd1498Szrj 	      && is_gimple_call (stmt)
2376*38fd1498Szrj 	      && !gimple_call_internal_p (stmt))
2377*38fd1498Szrj 	    {
2378*38fd1498Szrj 	      instrument_nonnull_arg (&gsi);
2379*38fd1498Szrj 	      bb = gimple_bb (stmt);
2380*38fd1498Szrj 	    }
2381*38fd1498Szrj 
2382*38fd1498Szrj 	  if (sanitize_flags_p (SANITIZE_BUILTIN, fun->decl)
2383*38fd1498Szrj 	      && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
2384*38fd1498Szrj 	    {
2385*38fd1498Szrj 	      instrument_builtin (&gsi);
2386*38fd1498Szrj 	      bb = gimple_bb (stmt);
2387*38fd1498Szrj 	    }
2388*38fd1498Szrj 
2389*38fd1498Szrj 	  if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE, fun->decl)
2390*38fd1498Szrj 	      && gimple_code (stmt) == GIMPLE_RETURN)
2391*38fd1498Szrj 	    {
2392*38fd1498Szrj 	      instrument_nonnull_return (&gsi);
2393*38fd1498Szrj 	      bb = gimple_bb (stmt);
2394*38fd1498Szrj 	    }
2395*38fd1498Szrj 
2396*38fd1498Szrj 	  if (sanitize_flags_p (SANITIZE_OBJECT_SIZE, fun->decl))
2397*38fd1498Szrj 	    {
2398*38fd1498Szrj 	      if (gimple_store_p (stmt))
2399*38fd1498Szrj 		instrument_object_size (&gsi, gimple_get_lhs (stmt), true);
2400*38fd1498Szrj 	      if (gimple_assign_load_p (stmt))
2401*38fd1498Szrj 		instrument_object_size (&gsi, gimple_assign_rhs1 (stmt),
2402*38fd1498Szrj 					false);
2403*38fd1498Szrj 	      if (is_gimple_call (stmt))
2404*38fd1498Szrj 		{
2405*38fd1498Szrj 		  unsigned args_num = gimple_call_num_args (stmt);
2406*38fd1498Szrj 		  for (unsigned i = 0; i < args_num; ++i)
2407*38fd1498Szrj 		    {
2408*38fd1498Szrj 		      tree arg = gimple_call_arg (stmt, i);
2409*38fd1498Szrj 		      if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2410*38fd1498Szrj 			continue;
2411*38fd1498Szrj 		      instrument_object_size (&gsi, arg, false);
2412*38fd1498Szrj 		    }
2413*38fd1498Szrj 		}
2414*38fd1498Szrj 	    }
2415*38fd1498Szrj 
2416*38fd1498Szrj 	  if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW, fun->decl))
2417*38fd1498Szrj 	    {
2418*38fd1498Szrj 	      if (is_gimple_assign (stmt)
2419*38fd1498Szrj 		  && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
2420*38fd1498Szrj 		instrument_pointer_overflow (&gsi,
2421*38fd1498Szrj 					     gimple_assign_rhs1 (stmt),
2422*38fd1498Szrj 					     gimple_assign_rhs2 (stmt));
2423*38fd1498Szrj 	      if (gimple_store_p (stmt))
2424*38fd1498Szrj 		maybe_instrument_pointer_overflow (&gsi,
2425*38fd1498Szrj 						   gimple_get_lhs (stmt));
2426*38fd1498Szrj 	      if (gimple_assign_single_p (stmt))
2427*38fd1498Szrj 		maybe_instrument_pointer_overflow (&gsi,
2428*38fd1498Szrj 						   gimple_assign_rhs1 (stmt));
2429*38fd1498Szrj 	      if (is_gimple_call (stmt))
2430*38fd1498Szrj 		{
2431*38fd1498Szrj 		  unsigned args_num = gimple_call_num_args (stmt);
2432*38fd1498Szrj 		  for (unsigned i = 0; i < args_num; ++i)
2433*38fd1498Szrj 		    {
2434*38fd1498Szrj 		      tree arg = gimple_call_arg (stmt, i);
2435*38fd1498Szrj 		      if (is_gimple_reg (arg))
2436*38fd1498Szrj 			continue;
2437*38fd1498Szrj 		      maybe_instrument_pointer_overflow (&gsi, arg);
2438*38fd1498Szrj 		    }
2439*38fd1498Szrj 		}
2440*38fd1498Szrj 	    }
2441*38fd1498Szrj 
2442*38fd1498Szrj 	  gsi_next (&gsi);
2443*38fd1498Szrj 	}
2444*38fd1498Szrj       if (gimple_purge_dead_eh_edges (bb))
2445*38fd1498Szrj 	ret = TODO_cleanup_cfg;
2446*38fd1498Szrj     }
2447*38fd1498Szrj   return ret;
2448*38fd1498Szrj }
2449*38fd1498Szrj 
2450*38fd1498Szrj } // anon namespace
2451*38fd1498Szrj 
2452*38fd1498Szrj gimple_opt_pass *
make_pass_ubsan(gcc::context * ctxt)2453*38fd1498Szrj make_pass_ubsan (gcc::context *ctxt)
2454*38fd1498Szrj {
2455*38fd1498Szrj   return new pass_ubsan (ctxt);
2456*38fd1498Szrj }
2457*38fd1498Szrj 
2458*38fd1498Szrj #include "gt-ubsan.h"
2459