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