abixml-reader: Support SONAME related properties on file suppression
authorDodji Seketeli <dodji@redhat.com>
Fri, 21 Feb 2020 11:32:42 +0000 (12:32 +0100)
committerDodji Seketeli <dodji@redhat.com>
Fri, 21 Feb 2020 15:01:26 +0000 (16:01 +0100)
When comparing binary files (using abidiff for instance) libabigail
can interpret the [suppress_file] section of a suppression
specification.  If the suppression specification matches either of the
compared files, no comparison is performed.

At the moment, that doesn't work when comparing abixml files.

Thus, this patch implements that feature for abixml files.

With this patch, one can now write a suppression specification like
this:

  [suppress_file]
    soname_regexp = <some-regexp>

or

  [suppress_file]
    file_name_regexp = <some-regexp>

If either abixml file has a soname matched by such a regexp, then no
comparison is performed.

* doc/manuals/libabigail-concepts.rst: Update the documentation to
mention soname_regexp and soname_not_regexp is supported in the
[suppress_file] section.
* include/abg-suppression.h (suppression_matches_soname)
(suppression_matches_soname_or_filename): Declare new functions.
Make them be friends of class suppression_base.
* src/abg-reader.cc
(read_context::corpus_is_suppressed_by_soname_or_filename): Define
new member function.
(read_corpus_from_input): Apply file suppression.
* src/abg-suppression.cc (read_file_suppression): Support
"soname_regexp" and "soname_not_regexp" in the [suppress_file]
section.
(suppression_matches_soname)
(suppression_matches_soname_or_filename): Define new functions.
* tests/data/test-diff-suppr/libtest48-soname-abixml-report-{1,2}.txt:
New test reference output files.
Likewise.
* tests/data/test-diff-suppr/libtest48-soname-abixml-suppr.txt:
New test suppression file.
* tests/data/test-diff-suppr/libtest48-soname-abixml-suppr-{2,3,4}.txt::
Likewise.
* tests/data/test-diff-suppr/libtest48-soname-abixml-v{0,1}.so: New
test binary input files.
* tests/data/test-diff-suppr/libtest48-soname-abixml-v{0,1}.so.abi:
New abixml for the binary input files above.
* tests/data/test-diff-suppr/test48-soname-abixml-v{0,1}.c: Source
code of the binary input files above.
* tests/data/Makefile.am: Add the above test material to source
distribution.
* tests/test-diff-suppr.cc (in_out_specs): Add the test input
above to this test harness.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
18 files changed:
doc/manuals/libabigail-concepts.rst
include/abg-suppression.h
src/abg-reader.cc
src/abg-suppression.cc
tests/data/Makefile.am
tests/data/test-diff-suppr/libtest48-soname-abixml-report-1.txt [new file with mode: 0644]
tests/data/test-diff-suppr/libtest48-soname-abixml-report-2.txt [new file with mode: 0644]
tests/data/test-diff-suppr/libtest48-soname-abixml-suppr-2.txt [new file with mode: 0644]
tests/data/test-diff-suppr/libtest48-soname-abixml-suppr-3.txt [new file with mode: 0644]
tests/data/test-diff-suppr/libtest48-soname-abixml-suppr-4.txt [new file with mode: 0644]
tests/data/test-diff-suppr/libtest48-soname-abixml-suppr.txt [new file with mode: 0644]
tests/data/test-diff-suppr/libtest48-soname-abixml-v0.so [new file with mode: 0755]
tests/data/test-diff-suppr/libtest48-soname-abixml-v0.so.abi [new file with mode: 0644]
tests/data/test-diff-suppr/libtest48-soname-abixml-v1.so [new file with mode: 0755]
tests/data/test-diff-suppr/libtest48-soname-abixml-v1.so.abi [new file with mode: 0644]
tests/data/test-diff-suppr/test48-soname-abixml-v0.c [new file with mode: 0644]
tests/data/test-diff-suppr/test48-soname-abixml-v1.c [new file with mode: 0644]
tests/test-diff-suppr.cc

