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