Make abi{pkg}diff filter out changes about private types

This is to address the following enhancement requests:

    #19588 - Add a --headers-dir1 and --headers-dir2 option to abidiff
    #19948 - Add --devel-pkg1 and --devel-pkg2 options to abipkgdiff

When the user specifies where to find header files for two binaries
(or packages) being compared, this patch generates a type suppression
specification that filters out change reports about types that are
defined in files that are not in the set of header files specified.

The type suppression specification also suppresses change reports
about changed/added/removed virtual member functions which enclosing
class type matches the type suppression specification.

There is a corner case that the patch handles too, and that is
exhibited by the accompanying test case for abidiff.  There can be a
class defined by DWARF as having no source location and as being a
pure declaration.  This can be a class declaration that has inline
virtual members only, and one or several non-defined virtual methods
too.  When that declaration is included in a source file, GCC
generates debug info that describes that class as being a
declaration-only class with no source declaration.  This patch
considers such a class as being non defined; you know, like a true
opaque type.  So it's considered being not defined in any public
header file.  Changes to this kind of class are thus filtered out.

	* include/abg-comp-filter.h: Update copyright year.
	* src/abg-comp-filter.cc (has_virtual_mem_fn_change): Make this
	static function become exported.
	(has_virtual_mem_fn_change): Declare new function.
	* include/abg-suppression.h
	(suppression_base::{get,set}_is_artificial): Declare new
	accessors.
	(type_suppression::get_source_locations_to_keep): Return an
	unordered set of strings, not a vector.  Add a non-const overload.
	(type_suppression::set_source_locations_to_keep): Set an unordered
	set of strings, not a vector.
	* src/abg-suppression.cc (suppression_base::priv::is_artificial_):
	New data member.
	(suppression_base::priv::priv): Initialize the new data member.
	(suppression_base::{get,set}_is_artificial): Define new accessors.
	(type_suppression::priv::source_locations_to_keep_): Change the
	vector of strings representing source file names into unordered
	set of string.
	(type_suppression::get_source_locations_to_keep): Return an
	unordered set of strings, not a vector.  Define a non-const
	overload.
	(type_suppression::set_source_locations_to_keep): Set an unordered
	set of strings, not a vector.
	(type_suppression::suppresses_diff): Make this suppress virtual
	member function diffs if the enclosing type of the changed virtual
	member is suppressed by the current type_suppression.
	(read_type_suppression): Adjust to use the fact that the source
	locations are not stored in an unordered set, not in a vector
	anymore.  Otherwise, using a vector here make things too slow.
	(type_suppression::suppresses_type): Likewise.  Also, If the type
	we are looking at has no location because it's a true opaque type
	and if the current suppression is an artificial suppression that
	is meant to suppress change reports about non-public types, then
	suppress the type.
	* include/abg-tools-utils.h (gen_suppr_spec_from_headers): Declare
	new public function.
	* src/abg-tools-utils.cc (PRIVATE_TYPES_SUPPR_SPEC_NAME): Define a
	new constant variable.
	(handle_fts_entry): Define new static function.
	(gen_suppr_spec_from_headers): Define new public function.
	* src/abg-comparison.cc
	(corpus_diff::priv::apply_suppressions_to_added_removed_fns_vars):
	If a type suppression suppresses a given class C, make it change
	added/removed virtual functions whose enclosing type is C.
	* tools/abidiff.cc (options::{headers_dir1, headers_dir2}): New
	data members.
	(display_usage): Add help strings for --headers-dir1 and
	--headers-dir2.
	(parse_command_line): Parse the new --headers-dir1 and
	--headers-dir2 options.
	(set_diff_context_from_opts): Generate suppression specifications
	to filter out changes on private types, if --headers-dir1 or
	--headers-dir2 is given.
	* tools/abipkgdiff.cc (options::{devel_package1, devel_package2}):
	New data members.
	(typedef package_sptr): New typedef.
	(enum package::kind): New enum.
	(package::kind_): New data member.  This replaces ...
	(package::is_debug_info_): ... this data member.
	(package::{devel_package_, private_types_suppressions_}): New data
	members.
	(package::package): Adjust.
	(package::get_kind): Define new member function.  This replaces
	...
	(package::is_debug_info): ... this member function overload.
	(package::set_kind): Define new member functin.  It replaces ...
	(package::is_debug_info): ... this member function overload.
	(package::{devel_package, private_types_suppressions}): Define new
	accessors.
	(package::erase_extraction_directies): Erase the sub-directory
	where development packages are extracted to.
	(compare_args::private_types_suppr{1,2}): New data members.
	(compare_args::compare_args): Adjust.
	(display_usage): Add help strings for --devel-pkg1/--devel-pkg2.
	(compare): Make the overload that compares elf files take private
	types suppressions.  Add the private types suppressions to the
	diff context.
	(pthread_routine_compare): Adjust the call to compare.
	(maybe_create_private_types_suppressions): Define new static
	function.
	(pthread_routine_extract_pkg_and_map_its_content): If a devel
	package was specified for the main package then extract it in
	parallel with the other package extraction.  When the extraction
	is done, create private types suppressions by visiting the
	directories that contain the header files.
	(compare): In the overload that compares packages by scheduling
	comparison of individual elf files that are in the packages, pass
	in the private type suppressions too.
	(parse_command_line): Parse the new --devel-pkg{1,2} command line
	options.
	(main): Associate the devel package to the main package, if the
	--devel-pkg{1,2}.
	* doc/manuals/abidiff.rst: Add documentation about the new
	--headers-dir1 and --headers-dir2 options.
	* doc/manuals/abipkgdiff.rst: Likewise, add documentation about
	the new --devel-pkg1 and --devel-pkg2 libraries.
	* tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt:
	New test reference output.
	* tests/data/test-diff-pkg/tbb-devel-4.1-9.20130314.fc22.x86_64.rpm:
	New test input package.
	* tests/data/test-diff-pkg/tbb-devel-4.3-3.20141204.fc23.x86_64.rpm: Likewise.
	* tests/test-diff-pkg.cc b/tests/test-diff-pkg.cc
	(InOutSpec::{first,second}_in_devel_package_path): New data
	members.
	(in_out_specs): Adjust.  Also, add a new entry describing the new
	test inputs above.
	(test_task::perform): When the new test entry contains devel
	packages, pass them to abipkgdiff using the --devel1 and --devel2
	options.
	* tests/data/test-diff-suppr/test30-include-dir-v0/test30-pub-lib-v0.h:
	A new test input source code.
	* tests/data/test-diff-suppr/test30-include-dir-v1/test30-pub-lib-v1.h: Likewise.
	* tests/data/test-diff-suppr/test30-priv-lib-v0.cc: Likewise.
	* tests/data/test-diff-suppr/test30-priv-lib-v0.h: Likewise.
	* tests/data/test-diff-suppr/test30-priv-lib-v1.cc: Likewise.
	* tests/data/test-diff-suppr/test30-priv-lib-v1.h: Likewise.
	* tests/data/test-diff-suppr/test30-pub-lib-v0.cc: Likewise.
	* tests/data/test-diff-suppr/test30-pub-lib-v0.so: Add new test
	binary input.
	* tests/data/test-diff-suppr/test30-pub-lib-v1.cc: Add new test
	input source code.
	* tests/data/test-diff-suppr/test30-pub-lib-v1.so: Add new test
	binary input.
	* tests/data/test-diff-suppr/test30-report-0.txt: Add new test
	reference output.
	* tests/data/test-diff-suppr/test30-report-1.txt: Add new test
	reference output.
	* tests/test-diff-suppr.cc (InOutSpec::headers_dir{1,2}): New data
	members.
	(InOutSpec::abidiff_options): Renamed the bidiff_options data
	member into this.
	(in_out_specs): Adjust.  Also, added the new test input above to
	this.
	(main): Adjust to invoke abidiff with the new --hd1 and --hd2
	options if the input specs for the tests has the new
	InOutSpec::headers_dir{1,2} data member set.  Renamed bidiff into
	abidiff.
	* tests/data/Makefile.am: Add the new test inputs to the source
	distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2016-05-20 09:19:51 +02:00
parent 3f1d7c3976
commit e19bf5627a
29 changed files with 1401 additions and 110 deletions

View File

@ -57,6 +57,18 @@ Options
to find the split debug information for the
*second-shared-library* file.
* ``--headers-dir1 | --hd1`` <headers-directory-path-1>
Specifies where to find the public headers of the first shared
library that the tool has to consider. The tool will thus filter
out ABI changes on types that are not defined in public headers.
* ``--headers-dir2 | --hd2`` <headers-directory-path-1>
Specifies where to find the public headers of the second shared
library that the tool has to consider. The tool will thus filter
out ABI changes on types that are not defined in public headers.
* ``--stat``
Rather than displaying the detailed ABI differences between

View File