index 6565d30b8c07b6fa0378d2c3ef8dfb9c4ce758ac..607edee68e408e5051071f0e744e61476124abca 100644 (file)
@@ -197,10 +197,10 @@ suppress ABI change reports for a particular kind of ABI artifact.
 $$$$$$$$$$$$$$$$$$$
 
 This directive prevents a given tool from loading a file (binary or
-not) if its file name matches certain properties.  Thus, if the tool
-is meant to compare the ABIs of two files, and if the directive
-prevents it from loading either one of the files, then no comparison
-is performed.
+abixml file) if its file name or other properties match certain
+properties.  Thus, if the tool is meant to compare the ABIs of two
+files, and if the directive prevents it from loading either one of the
+files, then no comparison is performed.
 
 Note that for the ``[suppress_file]`` directive to work, at least one
 of the following properties must be provided:
@@ -228,6 +228,28 @@ The potential properties of this sections are listed below:
   the regular expression specified as value of this property.
 
 
+* ``soname_regexp``
+
+  Usage:
+
+    ``soname_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>
+
+  Prevents the system from loading the file which contains a SONAME
+  property that matches the regular expression of this property.  Note
+  that this property also works on an abixml file if it contains a
+  SONAME property.
+
+* ``soname_not_regexp``
+
+  Usage:
+
+    ``soname_not_regexp`` ``=`` <:ref:`regular-expression <suppr_regexp_label>`>
+
+  Prevents the system from loading the file which contains a SONAME
+  property that does *NOT* match the regular expression of this
+  property.  Note that this property also works on an abixml file if
+  it contains a SONAME property.
+
 * ``label``
 
  Usage:
index 05709d69f096122e6a5dd1f2b395f26dbd1be463..1ccb77624eaaef77b2cb2983da57a27db414617e 100644 (file)
@@ -119,6 +119,15 @@ public:
   suppresses_diff(const diff*) const = 0;
 
   virtual ~suppression_base();
+
+  friend bool
+  suppression_matches_soname(const string& soname,
+                            const suppression_base& suppr);
+
+  friend bool
+  suppression_matches_soname_or_filename(const string& soname,
+                                        const string& filename,
+                                        const suppression_base& suppr);
 }; // end class suppression_base
 
 void
@@ -826,6 +835,15 @@ file_suppression_sptr
 file_is_suppressed(const string& file_path,
                   const suppressions_type& suppressions);
 
+bool
+suppression_matches_soname(const string& soname,
+                          const suppression_base& suppr);
+
+bool
+suppression_matches_soname_or_filename(const string& soname,
+                                      const string& filename,
+                                      const suppression_base& suppr);
+
 const char*
 get_private_types_suppr_spec_label();
 
index 7c8a56a9b4c5ce762ceacbccadd54a7f5ab2947d..915b2c1370f6c50bf7732764ae03c1b030ddb729 100644 (file)
@@ -794,6 +794,35 @@ public:
   get_suppressions() const
   {return const_cast<read_context*>(this)->get_suppressions();}
 
+  /// Test if there are suppression specifications (associated to the
+  /// current corpus) that match a given SONAME or file name.
+  ///
+  /// @param soname the SONAME to consider.
+  ///
+  /// @param the file name to consider.
+  ///
+  /// @return true iff there are suppression specifications (associated to the
+  /// current corpus) that match the SONAME denoted by @p soname or
+  /// the file name denoted by @p filename.
+  bool
+  corpus_is_suppressed_by_soname_or_filename(const string& soname,
+                                            const string& filename)
+  {
+    using suppr::suppressions_type;
+    using suppr::file_suppression_sptr;
+    using suppr::is_file_suppression;
+
+    for (suppressions_type::const_iterator s = get_suppressions().begin();
+        s != get_suppressions().end();
+        ++s)
+      if (file_suppression_sptr suppr = is_file_suppression(*s))
+       if (suppr::suppression_matches_soname_or_filename(soname, filename,
+                                                         *suppr))
+         return true;
+
+    return false;
+  }
+
   /// Add a given function to the set of exported functions of the
   /// current corpus, if the function satisfies the different
   /// constraints requirements.
@@ -1860,8 +1889,13 @@ read_corpus_from_input(read_context& ctxt)
       ctxt.set_exported_decls_builder(corp.get_exported_decls_builder().get());
 
       xml::xml_char_sptr path_str = XML_READER_GET_ATTRIBUTE(reader, "path");
+      string path;
+
       if (path_str)
-       corp.set_path(reinterpret_cast<char*>(path_str.get()));
+       {
+         path = reinterpret_cast<char*>(path_str.get());
+         corp.set_path(path);
+       }
 
       xml::xml_char_sptr architecture_str =
        XML_READER_GET_ATTRIBUTE(reader, "architecture");
