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