@ -15,12 +15,6 @@ function and variable sub-types, the two input packages must be
accompanied with their debug information packages that contain debug
information in `DWARF`_ format.
.. _ELF: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
.. _RPM: https://en.wikipedia.org/wiki/RPM_Package_Manager
.. _Deb: https://en.wikipedia.org/wiki/Deb_%28file_format%29
.. _tar: https://en.wikipedia.org/wiki/Tar_%28computing%29
.. _DWARF: http://www.dwarfstd.org
.. _abipkgdiff_invocation_label:
@ -31,6 +25,9 @@ Invocation
abipkgdiff [option] <package1> <package2>
``package1`` and ``package2`` are the packages that contain the
binaries to be compared.
.. _abipkgdiff_options_label:
Options
@ -56,6 +53,26 @@ Options
into a separate file, tells ``abipkgdiff`` where to find that
separate debug information package.
* ``--devel-pkg1 | --devel1`` <path>
Specifies where to find the `Development Package`_ associated with
the first package to be compared. That `Development Package`_ at
``path`` should at least contain header files in which public
types exposed by the libraries (of the first package to be
compared) are defined. When this option is provided, the tool
filters out reports about ABI changes to types that are *NOT*
defined in these header files.
* ``--devel-pkg2 | --devel2`` <path>
Specifies where to find the `Development Package`_ associated with
the second package to be compared. That `Development Package`_ at
``path`` should at least contains header files in which public
types exposed by the libraries (of the second package to be
compared) are defined. When this option is provided, the tool
filters out reports about ABI changes to types that are *NOT*
defined in these header files.
* ``--dso-only``
Compare ELF files that are shared libraries, only. Do not compare
@ -145,3 +162,10 @@ tool encountered an error.
In the later case, the value of the exit code is the same as for the
:ref:`abidiff tool <abidiff_return_value_label>`.
.. _ELF: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
.. _RPM: https://en.wikipedia.org/wiki/RPM_Package_Manager
.. _Deb: https://en.wikipedia.org/wiki/Deb_%28file_format%29
.. _tar: https://en.wikipedia.org/wiki/Tar_%28computing%29
.. _DWARF: http://www.dwarfstd.org
.. _Development Package: https://fedoraproject.org/wiki/Packaging:Guidelines?rd=Packaging/Guidelines#Devel_Packages

View File

@ -1,6 +1,6 @@
// -*- Mode: C++ -*-
//
// Copyright (C) 2013-2015 Red Hat, Inc.
// Copyright (C) 2013-2016 Red Hat, Inc.
//
// This file is part of the GNU Application Binary Interface Generic
// Analysis and Instrumentation Library (libabigail). This library is
@ -42,6 +42,9 @@ namespace filtering
bool
has_harmless_name_change(decl_base_sptr f, decl_base_sptr s);
bool
has_virtual_mem_fn_change(const function_decl_diff* diff);
class filter_base;
/// Convenience typedef for a shared pointer to filter_base
typedef shared_ptr<filter_base> filter_base_sptr;

View File

@ -23,6 +23,7 @@
#ifndef __ABG_SUPPRESSION_H__
#define __ABG_SUPPRESSION_H__
#include <tr1/unordered_set>
#include "abg-ini.h"
#include "abg-comparison.h"
@ -42,6 +43,7 @@ namespace suppr
{
using namespace abigail::comparison;
using std::tr1::unordered_set;
/// Base type of the suppression specifications types.
///
@ -66,6 +68,12 @@ public:
const string& file_name_regex_str,
const string& file_name_not_regex_str);
bool
get_is_artificial() const;
void
set_is_artificial(bool);
const string
get_label() const;
@ -230,11 +238,14 @@ public:
insertion_ranges&
get_data_member_insertion_ranges();
const vector<string>&
const unordered_set<string>&
get_source_locations_to_keep() const;
unordered_set<string>&
get_source_locations_to_keep();
void
set_source_locations_to_keep(const vector<string>&);
set_source_locations_to_keep(const unordered_set<string>&);
const string&
get_source_location_to_keep_regex_str() const;

View File

@ -25,6 +25,7 @@
#include <ostream>
#include <istream>
#include <iostream>
#include <abg-suppression.h>
namespace abigail
{
@ -54,6 +55,8 @@ bool check_file(const string& path, ostream& out, const string& prog_name = "");
bool string_ends_with(const string&, const string&);
bool string_is_ascii(const string&);
bool string_is_ascii_identifier(const string&);
suppr::type_suppression_sptr
gen_suppr_spec_from_headers(const string& hdrs_root_dir);
class temp_file;
@ -192,5 +195,7 @@ file_type guess_file_type(const string& file_path);
std::tr1::shared_ptr<char>
make_path_absolute(const char*p);
extern const char* PRIVATE_TYPES_SUPPR_SPEC_NAME;
}// end namespace tools_utils
}//end namespace abigail

View File

@ -600,7 +600,7 @@ has_virtual_mem_fn_change(const class_diff* diff)
///
/// @return true iff the function_decl_diff node contains changes
/// involving virtual member functions.
static bool
bool
has_virtual_mem_fn_change(const function_decl_diff* diff)
{
if (!diff)

View File

@ -10345,6 +10345,40 @@ corpus_diff::priv::apply_suppressions_to_added_removed_fns_vars()
ctxt))
suppressed_deleted_unrefed_fn_syms_[e->first] = e->second;
}
// Added/Delete virtual member functions changes that might be
// suppressed by a type_suppression that matches the enclosing
// class of the virtual member function.
else if (type_suppression_sptr type_suppr = is_type_suppression(*i))
{
// Added virtual functions
for (string_function_ptr_map::const_iterator e = added_fns_.begin();
e != added_fns_.end();
++e)
if (is_member_function(e->second)
&& get_member_function_is_virtual(e->second))
{
function_decl *f = e->second;
class_decl_sptr c =
is_method_type(f->get_type())->get_class_type();
assert(c);
if (type_suppr->suppresses_type(c, ctxt))
suppressed_added_fns_[e->first] = e->second;
}
// Deleted virtual functions
for (string_function_ptr_map::const_iterator e = deleted_fns_.begin();
e != deleted_fns_.end();
++e)
if (is_member_function(e->second)
&& get_member_function_is_virtual(e->second))
{
function_decl *f = e->second;
class_decl_sptr c =
is_method_type(f->get_type())->get_class_type();
assert(c);
if (type_suppr->suppresses_type(c, ctxt))
suppressed_deleted_fns_[e->first] = e->second;
}
}
// Added/Deleted variables
else if (variable_suppression_sptr var_suppr =
is_variable_suppression(*i))

View File