@@ -1871,8 +1905,24 @@ read_corpus_from_input(read_context& ctxt)
 
       xml::xml_char_sptr soname_str =
        XML_READER_GET_ATTRIBUTE(reader, "soname");
+      string soname;
+
       if (soname_str)
-       corp.set_soname(reinterpret_cast<char*>(soname_str.get()));
+       {
+         soname = reinterpret_cast<char*>(soname_str.get());
+         corp.set_soname(soname);
+       }
+
+      // Apply suppression specifications here to honour:
+      //
+      //   [suppress_file]
+      //     (soname_regexp
+      //      |soname_not_regexp
+      //      |file_name_regexp
+      //      |file_name_not_regexp) = <soname-or-file-name>
+      if ((!soname.empty() || !path.empty())
+         && ctxt.corpus_is_suppressed_by_soname_or_filename(soname, path))
+       return nil;
 
       node = xmlTextReaderExpand(reader.get());
       if (!node)
index 663749db51dd5f9aa15ed3aedce3ad62d38f8d2a..91286f25e39b7fec8841ac15247e9447a41b9c3c 100644 (file)
@@ -4335,14 +4335,39 @@ read_file_suppression(const ini::config::section& section)
     ? file_name_not_regex_prop->get_value()->as_string()
     : "";
 
+  ini::simple_property_sptr soname_regex_prop =
+    is_simple_property(section.find_property("soname_regexp"));
+  string soname_regex_str =
+    soname_regex_prop ? soname_regex_prop->get_value()->as_string() : "";
+
+  ini::simple_property_sptr soname_not_regex_prop =
+    is_simple_property(section.find_property("soname_not_regexp"));
+  string soname_not_regex_str =
+    soname_not_regex_prop
+    ? soname_not_regex_prop->get_value()->as_string()
+    : "";
+
   if (file_name_regex_str.empty()
-      && file_name_not_regex_str.empty())
+      && file_name_not_regex_str.empty()
+      && soname_regex_str.empty()
+      && soname_not_regex_str.empty())
     return result;
-
   result.reset(new file_suppression(label_str,
                                    file_name_regex_str,
                                    file_name_not_regex_str));
 
+  if (!soname_regex_str.empty())
+    {
+      result->set_soname_regex_str(soname_regex_str);
+      result->set_drops_artifact_from_ir(true);
+    }
+
+  if (!soname_not_regex_str.empty())
+    {
+      result->set_soname_not_regex_str(soname_not_regex_str);
+      result->set_drops_artifact_from_ir(true);
+    }
+
   return result;
 }
 
@@ -4382,6 +4407,42 @@ file_is_suppressed(const string& file_path,
   return file_suppression_sptr();
 }
 
+/// Test if a given SONAME is matched by a given suppression
+/// specification.
+///
+/// @param soname the SONAME to consider.
+///
+/// @param suppr the suppression specification to consider.
+///
+/// @return true iff a given SONAME is matched by a given suppression
+/// specification.
+bool
+suppression_matches_soname(const string& soname,
+                          const suppression_base& suppr)
+{
+  return suppr.priv_->matches_soname(soname);
+}
+
+/// Test if a given SONAME or file name is matched by a given
+/// suppression specification.
+///
+/// @param soname the SONAME to consider.
+///
+/// @param filename the file name to consider.
+///
+/// @param suppr the suppression specification to consider.
+///
+/// @return true iff either @p soname or @p filename is matched by the
+/// suppression specification @p suppr.
+bool
+suppression_matches_soname_or_filename(const string& soname,
+                                      const string& filename,
+                                      const suppression_base& suppr)
+{
+  return (suppression_matches_soname(soname, suppr)
+        || suppr.priv_->matches_binary_name(filename));
+}
+
 /// @return the name of the artificial private type suppression
 /// specification that is auto-generated by libabigail to suppress
 /// change reports about types that are not defined in public headers.
index a38fadfd36ca7ac92524ff8e96c181bf22bd2c28..5031e6d3279d988767f9e48772a9f783124fdc2a 100644 (file)
@@ -1273,6 +1273,18 @@ test-diff-suppr/test47-non-reachable-types-v1.o \
 test-diff-suppr/test47-non-reachable-types-v0.o.alltypes.abixml \
 test-diff-suppr/test47-non-reachable-types-v1.o.alltypes.abixml \
 test-diff-suppr/test47-non-reachable-types-report-10.txt \
