1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 2 // -*- Mode: C++ -*- 3 // 4 // Copyright (C) 2016-2022 Red Hat, Inc. 5 // 6 // Author: Dodji Seketeli 7 8 #ifndef __ABG_SUPPRESSION_H__ 9 #define __ABG_SUPPRESSION_H__ 10 11 #include <unordered_set> 12 13 #include "abg-ini.h" 14 #include "abg-comparison.h" 15 16 namespace abigail 17 { 18 19 class fe_iface; 20 21 /// @brief an engine to suppress the parts of the result of comparing 22 /// two sets of ABI artifacts. 23 /// 24 /// The user specifies the kind of changes between ABI artefact she 25 /// wants to see suppressed. That suppression specification is done 26 /// in an INI format. 27 /// 28 /// That INI file is parsed and represented internally using the types 29 /// that are defined in this namespace. 30 namespace suppr 31 { 32 33 using namespace abigail::comparison; 34 using std::unordered_set; 35 36 /// Base type of the suppression specifications types. 37 /// 38 /// This abstracts a suppression specification. It's a way to specify 39 /// how to drop reports about a particular diff node on the floor, if 40 /// it matches the supppression specification. 41 class suppression_base 42 { 43 public: 44 class priv; // declare publicly to allow subclasses to reuse the priv 45 private: 46 // Forbid default constructor 47 suppression_base(); 48 49 public: 50 std::unique_ptr<priv> priv_; 51 52 suppression_base(const string& label); 53 54 suppression_base(const string& label, 55 const string& file_name_regex_str, 56 const string& file_name_not_regex_str); 57 58 bool 59 get_drops_artifact_from_ir() const; 60 61 void 62 set_drops_artifact_from_ir(bool); 63 64 bool 65 get_is_artificial() const; 66 67 void 68 set_is_artificial(bool); 69 70 const string 71 get_label() const; 72 73 void 74 set_label(const string&); 75 76 void 77 set_file_name_regex_str(const string& regexp); 78 79 const string& 80 get_file_name_regex_str() const; 81 82 void 83 set_file_name_not_regex_str(const string& regexp); 84 85 const string& 86 get_file_name_not_regex_str() const; 87 88 bool 89 has_file_name_related_property() const; 90 91 void 92 set_soname_regex_str(const string& regexp); 93 94 const string& 95 get_soname_regex_str() const; 96 97 void 98 set_soname_not_regex_str(const string& regexp); 99 100 const string& 101 get_soname_not_regex_str() const; 102 103 bool 104 has_soname_related_property() const; 105 106 virtual bool 107 suppresses_diff(const diff*) const = 0; 108 109 virtual ~suppression_base(); 110 111 friend bool 112 suppression_matches_soname(const string& soname, 113 const suppression_base& suppr); 114 115 friend bool 116 suppression_matches_soname_or_filename(const string& soname, 117 const string& filename, 118 const suppression_base& suppr); 119 }; // end class suppression_base 120 121 /// Convenience typedef for a shared pointer to a @ref suppression. 122 typedef shared_ptr<suppression_base> suppression_sptr; 123 124 /// Convenience typedef for a vector of @ref suppression_sptr 125 typedef vector<suppression_sptr> suppressions_type; 126 127 void 128 read_suppressions(std::istream& input, 129 suppressions_type& suppressions); 130 131 void 132 read_suppressions(const string& file_path, 133 suppressions_type& suppressions); 134 135 class type_suppression; 136 137 /// Convenience typedef for a shared pointer to type_suppression. 138 typedef shared_ptr<type_suppression> type_suppression_sptr; 139 140 /// Convenience typedef for vector of @ref type_suppression_sptr. 141 typedef vector<type_suppression_sptr> type_suppressions_type; 142 143 /// Abstraction of a type suppression specification. 144 /// 145 /// Specifies under which condition reports about a type diff node 146 /// should be dropped on the floor. 147 class type_suppression : public suppression_base 148 { 149 class priv; 150 151 // Forbid this; 152 type_suppression(); 153 154 public: 155 std::unique_ptr<priv> priv_; 156 157 /// The kind of the type the current type suppression is supposed to 158 /// be about. 159 enum type_kind 160 { 161 UNKNOWN_TYPE_KIND, 162 CLASS_TYPE_KIND, 163 STRUCT_TYPE_KIND, 164 UNION_TYPE_KIND, 165 ENUM_TYPE_KIND, 166 ARRAY_TYPE_KIND, 167 TYPEDEF_TYPE_KIND, 168 BUILTIN_TYPE_KIND 169 }; // end enum type_kind 170 171 /// The different ways through which the type diff has been reached. 172 enum reach_kind 173 { 174 /// The type diff has been reached (from a function or variable 175 /// change) directly. 176 DIRECT_REACH_KIND = 0, 177 178 /// The type diff has been reached (from a function or variable 179 /// change) through a pointer. 180 POINTER_REACH_KIND, 181 182 /// The type diff has been reached (from a function or variable 183 /// change) through a reference; you know, like a c++ reference.. 184 REFERENCE_REACH_KIND, 185 186 /// The type diff has been reached (from a function or variable 187 /// change) through either a reference or a pointer. 188 REFERENCE_OR_POINTER_REACH_KIND 189 }; // end enum reach_kind 190 191 class insertion_range; 192 /// A convenience typedef for a shared pointer to @ref 193 /// insertion_range. 194 typedef shared_ptr<insertion_range> insertion_range_sptr; 195 /// A convenience typedef for a vector of @ref insertion_range_sptr. 196 typedef vector<insertion_range_sptr> insertion_ranges; 197 198 type_suppression(const string& label, 199 const string& type_name_regexp, 200 const string& type_name); 201 202 virtual ~type_suppression(); 203 204 void 205 set_type_name_regex_str(const string& name_regex_str); 206 207 const string& 208 get_type_name_regex_str() const; 209 210 void 211 set_type_name_not_regex_str(const string& name_regex_str); 212 213 const string& 214 get_type_name_not_regex_str() const; 215 216 void 217 set_type_name(const string& name); 218 219 const string& 220 get_type_name() const; 221 222 bool 223 get_consider_type_kind() const; 224 225 void 226 set_consider_type_kind(bool f); 227 228 void 229 set_type_kind(type_kind k); 230 231 type_kind 232 get_type_kind() const; 233 234 bool 235 get_consider_reach_kind() const; 236 237 void 238 set_consider_reach_kind(bool f); 239 240 reach_kind 241 get_reach_kind() const; 242 243 void 244 set_reach_kind(reach_kind k); 245 246 void 247 set_data_member_insertion_ranges(const insertion_ranges& r); 248 249 const insertion_ranges& 250 get_data_member_insertion_ranges() const; 251 252 insertion_ranges& 253 get_data_member_insertion_ranges(); 254 255 const unordered_set<string>& 256 get_source_locations_to_keep() const; 257 258 unordered_set<string>& 259 get_source_locations_to_keep(); 260 261 void 262 set_source_locations_to_keep(const unordered_set<string>&); 263 264 const string& 265 get_source_location_to_keep_regex_str() const; 266 267 void 268 set_source_location_to_keep_regex_str(const string&); 269 270 const vector<string>& 271 get_changed_enumerator_names() const; 272 273 void 274 set_changed_enumerator_names(const vector<string>&); 275 276 virtual bool 277 suppresses_diff(const diff* diff) const; 278 279 bool 280 suppresses_type(const type_base_sptr& type, 281 const diff_context_sptr& ctxt) const; 282 283 bool 284 suppresses_type(const type_base_sptr& type) const; 285 286 bool 287 suppresses_type(const type_base_sptr& type, 288 const scope_decl* type_scope) const; 289 }; // end type_suppression 290 291 type_suppression_sptr 292 is_type_suppression(const suppression_sptr); 293 294 /// The abstraction of a range of offsets in which a member of a type 295 /// might get inserted. 296 class type_suppression::insertion_range 297 { 298 struct priv; 299 std::unique_ptr<priv> priv_; 300 301 public: 302 303 class boundary; 304 class integer_boundary; 305 class fn_call_expr_boundary; 306 307 /// Convenience typedef for a shared_ptr to @ref boundary 308 typedef shared_ptr<boundary> boundary_sptr; 309 310 /// Convenience typedef for a shared_ptr to a @ref integer_boundary 311 typedef shared_ptr<integer_boundary> integer_boundary_sptr; 312 313 /// Convenience typedef for a shared_ptr to a @ref 314 /// fn_call_expr_boundary 315 typedef shared_ptr<fn_call_expr_boundary> fn_call_expr_boundary_sptr; 316 317 insertion_range(); 318 319 insertion_range(boundary_sptr begin, boundary_sptr end); 320 321 boundary_sptr 322 begin() const; 323 324 boundary_sptr 325 end() const; 326 327 static insertion_range::integer_boundary_sptr 328 create_integer_boundary(int value); 329 330 static insertion_range::fn_call_expr_boundary_sptr 331 create_fn_call_expr_boundary(ini::function_call_expr_sptr); 332 333 static insertion_range::fn_call_expr_boundary_sptr 334 create_fn_call_expr_boundary(const string&); 335 336 static bool 337 eval_boundary(boundary_sptr boundary, 338 class_decl_sptr context, 339 uint64_t& value); 340 341 static bool 342 boundary_value_is_end(uint64_t value); 343 }; // end class insertion_range 344 345 type_suppression::insertion_range::integer_boundary_sptr 346 is_integer_boundary(type_suppression::insertion_range::boundary_sptr); 347 348 type_suppression::insertion_range::fn_call_expr_boundary_sptr 349 is_fn_call_expr_boundary(type_suppression::insertion_range::boundary_sptr); 350 351 /// The abstraction of the boundary of an @ref insertion_range, in the 352 /// context of a @ref type_suppression 353 class type_suppression::insertion_range::boundary 354 { 355 struct priv; 356 std::unique_ptr<priv> priv_; 357 358 public: 359 boundary(); 360 virtual ~boundary(); 361 };// end class type_suppression::insertion_range::boundary 362 363 /// An @ref insertion_range boundary that is expressed as an integer 364 /// value. That integer value is usually a bit offset. 365 class type_suppression::insertion_range::integer_boundary 366 : public type_suppression::insertion_range::boundary 367 { 368 struct priv; 369 std::unique_ptr<priv> priv_; 370 371 integer_boundary(); 372 373 public: 374 integer_boundary(uint64_t value); 375 uint64_t as_integer() const; 376 operator uint64_t () const; 377 ~integer_boundary(); 378 }; //end class type_suppression::insertion_range::integer_boundary 379 380 /// An @ref insertion_range boundary that is expressed as function 381 /// call expression. The (integer) value of that expression is 382 /// usually a bit offset. 383 class type_suppression::insertion_range::fn_call_expr_boundary 384 : public type_suppression::insertion_range::boundary 385 { 386 struct priv; 387 std::unique_ptr<priv> priv_; 388 389 fn_call_expr_boundary(); 390 391 public: 392 fn_call_expr_boundary(ini::function_call_expr_sptr expr); 393 ini::function_call_expr_sptr as_function_call_expr() const; 394 operator ini::function_call_expr_sptr () const; 395 ~fn_call_expr_boundary(); 396 }; //end class type_suppression::insertion_range::fn_call_expr_boundary 397 398 class function_suppression; 399 400 /// Convenience typedef for a shared pointer to function_suppression. 401 typedef shared_ptr<function_suppression> function_suppression_sptr; 402 403 /// Convenience typedef for a vector of @ref function_suppression_sptr. 404 typedef vector<function_suppression_sptr> function_suppressions_type; 405 406 /// Abstraction of a function suppression specification. 407 /// 408 /// Specifies under which condition reports about a @ref 409 /// function_decl_diff diff node should be dropped on the floor for 410 /// the purpose of reporting. 411 class function_suppression : public suppression_base 412 { 413 struct priv; 414 415 public: 416 417 std::unique_ptr<priv> priv_; 418 class parameter_spec; 419 420 /// Convenience typedef for shared_ptr of @ref parameter_spec. 421 typedef shared_ptr<parameter_spec> parameter_spec_sptr; 422 423 /// Convenience typedef for vector of @ref parameter_spec_sptr. 424 typedef vector<parameter_spec_sptr> parameter_specs_type; 425 426 /// The kind of change the current function suppression should apply 427 /// to. 428 enum change_kind 429 { 430 UNDEFINED_CHANGE_KIND, 431 /// A change in a sub-type of the function. 432 FUNCTION_SUBTYPE_CHANGE_KIND = 1, 433 /// The function was added to the second subject of the diff. 434 ADDED_FUNCTION_CHANGE_KIND = 1 << 1, 435 /// The function was deleted from the second subject of the diff. 436 DELETED_FUNCTION_CHANGE_KIND = 1 << 2, 437 /// This represents all the changes possibly described by this 438 /// enum. It's a logical 'OR' of all the change enumerators 439 /// above. 440 ALL_CHANGE_KIND = (FUNCTION_SUBTYPE_CHANGE_KIND 441 | ADDED_FUNCTION_CHANGE_KIND 442 | DELETED_FUNCTION_CHANGE_KIND) 443 }; 444 445 function_suppression(); 446 447 function_suppression(const string& label, 448 const string& name, 449 const string& name_regex, 450 const string& return_type_name, 451 const string& return_type_regex, 452 parameter_specs_type& parm_specs, 453 const string& symbol_name, 454 const string& symbol_name_regex, 455 const string& symbol_version, 456 const string& symbol_version_regex_str); 457 458 virtual ~function_suppression(); 459 460 static change_kind 461 parse_change_kind(const string&); 462 463 change_kind 464 get_change_kind() const; 465 466 void 467 set_change_kind(change_kind k); 468 469 const string& 470 get_name() const; 471 472 void 473 set_name(const string&); 474 475 const string& 476 get_name_regex_str() const; 477 478 void 479 set_name_regex_str(const string&); 480 481 const string& 482 get_name_not_regex_str() const; 483 484 void 485 set_name_not_regex_str(const string&); 486 487 const string& 488 get_return_type_name() const; 489 490 void 491 set_return_type_name(const string&); 492 493 const string& 494 get_return_type_regex_str() const; 495 496 void 497 set_return_type_regex_str(const string& r); 498 499 const parameter_specs_type& 500 get_parameter_specs() const; 501 502 void 503 set_parameter_specs(parameter_specs_type&); 504 505 void 506 append_parameter_specs(const parameter_spec_sptr); 507 508 const string& 509 get_symbol_name() const; 510 511 void 512 set_symbol_name(const string& n); 513 514 const string& 515 get_symbol_name_regex_str() const; 516 517 void 518 set_symbol_name_regex_str(const string&); 519 520 const string& 521 get_symbol_name_not_regex_str() const; 522 523 void 524 set_symbol_name_not_regex_str(const string&); 525 526 const string& 527 get_symbol_version() const; 528 529 void 530 set_symbol_version(const string&); 531 532 const string& 533 get_symbol_version_regex_str() const; 534 535 void 536 set_symbol_version_regex_str(const string&); 537 538 bool 539 get_allow_other_aliases() const; 540 541 void 542 set_allow_other_aliases(bool f); 543 544 virtual bool 545 suppresses_diff(const diff* diff) const; 546 547 bool 548 suppresses_function(const function_decl* fn, 549 change_kind k, 550 const diff_context_sptr ctxt) const; 551 552 bool 553 suppresses_function(const function_decl_sptr fn, 554 change_kind k, 555 const diff_context_sptr ctxt) const; 556 557 bool 558 suppresses_function_symbol(const elf_symbol* sym, 559 change_kind k, 560 const diff_context_sptr ctxt); 561 562 bool 563 suppresses_function_symbol(const elf_symbol_sptr sym, 564 change_kind k, 565 const diff_context_sptr ctxt); 566 }; // end class function_suppression. 567 568 function_suppression_sptr 569 is_function_suppression(const suppression_sptr); 570 571 function_suppression::change_kind 572 operator&(function_suppression::change_kind l, 573 function_suppression::change_kind r); 574 575 function_suppression::change_kind 576 operator|(function_suppression::change_kind l, 577 function_suppression::change_kind r); 578 579 /// Abstraction of the specification of a function parameter in a 580 /// function suppression specification. 581 class function_suppression::parameter_spec 582 { 583 friend class function_suppression; 584 585 class priv; 586 std::unique_ptr<priv> priv_; 587 588 // Forbid this. 589 parameter_spec(); 590 591 public: 592 parameter_spec(size_t index, 593 const string& type_name, 594 const string& type_name_regex); 595 596 size_t 597 get_index() const; 598 599 void 600 set_index(size_t); 601 602 const string& 603 get_parameter_type_name() const; 604 605 void 606 set_parameter_type_name(const string&); 607 608 const string& 609 get_parameter_type_name_regex_str() const; 610 611 void 612 set_parameter_type_name_regex_str(const string&); 613 };// end class function_suppression::parameter_spec 614 615 class variable_suppression; 616 617 /// A convenience typedef for a shared pointer to @ref 618 /// variable_suppression. 619 typedef shared_ptr<variable_suppression> variable_suppression_sptr; 620 621 /// A convenience typedef for a vector of @ref 622 /// variable_suppression_sptr. 623 typedef vector<variable_suppression_sptr> variable_suppressions_type; 624 625 /// The abstraction of a variable suppression specification. 626 /// 627 /// It specifies under which condition reports about a @ref var_diff 628 /// diff node should be dropped on the floor for the purpose of 629 /// reporting. 630 class variable_suppression : public suppression_base 631 { 632 public: 633 634 /// The kind of change the current variable suppression should apply 635 /// to. 636 enum change_kind 637 { 638 UNDEFINED_CHANGE_KIND, 639 /// A change in a sub-type of the variable. 640 VARIABLE_SUBTYPE_CHANGE_KIND = 1, 641 /// The variable was added to the second second subject of the 642 /// diff. 643 ADDED_VARIABLE_CHANGE_KIND = 1 << 1, 644 /// The variable was deleted from the second subject of the diff. 645 DELETED_VARIABLE_CHANGE_KIND = 1 << 2, 646 /// This represents all the changes possibly described by this 647 /// enum. It's a logical 'OR' of all the change enumerators 648 /// above. 649 ALL_CHANGE_KIND = (VARIABLE_SUBTYPE_CHANGE_KIND 650 | ADDED_VARIABLE_CHANGE_KIND 651 | DELETED_VARIABLE_CHANGE_KIND) 652 }; 653 654 private: 655 struct priv; 656 657 public: 658 std::unique_ptr<priv> priv_; 659 660 variable_suppression(const string& label = "", 661 const string& name = "", 662 const string& name_regex_str = "", 663 const string& symbol_name = "", 664 const string& symbol_name_regex_str = "", 665 const string& symbol_version = "", 666 const string& symbol_version_regex_str = "", 667 const string& type_name = "", 668 const string& type_name_regex_str = ""); 669 670 virtual ~variable_suppression(); 671 672 static change_kind 673 parse_change_kind(const string&); 674 675 change_kind 676 get_change_kind() const; 677 678 void 679 set_change_kind(change_kind k); 680 681 const string& 682 get_name() const; 683 684 void 685 set_name(const string&); 686 687 const string& 688 get_name_regex_str() const; 689 690 void 691 set_name_regex_str(const string&); 692 693 const string& 694 get_name_not_regex_str() const; 695 696 void 697 set_name_not_regex_str(const string&); 698 699 const string& 700 get_symbol_name() const; 701 702 void 703 set_symbol_name(const string&); 704 705 const string& 706 get_symbol_name_regex_str() const; 707 708 void 709 set_symbol_name_regex_str(const string&); 710 711 const string& 712 get_symbol_name_not_regex_str() const; 713 714 void 715 set_symbol_name_not_regex_str(const string&); 716 717 const string& 718 get_symbol_version() const; 719 720 void 721 set_symbol_version(const string&); 722 723 const string& 724 get_symbol_version_regex_str() const; 725 726 void 727 set_symbol_version_regex_str(const string&); 728 729 const string& 730 get_type_name() const; 731 732 void 733 set_type_name(const string&); 734 735 const string& 736 get_type_name_regex_str() const; 737 738 void 739 set_type_name_regex_str(const string&); 740 741 bool 742 suppresses_diff(const diff* d) const; 743 744 bool 745 suppresses_variable(const var_decl* var, 746 change_kind k, 747 const diff_context_sptr cxt) const; 748 749 bool 750 suppresses_variable(const var_decl_sptr var, 751 change_kind k, 752 const diff_context_sptr cxt) const; 753 754 bool 755 suppresses_variable_symbol(const elf_symbol* sym, 756 change_kind k, 757 const diff_context_sptr cxt) const; 758 759 bool 760 suppresses_variable_symbol(const elf_symbol_sptr fn, 761 change_kind k, 762 const diff_context_sptr cxt) const; 763 }; // end class variable_suppression 764 765 variable_suppression_sptr 766 is_variable_suppression(const suppression_sptr); 767 768 variable_suppression::change_kind 769 operator&(variable_suppression::change_kind l, 770 variable_suppression::change_kind r); 771 772 variable_suppression::change_kind 773 operator|(variable_suppression::change_kind l, 774 variable_suppression::change_kind r); 775 776 class file_suppression; 777 778 /// A convenience typedef for a shared_ptr to @ref file_suppression 779 typedef shared_ptr<file_suppression> file_suppression_sptr; 780 781 /// Abstraction of a suppression specification to avoid loading a 782 /// file. 783 /// 784 /// This can be used by a tool that loads (binary) files, to know 785 /// which file it has to avoid loading. 786 class file_suppression: public suppression_base 787 { 788 std::unique_ptr<priv> priv_; 789 790 // Forbid this 791 file_suppression(); 792 793 public: 794 795 file_suppression(const string& label, 796 const string& file_name_regex, 797 const string& file_name_not_regex); 798 799 virtual bool 800 suppresses_diff(const diff* diff) const; 801 802 bool 803 suppresses_file(const string& file_path); 804 805 virtual ~file_suppression(); 806 }; // end file_suppression 807 808 file_suppression_sptr 809 is_file_suppression(const suppression_sptr); 810 811 file_suppression_sptr 812 file_is_suppressed(const string& file_path, 813 const suppressions_type& suppressions); 814 815 bool 816 suppression_matches_soname(const string& soname, 817 const suppression_base& suppr); 818 819 bool 820 suppression_matches_soname_or_filename(const string& soname, 821 const string& filename, 822 const suppression_base& suppr); 823 824 const char* 825 get_private_types_suppr_spec_label(); 826 827 bool 828 is_private_type_suppr_spec(const type_suppression&); 829 830 bool 831 is_private_type_suppr_spec(const suppression_sptr& s); 832 833 bool 834 suppression_can_match(const fe_iface&, 835 const suppression_base&); 836 837 bool 838 suppression_matches_function_name(const fe_iface&, 839 const suppr::function_suppression&, 840 const string&); 841 842 bool 843 suppression_matches_function_sym_name(const fe_iface&, 844 const suppr::function_suppression& s, 845 const string& fn_linkage_name); 846 847 bool 848 suppression_matches_variable_name(const fe_iface&, 849 const suppr::variable_suppression& s, 850 const string& var_name); 851 852 bool 853 suppression_matches_variable_sym_name(const fe_iface&, 854 const suppr::variable_suppression&, 855 const string&); 856 857 bool 858 suppression_matches_type_name_or_location(const fe_iface&, 859 const suppr::type_suppression&, 860 const string&, 861 const location&); 862 863 bool 864 is_elf_symbol_suppressed(const fe_iface&, 865 const elf_symbol_sptr& symbol); 866 867 bool 868 is_elf_symbol_suppressed(const fe_iface&, 869 const string& sym_name, 870 elf_symbol::type sym_type); 871 872 bool 873 is_function_suppressed(const fe_iface& fe, 874 const string& fn_name, 875 const string& fn_linkage_name, 876 bool require_drop_property = false); 877 878 bool 879 is_variable_suppressed(const fe_iface& fe, 880 const string& var_name, 881 const string& var_linkage_name, 882 bool require_drop_property = false); 883 884 bool 885 is_type_suppressed(const fe_iface& fe, 886 const string& type_name, 887 const location& type_location, 888 bool& type_is_private, 889 bool require_drop_property = false); 890 } // end namespace suppr 891 892 893 } // end namespace abigail 894 895 #endif //__ABG_SUPPRESSION_H__ 896