@ -28,6 +28,7 @@
#include "abg-suppression.h"
#include "abg-ini.h"
#include "abg-sptr-utils.h"
#include "abg-comp-filter.h"
#include "abg-tools-utils.h"
namespace abigail
@ -43,6 +44,7 @@ using std::tr1::dynamic_pointer_cast;
/// The private data of @ref suppression_base.
class suppression_base::priv
{
bool is_artificial_;
string label_;
string file_name_regex_str_;
mutable sptr_utils::regex_t_sptr file_name_regex_;
@ -55,16 +57,19 @@ class suppression_base::priv
public:
priv()
: is_artificial_()
{}
priv(const string& label)
: label_(label)
: is_artificial_(),
label_(label)
{}
priv(const string& label,
const string& file_name_regex_str,
const string& file_name_not_regex_str)
: label_(label),
: is_artificial_(),
label_(label),
file_name_regex_str_(file_name_regex_str),
file_name_not_regex_str_(file_name_not_regex_str)
{}
@ -190,6 +195,26 @@ suppression_base::suppression_base(const string& label,
{
}
/// Test is the suppression specification is artificial.
///
/// Artificial means that the suppression was automatically generated
/// by libabigail, rather than being constructed from a suppression
/// file provided by the user.
///
/// @return TRUE iff the suppression specification is artificial.
bool
suppression_base::get_is_artificial() const
{return priv_->is_artificial_;}
/// Set a flag saying if the suppression specification is artificial
/// or not.
///
/// Artificial means that the suppression was automatically generated
/// by libabigail, rather than being constructed from a suppression
/// file provided by the user.
void
suppression_base::set_is_artificial(bool f)
{priv_->is_artificial_ = f;}
/// Getter for the label associated to this suppression specification.
///
@ -484,7 +509,7 @@ class type_suppression::priv
bool consider_reach_kind_;
type_suppression::reach_kind reach_kind_;
type_suppression::insertion_ranges insertion_ranges_;
vector<string> source_locations_to_keep_;
unordered_set<string> source_locations_to_keep_;
string source_location_to_keep_regex_str_;
mutable sptr_utils::regex_t_sptr source_location_to_keep_regex_;
@ -739,13 +764,22 @@ type_suppression::insertion_ranges&
type_suppression::get_data_member_insertion_ranges()
{return priv_->insertion_ranges_;}
/// Getter for the array of source location paths of types that should
/// *NOT* be suppressed.
///
/// @return the set of source locations of types that should *NOT* be
/// supressed.
const unordered_set<string>&
type_suppression::get_source_locations_to_keep() const
{return priv_->source_locations_to_keep_;}
/// Getter for the array of source location paths of types that should
/// *NOT* be suppressed.
///
/// @return the array of source locations of types that should *NOT*
/// be supressed.
const vector<string>&
type_suppression::get_source_locations_to_keep() const
unordered_set<string>&
type_suppression::get_source_locations_to_keep()
{return priv_->source_locations_to_keep_;}
/// Setter for the array of source location paths of types that should
@ -753,7 +787,8 @@ type_suppression::get_source_locations_to_keep() const
///
/// @param l the new array.
void
type_suppression::set_source_locations_to_keep(const vector<string>& l)
type_suppression::set_source_locations_to_keep
(const unordered_set<string>& l)
{priv_->source_locations_to_keep_ = l;}
/// Getter of the regular expression string that designates the source
@ -784,7 +819,34 @@ type_suppression::suppresses_diff(const diff* diff) const
{
const type_diff_base* d = is_type_diff(diff);
if (!d)
return false;
{
// So the diff we are looking at is not a type diff. However,
// there are cases where a type suppression can suppress changes
// on functions.
// Typically, if a virtual member function's virtual index (its
// index in the vtable of a class) changes and if the current
// type suppression is meant to suppress change reports about
// the enclosing class of the virtual member function, then this
// type suppression should suppress reports about that function
// change.
const function_decl_diff* d = is_function_decl_diff(diff);
if (d)
{
// Let's see if 'd' carries a virtual member function
// change.
if (comparison::filtering::has_virtual_mem_fn_change(d))
{
function_decl_sptr f = d->first_function_decl();
class_decl_sptr fc =
is_method_type(f->get_type())->get_class_type();
assert(fc);
if (suppresses_type(fc, diff->context()))
return true;
}
}
return false;
}
// If the suppression should consider the way the diff node has been
// reached, then do it now.
@ -995,6 +1057,17 @@ type_suppression::suppresses_type(const type_base_sptr& type,
if (decl_base_sptr d = get_type_declaration(type))
{
location loc = d->get_location();
if (!loc)
{
if (class_decl_sptr c = is_class_type(d))
if (c->get_is_declaration_only()
&& c->get_definition_of_declaration())
{
c = c->get_definition_of_declaration();
loc = c->get_location();
}
}
if (loc)
{
translation_unit* tu = get_translation_unit(d);
@ -1011,15 +1084,12 @@ type_suppression::suppresses_type(const type_base_sptr& type,
return false;
tools_utils::base_name(loc_path, loc_path_base);
for (vector<string>::const_iterator s =
get_source_locations_to_keep().begin();
s != get_source_locations_to_keep().end();
++s)
{
if (tools_utils::string_ends_with(*s, loc_path)
|| tools_utils::string_ends_with(*s, loc_path_base))
return false;
}
if (get_source_locations_to_keep().find(loc_path_base)
!= get_source_locations_to_keep().end())
return false;
if (get_source_locations_to_keep().find(loc_path)
!= get_source_locations_to_keep().end())
return false;
}
else
{
@ -1034,6 +1104,29 @@ type_suppression::suppresses_type(const type_base_sptr& type,
}
else
{
// So the type had no source location.
//
// In the case where this type suppression was automatically
// generated to suppress types not defined in public
// headers, then this might mean that the type is not
// defined in the public headers. Otherwise, why does it
// not have a source location?
if (get_is_artificial())
{
if (class_decl_sptr cl = is_class_type(d))
{
if (cl->get_is_declaration_only())
// We tried hard above to get the definition of
// the declaration. If we reach this place, it
// means the class has no definition at this point.
assert(!cl->get_definition_of_declaration());
if (get_label() == tools_utils::PRIVATE_TYPES_SUPPR_SPEC_NAME)
// So this looks like what really amounts to an
// opaque type. So it's not defined in the public
// headers. So we want to filter it out.
return true;
}
}
if (!get_source_locations_to_keep().empty()
|| priv_->get_source_location_to_keep_regex())
// The user provided a "source_location_not_regexp" or
@ -1485,17 +1578,23 @@ read_type_suppression(const ini::config::section& section)
ini::property_sptr srcloc_not_in_prop =
section.find_property("source_location_not_in");
vector<string> srcloc_not_in;
unordered_set<string> srcloc_not_in;
if (srcloc_not_in_prop)
{
if (ini::simple_property_sptr p = is_simple_property(srcloc_not_in_prop))
srcloc_not_in.push_back(p->get_value()->as_string());
srcloc_not_in.insert(p->get_value()->as_string());
else
{
ini::list_property_sptr list_property =
is_list_property(srcloc_not_in_prop);
if (list_property)
srcloc_not_in = list_property->get_value()->get_content();
{
vector<string>::const_iterator i;
for (i = list_property->get_value()->get_content().begin();
i != list_property->get_value()->get_content().end();
++i)
srcloc_not_in.insert(*i);
}
}
}

View File

@ -24,6 +24,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <fts.h>
#include <cstdlib>
#include <cstring>
#include <ctype.h>
@ -40,6 +41,8 @@ using std::string;
namespace abigail
{
using namespace abigail::suppr;
/// @brief Namespace for a set of utility function used by tools based
/// on libabigail.
namespace tools_utils
@ -772,6 +775,77 @@ make_path_absolute(const char*p)
return result;
}
/// 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.
const char* PRIVATE_TYPES_SUPPR_SPEC_NAME =
"Artificial private types suppression specification";
/// This is a sub-routine of gen_suppr_spec_from_headers.
///
/// @param entry if this file represents a regular (or symlink) file,
/// then its file name is going to be added to the vector returned by
/// type_suppression::get_source_locations_to_keep().
///
/// @param if @p entry represents a file, then its file name is going
/// to be added to the vector returned by the method
/// type_suppression::get_source_locations_to_keep of this instance.
/// If this smart pointer is nil then a new instance @ref
/// type_suppression is created and this variable is made to point to
/// it.
static void
handle_fts_entry(const FTSENT *entry,
type_suppression_sptr& suppr)
{
if (entry == NULL
|| (entry->fts_info != FTS_F && entry->fts_info != FTS_SL)
|| entry->fts_info == FTS_ERR
|| entry->fts_info == FTS_NS)
return;
string fname = entry->fts_name;
if (!fname.empty())
{
if (string_ends_with(fname, ".h")
|| string_ends_with(fname, ".hpp")
|| string_ends_with(fname, ".hxx"))
{
if (!suppr)
suppr.reset(new type_suppression(PRIVATE_TYPES_SUPPR_SPEC_NAME,
/*type_name_regexp=*/"",
/*type_name=*/""));
suppr->set_is_artificial(true);
suppr->get_source_locations_to_keep().insert(fname);
}
}
}
/// Generate a type suppression specification that suppresses ABI
/// changes for types defines in source files that are *NOT* in a give
/// header root dir.
///
/// @param headers_root_dir ABI changes in types defined in files
/// *NOT* found in this directory tree are going be suppressed.
///
/// @return the resulting type suppression generated, if any file was
/// found in the directory tree @p headers_root_dir.
type_suppression_sptr
gen_suppr_spec_from_headers(const string& headers_root_dir)
{
char* paths[] = {const_cast<char*>(headers_root_dir.c_str()), 0};
type_suppression_sptr result;
FTS *file_hierarchy = fts_open(paths, FTS_LOGICAL|FTS_NOCHDIR, NULL);
if (!file_hierarchy)
return result;
FTSENT *entry;
while ((entry = fts_read(file_hierarchy)))
handle_fts_entry(entry, result);
fts_close(file_hierarchy);
return result;
}
}//end namespace tools_utils
using abigail::ir::function_decl;

View File

@ -928,6 +928,18 @@ test-diff-suppr/test29-suppr-5.txt \
test-diff-suppr/test29-suppr-6.txt \
test-diff-suppr/test29-suppr-7.txt \
test-diff-suppr/test29-suppr-8.txt \
test-diff-suppr/test30-include-dir-v0/test30-pub-lib-v0.h \
test-diff-suppr/test30-include-dir-v1/test30-pub-lib-v1.h \
test-diff-suppr/test30-priv-lib-v0.cc \
test-diff-suppr/test30-priv-lib-v0.h \
test-diff-suppr/test30-priv-lib-v1.cc \
test-diff-suppr/test30-priv-lib-v1.h \
test-diff-suppr/test30-pub-lib-v0.cc \
test-diff-suppr/test30-pub-lib-v0.so \
test-diff-suppr/test30-pub-lib-v1.cc \
test-diff-suppr/test30-pub-lib-v1.so \
test-diff-suppr/test30-report-0.txt \
test-diff-suppr/test30-report-1.txt \
\
test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1 \
test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1.abi \
@ -1125,7 +1137,10 @@ test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64.rpm \
test-diff-pkg/tbb-4.3-3.20141204.fc23.x86_64.rpm \
test-diff-pkg/tbb-debuginfo-4.1-9.20130314.fc22.x86_64.rpm \
test-diff-pkg/tbb-debuginfo-4.3-3.20141204.fc23.x86_64.rpm \
test-diff-pkg/tbb-devel-4.1-9.20130314.fc22.x86_64.rpm \
test-diff-pkg/tbb-devel-4.3-3.20141204.fc23.x86_64.rpm \
test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt \
test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt \
test-diff-pkg/libICE-debuginfo-1.0.6-1.el6.x86_64.rpm \
test-diff-pkg/libICE-debuginfo-1.0.9-2.el7.x86_64.rpm \
test-diff-pkg/libICE-1.0.6-1.el6.x86_64.rpm \
@ -1140,3 +1155,4 @@ test-diff-pkg/tarpkg-1-dir1.tar.gz \
test-diff-pkg/tarpkg-1-dir2.tar.gz \
test-diff-pkg/tarpkg-1-report-0.txt

View File

@ -0,0 +1,160 @@
================ changes of 'libtbb.so.2'===============
Functions changes summary: 0 Removed, 7 Changed (17 filtered out), 17 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
Function symbols changes summary: 0 Removed, 0 Added function symbol not referenced by debug info
Variable symbols changes summary: 3 Removed, 0 Added variable symbols not referenced by debug info
17 Added functions:
'method int tbb::interface7::internal::task_arena_base::internal_current_slot()' {_ZN3tbb10interface78internal15task_arena_base21internal_current_slotEv}
'method void tbb::interface7::internal::task_arena_base::internal_enqueue(tbb::task&, intptr_t)' {_ZNK3tbb10interface78internal15task_arena_base16internal_enqueueERNS_4taskEl}
'method void tbb::interface7::internal::task_arena_base::internal_execute(tbb::interface7::internal::delegate_base&)' {_ZNK3tbb10interface78internal15task_arena_base16internal_executeERNS1_13delegate_baseE}
'method void tbb::interface7::internal::task_arena_base::internal_initialize()' {_ZN3tbb10interface78internal15task_arena_base19internal_initializeEv}
'method void tbb::interface7::internal::task_arena_base::internal_terminate()' {_ZN3tbb10interface78internal15task_arena_base18internal_terminateEv}
'method void tbb::interface7::internal::task_arena_base::internal_wait()' {_ZNK3tbb10interface78internal15task_arena_base13internal_waitEv}
'method void tbb::interface8::internal::x86_rtm_rw_mutex::internal_acquire_reader(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&, bool)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex23internal_acquire_readerERNS2_11scoped_lockEb}
'method void tbb::interface8::internal::x86_rtm_rw_mutex::internal_acquire_writer(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&, bool)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex23internal_acquire_writerERNS2_11scoped_lockEb}
'method void tbb::interface8::internal::x86_rtm_rw_mutex::internal_construct()' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex18internal_constructEv}
'method bool tbb::interface8::internal::x86_rtm_rw_mutex::internal_downgrade(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex18internal_downgradeERNS2_11scoped_lockE}
'method void tbb::interface8::internal::x86_rtm_rw_mutex::internal_release(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex16internal_releaseERNS2_11scoped_lockE}
'method bool tbb::interface8::internal::x86_rtm_rw_mutex::internal_try_acquire_writer(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex27internal_try_acquire_writerERNS2_11scoped_lockE}
'method bool tbb::interface8::internal::x86_rtm_rw_mutex::internal_upgrade(tbb::interface8::internal::x86_rtm_rw_mutex::scoped_lock&)' {_ZN3tbb10interface88internal16x86_rtm_rw_mutex16internal_upgradeERNS2_11scoped_lockE}
'method void tbb::internal::concurrent_queue_base_v8::internal_push_move()' {_ZN3tbb8internal24concurrent_queue_base_v818internal_push_moveEPKv}
'method bool tbb::internal::concurrent_queue_base_v8::internal_push_move_if_not_full()' {_ZN3tbb8internal24concurrent_queue_base_v830internal_push_move_if_not_fullEPKv}
'method void tbb::internal::concurrent_queue_base_v8::move_content(tbb::internal::concurrent_queue_base_v8&)' {_ZN3tbb8internal24concurrent_queue_base_v812move_contentERS1_}
'method void tbb::task_group_context::capture_fp_settings()' {_ZN3tbb18task_group_context19capture_fp_settingsEv}
7 functions with some indirect sub-type change:
[C]'function void tbb::internal::throw_exception_v4(tbb::internal::exception_id)' at tbb_misc.cpp:119:1 has some indirect sub-type changes:
parameter 1 of type 'enum tbb::internal::exception_id' has sub-type changes:
1 enumerator insertion:
'tbb::internal::exception_id::eid_bad_tagged_msg_cast' value '20'
1 enumerator change:
'tbb::internal::exception_id::eid_max' from value '20' to '21'
[C]'method void tbb::mutex::scoped_lock::internal_acquire(tbb::mutex&)' at mutex.h:129:1 has some indirect sub-type changes:
parameter 1 of type 'tbb::mutex&' has sub-type changes:
in referenced type 'class tbb::mutex' at mutex.h:40:1:
1 base class insertion:
class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1
[C]'method void tbb::pipeline::run(std::size_t, tbb::task_group_context&)' at pipeline.cpp:633:1 has some indirect sub-type changes:
parameter 2 of type 'tbb::task_group_context&' has sub-type changes:
in referenced type 'class tbb::task_group_context' at task.h:302:1:
1 data member insertion:
'tbb::internal::cpu_ctl_env_space tbb::task_group_context::my_cpu_ctl_env', at offset 896 (in bits) at task.h:380:1
1 data member changes (2 filtered):
type of 'char tbb::task_group_context::_leading_padding[80]' changed:
type name changed from 'char[80]' to 'char[72]'
array type size changed from 640 to 576 bits:
array type subrange 1 changed length from 80 to 72
[C]'method void tbb::queuing_mutex::scoped_lock::acquire(tbb::queuing_mutex&)' at queuing_mutex.h:84:1 has some indirect sub-type changes:
parameter 1 of type 'tbb::queuing_mutex&' has sub-type changes:
in referenced type 'class tbb::queuing_mutex' at queuing_mutex.h:45:1:
1 base class insertion:
class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1
no data member change (1 filtered);
[C]'method void tbb::queuing_rw_mutex::scoped_lock::acquire(tbb::queuing_rw_mutex&, bool)' at queuing_rw_mutex.h:95:1 has some indirect sub-type changes:
parameter 1 of type 'tbb::queuing_rw_mutex&' has sub-type changes:
in referenced type 'class tbb::queuing_rw_mutex' at queuing_rw_mutex.h:47:1:
1 base class insertion:
class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1
no data member change (1 filtered);
[C]'method void tbb::recursive_mutex::scoped_lock::internal_acquire(tbb::recursive_mutex&)' at recursive_mutex.h:139:1 has some indirect sub-type changes:
parameter 1 of type 'tbb::recursive_mutex&' has sub-type changes:
in referenced type 'class tbb::recursive_mutex' at recursive_mutex.h:39:1:
1 base class insertion:
class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1
[C]'method void tbb::spin_mutex::scoped_lock::internal_acquire(tbb::spin_mutex&)' at spin_mutex.h:66:1 has some indirect sub-type changes:
parameter 1 of type 'tbb::spin_mutex&' has sub-type changes:
in referenced type 'class tbb::spin_mutex' at spin_mutex.h:40:1:
1 base class insertion:
class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1
3 Removed variable symbols not referenced by debug info:
_ZTVN3rml16versioned_objectE
_ZTVN3rml6clientE
_ZTVN3rml6serverE
================ end of changes of 'libtbb.so.2'===============
================ changes of 'libtbbmalloc.so.2'===============
Functions changes summary: 9 Removed, 0 Changed, 0 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
Function symbols changes summary: 0 Removed, 27 Added function symbols not referenced by debug info
Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referenced by debug info
9 Removed functions:
'function void* rml::internal::__TBB_internal_calloc(size_t, size_t)' {__TBB_internal_calloc}
'function void rml::internal::__TBB_internal_free(void*)' {__TBB_internal_free}
'function void* rml::internal::__TBB_internal_malloc(size_t)' {__TBB_internal_malloc}
'function int rml::internal::__TBB_internal_posix_memalign(void**, size_t, size_t)' {__TBB_internal_posix_memalign}
'function void* rml::internal::__TBB_internal_realloc(void*, size_t)' {__TBB_internal_realloc}
'function void* safer_scalable_aligned_realloc(void*, size_t, size_t, void*)' {safer_scalable_aligned_realloc}
'function void safer_scalable_free(void*, void (void*)*)' {safer_scalable_free}
'function size_t safer_scalable_msize(void*, typedef size_t (void*)*)' {safer_scalable_msize}
'function void* safer_scalable_realloc(void*, size_t, void*)' {safer_scalable_realloc}
27 Added function symbols not referenced by debug info:
_Z10BitScanRevm
_Z10FencedLoadRVKl
_Z11FencedStoreRVll
_Z15AtomicIncrementRVl
_Z15SpinWaitWhileEqRVKll
_Z16AtomicFetchStorePVvm
_Z21AtomicCompareExchangeRVlll
_Z8AtomicOrPVvm
_Z8do_yieldv
_Z9AtomicAddRVll
_Z9AtomicAndPVvm
_ZN11MallocMutex11scoped_lockC1ERS_
_ZN11MallocMutex11scoped_lockC1ERS_bPb, aliases _ZN11MallocMutex11scoped_lockC2ERS_bPb
_ZN11MallocMutex11scoped_lockC2ERS_, aliases _ZN11MallocMutex11scoped_lockC1ERS_
_ZN11MallocMutex11scoped_lockC2ERS_bPb
_ZN11MallocMutex11scoped_lockD1Ev, aliases _ZN11MallocMutex11scoped_lockD2Ev
_ZN11MallocMutex11scoped_lockD2Ev
_ZN11MallocMutexC1Ev, aliases _ZN11MallocMutexC2Ev
_ZN11MallocMutexC2Ev
_ZdlPvS_
_ZnwmPv
__TBB_malloc_safer_aligned_msize
__TBB_malloc_safer_aligned_realloc
__TBB_malloc_safer_free
__TBB_malloc_safer_msize
__TBB_malloc_safer_realloc
scalable_allocation_command
================ end of changes of 'libtbbmalloc.so.2'===============
================ changes of 'libtbbmalloc_proxy.so.2'===============
Functions changes summary: 1 Removed, 0 Changed, 5 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 Removed function:
'function bool __TBB_internal_find_original_malloc(int, const char**, void**)' {__TBB_internal_find_original_malloc}
5 Added functions:
'function void __libc_free(void*)' {__libc_free}
'function void* __libc_realloc(void*, size_t)' {__libc_realloc}
'function void* calloc(size_t, size_t)' {__libc_calloc, aliases calloc}
'function size_t malloc_usable_size(void*)' {malloc_usable_size}
'function void* valloc(size_t)' {__libc_valloc, aliases valloc}
================ end of changes of 'libtbbmalloc_proxy.so.2'===============

View File

@ -0,0 +1,9 @@
class S
{
class priv_type;
priv_type* priv;
friend int public_function(S*);
};
int public_function(S*);

View File

@ -0,0 +1,9 @@
class S
{
class priv_type;
priv_type* priv;
friend int public_function(S*);
};
int public_function(S*);

View File

@ -0,0 +1,4 @@
// Compile this with:
// g++ -g -Wall -shared -fPIC -o test30-priv-lib-v0.so test30-priv-lib-v0.cc
#include "test30-priv-lib-v0.h"

View File

@ -0,0 +1,18 @@
// This is a class that, when #included in a .cc file will generate a
// dwarf representation that is declaration-only class because the all
// of the methods of the class are inline virtual methods but one.
// And the one virtual method that is not inline is not defined. So
// the .cc file that is going to define that method is going to see
// the class as being defined, and that file will also have the
// definition of the vtable.
class non_defined_class
{
public:
virtual int virtual_func_to_be_removed(){return 0;}
non_defined_class(){};
virtual ~non_defined_class(){}
virtual int virtual_func0(){return 0;}
virtual int virtual_func1();
};
int private_function(non_defined_class *);

View File

@ -0,0 +1,23 @@
// Compile this with:
// g++ -g -Wall -shared -fPIC -o test30-priv-lib-v1.so test30-priv-lib-v1.cc
#include "test30-priv-lib-v1.h"
class opaque_class
{
public:
virtual int inserted_member();
virtual int member0();
};
int
opaque_class::member0()
{return 0;}
int
opaque_class::inserted_member()
{return 0;}
int
private_function(opaque_class *o)
{return o->member0() + o->inserted_member();}

View File

@ -0,0 +1,18 @@
// This is a class that, when #included in a .cc file will generate a
// dwarf representation that is declaration-only class because the all
// of the methods of the class are inline virtual methods but one.
// And the one virtual method that is not inline is not defined. So
// the .cc file that is going to define that method is going to see
// the class as being defined, and that file will also have the
// definition of the vtable.
class non_defined_class
{
public:
non_defined_class(){};
virtual ~non_defined_class(){}
virtual int virtual_func_inserted(){return 0;};
virtual int virtual_func1();
virtual int virtual_func0(){return 0;}
};
int private_function(non_defined_class *);

View File

@ -0,0 +1,22 @@
// Compile this with:
// g++ -g -Wall -shared -fPIC -o test30-pub-lib-v0.so test30-pub-lib-v0.cc
#include "test30-include-dir-v0/test30-pub-lib-v0.h"
#include "test30-priv-lib-v0.h"
int
private_function(non_defined_class*)
{
non_defined_class o;
return o.virtual_func0() + o.virtual_func_to_be_removed();
}
class S::priv_type
{
public:
non_defined_class* member0;
};
int
public_function(S* s)
{return private_function(s->priv->member0);}

Binary file not shown.

View File

@ -0,0 +1,23 @@
// Compile this with:
// g++ -g -Wall -shared -fPIC -o test30-pub-lib-v1.so test30-pub-lib-v1.cc
#include "test30-include-dir-v1/test30-pub-lib-v1.h"
#include "test30-priv-lib-v1.h"
int
private_function(non_defined_class *)
{
non_defined_class o;
return o.virtual_func0() + o.virtual_func_inserted();
}
class S::priv_type
{
public:
non_defined_class* member0;
int member1;
};
int
public_function(S* s)
{return private_function(s->priv->member0) + s->priv->member1;}

Binary file not shown.

View File

@ -0,0 +1,32 @@
Functions changes summary: 1 Removed, 2 Changed, 1 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 Removed function:
'method virtual int non_defined_class::virtual_func_to_be_removed()' {_ZN17non_defined_class26virtual_func_to_be_removedEv}
note that this removes an entry from the vtable of class non_defined_class
1 Added function:
'method virtual int non_defined_class::virtual_func_inserted()' {_ZN17non_defined_class21virtual_func_insertedEv}
note that this adds a new entry to the vtable of class non_defined_class
2 functions with some indirect sub-type change:
[C]'method virtual int non_defined_class::virtual_func0()' at test30-priv-lib-v1.h:15:1 has some indirect sub-type changes:
the vtable offset of method virtual int non_defined_class::virtual_func0() changed from 3 to 4
note that this is an ABI incompatible change to the vtable of class non_defined_class
[C]'function int public_function(S*)' at test30-pub-lib-v1.cc:22:1 has some indirect sub-type changes:
parameter 1 of type 'S*' has sub-type changes:
in pointed to type 'class S' at test30-pub-lib-v1.h:1:1:
1 data member change:
type of 'S::priv_type* S::priv' changed:
in pointed to type 'class S::priv_type' at test30-pub-lib-v1.cc:14:1:
type size changed from 64 to 128 bits
1 data member insertion:
'int S::priv_type::member1', at offset 64 (in bits) at test30-pub-lib-v1.cc:18:1

View File

@ -0,0 +1,3 @@
Functions changes summary: 0 Removed (1 filtered out), 0 Changed (2 filtered out), 0 Added function (1 filtered out)
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

View File

@ -55,6 +55,8 @@ struct InOutSpec
const char* suppression_path;
const char* first_in_debug_package_path;
const char* second_in_debug_package_path;
const char* first_in_devel_package_path;
const char* second_in_devel_package_path;
const char* ref_report_path;
const char* out_report_path;
};// end struct InOutSpec
@ -69,6 +71,8 @@ static InOutSpec in_out_specs[] =
"",
"",
"",
"",
"",
"data/test-diff-pkg/dirpkg-0-report-0.txt",
"output/test-diff-pkg/dirpkg-0-report-0.txt"
},
@ -80,6 +84,8 @@ static InOutSpec in_out_specs[] =
"",
"",
"",
"",
"",
"data/test-diff-pkg/dirpkg-1-report-0.txt",
"output/test-diff-pkg/dirpkg-1-report-0.txt"
},
@ -92,6 +98,8 @@ static InOutSpec in_out_specs[] =
"",
"",
"",
"",
"",
"data/test-diff-pkg/dirpkg-1-report-1.txt",
"output/test-diff-pkg/dirpkg-1-report-1.txt"
},
@ -104,6 +112,8 @@ static InOutSpec in_out_specs[] =
"",
"",
"",
"",
"",
"data/test-diff-pkg/dirpkg-2-report-0.txt",
"output/test-diff-pkg/dirpkg-2-report-0.txt"
},
@ -117,6 +127,8 @@ static InOutSpec in_out_specs[] =
"data/test-diff-pkg/dirpkg-3.suppr",
"",
"",
"",
"",
"data/test-diff-pkg/dirpkg-3-report-0.txt",
"output/test-diff-pkg/dirpkg-3-report-0.txt"
},
@ -131,6 +143,8 @@ static InOutSpec in_out_specs[] =
"data/test-diff-pkg/dirpkg-3.suppr",
"",
"",
"",
"",
"data/test-diff-pkg/dirpkg-3-report-1.txt",
"output/test-diff-pkg/dirpkg-3-report-1.txt"
},
@ -141,6 +155,8 @@ static InOutSpec in_out_specs[] =
"data/test-diff-pkg/dirpkg-3.suppr",
"",
"",
"",
"",
"data/test-diff-pkg/dirpkg-3-report-2.txt",
"output/test-diff-pkg/dirpkg-3-report-2.txt"
},
@ -151,6 +167,8 @@ static InOutSpec in_out_specs[] =
"",
"",
"",
"",
"",
"data/test-diff-pkg/symlink-dir-test1-report0.txt ",
"output/test-diff-pkg/symlink-dir-test1-report0.txt "
},
@ -162,6 +180,8 @@ static InOutSpec in_out_specs[] =
"",
"",
"",
"",
"",
"data/test-diff-pkg/tarpkg-0-report-0.txt",
"output/test-diff-pkg/tarpkg-0-report-0.txt"
},
@ -172,6 +192,8 @@ static InOutSpec in_out_specs[] =
"",
"",
"",
"",
"",
"data/test-diff-pkg/tarpkg-0-report-0.txt",
"output/test-diff-pkg/tarpkg-0-report-01.txt"
},
@ -182,6 +204,8 @@ static InOutSpec in_out_specs[] =
"",
"",
"",
"",
"",
"data/test-diff-pkg/tarpkg-0-report-0.txt",
"output/test-diff-pkg/tarpkg-0-report-02.txt"
},
@ -192,6 +216,8 @@ static InOutSpec in_out_specs[] =
"",
"",
"",
"",
"",
"data/test-diff-pkg/tarpkg-0-report-0.txt",
"output/test-diff-pkg/tarpkg-0-report-03.txt"
},
@ -202,6 +228,8 @@ static InOutSpec in_out_specs[] =
"",
"",
"",
"",
"",
"data/test-diff-pkg/tarpkg-1-report-0.txt",
"output/test-diff-pkg/tarpkg-1-report-0.txt"
},
@ -216,55 +244,65 @@ static InOutSpec in_out_specs[] =
"",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm",
"",
"",
"data/test-diff-pkg/test-rpm-report-0.txt",
"output/test-diff-pkg/test-rpm-report-0.txt"
},
// Two RPM packages with 2nd package debuginfo missing
{
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
"--no-show-locs",
"",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"",
"data/test-diff-pkg/test-rpm-report-1.txt",
"output/test-diff-pkg/test-rpm-report-1.txt"
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
"--no-show-locs",
"",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"",
"",
"",
"data/test-diff-pkg/test-rpm-report-1.txt",
"output/test-diff-pkg/test-rpm-report-1.txt"
},
// Two RPM packages with first package debuginfo missing
{
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
"--no-show-locs",
"",
"",
"data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm",
"data/test-diff-pkg/test-rpm-report-2.txt",
"output/test-diff-pkg/test-rpm-report-2.txt"
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
"--no-show-locs",
"",
"",
"data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm",
"",
"",
"data/test-diff-pkg/test-rpm-report-2.txt",
"output/test-diff-pkg/test-rpm-report-2.txt"
},
// Two RPM packages with missing debuginfo
{
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
"--no-show-locs",
"",
"",
"",
"data/test-diff-pkg/test-rpm-report-3.txt",
"output/test-diff-pkg/test-rpm-report-3.txt"
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm",
"--no-show-locs",
"",
"",
"",
"",
"",
"data/test-diff-pkg/test-rpm-report-3.txt",
"output/test-diff-pkg/test-rpm-report-3.txt"
},
// Two RPM packages with no ABI change
{
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"--no-show-locs",
"",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/test-rpm-report-4.txt",
"output/test-diff-pkg/test-rpm-report-4.txt"
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm",
"--no-show-locs",
"",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"",
"",
"data/test-diff-pkg/test-rpm-report-4.txt",
"output/test-diff-pkg/test-rpm-report-4.txt"
},
// Two RPM packages with debuginfo available and we don't want to
// see added symbols.
@ -275,6 +313,8 @@ static InOutSpec in_out_specs[] =
"",
"data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm",
"data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm",
"",
"",
"data/test-diff-pkg/test-rpm-report-5.txt",
"output/test-diff-pkg/test-rpm-report-5.txt"
},
@ -285,17 +325,22 @@ static InOutSpec in_out_specs[] =
"",
"data/test-diff-pkg/qemu-kvm-rhev-debuginfo-2.3.0-7.el7.ppc64.rpm",
"data/test-diff-pkg/qemu-kvm-rhev-debuginfo-2.3.0-20.el7.ppc64.rpm",
"",
"",
"data/test-diff-pkg/qemu-img-rhev-2.3.0-7.el7.ppc64--qemu-img-rhev-2.3.0-20.el7.ppc64-report-0.txt",
"output/test-diff-pkg/qemu-img-rhev-2.3.0-7.el7.ppc64--qemu-img-rhev-2.3.0-20.el7.ppc64-report-0.txt"
},
{"data/test-diff-pkg/empty-pkg-libvirt-0.9.11.3-1.el7.ppc64.rpm",
"data/test-diff-pkg/empty-pkg-libvirt-1.2.17-13.el7_2.2.ppc64.rpm",
"",
"",
"",
"",
"data/test-diff-pkg/empty-pkg-report-0.txt",
"output/test-diff-pkg/empty-pkg-report-0.txt"
{
"data/test-diff-pkg/empty-pkg-libvirt-0.9.11.3-1.el7.ppc64.rpm",
"data/test-diff-pkg/empty-pkg-libvirt-1.2.17-13.el7_2.2.ppc64.rpm",
"",
"",
"",
"",
"",
"",
"data/test-diff-pkg/empty-pkg-report-0.txt",
"output/test-diff-pkg/empty-pkg-report-0.txt"
},
{
"data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64.rpm",
@ -304,9 +349,23 @@ static InOutSpec in_out_specs[] =
"",
"data/test-diff-pkg/tbb-debuginfo-4.1-9.20130314.fc22.x86_64.rpm",
"data/test-diff-pkg/tbb-debuginfo-4.3-3.20141204.fc23.x86_64.rpm",
"",
"",
"data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt",
"output/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt"
},
{
"data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64.rpm",
"data/test-diff-pkg/tbb-4.3-3.20141204.fc23.x86_64.rpm",
"",
"",
"data/test-diff-pkg/tbb-debuginfo-4.1-9.20130314.fc22.x86_64.rpm",
"data/test-diff-pkg/tbb-debuginfo-4.3-3.20141204.fc23.x86_64.rpm",
"data/test-diff-pkg/tbb-devel-4.1-9.20130314.fc22.x86_64.rpm",
"data/test-diff-pkg/tbb-devel-4.3-3.20141204.fc23.x86_64.rpm",
"data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt",
"output/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt"
},
{
"data/test-diff-pkg/libICE-1.0.6-1.el6.x86_64.rpm",
"data/test-diff-pkg/libICE-1.0.9-2.el7.x86_64.rpm",
@ -314,6 +373,8 @@ static InOutSpec in_out_specs[] =
"",
"data/test-diff-pkg/libICE-debuginfo-1.0.6-1.el6.x86_64.rpm",
"data/test-diff-pkg/libICE-debuginfo-1.0.9-2.el7.x86_64.rpm",
"",
"",
"data/test-diff-pkg/libICE-1.0.6-1.el6.x86_64.rpm--libICE-1.0.9-2.el7.x86_64.rpm-report-0.txt",
"output/test-diff-pkg/libICE-1.0.6-1.el6.x86_64.rpm--libICE-1.0.9-2.el7.x86_64.rpm-report-0.txt"
},
@ -324,6 +385,8 @@ static InOutSpec in_out_specs[] =
"",
"data/test-diff-pkg/gtk2-debuginfo-2.24.22-5.el7.i686.rpm",
"data/test-diff-pkg/gtk2-debuginfo-2.24.28-8.el7.i686.rpm",
"",
"",
"data/test-diff-pkg/gtk2-immodule-xim-2.24.22-5.el7.i686--gtk2-immodule-xim-2.24.28-8.el7.i686-report-0.txt",
"output/test-diff-pkg/gtk2-immodule-xim-2.24.22-5.el7.i686--gtk2-immodule-xim-2.24.28-8.el7.i686-report-0.txt"
},
@ -338,12 +401,14 @@ static InOutSpec in_out_specs[] =
"",
"data/test-diff-pkg/libsigc++-2.0-0c2a-dbgsym_2.4.0-1_amd64.ddeb",
"data/test-diff-pkg/libsigc++-2.0-0v5-dbgsym_2.4.1-1ubuntu2_amd64.ddeb",
"",
"",
"data/test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64--libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64-report-0.txt",
"output/test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64--libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64-report-0.txt"
},
#endif // WITH_DEB
// This should be the last entry.
{0, 0, 0, 0, 0, 0, 0, 0}
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
/// A task which launches abipkgdiff on the binaries passed to the
@ -379,6 +444,7 @@ struct test_task : public abigail::workers::task
prog_options,
ref_abi_diff_report_path, out_abi_diff_report_path, cmd, abipkgdiff,
first_in_debug_package_path, second_in_debug_package_path,
first_in_devel_package_path, second_in_devel_package_path,
suppression_path;
first_in_package_path =
@ -402,6 +468,16 @@ struct test_task : public abigail::workers::task
else
second_in_debug_package_path.clear();
if (spec.first_in_devel_package_path
&& strcmp(spec.first_in_devel_package_path, ""))
first_in_devel_package_path =
string(get_src_dir()) + "/tests/" + spec.first_in_devel_package_path;
if (spec.second_in_devel_package_path
&& strcmp(spec.second_in_devel_package_path, ""))
second_in_devel_package_path =
string(get_src_dir()) + "/tests/" + spec.second_in_devel_package_path;
if (spec.suppression_path
&& strcmp(spec.suppression_path, ""))
suppression_path =
@ -432,6 +508,12 @@ struct test_task : public abigail::workers::task
if (!second_in_debug_package_path.empty())
abipkgdiff += " --d2 " + second_in_debug_package_path;
if (!first_in_devel_package_path.empty())
abipkgdiff += " --devel1 " + first_in_devel_package_path;
if (!second_in_devel_package_path.empty())
abipkgdiff += " --devel2 " + second_in_devel_package_path;
if (!suppression_path.empty())
abipkgdiff += " --suppressions " + suppression_path;