+test-diff-suppr/libtest48-soname-abixml-v0.so \
+test-diff-suppr/libtest48-soname-abixml-v0.so.abi \
+test-diff-suppr/libtest48-soname-abixml-v1.so \
+test-diff-suppr/libtest48-soname-abixml-v1.so.abi \
+test-diff-suppr/test48-soname-abixml-v0.c \
+test-diff-suppr/test48-soname-abixml-v1.c \
+test-diff-suppr/libtest48-soname-abixml-report-1.txt \
+test-diff-suppr/libtest48-soname-abixml-report-2.txt \
+test-diff-suppr/libtest48-soname-abixml-suppr.txt \
+test-diff-suppr/libtest48-soname-abixml-suppr-2.txt \
+test-diff-suppr/libtest48-soname-abixml-suppr-3.txt \
+test-diff-suppr/libtest48-soname-abixml-suppr-4.txt \
 \
 test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1 \
 test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1.abi \
diff --git a/tests/data/test-diff-suppr/libtest48-soname-abixml-report-1.txt b/tests/data/test-diff-suppr/libtest48-soname-abixml-report-1.txt
new file mode 100644 (file)
index 0000000..9ba2b12
--- /dev/null
@@ -0,0 +1,16 @@
+ELF SONAME changed
+Functions changes summary: 0 Removed, 1 Changed, 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
+SONAME changed from 'test48-soname-abixml-v0' to 'test48-soname-abixml-v1'
+
+1 function with some indirect sub-type change:
+
+  [C]'function void foo(S*)' at test48-soname-abixml-v1.c:8:1 has some indirect sub-type changes:
+    parameter 1 of type 'S*' has sub-type changes:
+      in pointed to type 'struct S' at test48-soname-abixml-v1.c:1:1:
+        type size changed from 32 to 64 (in bits)
+        1 data member insertion:
+          'char S::m1', at offset 32 (in bits) at test48-soname-abixml-v1.c:4:1
+
+
diff --git a/tests/data/test-diff-suppr/libtest48-soname-abixml-report-2.txt b/tests/data/test-diff-suppr/libtest48-soname-abixml-report-2.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/data/test-diff-suppr/libtest48-soname-abixml-suppr-2.txt b/tests/data/test-diff-suppr/libtest48-soname-abixml-suppr-2.txt
new file mode 100644 (file)
index 0000000..c9b7ad4
--- /dev/null
@@ -0,0 +1,2 @@
+[suppress_file]
+  soname_regexp = test48<typo>-soname-abixml-v.*
diff --git a/tests/data/test-diff-suppr/libtest48-soname-abixml-suppr-3.txt b/tests/data/test-diff-suppr/libtest48-soname-abixml-suppr-3.txt
new file mode 100644 (file)
index 0000000..c69c250
--- /dev/null
@@ -0,0 +1,2 @@
+[suppress_file]
+  file_name_regexp = ^libtest48-soname-abixml-v.*$
diff --git a/tests/data/test-diff-suppr/libtest48-soname-abixml-suppr-4.txt b/tests/data/test-diff-suppr/libtest48-soname-abixml-suppr-4.txt
new file mode 100644 (file)
index 0000000..1a20527
--- /dev/null
@@ -0,0 +1,2 @@
+[suppress_file]
+  file_name_regexp = ^libtest48<typo>-soname-abixml-v.*$
diff --git a/tests/data/test-diff-suppr/libtest48-soname-abixml-suppr.txt b/tests/data/test-diff-suppr/libtest48-soname-abixml-suppr.txt
new file mode 100644 (file)
index 0000000..08d61c0
--- /dev/null
@@ -0,0 +1,2 @@
+[suppress_file]
+  soname_regexp = test48-soname-abixml-v.*
diff --git a/tests/data/test-diff-suppr/libtest48-soname-abixml-v0.so b/tests/data/test-diff-suppr/libtest48-soname-abixml-v0.so
new file mode 100755 (executable)
index 0000000..e805adf
Binary files /dev/null and b/tests/data/test-diff-suppr/libtest48-soname-abixml-v0.so differ
diff --git a/tests/data/test-diff-suppr/libtest48-soname-abixml-v0.so.abi b/tests/data/test-diff-suppr/libtest48-soname-abixml-v0.so.abi
new file mode 100644 (file)
index 0000000..f9fa8e5
--- /dev/null
@@ -0,0 +1,24 @@
+<abi-corpus path='libtest48-soname-abixml-v0.so' architecture='elf-amd-x86_64' soname='test48-soname-abixml-v0'>
+  <elf-needed>
+    <dependency name='libc.so.6'/>
+  </elf-needed>
+  <elf-function-symbols>
+    <elf-symbol name='_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr version='1.0' address-size='64' path='test48-soname-abixml-v0.c' comp-dir-path='/home/dodji/git/libabigail/suppress-file-abixml/tests/data/test-diff-suppr' language='LANG_C99'>
+    <type-decl name='int' size-in-bits='32' id='type-id-1'/>
+    <type-decl name='void' id='type-id-2'/>
+    <class-decl name='S' size-in-bits='32' is-struct='yes' visibility='default' filepath='/home/dodji/git/libabigail/suppress-file-abixml/tests/data/test-diff-suppr/test48-soname-abixml-v0.c' line='1' column='1' id='type-id-3'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m0' type-id='type-id-1' visibility='default' filepath='/home/dodji/git/libabigail/suppress-file-abixml/tests/data/test-diff-suppr/test48-soname-abixml-v0.c' line='3' column='1'/>
+      </data-member>
+    </class-decl>
+    <pointer-type-def type-id='type-id-3' size-in-bits='64' id='type-id-4'/>
+    <function-decl name='foo' mangled-name='foo' filepath='/home/dodji/git/libabigail/suppress-file-abixml/tests/data/test-diff-suppr/test48-soname-abixml-v0.c' line='7' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
+      <parameter type-id='type-id-4' name='a' filepath='/home/dodji/git/libabigail/suppress-file-abixml/tests/data/test-diff-suppr/test48-soname-abixml-v0.c' line='7' column='1'/>
+      <return type-id='type-id-2'/>
+    </function-decl>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-diff-suppr/libtest48-soname-abixml-v1.so b/tests/data/test-diff-suppr/libtest48-soname-abixml-v1.so
new file mode 100755 (executable)
index 0000000..a10a9f8
Binary files /dev/null and b/tests/data/test-diff-suppr/libtest48-soname-abixml-v1.so differ
diff --git a/tests/data/test-diff-suppr/libtest48-soname-abixml-v1.so.abi b/tests/data/test-diff-suppr/libtest48-soname-abixml-v1.so.abi
new file mode 100644 (file)
index 0000000..060ceb4
--- /dev/null
@@ -0,0 +1,28 @@
+<abi-corpus path='libtest48-soname-abixml-v1.so' architecture='elf-amd-x86_64' soname='test48-soname-abixml-v1'>
+  <elf-needed>
+    <dependency name='libc.so.6'/>
+  </elf-needed>
+  <elf-function-symbols>
+    <elf-symbol name='_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+  </elf-function-symbols>
+  <abi-instr version='1.0' address-size='64' path='test48-soname-abixml-v1.c' comp-dir-path='/home/dodji/git/libabigail/suppress-file-abixml/tests/data/test-diff-suppr' language='LANG_C99'>
+    <type-decl name='char' size-in-bits='8' id='type-id-1'/>
+    <type-decl name='int' size-in-bits='32' id='type-id-2'/>
+    <type-decl name='void' id='type-id-3'/>
+    <class-decl name='S' size-in-bits='64' is-struct='yes' visibility='default' filepath='/home/dodji/git/libabigail/suppress-file-abixml/tests/data/test-diff-suppr/test48-soname-abixml-v1.c' line='1' column='1' id='type-id-4'>
+      <data-member access='public' layout-offset-in-bits='0'>
+        <var-decl name='m0' type-id='type-id-2' visibility='default' filepath='/home/dodji/git/libabigail/suppress-file-abixml/tests/data/test-diff-suppr/test48-soname-abixml-v1.c' line='3' column='1'/>
+      </data-member>
+      <data-member access='public' layout-offset-in-bits='32'>
+        <var-decl name='m1' type-id='type-id-1' visibility='default' filepath='/home/dodji/git/libabigail/suppress-file-abixml/tests/data/test-diff-suppr/test48-soname-abixml-v1.c' line='4' column='1'/>
+      </data-member>
+    </class-decl>
+    <pointer-type-def type-id='type-id-4' size-in-bits='64' id='type-id-5'/>
+    <function-decl name='foo' mangled-name='foo' filepath='/home/dodji/git/libabigail/suppress-file-abixml/tests/data/test-diff-suppr/test48-soname-abixml-v1.c' line='8' column='1' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='foo'>
+      <parameter type-id='type-id-5' name='a' filepath='/home/dodji/git/libabigail/suppress-file-abixml/tests/data/test-diff-suppr/test48-soname-abixml-v1.c' line='8' column='1'/>
+      <return type-id='type-id-3'/>
+    </function-decl>
+  </abi-instr>
+</abi-corpus>
diff --git a/tests/data/test-diff-suppr/test48-soname-abixml-v0.c b/tests/data/test-diff-suppr/test48-soname-abixml-v0.c
new file mode 100644 (file)
index 0000000..3ea3ca7
--- /dev/null
@@ -0,0 +1,8 @@
+struct S
+{
+  int m0;
+};
+
+void
+foo(struct S *a __attribute__((unused)))
+{}
diff --git a/tests/data/test-diff-suppr/test48-soname-abixml-v1.c b/tests/data/test-diff-suppr/test48-soname-abixml-v1.c
new file mode 100644 (file)
index 0000000..fc74925
--- /dev/null
@@ -0,0 +1,9 @@
+struct S
+{
+  int m0;
+  char m1;
+};
+
+void
+foo(struct S *a __attribute__((unused)))
+{}
index b513a4b4180b98f4e42cdd551cf6d2bb9d4bbaed..26de00903fc67a4d526e807c10adc08e4395a162 100644 (file)
@@ -1958,6 +1958,56 @@ InOutSpec in_out_specs[] =
     "data/test-diff-suppr/test47-non-reachable-types-report-10.txt",
     "output/test-diff-suppr/test47-non-reachable-types-report-10.txt"
   },
