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