File diff suppressed because it is too large Load Diff

View File

@ -55,6 +55,7 @@ using namespace abigail::dwarf_reader;
using abigail::tools_utils::emit_prefix;
using abigail::tools_utils::check_file;
using abigail::tools_utils::guess_file_type;
using abigail::tools_utils::gen_suppr_spec_from_headers;
using abigail::tools_utils::abidiff_status;
struct options
@ -70,6 +71,8 @@ struct options
vector<string> drop_var_regex_patterns;
vector<string> keep_fn_regex_patterns;
vector<string> keep_var_regex_patterns;
string headers_dir1;
string headers_dir2;
bool no_arch;
bool show_stats_only;
bool show_symtabs;
@ -126,10 +129,12 @@ display_usage(const string& prog_name, ostream& out)
emit_prefix(prog_name, out)
<< "usage: " << prog_name << " [options] [<file1> <file2>]\n"
<< " where options can be:\n"
<< " --help|-h display this message\n "
<< " --version|-v display program version information and exit\n"
<< " --debug-info-dir1|--d1 <path> the root for the debug info of file1\n"
<< " --debug-info-dir2|--d2 <path> the root for the debug info of file2\n"
<< " --help|-h display this message\n "
<< " --headers-dir1|--hd1 <path> the path headers of file1\n"
<< " --headers-dir2|--hd2 <path> the path headers of file2\n"
<< " --stat only display the diff stats\n"
<< " --symtabs only display the symbol tables of the corpora\n"
<< " --no-architecture do not take architecture in account\n"
@ -228,6 +233,32 @@ parse_command_line(int argc, char* argv[], options& opts)
abigail::tools_utils::make_path_absolute(argv[j]);
++i;
}
else if (!strcmp(argv[i], "--headers-dir1")
|| !strcmp(argv[i], "--hd1"))
{
int j = i + 1;
if (j >= argc)
{
opts.missing_operand = true;
opts.wrong_option = argv[i];
return true;
}
opts.headers_dir1 = argv[j];
++i;
}
else if (!strcmp(argv[i], "--headers-dir2")
|| !strcmp(argv[i], "--hd2"))
{
int j = i + 1;
if (j >= argc)
{
opts.missing_operand = true;
opts.wrong_option = argv[i];
return true;
}
opts.headers_dir2 = argv[j];
++i;
}
else if (!strcmp(argv[i], "--stat"))
opts.show_stats_only = true;
else if (!strcmp(argv[i], "--symtabs"))
@ -495,6 +526,26 @@ set_diff_context_from_opts(diff_context_sptr ctxt,
read_suppressions(*i, supprs);
ctxt->add_suppressions(supprs);
if (!opts.headers_dir1.empty())
{
// Generate suppression specification to avoid showing ABI
// changes on types that are not defined in public headers.
suppression_sptr suppr =
gen_suppr_spec_from_headers(opts.headers_dir1);
if (suppr)
ctxt->add_suppression(suppr);
}
if (!opts.headers_dir2.empty())
{
// Generate suppression specification to avoid showing ABI
// changes on types that are not defined in public headers.
suppression_sptr suppr =
gen_suppr_spec_from_headers(opts.headers_dir2);
if (suppr)
ctxt->add_suppression(suppr);
}
ctxt->dump_diff_tree(opts.dump_diff_tree);
}