+  {
+    "data/test-diff-suppr/libtest48-soname-abixml-v0.so",
+    "data/test-diff-suppr/libtest48-soname-abixml-v1.so.abi",
+    "",
+    "",
+    "",
+    "--no-default-suppression",
+    "data/test-diff-suppr/libtest48-soname-abixml-report-1.txt",
+    "output/test-diff-suppr/libtest48-soname-abixml-report-1.txt"
+  },
+  {
+    "data/test-diff-suppr/libtest48-soname-abixml-v0.so",
+    "data/test-diff-suppr/libtest48-soname-abixml-v1.so.abi",
+    "",
+    "",
+    "data/test-diff-suppr/libtest48-soname-abixml-suppr.txt",
+    "--no-default-suppression",
+    "data/test-diff-suppr/libtest48-soname-abixml-report-2.txt",
+    "output/test-diff-suppr/libtest48-soname-abixml-report-2.txt"
+  },
+  {
+    "data/test-diff-suppr/libtest48-soname-abixml-v0.so",
+    "data/test-diff-suppr/libtest48-soname-abixml-v1.so.abi",
+    "",
+    "",
+    "data/test-diff-suppr/libtest48-soname-abixml-suppr-2.txt",
+    "--no-default-suppression",
+    "data/test-diff-suppr/libtest48-soname-abixml-report-1.txt",
+    "output/test-diff-suppr/libtest48-soname-abixml-report-1.txt"
+  },
+  {
+    "data/test-diff-suppr/libtest48-soname-abixml-v0.so",
+    "data/test-diff-suppr/libtest48-soname-abixml-v1.so.abi",
+    "",
+    "",
+    "data/test-diff-suppr/libtest48-soname-abixml-suppr-3.txt",
+    "--no-default-suppression",
+    "data/test-diff-suppr/libtest48-soname-abixml-report-2.txt",
+    "output/test-diff-suppr/libtest48-soname-abixml-report-2.txt"
+  },
+  {
+    "data/test-diff-suppr/libtest48-soname-abixml-v0.so",
+    "data/test-diff-suppr/libtest48-soname-abixml-v1.so.abi",
+    "",
+    "",
+    "data/test-diff-suppr/libtest48-soname-abixml-suppr-4.txt",
+    "--no-default-suppression",
+    "data/test-diff-suppr/libtest48-soname-abixml-report-1.txt",
+    "output/test-diff-suppr/libtest48-soname-abixml-report-1.txt"
+  },
   // This should be the last entry
   {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
 };