1 /* Pointer Bounds Checker insrumentation pass. 2 Copyright (C) 2014-2018 Free Software Foundation, Inc. 3 Contributed by Ilya Enkovich (ilya.enkovich@intel.com) 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 3, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #include "config.h" 22 #include "system.h" 23 #include "coretypes.h" 24 #include "backend.h" 25 #include "target.h" 26 #include "rtl.h" 27 #include "tree.h" 28 #include "gimple.h" 29 #include "cfghooks.h" 30 #include "tree-pass.h" 31 #include "ssa.h" 32 #include "cgraph.h" 33 #include "diagnostic.h" 34 #include "fold-const.h" 35 #include "stor-layout.h" 36 #include "varasm.h" 37 #include "tree-iterator.h" 38 #include "tree-cfg.h" 39 #include "langhooks.h" 40 #include "tree-ssa-address.h" 41 #include "tree-ssa-loop-niter.h" 42 #include "gimple-pretty-print.h" 43 #include "gimple-iterator.h" 44 #include "gimplify.h" 45 #include "gimplify-me.h" 46 #include "print-tree.h" 47 #include "calls.h" 48 #include "expr.h" 49 #include "tree-ssa-propagate.h" 50 #include "tree-chkp.h" 51 #include "gimple-walk.h" 52 #include "tree-dfa.h" 53 #include "ipa-chkp.h" 54 #include "params.h" 55 #include "stringpool.h" 56 #include "attribs.h" 57 58 /* Pointer Bounds Checker instruments code with memory checks to find 59 out-of-bounds memory accesses. Checks are performed by computing 60 bounds for each pointer and then comparing address of accessed 61 memory before pointer dereferencing. 62 63 1. Function clones. 64 65 See ipa-chkp.c. 66 67 2. Instrumentation. 68 69 There are few things to instrument: 70 71 a) Memory accesses - add checker calls to check address of accessed memory 72 against bounds of dereferenced pointer. Obviously safe memory 73 accesses like static variable access does not have to be instrumented 74 with checks. 75 76 Example: 77 78 val_2 = *p_1; 79 80 with 4 bytes access is transformed into: 81 82 __builtin___chkp_bndcl (__bound_tmp.1_3, p_1); 83 D.1_4 = p_1 + 3; 84 __builtin___chkp_bndcu (__bound_tmp.1_3, D.1_4); 85 val_2 = *p_1; 86 87 where __bound_tmp.1_3 are bounds computed for pointer p_1, 88 __builtin___chkp_bndcl is a lower bound check and 89 __builtin___chkp_bndcu is an upper bound check. 90 91 b) Pointer stores. 92 93 When pointer is stored in memory we need to store its bounds. To 94 achieve compatibility of instrumented code with regular codes 95 we have to keep data layout and store bounds in special bound tables 96 via special checker call. Implementation of bounds table may vary for 97 different platforms. It has to associate pointer value and its 98 location (it is required because we may have two equal pointers 99 with different bounds stored in different places) with bounds. 100 Another checker builtin allows to get bounds for specified pointer 101 loaded from specified location. 102 103 Example: 104 105 buf1[i_1] = &buf2; 106 107 is transformed into: 108 109 buf1[i_1] = &buf2; 110 D.1_2 = &buf1[i_1]; 111 __builtin___chkp_bndstx (D.1_2, &buf2, __bound_tmp.1_2); 112 113 where __bound_tmp.1_2 are bounds of &buf2. 114 115 c) Static initialization. 116 117 The special case of pointer store is static pointer initialization. 118 Bounds initialization is performed in a few steps: 119 - register all static initializations in front-end using 120 chkp_register_var_initializer 121 - when file compilation finishes we create functions with special 122 attribute 'chkp ctor' and put explicit initialization code 123 (assignments) for all statically initialized pointers. 124 - when checker constructor is compiled checker pass adds required 125 bounds initialization for all statically initialized pointers 126 - since we do not actually need excess pointers initialization 127 in checker constructor we remove such assignments from them 128 129 d) Calls. 130 131 For each call in the code we add additional arguments to pass 132 bounds for pointer arguments. We determine type of call arguments 133 using arguments list from function declaration; if function 134 declaration is not available we use function type; otherwise 135 (e.g. for unnamed arguments) we use type of passed value. Function 136 declaration/type is replaced with the instrumented one. 137 138 Example: 139 140 val_1 = foo (&buf1, &buf2, &buf1, 0); 141 142 is translated into: 143 144 val_1 = foo.chkp (&buf1, __bound_tmp.1_2, &buf2, __bound_tmp.1_3, 145 &buf1, __bound_tmp.1_2, 0); 146 147 e) Returns. 148 149 If function returns a pointer value we have to return bounds also. 150 A new operand was added for return statement to hold returned bounds. 151 152 Example: 153 154 return &_buf1; 155 156 is transformed into 157 158 return &_buf1, __bound_tmp.1_1; 159 160 3. Bounds computation. 161 162 Compiler is fully responsible for computing bounds to be used for each 163 memory access. The first step for bounds computation is to find the 164 origin of pointer dereferenced for memory access. Basing on pointer 165 origin we define a way to compute its bounds. There are just few 166 possible cases: 167 168 a) Pointer is returned by call. 169 170 In this case we use corresponding checker builtin method to obtain returned 171 bounds. 172 173 Example: 174 175 buf_1 = malloc (size_2); 176 foo (buf_1); 177 178 is translated into: 179 180 buf_1 = malloc (size_2); 181 __bound_tmp.1_3 = __builtin___chkp_bndret (buf_1); 182 foo (buf_1, __bound_tmp.1_3); 183 184 b) Pointer is an address of an object. 185 186 In this case compiler tries to compute objects size and create corresponding 187 bounds. If object has incomplete type then special checker builtin is used to 188 obtain its size at runtime. 189 190 Example: 191 192 foo () 193 { 194 <unnamed type> __bound_tmp.3; 195 static int buf[100]; 196 197 <bb 3>: 198 __bound_tmp.3_2 = __builtin___chkp_bndmk (&buf, 400); 199 200 <bb 2>: 201 return &buf, __bound_tmp.3_2; 202 } 203 204 Example: 205 206 Address of an object 'extern int buf[]' with incomplete type is 207 returned. 208 209 foo () 210 { 211 <unnamed type> __bound_tmp.4; 212 long unsigned int __size_tmp.3; 213 214 <bb 3>: 215 __size_tmp.3_4 = __builtin_ia32_sizeof (buf); 216 __bound_tmp.4_3 = __builtin_ia32_bndmk (&buf, __size_tmp.3_4); 217 218 <bb 2>: 219 return &buf, __bound_tmp.4_3; 220 } 221 222 c) Pointer is the result of object narrowing. 223 224 It happens when we use pointer to an object to compute pointer to a part 225 of an object. E.g. we take pointer to a field of a structure. In this 226 case we perform bounds intersection using bounds of original object and 227 bounds of object's part (which are computed basing on its type). 228 229 There may be some debatable questions about when narrowing should occur 230 and when it should not. To avoid false bound violations in correct 231 programs we do not perform narrowing when address of an array element is 232 obtained (it has address of the whole array) and when address of the first 233 structure field is obtained (because it is guaranteed to be equal to 234 address of the whole structure and it is legal to cast it back to structure). 235 236 Default narrowing behavior may be changed using compiler flags. 237 238 Example: 239 240 In this example address of the second structure field is returned. 241 242 foo (struct A * p, __bounds_type __bounds_of_p) 243 { 244 <unnamed type> __bound_tmp.3; 245 int * _2; 246 int * _5; 247 248 <bb 2>: 249 _5 = &p_1(D)->second_field; 250 __bound_tmp.3_6 = __builtin___chkp_bndmk (_5, 4); 251 __bound_tmp.3_8 = __builtin___chkp_intersect (__bound_tmp.3_6, 252 __bounds_of_p_3(D)); 253 _2 = &p_1(D)->second_field; 254 return _2, __bound_tmp.3_8; 255 } 256 257 Example: 258 259 In this example address of the first field of array element is returned. 260 261 foo (struct A * p, __bounds_type __bounds_of_p, int i) 262 { 263 long unsigned int _3; 264 long unsigned int _4; 265 struct A * _6; 266 int * _7; 267 268 <bb 2>: 269 _3 = (long unsigned int) i_1(D); 270 _4 = _3 * 8; 271 _6 = p_5(D) + _4; 272 _7 = &_6->first_field; 273 return _7, __bounds_of_p_2(D); 274 } 275 276 277 d) Pointer is the result of pointer arithmetic or type cast. 278 279 In this case bounds of the base pointer are used. In case of binary 280 operation producing a pointer we are analyzing data flow further 281 looking for operand's bounds. One operand is considered as a base 282 if it has some valid bounds. If we fall into a case when none of 283 operands (or both of them) has valid bounds, a default bounds value 284 is used. 285 286 Trying to find out bounds for binary operations we may fall into 287 cyclic dependencies for pointers. To avoid infinite recursion all 288 walked phi nodes instantly obtain corresponding bounds but created 289 bounds are marked as incomplete. It helps us to stop DF walk during 290 bounds search. 291 292 When we reach pointer source, some args of incomplete bounds phi obtain 293 valid bounds and those values are propagated further through phi nodes. 294 If no valid bounds were found for phi node then we mark its result as 295 invalid bounds. Process stops when all incomplete bounds become either 296 valid or invalid and we are able to choose a pointer base. 297 298 e) Pointer is loaded from the memory. 299 300 In this case we just need to load bounds from the bounds table. 301 302 Example: 303 304 foo () 305 { 306 <unnamed type> __bound_tmp.3; 307 static int * buf; 308 int * _2; 309 310 <bb 2>: 311 _2 = buf; 312 __bound_tmp.3_4 = __builtin___chkp_bndldx (&buf, _2); 313 return _2, __bound_tmp.3_4; 314 } 315 316 */ 317 318 typedef void (*assign_handler)(tree, tree, void *); 319 320 static tree chkp_get_zero_bounds (); 321 static tree chkp_find_bounds (tree ptr, gimple_stmt_iterator *iter); 322 static tree chkp_find_bounds_loaded (tree ptr, tree ptr_src, 323 gimple_stmt_iterator *iter); 324 static void chkp_parse_array_and_component_ref (tree node, tree *ptr, 325 tree *elt, bool *safe, 326 bool *bitfield, 327 tree *bounds, 328 gimple_stmt_iterator *iter, 329 bool innermost_bounds); 330 static void chkp_parse_bit_field_ref (tree node, location_t loc, 331 tree *offset, tree *size); 332 static tree 333 chkp_make_addressed_object_bounds (tree obj, gimple_stmt_iterator *iter); 334 335 #define chkp_bndldx_fndecl \ 336 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDLDX)) 337 #define chkp_bndstx_fndecl \ 338 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDSTX)) 339 #define chkp_checkl_fndecl \ 340 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDCL)) 341 #define chkp_checku_fndecl \ 342 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDCU)) 343 #define chkp_bndmk_fndecl \ 344 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDMK)) 345 #define chkp_ret_bnd_fndecl \ 346 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDRET)) 347 #define chkp_intersect_fndecl \ 348 (targetm.builtin_chkp_function (BUILT_IN_CHKP_INTERSECT)) 349 #define chkp_narrow_bounds_fndecl \ 350 (targetm.builtin_chkp_function (BUILT_IN_CHKP_NARROW)) 351 #define chkp_sizeof_fndecl \ 352 (targetm.builtin_chkp_function (BUILT_IN_CHKP_SIZEOF)) 353 #define chkp_extract_lower_fndecl \ 354 (targetm.builtin_chkp_function (BUILT_IN_CHKP_EXTRACT_LOWER)) 355 #define chkp_extract_upper_fndecl \ 356 (targetm.builtin_chkp_function (BUILT_IN_CHKP_EXTRACT_UPPER)) 357 358 static GTY (()) tree chkp_uintptr_type; 359 360 static GTY (()) tree chkp_zero_bounds_var; 361 static GTY (()) tree chkp_none_bounds_var; 362 363 static GTY (()) basic_block entry_block; 364 static GTY (()) tree zero_bounds; 365 static GTY (()) tree none_bounds; 366 static GTY (()) tree incomplete_bounds; 367 static GTY (()) tree tmp_var; 368 static GTY (()) tree size_tmp_var; 369 static GTY (()) bitmap chkp_abnormal_copies; 370 371 struct hash_set<tree> *chkp_invalid_bounds; 372 struct hash_set<tree> *chkp_completed_bounds_set; 373 struct hash_map<tree, tree> *chkp_reg_bounds; 374 struct hash_map<tree, tree> *chkp_bound_vars; 375 struct hash_map<tree, tree> *chkp_reg_addr_bounds; 376 struct hash_map<tree, tree> *chkp_incomplete_bounds_map; 377 struct hash_map<tree, tree> *chkp_bounds_map; 378 struct hash_map<tree, tree> *chkp_static_var_bounds; 379 380 static bool in_chkp_pass; 381 382 #define CHKP_BOUND_TMP_NAME "__bound_tmp" 383 #define CHKP_SIZE_TMP_NAME "__size_tmp" 384 #define CHKP_BOUNDS_OF_SYMBOL_PREFIX "__chkp_bounds_of_" 385 #define CHKP_STRING_BOUNDS_PREFIX "__chkp_string_bounds_" 386 #define CHKP_VAR_BOUNDS_PREFIX "__chkp_var_bounds_" 387 #define CHKP_ZERO_BOUNDS_VAR_NAME "__chkp_zero_bounds" 388 #define CHKP_NONE_BOUNDS_VAR_NAME "__chkp_none_bounds" 389 390 /* Static checker constructors may become very large and their 391 compilation with optimization may take too much time. 392 Therefore we put a limit to number of statements in one 393 constructor. Tests with 100 000 statically initialized 394 pointers showed following compilation times on Sandy Bridge 395 server (used -O2): 396 limit 100 => ~18 sec. 397 limit 300 => ~22 sec. 398 limit 1000 => ~30 sec. 399 limit 3000 => ~49 sec. 400 limit 5000 => ~55 sec. 401 limit 10000 => ~76 sec. 402 limit 100000 => ~532 sec. */ 403 #define MAX_STMTS_IN_STATIC_CHKP_CTOR (PARAM_VALUE (PARAM_CHKP_MAX_CTOR_SIZE)) 404 405 struct chkp_ctor_stmt_list 406 { 407 tree stmts; 408 int avail; 409 }; 410 411 /* Return 1 if function FNDECL is instrumented by Pointer 412 Bounds Checker. */ 413 bool 414 chkp_function_instrumented_p (tree fndecl) 415 { 416 return fndecl 417 && lookup_attribute ("chkp instrumented", DECL_ATTRIBUTES (fndecl)); 418 } 419 420 /* Mark function FNDECL as instrumented. */ 421 void 422 chkp_function_mark_instrumented (tree fndecl) 423 { 424 if (chkp_function_instrumented_p (fndecl)) 425 return; 426 427 DECL_ATTRIBUTES (fndecl) 428 = tree_cons (get_identifier ("chkp instrumented"), NULL, 429 DECL_ATTRIBUTES (fndecl)); 430 } 431 432 /* Return true when STMT is builtin call to instrumentation function 433 corresponding to CODE. */ 434 435 bool 436 chkp_gimple_call_builtin_p (gimple *call, 437 enum built_in_function code) 438 { 439 tree fndecl; 440 /* We are skipping the check for address-spaces, that's 441 why we don't use gimple_call_builtin_p directly here. */ 442 if (is_gimple_call (call) 443 && (fndecl = gimple_call_fndecl (call)) != NULL 444 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD 445 && (fndecl = targetm.builtin_chkp_function (code)) 446 && (DECL_FUNCTION_CODE (gimple_call_fndecl (call)) 447 == DECL_FUNCTION_CODE (fndecl))) 448 return true; 449 return false; 450 } 451 452 /* Emit code to build zero bounds and return RTL holding 453 the result. */ 454 rtx 455 chkp_expand_zero_bounds () 456 { 457 tree zero_bnd; 458 459 if (flag_chkp_use_static_const_bounds) 460 zero_bnd = chkp_get_zero_bounds_var (); 461 else 462 zero_bnd = chkp_build_make_bounds_call (integer_zero_node, 463 integer_zero_node); 464 return expand_normal (zero_bnd); 465 } 466 467 /* Emit code to store zero bounds for PTR located at MEM. */ 468 void 469 chkp_expand_bounds_reset_for_mem (tree mem, tree ptr) 470 { 471 tree zero_bnd, bnd, addr, bndstx; 472 473 if (flag_chkp_use_static_const_bounds) 474 zero_bnd = chkp_get_zero_bounds_var (); 475 else 476 zero_bnd = chkp_build_make_bounds_call (integer_zero_node, 477 integer_zero_node); 478 bnd = make_tree (pointer_bounds_type_node, 479 assign_temp (pointer_bounds_type_node, 0, 1)); 480 addr = build1 (ADDR_EXPR, 481 build_pointer_type (TREE_TYPE (mem)), mem); 482 bndstx = chkp_build_bndstx_call (addr, ptr, bnd); 483 484 expand_assignment (bnd, zero_bnd, false); 485 expand_normal (bndstx); 486 } 487 488 /* Build retbnd call for returned value RETVAL. 489 490 If BNDVAL is not NULL then result is stored 491 in it. Otherwise a temporary is created to 492 hold returned value. 493 494 GSI points to a position for a retbnd call 495 and is set to created stmt. 496 497 Cgraph edge is created for a new call if 498 UPDATE_EDGE is 1. 499 500 Obtained bounds are returned. */ 501 tree 502 chkp_insert_retbnd_call (tree bndval, tree retval, 503 gimple_stmt_iterator *gsi) 504 { 505 gimple *call; 506 507 if (!bndval) 508 bndval = create_tmp_reg (pointer_bounds_type_node, "retbnd"); 509 510 call = gimple_build_call (chkp_ret_bnd_fndecl, 1, retval); 511 gimple_call_set_lhs (call, bndval); 512 gsi_insert_after (gsi, call, GSI_CONTINUE_LINKING); 513 514 return bndval; 515 } 516 517 /* Build a GIMPLE_CALL identical to CALL but skipping bounds 518 arguments. */ 519 520 gcall * 521 chkp_copy_call_skip_bounds (gcall *call) 522 { 523 bitmap bounds; 524 unsigned i; 525 526 bitmap_obstack_initialize (NULL); 527 bounds = BITMAP_ALLOC (NULL); 528 529 for (i = 0; i < gimple_call_num_args (call); i++) 530 if (POINTER_BOUNDS_P (gimple_call_arg (call, i))) 531 bitmap_set_bit (bounds, i); 532 533 if (!bitmap_empty_p (bounds)) 534 call = gimple_call_copy_skip_args (call, bounds); 535 gimple_call_set_with_bounds (call, false); 536 537 BITMAP_FREE (bounds); 538 bitmap_obstack_release (NULL); 539 540 return call; 541 } 542 543 /* Redirect edge E to the correct node according to call_stmt. 544 Return 1 if bounds removal from call_stmt should be done 545 instead of redirection. */ 546 547 bool 548 chkp_redirect_edge (cgraph_edge *e) 549 { 550 bool instrumented = false; 551 tree decl = e->callee->decl; 552 553 if (e->callee->instrumentation_clone 554 || chkp_function_instrumented_p (decl)) 555 instrumented = true; 556 557 if (instrumented 558 && !gimple_call_with_bounds_p (e->call_stmt)) 559 e->redirect_callee (cgraph_node::get_create (e->callee->orig_decl)); 560 else if (!instrumented 561 && gimple_call_with_bounds_p (e->call_stmt) 562 && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDCL) 563 && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDCU) 564 && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDSTX)) 565 { 566 if (e->callee->instrumented_version) 567 e->redirect_callee (e->callee->instrumented_version); 568 else 569 { 570 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl)); 571 /* Avoid bounds removal if all args will be removed. */ 572 if (!args || TREE_VALUE (args) != void_type_node) 573 return true; 574 else 575 gimple_call_set_with_bounds (e->call_stmt, false); 576 } 577 } 578 579 return false; 580 } 581 582 /* Mark statement S to not be instrumented. */ 583 static void 584 chkp_mark_stmt (gimple *s) 585 { 586 gimple_set_plf (s, GF_PLF_1, true); 587 } 588 589 /* Mark statement S to be instrumented. */ 590 static void 591 chkp_unmark_stmt (gimple *s) 592 { 593 gimple_set_plf (s, GF_PLF_1, false); 594 } 595 596 /* Return 1 if statement S should not be instrumented. */ 597 static bool 598 chkp_marked_stmt_p (gimple *s) 599 { 600 return gimple_plf (s, GF_PLF_1); 601 } 602 603 /* Get var to be used for bound temps. */ 604 static tree 605 chkp_get_tmp_var (void) 606 { 607 if (!tmp_var) 608 tmp_var = create_tmp_reg (pointer_bounds_type_node, CHKP_BOUND_TMP_NAME); 609 610 return tmp_var; 611 } 612 613 /* Get SSA_NAME to be used as temp. */ 614 static tree 615 chkp_get_tmp_reg (gimple *stmt) 616 { 617 if (in_chkp_pass) 618 return make_ssa_name (chkp_get_tmp_var (), stmt); 619 620 return make_temp_ssa_name (pointer_bounds_type_node, stmt, 621 CHKP_BOUND_TMP_NAME); 622 } 623 624 /* Get var to be used for size temps. */ 625 static tree 626 chkp_get_size_tmp_var (void) 627 { 628 if (!size_tmp_var) 629 size_tmp_var = create_tmp_reg (chkp_uintptr_type, CHKP_SIZE_TMP_NAME); 630 631 return size_tmp_var; 632 } 633 634 /* Register bounds BND for address of OBJ. */ 635 static void 636 chkp_register_addr_bounds (tree obj, tree bnd) 637 { 638 if (bnd == incomplete_bounds) 639 return; 640 641 chkp_reg_addr_bounds->put (obj, bnd); 642 643 if (dump_file && (dump_flags & TDF_DETAILS)) 644 { 645 fprintf (dump_file, "Regsitered bound "); 646 print_generic_expr (dump_file, bnd); 647 fprintf (dump_file, " for address of "); 648 print_generic_expr (dump_file, obj); 649 fprintf (dump_file, "\n"); 650 } 651 } 652 653 /* Return bounds registered for address of OBJ. */ 654 static tree 655 chkp_get_registered_addr_bounds (tree obj) 656 { 657 tree *slot = chkp_reg_addr_bounds->get (obj); 658 return slot ? *slot : NULL_TREE; 659 } 660 661 /* Mark BOUNDS as completed. */ 662 static void 663 chkp_mark_completed_bounds (tree bounds) 664 { 665 chkp_completed_bounds_set->add (bounds); 666 667 if (dump_file && (dump_flags & TDF_DETAILS)) 668 { 669 fprintf (dump_file, "Marked bounds "); 670 print_generic_expr (dump_file, bounds); 671 fprintf (dump_file, " as completed\n"); 672 } 673 } 674 675 /* Return 1 if BOUNDS were marked as completed and 0 otherwise. */ 676 static bool 677 chkp_completed_bounds (tree bounds) 678 { 679 return chkp_completed_bounds_set->contains (bounds); 680 } 681 682 /* Clear comleted bound marks. */ 683 static void 684 chkp_erase_completed_bounds (void) 685 { 686 delete chkp_completed_bounds_set; 687 chkp_completed_bounds_set = new hash_set<tree>; 688 } 689 690 /* This function is used to provide a base address for 691 chkp_get_hard_register_fake_addr_expr. */ 692 static tree 693 chkp_get_hard_register_var_fake_base_address () 694 { 695 int prec = TYPE_PRECISION (ptr_type_node); 696 return wide_int_to_tree (ptr_type_node, wi::min_value (prec, SIGNED)); 697 } 698 699 /* If we check bounds for a hard register variable, we cannot 700 use its address - it is illegal, so instead of that we use 701 this fake value. */ 702 static tree 703 chkp_get_hard_register_fake_addr_expr (tree obj) 704 { 705 tree addr = chkp_get_hard_register_var_fake_base_address (); 706 tree outer = obj; 707 while (TREE_CODE (outer) == COMPONENT_REF || TREE_CODE (outer) == ARRAY_REF) 708 { 709 if (TREE_CODE (outer) == COMPONENT_REF) 710 { 711 addr = fold_build_pointer_plus (addr, 712 component_ref_field_offset (outer)); 713 outer = TREE_OPERAND (outer, 0); 714 } 715 else if (TREE_CODE (outer) == ARRAY_REF) 716 { 717 tree indx = fold_convert(size_type_node, TREE_OPERAND(outer, 1)); 718 tree offset = size_binop (MULT_EXPR, 719 array_ref_element_size (outer), indx); 720 addr = fold_build_pointer_plus (addr, offset); 721 outer = TREE_OPERAND (outer, 0); 722 } 723 } 724 725 return addr; 726 } 727 728 /* Mark BOUNDS associated with PTR as incomplete. */ 729 static void 730 chkp_register_incomplete_bounds (tree bounds, tree ptr) 731 { 732 chkp_incomplete_bounds_map->put (bounds, ptr); 733 734 if (dump_file && (dump_flags & TDF_DETAILS)) 735 { 736 fprintf (dump_file, "Regsitered incomplete bounds "); 737 print_generic_expr (dump_file, bounds); 738 fprintf (dump_file, " for "); 739 print_generic_expr (dump_file, ptr); 740 fprintf (dump_file, "\n"); 741 } 742 } 743 744 /* Return 1 if BOUNDS are incomplete and 0 otherwise. */ 745 static bool 746 chkp_incomplete_bounds (tree bounds) 747 { 748 if (bounds == incomplete_bounds) 749 return true; 750 751 if (chkp_completed_bounds (bounds)) 752 return false; 753 754 return chkp_incomplete_bounds_map->get (bounds) != NULL; 755 } 756 757 /* Clear incomleted bound marks. */ 758 static void 759 chkp_erase_incomplete_bounds (void) 760 { 761 delete chkp_incomplete_bounds_map; 762 chkp_incomplete_bounds_map = new hash_map<tree, tree>; 763 } 764 765 /* Build and return bndmk call which creates bounds for structure 766 pointed by PTR. Structure should have complete type. */ 767 tree 768 chkp_make_bounds_for_struct_addr (tree ptr) 769 { 770 tree type = TREE_TYPE (ptr); 771 tree size; 772 773 gcc_assert (POINTER_TYPE_P (type)); 774 775 size = TYPE_SIZE (TREE_TYPE (type)); 776 777 gcc_assert (size); 778 779 return build_call_nary (pointer_bounds_type_node, 780 build_fold_addr_expr (chkp_bndmk_fndecl), 781 2, ptr, size); 782 } 783 784 /* Traversal function for chkp_may_finish_incomplete_bounds. 785 Set RES to 0 if at least one argument of phi statement 786 defining bounds (passed in KEY arg) is unknown. 787 Traversal stops when first unknown phi argument is found. */ 788 bool 789 chkp_may_complete_phi_bounds (tree const &bounds, tree *slot ATTRIBUTE_UNUSED, 790 bool *res) 791 { 792 gimple *phi; 793 unsigned i; 794 795 gcc_assert (TREE_CODE (bounds) == SSA_NAME); 796 797 phi = SSA_NAME_DEF_STMT (bounds); 798 799 gcc_assert (phi && gimple_code (phi) == GIMPLE_PHI); 800 801 for (i = 0; i < gimple_phi_num_args (phi); i++) 802 { 803 tree phi_arg = gimple_phi_arg_def (phi, i); 804 if (!phi_arg) 805 { 806 *res = false; 807 /* Do not need to traverse further. */ 808 return false; 809 } 810 } 811 812 return true; 813 } 814 815 /* Return 1 if all phi nodes created for bounds have their 816 arguments computed. */ 817 static bool 818 chkp_may_finish_incomplete_bounds (void) 819 { 820 bool res = true; 821 822 chkp_incomplete_bounds_map 823 ->traverse<bool *, chkp_may_complete_phi_bounds> (&res); 824 825 return res; 826 } 827 828 /* Helper function for chkp_finish_incomplete_bounds. 829 Recompute args for bounds phi node. */ 830 bool 831 chkp_recompute_phi_bounds (tree const &bounds, tree *slot, 832 void *res ATTRIBUTE_UNUSED) 833 { 834 tree ptr = *slot; 835 gphi *bounds_phi; 836 gphi *ptr_phi; 837 unsigned i; 838 839 gcc_assert (TREE_CODE (bounds) == SSA_NAME); 840 gcc_assert (TREE_CODE (ptr) == SSA_NAME); 841 842 bounds_phi = as_a <gphi *> (SSA_NAME_DEF_STMT (bounds)); 843 ptr_phi = as_a <gphi *> (SSA_NAME_DEF_STMT (ptr)); 844 845 for (i = 0; i < gimple_phi_num_args (bounds_phi); i++) 846 { 847 tree ptr_arg = gimple_phi_arg_def (ptr_phi, i); 848 tree bound_arg = chkp_find_bounds (ptr_arg, NULL); 849 850 add_phi_arg (bounds_phi, bound_arg, 851 gimple_phi_arg_edge (ptr_phi, i), 852 UNKNOWN_LOCATION); 853 } 854 855 return true; 856 } 857 858 /* Mark BOUNDS as invalid. */ 859 static void 860 chkp_mark_invalid_bounds (tree bounds) 861 { 862 chkp_invalid_bounds->add (bounds); 863 864 if (dump_file && (dump_flags & TDF_DETAILS)) 865 { 866 fprintf (dump_file, "Marked bounds "); 867 print_generic_expr (dump_file, bounds); 868 fprintf (dump_file, " as invalid\n"); 869 } 870 } 871 872 /* Return 1 if BOUNDS were marked as invalid and 0 otherwise. */ 873 static bool 874 chkp_valid_bounds (tree bounds) 875 { 876 if (bounds == zero_bounds || bounds == none_bounds) 877 return false; 878 879 return !chkp_invalid_bounds->contains (bounds); 880 } 881 882 /* Helper function for chkp_finish_incomplete_bounds. 883 Check all arguments of phi nodes trying to find 884 valid completed bounds. If there is at least one 885 such arg then bounds produced by phi node are marked 886 as valid completed bounds and all phi args are 887 recomputed. */ 888 bool 889 chkp_find_valid_phi_bounds (tree const &bounds, tree *slot, bool *res) 890 { 891 gimple *phi; 892 unsigned i; 893 894 gcc_assert (TREE_CODE (bounds) == SSA_NAME); 895 896 if (chkp_completed_bounds (bounds)) 897 return true; 898 899 phi = SSA_NAME_DEF_STMT (bounds); 900 901 gcc_assert (phi && gimple_code (phi) == GIMPLE_PHI); 902 903 for (i = 0; i < gimple_phi_num_args (phi); i++) 904 { 905 tree phi_arg = gimple_phi_arg_def (phi, i); 906 907 gcc_assert (phi_arg); 908 909 if (chkp_valid_bounds (phi_arg) && !chkp_incomplete_bounds (phi_arg)) 910 { 911 *res = true; 912 chkp_mark_completed_bounds (bounds); 913 chkp_recompute_phi_bounds (bounds, slot, NULL); 914 return true; 915 } 916 } 917 918 return true; 919 } 920 921 /* Helper function for chkp_finish_incomplete_bounds. 922 Marks all incompleted bounds as invalid. */ 923 bool 924 chkp_mark_invalid_bounds_walker (tree const &bounds, 925 tree *slot ATTRIBUTE_UNUSED, 926 void *res ATTRIBUTE_UNUSED) 927 { 928 if (!chkp_completed_bounds (bounds)) 929 { 930 chkp_mark_invalid_bounds (bounds); 931 chkp_mark_completed_bounds (bounds); 932 } 933 return true; 934 } 935 936 /* When all bound phi nodes have all their args computed 937 we have enough info to find valid bounds. We iterate 938 through all incompleted bounds searching for valid 939 bounds. Found valid bounds are marked as completed 940 and all remaining incompleted bounds are recomputed. 941 Process continues until no new valid bounds may be 942 found. All remained incompleted bounds are marked as 943 invalid (i.e. have no valid source of bounds). */ 944 static void 945 chkp_finish_incomplete_bounds (void) 946 { 947 bool found_valid = true; 948 949 while (found_valid) 950 { 951 found_valid = false; 952 953 chkp_incomplete_bounds_map-> 954 traverse<bool *, chkp_find_valid_phi_bounds> (&found_valid); 955 956 if (found_valid) 957 chkp_incomplete_bounds_map-> 958 traverse<void *, chkp_recompute_phi_bounds> (NULL); 959 } 960 961 chkp_incomplete_bounds_map-> 962 traverse<void *, chkp_mark_invalid_bounds_walker> (NULL); 963 chkp_incomplete_bounds_map-> 964 traverse<void *, chkp_recompute_phi_bounds> (NULL); 965 966 chkp_erase_completed_bounds (); 967 chkp_erase_incomplete_bounds (); 968 } 969 970 /* Return 1 if type TYPE is a pointer type or a 971 structure having a pointer type as one of its fields. 972 Otherwise return 0. */ 973 bool 974 chkp_type_has_pointer (const_tree type) 975 { 976 bool res = false; 977 978 if (BOUNDED_TYPE_P (type)) 979 res = true; 980 else if (RECORD_OR_UNION_TYPE_P (type)) 981 { 982 tree field; 983 984 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) 985 if (TREE_CODE (field) == FIELD_DECL) 986 res = res || chkp_type_has_pointer (TREE_TYPE (field)); 987 } 988 else if (TREE_CODE (type) == ARRAY_TYPE) 989 res = chkp_type_has_pointer (TREE_TYPE (type)); 990 991 return res; 992 } 993 994 unsigned 995 chkp_type_bounds_count (const_tree type) 996 { 997 unsigned res = 0; 998 999 if (!type) 1000 res = 0; 1001 else if (BOUNDED_TYPE_P (type)) 1002 res = 1; 1003 else if (RECORD_OR_UNION_TYPE_P (type)) 1004 { 1005 bitmap have_bound; 1006 1007 bitmap_obstack_initialize (NULL); 1008 have_bound = BITMAP_ALLOC (NULL); 1009 chkp_find_bound_slots (type, have_bound); 1010 res = bitmap_count_bits (have_bound); 1011 BITMAP_FREE (have_bound); 1012 bitmap_obstack_release (NULL); 1013 } 1014 1015 return res; 1016 } 1017 1018 /* Get bounds associated with NODE via 1019 chkp_set_bounds call. */ 1020 tree 1021 chkp_get_bounds (tree node) 1022 { 1023 tree *slot; 1024 1025 if (!chkp_bounds_map) 1026 return NULL_TREE; 1027 1028 slot = chkp_bounds_map->get (node); 1029 return slot ? *slot : NULL_TREE; 1030 } 1031 1032 /* Associate bounds VAL with NODE. */ 1033 void 1034 chkp_set_bounds (tree node, tree val) 1035 { 1036 if (!chkp_bounds_map) 1037 chkp_bounds_map = new hash_map<tree, tree>; 1038 1039 chkp_bounds_map->put (node, val); 1040 } 1041 1042 /* Check if statically initialized variable VAR require 1043 static bounds initialization. If VAR is added into 1044 bounds initlization list then 1 is returned. Otherwise 1045 return 0. */ 1046 extern bool 1047 chkp_register_var_initializer (tree var) 1048 { 1049 if (!flag_check_pointer_bounds 1050 || DECL_INITIAL (var) == error_mark_node) 1051 return false; 1052 1053 gcc_assert (VAR_P (var)); 1054 gcc_assert (DECL_INITIAL (var)); 1055 1056 if (TREE_STATIC (var) 1057 && chkp_type_has_pointer (TREE_TYPE (var))) 1058 { 1059 varpool_node::get_create (var)->need_bounds_init = 1; 1060 return true; 1061 } 1062 1063 return false; 1064 } 1065 1066 /* Helper function for chkp_finish_file. 1067 1068 Add new modification statement (RHS is assigned to LHS) 1069 into list of static initializer statementes (passed in ARG). 1070 If statements list becomes too big, emit checker constructor 1071 and start the new one. */ 1072 static void 1073 chkp_add_modification_to_stmt_list (tree lhs, 1074 tree rhs, 1075 void *arg) 1076 { 1077 struct chkp_ctor_stmt_list *stmts = (struct chkp_ctor_stmt_list *)arg; 1078 tree modify; 1079 1080 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs))) 1081 rhs = build1 (CONVERT_EXPR, TREE_TYPE (lhs), rhs); 1082 1083 modify = build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, rhs); 1084 append_to_statement_list (modify, &stmts->stmts); 1085 1086 stmts->avail--; 1087 } 1088 1089 /* Build and return ADDR_EXPR for specified object OBJ. */ 1090 static tree 1091 chkp_build_addr_expr (tree obj) 1092 { 1093 /* We first check whether it is a "hard reg case". */ 1094 tree base = get_base_address (obj); 1095 if (VAR_P (base) && DECL_HARD_REGISTER (base)) 1096 return chkp_get_hard_register_fake_addr_expr (obj); 1097 1098 /* If not - return regular ADDR_EXPR. */ 1099 return TREE_CODE (obj) == TARGET_MEM_REF 1100 ? tree_mem_ref_addr (ptr_type_node, obj) 1101 : build_fold_addr_expr (obj); 1102 } 1103 1104 /* Helper function for chkp_finish_file. 1105 Initialize bound variable BND_VAR with bounds of variable 1106 VAR to statements list STMTS. If statements list becomes 1107 too big, emit checker constructor and start the new one. */ 1108 static void 1109 chkp_output_static_bounds (tree bnd_var, tree var, 1110 struct chkp_ctor_stmt_list *stmts) 1111 { 1112 tree lb, ub, size; 1113 1114 if (TREE_CODE (var) == STRING_CST) 1115 { 1116 lb = build1 (CONVERT_EXPR, size_type_node, chkp_build_addr_expr (var)); 1117 size = build_int_cst (size_type_node, TREE_STRING_LENGTH (var) - 1); 1118 } 1119 else if (DECL_SIZE (var) 1120 && !chkp_variable_size_type (TREE_TYPE (var))) 1121 { 1122 /* Compute bounds using statically known size. */ 1123 lb = build1 (CONVERT_EXPR, size_type_node, chkp_build_addr_expr (var)); 1124 size = size_binop (MINUS_EXPR, DECL_SIZE_UNIT (var), size_one_node); 1125 } 1126 else 1127 { 1128 /* Compute bounds using dynamic size. */ 1129 tree call; 1130 1131 lb = build1 (CONVERT_EXPR, size_type_node, chkp_build_addr_expr (var)); 1132 call = build1 (ADDR_EXPR, 1133 build_pointer_type (TREE_TYPE (chkp_sizeof_fndecl)), 1134 chkp_sizeof_fndecl); 1135 size = build_call_nary (TREE_TYPE (TREE_TYPE (chkp_sizeof_fndecl)), 1136 call, 1, var); 1137 1138 if (flag_chkp_zero_dynamic_size_as_infinite) 1139 { 1140 tree max_size, cond; 1141 1142 max_size = build2 (MINUS_EXPR, size_type_node, size_zero_node, lb); 1143 cond = build2 (NE_EXPR, boolean_type_node, size, size_zero_node); 1144 size = build3 (COND_EXPR, size_type_node, cond, size, max_size); 1145 } 1146 1147 size = size_binop (MINUS_EXPR, size, size_one_node); 1148 } 1149 1150 ub = size_binop (PLUS_EXPR, lb, size); 1151 stmts->avail -= targetm.chkp_initialize_bounds (bnd_var, lb, ub, 1152 &stmts->stmts); 1153 if (stmts->avail <= 0) 1154 { 1155 cgraph_build_static_cdtor ('B', stmts->stmts, 1156 MAX_RESERVED_INIT_PRIORITY + 2); 1157 stmts->avail = MAX_STMTS_IN_STATIC_CHKP_CTOR; 1158 stmts->stmts = NULL; 1159 } 1160 } 1161 1162 /* Return entry block to be used for checker initilization code. 1163 Create new block if required. */ 1164 static basic_block 1165 chkp_get_entry_block (void) 1166 { 1167 if (!entry_block) 1168 entry_block 1169 = split_block_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun))->dest; 1170 1171 return entry_block; 1172 } 1173 1174 /* Return a bounds var to be used for pointer var PTR_VAR. */ 1175 static tree 1176 chkp_get_bounds_var (tree ptr_var) 1177 { 1178 tree bnd_var; 1179 tree *slot; 1180 1181 slot = chkp_bound_vars->get (ptr_var); 1182 if (slot) 1183 bnd_var = *slot; 1184 else 1185 { 1186 bnd_var = create_tmp_reg (pointer_bounds_type_node, 1187 CHKP_BOUND_TMP_NAME); 1188 chkp_bound_vars->put (ptr_var, bnd_var); 1189 } 1190 1191 return bnd_var; 1192 } 1193 1194 /* If BND is an abnormal bounds copy, return a copied value. 1195 Otherwise return BND. */ 1196 static tree 1197 chkp_get_orginal_bounds_for_abnormal_copy (tree bnd) 1198 { 1199 if (bitmap_bit_p (chkp_abnormal_copies, SSA_NAME_VERSION (bnd))) 1200 { 1201 gimple *bnd_def = SSA_NAME_DEF_STMT (bnd); 1202 gcc_checking_assert (gimple_code (bnd_def) == GIMPLE_ASSIGN); 1203 bnd = gimple_assign_rhs1 (bnd_def); 1204 } 1205 1206 return bnd; 1207 } 1208 1209 /* Register bounds BND for object PTR in global bounds table. 1210 A copy of bounds may be created for abnormal ssa names. 1211 Returns bounds to use for PTR. */ 1212 static tree 1213 chkp_maybe_copy_and_register_bounds (tree ptr, tree bnd) 1214 { 1215 bool abnormal_ptr; 1216 1217 if (!chkp_reg_bounds) 1218 return bnd; 1219 1220 /* Do nothing if bounds are incomplete_bounds 1221 because it means bounds will be recomputed. */ 1222 if (bnd == incomplete_bounds) 1223 return bnd; 1224 1225 abnormal_ptr = (TREE_CODE (ptr) == SSA_NAME 1226 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr) 1227 && gimple_code (SSA_NAME_DEF_STMT (ptr)) != GIMPLE_PHI); 1228 1229 /* A single bounds value may be reused multiple times for 1230 different pointer values. It may cause coalescing issues 1231 for abnormal SSA names. To avoid it we create a bounds 1232 copy in case it is computed for abnormal SSA name. 1233 1234 We also cannot reuse such created copies for other pointers */ 1235 if (abnormal_ptr 1236 || bitmap_bit_p (chkp_abnormal_copies, SSA_NAME_VERSION (bnd))) 1237 { 1238 tree bnd_var = NULL_TREE; 1239 1240 if (abnormal_ptr) 1241 { 1242 if (SSA_NAME_VAR (ptr)) 1243 bnd_var = chkp_get_bounds_var (SSA_NAME_VAR (ptr)); 1244 } 1245 else 1246 bnd_var = chkp_get_tmp_var (); 1247 1248 /* For abnormal copies we may just find original 1249 bounds and use them. */ 1250 if (!abnormal_ptr && !SSA_NAME_IS_DEFAULT_DEF (bnd)) 1251 bnd = chkp_get_orginal_bounds_for_abnormal_copy (bnd); 1252 /* For undefined values we usually use none bounds 1253 value but in case of abnormal edge it may cause 1254 coalescing failures. Use default definition of 1255 bounds variable instead to avoid it. */ 1256 else if (SSA_NAME_IS_DEFAULT_DEF (ptr) 1257 && TREE_CODE (SSA_NAME_VAR (ptr)) != PARM_DECL) 1258 { 1259 bnd = get_or_create_ssa_default_def (cfun, bnd_var); 1260 1261 if (dump_file && (dump_flags & TDF_DETAILS)) 1262 { 1263 fprintf (dump_file, "Using default def bounds "); 1264 print_generic_expr (dump_file, bnd); 1265 fprintf (dump_file, " for abnormal default def SSA name "); 1266 print_generic_expr (dump_file, ptr); 1267 fprintf (dump_file, "\n"); 1268 } 1269 } 1270 else 1271 { 1272 tree copy; 1273 gimple *def = SSA_NAME_DEF_STMT (ptr); 1274 gimple *assign; 1275 gimple_stmt_iterator gsi; 1276 1277 if (bnd_var) 1278 copy = make_ssa_name (bnd_var); 1279 else 1280 copy = make_temp_ssa_name (pointer_bounds_type_node, 1281 NULL, 1282 CHKP_BOUND_TMP_NAME); 1283 bnd = chkp_get_orginal_bounds_for_abnormal_copy (bnd); 1284 assign = gimple_build_assign (copy, bnd); 1285 1286 if (dump_file && (dump_flags & TDF_DETAILS)) 1287 { 1288 fprintf (dump_file, "Creating a copy of bounds "); 1289 print_generic_expr (dump_file, bnd); 1290 fprintf (dump_file, " for abnormal SSA name "); 1291 print_generic_expr (dump_file, ptr); 1292 fprintf (dump_file, "\n"); 1293 } 1294 1295 if (gimple_code (def) == GIMPLE_NOP) 1296 { 1297 gsi = gsi_last_bb (chkp_get_entry_block ()); 1298 if (!gsi_end_p (gsi) && is_ctrl_stmt (gsi_stmt (gsi))) 1299 gsi_insert_before (&gsi, assign, GSI_CONTINUE_LINKING); 1300 else 1301 gsi_insert_after (&gsi, assign, GSI_CONTINUE_LINKING); 1302 } 1303 else 1304 { 1305 gimple *bnd_def = SSA_NAME_DEF_STMT (bnd); 1306 /* Sometimes (e.g. when we load a pointer from a 1307 memory) bounds are produced later than a pointer. 1308 We need to insert bounds copy appropriately. */ 1309 if (gimple_code (bnd_def) != GIMPLE_NOP 1310 && stmt_dominates_stmt_p (def, bnd_def)) 1311 gsi = gsi_for_stmt (bnd_def); 1312 else 1313 gsi = gsi_for_stmt (def); 1314 gsi_insert_after (&gsi, assign, GSI_CONTINUE_LINKING); 1315 } 1316 1317 bnd = copy; 1318 } 1319 1320 if (abnormal_ptr) 1321 bitmap_set_bit (chkp_abnormal_copies, SSA_NAME_VERSION (bnd)); 1322 } 1323 1324 chkp_reg_bounds->put (ptr, bnd); 1325 1326 if (dump_file && (dump_flags & TDF_DETAILS)) 1327 { 1328 fprintf (dump_file, "Regsitered bound "); 1329 print_generic_expr (dump_file, bnd); 1330 fprintf (dump_file, " for pointer "); 1331 print_generic_expr (dump_file, ptr); 1332 fprintf (dump_file, "\n"); 1333 } 1334 1335 return bnd; 1336 } 1337 1338 /* Get bounds registered for object PTR in global bounds table. */ 1339 static tree 1340 chkp_get_registered_bounds (tree ptr) 1341 { 1342 tree *slot; 1343 1344 if (!chkp_reg_bounds) 1345 return NULL_TREE; 1346 1347 slot = chkp_reg_bounds->get (ptr); 1348 return slot ? *slot : NULL_TREE; 1349 } 1350 1351 /* Add bound retvals to return statement pointed by GSI. */ 1352 1353 static void 1354 chkp_add_bounds_to_ret_stmt (gimple_stmt_iterator *gsi) 1355 { 1356 greturn *ret = as_a <greturn *> (gsi_stmt (*gsi)); 1357 tree retval = gimple_return_retval (ret); 1358 tree ret_decl = DECL_RESULT (cfun->decl); 1359 tree bounds; 1360 1361 if (!retval) 1362 return; 1363 1364 if (BOUNDED_P (ret_decl)) 1365 { 1366 bounds = chkp_find_bounds (retval, gsi); 1367 bounds = chkp_maybe_copy_and_register_bounds (ret_decl, bounds); 1368 gimple_return_set_retbnd (ret, bounds); 1369 } 1370 1371 update_stmt (ret); 1372 } 1373 1374 /* Force OP to be suitable for using as an argument for call. 1375 New statements (if any) go to SEQ. */ 1376 static tree 1377 chkp_force_gimple_call_op (tree op, gimple_seq *seq) 1378 { 1379 gimple_seq stmts; 1380 gimple_stmt_iterator si; 1381 1382 op = force_gimple_operand (unshare_expr (op), &stmts, true, NULL_TREE); 1383 1384 for (si = gsi_start (stmts); !gsi_end_p (si); gsi_next (&si)) 1385 chkp_mark_stmt (gsi_stmt (si)); 1386 1387 gimple_seq_add_seq (seq, stmts); 1388 1389 return op; 1390 } 1391 1392 /* Generate lower bound check for memory access by ADDR. 1393 Check is inserted before the position pointed by ITER. 1394 DIRFLAG indicates whether memory access is load or store. */ 1395 static void 1396 chkp_check_lower (tree addr, tree bounds, 1397 gimple_stmt_iterator iter, 1398 location_t location, 1399 tree dirflag) 1400 { 1401 gimple_seq seq; 1402 gimple *check; 1403 tree node; 1404 1405 if (!chkp_function_instrumented_p (current_function_decl) 1406 && bounds == chkp_get_zero_bounds ()) 1407 return; 1408 1409 if (dirflag == integer_zero_node 1410 && !flag_chkp_check_read) 1411 return; 1412 1413 if (dirflag == integer_one_node 1414 && !flag_chkp_check_write) 1415 return; 1416 1417 seq = NULL; 1418 1419 node = chkp_force_gimple_call_op (addr, &seq); 1420 1421 check = gimple_build_call (chkp_checkl_fndecl, 2, node, bounds); 1422 chkp_mark_stmt (check); 1423 gimple_call_set_with_bounds (check, true); 1424 gimple_set_location (check, location); 1425 gimple_seq_add_stmt (&seq, check); 1426 1427 gsi_insert_seq_before (&iter, seq, GSI_SAME_STMT); 1428 1429 if (dump_file && (dump_flags & TDF_DETAILS)) 1430 { 1431 gimple *before = gsi_stmt (iter); 1432 fprintf (dump_file, "Generated lower bound check for statement "); 1433 print_gimple_stmt (dump_file, before, 0, TDF_VOPS|TDF_MEMSYMS); 1434 fprintf (dump_file, " "); 1435 print_gimple_stmt (dump_file, check, 0, TDF_VOPS|TDF_MEMSYMS); 1436 } 1437 } 1438 1439 /* Generate upper bound check for memory access by ADDR. 1440 Check is inserted before the position pointed by ITER. 1441 DIRFLAG indicates whether memory access is load or store. */ 1442 static void 1443 chkp_check_upper (tree addr, tree bounds, 1444 gimple_stmt_iterator iter, 1445 location_t location, 1446 tree dirflag) 1447 { 1448 gimple_seq seq; 1449 gimple *check; 1450 tree node; 1451 1452 if (!chkp_function_instrumented_p (current_function_decl) 1453 && bounds == chkp_get_zero_bounds ()) 1454 return; 1455 1456 if (dirflag == integer_zero_node 1457 && !flag_chkp_check_read) 1458 return; 1459 1460 if (dirflag == integer_one_node 1461 && !flag_chkp_check_write) 1462 return; 1463 1464 seq = NULL; 1465 1466 node = chkp_force_gimple_call_op (addr, &seq); 1467 1468 check = gimple_build_call (chkp_checku_fndecl, 2, node, bounds); 1469 chkp_mark_stmt (check); 1470 gimple_call_set_with_bounds (check, true); 1471 gimple_set_location (check, location); 1472 gimple_seq_add_stmt (&seq, check); 1473 1474 gsi_insert_seq_before (&iter, seq, GSI_SAME_STMT); 1475 1476 if (dump_file && (dump_flags & TDF_DETAILS)) 1477 { 1478 gimple *before = gsi_stmt (iter); 1479 fprintf (dump_file, "Generated upper bound check for statement "); 1480 print_gimple_stmt (dump_file, before, 0, TDF_VOPS|TDF_MEMSYMS); 1481 fprintf (dump_file, " "); 1482 print_gimple_stmt (dump_file, check, 0, TDF_VOPS|TDF_MEMSYMS); 1483 } 1484 } 1485 1486 /* Generate lower and upper bound checks for memory access 1487 to memory slot [FIRST, LAST] againsr BOUNDS. Checks 1488 are inserted before the position pointed by ITER. 1489 DIRFLAG indicates whether memory access is load or store. */ 1490 void 1491 chkp_check_mem_access (tree first, tree last, tree bounds, 1492 gimple_stmt_iterator iter, 1493 location_t location, 1494 tree dirflag) 1495 { 1496 chkp_check_lower (first, bounds, iter, location, dirflag); 1497 chkp_check_upper (last, bounds, iter, location, dirflag); 1498 } 1499 1500 /* Replace call to _bnd_chk_* pointed by GSI with 1501 bndcu and bndcl calls. DIRFLAG determines whether 1502 check is for read or write. */ 1503 1504 void 1505 chkp_replace_address_check_builtin (gimple_stmt_iterator *gsi, 1506 tree dirflag) 1507 { 1508 gimple_stmt_iterator call_iter = *gsi; 1509 gimple *call = gsi_stmt (*gsi); 1510 tree fndecl = gimple_call_fndecl (call); 1511 tree addr = gimple_call_arg (call, 0); 1512 tree bounds = chkp_find_bounds (addr, gsi); 1513 1514 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_LBOUNDS 1515 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_BOUNDS) 1516 chkp_check_lower (addr, bounds, *gsi, gimple_location (call), dirflag); 1517 1518 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_UBOUNDS) 1519 chkp_check_upper (addr, bounds, *gsi, gimple_location (call), dirflag); 1520 1521 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_BOUNDS) 1522 { 1523 tree size = gimple_call_arg (call, 1); 1524 addr = fold_build_pointer_plus (addr, size); 1525 addr = fold_build_pointer_plus_hwi (addr, -1); 1526 chkp_check_upper (addr, bounds, *gsi, gimple_location (call), dirflag); 1527 } 1528 1529 gsi_remove (&call_iter, true); 1530 } 1531 1532 /* Replace call to _bnd_get_ptr_* pointed by GSI with 1533 corresponding bounds extract call. */ 1534 1535 void 1536 chkp_replace_extract_builtin (gimple_stmt_iterator *gsi) 1537 { 1538 gimple *call = gsi_stmt (*gsi); 1539 tree fndecl = gimple_call_fndecl (call); 1540 tree addr = gimple_call_arg (call, 0); 1541 tree bounds = chkp_find_bounds (addr, gsi); 1542 gimple *extract; 1543 1544 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_GET_PTR_LBOUND) 1545 fndecl = chkp_extract_lower_fndecl; 1546 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_GET_PTR_UBOUND) 1547 fndecl = chkp_extract_upper_fndecl; 1548 else 1549 gcc_unreachable (); 1550 1551 extract = gimple_build_call (fndecl, 1, bounds); 1552 gimple_call_set_lhs (extract, gimple_call_lhs (call)); 1553 chkp_mark_stmt (extract); 1554 1555 gsi_replace (gsi, extract, false); 1556 } 1557 1558 /* Return COMPONENT_REF accessing FIELD in OBJ. */ 1559 static tree 1560 chkp_build_component_ref (tree obj, tree field) 1561 { 1562 tree res; 1563 1564 /* If object is TMR then we do not use component_ref but 1565 add offset instead. We need it to be able to get addr 1566 of the reasult later. */ 1567 if (TREE_CODE (obj) == TARGET_MEM_REF) 1568 { 1569 tree offs = TMR_OFFSET (obj); 1570 offs = fold_binary_to_constant (PLUS_EXPR, TREE_TYPE (offs), 1571 offs, DECL_FIELD_OFFSET (field)); 1572 1573 gcc_assert (offs); 1574 1575 res = copy_node (obj); 1576 TREE_TYPE (res) = TREE_TYPE (field); 1577 TMR_OFFSET (res) = offs; 1578 } 1579 else 1580 res = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL_TREE); 1581 1582 return res; 1583 } 1584 1585 /* Return ARRAY_REF for array ARR and index IDX with 1586 specified element type ETYPE and element size ESIZE. */ 1587 static tree 1588 chkp_build_array_ref (tree arr, tree etype, tree esize, 1589 unsigned HOST_WIDE_INT idx) 1590 { 1591 tree index = build_int_cst (size_type_node, idx); 1592 tree res; 1593 1594 /* If object is TMR then we do not use array_ref but 1595 add offset instead. We need it to be able to get addr 1596 of the reasult later. */ 1597 if (TREE_CODE (arr) == TARGET_MEM_REF) 1598 { 1599 tree offs = TMR_OFFSET (arr); 1600 1601 esize = fold_binary_to_constant (MULT_EXPR, TREE_TYPE (esize), 1602 esize, index); 1603 gcc_assert(esize); 1604 1605 offs = fold_binary_to_constant (PLUS_EXPR, TREE_TYPE (offs), 1606 offs, esize); 1607 gcc_assert (offs); 1608 1609 res = copy_node (arr); 1610 TREE_TYPE (res) = etype; 1611 TMR_OFFSET (res) = offs; 1612 } 1613 else 1614 res = build4 (ARRAY_REF, etype, arr, index, NULL_TREE, NULL_TREE); 1615 1616 return res; 1617 } 1618 1619 /* Helper function for chkp_add_bounds_to_call_stmt. 1620 Fill ALL_BOUNDS output array with created bounds. 1621 1622 OFFS is used for recursive calls and holds basic 1623 offset of TYPE in outer structure in bits. 1624 1625 ITER points a position where bounds are searched. 1626 1627 ALL_BOUNDS[i] is filled with elem bounds if there 1628 is a field in TYPE which has pointer type and offset 1629 equal to i * POINTER_SIZE in bits. */ 1630 static void 1631 chkp_find_bounds_for_elem (tree elem, tree *all_bounds, 1632 HOST_WIDE_INT offs, 1633 gimple_stmt_iterator *iter) 1634 { 1635 tree type = TREE_TYPE (elem); 1636 1637 if (BOUNDED_TYPE_P (type)) 1638 { 1639 if (!all_bounds[offs / POINTER_SIZE]) 1640 { 1641 tree temp = make_temp_ssa_name (type, NULL, ""); 1642 gimple *assign = gimple_build_assign (temp, elem); 1643 gimple_stmt_iterator gsi; 1644 1645 gsi_insert_before (iter, assign, GSI_SAME_STMT); 1646 gsi = gsi_for_stmt (assign); 1647 1648 all_bounds[offs / POINTER_SIZE] = chkp_find_bounds (temp, &gsi); 1649 } 1650 } 1651 else if (RECORD_OR_UNION_TYPE_P (type)) 1652 { 1653 tree field; 1654 1655 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) 1656 if (TREE_CODE (field) == FIELD_DECL) 1657 { 1658 tree base = unshare_expr (elem); 1659 tree field_ref = chkp_build_component_ref (base, field); 1660 HOST_WIDE_INT field_offs 1661 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)); 1662 if (DECL_FIELD_OFFSET (field)) 1663 field_offs += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field)) * 8; 1664 1665 chkp_find_bounds_for_elem (field_ref, all_bounds, 1666 offs + field_offs, iter); 1667 } 1668 } 1669 else if (TREE_CODE (type) == ARRAY_TYPE) 1670 { 1671 tree maxval = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); 1672 tree etype = TREE_TYPE (type); 1673 HOST_WIDE_INT esize = TREE_INT_CST_LOW (TYPE_SIZE (etype)); 1674 unsigned HOST_WIDE_INT cur; 1675 1676 if (!maxval || integer_minus_onep (maxval)) 1677 return; 1678 1679 for (cur = 0; cur <= TREE_INT_CST_LOW (maxval); cur++) 1680 { 1681 tree base = unshare_expr (elem); 1682 tree arr_elem = chkp_build_array_ref (base, etype, 1683 TYPE_SIZE (etype), 1684 cur); 1685 chkp_find_bounds_for_elem (arr_elem, all_bounds, offs + cur * esize, 1686 iter); 1687 } 1688 } 1689 } 1690 1691 /* Maximum number of elements to check in an array. */ 1692 1693 #define CHKP_ARRAY_MAX_CHECK_STEPS 4096 1694 1695 /* Fill HAVE_BOUND output bitmap with information about 1696 bounds requred for object of type TYPE. 1697 1698 OFFS is used for recursive calls and holds basic 1699 offset of TYPE in outer structure in bits. 1700 1701 HAVE_BOUND[i] is set to 1 if there is a field 1702 in TYPE which has pointer type and offset 1703 equal to i * POINTER_SIZE - OFFS in bits. */ 1704 void 1705 chkp_find_bound_slots_1 (const_tree type, bitmap have_bound, 1706 HOST_WIDE_INT offs) 1707 { 1708 if (BOUNDED_TYPE_P (type)) 1709 bitmap_set_bit (have_bound, offs / POINTER_SIZE); 1710 else if (RECORD_OR_UNION_TYPE_P (type)) 1711 { 1712 tree field; 1713 1714 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) 1715 if (TREE_CODE (field) == FIELD_DECL) 1716 { 1717 HOST_WIDE_INT field_offs = 0; 1718 if (DECL_FIELD_BIT_OFFSET (field)) 1719 field_offs += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)); 1720 if (DECL_FIELD_OFFSET (field)) 1721 field_offs += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field)) * 8; 1722 chkp_find_bound_slots_1 (TREE_TYPE (field), have_bound, 1723 offs + field_offs); 1724 } 1725 } 1726 else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)) 1727 { 1728 /* The object type is an array of complete type, i.e., other 1729 than a flexible array. */ 1730 tree maxval = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); 1731 tree etype = TREE_TYPE (type); 1732 HOST_WIDE_INT esize = TREE_INT_CST_LOW (TYPE_SIZE (etype)); 1733 unsigned HOST_WIDE_INT cur; 1734 1735 if (!maxval 1736 || TREE_CODE (maxval) != INTEGER_CST 1737 || integer_minus_onep (maxval)) 1738 return; 1739 1740 for (cur = 0; 1741 cur <= MIN (CHKP_ARRAY_MAX_CHECK_STEPS, TREE_INT_CST_LOW (maxval)); 1742 cur++) 1743 chkp_find_bound_slots_1 (etype, have_bound, offs + cur * esize); 1744 } 1745 } 1746 1747 /* Fill bitmap RES with information about bounds for 1748 type TYPE. See chkp_find_bound_slots_1 for more 1749 details. */ 1750 void 1751 chkp_find_bound_slots (const_tree type, bitmap res) 1752 { 1753 bitmap_clear (res); 1754 chkp_find_bound_slots_1 (type, res, 0); 1755 } 1756 1757 /* Return 1 if call to FNDECL should be instrumented 1758 and 0 otherwise. */ 1759 1760 static bool 1761 chkp_instrument_normal_builtin (tree fndecl) 1762 { 1763 switch (DECL_FUNCTION_CODE (fndecl)) 1764 { 1765 case BUILT_IN_STRLEN: 1766 case BUILT_IN_STRCPY: 1767 case BUILT_IN_STRNCPY: 1768 case BUILT_IN_STPCPY: 1769 case BUILT_IN_STPNCPY: 1770 case BUILT_IN_STRCAT: 1771 case BUILT_IN_STRNCAT: 1772 case BUILT_IN_MEMCPY: 1773 case BUILT_IN_MEMPCPY: 1774 case BUILT_IN_MEMSET: 1775 case BUILT_IN_MEMMOVE: 1776 case BUILT_IN_BZERO: 1777 case BUILT_IN_STRCMP: 1778 case BUILT_IN_STRNCMP: 1779 case BUILT_IN_BCMP: 1780 case BUILT_IN_MEMCMP: 1781 case BUILT_IN_MEMCPY_CHK: 1782 case BUILT_IN_MEMPCPY_CHK: 1783 case BUILT_IN_MEMMOVE_CHK: 1784 case BUILT_IN_MEMSET_CHK: 1785 case BUILT_IN_STRCPY_CHK: 1786 case BUILT_IN_STRNCPY_CHK: 1787 case BUILT_IN_STPCPY_CHK: 1788 case BUILT_IN_STPNCPY_CHK: 1789 case BUILT_IN_STRCAT_CHK: 1790 case BUILT_IN_STRNCAT_CHK: 1791 case BUILT_IN_MALLOC: 1792 case BUILT_IN_CALLOC: 1793 case BUILT_IN_REALLOC: 1794 return 1; 1795 1796 default: 1797 return 0; 1798 } 1799 } 1800 1801 /* Add bound arguments to call statement pointed by GSI. 1802 Also performs a replacement of user checker builtins calls 1803 with internal ones. */ 1804 1805 static void 1806 chkp_add_bounds_to_call_stmt (gimple_stmt_iterator *gsi) 1807 { 1808 gcall *call = as_a <gcall *> (gsi_stmt (*gsi)); 1809 unsigned arg_no = 0; 1810 tree fndecl = gimple_call_fndecl (call); 1811 tree fntype; 1812 tree first_formal_arg; 1813 tree arg; 1814 bool use_fntype = false; 1815 tree op; 1816 ssa_op_iter iter; 1817 gcall *new_call; 1818 1819 /* Do nothing for internal functions. */ 1820 if (gimple_call_internal_p (call)) 1821 return; 1822 1823 fntype = TREE_TYPE (TREE_TYPE (gimple_call_fn (call))); 1824 1825 /* Do nothing if back-end builtin is called. */ 1826 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) 1827 return; 1828 1829 /* Do nothing for some middle-end builtins. */ 1830 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 1831 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_OBJECT_SIZE) 1832 return; 1833 1834 /* Do nothing for calls to not instrumentable functions. */ 1835 if (fndecl && !chkp_instrumentable_p (fndecl)) 1836 return; 1837 1838 /* Ignore CHKP_INIT_PTR_BOUNDS, CHKP_NULL_PTR_BOUNDS 1839 and CHKP_COPY_PTR_BOUNDS. */ 1840 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 1841 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_INIT_PTR_BOUNDS 1842 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_NULL_PTR_BOUNDS 1843 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_COPY_PTR_BOUNDS 1844 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_SET_PTR_BOUNDS)) 1845 return; 1846 1847 /* Check user builtins are replaced with checks. */ 1848 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 1849 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_LBOUNDS 1850 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_UBOUNDS 1851 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_BOUNDS)) 1852 { 1853 chkp_replace_address_check_builtin (gsi, integer_minus_one_node); 1854 return; 1855 } 1856 1857 /* Check user builtins are replaced with bound extract. */ 1858 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 1859 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_GET_PTR_LBOUND 1860 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_GET_PTR_UBOUND)) 1861 { 1862 chkp_replace_extract_builtin (gsi); 1863 return; 1864 } 1865 1866 /* BUILT_IN_CHKP_NARROW_PTR_BOUNDS call is replaced with 1867 target narrow bounds call. */ 1868 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 1869 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_NARROW_PTR_BOUNDS) 1870 { 1871 tree arg = gimple_call_arg (call, 1); 1872 tree bounds = chkp_find_bounds (arg, gsi); 1873 1874 gimple_call_set_fndecl (call, chkp_narrow_bounds_fndecl); 1875 gimple_call_set_arg (call, 1, bounds); 1876 update_stmt (call); 1877 1878 return; 1879 } 1880 1881 /* BUILT_IN_CHKP_STORE_PTR_BOUNDS call is replaced with 1882 bndstx call. */ 1883 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 1884 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_STORE_PTR_BOUNDS) 1885 { 1886 tree addr = gimple_call_arg (call, 0); 1887 tree ptr = gimple_call_arg (call, 1); 1888 tree bounds = chkp_find_bounds (ptr, gsi); 1889 gimple_stmt_iterator iter = gsi_for_stmt (call); 1890 1891 chkp_build_bndstx (addr, ptr, bounds, gsi); 1892 gsi_remove (&iter, true); 1893 1894 return; 1895 } 1896 1897 if (!flag_chkp_instrument_calls) 1898 return; 1899 1900 /* We instrument only some subset of builtins. We also instrument 1901 builtin calls to be inlined. */ 1902 if (fndecl 1903 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 1904 && !chkp_instrument_normal_builtin (fndecl)) 1905 { 1906 if (!lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl))) 1907 return; 1908 1909 struct cgraph_node *clone = chkp_maybe_create_clone (fndecl); 1910 if (!clone 1911 || !gimple_has_body_p (clone->decl)) 1912 return; 1913 } 1914 1915 /* If function decl is available then use it for 1916 formal arguments list. Otherwise use function type. */ 1917 if (fndecl 1918 && DECL_ARGUMENTS (fndecl) 1919 && gimple_call_fntype (call) == TREE_TYPE (fndecl)) 1920 first_formal_arg = DECL_ARGUMENTS (fndecl); 1921 else 1922 { 1923 first_formal_arg = TYPE_ARG_TYPES (fntype); 1924 use_fntype = true; 1925 } 1926 1927 /* Fill vector of new call args. */ 1928 vec<tree> new_args = vNULL; 1929 new_args.create (gimple_call_num_args (call)); 1930 arg = first_formal_arg; 1931 for (arg_no = 0; arg_no < gimple_call_num_args (call); arg_no++) 1932 { 1933 tree call_arg = gimple_call_arg (call, arg_no); 1934 tree type; 1935 1936 /* Get arg type using formal argument description 1937 or actual argument type. */ 1938 if (arg) 1939 if (use_fntype) 1940 if (TREE_VALUE (arg) != void_type_node) 1941 { 1942 type = TREE_VALUE (arg); 1943 arg = TREE_CHAIN (arg); 1944 } 1945 else 1946 type = TREE_TYPE (call_arg); 1947 else 1948 { 1949 type = TREE_TYPE (arg); 1950 arg = TREE_CHAIN (arg); 1951 } 1952 else 1953 type = TREE_TYPE (call_arg); 1954 1955 new_args.safe_push (call_arg); 1956 1957 if (BOUNDED_TYPE_P (type) 1958 || pass_by_reference (NULL, TYPE_MODE (type), type, true)) 1959 new_args.safe_push (chkp_find_bounds (call_arg, gsi)); 1960 else if (chkp_type_has_pointer (type)) 1961 { 1962 HOST_WIDE_INT max_bounds 1963 = TREE_INT_CST_LOW (TYPE_SIZE (type)) / POINTER_SIZE; 1964 tree *all_bounds = (tree *)xmalloc (sizeof (tree) * max_bounds); 1965 HOST_WIDE_INT bnd_no; 1966 1967 memset (all_bounds, 0, sizeof (tree) * max_bounds); 1968 1969 chkp_find_bounds_for_elem (call_arg, all_bounds, 0, gsi); 1970 1971 for (bnd_no = 0; bnd_no < max_bounds; bnd_no++) 1972 if (all_bounds[bnd_no]) 1973 new_args.safe_push (all_bounds[bnd_no]); 1974 1975 free (all_bounds); 1976 } 1977 } 1978 1979 if (new_args.length () == gimple_call_num_args (call)) 1980 new_call = call; 1981 else 1982 { 1983 new_call = gimple_build_call_vec (gimple_op (call, 1), new_args); 1984 gimple_call_set_lhs (new_call, gimple_call_lhs (call)); 1985 gimple_call_copy_flags (new_call, call); 1986 gimple_call_set_chain (new_call, gimple_call_chain (call)); 1987 } 1988 new_args.release (); 1989 1990 /* For direct calls fndecl is replaced with instrumented version. */ 1991 if (fndecl) 1992 { 1993 tree new_decl = chkp_maybe_create_clone (fndecl)->decl; 1994 gimple_call_set_fndecl (new_call, new_decl); 1995 /* In case of a type cast we should modify used function 1996 type instead of using type of new fndecl. */ 1997 if (gimple_call_fntype (call) != TREE_TYPE (fndecl)) 1998 { 1999 tree type = gimple_call_fntype (call); 2000 type = chkp_copy_function_type_adding_bounds (type); 2001 gimple_call_set_fntype (new_call, type); 2002 } 2003 else 2004 gimple_call_set_fntype (new_call, TREE_TYPE (new_decl)); 2005 } 2006 /* For indirect call we should fix function pointer type if 2007 pass some bounds. */ 2008 else if (new_call != call) 2009 { 2010 tree type = gimple_call_fntype (call); 2011 type = chkp_copy_function_type_adding_bounds (type); 2012 gimple_call_set_fntype (new_call, type); 2013 } 2014 2015 /* replace old call statement with the new one. */ 2016 if (call != new_call) 2017 { 2018 FOR_EACH_SSA_TREE_OPERAND (op, call, iter, SSA_OP_ALL_DEFS) 2019 { 2020 SSA_NAME_DEF_STMT (op) = new_call; 2021 } 2022 gsi_replace (gsi, new_call, true); 2023 } 2024 else 2025 update_stmt (new_call); 2026 2027 gimple_call_set_with_bounds (new_call, true); 2028 } 2029 2030 /* Return constant static bounds var with specified bounds LB and UB. 2031 If such var does not exists then new var is created with specified NAME. */ 2032 static tree 2033 chkp_make_static_const_bounds (HOST_WIDE_INT lb, 2034 HOST_WIDE_INT ub, 2035 const char *name) 2036 { 2037 tree id = get_identifier (name); 2038 tree var; 2039 varpool_node *node; 2040 symtab_node *snode; 2041 2042 var = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, 2043 pointer_bounds_type_node); 2044 TREE_STATIC (var) = 1; 2045 TREE_PUBLIC (var) = 1; 2046 2047 /* With LTO we may have constant bounds already in varpool. 2048 Try to find it. */ 2049 if ((snode = symtab_node::get_for_asmname (DECL_ASSEMBLER_NAME (var)))) 2050 { 2051 /* We don't allow this symbol usage for non bounds. */ 2052 if (snode->type != SYMTAB_VARIABLE 2053 || !POINTER_BOUNDS_P (snode->decl)) 2054 sorry ("-fcheck-pointer-bounds requires %qs " 2055 "name for internal usage", 2056 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (var))); 2057 2058 return snode->decl; 2059 } 2060 2061 TREE_USED (var) = 1; 2062 TREE_READONLY (var) = 1; 2063 TREE_ADDRESSABLE (var) = 0; 2064 DECL_ARTIFICIAL (var) = 1; 2065 DECL_READ_P (var) = 1; 2066 DECL_INITIAL (var) = targetm.chkp_make_bounds_constant (lb, ub); 2067 make_decl_one_only (var, DECL_ASSEMBLER_NAME (var)); 2068 /* We may use this symbol during ctors generation in chkp_finish_file 2069 when all symbols are emitted. Force output to avoid undefined 2070 symbols in ctors. */ 2071 node = varpool_node::get_create (var); 2072 node->force_output = 1; 2073 2074 varpool_node::finalize_decl (var); 2075 2076 return var; 2077 } 2078 2079 /* Generate code to make bounds with specified lower bound LB and SIZE. 2080 if AFTER is 1 then code is inserted after position pointed by ITER 2081 otherwise code is inserted before position pointed by ITER. 2082 If ITER is NULL then code is added to entry block. */ 2083 static tree 2084 chkp_make_bounds (tree lb, tree size, gimple_stmt_iterator *iter, bool after) 2085 { 2086 gimple_seq seq; 2087 gimple_stmt_iterator gsi; 2088 gimple *stmt; 2089 tree bounds; 2090 2091 if (iter) 2092 gsi = *iter; 2093 else 2094 gsi = gsi_start_bb (chkp_get_entry_block ()); 2095 2096 seq = NULL; 2097 2098 lb = chkp_force_gimple_call_op (lb, &seq); 2099 size = chkp_force_gimple_call_op (size, &seq); 2100 2101 stmt = gimple_build_call (chkp_bndmk_fndecl, 2, lb, size); 2102 chkp_mark_stmt (stmt); 2103 2104 bounds = chkp_get_tmp_reg (stmt); 2105 gimple_call_set_lhs (stmt, bounds); 2106 2107 gimple_seq_add_stmt (&seq, stmt); 2108 2109 if (iter && after) 2110 gsi_insert_seq_after (&gsi, seq, GSI_SAME_STMT); 2111 else 2112 gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT); 2113 2114 if (dump_file && (dump_flags & TDF_DETAILS)) 2115 { 2116 fprintf (dump_file, "Made bounds: "); 2117 print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS); 2118 if (iter) 2119 { 2120 fprintf (dump_file, " inserted before statement: "); 2121 print_gimple_stmt (dump_file, gsi_stmt (*iter), 0, TDF_VOPS|TDF_MEMSYMS); 2122 } 2123 else 2124 fprintf (dump_file, " at function entry\n"); 2125 } 2126 2127 /* update_stmt (stmt); */ 2128 2129 return bounds; 2130 } 2131 2132 /* Return var holding zero bounds. */ 2133 tree 2134 chkp_get_zero_bounds_var (void) 2135 { 2136 if (!chkp_zero_bounds_var) 2137 chkp_zero_bounds_var 2138 = chkp_make_static_const_bounds (0, -1, 2139 CHKP_ZERO_BOUNDS_VAR_NAME); 2140 return chkp_zero_bounds_var; 2141 } 2142 2143 /* Return var holding none bounds. */ 2144 tree 2145 chkp_get_none_bounds_var (void) 2146 { 2147 if (!chkp_none_bounds_var) 2148 chkp_none_bounds_var 2149 = chkp_make_static_const_bounds (-1, 0, 2150 CHKP_NONE_BOUNDS_VAR_NAME); 2151 return chkp_none_bounds_var; 2152 } 2153 2154 /* Return SSA_NAME used to represent zero bounds. */ 2155 static tree 2156 chkp_get_zero_bounds (void) 2157 { 2158 if (zero_bounds) 2159 return zero_bounds; 2160 2161 if (dump_file && (dump_flags & TDF_DETAILS)) 2162 fprintf (dump_file, "Creating zero bounds..."); 2163 2164 if ((flag_chkp_use_static_bounds && flag_chkp_use_static_const_bounds) 2165 || flag_chkp_use_static_const_bounds > 0) 2166 { 2167 gimple_stmt_iterator gsi = gsi_start_bb (chkp_get_entry_block ()); 2168 gimple *stmt; 2169 2170 zero_bounds = chkp_get_tmp_reg (NULL); 2171 stmt = gimple_build_assign (zero_bounds, chkp_get_zero_bounds_var ()); 2172 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); 2173 } 2174 else 2175 zero_bounds = chkp_make_bounds (integer_zero_node, 2176 integer_zero_node, 2177 NULL, 2178 false); 2179 2180 return zero_bounds; 2181 } 2182 2183 /* Return SSA_NAME used to represent none bounds. */ 2184 static tree 2185 chkp_get_none_bounds (void) 2186 { 2187 if (none_bounds) 2188 return none_bounds; 2189 2190 if (dump_file && (dump_flags & TDF_DETAILS)) 2191 fprintf (dump_file, "Creating none bounds..."); 2192 2193 2194 if ((flag_chkp_use_static_bounds && flag_chkp_use_static_const_bounds) 2195 || flag_chkp_use_static_const_bounds > 0) 2196 { 2197 gimple_stmt_iterator gsi = gsi_start_bb (chkp_get_entry_block ()); 2198 gimple *stmt; 2199 2200 none_bounds = chkp_get_tmp_reg (NULL); 2201 stmt = gimple_build_assign (none_bounds, chkp_get_none_bounds_var ()); 2202 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); 2203 } 2204 else 2205 none_bounds = chkp_make_bounds (integer_minus_one_node, 2206 build_int_cst (size_type_node, 2), 2207 NULL, 2208 false); 2209 2210 return none_bounds; 2211 } 2212 2213 /* Return bounds to be used as a result of operation which 2214 should not create poiunter (e.g. MULT_EXPR). */ 2215 static tree 2216 chkp_get_invalid_op_bounds (void) 2217 { 2218 return chkp_get_zero_bounds (); 2219 } 2220 2221 /* Return bounds to be used for loads of non-pointer values. */ 2222 static tree 2223 chkp_get_nonpointer_load_bounds (void) 2224 { 2225 return chkp_get_zero_bounds (); 2226 } 2227 2228 /* Return 1 if may use bndret call to get bounds for pointer 2229 returned by CALL. */ 2230 static bool 2231 chkp_call_returns_bounds_p (gcall *call) 2232 { 2233 if (gimple_call_internal_p (call)) 2234 { 2235 if (gimple_call_internal_fn (call) == IFN_VA_ARG) 2236 return true; 2237 return false; 2238 } 2239 2240 if (gimple_call_builtin_p (call, BUILT_IN_CHKP_NARROW_PTR_BOUNDS) 2241 || chkp_gimple_call_builtin_p (call, BUILT_IN_CHKP_NARROW)) 2242 return true; 2243 2244 if (gimple_call_with_bounds_p (call)) 2245 return true; 2246 2247 tree fndecl = gimple_call_fndecl (call); 2248 2249 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) 2250 return false; 2251 2252 if (fndecl && !chkp_instrumentable_p (fndecl)) 2253 return false; 2254 2255 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) 2256 { 2257 if (chkp_instrument_normal_builtin (fndecl)) 2258 return true; 2259 2260 if (!lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl))) 2261 return false; 2262 2263 struct cgraph_node *clone = chkp_maybe_create_clone (fndecl); 2264 return (clone && gimple_has_body_p (clone->decl)); 2265 } 2266 2267 return true; 2268 } 2269 2270 /* Build bounds returned by CALL. */ 2271 static tree 2272 chkp_build_returned_bound (gcall *call) 2273 { 2274 gimple_stmt_iterator gsi; 2275 tree bounds; 2276 gimple *stmt; 2277 tree fndecl = gimple_call_fndecl (call); 2278 unsigned int retflags; 2279 tree lhs = gimple_call_lhs (call); 2280 2281 /* To avoid fixing alloca expands in targets we handle 2282 it separately. */ 2283 if (fndecl 2284 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 2285 && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (fndecl))) 2286 { 2287 tree size = gimple_call_arg (call, 0); 2288 gimple_stmt_iterator iter = gsi_for_stmt (call); 2289 bounds = chkp_make_bounds (lhs, size, &iter, true); 2290 } 2291 /* We know bounds returned by set_bounds builtin call. */ 2292 else if (fndecl 2293 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 2294 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_SET_PTR_BOUNDS) 2295 { 2296 tree lb = gimple_call_arg (call, 0); 2297 tree size = gimple_call_arg (call, 1); 2298 gimple_stmt_iterator iter = gsi_for_stmt (call); 2299 bounds = chkp_make_bounds (lb, size, &iter, true); 2300 } 2301 /* Detect bounds initialization calls. */ 2302 else if (fndecl 2303 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 2304 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_INIT_PTR_BOUNDS) 2305 bounds = chkp_get_zero_bounds (); 2306 /* Detect bounds nullification calls. */ 2307 else if (fndecl 2308 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 2309 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_NULL_PTR_BOUNDS) 2310 bounds = chkp_get_none_bounds (); 2311 /* Detect bounds copy calls. */ 2312 else if (fndecl 2313 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 2314 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_COPY_PTR_BOUNDS) 2315 { 2316 gimple_stmt_iterator iter = gsi_for_stmt (call); 2317 bounds = chkp_find_bounds (gimple_call_arg (call, 1), &iter); 2318 } 2319 /* Do not use retbnd when returned bounds are equal to some 2320 of passed bounds. */ 2321 else if (((retflags = gimple_call_return_flags (call)) & ERF_RETURNS_ARG) 2322 && (retflags & ERF_RETURN_ARG_MASK) < gimple_call_num_args (call)) 2323 { 2324 gimple_stmt_iterator iter = gsi_for_stmt (call); 2325 unsigned int retarg = retflags & ERF_RETURN_ARG_MASK, argno; 2326 if (gimple_call_with_bounds_p (call)) 2327 { 2328 for (argno = 0; argno < gimple_call_num_args (call); argno++) 2329 if (!POINTER_BOUNDS_P (gimple_call_arg (call, argno))) 2330 { 2331 if (retarg) 2332 retarg--; 2333 else 2334 break; 2335 } 2336 } 2337 else 2338 argno = retarg; 2339 2340 bounds = chkp_find_bounds (gimple_call_arg (call, argno), &iter); 2341 } 2342 else if (chkp_call_returns_bounds_p (call) 2343 && BOUNDED_P (lhs)) 2344 { 2345 gcc_assert (TREE_CODE (lhs) == SSA_NAME); 2346 2347 /* In general case build checker builtin call to 2348 obtain returned bounds. */ 2349 stmt = gimple_build_call (chkp_ret_bnd_fndecl, 1, 2350 gimple_call_lhs (call)); 2351 chkp_mark_stmt (stmt); 2352 2353 gsi = gsi_for_stmt (call); 2354 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT); 2355 2356 bounds = chkp_get_tmp_reg (stmt); 2357 gimple_call_set_lhs (stmt, bounds); 2358 2359 update_stmt (stmt); 2360 } 2361 else 2362 bounds = chkp_get_zero_bounds (); 2363 2364 if (dump_file && (dump_flags & TDF_DETAILS)) 2365 { 2366 fprintf (dump_file, "Built returned bounds ("); 2367 print_generic_expr (dump_file, bounds); 2368 fprintf (dump_file, ") for call: "); 2369 print_gimple_stmt (dump_file, call, 0, TDF_VOPS | TDF_MEMSYMS); 2370 } 2371 2372 bounds = chkp_maybe_copy_and_register_bounds (lhs, bounds); 2373 2374 return bounds; 2375 } 2376 2377 /* Return bounds used as returned by call 2378 which produced SSA name VAL. */ 2379 gcall * 2380 chkp_retbnd_call_by_val (tree val) 2381 { 2382 if (TREE_CODE (val) != SSA_NAME) 2383 return NULL; 2384 2385 gcc_assert (gimple_code (SSA_NAME_DEF_STMT (val)) == GIMPLE_CALL); 2386 2387 imm_use_iterator use_iter; 2388 use_operand_p use_p; 2389 FOR_EACH_IMM_USE_FAST (use_p, use_iter, val) 2390 if (chkp_gimple_call_builtin_p (USE_STMT (use_p), BUILT_IN_CHKP_BNDRET)) 2391 return as_a <gcall *> (USE_STMT (use_p)); 2392 2393 return NULL; 2394 } 2395 2396 /* Check the next parameter for the given PARM is bounds 2397 and return it's default SSA_NAME (create if required). */ 2398 static tree 2399 chkp_get_next_bounds_parm (tree parm) 2400 { 2401 tree bounds = TREE_CHAIN (parm); 2402 gcc_assert (POINTER_BOUNDS_P (bounds)); 2403 bounds = ssa_default_def (cfun, bounds); 2404 if (!bounds) 2405 { 2406 bounds = make_ssa_name (TREE_CHAIN (parm), gimple_build_nop ()); 2407 set_ssa_default_def (cfun, TREE_CHAIN (parm), bounds); 2408 } 2409 return bounds; 2410 } 2411 2412 /* Return bounds to be used for input argument PARM. */ 2413 static tree 2414 chkp_get_bound_for_parm (tree parm) 2415 { 2416 tree decl = SSA_NAME_VAR (parm); 2417 tree bounds; 2418 2419 gcc_assert (TREE_CODE (decl) == PARM_DECL); 2420 2421 bounds = chkp_get_registered_bounds (parm); 2422 2423 if (!bounds) 2424 bounds = chkp_get_registered_bounds (decl); 2425 2426 if (!bounds) 2427 { 2428 tree orig_decl = cgraph_node::get (cfun->decl)->orig_decl; 2429 2430 /* For static chain param we return zero bounds 2431 because currently we do not check dereferences 2432 of this pointer. */ 2433 if (cfun->static_chain_decl == decl) 2434 bounds = chkp_get_zero_bounds (); 2435 /* If non instrumented runtime is used then it may be useful 2436 to use zero bounds for input arguments of main 2437 function. */ 2438 else if (flag_chkp_zero_input_bounds_for_main 2439 && id_equal (DECL_ASSEMBLER_NAME (orig_decl), "main")) 2440 bounds = chkp_get_zero_bounds (); 2441 else if (BOUNDED_P (parm)) 2442 { 2443 bounds = chkp_get_next_bounds_parm (decl); 2444 bounds = chkp_maybe_copy_and_register_bounds (decl, bounds); 2445 2446 if (dump_file && (dump_flags & TDF_DETAILS)) 2447 { 2448 fprintf (dump_file, "Built arg bounds ("); 2449 print_generic_expr (dump_file, bounds); 2450 fprintf (dump_file, ") for arg: "); 2451 print_node (dump_file, "", decl, 0); 2452 } 2453 } 2454 else 2455 bounds = chkp_get_zero_bounds (); 2456 } 2457 2458 if (!chkp_get_registered_bounds (parm)) 2459 bounds = chkp_maybe_copy_and_register_bounds (parm, bounds); 2460 2461 if (dump_file && (dump_flags & TDF_DETAILS)) 2462 { 2463 fprintf (dump_file, "Using bounds "); 2464 print_generic_expr (dump_file, bounds); 2465 fprintf (dump_file, " for parm "); 2466 print_generic_expr (dump_file, parm); 2467 fprintf (dump_file, " of type "); 2468 print_generic_expr (dump_file, TREE_TYPE (parm)); 2469 fprintf (dump_file, ".\n"); 2470 } 2471 2472 return bounds; 2473 } 2474 2475 /* Build and return CALL_EXPR for bndstx builtin with specified 2476 arguments. */ 2477 tree 2478 chkp_build_bndldx_call (tree addr, tree ptr) 2479 { 2480 tree fn = build1 (ADDR_EXPR, 2481 build_pointer_type (TREE_TYPE (chkp_bndldx_fndecl)), 2482 chkp_bndldx_fndecl); 2483 tree call = build_call_nary (TREE_TYPE (TREE_TYPE (chkp_bndldx_fndecl)), 2484 fn, 2, addr, ptr); 2485 CALL_WITH_BOUNDS_P (call) = true; 2486 return call; 2487 } 2488 2489 /* Insert code to load bounds for PTR located by ADDR. 2490 Code is inserted after position pointed by GSI. 2491 Loaded bounds are returned. */ 2492 static tree 2493 chkp_build_bndldx (tree addr, tree ptr, gimple_stmt_iterator *gsi) 2494 { 2495 gimple_seq seq; 2496 gimple *stmt; 2497 tree bounds; 2498 2499 seq = NULL; 2500 2501 addr = chkp_force_gimple_call_op (addr, &seq); 2502 ptr = chkp_force_gimple_call_op (ptr, &seq); 2503 2504 stmt = gimple_build_call (chkp_bndldx_fndecl, 2, addr, ptr); 2505 chkp_mark_stmt (stmt); 2506 bounds = chkp_get_tmp_reg (stmt); 2507 gimple_call_set_lhs (stmt, bounds); 2508 2509 gimple_seq_add_stmt (&seq, stmt); 2510 2511 gsi_insert_seq_after (gsi, seq, GSI_CONTINUE_LINKING); 2512 2513 if (dump_file && (dump_flags & TDF_DETAILS)) 2514 { 2515 fprintf (dump_file, "Generated bndldx for pointer "); 2516 print_generic_expr (dump_file, ptr); 2517 fprintf (dump_file, ": "); 2518 print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS | TDF_MEMSYMS); 2519 } 2520 2521 return bounds; 2522 } 2523 2524 /* Build and return CALL_EXPR for bndstx builtin with specified 2525 arguments. */ 2526 tree 2527 chkp_build_bndstx_call (tree addr, tree ptr, tree bounds) 2528 { 2529 tree fn = build1 (ADDR_EXPR, 2530 build_pointer_type (TREE_TYPE (chkp_bndstx_fndecl)), 2531 chkp_bndstx_fndecl); 2532 tree call = build_call_nary (TREE_TYPE (TREE_TYPE (chkp_bndstx_fndecl)), 2533 fn, 3, ptr, bounds, addr); 2534 CALL_WITH_BOUNDS_P (call) = true; 2535 return call; 2536 } 2537 2538 /* Insert code to store BOUNDS for PTR stored by ADDR. 2539 New statements are inserted after position pointed 2540 by GSI. */ 2541 void 2542 chkp_build_bndstx (tree addr, tree ptr, tree bounds, 2543 gimple_stmt_iterator *gsi) 2544 { 2545 gimple_seq seq; 2546 gimple *stmt; 2547 2548 seq = NULL; 2549 2550 addr = chkp_force_gimple_call_op (addr, &seq); 2551 ptr = chkp_force_gimple_call_op (ptr, &seq); 2552 2553 stmt = gimple_build_call (chkp_bndstx_fndecl, 3, ptr, bounds, addr); 2554 chkp_mark_stmt (stmt); 2555 gimple_call_set_with_bounds (stmt, true); 2556 2557 gimple_seq_add_stmt (&seq, stmt); 2558 2559 gsi_insert_seq_after (gsi, seq, GSI_CONTINUE_LINKING); 2560 2561 if (dump_file && (dump_flags & TDF_DETAILS)) 2562 { 2563 fprintf (dump_file, "Generated bndstx for pointer store "); 2564 print_gimple_stmt (dump_file, gsi_stmt (*gsi), 0, TDF_VOPS|TDF_MEMSYMS); 2565 print_gimple_stmt (dump_file, stmt, 2, TDF_VOPS|TDF_MEMSYMS); 2566 } 2567 } 2568 2569 /* This function is called when call statement 2570 is inlined and therefore we can't use bndret 2571 for its LHS anymore. Function fixes bndret 2572 call using new RHS value if possible. */ 2573 void 2574 chkp_fixup_inlined_call (tree lhs, tree rhs) 2575 { 2576 tree addr, bounds; 2577 gcall *retbnd, *bndldx; 2578 2579 if (!BOUNDED_P (lhs)) 2580 return; 2581 2582 /* Search for retbnd call. */ 2583 retbnd = chkp_retbnd_call_by_val (lhs); 2584 if (!retbnd) 2585 return; 2586 2587 /* Currently only handle cases when call is replaced 2588 with a memory access. In this case bndret call 2589 may be replaced with bndldx call. Otherwise we 2590 have to search for bounds which may cause wrong 2591 result due to various optimizations applied. */ 2592 switch (TREE_CODE (rhs)) 2593 { 2594 case VAR_DECL: 2595 if (DECL_REGISTER (rhs)) 2596 return; 2597 break; 2598 2599 case MEM_REF: 2600 break; 2601 2602 case ARRAY_REF: 2603 case COMPONENT_REF: 2604 addr = get_base_address (rhs); 2605 if (!DECL_P (addr) 2606 && TREE_CODE (addr) != MEM_REF) 2607 return; 2608 if (DECL_P (addr) && DECL_REGISTER (addr)) 2609 return; 2610 break; 2611 2612 default: 2613 return; 2614 } 2615 2616 /* Create a new statements sequence with bndldx call. */ 2617 gimple_stmt_iterator gsi = gsi_for_stmt (retbnd); 2618 addr = build_fold_addr_expr (rhs); 2619 chkp_build_bndldx (addr, lhs, &gsi); 2620 bndldx = as_a <gcall *> (gsi_stmt (gsi)); 2621 2622 /* Remove bndret call. */ 2623 bounds = gimple_call_lhs (retbnd); 2624 gsi = gsi_for_stmt (retbnd); 2625 gsi_remove (&gsi, true); 2626 2627 /* Link new bndldx call. */ 2628 gimple_call_set_lhs (bndldx, bounds); 2629 update_stmt (bndldx); 2630 } 2631 2632 /* Compute bounds for pointer NODE which was assigned in 2633 assignment statement ASSIGN. Return computed bounds. */ 2634 static tree 2635 chkp_compute_bounds_for_assignment (tree node, gimple *assign) 2636 { 2637 enum tree_code rhs_code = gimple_assign_rhs_code (assign); 2638 tree rhs1 = gimple_assign_rhs1 (assign); 2639 tree bounds = NULL_TREE; 2640 gimple_stmt_iterator iter = gsi_for_stmt (assign); 2641 tree base = NULL; 2642 2643 if (dump_file && (dump_flags & TDF_DETAILS)) 2644 { 2645 fprintf (dump_file, "Computing bounds for assignment: "); 2646 print_gimple_stmt (dump_file, assign, 0, TDF_VOPS|TDF_MEMSYMS); 2647 } 2648 2649 switch (rhs_code) 2650 { 2651 case MEM_REF: 2652 case TARGET_MEM_REF: 2653 case COMPONENT_REF: 2654 case ARRAY_REF: 2655 /* We need to load bounds from the bounds table. */ 2656 bounds = chkp_find_bounds_loaded (node, rhs1, &iter); 2657 break; 2658 2659 case VAR_DECL: 2660 case SSA_NAME: 2661 case ADDR_EXPR: 2662 case POINTER_PLUS_EXPR: 2663 case NOP_EXPR: 2664 case CONVERT_EXPR: 2665 case INTEGER_CST: 2666 /* Bounds are just propagated from RHS. */ 2667 bounds = chkp_find_bounds (rhs1, &iter); 2668 base = rhs1; 2669 break; 2670 2671 case VIEW_CONVERT_EXPR: 2672 /* Bounds are just propagated from RHS. */ 2673 bounds = chkp_find_bounds (TREE_OPERAND (rhs1, 0), &iter); 2674 break; 2675 2676 case PARM_DECL: 2677 if (BOUNDED_P (rhs1)) 2678 { 2679 /* We need to load bounds from the bounds table. */ 2680 bounds = chkp_build_bndldx (chkp_build_addr_expr (rhs1), 2681 node, &iter); 2682 TREE_ADDRESSABLE (rhs1) = 1; 2683 } 2684 else 2685 bounds = chkp_get_nonpointer_load_bounds (); 2686 break; 2687 2688 case MINUS_EXPR: 2689 case PLUS_EXPR: 2690 case BIT_AND_EXPR: 2691 case BIT_IOR_EXPR: 2692 case BIT_XOR_EXPR: 2693 { 2694 tree rhs2 = gimple_assign_rhs2 (assign); 2695 tree bnd1 = chkp_find_bounds (rhs1, &iter); 2696 tree bnd2 = chkp_find_bounds (rhs2, &iter); 2697 2698 /* First we try to check types of operands. If it 2699 does not help then look at bound values. 2700 2701 If some bounds are incomplete and other are 2702 not proven to be valid (i.e. also incomplete 2703 or invalid because value is not pointer) then 2704 resulting value is incomplete and will be 2705 recomputed later in chkp_finish_incomplete_bounds. */ 2706 if (BOUNDED_P (rhs1) 2707 && !BOUNDED_P (rhs2)) 2708 bounds = bnd1; 2709 else if (BOUNDED_P (rhs2) 2710 && !BOUNDED_P (rhs1) 2711 && rhs_code != MINUS_EXPR) 2712 bounds = bnd2; 2713 else if (chkp_incomplete_bounds (bnd1)) 2714 if (chkp_valid_bounds (bnd2) && rhs_code != MINUS_EXPR 2715 && !chkp_incomplete_bounds (bnd2)) 2716 bounds = bnd2; 2717 else 2718 bounds = incomplete_bounds; 2719 else if (chkp_incomplete_bounds (bnd2)) 2720 if (chkp_valid_bounds (bnd1) 2721 && !chkp_incomplete_bounds (bnd1)) 2722 bounds = bnd1; 2723 else 2724 bounds = incomplete_bounds; 2725 else if (!chkp_valid_bounds (bnd1)) 2726 if (chkp_valid_bounds (bnd2) && rhs_code != MINUS_EXPR) 2727 bounds = bnd2; 2728 else if (bnd2 == chkp_get_zero_bounds ()) 2729 bounds = bnd2; 2730 else 2731 bounds = bnd1; 2732 else if (!chkp_valid_bounds (bnd2)) 2733 bounds = bnd1; 2734 else 2735 /* Seems both operands may have valid bounds 2736 (e.g. pointer minus pointer). In such case 2737 use default invalid op bounds. */ 2738 bounds = chkp_get_invalid_op_bounds (); 2739 2740 base = (bounds == bnd1) ? rhs1 : (bounds == bnd2) ? rhs2 : NULL; 2741 } 2742 break; 2743 2744 case BIT_NOT_EXPR: 2745 case NEGATE_EXPR: 2746 case LSHIFT_EXPR: 2747 case RSHIFT_EXPR: 2748 case LROTATE_EXPR: 2749 case RROTATE_EXPR: 2750 case EQ_EXPR: 2751 case NE_EXPR: 2752 case LT_EXPR: 2753 case LE_EXPR: 2754 case GT_EXPR: 2755 case GE_EXPR: 2756 case MULT_EXPR: 2757 case RDIV_EXPR: 2758 case TRUNC_DIV_EXPR: 2759 case FLOOR_DIV_EXPR: 2760 case CEIL_DIV_EXPR: 2761 case ROUND_DIV_EXPR: 2762 case TRUNC_MOD_EXPR: 2763 case FLOOR_MOD_EXPR: 2764 case CEIL_MOD_EXPR: 2765 case ROUND_MOD_EXPR: 2766 case EXACT_DIV_EXPR: 2767 case FIX_TRUNC_EXPR: 2768 case FLOAT_EXPR: 2769 case REALPART_EXPR: 2770 case IMAGPART_EXPR: 2771 case POINTER_DIFF_EXPR: 2772 /* No valid bounds may be produced by these exprs. */ 2773 bounds = chkp_get_invalid_op_bounds (); 2774 break; 2775 2776 case COND_EXPR: 2777 { 2778 tree val1 = gimple_assign_rhs2 (assign); 2779 tree val2 = gimple_assign_rhs3 (assign); 2780 tree bnd1 = chkp_find_bounds (val1, &iter); 2781 tree bnd2 = chkp_find_bounds (val2, &iter); 2782 gimple *stmt; 2783 2784 if (chkp_incomplete_bounds (bnd1) || chkp_incomplete_bounds (bnd2)) 2785 bounds = incomplete_bounds; 2786 else if (bnd1 == bnd2) 2787 bounds = bnd1; 2788 else 2789 { 2790 rhs1 = unshare_expr (rhs1); 2791 2792 bounds = chkp_get_tmp_reg (assign); 2793 stmt = gimple_build_assign (bounds, COND_EXPR, rhs1, bnd1, bnd2); 2794 gsi_insert_after (&iter, stmt, GSI_SAME_STMT); 2795 2796 if (!chkp_valid_bounds (bnd1) && !chkp_valid_bounds (bnd2)) 2797 chkp_mark_invalid_bounds (bounds); 2798 } 2799 } 2800 break; 2801 2802 case MAX_EXPR: 2803 case MIN_EXPR: 2804 { 2805 tree rhs2 = gimple_assign_rhs2 (assign); 2806 tree bnd1 = chkp_find_bounds (rhs1, &iter); 2807 tree bnd2 = chkp_find_bounds (rhs2, &iter); 2808 2809 if (chkp_incomplete_bounds (bnd1) || chkp_incomplete_bounds (bnd2)) 2810 bounds = incomplete_bounds; 2811 else if (bnd1 == bnd2) 2812 bounds = bnd1; 2813 else 2814 { 2815 gimple *stmt; 2816 tree cond = build2 (rhs_code == MAX_EXPR ? GT_EXPR : LT_EXPR, 2817 boolean_type_node, rhs1, rhs2); 2818 bounds = chkp_get_tmp_reg (assign); 2819 stmt = gimple_build_assign (bounds, COND_EXPR, cond, bnd1, bnd2); 2820 2821 gsi_insert_after (&iter, stmt, GSI_SAME_STMT); 2822 2823 if (!chkp_valid_bounds (bnd1) && !chkp_valid_bounds (bnd2)) 2824 chkp_mark_invalid_bounds (bounds); 2825 } 2826 } 2827 break; 2828 2829 default: 2830 bounds = chkp_get_zero_bounds (); 2831 warning (0, "pointer bounds were lost due to unexpected expression %s", 2832 get_tree_code_name (rhs_code)); 2833 } 2834 2835 gcc_assert (bounds); 2836 2837 /* We may reuse bounds of other pointer we copy/modify. But it is not 2838 allowed for abnormal ssa names. If we produced a pointer using 2839 abnormal ssa name, we better make a bounds copy to avoid coalescing 2840 issues. */ 2841 if (base 2842 && TREE_CODE (base) == SSA_NAME 2843 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (base)) 2844 { 2845 gimple *stmt = gimple_build_assign (chkp_get_tmp_reg (NULL), bounds); 2846 gsi_insert_after (&iter, stmt, GSI_SAME_STMT); 2847 bounds = gimple_assign_lhs (stmt); 2848 } 2849 2850 if (node) 2851 bounds = chkp_maybe_copy_and_register_bounds (node, bounds); 2852 2853 return bounds; 2854 } 2855 2856 /* Compute bounds for ssa name NODE defined by DEF_STMT pointed by ITER. 2857 2858 There are just few statement codes allowed: NOP (for default ssa names), 2859 ASSIGN, CALL, PHI, ASM. 2860 2861 Return computed bounds. */ 2862 static tree 2863 chkp_get_bounds_by_definition (tree node, gimple *def_stmt, 2864 gphi_iterator *iter) 2865 { 2866 tree var, bounds; 2867 enum gimple_code code = gimple_code (def_stmt); 2868 gphi *stmt; 2869 2870 if (dump_file && (dump_flags & TDF_DETAILS)) 2871 { 2872 fprintf (dump_file, "Searching for bounds for node: "); 2873 print_generic_expr (dump_file, node); 2874 2875 fprintf (dump_file, " using its definition: "); 2876 print_gimple_stmt (dump_file, def_stmt, 0, TDF_VOPS | TDF_MEMSYMS); 2877 } 2878 2879 switch (code) 2880 { 2881 case GIMPLE_NOP: 2882 var = SSA_NAME_VAR (node); 2883 switch (TREE_CODE (var)) 2884 { 2885 case PARM_DECL: 2886 bounds = chkp_get_bound_for_parm (node); 2887 break; 2888 2889 case VAR_DECL: 2890 /* For uninitialized pointers use none bounds. */ 2891 bounds = chkp_get_none_bounds (); 2892 bounds = chkp_maybe_copy_and_register_bounds (node, bounds); 2893 break; 2894 2895 case RESULT_DECL: 2896 { 2897 tree base_type; 2898 2899 gcc_assert (TREE_CODE (TREE_TYPE (node)) == REFERENCE_TYPE); 2900 2901 base_type = TREE_TYPE (TREE_TYPE (node)); 2902 2903 gcc_assert (TYPE_SIZE (base_type) 2904 && TREE_CODE (TYPE_SIZE (base_type)) == INTEGER_CST 2905 && tree_to_uhwi (TYPE_SIZE (base_type)) != 0); 2906 2907 bounds = chkp_make_bounds (node, TYPE_SIZE_UNIT (base_type), 2908 NULL, false); 2909 bounds = chkp_maybe_copy_and_register_bounds (node, bounds); 2910 } 2911 break; 2912 2913 default: 2914 if (dump_file && (dump_flags & TDF_DETAILS)) 2915 { 2916 fprintf (dump_file, "Unexpected var with no definition\n"); 2917 print_generic_expr (dump_file, var); 2918 } 2919 internal_error ("chkp_get_bounds_by_definition: Unexpected var of type %s", 2920 get_tree_code_name (TREE_CODE (var))); 2921 } 2922 break; 2923 2924 case GIMPLE_ASSIGN: 2925 bounds = chkp_compute_bounds_for_assignment (node, def_stmt); 2926 break; 2927 2928 case GIMPLE_CALL: 2929 bounds = chkp_build_returned_bound (as_a <gcall *> (def_stmt)); 2930 break; 2931 2932 case GIMPLE_PHI: 2933 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (node)) 2934 if (SSA_NAME_VAR (node)) 2935 var = chkp_get_bounds_var (SSA_NAME_VAR (node)); 2936 else 2937 var = make_temp_ssa_name (pointer_bounds_type_node, 2938 NULL, 2939 CHKP_BOUND_TMP_NAME); 2940 else 2941 var = chkp_get_tmp_var (); 2942 stmt = create_phi_node (var, gimple_bb (def_stmt)); 2943 bounds = gimple_phi_result (stmt); 2944 *iter = gsi_for_phi (stmt); 2945 2946 bounds = chkp_maybe_copy_and_register_bounds (node, bounds); 2947 2948 /* Created bounds do not have all phi args computed and 2949 therefore we do not know if there is a valid source 2950 of bounds for that node. Therefore we mark bounds 2951 as incomplete and then recompute them when all phi 2952 args are computed. */ 2953 chkp_register_incomplete_bounds (bounds, node); 2954 break; 2955 2956 case GIMPLE_ASM: 2957 bounds = chkp_get_zero_bounds (); 2958 bounds = chkp_maybe_copy_and_register_bounds (node, bounds); 2959 break; 2960 2961 default: 2962 internal_error ("chkp_get_bounds_by_definition: Unexpected GIMPLE code %s", 2963 gimple_code_name[code]); 2964 } 2965 2966 return bounds; 2967 } 2968 2969 /* Return CALL_EXPR for bndmk with specified LOWER_BOUND and SIZE. */ 2970 tree 2971 chkp_build_make_bounds_call (tree lower_bound, tree size) 2972 { 2973 tree call = build1 (ADDR_EXPR, 2974 build_pointer_type (TREE_TYPE (chkp_bndmk_fndecl)), 2975 chkp_bndmk_fndecl); 2976 return build_call_nary (TREE_TYPE (TREE_TYPE (chkp_bndmk_fndecl)), 2977 call, 2, lower_bound, size); 2978 } 2979 2980 /* Create static bounds var of specfified OBJ which is 2981 is either VAR_DECL or string constant. */ 2982 static tree 2983 chkp_make_static_bounds (tree obj) 2984 { 2985 static int string_id = 1; 2986 static int var_id = 1; 2987 tree *slot; 2988 const char *var_name; 2989 char *bnd_var_name; 2990 tree bnd_var; 2991 2992 /* First check if we already have required var. */ 2993 if (chkp_static_var_bounds) 2994 { 2995 /* For vars we use assembler name as a key in 2996 chkp_static_var_bounds map. It allows to 2997 avoid duplicating bound vars for decls 2998 sharing assembler name. */ 2999 if (VAR_P (obj)) 3000 { 3001 tree name = DECL_ASSEMBLER_NAME (obj); 3002 slot = chkp_static_var_bounds->get (name); 3003 if (slot) 3004 return *slot; 3005 } 3006 else 3007 { 3008 slot = chkp_static_var_bounds->get (obj); 3009 if (slot) 3010 return *slot; 3011 } 3012 } 3013 3014 /* Build decl for bounds var. */ 3015 if (VAR_P (obj)) 3016 { 3017 if (DECL_IGNORED_P (obj)) 3018 { 3019 bnd_var_name = (char *) xmalloc (strlen (CHKP_VAR_BOUNDS_PREFIX) + 10); 3020 sprintf (bnd_var_name, "%s%d", CHKP_VAR_BOUNDS_PREFIX, var_id++); 3021 } 3022 else 3023 { 3024 var_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (obj)); 3025 3026 /* For hidden symbols we want to skip first '*' char. */ 3027 if (*var_name == '*') 3028 var_name++; 3029 3030 bnd_var_name = (char *) xmalloc (strlen (var_name) 3031 + strlen (CHKP_BOUNDS_OF_SYMBOL_PREFIX) + 1); 3032 strcpy (bnd_var_name, CHKP_BOUNDS_OF_SYMBOL_PREFIX); 3033 strcat (bnd_var_name, var_name); 3034 } 3035 3036 bnd_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, 3037 get_identifier (bnd_var_name), 3038 pointer_bounds_type_node); 3039 3040 /* Address of the obj will be used as lower bound. */ 3041 TREE_ADDRESSABLE (obj) = 1; 3042 } 3043 else 3044 { 3045 bnd_var_name = (char *) xmalloc (strlen (CHKP_STRING_BOUNDS_PREFIX) + 10); 3046 sprintf (bnd_var_name, "%s%d", CHKP_STRING_BOUNDS_PREFIX, string_id++); 3047 3048 bnd_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, 3049 get_identifier (bnd_var_name), 3050 pointer_bounds_type_node); 3051 } 3052 3053 free (bnd_var_name); 3054 3055 TREE_PUBLIC (bnd_var) = 0; 3056 TREE_USED (bnd_var) = 1; 3057 TREE_READONLY (bnd_var) = 0; 3058 TREE_STATIC (bnd_var) = 1; 3059 TREE_ADDRESSABLE (bnd_var) = 0; 3060 DECL_ARTIFICIAL (bnd_var) = 1; 3061 DECL_COMMON (bnd_var) = 1; 3062 DECL_COMDAT (bnd_var) = 1; 3063 DECL_READ_P (bnd_var) = 1; 3064 DECL_INITIAL (bnd_var) = chkp_build_addr_expr (obj); 3065 /* Force output similar to constant bounds. 3066 See chkp_make_static_const_bounds. */ 3067 varpool_node::get_create (bnd_var)->force_output = 1; 3068 /* Mark symbol as requiring bounds initialization. */ 3069 varpool_node::get_create (bnd_var)->need_bounds_init = 1; 3070 varpool_node::finalize_decl (bnd_var); 3071 3072 /* Add created var to the map to use it for other references 3073 to obj. */ 3074 if (!chkp_static_var_bounds) 3075 chkp_static_var_bounds = new hash_map<tree, tree>; 3076 3077 if (VAR_P (obj)) 3078 { 3079 tree name = DECL_ASSEMBLER_NAME (obj); 3080 chkp_static_var_bounds->put (name, bnd_var); 3081 } 3082 else 3083 chkp_static_var_bounds->put (obj, bnd_var); 3084 3085 return bnd_var; 3086 } 3087 3088 /* When var has incomplete type we cannot get size to 3089 compute its bounds. In such cases we use checker 3090 builtin call which determines object size at runtime. */ 3091 static tree 3092 chkp_generate_extern_var_bounds (tree var) 3093 { 3094 tree bounds, size_reloc, lb, size, max_size, cond; 3095 gimple_stmt_iterator gsi; 3096 gimple_seq seq = NULL; 3097 gimple *stmt; 3098 3099 /* If instrumentation is not enabled for vars having 3100 incomplete type then just return zero bounds to avoid 3101 checks for this var. */ 3102 if (!flag_chkp_incomplete_type) 3103 return chkp_get_zero_bounds (); 3104 3105 if (dump_file && (dump_flags & TDF_DETAILS)) 3106 { 3107 fprintf (dump_file, "Generating bounds for extern symbol '"); 3108 print_generic_expr (dump_file, var); 3109 fprintf (dump_file, "'\n"); 3110 } 3111 3112 stmt = gimple_build_call (chkp_sizeof_fndecl, 1, var); 3113 3114 size_reloc = create_tmp_reg (chkp_uintptr_type, CHKP_SIZE_TMP_NAME); 3115 gimple_call_set_lhs (stmt, size_reloc); 3116 3117 gimple_seq_add_stmt (&seq, stmt); 3118 3119 lb = chkp_build_addr_expr (var); 3120 size = make_ssa_name (chkp_get_size_tmp_var ()); 3121 3122 if (flag_chkp_zero_dynamic_size_as_infinite) 3123 { 3124 /* We should check that size relocation was resolved. 3125 If it was not then use maximum possible size for the var. */ 3126 max_size = build2 (MINUS_EXPR, chkp_uintptr_type, integer_zero_node, 3127 fold_convert (chkp_uintptr_type, lb)); 3128 max_size = chkp_force_gimple_call_op (max_size, &seq); 3129 3130 cond = build2 (NE_EXPR, boolean_type_node, 3131 size_reloc, integer_zero_node); 3132 stmt = gimple_build_assign (size, COND_EXPR, cond, size_reloc, max_size); 3133 gimple_seq_add_stmt (&seq, stmt); 3134 } 3135 else 3136 { 3137 stmt = gimple_build_assign (size, size_reloc); 3138 gimple_seq_add_stmt (&seq, stmt); 3139 } 3140 3141 gsi = gsi_start_bb (chkp_get_entry_block ()); 3142 gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); 3143 3144 bounds = chkp_make_bounds (lb, size, &gsi, true); 3145 3146 return bounds; 3147 } 3148 3149 /* Return 1 if TYPE has fields with zero size or fields 3150 marked with chkp_variable_size attribute. */ 3151 bool 3152 chkp_variable_size_type (tree type) 3153 { 3154 bool res = false; 3155 tree field; 3156 3157 if (RECORD_OR_UNION_TYPE_P (type)) 3158 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) 3159 { 3160 if (TREE_CODE (field) == FIELD_DECL) 3161 res = res 3162 || lookup_attribute ("bnd_variable_size", DECL_ATTRIBUTES (field)) 3163 || chkp_variable_size_type (TREE_TYPE (field)); 3164 } 3165 else 3166 res = !TYPE_SIZE (type) 3167 || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST 3168 || tree_to_uhwi (TYPE_SIZE (type)) == 0; 3169 3170 return res; 3171 } 3172 3173 /* Compute and return bounds for address of DECL which is 3174 one of VAR_DECL, PARM_DECL, RESULT_DECL. */ 3175 static tree 3176 chkp_get_bounds_for_decl_addr (tree decl) 3177 { 3178 tree bounds; 3179 3180 gcc_assert (VAR_P (decl) 3181 || TREE_CODE (decl) == PARM_DECL 3182 || TREE_CODE (decl) == RESULT_DECL); 3183 3184 bounds = chkp_get_registered_addr_bounds (decl); 3185 3186 if (bounds) 3187 return bounds; 3188 3189 if (dump_file && (dump_flags & TDF_DETAILS)) 3190 { 3191 fprintf (dump_file, "Building bounds for address of decl "); 3192 print_generic_expr (dump_file, decl); 3193 fprintf (dump_file, "\n"); 3194 } 3195 3196 /* Use zero bounds if size is unknown and checks for 3197 unknown sizes are restricted. */ 3198 if ((!DECL_SIZE (decl) 3199 || (chkp_variable_size_type (TREE_TYPE (decl)) 3200 && (TREE_STATIC (decl) 3201 || DECL_EXTERNAL (decl) 3202 || TREE_PUBLIC (decl)))) 3203 && !flag_chkp_incomplete_type) 3204 return chkp_get_zero_bounds (); 3205 3206 if (VOID_TYPE_P (TREE_TYPE (decl))) 3207 return chkp_get_zero_bounds (); 3208 3209 if (flag_chkp_use_static_bounds 3210 && VAR_P (decl) 3211 && (TREE_STATIC (decl) 3212 || DECL_EXTERNAL (decl) 3213 || TREE_PUBLIC (decl)) 3214 && !DECL_THREAD_LOCAL_P (decl)) 3215 { 3216 tree bnd_var = chkp_make_static_bounds (decl); 3217 gimple_stmt_iterator gsi = gsi_start_bb (chkp_get_entry_block ()); 3218 gimple *stmt; 3219 3220 bounds = chkp_get_tmp_reg (NULL); 3221 stmt = gimple_build_assign (bounds, bnd_var); 3222 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); 3223 } 3224 else if (!DECL_SIZE (decl) 3225 || (chkp_variable_size_type (TREE_TYPE (decl)) 3226 && (TREE_STATIC (decl) 3227 || DECL_EXTERNAL (decl) 3228 || TREE_PUBLIC (decl)))) 3229 { 3230 gcc_assert (VAR_P (decl)); 3231 bounds = chkp_generate_extern_var_bounds (decl); 3232 } 3233 else 3234 { 3235 tree lb = chkp_build_addr_expr (decl); 3236 bounds = chkp_make_bounds (lb, DECL_SIZE_UNIT (decl), NULL, false); 3237 } 3238 3239 return bounds; 3240 } 3241 3242 /* Compute and return bounds for constant string. */ 3243 static tree 3244 chkp_get_bounds_for_string_cst (tree cst) 3245 { 3246 tree bounds; 3247 tree lb; 3248 tree size; 3249 3250 gcc_assert (TREE_CODE (cst) == STRING_CST); 3251 3252 bounds = chkp_get_registered_bounds (cst); 3253 3254 if (bounds) 3255 return bounds; 3256 3257 if ((flag_chkp_use_static_bounds && flag_chkp_use_static_const_bounds) 3258 || flag_chkp_use_static_const_bounds > 0) 3259 { 3260 tree bnd_var = chkp_make_static_bounds (cst); 3261 gimple_stmt_iterator gsi = gsi_start_bb (chkp_get_entry_block ()); 3262 gimple *stmt; 3263 3264 bounds = chkp_get_tmp_reg (NULL); 3265 stmt = gimple_build_assign (bounds, bnd_var); 3266 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); 3267 } 3268 else 3269 { 3270 lb = chkp_build_addr_expr (cst); 3271 size = build_int_cst (chkp_uintptr_type, TREE_STRING_LENGTH (cst)); 3272 bounds = chkp_make_bounds (lb, size, NULL, false); 3273 } 3274 3275 bounds = chkp_maybe_copy_and_register_bounds (cst, bounds); 3276 3277 return bounds; 3278 } 3279 3280 /* Generate code to instersect bounds BOUNDS1 and BOUNDS2 and 3281 return the result. if ITER is not NULL then Code is inserted 3282 before position pointed by ITER. Otherwise code is added to 3283 entry block. */ 3284 static tree 3285 chkp_intersect_bounds (tree bounds1, tree bounds2, gimple_stmt_iterator *iter) 3286 { 3287 if (!bounds1 || bounds1 == chkp_get_zero_bounds ()) 3288 return bounds2 ? bounds2 : bounds1; 3289 else if (!bounds2 || bounds2 == chkp_get_zero_bounds ()) 3290 return bounds1; 3291 else 3292 { 3293 gimple_seq seq; 3294 gimple *stmt; 3295 tree bounds; 3296 3297 seq = NULL; 3298 3299 stmt = gimple_build_call (chkp_intersect_fndecl, 2, bounds1, bounds2); 3300 chkp_mark_stmt (stmt); 3301 3302 bounds = chkp_get_tmp_reg (stmt); 3303 gimple_call_set_lhs (stmt, bounds); 3304 3305 gimple_seq_add_stmt (&seq, stmt); 3306 3307 /* We are probably doing narrowing for constant expression. 3308 In such case iter may be undefined. */ 3309 if (!iter) 3310 { 3311 gimple_stmt_iterator gsi = gsi_last_bb (chkp_get_entry_block ()); 3312 iter = &gsi; 3313 gsi_insert_seq_after (iter, seq, GSI_SAME_STMT); 3314 } 3315 else 3316 gsi_insert_seq_before (iter, seq, GSI_SAME_STMT); 3317 3318 if (dump_file && (dump_flags & TDF_DETAILS)) 3319 { 3320 fprintf (dump_file, "Bounds intersection: "); 3321 print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS); 3322 fprintf (dump_file, " inserted before statement: "); 3323 print_gimple_stmt (dump_file, gsi_stmt (*iter), 0, 3324 TDF_VOPS|TDF_MEMSYMS); 3325 } 3326 3327 return bounds; 3328 } 3329 } 3330 3331 /* Return 1 if we are allowed to narrow bounds for addressed FIELD 3332 and 0 othersize. REF is reference to the field. */ 3333 3334 static bool 3335 chkp_may_narrow_to_field (tree ref, tree field) 3336 { 3337 return DECL_SIZE (field) && TREE_CODE (DECL_SIZE (field)) == INTEGER_CST 3338 && tree_to_uhwi (DECL_SIZE (field)) != 0 3339 && !(flag_chkp_flexible_struct_trailing_arrays 3340 && array_at_struct_end_p (ref)) 3341 && (!DECL_FIELD_OFFSET (field) 3342 || TREE_CODE (DECL_FIELD_OFFSET (field)) == INTEGER_CST) 3343 && (!DECL_FIELD_BIT_OFFSET (field) 3344 || TREE_CODE (DECL_FIELD_BIT_OFFSET (field)) == INTEGER_CST) 3345 && !lookup_attribute ("bnd_variable_size", DECL_ATTRIBUTES (field)) 3346 && !chkp_variable_size_type (TREE_TYPE (field)); 3347 } 3348 3349 /* Return 1 if bounds for FIELD should be narrowed to 3350 field's own size. REF is reference to the field. */ 3351 3352 static bool 3353 chkp_narrow_bounds_for_field (tree ref, tree field) 3354 { 3355 HOST_WIDE_INT offs; 3356 HOST_WIDE_INT bit_offs; 3357 3358 if (!chkp_may_narrow_to_field (ref, field)) 3359 return false; 3360 3361 /* Access to compiler generated fields should not cause 3362 bounds narrowing. */ 3363 if (DECL_ARTIFICIAL (field)) 3364 return false; 3365 3366 offs = tree_to_uhwi (DECL_FIELD_OFFSET (field)); 3367 bit_offs = tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)); 3368 3369 return (flag_chkp_narrow_bounds 3370 && (flag_chkp_first_field_has_own_bounds 3371 || offs 3372 || bit_offs)); 3373 } 3374 3375 /* Perform narrowing for BOUNDS of an INNER reference. Shift boundary 3376 by OFFSET bytes and limit to SIZE bytes. Newly created statements are 3377 added to ITER. */ 3378 3379 static tree 3380 chkp_narrow_size_and_offset (tree bounds, tree inner, tree offset, 3381 tree size, gimple_stmt_iterator *iter) 3382 { 3383 tree addr = chkp_build_addr_expr (unshare_expr (inner)); 3384 tree t = TREE_TYPE (addr); 3385 3386 gimple *stmt = gimple_build_assign (NULL_TREE, addr); 3387 addr = make_temp_ssa_name (t, stmt, CHKP_BOUND_TMP_NAME); 3388 gimple_assign_set_lhs (stmt, addr); 3389 gsi_insert_seq_before (iter, stmt, GSI_SAME_STMT); 3390 3391 stmt = gimple_build_assign (NULL_TREE, POINTER_PLUS_EXPR, addr, offset); 3392 tree shifted = make_temp_ssa_name (t, stmt, CHKP_BOUND_TMP_NAME); 3393 gimple_assign_set_lhs (stmt, shifted); 3394 gsi_insert_seq_before (iter, stmt, GSI_SAME_STMT); 3395 3396 tree bounds2 = chkp_make_bounds (shifted, size, iter, false); 3397 3398 return chkp_intersect_bounds (bounds, bounds2, iter); 3399 } 3400 3401 /* Perform narrowing for BOUNDS using bounds computed for field 3402 access COMPONENT. ITER meaning is the same as for 3403 chkp_intersect_bounds. */ 3404 3405 static tree 3406 chkp_narrow_bounds_to_field (tree bounds, tree component, 3407 gimple_stmt_iterator *iter) 3408 { 3409 tree field = TREE_OPERAND (component, 1); 3410 tree size = DECL_SIZE_UNIT (field); 3411 tree field_ptr = chkp_build_addr_expr (component); 3412 tree field_bounds; 3413 3414 field_bounds = chkp_make_bounds (field_ptr, size, iter, false); 3415 3416 return chkp_intersect_bounds (field_bounds, bounds, iter); 3417 } 3418 3419 /* Parse field or array access NODE. 3420 3421 PTR ouput parameter holds a pointer to the outermost 3422 object. 3423 3424 BITFIELD output parameter is set to 1 if bitfield is 3425 accessed and to 0 otherwise. If it is 1 then ELT holds 3426 outer component for accessed bit field. 3427 3428 SAFE outer parameter is set to 1 if access is safe and 3429 checks are not required. 3430 3431 BOUNDS outer parameter holds bounds to be used to check 3432 access (may be NULL). 3433 3434 If INNERMOST_BOUNDS is 1 then try to narrow bounds to the 3435 innermost accessed component. */ 3436 static void 3437 chkp_parse_array_and_component_ref (tree node, tree *ptr, 3438 tree *elt, bool *safe, 3439 bool *bitfield, 3440 tree *bounds, 3441 gimple_stmt_iterator *iter, 3442 bool innermost_bounds) 3443 { 3444 tree comp_to_narrow = NULL_TREE; 3445 tree last_comp = NULL_TREE; 3446 bool array_ref_found = false; 3447 tree *nodes; 3448 tree var; 3449 int len; 3450 int i; 3451 3452 /* Compute tree height for expression. */ 3453 var = node; 3454 len = 1; 3455 while (TREE_CODE (var) == COMPONENT_REF 3456 || TREE_CODE (var) == ARRAY_REF 3457 || TREE_CODE (var) == VIEW_CONVERT_EXPR 3458 || TREE_CODE (var) == BIT_FIELD_REF) 3459 { 3460 var = TREE_OPERAND (var, 0); 3461 len++; 3462 } 3463 3464 gcc_assert (len > 1); 3465 3466 /* It is more convenient for us to scan left-to-right, 3467 so walk tree again and put all node to nodes vector 3468 in reversed order. */ 3469 nodes = XALLOCAVEC (tree, len); 3470 nodes[len - 1] = node; 3471 for (i = len - 2; i >= 0; i--) 3472 nodes[i] = TREE_OPERAND (nodes[i + 1], 0); 3473 3474 if (bounds) 3475 *bounds = NULL; 3476 *safe = true; 3477 *bitfield = ((TREE_CODE (node) == COMPONENT_REF 3478 && DECL_BIT_FIELD_TYPE (TREE_OPERAND (node, 1))) 3479 || TREE_CODE (node) == BIT_FIELD_REF); 3480 /* To get bitfield address we will need outer element. */ 3481 if (*bitfield) 3482 *elt = nodes[len - 2]; 3483 else 3484 *elt = NULL_TREE; 3485 3486 /* If we have indirection in expression then compute 3487 outermost structure bounds. Computed bounds may be 3488 narrowed later. */ 3489 if (TREE_CODE (nodes[0]) == MEM_REF || INDIRECT_REF_P (nodes[0])) 3490 { 3491 *safe = false; 3492 *ptr = TREE_OPERAND (nodes[0], 0); 3493 if (bounds) 3494 *bounds = chkp_find_bounds (*ptr, iter); 3495 } 3496 else 3497 { 3498 gcc_assert (VAR_P (var) 3499 || TREE_CODE (var) == PARM_DECL 3500 || TREE_CODE (var) == RESULT_DECL 3501 || TREE_CODE (var) == STRING_CST 3502 || TREE_CODE (var) == SSA_NAME); 3503 3504 *ptr = chkp_build_addr_expr (var); 3505 3506 /* For hard register cases chkp_build_addr_expr returns INTEGER_CST 3507 and later on chkp_find_bounds will fail to find proper bounds. 3508 In order to avoid that, we find/create bounds right aways using 3509 the var itself. */ 3510 if (VAR_P (var) && DECL_HARD_REGISTER (var)) 3511 *bounds = chkp_make_addressed_object_bounds (var, iter); 3512 } 3513 3514 /* In this loop we are trying to find a field access 3515 requiring narrowing. There are two simple rules 3516 for search: 3517 1. Leftmost array_ref is chosen if any. 3518 2. Rightmost suitable component_ref is chosen if innermost 3519 bounds are required and no array_ref exists. */ 3520 for (i = 1; i < len; i++) 3521 { 3522 var = nodes[i]; 3523 3524 if (TREE_CODE (var) == ARRAY_REF) 3525 { 3526 *safe = false; 3527 array_ref_found = true; 3528 if (flag_chkp_narrow_bounds 3529 && !flag_chkp_narrow_to_innermost_arrray 3530 && (!last_comp 3531 || chkp_may_narrow_to_field (var, 3532 TREE_OPERAND (last_comp, 1)))) 3533 { 3534 comp_to_narrow = last_comp; 3535 break; 3536 } 3537 } 3538 else if (TREE_CODE (var) == COMPONENT_REF) 3539 { 3540 tree field = TREE_OPERAND (var, 1); 3541 3542 if (innermost_bounds 3543 && !array_ref_found 3544 && chkp_narrow_bounds_for_field (var, field)) 3545 comp_to_narrow = var; 3546 last_comp = var; 3547 3548 if (flag_chkp_narrow_bounds 3549 && flag_chkp_narrow_to_innermost_arrray 3550 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE) 3551 { 3552 if (bounds) 3553 *bounds = chkp_narrow_bounds_to_field (*bounds, var, iter); 3554 comp_to_narrow = NULL; 3555 } 3556 } 3557 else if (TREE_CODE (var) == BIT_FIELD_REF) 3558 { 3559 if (flag_chkp_narrow_bounds && bounds) 3560 { 3561 tree offset, size; 3562 chkp_parse_bit_field_ref (var, UNKNOWN_LOCATION, &offset, &size); 3563 *bounds 3564 = chkp_narrow_size_and_offset (*bounds, TREE_OPERAND (var, 0), 3565 offset, size, iter); 3566 } 3567 } 3568 else if (TREE_CODE (var) == VIEW_CONVERT_EXPR) 3569 /* Nothing to do for it. */ 3570 ; 3571 else 3572 gcc_unreachable (); 3573 } 3574 3575 if (comp_to_narrow && DECL_SIZE (TREE_OPERAND (comp_to_narrow, 1)) && bounds) 3576 *bounds = chkp_narrow_bounds_to_field (*bounds, comp_to_narrow, iter); 3577 3578 if (innermost_bounds && bounds && !*bounds) 3579 *bounds = chkp_find_bounds (*ptr, iter); 3580 } 3581 3582 /* Parse BIT_FIELD_REF to a NODE for a given location LOC. Return OFFSET 3583 and SIZE in bytes. */ 3584 3585 static 3586 void chkp_parse_bit_field_ref (tree node, location_t loc, tree *offset, 3587 tree *size) 3588 { 3589 tree bpu = fold_convert (size_type_node, bitsize_int (BITS_PER_UNIT)); 3590 tree offs = fold_convert (size_type_node, TREE_OPERAND (node, 2)); 3591 tree rem = size_binop_loc (loc, TRUNC_MOD_EXPR, offs, bpu); 3592 offs = size_binop_loc (loc, TRUNC_DIV_EXPR, offs, bpu); 3593 3594 tree s = fold_convert (size_type_node, TREE_OPERAND (node, 1)); 3595 s = size_binop_loc (loc, PLUS_EXPR, s, rem); 3596 s = size_binop_loc (loc, CEIL_DIV_EXPR, s, bpu); 3597 s = fold_convert (size_type_node, s); 3598 3599 *offset = offs; 3600 *size = s; 3601 } 3602 3603 /* Compute and return bounds for address of OBJ. */ 3604 static tree 3605 chkp_make_addressed_object_bounds (tree obj, gimple_stmt_iterator *iter) 3606 { 3607 tree bounds = chkp_get_registered_addr_bounds (obj); 3608 3609 if (bounds) 3610 return bounds; 3611 3612 switch (TREE_CODE (obj)) 3613 { 3614 case VAR_DECL: 3615 case PARM_DECL: 3616 case RESULT_DECL: 3617 bounds = chkp_get_bounds_for_decl_addr (obj); 3618 break; 3619 3620 case STRING_CST: 3621 bounds = chkp_get_bounds_for_string_cst (obj); 3622 break; 3623 3624 case ARRAY_REF: 3625 case COMPONENT_REF: 3626 case BIT_FIELD_REF: 3627 { 3628 tree elt; 3629 tree ptr; 3630 bool safe; 3631 bool bitfield; 3632 3633 chkp_parse_array_and_component_ref (obj, &ptr, &elt, &safe, 3634 &bitfield, &bounds, iter, true); 3635 3636 gcc_assert (bounds); 3637 } 3638 break; 3639 3640 case FUNCTION_DECL: 3641 case LABEL_DECL: 3642 bounds = chkp_get_zero_bounds (); 3643 break; 3644 3645 case MEM_REF: 3646 bounds = chkp_find_bounds (TREE_OPERAND (obj, 0), iter); 3647 break; 3648 3649 case REALPART_EXPR: 3650 case IMAGPART_EXPR: 3651 bounds = chkp_make_addressed_object_bounds (TREE_OPERAND (obj, 0), iter); 3652 break; 3653 3654 default: 3655 if (dump_file && (dump_flags & TDF_DETAILS)) 3656 { 3657 fprintf (dump_file, "chkp_make_addressed_object_bounds: " 3658 "unexpected object of type %s\n", 3659 get_tree_code_name (TREE_CODE (obj))); 3660 print_node (dump_file, "", obj, 0); 3661 } 3662 internal_error ("chkp_make_addressed_object_bounds: " 3663 "Unexpected tree code %s", 3664 get_tree_code_name (TREE_CODE (obj))); 3665 } 3666 3667 chkp_register_addr_bounds (obj, bounds); 3668 3669 return bounds; 3670 } 3671 3672 /* Compute bounds for pointer PTR loaded from PTR_SRC. Generate statements 3673 to compute bounds if required. Computed bounds should be available at 3674 position pointed by ITER. 3675 3676 If PTR_SRC is NULL_TREE then pointer definition is identified. 3677 3678 If PTR_SRC is not NULL_TREE then ITER points to statements which loads 3679 PTR. If PTR is a any memory reference then ITER points to a statement 3680 after which bndldx will be inserterd. In both cases ITER will be updated 3681 to point to the inserted bndldx statement. */ 3682 3683 static tree 3684 chkp_find_bounds_1 (tree ptr, tree ptr_src, gimple_stmt_iterator *iter) 3685 { 3686 tree addr = NULL_TREE; 3687 tree bounds = NULL_TREE; 3688 3689 if (!ptr_src) 3690 ptr_src = ptr; 3691 3692 bounds = chkp_get_registered_bounds (ptr_src); 3693 3694 if (bounds) 3695 return bounds; 3696 3697 switch (TREE_CODE (ptr_src)) 3698 { 3699 case MEM_REF: 3700 case VAR_DECL: 3701 if (BOUNDED_P (ptr_src)) 3702 if (VAR_P (ptr) && DECL_REGISTER (ptr)) 3703 bounds = chkp_get_zero_bounds (); 3704 else 3705 { 3706 addr = chkp_build_addr_expr (ptr_src); 3707 bounds = chkp_build_bndldx (addr, ptr, iter); 3708 } 3709 else 3710 bounds = chkp_get_nonpointer_load_bounds (); 3711 break; 3712 3713 case ARRAY_REF: 3714 case COMPONENT_REF: 3715 addr = get_base_address (ptr_src); 3716 if (VAR_P (addr) && DECL_HARD_REGISTER (addr)) 3717 { 3718 bounds = chkp_get_zero_bounds (); 3719 break; 3720 } 3721 if (DECL_P (addr) 3722 || TREE_CODE (addr) == MEM_REF 3723 || TREE_CODE (addr) == TARGET_MEM_REF) 3724 { 3725 if (BOUNDED_P (ptr_src)) 3726 if (VAR_P (ptr) && DECL_REGISTER (ptr)) 3727 bounds = chkp_get_zero_bounds (); 3728 else 3729 { 3730 addr = chkp_build_addr_expr (ptr_src); 3731 bounds = chkp_build_bndldx (addr, ptr, iter); 3732 } 3733 else 3734 bounds = chkp_get_nonpointer_load_bounds (); 3735 } 3736 else 3737 { 3738 gcc_assert (TREE_CODE (addr) == SSA_NAME); 3739 bounds = chkp_find_bounds (addr, iter); 3740 } 3741 break; 3742 3743 case PARM_DECL: 3744 /* Handled above but failed. */ 3745 bounds = chkp_get_invalid_op_bounds (); 3746 break; 3747 3748 case TARGET_MEM_REF: 3749 addr = chkp_build_addr_expr (ptr_src); 3750 bounds = chkp_build_bndldx (addr, ptr, iter); 3751 break; 3752 3753 case SSA_NAME: 3754 bounds = chkp_get_registered_bounds (ptr_src); 3755 if (!bounds) 3756 { 3757 gimple *def_stmt = SSA_NAME_DEF_STMT (ptr_src); 3758 gphi_iterator phi_iter; 3759 3760 bounds = chkp_get_bounds_by_definition (ptr_src, def_stmt, &phi_iter); 3761 3762 gcc_assert (bounds); 3763 3764 if (gphi *def_phi = dyn_cast <gphi *> (def_stmt)) 3765 { 3766 unsigned i; 3767 3768 for (i = 0; i < gimple_phi_num_args (def_phi); i++) 3769 { 3770 tree arg = gimple_phi_arg_def (def_phi, i); 3771 tree arg_bnd; 3772 gphi *phi_bnd; 3773 3774 arg_bnd = chkp_find_bounds (arg, NULL); 3775 3776 /* chkp_get_bounds_by_definition created new phi 3777 statement and phi_iter points to it. 3778 3779 Previous call to chkp_find_bounds could create 3780 new basic block and therefore change phi statement 3781 phi_iter points to. */ 3782 phi_bnd = phi_iter.phi (); 3783 3784 add_phi_arg (phi_bnd, arg_bnd, 3785 gimple_phi_arg_edge (def_phi, i), 3786 UNKNOWN_LOCATION); 3787 } 3788 3789 /* If all bound phi nodes have their arg computed 3790 then we may finish its computation. See 3791 chkp_finish_incomplete_bounds for more details. */ 3792 if (chkp_may_finish_incomplete_bounds ()) 3793 chkp_finish_incomplete_bounds (); 3794 } 3795 3796 gcc_assert (bounds == chkp_get_registered_bounds (ptr_src) 3797 || chkp_incomplete_bounds (bounds)); 3798 } 3799 break; 3800 3801 case ADDR_EXPR: 3802 case WITH_SIZE_EXPR: 3803 bounds = chkp_make_addressed_object_bounds (TREE_OPERAND (ptr_src, 0), iter); 3804 break; 3805 3806 case INTEGER_CST: 3807 case COMPLEX_CST: 3808 case VECTOR_CST: 3809 if (integer_zerop (ptr_src)) 3810 bounds = chkp_get_none_bounds (); 3811 else 3812 bounds = chkp_get_invalid_op_bounds (); 3813 break; 3814 3815 default: 3816 if (dump_file && (dump_flags & TDF_DETAILS)) 3817 { 3818 fprintf (dump_file, "chkp_find_bounds: unexpected ptr of type %s\n", 3819 get_tree_code_name (TREE_CODE (ptr_src))); 3820 print_node (dump_file, "", ptr_src, 0); 3821 } 3822 internal_error ("chkp_find_bounds: Unexpected tree code %s", 3823 get_tree_code_name (TREE_CODE (ptr_src))); 3824 } 3825 3826 if (!bounds) 3827 { 3828 if (dump_file && (dump_flags & TDF_DETAILS)) 3829 { 3830 fprintf (stderr, "chkp_find_bounds: cannot find bounds for pointer\n"); 3831 print_node (dump_file, "", ptr_src, 0); 3832 } 3833 internal_error ("chkp_find_bounds: Cannot find bounds for pointer"); 3834 } 3835 3836 return bounds; 3837 } 3838 3839 /* Normal case for bounds search without forced narrowing. */ 3840 static tree 3841 chkp_find_bounds (tree ptr, gimple_stmt_iterator *iter) 3842 { 3843 return chkp_find_bounds_1 (ptr, NULL_TREE, iter); 3844 } 3845 3846 /* Search bounds for pointer PTR loaded from PTR_SRC 3847 by statement *ITER points to. */ 3848 static tree 3849 chkp_find_bounds_loaded (tree ptr, tree ptr_src, gimple_stmt_iterator *iter) 3850 { 3851 return chkp_find_bounds_1 (ptr, ptr_src, iter); 3852 } 3853 3854 /* Helper function which checks type of RHS and finds all pointers in 3855 it. For each found pointer we build it's accesses in LHS and RHS 3856 objects and then call HANDLER for them. Function is used to copy 3857 or initilize bounds for copied object. */ 3858 static void 3859 chkp_walk_pointer_assignments (tree lhs, tree rhs, void *arg, 3860 assign_handler handler) 3861 { 3862 tree type = TREE_TYPE (lhs); 3863 3864 /* We have nothing to do with clobbers. */ 3865 if (TREE_CLOBBER_P (rhs)) 3866 return; 3867 3868 if (BOUNDED_TYPE_P (type)) 3869 handler (lhs, rhs, arg); 3870 else if (RECORD_OR_UNION_TYPE_P (type)) 3871 { 3872 tree field; 3873 3874 if (TREE_CODE (rhs) == CONSTRUCTOR) 3875 { 3876 unsigned HOST_WIDE_INT cnt; 3877 tree val; 3878 3879 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (rhs), cnt, field, val) 3880 { 3881 if (field && chkp_type_has_pointer (TREE_TYPE (field))) 3882 { 3883 tree lhs_field = chkp_build_component_ref (lhs, field); 3884 chkp_walk_pointer_assignments (lhs_field, val, arg, handler); 3885 } 3886 } 3887 } 3888 else 3889 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) 3890 if (TREE_CODE (field) == FIELD_DECL 3891 && chkp_type_has_pointer (TREE_TYPE (field))) 3892 { 3893 tree rhs_field = chkp_build_component_ref (rhs, field); 3894 tree lhs_field = chkp_build_component_ref (lhs, field); 3895 chkp_walk_pointer_assignments (lhs_field, rhs_field, arg, handler); 3896 } 3897 } 3898 else if (TREE_CODE (type) == ARRAY_TYPE) 3899 { 3900 unsigned HOST_WIDE_INT cur = 0; 3901 tree maxval = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); 3902 tree etype = TREE_TYPE (type); 3903 tree esize = TYPE_SIZE (etype); 3904 3905 if (TREE_CODE (rhs) == CONSTRUCTOR) 3906 { 3907 unsigned HOST_WIDE_INT cnt; 3908 tree purp, val, lhs_elem; 3909 3910 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (rhs), cnt, purp, val) 3911 { 3912 if (purp && TREE_CODE (purp) == RANGE_EXPR) 3913 { 3914 tree lo_index = TREE_OPERAND (purp, 0); 3915 tree hi_index = TREE_OPERAND (purp, 1); 3916 3917 for (cur = (unsigned)tree_to_uhwi (lo_index); 3918 cur <= (unsigned)tree_to_uhwi (hi_index); 3919 cur++) 3920 { 3921 lhs_elem = chkp_build_array_ref (lhs, etype, esize, cur); 3922 chkp_walk_pointer_assignments (lhs_elem, val, arg, handler); 3923 } 3924 } 3925 else 3926 { 3927 if (purp) 3928 { 3929 gcc_assert (TREE_CODE (purp) == INTEGER_CST); 3930 cur = tree_to_uhwi (purp); 3931 } 3932 3933 lhs_elem = chkp_build_array_ref (lhs, etype, esize, cur++); 3934 3935 chkp_walk_pointer_assignments (lhs_elem, val, arg, handler); 3936 } 3937 } 3938 } 3939 /* Copy array only when size is known. */ 3940 else if (maxval && !integer_minus_onep (maxval)) 3941 for (cur = 0; cur <= TREE_INT_CST_LOW (maxval); cur++) 3942 { 3943 tree lhs_elem = chkp_build_array_ref (lhs, etype, esize, cur); 3944 tree rhs_elem = chkp_build_array_ref (rhs, etype, esize, cur); 3945 chkp_walk_pointer_assignments (lhs_elem, rhs_elem, arg, handler); 3946 } 3947 } 3948 else 3949 internal_error("chkp_walk_pointer_assignments: unexpected RHS type: %s", 3950 get_tree_code_name (TREE_CODE (type))); 3951 } 3952 3953 /* Add code to copy bounds for assignment of RHS to LHS. 3954 ARG is an iterator pointing ne code position. */ 3955 static void 3956 chkp_copy_bounds_for_elem (tree lhs, tree rhs, void *arg) 3957 { 3958 gimple_stmt_iterator *iter = (gimple_stmt_iterator *)arg; 3959 tree bounds = chkp_find_bounds (rhs, iter); 3960 tree addr = chkp_build_addr_expr(lhs); 3961 3962 chkp_build_bndstx (addr, rhs, bounds, iter); 3963 } 3964 3965 /* Emit static bound initilizers and size vars. */ 3966 void 3967 chkp_finish_file (void) 3968 { 3969 struct varpool_node *node; 3970 struct chkp_ctor_stmt_list stmts; 3971 3972 if (seen_error ()) 3973 return; 3974 3975 /* Iterate through varpool and generate bounds initialization 3976 constructors for all statically initialized pointers. */ 3977 stmts.avail = MAX_STMTS_IN_STATIC_CHKP_CTOR; 3978 stmts.stmts = NULL; 3979 FOR_EACH_VARIABLE (node) 3980 /* Check that var is actually emitted and we need and may initialize 3981 its bounds. */ 3982 if (node->need_bounds_init 3983 && !POINTER_BOUNDS_P (node->decl) 3984 && DECL_RTL (node->decl) 3985 && MEM_P (DECL_RTL (node->decl)) 3986 && TREE_ASM_WRITTEN (node->decl)) 3987 { 3988 chkp_walk_pointer_assignments (node->decl, 3989 DECL_INITIAL (node->decl), 3990 &stmts, 3991 chkp_add_modification_to_stmt_list); 3992 3993 if (stmts.avail <= 0) 3994 { 3995 cgraph_build_static_cdtor ('P', stmts.stmts, 3996 MAX_RESERVED_INIT_PRIORITY + 3); 3997 stmts.avail = MAX_STMTS_IN_STATIC_CHKP_CTOR; 3998 stmts.stmts = NULL; 3999 } 4000 } 4001 4002 if (stmts.stmts) 4003 cgraph_build_static_cdtor ('P', stmts.stmts, 4004 MAX_RESERVED_INIT_PRIORITY + 3); 4005 4006 /* Iterate through varpool and generate bounds initialization 4007 constructors for all static bounds vars. */ 4008 stmts.avail = MAX_STMTS_IN_STATIC_CHKP_CTOR; 4009 stmts.stmts = NULL; 4010 FOR_EACH_VARIABLE (node) 4011 if (node->need_bounds_init 4012 && POINTER_BOUNDS_P (node->decl) 4013 && TREE_ASM_WRITTEN (node->decl)) 4014 { 4015 tree bnd = node->decl; 4016 tree var; 4017 4018 gcc_assert (DECL_INITIAL (bnd) 4019 && TREE_CODE (DECL_INITIAL (bnd)) == ADDR_EXPR); 4020 4021 var = TREE_OPERAND (DECL_INITIAL (bnd), 0); 4022 chkp_output_static_bounds (bnd, var, &stmts); 4023 } 4024 4025 if (stmts.stmts) 4026 cgraph_build_static_cdtor ('B', stmts.stmts, 4027 MAX_RESERVED_INIT_PRIORITY + 2); 4028 4029 delete chkp_static_var_bounds; 4030 delete chkp_bounds_map; 4031 } 4032 4033 /* An instrumentation function which is called for each statement 4034 having memory access we want to instrument. It inserts check 4035 code and bounds copy code. 4036 4037 ITER points to statement to instrument. 4038 4039 NODE holds memory access in statement to check. 4040 4041 LOC holds the location information for statement. 4042 4043 DIRFLAGS determines whether access is read or write. 4044 4045 ACCESS_OFFS should be added to address used in NODE 4046 before check. 4047 4048 ACCESS_SIZE holds size of checked access. 4049 4050 SAFE indicates if NODE access is safe and should not be 4051 checked. */ 4052 static void 4053 chkp_process_stmt (gimple_stmt_iterator *iter, tree node, 4054 location_t loc, tree dirflag, 4055 tree access_offs, tree access_size, 4056 bool safe) 4057 { 4058 tree node_type = TREE_TYPE (node); 4059 tree size = access_size ? access_size : TYPE_SIZE_UNIT (node_type); 4060 tree addr_first = NULL_TREE; /* address of the first accessed byte */ 4061 tree addr_last = NULL_TREE; /* address of the last accessed byte */ 4062 tree ptr = NULL_TREE; /* a pointer used for dereference */ 4063 tree bounds = NULL_TREE; 4064 bool reg_store = false; 4065 4066 /* We do not need instrumentation for clobbers. */ 4067 if (dirflag == integer_one_node 4068 && gimple_code (gsi_stmt (*iter)) == GIMPLE_ASSIGN 4069 && TREE_CLOBBER_P (gimple_assign_rhs1 (gsi_stmt (*iter)))) 4070 return; 4071 4072 switch (TREE_CODE (node)) 4073 { 4074 case ARRAY_REF: 4075 case COMPONENT_REF: 4076 { 4077 bool bitfield; 4078 tree elt; 4079 4080 if (safe) 4081 { 4082 /* We are not going to generate any checks, so do not 4083 generate bounds as well. */ 4084 addr_first = chkp_build_addr_expr (node); 4085 break; 4086 } 4087 4088 chkp_parse_array_and_component_ref (node, &ptr, &elt, &safe, 4089 &bitfield, &bounds, iter, false); 4090 4091 /* Break if there is no dereference and operation is safe. */ 4092 4093 if (bitfield) 4094 { 4095 tree field = TREE_OPERAND (node, 1); 4096 4097 if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST) 4098 size = DECL_SIZE_UNIT (field); 4099 4100 if (elt) 4101 elt = chkp_build_addr_expr (elt); 4102 addr_first = fold_convert_loc (loc, ptr_type_node, elt ? elt : ptr); 4103 addr_first = fold_build_pointer_plus_loc (loc, 4104 addr_first, 4105 byte_position (field)); 4106 } 4107 else 4108 addr_first = chkp_build_addr_expr (node); 4109 } 4110 break; 4111 4112 case INDIRECT_REF: 4113 ptr = TREE_OPERAND (node, 0); 4114 addr_first = ptr; 4115 break; 4116 4117 case MEM_REF: 4118 ptr = TREE_OPERAND (node, 0); 4119 addr_first = chkp_build_addr_expr (node); 4120 break; 4121 4122 case TARGET_MEM_REF: 4123 ptr = TMR_BASE (node); 4124 addr_first = chkp_build_addr_expr (node); 4125 break; 4126 4127 case ARRAY_RANGE_REF: 4128 printf("ARRAY_RANGE_REF\n"); 4129 debug_gimple_stmt(gsi_stmt(*iter)); 4130 debug_tree(node); 4131 gcc_unreachable (); 4132 break; 4133 4134 case BIT_FIELD_REF: 4135 { 4136 tree offset, size; 4137 4138 gcc_assert (!access_offs); 4139 gcc_assert (!access_size); 4140 4141 chkp_parse_bit_field_ref (node, loc, &offset, &size); 4142 4143 chkp_process_stmt (iter, TREE_OPERAND (node, 0), loc, 4144 dirflag, offset, size, safe); 4145 return; 4146 } 4147 break; 4148 4149 case VAR_DECL: 4150 case RESULT_DECL: 4151 case PARM_DECL: 4152 if (dirflag != integer_one_node 4153 || DECL_REGISTER (node)) 4154 return; 4155 4156 safe = true; 4157 addr_first = chkp_build_addr_expr (node); 4158 break; 4159 4160 default: 4161 return; 4162 } 4163 4164 /* If addr_last was not computed then use (addr_first + size - 1) 4165 expression to compute it. */ 4166 if (!addr_last) 4167 { 4168 addr_last = fold_build_pointer_plus_loc (loc, addr_first, size); 4169 addr_last = fold_build_pointer_plus_hwi_loc (loc, addr_last, -1); 4170 } 4171 4172 /* Shift both first_addr and last_addr by access_offs if specified. */ 4173 if (access_offs) 4174 { 4175 addr_first = fold_build_pointer_plus_loc (loc, addr_first, access_offs); 4176 addr_last = fold_build_pointer_plus_loc (loc, addr_last, access_offs); 4177 } 4178 4179 if (dirflag == integer_one_node) 4180 { 4181 tree base = get_base_address (node); 4182 if (VAR_P (base) && DECL_HARD_REGISTER (base)) 4183 reg_store = true; 4184 } 4185 4186 /* Generate bndcl/bndcu checks if memory access is not safe. */ 4187 if (!safe) 4188 { 4189 gimple_stmt_iterator stmt_iter = *iter; 4190 4191 if (!bounds) 4192 bounds = chkp_find_bounds (ptr, iter); 4193 4194 chkp_check_mem_access (addr_first, addr_last, bounds, 4195 stmt_iter, loc, dirflag); 4196 } 4197 4198 /* We need to store bounds in case pointer is stored. */ 4199 if (dirflag == integer_one_node 4200 && !reg_store 4201 && chkp_type_has_pointer (node_type) 4202 && flag_chkp_store_bounds) 4203 { 4204 gimple *stmt = gsi_stmt (*iter); 4205 tree rhs1 = gimple_assign_rhs1 (stmt); 4206 enum tree_code rhs_code = gimple_assign_rhs_code (stmt); 4207 4208 if (get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS) 4209 chkp_walk_pointer_assignments (node, rhs1, iter, 4210 chkp_copy_bounds_for_elem); 4211 else 4212 { 4213 bounds = chkp_compute_bounds_for_assignment (NULL_TREE, stmt); 4214 chkp_build_bndstx (addr_first, rhs1, bounds, iter); 4215 } 4216 } 4217 } 4218 4219 /* Add code to copy bounds for all pointers copied 4220 in ASSIGN created during inline of EDGE. */ 4221 void 4222 chkp_copy_bounds_for_assign (gimple *assign, struct cgraph_edge *edge) 4223 { 4224 tree lhs = gimple_assign_lhs (assign); 4225 tree rhs = gimple_assign_rhs1 (assign); 4226 gimple_stmt_iterator iter = gsi_for_stmt (assign); 4227 4228 if (!flag_chkp_store_bounds) 4229 return; 4230 4231 chkp_walk_pointer_assignments (lhs, rhs, &iter, chkp_copy_bounds_for_elem); 4232 4233 /* We should create edges for all created calls to bndldx and bndstx. */ 4234 while (gsi_stmt (iter) != assign) 4235 { 4236 gimple *stmt = gsi_stmt (iter); 4237 if (gimple_code (stmt) == GIMPLE_CALL) 4238 { 4239 tree fndecl = gimple_call_fndecl (stmt); 4240 struct cgraph_node *callee = cgraph_node::get_create (fndecl); 4241 4242 gcc_assert (chkp_gimple_call_builtin_p (stmt, BUILT_IN_CHKP_BNDSTX) 4243 || chkp_gimple_call_builtin_p (stmt, BUILT_IN_CHKP_BNDLDX) 4244 || chkp_gimple_call_builtin_p (stmt, BUILT_IN_CHKP_BNDRET)); 4245 4246 edge->caller->create_edge (callee, as_a <gcall *> (stmt), edge->count); 4247 } 4248 gsi_prev (&iter); 4249 } 4250 } 4251 4252 /* Some code transformation made during instrumentation pass 4253 may put code into inconsistent state. Here we find and fix 4254 such flaws. */ 4255 void 4256 chkp_fix_cfg () 4257 { 4258 basic_block bb; 4259 gimple_stmt_iterator i; 4260 4261 /* We could insert some code right after stmt which ends bb. 4262 We wanted to put this code on fallthru edge but did not 4263 add new edges from the beginning because it may cause new 4264 phi node creation which may be incorrect due to incomplete 4265 bound phi nodes. */ 4266 FOR_ALL_BB_FN (bb, cfun) 4267 for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) 4268 { 4269 gimple *stmt = gsi_stmt (i); 4270 gimple_stmt_iterator next = i; 4271 4272 gsi_next (&next); 4273 4274 if (stmt_ends_bb_p (stmt) 4275 && !gsi_end_p (next)) 4276 { 4277 edge fall = find_fallthru_edge (bb->succs); 4278 basic_block dest = NULL; 4279 int flags = 0; 4280 4281 gcc_assert (fall); 4282 4283 /* We cannot split abnormal edge. Therefore we 4284 store its params, make it regular and then 4285 rebuild abnormal edge after split. */ 4286 if (fall->flags & EDGE_ABNORMAL) 4287 { 4288 flags = fall->flags & ~EDGE_FALLTHRU; 4289 dest = fall->dest; 4290 4291 fall->flags &= ~EDGE_COMPLEX; 4292 } 4293 4294 while (!gsi_end_p (next)) 4295 { 4296 gimple *next_stmt = gsi_stmt (next); 4297 gsi_remove (&next, false); 4298 gsi_insert_on_edge (fall, next_stmt); 4299 } 4300 4301 gsi_commit_edge_inserts (); 4302 4303 /* Re-create abnormal edge. */ 4304 if (dest) 4305 make_edge (bb, dest, flags); 4306 } 4307 } 4308 } 4309 4310 /* Walker callback for chkp_replace_function_pointers. Replaces 4311 function pointer in the specified operand with pointer to the 4312 instrumented function version. */ 4313 static tree 4314 chkp_replace_function_pointer (tree *op, int *walk_subtrees, 4315 void *data ATTRIBUTE_UNUSED) 4316 { 4317 if (TREE_CODE (*op) == FUNCTION_DECL 4318 && chkp_instrumentable_p (*op) 4319 && (DECL_BUILT_IN_CLASS (*op) == NOT_BUILT_IN 4320 /* For builtins we replace pointers only for selected 4321 function and functions having definitions. */ 4322 || (DECL_BUILT_IN_CLASS (*op) == BUILT_IN_NORMAL 4323 && (chkp_instrument_normal_builtin (*op) 4324 || gimple_has_body_p (*op))))) 4325 { 4326 struct cgraph_node *node = cgraph_node::get_create (*op); 4327 struct cgraph_node *clone = NULL; 4328 4329 if (!node->instrumentation_clone) 4330 clone = chkp_maybe_create_clone (*op); 4331 4332 if (clone) 4333 *op = clone->decl; 4334 *walk_subtrees = 0; 4335 } 4336 4337 return NULL; 4338 } 4339 4340 /* This function searches for function pointers in statement 4341 pointed by GSI and replaces them with pointers to instrumented 4342 function versions. */ 4343 static void 4344 chkp_replace_function_pointers (gimple_stmt_iterator *gsi) 4345 { 4346 gimple *stmt = gsi_stmt (*gsi); 4347 /* For calls we want to walk call args only. */ 4348 if (gimple_code (stmt) == GIMPLE_CALL) 4349 { 4350 unsigned i; 4351 for (i = 0; i < gimple_call_num_args (stmt); i++) 4352 walk_tree (gimple_call_arg_ptr (stmt, i), 4353 chkp_replace_function_pointer, NULL, NULL); 4354 } 4355 else 4356 walk_gimple_stmt (gsi, NULL, chkp_replace_function_pointer, NULL); 4357 } 4358 4359 /* This function instruments all statements working with memory, 4360 calls and rets. 4361 4362 It also removes excess statements from static initializers. */ 4363 static void 4364 chkp_instrument_function (void) 4365 { 4366 basic_block bb, next; 4367 gimple_stmt_iterator i; 4368 enum gimple_rhs_class grhs_class; 4369 bool safe = lookup_attribute ("chkp ctor", DECL_ATTRIBUTES (cfun->decl)); 4370 4371 bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; 4372 do 4373 { 4374 next = bb->next_bb; 4375 for (i = gsi_start_bb (bb); !gsi_end_p (i); ) 4376 { 4377 gimple *s = gsi_stmt (i); 4378 4379 /* Skip statement marked to not be instrumented. */ 4380 if (chkp_marked_stmt_p (s)) 4381 { 4382 gsi_next (&i); 4383 continue; 4384 } 4385 4386 chkp_replace_function_pointers (&i); 4387 4388 switch (gimple_code (s)) 4389 { 4390 case GIMPLE_ASSIGN: 4391 chkp_process_stmt (&i, gimple_assign_lhs (s), 4392 gimple_location (s), integer_one_node, 4393 NULL_TREE, NULL_TREE, safe); 4394 chkp_process_stmt (&i, gimple_assign_rhs1 (s), 4395 gimple_location (s), integer_zero_node, 4396 NULL_TREE, NULL_TREE, safe); 4397 grhs_class = get_gimple_rhs_class (gimple_assign_rhs_code (s)); 4398 if (grhs_class == GIMPLE_BINARY_RHS) 4399 chkp_process_stmt (&i, gimple_assign_rhs2 (s), 4400 gimple_location (s), integer_zero_node, 4401 NULL_TREE, NULL_TREE, safe); 4402 break; 4403 4404 case GIMPLE_RETURN: 4405 { 4406 greturn *r = as_a <greturn *> (s); 4407 if (gimple_return_retval (r) != NULL_TREE) 4408 { 4409 chkp_process_stmt (&i, gimple_return_retval (r), 4410 gimple_location (r), 4411 integer_zero_node, 4412 NULL_TREE, NULL_TREE, safe); 4413 4414 /* Additionally we need to add bounds 4415 to return statement. */ 4416 chkp_add_bounds_to_ret_stmt (&i); 4417 } 4418 } 4419 break; 4420 4421 case GIMPLE_CALL: 4422 chkp_add_bounds_to_call_stmt (&i); 4423 break; 4424 4425 default: 4426 ; 4427 } 4428 4429 gsi_next (&i); 4430 4431 /* We do not need any actual pointer stores in checker 4432 static initializer. */ 4433 if (lookup_attribute ("chkp ctor", DECL_ATTRIBUTES (cfun->decl)) 4434 && gimple_code (s) == GIMPLE_ASSIGN 4435 && gimple_store_p (s)) 4436 { 4437 gimple_stmt_iterator del_iter = gsi_for_stmt (s); 4438 gsi_remove (&del_iter, true); 4439 unlink_stmt_vdef (s); 4440 release_defs(s); 4441 } 4442 } 4443 bb = next; 4444 } 4445 while (bb); 4446 4447 /* Some input params may have bounds and be address taken. In this case 4448 we should store incoming bounds into bounds table. */ 4449 tree arg; 4450 if (flag_chkp_store_bounds) 4451 for (arg = DECL_ARGUMENTS (cfun->decl); arg; arg = DECL_CHAIN (arg)) 4452 if (TREE_ADDRESSABLE (arg)) 4453 { 4454 if (BOUNDED_P (arg)) 4455 { 4456 tree bounds = chkp_get_next_bounds_parm (arg); 4457 tree def_ptr = ssa_default_def (cfun, arg); 4458 gimple_stmt_iterator iter 4459 = gsi_start_bb (chkp_get_entry_block ()); 4460 chkp_build_bndstx (chkp_build_addr_expr (arg), 4461 def_ptr ? def_ptr : arg, 4462 bounds, &iter); 4463 4464 /* Skip bounds arg. */ 4465 arg = TREE_CHAIN (arg); 4466 } 4467 else if (chkp_type_has_pointer (TREE_TYPE (arg))) 4468 { 4469 tree orig_arg = arg; 4470 bitmap slots = BITMAP_ALLOC (NULL); 4471 gimple_stmt_iterator iter 4472 = gsi_start_bb (chkp_get_entry_block ()); 4473 bitmap_iterator bi; 4474 unsigned bnd_no; 4475 4476 chkp_find_bound_slots (TREE_TYPE (arg), slots); 4477 4478 EXECUTE_IF_SET_IN_BITMAP (slots, 0, bnd_no, bi) 4479 { 4480 tree bounds = chkp_get_next_bounds_parm (arg); 4481 HOST_WIDE_INT offs = bnd_no * POINTER_SIZE / BITS_PER_UNIT; 4482 tree addr = chkp_build_addr_expr (orig_arg); 4483 tree ptr = build2 (MEM_REF, ptr_type_node, addr, 4484 build_int_cst (ptr_type_node, offs)); 4485 chkp_build_bndstx (chkp_build_addr_expr (ptr), ptr, 4486 bounds, &iter); 4487 4488 arg = DECL_CHAIN (arg); 4489 } 4490 BITMAP_FREE (slots); 4491 } 4492 } 4493 } 4494 4495 /* Find init/null/copy_ptr_bounds calls and replace them 4496 with assignments. It should allow better code 4497 optimization. */ 4498 4499 static void 4500 chkp_remove_useless_builtins () 4501 { 4502 basic_block bb; 4503 gimple_stmt_iterator gsi; 4504 4505 FOR_EACH_BB_FN (bb, cfun) 4506 { 4507 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 4508 { 4509 gimple *stmt = gsi_stmt (gsi); 4510 tree fndecl; 4511 enum built_in_function fcode; 4512 4513 /* Find builtins returning first arg and replace 4514 them with assignments. */ 4515 if (gimple_code (stmt) == GIMPLE_CALL 4516 && (fndecl = gimple_call_fndecl (stmt)) 4517 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 4518 && (fcode = DECL_FUNCTION_CODE (fndecl)) 4519 && (fcode == BUILT_IN_CHKP_INIT_PTR_BOUNDS 4520 || fcode == BUILT_IN_CHKP_NULL_PTR_BOUNDS 4521 || fcode == BUILT_IN_CHKP_COPY_PTR_BOUNDS 4522 || fcode == BUILT_IN_CHKP_SET_PTR_BOUNDS)) 4523 { 4524 tree res = gimple_call_arg (stmt, 0); 4525 update_call_from_tree (&gsi, res); 4526 stmt = gsi_stmt (gsi); 4527 update_stmt (stmt); 4528 } 4529 } 4530 } 4531 } 4532 4533 /* Initialize pass. */ 4534 static void 4535 chkp_init (void) 4536 { 4537 basic_block bb; 4538 gimple_stmt_iterator i; 4539 4540 in_chkp_pass = true; 4541 4542 for (bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; bb; bb = bb->next_bb) 4543 for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) 4544 chkp_unmark_stmt (gsi_stmt (i)); 4545 4546 chkp_invalid_bounds = new hash_set<tree>; 4547 chkp_completed_bounds_set = new hash_set<tree>; 4548 delete chkp_reg_bounds; 4549 chkp_reg_bounds = new hash_map<tree, tree>; 4550 delete chkp_bound_vars; 4551 chkp_bound_vars = new hash_map<tree, tree>; 4552 chkp_reg_addr_bounds = new hash_map<tree, tree>; 4553 chkp_incomplete_bounds_map = new hash_map<tree, tree>; 4554 delete chkp_bounds_map; 4555 chkp_bounds_map = new hash_map<tree, tree>; 4556 chkp_abnormal_copies = BITMAP_GGC_ALLOC (); 4557 4558 entry_block = NULL; 4559 zero_bounds = NULL_TREE; 4560 none_bounds = NULL_TREE; 4561 incomplete_bounds = integer_zero_node; 4562 tmp_var = NULL_TREE; 4563 size_tmp_var = NULL_TREE; 4564 4565 chkp_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode, true); 4566 4567 /* We create these constant bounds once for each object file. 4568 These symbols go to comdat section and result in single copy 4569 of each one in the final binary. */ 4570 chkp_get_zero_bounds_var (); 4571 chkp_get_none_bounds_var (); 4572 4573 calculate_dominance_info (CDI_DOMINATORS); 4574 calculate_dominance_info (CDI_POST_DOMINATORS); 4575 4576 bitmap_obstack_initialize (NULL); 4577 } 4578 4579 /* Finalize instrumentation pass. */ 4580 static void 4581 chkp_fini (void) 4582 { 4583 in_chkp_pass = false; 4584 4585 delete chkp_invalid_bounds; 4586 delete chkp_completed_bounds_set; 4587 delete chkp_reg_addr_bounds; 4588 delete chkp_incomplete_bounds_map; 4589 4590 free_dominance_info (CDI_DOMINATORS); 4591 free_dominance_info (CDI_POST_DOMINATORS); 4592 4593 bitmap_obstack_release (NULL); 4594 4595 entry_block = NULL; 4596 zero_bounds = NULL_TREE; 4597 none_bounds = NULL_TREE; 4598 } 4599 4600 /* Main instrumentation pass function. */ 4601 static unsigned int 4602 chkp_execute (void) 4603 { 4604 chkp_init (); 4605 4606 chkp_instrument_function (); 4607 4608 chkp_remove_useless_builtins (); 4609 4610 chkp_function_mark_instrumented (cfun->decl); 4611 4612 chkp_fix_cfg (); 4613 4614 chkp_fini (); 4615 4616 return 0; 4617 } 4618 4619 /* Instrumentation pass gate. */ 4620 static bool 4621 chkp_gate (void) 4622 { 4623 cgraph_node *node = cgraph_node::get (cfun->decl); 4624 return ((node != NULL 4625 && node->instrumentation_clone) 4626 || lookup_attribute ("chkp ctor", DECL_ATTRIBUTES (cfun->decl))); 4627 } 4628 4629 namespace { 4630 4631 const pass_data pass_data_chkp = 4632 { 4633 GIMPLE_PASS, /* type */ 4634 "chkp", /* name */ 4635 OPTGROUP_NONE, /* optinfo_flags */ 4636 TV_NONE, /* tv_id */ 4637 PROP_ssa | PROP_cfg, /* properties_required */ 4638 0, /* properties_provided */ 4639 0, /* properties_destroyed */ 4640 0, /* todo_flags_start */ 4641 TODO_verify_il 4642 | TODO_update_ssa /* todo_flags_finish */ 4643 }; 4644 4645 class pass_chkp : public gimple_opt_pass 4646 { 4647 public: 4648 pass_chkp (gcc::context *ctxt) 4649 : gimple_opt_pass (pass_data_chkp, ctxt) 4650 {} 4651 4652 /* opt_pass methods: */ 4653 virtual opt_pass * clone () 4654 { 4655 return new pass_chkp (m_ctxt); 4656 } 4657 4658 virtual bool gate (function *) 4659 { 4660 return chkp_gate (); 4661 } 4662 4663 virtual unsigned int execute (function *) 4664 { 4665 return chkp_execute (); 4666 } 4667 4668 }; // class pass_chkp 4669 4670 } // anon namespace 4671 4672 gimple_opt_pass * 4673 make_pass_chkp (gcc::context *ctxt) 4674 { 4675 return new pass_chkp (ctxt); 4676 } 4677 4678 #include "gt-tree-chkp.h" 4679