View File

@ -89,12 +89,16 @@ using std::map;
using std::ostringstream;
using std::tr1::shared_ptr;
using abigail::tools_utils::maybe_get_symlink_target_file_path;
using abigail::tools_utils::file_exists;
using abigail::tools_utils::is_dir;
using abigail::tools_utils::emit_prefix;
using abigail::tools_utils::check_file;
using abigail::tools_utils::guess_file_type;
using abigail::tools_utils::string_ends_with;
using abigail::tools_utils::file_type;
using abigail::tools_utils::make_path_absolute;
using abigail::tools_utils::base_name;
using abigail::tools_utils::gen_suppr_spec_from_headers;
using abigail::tools_utils::abidiff_status;
using abigail::ir::corpus_sptr;
using abigail::comparison::diff_context;
@ -156,6 +160,8 @@ public:
string package2;
string debug_package1;
string debug_package2;
string devel_package1;
string devel_package2;
bool keep_tmp_files;
bool compare_dso_only;
bool show_linkage_names;
@ -242,18 +248,43 @@ struct abi_diff
}
};
class package;
/// Convenience typedef for a shared pointer to a @ref package.
typedef shared_ptr<package> package_sptr;
/// Abstracts a package.
class package
{
public:
/// The kind of package we are looking at.
enum kind
{
/// Main package. Contains binaries to ABI-compare.
KIND_MAIN = 0,
/// Devel package. Contains public headers files in which public
/// types are defined.
KIND_DEVEL,
/// Debug info package. Contains the debug info for the binaries
/// int he main packge.
KIND_DEBUG_INFO,
/// Source package. Contains the source of the binaries in the
/// main package.
KIND_SRC
};
private:
string path_;
string extracted_dir_path_;
abigail::tools_utils::file_type type_;
bool is_debug_info_;
kind kind_;
map<string, elf_file_sptr> path_elf_file_sptr_map_;
shared_ptr<package> debug_info_package_;
package_sptr debug_info_package_;
package_sptr devel_package_;
suppressions_type private_types_suppressions_;
public:
/// Constructor for the @ref package type.
///
/// @param path the path to the package.
@ -261,12 +292,12 @@ public:
/// @parm dir the temporary directory where to extract the content
/// of the package.
///
/// @param is_debug_info true if the pacakge is a debug info package.
/// @param pkg_kind the kind of package.
package(const string& path,
const string& dir,
bool is_debug_info = false)
kind pkg_kind = package::KIND_MAIN)
: path_(path),
is_debug_info_(is_debug_info)
kind_(pkg_kind)
{
type_ = guess_file_type(path);
if (type_ == abigail::tools_utils::FILE_TYPE_DIR)
@ -327,19 +358,19 @@ public:
void type(abigail::tools_utils::file_type t)
{type_ = t;}
/// Test if the current package is a debug info package.
/// Get the package kind
///
/// @return true iff the current package is a debug info package.
bool
is_debug_info() const
{return is_debug_info_;}
/// @return the package kind
kind
get_kind() const
{return kind_;}
/// Set the flag that says if the current package is a debug info package.
/// Set the package kind
///
/// @param f the new flag.
/// @param k the package kind.
void
is_debug_info(bool f)
{is_debug_info_ = f;}
set_kind(kind k)
{kind_ = k;}
/// Getter for the path <-> elf_file map.
///
@ -372,6 +403,38 @@ public:
debug_info_package(const shared_ptr<package> p)
{debug_info_package_ = p;}
/// Getter for the devel package associated to the current package.
///
/// @return the devel package associated to the current package.
const package_sptr&
devel_package() const
{return devel_package_;}
/// Setter of the devel package associated to the current package.
///
/// @param p the new devel package associated to the current package.
void
devel_package(const package_sptr& p)
{devel_package_ = p;}
/// Getter of the specifications to suppress change reports about
/// private types.
///
/// @return the vector of specifications to suppress change reports
/// about private types.
const suppressions_type&
private_types_suppressions() const
{return private_types_suppressions_;}
/// Getter of the specifications to suppress change reports about
/// private types.
///
/// @return the vector of specifications to suppress change reports
/// about private types.
suppressions_type&
private_types_suppressions()
{return private_types_suppressions_;}
/// Erase the content of the temporary extraction directory that has
/// been populated by the @ref extract_package() function;
void
@ -409,6 +472,8 @@ public:
erase_extraction_directory();
if (debug_info_package())
debug_info_package()->erase_extraction_directory();
if (devel_package())
devel_package()->erase_extraction_directory();
}
};
@ -424,9 +489,11 @@ struct package_descriptor
struct compare_args
{
const elf_file elf1;
const string& debug_dir1;
const string& debug_dir1;
const suppressions_type& private_types_suppr1;
const elf_file elf2;
const string& debug_dir2;
const string& debug_dir2;
const suppressions_type& private_types_suppr2;
const options& opts;
/// Constructor for compare_args, which is used to pass
@ -444,10 +511,15 @@ struct compare_args
///
/// @param opts the options the current program has been called with.
compare_args(const elf_file &elf1, const string& debug_dir1,
const suppressions_type& priv_types_suppr1,
const elf_file &elf2, const string& debug_dir2,
const suppressions_type& priv_types_suppr2,
const options& opts)
: elf1(elf1), debug_dir1(debug_dir1), elf2(elf2),
debug_dir2(debug_dir2), opts(opts)
: elf1(elf1), debug_dir1(debug_dir1),
private_types_suppr1(priv_types_suppr1),
elf2(elf2), debug_dir2(debug_dir2),
private_types_suppr2(priv_types_suppr2),
opts(opts)
{}
};
/// A convenience typedef for arguments passed to the comparison workers.
@ -507,10 +579,12 @@ display_usage(const string& prog_name, ostream& out)
<< " where options can be:\n"
<< " --debug-info-pkg1|--d1 <path> path of debug-info package of package1\n"
<< " --debug-info-pkg2|--d2 <path> path of debug-info package of package2\n"
<< " --devel-pkg1|--devel1 <path> path of devel package of pakage1\n"
<< " --devel-pkg2|--devel2 <path> path of devel package of pakage1\n"
<< " --suppressions|--suppr <path> specify supression specification path\n"
<< " --keep-tmp-files don't erase created temporary files\n"
<< " --dso-only compare shared libraries only\n"
<< " --no-linkage-name do not display linkage names of "
<< " --no-linkage-name do not display linkage names of "
"added/removed/changed\n"
<< " --redundant display redundant changes\n"
<< " --no-show-locs do not show location information\n"
@ -930,8 +1004,10 @@ set_diff_context_from_opts(diff_context_sptr ctxt,
static abidiff_status
compare(const elf_file& elf1,
const string& debug_dir1,
const suppressions_type& priv_types_supprs1,
const elf_file& elf2,
const string& debug_dir2,
const suppressions_type& priv_types_supprs2,
const options& opts,
abigail::ir::environment_sptr &env,
corpus_diff_sptr &diff,
@ -968,6 +1044,20 @@ compare(const elf_file& elf1,
return abigail::tools_utils::ABIDIFF_OK;
}
// Add the first private type suppressions set to the set of
// suppressions.
for (suppressions_type::const_iterator i = priv_types_supprs1.begin();
i != priv_types_supprs1.end();
++i)
supprs.push_back(*i);
// Add the second private type suppressions set to the set of
// suppressions.
for (suppressions_type::const_iterator i = priv_types_supprs2.begin();
i != priv_types_supprs2.end();
++i)
supprs.push_back(*i);
if (verbose)
emit_prefix("abipkgdiff", cerr)
<< " Reading file "
@ -1097,8 +1187,8 @@ pthread_routine_compare(vector<compare_args_sptr> *args)
break;
abigail::ir::environment_sptr env(new abigail::ir::environment);
status |= s = compare(a->elf1, a->debug_dir1,
a->elf2, a->debug_dir2,
status |= s = compare(a->elf1, a->debug_dir1, a->private_types_suppr1,
a->elf2, a->debug_dir2, a->private_types_suppr2,
a->opts, env, diff, ctxt);
const string key = a->elf1.path;
@ -1211,6 +1301,55 @@ create_maps_of_package_content(package& package,
return true;
}
/// If devel packages were associated to the main package we are
/// looking at, use the names of the header files (extracted from the
/// package) to generate suppression specification to filter out types
/// that are not defined in those header files.
///
/// Filtering out types not defined in publi headers amounts to filter
/// out types that are deemed private to the package we are looking
/// at.
///
/// If the function succeeds, the generated private type suppressions
/// are available by invoking the
/// package::private_types_suppressions() accessor of the @p pkg
/// parameter.
///
/// @param pkg the main package we are looking at.
///
/// @return true iff suppression specifications were generated for
/// types private to the package.
static bool
maybe_create_private_types_suppressions(package& pkg)
{
if (!pkg.private_types_suppressions().empty())
return false;
package_sptr devel_pkg = pkg.devel_package();
if (!devel_pkg
|| !file_exists(devel_pkg->extracted_dir_path())
|| !is_dir(devel_pkg->extracted_dir_path()))
return false;
string headers_path = devel_pkg->extracted_dir_path();
if (devel_pkg->type() == abigail::tools_utils::FILE_TYPE_RPM
||devel_pkg->type() == abigail::tools_utils::FILE_TYPE_DEB)
// For RPM and DEB packages, header files are under the
// /usr/include sub-directories.
headers_path += "/usr/include";
if (!is_dir(headers_path))
return false;
suppression_sptr suppr =
gen_suppr_spec_from_headers(headers_path);
if (suppr)
pkg.private_types_suppressions().push_back(suppr);
return suppr;
}
static inline bool
pthread_join(pthread_t thr)
{
@ -1239,11 +1378,11 @@ pthread_join(pthread_t thr)
static void
pthread_routine_extract_pkg_and_map_its_content(package_descriptor *a)
{
pthread_t thr_pkg, thr_debug;
pthread_t thr_pkg, thr_debug, thr_devel;
package& package = a->pkg;
const options& opts = a->opts;
ftw_cb_type callback = a->callback;
bool has_debug_info_pkg, result = true;
bool has_debug_info_pkg, has_devel_pkg, result = true;
// The debug-info package usually takes longer to extract than the main
// package plus that package's mapping for ELFs and optionally suppression
@ -1268,6 +1407,29 @@ pthread_routine_extract_pkg_and_map_its_content(package_descriptor *a)
}
}
if ((has_devel_pkg = package.devel_package()))
{
// A devel package was provided for 'package'. Let's extract it
// too.
if (pthread_create(&thr_devel, /*attr=*/NULL,
reinterpret_cast<void*(*)(void*)>
(pthread_routine_extract_package),
package.devel_package().get()))
{
result = false;
goto exit;
}
// Wait for devel package extraction to complete if we're
// not running in parallel.
if (!opts.parallel)
{
result = pthread_join(thr_devel);
if (!result)
goto exit;
}
}
// Extract the package itself.
if (pthread_create(&thr_pkg, /*attr=*/NULL,
reinterpret_cast<void*(*)(void*)>(pthread_routine_extract_package),
@ -1283,7 +1445,14 @@ pthread_routine_extract_pkg_and_map_its_content(package_descriptor *a)
if (result)
result = create_maps_of_package_content(package, opts, callback);
// Let's wait for both extractions to finish before we exit.
// Wait for devel package extraction to finish
if (has_devel_pkg && opts.parallel)
result &= pthread_join(thr_devel);
maybe_create_private_types_suppressions(package);
// Let's wait for debug package extractions to finish before
// we exit.
if (has_debug_info_pkg && opts.parallel)
result &= pthread_join(thr_debug);
@ -1430,9 +1599,15 @@ compare(package& first_package,
|| iter->second->type == abigail::dwarf_reader::ELF_TYPE_EXEC
|| iter->second->type == abigail::dwarf_reader::ELF_TYPE_PI_EXEC))
{
elf_pairs.push_back(compare_args_sptr(new compare_args(*it->second,
debug_dir1, *iter->second,
debug_dir2, opts)));
elf_pairs.push_back
(compare_args_sptr (new compare_args
(*it->second,
debug_dir1,
first_package.private_types_suppressions(),
*iter->second,
debug_dir2,
second_package.private_types_suppressions(),
opts)));
}
else
{
@ -1652,6 +1827,34 @@ parse_command_line(int argc, char* argv[], options& opts)
abigail::tools_utils::make_path_absolute(argv[j]).get();
++i;
}
else if (!strcmp(argv[i], "--devel-pkg1")
|| !strcmp(argv[i], "--devel1"))
{
int j = i + 1;
if (j >= argc)
{
opts.missing_operand = true;
opts.wrong_option = argv[i];
return true;
}
opts.devel_package1 =
abigail::tools_utils::make_path_absolute(argv[j]).get();
++i;
}
else if (!strcmp(argv[i], "--devel-pkg2")
|| !strcmp(argv[i], "--devel2"))
{
int j = i + 1;
if (j >= argc)
{
opts.missing_operand = true;
opts.wrong_option = argv[i];
return true;
}
opts.devel_package2 =
abigail::tools_utils::make_path_absolute(argv[j]).get();
++i;
}
else if (!strcmp(argv[i], "--keep-tmp-files"))
opts.keep_tmp_files = true;
else if (!strcmp(argv[i], "--dso-only"))
@ -1765,13 +1968,26 @@ main(int argc, char* argv[])
first_package->debug_info_package
(package_sptr(new package(opts.debug_package1,
"debug_package1",
/*is_debug_info=*/true)));
/*pkg_kind=*/package::KIND_DEBUG_INFO)));
if (!opts.debug_package2.empty())
second_package->debug_info_package
(package_sptr(new package(opts.debug_package2,
"debug_package2",
/*is_debug_info=*/true)));
/*pkg_kind=*/package::KIND_DEBUG_INFO)));
if (!opts.devel_package1.empty())
first_package->devel_package
(package_sptr(new package(opts.devel_package1,
"devel_package1",
/*pkg_kind=*/package::KIND_DEVEL)));
;
if (!opts.devel_package2.empty())
second_package->devel_package
(package_sptr(new package(opts.devel_package2,
"devel_package2",
/*pkg_kind=*/package::KIND_DEVEL)));
switch (first_package->type())
{