Commit Graph

408 Commits

Author SHA1 Message Date
Dodji Seketeli
1ddde3d9d0 Try to avoid a race condition when abipkgdiff extracts packages.
abipkgdiff extracts the content of the first package in a directory
named <tmpdir>/package1 and the content second package in
<tmpdir>/package2.  If two independant instances of abipkgdiff are
launched at the same time, they are going to walk on each others'
toes, to say the least.

This patch extracts the content of each package in directory named
<tmpdir>/<randomname>/package1, where randomname is supposed to be a
random number, and so should be unique, most of the time.

I guess we should try harder to generate a randomname that is unique
when we see that the directory <tmpdir>/<randomname> exists already,
but for now, what we have is good enough, or at least better than what
we have had so far.

	* include/abg-tools-utils.h (get_random_number)
	(get_random_number_as_string): Declare new functions.
	* src/abg-tools-utils.cc (get_random_number)
	(get_random_number_as_string): Define them.
	* tools/abipkgdiff.cc
	(package::extracted_package_parent_dir_path): New data member.
	(package::package): Initialize
	package::extracted_package_parent_dir_path to
	<tmpdir>/<randomname>, with randomname being a random number
	represented as a string.
	(extract_rpm): Make sure to create a hierarchy of directories, not
	just a directory.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-20 00:02:00 +02:00
Dodji Seketeli
7cae79e0d8 On changed fn, show symbol info when name is different from linkage name in C
In change reports for function sub-type changes, for the C language,
when the name of the function is different from its linkage name, even
when the function symbol has no aliases, show the symbol information
of the function.

	* include/abg-ir.h (translation_unit::language): New enum type.
	(translation_unit::{get_language, set_language}): Declare new
	accessors.
	(translation_unit_language_to_string)
	(string_to_translation_unit_language, is_c_language)
	(is_cplus_plus_language): Declare new functions.
	* src/abg-ir.cc (translation_unit::priv::language_): New data
	member.
	(translation_unit::priv::language_): Initialize it.
	(translation_unit::{set_language, get_language}): Define new
	member functions.
	(translation_unit_language_to_string)
	(string_to_translation_unit_language, is_c_language)
	(is_cplus_plus_language): Define new functions.
	* src/abg-dwarf-reader.cc (dwarf_language_to_tu_language): New
	static function.
	(build_translation_unit_and_add_to_ir): Read the language of the
	translation unit.
	* src/abg-comparison.cc (corpus_diff::report): When reporting a
	change in a function sub-type, if we are in C language translation
	unit, if the function name is different from its linkage name,
	even if the symbol doesn't have any alias, show symbol
	information.
	* src/abg-reader.cc (read_translation_unit_from_input): Read the
	'language' property of the translation unit, if present.
	* src/abg-writer.cc (write_translation_unit): Write the 'language'
	property to the translation unit, if present.
	* tests/data/test-read-dwarf/test0.abi: Adjust for the new
	'language' property of the 'abi-instr' element.
	* tests/data/test-read-dwarf/test1.abi: Likewise.
	* tests/data/test-read-dwarf/test2.so.abi: Likewise.
	* tests/data/test-read-dwarf/test3.so.abi: Likewise.
	* tests/data/test-read-dwarf/test4.so.abi: Likewise.
	* tests/data/test-read-dwarf/test5.o.abi: Likewise.
	* tests/data/test-read-dwarf/test6.so.abi: Likewise.
	* tests/data/test-read-dwarf/test7.so.abi: Likewise.
	* tests/data/test-read-dwarf/test8-qualified-this-pointer.so.abi:
	Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-19 19:52:01 +02:00
Dodji Seketeli
f3ed9dfa92 Support file_name_regexp and soname_regexp in supp-specs
With this patch it's now possible to express the soname or name of the binary
file that contains the ABI artifacts the suppression specifications
should apply to.

	* include/abg-comparison.h (suppression_base::priv_): Make this
	pimpl member protected.
	(suppression_base::set_file_name_regex_str)
	(get_file_name_regex_str, get_soname_regex_str)
	(set_soname_regex_str): Declare new accessors.
	(function_suppression::{suppresses_function,
	suppresses_function_symbol}): Take a diff_context_sptr.
	(variable_suppression::{suppresses_variable,
	suppresses_variable_symbol}): Take a diff_context_sptr.
	* src/abg-comparison.cc
	(suppression_base::priv::{file_name_regex_str_, file_name_regex_,
	soname_regex_str_, soname_regex_}): Define new data members.
	(suppression_base::priv::get_file_name_regex_str)
	(get_soname_regex_str): Define new member functions.
	(suppression_base::set_file_name_regex_str)
	(get_file_name_regex_str, get_soname_regex_str)
	(set_soname_regex_str): Define new accessors.
	(type_suppression::suppresses_diff): Evaluate file_name_regexp and
	soname_regexp.
	(read_type_suppression): Fix the reading of the "label" property.
	Read the file_name_regexp and soname_regexp properties.
	(function_suppression::{suppresses_function,
	suppresses_function_symbol): Take a diff_context_sptr parameter.
	Evaluate file_name_regexp and soname_regexp properties.
	(function_suppression::suppresses_diff): Adjust for the api change
	of function_suppression::suppresses_function().
	(read_function_suppression): Read the file_name_regexp and
	soname_regexp properties.
	(variable_suppression::suppresses_variable): Take a
	diff_context_sptr parameter and evaluate file_name_regexp and
	soname_regexp properties.
	(variable_suppression::suppresses_variable_symbol): Likewise.
	(variable_suppression::suppresses_diff): Adjust for the api change
	of variable_suppression::suppresses_variable().
	(read_variable_suppression): Read the file_name_regexp and
	soname_regexp properties.
	(function_is_suppressed, variable_is_suppressed): Take a
	diff_context_sptr parameter.
	(corpus_diff::priv::apply_suppressions_to_added_removed_fns_vars):
	Adjust.
	* doc/manuals/libabigail-concepts.rst: Document file_name_regexp
	and soname_regexp in the manual.
	* tests/data/test-diff-suppr/libtest24-soname-v{0,1}.so: New test
	binary input files.
	* tests/data/test-diff-suppr/test24-soname-report-{0,4}.txt: New
	test input files.
	* tests/data/test-diff-suppr/test24-soname-suppr-{0,4}.txt:
	Likewise.
	* tests/data/test-diff-suppr/test24-soname-v{0,1}.cc: Source code
	of the binary test input files above.
	* tests/data/Makefile.am: Add the new test material above to
	source distribution.
	* tests/test-diff-suppr.cc (in_out_spec): Add the new test inputs
	to the set of tests this harness has to run over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-19 19:48:51 +02:00
Dodji Seketeli
5df40e91ce Remove the last direct fiddling with ELF from abipkgdiff.cc
Directly using elfutils from abipkgdiff.cc feels like a taping into
the wrong abstraction layer from this level.  So this patch moves the
determination of the type of elf file into abg-dwarf-reader.cc and
uses it from there.  The patch also simplifies the instantiation of
types elf_file and package, from abipkgdiff.cc.

	* abg-dwarf-reader.h (enum elf_type): Move this declaration here
	from abipkgdiff.cc to here.
	(get_type_of_elf_file): Declare this new function.
	(get_soname_from_elf): Change this to take a path to the elf file
	rather than a Elf* handler.  So now to use this, the user doesn't
	have to get her hand dirty with elfutils.
	* src/abg-dwarf-reader.cc (get_soname_from_elf): Change this to
	take a path to the elf file rather than a Elf* handler.
	(elf_file_type): Move this static function here, from
	abipkgdiff.cc.
	(get_type_of_elf_file): New function.  This has been factorized
	out of create_maps_of_package_content() in abipkgdiff.cc.
	* tools/abipkgdiff.cc (class elf_file): Changed struct elf_file
	into this.  Make the default constructor private.
	(elf_file::elf_file): Change the constructor to just take the path
	to the elf_file.  The base name, soname and elf file type are now
	computed from the path file, in the constructor.  This makes
	instantiation much much easier from the point of view of the user
	of the type.
	(struct abi_diff): Renamed struct abi_changes into this.
	(abi_diff::has_changes): Define new member function.
	(abi_diffs): Remove this global variable.
	(package::package): Remove the elf file type from the set of
	parameters of this constructor.  Rather, compute that elf file
	type from the path to the elf file, in the constructor.  Again,
	this eases the use of the type.
	(elf_file_type): Remove this from here, as it got moved to
	abg-dwarf-reader.cc.
	(compare): In the elf_file overload, return true if the comparison
	yields ABI changes.
	(create_maps_of_package_content): Do not fiddle with elfutils
	stuff here.  Rather, just instantiate elf_file and the analyzing
	of the file magically happens.
	(compare): Make the package overload take an abi_diff as output
	parameter, rather than populating a global variable in return.
	(compare): Add an other overload for package that doesn't take the
	abi_diff as output parameter and write it in terms of the previous
	one.
	(main): Adjust as the instantiation of package is now simpler.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-17 10:09:57 +02:00
Sinny Kumari
254dfd3655 Move get_soname() function to abg-dwarf-reader.h/cc
Initially, fetching SONAME from a given DSO file was done in
abipkgdiff.cc. But, this function fits better when defined in
abg-dwarf-reader.cc in order to make it usable by other tools if
needed. For consistancy, get_soname() function has been renamed to
get_soname_from_elf().

        * include/abg-dwarf-reader.h (get_soname_from_elf): Declare
         new function
        * src/abg-dwarf-reader.cc (get_soname_from_elf): Define new
        function
        * tools/abipkgdiff.cc (get_soname): Remove function
        (pkg_diff): Call get_soname_from_elf() instead of get_soname()

Signed-off-by: Sinny Kumari <sinny@redhat.com>
2015-07-17 10:09:06 +02:00
Sinny Kumari
b55e516d49 Guess RPM file type
To run abipkgdiff between two pacakges, it should know whether
input files are valid pacakge file or not. This patch detects RPM and SRPM
pacakge file type. abipkgdiff uses it to know whether input files are
valid RPM pacakge file or not.

	* include/abg-tools-utils.h (file_type): Added member
	FILE_TYPE_RPM and FILE_TYPE_SRPM
	(operator<<): New function declaration.
	* src/abg-tools-utils.cc (file_type): Detect RPM and
	SRPM file type
	(operator<<): New function definition
	* tools/abidiff.cc (main): Check for RPM and SRPM
	file type as well.
	* tools/abilint.cci (main): Check for RPM and SRPM file
	type as well.
	* tools/abipkgdiff.cc (main): Check whether input files
	to abipkgdiff are valid RPM files or not.

Signed-off-by: Sinny Kumari <sinny@redhat.com>
2015-07-17 10:07:37 +02:00
Dodji Seketeli
5b09ea77e2 Handle the life time of the map of canonical types
While working on something else, it turned out that we need to cleanup
(de-allocate) the map of canonical types when all the translation
units that own types are de-allocated.  Otherwise, when new
translation units are created later, the types in the canonical types
map become unrelated to the types in these new translation units,
leading to memory management issues.

This patch introduces a "usage watchdog" which detects when no
translation unit uses the type system anymore.  That usage watchdog is
then used in the destructor of the translation_unit type to
de-allocate the global data that is logically owned by by the type
system.

The patch also changes the API to read translation units and corpora
in a way that forces users to get a handle on the resulting shared
pointer.

	* include/abg-ir.h (type_base::canonical_types_map_type): Move
	this typedef into abg-ir.cc and out of the type_base namespace.
	(type_base::get_canonical_types_map): Likewise.
	* src/abg-ir.cc (canonical_types_map_type): New typedef that got
	moved here from type_base::canonical_types_map_type.
	(get_canonical_types_map): Likewise got moved here from
	type_base::get_canonical_types_map.  Made static in the process.
	(class usage_watchdog): New type.
	(usage_watchdog_sptr, usage_watchdog_wptr): New typedefs.
	(get_usage_watchdog, get_usage_watchdog_wptr, ref_usage_watchdog)
	(maybe_cleanup_type_system_data): New static functions.
	(translation_unit::priv::usage_watchdog_): Add new data member.
	(translation_unit::priv::priv): Get a reference on the usage
	watchdog.
	(translation_unit::priv::~priv): If the usage watchdog says that
	the type system is not used, then cleanup the global data
	logically owned by the type system.

	* include/abg-dwarf-reader.h (read_corpus_from_elf): Make this
	return a corpus and set the status by reference using a parameter.
	* src/abg-dwarf-reader.cc (read_corpus_from_elf): Implement the
	above.
	* include/abg-reader.h (read_translation_unit_from_file)
	(read_translation_unit_from_buffer)
	(read_translation_unit_from_istream): Remove the overloads that do
	not return a translation_unit_sptr and that pass it as a
	parameter.  Only keep the overloads that return a
	translation_unit_sptr, forcing users of the API to own a proper
	reference on the resulting translation_unit pointer.  That is
	important to handle the life time of the global data of the type
	system that need to be cleared when the last translation unit is
	de-allocated.
	* src/abg-reader.cc (read_translation_unit_from_input): Make this
	return a translation_unit_sptr.
	(read_translation_unit_from_file)
	(read_translation_unit_from_buffer)
	(read_translation_unit_from_istream): Remove the overloads that do
	not return a translation_unit_sptr and that pass it as a
	parameter.  Only keep the overloads that return a
	translation_unit_sptr.
	(read_to_translation_unit): Make this return a
	translation_unit_sptr.
	* tests/print-diff-tree.cc (main): Adjust.
	* tests/test-diff-dwarf.cc (main): Likewise.
	* tests/test-ir-walker.cc (main): Likewise.
	* tests/test-read-dwarf.cc (main): Likewise.
	* tests/test-read-write.cc (main): Likewise.
	* tools/abicompat.cc (main): Likewise.
	* tools/abidiff.cc (main): Likewise.
	* tools/abidw.cc (main): Likewise.
	* tools/abilint.cc (main): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-09 11:12:40 +02:00
Dodji Seketeli
a2601a596a Factorize incompatible and subtype changes detection
In abg-comparison.h, there is no function to test if a given
corpus_diff carries incompatible or subtype (after having applied
suppression specifications) ABI changes.  So this patch factorizes the
code of abidiff.cc to provide these features to corpus_diff.

	* include/abg-comparison.h (corpus_diff::{has_incompatible_changes,
	has_net_subtype_changes}): Declare new member functions.
	* src/abg-comparison.cc (corpus_diff::{has_incompatible_changes,
	has_net_subtype_changes}): Define them.
	* abidiff.cc (main): Use the new member functions above.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-09 11:10:24 +02:00
Dodji Seketeli
fe9fa7a05f Support filtering out just one alias of a function
Suppose a function private_foo() has a symbol private_foo and also a
another one (an alias) named public_foo.  Then suppose we want to
filter out sub-type changes to private_foo().  But then we still want
to see changes to public_foo.

This patch does add this feature.  The [suppress_function] directive
now has a new (hidden) boolean 'allow_other_aliases' property.  When
set to 'yes' or 'true', if the function being looked at has an alias
symbol that does *NOT* match the other properties of the directive,
then the directive doesn't suppress reports for the function.  This
new  property is set to yes by default.

This means that when a function has got multiple aliases, to suppress
the function, one needs to write a regular expression that matches the
names of aliases.  Otherwise the function will not be suppressed.

	* include/abg-comparison.h (function_suppression::{get,
	set}_allow_other_aliases): Declare new member functions.
	* src/abg-comparison.cc
	(function_suppression::priv::allow_other_aliases_): New data
	member.
	(function_suppression::priv::priv): Initialize it to 'true'.
	(function_suppression::{get, set}_allow_other_aliases): Define new
	member functions.
	(read_function_suppression): Parse the new "allow_other_aliases"
	property.
	(function_suppression::suppresses_function): Update to evaluate
	the new 'allow_other_aliases' property when there is a property to
	match against some a symbol name of the function.
	(corpus_diff::report): Fix the printing of function aliases when
	printing sub-type changes to properly emit the plural of the word
	'symbol' when the function has several aliases.
	* include/abg-ir.h (elf_symbol::get_number_of_aliases): Declare
	new member function.
	* src/abg-ir.cc (elf_symbol::get_number_of_aliases): Define new
	member function.
	* doc/manuals/libabigail-concepts.rst: Update manual.
	* tests/data/test-diff-dwarf/test5-report.txt: Adjust.
	* tests/data/test-diff-suppr/libtest23-alias-filter-v0.so: New
	test input.
	* tests/data/test-diff-suppr/libtest23-alias-filter-v1.so: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-0.suppr: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-1.suppr: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-2.suppr: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-3.suppr: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-4.suppr: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-report-0.txt: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-report-1.txt: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-report-2.txt: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-report-3.txt: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-report-4.txt: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-report-5.txt: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-v0.c: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-v1.c: Likewise.
	* tests/data/test-diff-suppr/test23-alias-filter-version-script: Likewise.
	* tests/data/Makefile.am: Add the new test stuff to source
	distribution.
	* tests/test-diff-suppr.cc (in_out_spec): Add the tests inputs
	above to the list of input to run over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-02 17:15:35 +02:00
Dodji Seketeli
25dc383b40 Show aliases of functions with changed sub-types
The report emitted by abidiff now tells the user about the aliases of
the current function, when that function has some sub-type changes.

	* include/abg-ir.h (elf_symbol::get_aliases_id_string): Declare
	new overload.
	* src/abg-ir.cc (elf_symbol::get_aliases_id_string): Define new
	overload.
	* src/abg-comparison.cc (corpus_diff::report): For functions with
	sub-type changes report their aliases.  Do not do this if the
	function is a constructor or destructor because these almost
	always have aliases, at least with GCC and the developer most
	certainly has not done anything special for that; she would thus
	be uselessly surprised by that remote implementation detail.
	* tests/data/test-diff-dwarf/test5-report.txt: Adjust test.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-01 11:03:16 +02:00
Dodji Seketeli
79383f937c Apply suppression specifications to added and removed functions and variables
Until now, specifications for suppressing change reports were applied
only to functions and variables that have sub-type changes.  Change
reports about function and variables that were added or removed could
not be suppressed.

This patch makes suppression specifications to apply to added and
removed functions and variables too.  They can also apply to function
and variable symbols that are not referenced by any debug info.

The patch also fixes some typo and formatting glitches and updates
some existing tests accordingly.

	* include/abg-comparison.h (is_type_suppression)
	(is_function_suppression): Declare new functions.
	({function, variable}_suppression::change_kind): Declare new enum.
	(function_suppression::{parse_change_kind, get_change_kind,
	set_change_kind, suppresses_function,
	suppresses_function_symbol}): Declare new member functions.
	(variable_suppression::{parse_change_kind, get_change_kind,
	set_change_kind, suppresses_variable, suppresses_variable,
	suppresses_variable_symbol}): Declare new member functions.
	(operator{&,|}): Declare new operators for
	function_suppression::change_kind and
	variable_suppression::change_kind enums.
	(corpus_diff::diff_stats::{num_removed_func_filtered_out,
	net_num_func_removed, num_added_func_filtered_out,
	net_num_func_added, num_removed_vars_filtered_out,
	net_num_vars_removed, num_added_vars_filtered_out,
	net_num_vars_added, num_removed_func_syms_filtered_out,
	num_added_func_syms_filtered_out, net_num_removed_func_syms,
	net_num_added_func_syms, num_added_var_syms_filtered_out,
	num_removed_vars_filtered_out, net_num_removed_var_syms,
	net_num_added_var_syms}): Declare new member functions.
	(corpus_diff::diff_stats::num_changed_vars_filtered_out): Renamed
	corpus_diff::diff_stats::num_vars_filtered_out into this.
	(corpus_diff::diff_stats::num_changed_func_filtered_out): Renamed
	corpus_diff::diff_stats::num_func_filtered_out into this.
	* src/abg-comparison.cc (is_type_suppression)
	(is_function_suppression): Define new
	function.
	(function_suppression::priv::change_kind): New data member.
	(function_suppression::priv): Initialize it.
	(function_suppression::{parse_change_kind, get_change_kind,
	set_change_kind, suppresses_function,
	suppresses_function_symbol}): Define new member functions.
	(operator{&,|}): Define new operators for the new
	function_suppression::change_kind enum.
	(function_suppression::suppresses_diff): Re-write this in terms of
	the new function_suppression::suppresses_function() function.
	(read_function_suppression): Support reading the new "change_kind"
	property.
	(variable_suppression::priv::change_kind_): New data member.
	(variable_suppression::priv::priv): Initialize it.
	(variable_suppression::{parse_change_kind, get_change_kind,
	set_change_kind, suppresses_variable,
	suppresses_variable_symbol}): Define new member functions.
	(is_variable_suppression): Define new function.
	(operator{&,|}): Define new operators for
	variable_suppression::change_kind enum.
	(variable_suppression::suppresses_diff): Re-write in terms of the
	new variable_suppression::suppresses_variable function.
	(read_variable_suppression): Support reading the new "change_kind"
	property.
	(corpus_diff::diff_stats::priv::{num_removed_func_filtered_out,
	num_added_func_filtered_out, num_removed_vars_filtered_out,
	num_added_vars_filtered_out, num_removed_func_syms_filtered_out,
	num_added_func_syms_filtered_out,
	num_removed_var_syms_filtered_out,
	num_added_var_syms_filtered_out}): New data members.
	(corpus_diff::diff_stats::priv::num_changed_func_filtered_out):
	Renamed the data member num_func_filtered_out into this.
	(corpus_diff::diff_stats::priv::num_changed_vars_filtered_out):
	Renamed data member num_vars_filtered_out into this.
	(corpus_diff::diff_stats::priv::priv): Initialize the new data
	members.
	(corpus_diff::diff_stats::{num_removed_func_filtered_out,
	num_removed_func_filtered_out, net_num_func_removed,
	net_num_func_added, num_added_func_filtered_out,
	net_num_func_added, num_removed_vars_filtered_out,
	num_removed_vars_filtered_out, net_num_vars_removed,
	num_added_vars_filtered_out, net_num_vars_added,
	num_removed_func_syms_filtered_out,
	num_added_func_syms_filtered_out, net_num_removed_func_syms,
	net_num_added_func_syms, num_added_var_syms_filtered_out,
	num_removed_vars_filtered_out, net_num_removed_var_syms,
	net_num_added_var_syms}): Define new member functions.
	(corpus_diff::diff_stats::num_changed_func_filtered_out): Renamed
	corpus_diff::diff_stats::num_func_filtered_out into this.
	(corpus_diff::diff_stats::num_changed_vars_filtered_out): Renamed
	corpus_diff::diff_stats::num_vars_filtered_out into this.
	(corpus_diff::diff_stats::{net_num_func_changed,
	net_num_vars_changed}): Adjust.
	(corpus_diff::priv::{suppressed_deleted_fns_,
	suppressed_added_fns_, suppressed_deleted_vars_,
	suppressed_added_vars_, suppressed_added_unrefed_fn_syms_,
	suppressed_deleted_unrefed_fn_syms_,
	suppressed_added_unrefed_var_syms_,
	suppressed_deleted_unrefed_fn_syms_}): New data members.
	(corpus_diff::priv::{apply_suppressions_to_added_removed_fns_vars,
	deleted_function_is_suppressed, added_function_is_suppressed,
	deleted_variable_is_suppressed, added_variable_is_suppressed,
	added_unrefed_fn_sym_is_suppressed,
	deleted_unrefed_fn_sym_is_suppressed,
	added_unrefed_var_sym_is_suppressed,
	deleted_unrefed_var_sym_is_suppressed}): Define member functions.
	(function_is_suppressed, variable_is_suppressed): Define new
	functions.
	(corpus_diff::priv::apply_filters_and_compute_diff_stats): Compute
	stats for filtered added or removed functions, variables and their
	symbols.
	(corpus_diff::priv::emit_diff_stats): Emit diff stats for filtered
	added or removed functions, variables and symbols.
	(corpus_diff::report): Support suppressed reports about added or
	removed functions, variables and symbols.  Fixed a typo that was
	in there for a while.  Note that that fix requires updating some
	regression tests, and the part of this patch that touches
	regression tests does that.
	(apply_suppressions):  In the overload for corpus_diff, apply the
	suppression to added or removed functions and variables.
	* doc/manuals/libabigail-concepts.rst: Update this manual to
	reflect the changes above.  Also, perform an extensive cleanup of
	the manual to introduce more section titles to make it easier to
	navigate the document using the table of content.
	* tests/data/test-abicompat/test2-var-removed-report-0.txt:
	Adjust.
	* tests/data/test-diff-dwarf/test0-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test12-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test18-alias-sym-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test19-soname-report-0.txt: Likewise.
	* tests/data/test-diff-dwarf/test7-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test8-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test9-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test16-syms-only-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test17-non-refed-syms-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test28-vtable-changes-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test0-report.txt: Likewise.
	* tests/data/test-diff-filter/test01-report.txt: Likewise.
	* tests/data/test-diff-filter/test13-report.txt: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-v0.o: Add new test
	material.
	* tests/data/test-diff-filter/test15-0-report.txt: Likewise.
	* tests/data/test-diff-filter/test2-report.txt: Likewise.
	* tests/data/test-diff-filter/test21-compatible-vars-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test24-compatible-vars-report-1.txt:
	Likewise.
	* test-diff-suppr/test15-suppr-added-fn-v1.o: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-0.suppr: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-1.suppr: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-2.suppr: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-3.suppr: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-4.suppr: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-report-0.txt: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-report-1.txt: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-report-2.txt: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-report-3.txt: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-report-4.txt: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-report-5.txt: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-v0.cc: Likewise.
	* test-diff-suppr/test15-suppr-added-fn-v1.cc: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-v0.o: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-v1.o: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-0.suppr: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-1.suppr: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-2.suppr: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-3.suppr: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-4.suppr: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-report-0.txt: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-report-1.txt: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-report-2.txt: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-report-3.txt: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-report-4.txt: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-report-5.txt: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-v0.cc: Likewise.
	* test-diff-suppr/test16-suppr-removed-fn-v1.cc: Likewise.
	* test-diff-suppr/test17-suppr-added-var-v0.o: Likewise.
	* test-diff-suppr/test17-suppr-added-var-v1.o: Likewise.
	* test-diff-suppr/test17-suppr-added-var-0.suppr: Likewise.
	* test-diff-suppr/test17-suppr-added-var-1.suppr: Likewise.
	* test-diff-suppr/test17-suppr-added-var-2.suppr: Likewise.
	* test-diff-suppr/test17-suppr-added-var-3.suppr: Likewise.
	* test-diff-suppr/test17-suppr-added-var-4.suppr: Likewise.
	* test-diff-suppr/test17-suppr-added-var-report-0.txt: Likewise.
	* test-diff-suppr/test17-suppr-added-var-report-1.txt: Likewise.
	* test-diff-suppr/test17-suppr-added-var-report-2.txt: Likewise.
	* test-diff-suppr/test17-suppr-added-var-report-3.txt: Likewise.
	* test-diff-suppr/test17-suppr-added-var-report-4.txt: Likewise.
	* test-diff-suppr/test17-suppr-added-var-report-5.txt: Likewise.
	* test-diff-suppr/test17-suppr-added-var-v0.cc: Likewise.
	* test-diff-suppr/test17-suppr-added-var-v1.cc: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-v0.o: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-v1.o: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-0.suppr: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-1.suppr: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-2.suppr: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-3.suppr: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-4.suppr: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-report-0.txt: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-report-1.txt: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-report-2.txt: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-report-3.txt: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-report-4.txt: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-report-5.txt: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-v0.cc: Likewise.
	* test-diff-suppr/test18-suppr-removed-var-v1.cc: Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-v0.o: New
	test input.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-v1.o:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-0.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-1.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-2.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-3.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-4.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-report-0.txt:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-report-2.txt:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-report-3.txt:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-report-4.txt:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-report-5.txt:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-v0.cc:
	Likewise.
	* tests/data/test-diff-suppr/test19-suppr-added-fn-sym-v1.cc:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-v0.o:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-v1.o:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-0.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-1.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-2.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-3.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-4.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-report-0.txt:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-report-2.txt:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-report-3.txt:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-report-4.txt:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-report-5.txt:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-v0.cc:
	Likewise.
	* tests/data/test-diff-suppr/test20-suppr-removed-fn-sym-v1.cc:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-v0.o:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-v1.o:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-0.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-1.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-2.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-3.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-4.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-report-0.txt:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-report-2.txt:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-report-3.txt:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-report-4.txt:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-report-5.txt:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-v0.cc:
	Likewise.
	* tests/data/test-diff-suppr/test21-suppr-added-var-sym-v1.cc:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-v0.o:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-v1.o:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-0.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-1.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-2.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-3.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-4.suppr:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-report-0.txt:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-report-2.txt:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-report-3.txt:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-report-4.txt:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-report-5.txt:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-v0.cc:
	Likewise.
	* tests/data/test-diff-suppr/test22-suppr-removed-var-sym-v1.cc:
	Likewise.
	* tests/data/Makefile.am: Add the new test materials above to source
	distribution.
	* tests/test-diff-suppr.cc (in_out_specs): Add the new tests
	material above to the list of test inputs this harness has to run
	over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-06-24 12:09:53 +02:00
Dodji Seketeli
9e64891731 Do not compare static data members when comparing types
The comparison code was too eager in comparing class types because it
was comparing static data members in the process.  This was causing
some spurious false positives about functions or variables sub-type
changes.  This patch fixes that by not comparing static data members
when comparing class types.

	* include/abg-ir.h (class_decl::get_non_static_data_members):
	Declare new data members.
	* src/abg-comparison.cc
	(class_diff::ensure_lookup_tables_populated): Only look at
	non-static data members.
	(compute_diff): In the overload for class_decl, only compare
	non-static data members.
	* src/abg-hash.cc (class_decl:#️⃣:operator()): Do not hash
	static data members members hashing a class_decl.
	* src/abg-ir.cc (class_decl::priv::data_members_): New data
	member.
	(class_decl::priv::priv): When initializing data members, store
	the non-static data members on the side, in the new
	class_decl::priv::non_static_data_members_ data member.
	(class_decl::get_non_static_data_members): Define member function.
	(class_decl::add_data_member): Store the non-static data members
	on the side in class_decl::priv::non_static_data_members_.
	(equals): In the overload for class_decl, do not take in account
	static data members when running the comparison.
	* tests/data/test-diff-dwarf/test7-report.txt: Adjust.
	* tests/data/test-diff-filter/test12-report.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-06-23 13:17:37 +02:00
Dodji Seketeli
723222568e Change the linkage name only when necessary
Up to now the linkage name of a declaration was set to the name of
it's underlying symbol.  This patch changes that to instead honour
what the DW_AT_linkage_name DWARF property says, unless the value of
that property is either missing or wrong.

	* include/abg-ir.h (elf_symbol::get_alias_from_name): Declare new
	member function.
	* src/abg-ir.cc (elf_symbol::get_alias_from_name): Define it.
	* src/abg-dwarf-reader.cc (build_var_decl, build_function_decl):
	Once the linkage name is supposed to contain the value of the
	DW_AT_linkage_name attribute, set it the name of the underlying
	symbol only if value of DW_At_linkage_name is missing or different
	from the names of all the aliases of the underlying symbol.
	* tests/data/test-read-dwarf/test2.so.abi: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-06-04 13:30:16 +02:00
Dodji Seketeli
afd0411b64 Various white space cleanups
* include/abg-comparison.h: Remove various useless vertical white
	spaces.
	* tests/test-diff-dwarf.cc (in_out_spec): Fix indentation of some
	entries.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-06-04 13:30:16 +02:00
Dodji Seketeli
0cd814766b Support new 'accessed_through' suppression property
It turned out it's important to be able to suppress changes about
types that are reachable from a function parameter only through e.g, a
pointer or a reference, so that only changes types that are reachable
directly from a function parameter are emitted.

This patch adds that feature.

While doing this, I noticed this: Suppose a diff node D2 is marked as
being redundant with a diff node D1 seen previously.  So only D1 is
reported; D2 is not, because it's been filtered out, because it's
redundant with D1.  But then suppose D1 is filtered out, due to a
suppression specification.  At that point, D2 should not be marked
redundant anymore, and should be reported.

Of course, the code before this patch was wrongly filtering D2 *and*
D1 out.  So this patch fixes that.

	* include/abg-comparison.h (enum type_suppression::reach_kind):
	Define new enum.
	(type_suppression::{get_consider_reach_kind,
	set_consider_reach_kind, get_reach_kind,
	mark_last_diff_visited_per_class_of_equivalence,
	clear_last_diffs_visited_per_class_of_equivalence,
	get_last_visited_diff_of_class_of_equivalence}): Declare new
	member functions.
	* src/abg-comparison.cc (diff_has_ancestor_filtered_out)
	(read_suppression_reach_kind): Define static function.
	(type_suppression::priv::{consider_reach_kind_, reach_kind_}):
	Define new data members.
	(type_suppression::priv::priv): Take a new reach_kind parameter.
	(type_suppression::type_suppression): Adjust to new prototype of
	priv constructor.
	(type_suppression::{get_consider_reach_kind,
	set_consider_reach_kind, get_reach_kind, set_reach_kind}): Define
	new member functions.
	(type_suppression::suppresses_diff): Interpret the result of
	type_suppression::get_reach_kind() to determine if the suppression
	specification suppresses a given diff node.
	(read_type_suppression): Support reading the content of the
	"accessed_through" property.
	(diff_context::priv::last_visited_diff_node_): New data member.
	(diff_context::{mark_last_diff_visited_per_class_of_equivalence,
	clear_last_diffs_visited_per_class_of_equivalence,
	get_last_visited_diff_of_class_of_equivalence}): Define new data
	members.
	(redundancy_marking_visitor::visit_begin): So if the current diff
	node has already been visited, but if the previously visited node
	has been filtered out, then do not mark this node as being
	redundant.  And mark the current diff node as being the last
	visited one in its class of equivalence.
	(categorize_redundancy): Clear the map of diff nodes visited per
	class of equivalence.
	* doc/manuals/libabigail-concepts.rst: Document the new
	'accessed_through' property.
	* tests/data/test-diff-suppr/test13-suppr-through-pointer-0.suppr:
	New test input data.
	* tests/data/test-diff-suppr/test13-suppr-through-pointer-report-{0,1}.txt:
	Likewise.
	* tests/data/test-diff-suppr/libtest13-suppr-through-pointer-v{0,1}.so:
	New test input binaries.
	* tests/data/test-diff-suppr/test13-suppr-through-pointer-v{0,1}.cc:
	Source code of the test input binaries above.
	* tests/data/test-diff-suppr/test14-suppr-non-redundant-0.suppr:
	New test input data.
	* tests/data/test-diff-suppr/test14-suppr-non-redundant-report-0.txt:
	Likewise.
	* tests/data/test-diff-suppr/test14-suppr-non-redundant-v{0,1}.o:
	New test input binaries.
	* tests/data/test-diff-suppr/test14-suppr-non-redundant-v{0,1}.cc:
	Source code of the binaries above.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-06-04 13:29:32 +02:00
Dodji Seketeli
85929105f5 Fix redundancy marking for change of types used directly
If a type T is used directly (i.e, not through a pointer or reference)
as a function parameter or as a base class, a change in T should never
be marked as redundant in that context.  Otherwise, the change in that
context might be filtered out, possibly hiding real ABI incompatible
changes.

This patch implements this policy.

Also, it turned out in some circumstances, we where marking the first
visited diff node of a given class of equivalence of nodes as being
redundant, while we should only mark the *subsequently* visited nodes
of that class of equivalence as visited.  The patch also fixes that.

	* include/abg-comparison.h (pointer_map): Make this be a map of
	{size_t, size_t} pairs, rather than {size_t, bool}, so that each
	pointer in the map can be associated to another one.
	(diff_context::diff_has_been_visited): Return the pointer to the
	first diff node of the equivalence class that has been visited.
	* src/abg-comparison.cc (is_pointer_diff, is_reference_diff)
	(is_reference_or_pointer_diff, is_fn_parm_diff, is_base_diff)
	(is_child_node_of_function_parm_diff, is_child_node_of_base_diff):
	Define new static functions.
	(diff_context::diff_has_been_visited): Return the pointer to the
	first diff node of the equivalence class that has been visited.
	(diff_context::mark_diff_as_visited): Save the pointer to the
	first diff node of a given class of equivalence that has been
	visited.
	(redundancy_marking_visitor::visit_begin): If a diff node is a
	child node of a function parameter diff or base diff node and if
	it's not a pointer or reference diff node, then do not mark it as
	redundant.  Also, make sure to not mark the first diff node of a
	given class of equivalence that has been visited, as redundant;
	only the other subsequent nodes should be marked redundant; we
	were hitting this case because of an optimization that makes
	equivalent class diff nodes to share their private (pimpl) data.
	* tests/data/test-diff-filter/test29-finer-redundancy-marking-v{0,1}.o:
	New test input binaries.
	* tests/data/test-diff-filter/test29-finer-redundancy-marking-v{0,1}.cc:
	Source code of the new test input binaries above.
	* tests/data/test-diff-filter/test29-finer-redundancy-marking-report-0.txt:
	New test input.
	* tests/data/Makefile.am: Add the new test material above to the
	source distribution.
	* tests/test-diff-filter.cc (in_out_specs): Make this test harness
	run over the additional test input above.
	* tests/data/test-diff-suppr/test5-fn-suppr-report-0.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-06-03 12:13:54 +02:00
Dodji Seketeli
41d0ad035f Fix symbols comparison
While working on something else, I noticed that the code for handling
copying symbols (and their aliases) was broken, and so comparing two
symbols which main name were different by which had aliases that were
equal was wrongly resulting in the two symbol being different. I think
we shouldn't actually copy symbols and their aliases.  Once a symbol
is allocated, interested code should just manipulate that symbol by
address rather than by value an thus do away with the copying.

The patch does that, essentially.  In the implementation of a symbol,
the aliases as well as the main symbol are now weak pointers, rather
than naked pointers.  Numerous API entry points that were taking
containers of elf_symbol (and were copying elf_symbols over) are not
taking containers of smart pointers to elf_symbol.  Copying of
instances of elf_symbol is now thus disabled.

As a result many tests that were exercising elf_symbols (with alias)
comparison have been updated.

As a result, many empty sub-result of PR libabigail/PR17948 are now
fixed.

	* include/abg-ir.h (elf_symbol_wptr): New typedef.
	(elf_symbol): Make the constructors and assignment operator
	private.  The type can neither be copied nor created with the new
	operator.
	(elf_symbol::create): New static member function.
	(elf_symbol::{get_main_symbol, get_next_alias, add_alias}):
	Adjust.
	( compute_aliases_for_elf_symbol): Likewise.
	(elf_symbol::operator=): Make this private.
	(elf_symbol::get_alias_which_equals): Declare new member function.
	* src/abg-comp-filter.cc (function_name_changed_but_not_symbol):
	Adjust.
	* src/abg-comparison.cc
	(class_diff::ensure_lookup_tables_populated): Adjust.
	* src/abg-corpus.cc
	(corpus::priv::build_unreferenced_symbols_tables): Likewise.
	* include/abg-dwarf-reader.h (lookup_symbol_from_elf)
	(lookup_public_function_symbol_from_elf): Adjust.
	* src/abg-dwarf-reader.cc (lookup_symbol_from_sysv_hash_tab)
	(lookup_symbol_from_gnu_hash_tab, lookup_symbol_from_elf_hash_tab)
	(lookup_symbol_from_symtab, lookup_symbol_from_elf)
	(lookup_public_function_symbol_from_elf)
	(lookup_public_variable_symbol_from_elf): Adjust.
	(read_context::lookup_elf_symbol_from_index): Likewise.
	(read_context::lookup_elf_fn_symbol_from_address): Likewise.
	(read_context::lookup_elf_var_symbol_from_address): Likewise.
	(read_context::lookup_public_function_symbol_from_elf): Likewise.
	(read_context::lookup_public_variable_symbol_from_elf): Likewise.
	(read_context::load_symbol_maps): Likewise.
	(build_var_decl, build_function_decl): Likewise.
	* src/abg-ir.cc (elf_symbol::priv::{main_symbol_, next_alias_}):
	Change the type of these from elf_symbol* to elf_symbol_wptr.
	(elf_symbol::priv::priv): Adjust.
	(elf_symbol::{create, get_alias_which_equals}): Define new functions.
	(textually_equals): Likewise.
	(elf_symbol::{get_main_symbol, is_main_symbol, get_next_alias,
	add_alias}): Adjust to return or take elf_symbol_sptr type, rather
	than a elf_symbol* one.
	(elf_symbol::{get_aliases_id_string, does_alias}): Adjust.
	(compute_alias_for_elf_symbol): Likewise.
	(elf_symbol::operator==): Two symbols A and B are now equal if A
	has at least one alias that is textually equal to B.
	(equals): In the overload for function_decls, in the part where we
	compare the decl_base part of the functions without considering
	their decl names, we now also omit considering their linkage
	names, because we compared they symbols before.
	* tools/abisym.cc (main): Adjust.
	* tests/data/test-diff-dwarf/test12-report.txt: Adjust.
	* tests/data/test-diff-dwarf/test12-report.txt: Adjust.
	* tests/data/test-diff-dwarf/test18-alias-sym-report-0.txt: Adjust.
	* tests/data/test-diff-dwarf/test8-report.txt: Adjust.
	* tests/data/test-diff-filter/test10-report.txt: Adjust.
	* tests/data/test-diff-filter/test13-report.txt: Adjust.
	* tests/data/test-diff-filter/test2-report.txt: Adjust.
	* tests/data/test-diff-filter/test20-inline-report-0.txt: Adjust.
	* tests/data/test-diff-filter/test20-inline-report-1.txt: Adjust.
	* tests/data/test-diff-filter/test9-report.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-06-02 00:07:02 +02:00
Dodji Seketeli
d0bd599b4b Support specifying data member insertion in suppressions
This patch is for supporting this kind of things:

    [suppress_type]
      name = S
      has_data_member_inserted_between = {8, end}

or:

    [suppress_type]
      name = S
      has_data_members_inserted_between = {{8, 31}, {64, end}}

or:

    [suppress_type]
      name = S
      has_data_members_inserted_at = offset_after(member0)

How cool is that, heh?

Anyway, to do this, the patch adds support for tuple values (i.e,
lists of values) in INI files.

Then on top of that the patch adds support for the specific
has_data_member_inserted_between, has_data_members_inserted_between
and has_data_members_inserted_at properties.

	* include/abg-comparison.h (type_suppression::insertion_range):
	Declare new type.
	(type_suppression::insertion_ranges): Declare new typedef.
	(type_suppression::{s,g}et_data_member_insertion_ranges): Declare
	new member functions.
	(is_integer_boundary, is_fn_call_expr_boundary): Declare new
	functions.
	(type_suppression::insertion_range::{boundary, integer_boundary,
	fn_call_expr_boundary}): Define new types.
	* src/abg-comparison.cc:
	(struct type_suppression::insertion_range::priv): New type.
	(type_suppression::insertion_range::{insertion_range, begin,
	end}): Define new member functions.
	(type_suppression::priv::insertion_ranges_): Add data member.
	(type_suppression::{s,g}et_data_member_insertion_ranges): Define
	new member functions.
	(type_suppression::insertion_range::boundary::priv): Define new
	type.
	(type_suppression::insertion_range::boundary::{boundary,
	~boundary}): Define new member functions.
	(type_suppression::insertion_range::integer_boundary::priv):
	Define new type.
	(type_suppression::insertion_range::integer_boundary::{integer_boundary,
	as_integer, operator int, ~integer_boundary}): Define member
	functions.
	(type_suppression::insertion_range::fn_call_expr_boundary::priv):
	Define new type.
	(type_suppression::insertion_range::fn_call_expr_boundary::{fn_call_expr_boundary,
	as_function_call_expr, operator ini::function_call_expr_sptr}):
	Define new member functions.
	(type_suppression::insertion_range::{create_integer_boundary,
	type_suppression::insertion_range::create_fn_call_expr_boundary,
	type_suppression::insertion_range::eval_boundary}): Define new
	member functions.
	(is_integer_boundary, is_fn_call_expr_boundary): Define new
	functions.
	(read_type_suppression, read_function_suppression)
	(read_variable_suppression): Support the new kinds of
	property-related types. Aslo, in read_type_suppression, support
	the new properties has_data_member_inserted_at,
	has_data_member_inserted_between and
	has_data_members_inserted_between.
	(type_suppression::suppresses_diff): If we are looking at a type
	diff node that has inserted data members, evaluate the insertion
	ranges of the current type_suppression and see if they match the
	inserted data members.
	* include/abg-ini.h (property, simple_property, property_value)
	(string_property_value, tuple_property_value, function_call_expr):
	Declare new types.
	(property_sptr, property_value_sptr, string_property_value_sptr)
	(tuple_property_value_sptr): Declare new typedefs.
	(is_string_property_value, is_tuple_property_value)
	(is_simple_property, is_tuple_property, read_function_call_expr):
	Declare new functions.
	* src/abg-ini.cc (char_is_white_space, char_is_comment_start)
	(char_is_delimiter, char_is_property_value_char)
	(char_is_section_name_char, char_is_property_name_char)
	(char_is_comment_start, char_is_white_space)
	(remove_trailing_white_spaces, is_string_property_value)
	(is_tuple_property_value, is_simple_property, is_tuple_property)
	(write_property_value, char_is_function_name_char)
	(char_is_function_argument_char): Define new functions.
	(property::priv, tuple_property_value::priv)
	(simple_property::priv, tuple_property::priv): Define new types.
	(property::{property, get_name, set_name, ~property}): Define new
	member functions.
	(struct property_value::priv): Define new type.
	(property_value::{property_value, get_kind, operator const
	string&(), ~property_value}): Define new member functions.
	(struct string_property_value::priv): Define new type.
	(string_property_value::{string_property_value, set_content,
	as_string, operator string()}, ~string_property_value): Define new
	member functions.
	(tuple_property_value::{tuple_property_value, get_value_items,
	~tuple_property_value, as_string}): Likewise.
	(simple_property::{simple_property, get_value, set_value,
	~simple_property}): Likewise.
	(tuple_property::{tuple_property, set_value, get_value}):
	Likewise.
	(config::section::find_property): Adjust return type.
	(read_context::{char_is_delimiter, char_is_property_value_char,
	char_is_section_name_char, char_is_property_name_char,
	char_is_comment_start, char_is_white_space}): Remove these from
	here as they got moved them to be non-member functions above.
	(read_context::read_property_value): Return a property_value_sptr
	and do not take any parameter anymore.
	(read_context::{read_string_property_value,
	read_tuple_property_value, read_function_name,
	read_function_argument, read_function_call_expr}): Define new
	member functions.
	(read_context::read_property): Adjust return type.  Also, change to read
	the different new kinds of properties values.
	(function_call_expr::priv): Define new type.
	(function_call_expr::{function_call_expr, get_name,
	get_arguments}): New member functions.
	(read_context::read_section): Adjust.
	(write_property, write_section): Adjust.
	* tests/data/test-diff-suppr/libtest{11,12}-add-data-member-v{0,1}.so:
	New test input binaries.
	* tests/data/test-diff-suppr/test{11,12}-add-data-member-{0,1}.suppr:
	New input suppression files.
	* tests/data/test-diff-suppr/test11-add-data-member-{2,3,4}.suppr:
	Add new test input files.
	* tests/data/test-diff-suppr/test{11,12}-add-data-member-report-{0,1}.txt:
	New reference output files.
	* tests/data/test-diff-suppr/test12-add-data-member-report-2.txt:
	Likewise.
	* tests/data/test-diff-suppr/test{11,12}-add-data-member-v{0,1}.cc:
	Source code for the new binaries above.
	* tests/test-diff-suppr.cc (in_out_specs): Add new test inputs.
	* tests/data/Makefile.am: Add the new test related files above to
	source distribution.
	* doc/manuals/libabigail-concepts.rst: Document the new properties
	has_data_member_inserted_at, has_data_member_inserted_between and
	has_data_members_inserted_between.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-05-24 23:43:02 +02:00
Dodji Seketeli
6ce6f160b5 Better detection of parameter sub-type changes
Just looking at if the name of the changed type hasn't changed is not
enough for detecting a sub-type change; that will be fooled by
compatible changes (changes involving typedefs).  So this patch looks
through compatible changes for that matter.

	* include/abg-fwd.h (type_has_sub_type_changes): Declare new
	function.
	* src/abg-ir.cc (type_has_sub_type_changes): Define it.
	* src/abg-comparison.cc (fn_parm_diff::report): Use the new
	function type_has_sub_type_changes() instead of just looking at
	name changes.
	* tests/data/test-diff-dwarf/test4-report.txt: Adjust this
	reference test output.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-05-06 10:20:15 +02:00
Dodji Seketeli
5c08779f5d Add debugging function for function parameters
* include/abg-ir.h
	(function_decl::parameter::get_pretty_representation): Declare new
	virtual member function.
	* src/abg-ir.cc
	(function_decl::parameter::get_pretty_representation): Define it.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-05-06 10:13:02 +02:00
Dodji Seketeli
13424c9412 Add a debugging function for type_or_decl_base*
* include/abg-fwd.h (get_pretty_representation): Declare new
	overload for type_or_decl_base*.
	* src/abg-ir.cc (get_pretty_representation): Define it and express
	the previous overload for type_or_decl_base_sptr in terms of this
	new one.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-05-06 09:49:00 +02:00
Dodji Seketeli
5852910238 Return a reference to smart pointer for the void type node
This is just a small optimization in the passing

	* src/abg-ir.h (type_decl::get_void_type_decl): Return a reference
	to the smart pointer initially returned.
	* src/abg-ir.cc (type_decl::get_void_type_decl): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-05-05 10:45:15 +02:00
Dodji Seketeli
9b4d20db90 Bug 18342 - Segmentation fault while comparing functions with variadic parameters
In the IR built from DWARF, a variadic variadic parameter has an empty
type.  Later during type comparison, comparing an empty (NULL) type
with other types proves to be troublesome.

This patch handles the issue by creating a new kind of
abigail::type_decl type specifically for variadic parameters.  This is
like what is done for void types.

After that it appears that the categorizing sub-system flags a change
of variadic type to non-variadic type as redundant if that change
appears several times on different functions.  We don't want that
because it can hide important changes we want to see.  The patch fixes
that too.

	* include/abg-fwd.h (is_array_type): New overload for a naked
	pointer.
	* include/abg-ir.h (type_decl::get_variadic_parameter_type_decl): Declare new
	static function.
	* src/abg-ir.cc (is_array_type): Define new function overload for
	naked pointers
	(type_decl::get_variadic_parameter_type_decl): Define new static
	function.
	* src/abg-dwarf-reader.cc (build_function_decl): The type of
	variadic parameter is now a special type_decl.
	* include/abg-comparison.h (is_diff_of_variadic_parameter_type)
	(is_diff_of_variadic_parameter): New function declarations.
	* src/abg-comparison.cc (is_diff_of_variadic_parameter_type)
	(is_diff_of_variadic_parameter): Define new functions.
	(compute_diff): Refuse to return a NULL
	diff for types.  Assert that the parameters are non-NULL.
	(report_size_and_alignment_changes): We are comparing arrays only
	if the two parameters are arrays.
	(fn_parm_diff::fn_parm_diff): Refuse that type diff for this diff
	node is non empty.
	(fn_parm_diff::report): Strengthen an assert.  Cleanup a comment.
	(redundancy_marking_visitor::visit_begin): Do not mark function
	type and variadic parms diff nodes as redundant for local changes.
	* tests/data/test-diff-dwarf/libtest26-added-parms-before-variadic-v{0,1}.so:
	New test input binaries.
	* tests/data/test-diff-dwarf/test26-added-parms-before-variadic-report.txt:
	New test output reference.
	* tests/data/test-diff-dwarf/test26-added-parms-before-variadic-v{0,1}.c:
	Source code of the new test input binaries above.
	* tests/data/Makefile.am: Add the new test stuff to source
	distribution.
	* tests/test-diff-dwarf.cc (in_out_specs): Add the new test inputs
	above to the set of input to run this test harness over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-05-05 10:45:06 +02:00
Dodji Seketeli
fc55e7f343 Make abidiff and abicompat return meaningful exit codes
As per https://sourceware.org/bugzilla/show_bug.cgi?id=18146, abidiff
the exit code of abidiff and abicompat is now a bit field that can be
inspected to know if the ABI change reported is incompatible for sure,
or if it needs user review of the output to decide.

This patch also updates the documentation.

	* doc/manuals/abicompat.rst: Update documentation for abicompat
	exit codes.
	* doc/manuals/abidiff.rst: Likewise for abidiff exit codes.
	* include/abg-tools-utils.h (enum abidiff_status): Declare new
	enum.
	(operator{|,&,|=}): Declare new operators for the new enum
	abidiff_status.
	(abidiff_status_has_error, abidiff_status_has_abi_change)
	(abidiff_status_has_incompatible_abi_change): Declare new
	functions.
	* src/abg-tools-utils.cc (operator{|,&,|=}): Define these new
	operators.
	(abidiff_status_has_error, abidiff_status_has_abi_change)
	(abidiff_status_has_incompatible_abi_change): Define new
	functions.
	* tests/test-diff-filter.cc (main): Adjust for the new exit code
	of abidiff.
	* tests/test-diff-suppr.cc (main): Likewise.
	* tests/test-abicompat.cc (main): Likewise.
	* tools/abicompat.cc (enum abicompat_status): Remove.
	(operator{|,&,|=}): Remove these operators for enum
	abicompat_status.
	(perform_compat_check_in_normal_mode)
	(perform_compat_check_in_weak_mode): Return abidiff_status instead
	of abicompat_status.  Adjust therefore.
	(main): Adjust to return abidiff_status now, instead of a just
	zero for all non-error cases.
	* tools/abidiff.cc (main): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-04-10 16:26:36 +02:00
Dodji Seketeli
a102a2f032 Add support for abicompat weak mode
This patch implements the weak mode of abicompat.  In this mode, just
the application and the new version of the library are provided.  The
types of functions and variables of the library that are consumed by
the application are compared to the types of the functions and
variables expected by the application.  The goal is to check if the
types of the declarations consumed by the application and provided by
the library are compatible with what the application expects.

The abicompat first gets the set of symbols undefined in the
application and exported by the library.  It then builds the set of
declarations exported by the library that have those symbols.  We call
these the set of declarations of the library that are consumed by the
application.

Note that the debug information for the application does not contain
the declarations of the functions/variables whose symbols are
undefined.  So we can not just read them to compare them to
declarations exported by the library.

But the *types* of the variables and the *sub-types* of the functions
whose symbols are undefined in the application are present in the
debug information of the application.

So in the weak mode, abicompat compare the *types* of the declarations
consumed by the application as expected by the application (described
by the debug information of the application) with the types of the
declarations exported by the library.

To do this a number of changes were necessary.

The patch builds a representation of all the types found in the
application's debug info.  Before that, only the types that are
reachable from exported declarations were represented.

The abidw tool got a new --load-all-types to test this new ability of
loading all types.

The patch also adds support for looking a type, not by name, but by
its internal representation.

In the comparison engine, function_type_diff is introduced to
represent changes between two function types.  For this, a new class
type_or_decl_base has been introduced in the IR.  It's now the base
class for both decl_base and type_base.  And abigail::comparison::diff
now takes two pointers of type_or_decl, not decl_base anymore.  So
function_type_diff can take two function_type now; not that a
function_type has no declaration so it doesn't inherit decl_base.  A
bunch of changes got made just to adjust to this modification.

A number of fixes were made too, to make this work, like adding
missing comparison operators, removing asserts that too strong, etc..

The patch also adjust the test suite as well as the documentation.

	* include/abg-fwd.h (class type_or_decl_base): Forward declare
	this.
	(is_decl, is_type, is_function_type, get_name, get_type_name)
	(get_function_type_name, get_pretty_representation)
	(lookup_function_type_in_corpus, lookup_type_in_translation_unit)
	(lookup_function_type_in_translation_unit)
	(synthesize_function_type_from_translation_unit)
	(hash_type_or_decl): New function declarations.
	* src/abg-corpus.cc (lookup_type_in_corpus)
	(lookup_function_type_in_corpus): Define new functions.
	* include/abg-ir.h
	(translation_unit::lookup_function_type_in_translation_unit):
	Declare new friend function.
	(class type_or_decl_base): Declare this.
	(operator==(const type_or_decl_base&, const type_or_decl_base&)):
	Declare new operator.
	(operator==(const type_or_decl_base_sptr&, const
	type_or_decl_base_sptr&)): Likewise.
	(class {decl_base, type_base}): Make these class inherit
	type_or_decl_base.
	(decl_base::get_member_scopes): New const overload.
	(bool operator==(const function_decl::parameter_sptr&,
	                 const function_decl::parameter_sptr&)): New operator.
	(function_type::get_parameters): Remove the non-const overload.
	(function_type::get_pretty_representation): Declare new member
	function.
	(method_type::get_pretty_representation): Likewise.
	* src/abg-ir.cc (bool operator==(const type_or_decl_base&, const
	type_or_decl_base&)): Define new equality operator.
	(bool operator==(const type_or_decl_base_sptr&, const
	type_or_decl_base_sptr&)): Likewise.
	(strip_typedef): Do not expect canonicalized types anymore.  Now
	the system accepts (and expects) canonicalized types in certain
	cases.  For instance, non-complete types and aggregated types that
	contain non-complete sub-types.
	(get_name, get_function_type_name, get_type_name)
	(get_pretty_representation, is_decl, is_type, is_function_type)
	(lookup_function_type_in_translation_unit)
	(synthesize_function_type_from_translation_unit)
	(lookup_type_in_scope, lookup_type_in_translation_unit): Define
	new functions or new overloads.
	(bool operator==(const function_decl::parameter_sptr&,
	                 const function_decl::parameter_sptr& r)): Define
	new operator.
	(function_type::get_parameters): Remove non-const overload.
	(function_type::get_pretty_representation): Define new function.
	(function_type::traverse): Adjust.
	(method_type::get_pretty_representation): Likewise.
	(function_decl::get_pretty_representation): Avoid emitting the
	type of cdtors.
	(hash_type_or_decl): Define new function.
	* include/abg-dwarf-reader.h (create_read_context)
	(read_corpus_from_elf): Take a new 'read_all_types' flag.
	* src/abg-dwarf-reader.cc (read_context::load_all_types_): New
	flag.
	(read_context::read_context): Initialize it.
	(read_context::canonical_types_scheduled): If some types still
	have non-canonicalized sub-types, then do not canonicalize them.
	(read_context::load_all_types): New member functions.
	(build_function_decl): Do not represent void return type like
	empty type anymore, rather, represent it like a void type node.
	(build_ir_node_from_die): When asked, load all types
	including those that are not reachable from an exported
	declaration.
	(create_read_context, read_corpus_from_elf): Take a new
	'load_all_types' flag and honour it.
	* src/abg-reader.cc (read_context::type_is_from_translation_unit):
	Support looking up function types in the current translation unit,
	now that we now how to lookup function types.
	* include/abg-comparison.h (diff_context::{has_diff_for, add_diff,
	set_canonical_diff_for, set_or_get_canonical_diff_for,
	get_canonical_diff_for}): Make these take instances of
	type_or_decl_base_sptr, instead of decl_base_sptr.
	(diff::diff): Likewise.
	(diff::{first_subject, second_subject}): Make these return
	type_or_decl_base_sptr instead of decl_base_sptr.
	(type_diff_base::type_diff_base): Make these take instances of
	type_or_decl_base_sptr instead of decl_base_sptr.
	(distinct_diff::distinct_diff): Likewise.
	(distinct_diff::{first, second}): Make these return
	type_or_decl_base_sptr instead of decl_base_sptr.
	(distinct_diff::entities_are_of_distinct_kinds): Make these take
	instances of type_or_decl_base_sptr instead of decl_base_sptr.
	(class function_type_diff): Create this new type.  It's a
	factorization of the function_decl_diff type.
	* src/abg-comparison.cc ():
	* src/abg-comp-filter.cc ({harmless, harmful}_filter::visit):
	Adjust as diff::{first,second}_subject() now returns a
	type_or_decl_base_sptr, no more a decl_base_sptr.
	(decls_type, decls_diff_map_type): Remove these typedefs and replace it with ...
	(types_or_decls_type, types_or_decls_diff_map_type): ... these.
	(struct {decls_hash, decls_equals): Remove these type sand replace them with ...
	(struct {types_or_decls_hash, types_or_decls_equals}): ... these.
	({type_suppression, variable_suppression}::suppresses_diff):
	Adjust.
	(diff_context::priv::decls_diff_map): Replace this with ...
	(diff_context::priv::types_or_decls_diff_map): ... this.
	(diff_context::{has_diff_for, add_diff, get_canonical_diff_for,
	set_canonical_diff_for, set_or_get_canonical_diff_for}): Take
	type_or_decl_base_sptr instead of decl_base_sptr.
	(diff::priv::{first, second}_subject): Make the type of these be
	type_or_decl_base_sptr, no more decl_base_sptr.
	(diff::priv::priv): Adjust for the subjects of the diff being of
	type type_or_decl_sptr now, no more decl_base_sptr.
	(diff_less_than_functor::operator()(const diff_sptr, const
	diff_sptr) const): Adjust.
	(diff::diff): djust for the subjects of the diff being of type
	type_or_decl_sptr now, no more decl_base_sptr.
	(diff::{first,second}_subject): Make the type of these be
	type_or_decl_base_sptr, no more decl_base_sptr.
	(report_size_and_alignment_changes): Likewise.
	(type_diff_base::type_diff_base): Make the type of this be
	type_or_decl_base_sptr instead of type_base_sptr.
	(distinct_diff::distinct_diff): Make this take instances of
	type_or_decl_base_sptr instead of decl_base_sptr.
	(distinct_diff::{first, second, entities_are_of_distinct_kinds}):
	Likewise.
	(distinct_diff::has_changes): Simplify logic.
	(distinct_diff::report): Adjust.
	(compute_diff_for_types): Add an additional case to support the
	new function_type.
	(report_size_and_alignment_changes): Make this take instances of
	type_or_decl_base_sptr instead of decl_base_sptr.
	(class_diff::priv::member_type_has_changed): Return an instance of
	type_or_decl_base_sptr rather than a decl_base_sptr.
	(class_diff::report): Adjust.
	(diff_comp::operator()(const diff&, diff&) const): Adjust.
	(enum function_decl_diff::priv::Flags): Remove.
	(function_decl_diff::priv::{first_fn_flags_, second_fn_flags_,
	fn_flags_changes_}): Remove.
	(function_decl_diff::priv::{fn_is_declared_inline_to_flag,
	fn_binding_to_flag}): Remove.
	(function_decl_diff::{deleted_parameter_at,
	inserted_parameter_at}): Remove.
	(function_decl_diff::ensure_lookup_tables_populated): Empty this.
	(function_decl_diff::chain_into_hierarchy): Adjust.
	(function_decl_diff::function_decl_diff): This now only takes the
	subjects.  It's body is now empty.
	(function_decl_diff::{return_type_diff, subtype_changed_parms,
	removed_parms, added_parms, type_diff}): Remove these member
	functions.
	(function_decl_diff::type_diff): Define new member function.
	(function_decl_diff::report): Simplify logic by using the
	reporting of the child type diff node.
	(compute_diff): Likewise, in the overload for function_decl_sptr
	simplify logic by using the child type diff object.
	(function_type_diff::priv): Define new type.
	(function_type_diff::{function_type_diff,
	ensure_lookup_tables_populated, deleted_parameter_at,
	inserted_parameter_at, finish_diff_type, first_function_type,
	second_function_type, return_type_diff, subtype_changed_parms,
	removed_parms, added_parms, get_pretty_representation,
	has_changes, has_local_changes, report, chain_into_hierarchy}):
	Define new functions.
	(compute_diff): Define new overload for function_type_sptr.
	* tools/abicompat.cc (options::weak_mode): New data member.
	(options::options): Initialize it.
	(enum abicompat_status): New enum
	(abicompat_status operator|(abicompat_status, abicompat_status))
	(abicompat_status& operator|=(abicompat_status &, abicompat_status))
	(abicompat_status operator&(abicompat_status, abicompat_status)):
	New operators to manipulate the abicompat_status enum.
	(display_usage): Add help string for the new --weak-mode option.
	(parse_command_line): Add the new --weak-mode command line
	argument.  If the tool is called with just the application and one
	library then assume that we are in the weak mode.
	(perform_compat_check_in_normal_mode): Define new function, factorized
	from what was in the main function.
	(perform_compat_check_in_weak_mode): Define new function.
	(struct {fn,var}_change): Define new types.
	(main): Use perform_compat_check_in_weak_mode() and
	perform_compat_check_in_normal_mode().
	* tools/abidiff.cc (main): Adjust.
	* tools/abidw.cc: (options::load_all_types): Add new data member.
	(options::options): Initialize it.
	(display_usage): New help string for --load-all-types.
	(parse_command_line): Support the new --load-all-types option.
	(main): Adjust and honour the --load-all-types option.
	* tools/abilint.cc (main): Adjust.
	* doc/manuals/abicompat.rst: Update documentation for the new weak
	mode.  Also provide stuff that was missing from the examples
	provided.
	* doc/manuals/abidw.rst: Update documentation for the new
	--load-all-types option.
	* tests/print-diff-tree.cc (main): Adjust.
	* tests/test-diff-dwarf.cc (main): Likewise.
	* tests/test-read-dwarf.cc (main): Likewise.
	* tests/data/test-abicompat/test0-fn-changed-app: Recompile this.
	* tests/data/test-abicompat/libtest5-fn-changed-libapp-v{0,1}.so:
	New new test input binaries
	* tests/data/test-abicompat/test5-fn-changed-app: Likewise.
	* tests/data/test-abicompat/test6-var-changed-app: Likewise.
	* tests/data/test-abicompat/libtest6-var-changed-libapp-v{0,1}.so:
	Likewise.
	* tests/data/test-abicompat/test5-fn-changed-report-0.txt:
	Reference output for one test above.
	* tests/data/test-abicompat/test6-var-changed-report-0.txt:
	Likewise.
	* tests/data/test-abicompat/test5-fn-changed-app.cc: Source file
	for a binary above.
	* tests/data/test-abicompat/test5-fn-changed-libapp-v{0,1}.{h,cc}:
	Likewise.
	* tests/data/test-abicompat/test6-var-changed-libapp-v{0,1}.{cc,h}:
	Likewise.
	* tests/data/test-abicompat/test6-var-changed-app.cc: Likewise.
	* tests/data/Makefile.am: Add the test related files above to the
	source distribution.
	* tests/test-abicompat.cc (in_out_spec): Add the new test input
	above to the list of inputs to feed to this test harness.
	(main): Support taking just the app and one library.
	* tests/data/test-read-dwarf/test{0, 1, 2.so, 3.so, 5.o,
	8-qualified-this-pointer.so,}.abi: Adjust for void type being
	really emitted now, as opposed to just being an empty type.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-04-03 22:45:41 +02:00
Dodji Seketeli
aa84bad114 18179 - abidiff crashes on libcangjie
At non-complete class resolution time, it appears that some type
lookup can return non-class type (for instance typedef types, when we
are expecting class types.

This patch implements class type lookup specifically (rather than
broad types lookup) and uses that during the non-complete class
resolution process.

	* include/abg-fwd.h (lookup_class_type_in_corpus)
	(lookup_class_type_in_translation_unit): Declare new functions.
	* src/abg-ir.cc (lookup_class_type_in_translation_unit): Define
	new function.
	(get_node, convert_node_to_decl): Define new specializations for
	the class_decl type.
	* src/abg-corpus.cc (lookup_class_type_in_corpus): Define new
	function.
	* src/abg-dwarf-reader.cc
	(read_context::resolve_declaration_only_classes): Lookup class
	types specifically.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-03-30 12:17:52 +02:00
Dodji Seketeli
b041bc9cf0 Fix redundancy propagation on node with filtered local changes
Until now, if a diff node N has a local change, even if all of its
children nodes are redundant, N is not considered as being redundant.
This is an issue if the local changes of N are filtered out; in that
case, N should be considered redundant.

This patch fixes that.  It introduces a second category bitmap on the
diff node that stores the categorization of the diff node that does
*NOT* take in account the categories inherited from its children
nodes.  That way, it's possible to know if the *local changes* of a
given node have been filtered out.

	* include/abg-comparison.h (diff::{get_local_category,
	add_to_local_category, add_to_local_and_inherited_categories,
	remove_from_local_category, set_local_category,
	is_filtered_out_wrt_non_inherited_categories,
	has_local_changes_to_be_reported}): Declare new member functions.
	* src/abg-comp-filter.cc ({harmless, harmful}_filter::{visit,
	visit_end}): Update local category too.
	* src/abg-comparison.cc (diff::priv::local_category_): Add new
	data member.
	(diff::priv::priv): Initialize it.
	(diff::priv::is_filtered_out): Add new member function.  This is
	factorized out of diff::is_filtered_out().
	(diff::is_filtered_out): Re-write in terms of
	diff::priv::is_filtered_out().
	(diff::{get_local_category, add_to_local_category,
	add_to_local_and_inherited_categories, remove_from_local_category,
	set_local_category, is_filtered_out_wrt_non_inherited_categories,
	has_local_changes_to_be_reported}): Define new member functions.
	(suppression_categorization_visitor::visit_begin): Update local
	categories too.
	(redundancy_marking_visitor::visit_end): If all of the children
	nodes of the a diff node N are redundant and if N has filtered-out
	local changes, then N is redundant too.
	* tests/data/test-diff-filter/libtest28-redundant-and-filtered-children-nodes-v{1,2}.so:
	New binary test inputs.
	* tests/data/test-diff-filter/test28-redundant-and-filtered-children-nodes-v{0,1}.cc:
	Source code for the binary test inputs above.
	* tests/data/test-diff-filter/test28-redundant-and-filtered-children-nodes-report-{0,1}.txt:
	New test output references.
	* tests/test-diff-filter.cc (in_out_specs): Add the test inputs
	above to the set of inputs this test harness has to run over.
	* tests/data/Makefile.am: Add the test materials above to the
	source distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-03-18 18:41:52 +01:00
Dodji Seketeli
f9ec2f1555 Make is_global_scope() return a pointer to the global scope
This helps while debugging from GDB.

	* include/abg-fwd.h (is_global_scope): Return a global_scope*.
	* src/abg-ir.cc (is_global_scope): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-03-17 12:00:52 +01:00
Dodji Seketeli
635e5fa6b2 Delay non-complete class type resolution up to end of corpus reading
From the DWARF emitted by GCC 4.4.7 for libstdc++ we encountered an
interesting construct.

A non-complete version of std::runtime_error is declared in
libstdc++-v3/src/functexcept.cc and is represented in DWARF as:

     [ 37344]      class_type
		    name                 (strp) "runtime_error"
		    declaration          (flag)

Then a bit later, that *non-complete* class is used as a base class
for a class, *without* being fully defined!  This shouldn't happen
but, well, it does:

     [ 3b3a1]    class_type
		  specification        (ref4) [ 3733e]
		  byte_size            (data1) 16
		  decl_file            (data1) 5
		  decl_line (data1) 141
		  containing_type      (ref4) [ 3734a]
		  sibling              (ref4) [3b405]
     [ 3b3b1]      inheritance
		   type                 (ref4) [ 37344] <---- here.

The thing is that, later, in another translation unit
(libstdc++-v3/src/stdexcept.cc), that same class is defined fully:

     [ 7e9f9]      class_type
		   name                 (strp) "runtime_error"
		   declaration          (flag)
[...]

     [ 80c95]    class_type
		 specification        (ref4) [ 7e9f9]
		 byte_size            (data1) 16
		 decl_file            (data1) 4
		 decl_line            (data1) 108
		 containing_type      (ref4) [ 7e9ff]
		 sibling              (ref4) [ 80d2b]
		 [...] <---------- and the definition goes here.

But then you see that the DIE offset of the "version" of the
runtime_error class that is "defined" libstdc++-v3/src/stdexcept.cc in
is different from the version that is only declared in
libstdc++-v3/src/functexcept.cc.  But virtue of the "One Definition
Rule", we can assume that they designate the same type.  But still,
runtime_error should have been defined in
libstdc++-v3/src/stdexcept.cc.  Anyhow, libabigail needs to be able to
handle this.  That is, it needs to wait until the entire ABI corpus is
loaded from DWARF, then lookup the definition of all the non-complete
types we have encountered.

And then only after that non-complete type resolution has taken place,
we can proceed with type canonicalizing, rather than doing it after
the loading of each translation unit like what we were doing
previously.

This is what this patch does.

	* include/abg-fwd.h (lookup_type_in_corpus): Declare new function.
	* src/abg-corpus.cc (lookup_type_in_corpus): Define new function
	here.
	* include/abg-ir.h (function_types_type): Declare new typedef.
	(translation_unit::get_canonical_function_type): Remove member function.
	(translation_unit::bind_function_type_life_time): Declare new
	member function.
	(classes_type): New typedef.
	* src/abg-ir.cc
	(translation_unit::priv::canonical_function_types_): Remove data
	member.
	(translation_unit::priv::function_types): New data member.
	(translation_unit::get_canonical_function_type): Remove this
	function definition.
	(translation_unit::bind_function_type_life_time): New function
	definition.
	(lookup_node_in_scope): Ensure that the type returned is
	complete.
	* src/abg-dwarf-reader.cc (string_classes_map): New typedef.
	(read_context::decl_only_classes_map_): New data member.
	(read_context::declaration_only_classes): New accessor.
	(read_context::{maybe_schedule_declaration_only_class_for_resolution,
	is_decl_only_class_scheduled_for_resolution,
	resolve_declaration_only_classes, current_elf_file_is_executable,
	current_elf_file_is_dso}): Define new member functions.
	(read_context::clear_per_translation_unit_data): Do not clear the
	data structures that associate DIEs to decls/types or that contain
	the types to canonicalize here.  Rather, clear them ...
	(read_context::clear_per_corpus_data): ... here instead.
	(read_context::build_translation_unit_and_add_to_ir): Do not
	perform late type canonicalizing here.  Rather, do it ...
	(read_debug_info_into_corpus): ... here instead.  And before that,
	call read_context::clear_per_corpus_data() and the new
	read_context::resolve_declaration_only_classes() here.
	(build_class_type_and_add_to_ir): Schedule the non-complete types
	for resolution to complete types.  Assert that base classes that
	are non-complete are scheduled to be completed.
	(build_function_decl): Do not try to canonicalize function types
	this early, systematically.  Now, all the non-complete types needs
	to be completed before starting canonicalizing.  So let function
	types go through the normal processes of deciding when to
	canonicalize them.  But then, bind the life time of the function
	type to the life time of the current translation unit.
	(maybe_canonicalize_type): If a class type is non-complete,
	schedule it for late canonicalizing.
	* src/abg-hash.cc (class_decl:#️⃣:operator()(const class_decl&)
	const): During hashing, a base class should be complete.
	* src/abg-reader.cc
	(read_context::clear_per_translation_unit_data): Do not clear
	id/xml node, and type maps here.  Rather, clear it ...
	(read_context::clear_per_corpus_data): ... here instead.
	(read_translation_unit_from_input): Do not perform late
	canonicalizing here.  Rather, do it ...
	(read_corpus_from_input): ... here.  Also, call the new
	read_context::clear_per_corpus_data() here.
	(build_function_decl): Do not canonicalize function types here so
	early.  Rather, bind the life time of the function type to the
	life time of the translation unit.
	* src/abg-writer.cc (write_translation_unit): Do not clear the
	type/ID map here.
	* tests/data/test-read-dwarf/test2.so.abi: Adjust test input.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-03-17 10:54:12 +01:00
Dodji Seketeli
03032ba544 Add an overload for is_type() that takes naked pointers
This is useful to call is_type() under GDB.

	* include/abg-fwd.h (is_type): Declare new overload that takes a
	naked pointer.
	* src/abg-ir.cc (is_type): Define new overload that takes a naked
	pointer.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-03-13 17:43:57 +01:00
Dodji Seketeli
7f1dd88907 Declaration-only classes shouldn't have canonical types
I am seeing issues related to the fact that a declaration-only class A
would compare different to the full version of class A.  This is due
to the fact that that the declaration-only A and the full A have
different hashes, even though they structurally compare equal.  So
they have different canonical types, with the current code.  This
patch arranges for declaration-only classes to have no canonical type,
forcing it to compare structurally to other types.  Then the patch
adjusts strip_typedef() that used to expect that all types it sees
have canonical types.  Then the patch changes the type hashing code to
avoid making it cache their hash, because otherwise, in some cases
when we hash a type (too) early, a temporary hash of it gets stored ad
infinitum, even after the type has been later updated.  Last but not
least, the patch returns a zero hash for declaration-only classes.

	* include/abg-fwd.h (keep_type_alive): Declare new function.
	* src/abg-ir.cc (strip_typedef): Simplify logic.  Support types
	that are not canonicalized.
	(type_base::get_canonical_type_for): For declaration-only classes,
	return an empty canonical class, forcing the class to be compared
	structurally.
	(keep_type_alive): Define new function.
	* src/abg-hash.cc ({decl_base, type_decl, scope_type_decl,
	qualified_type_def, pointer_type_def, reference_type_def,
	array_type_def, enum_type_decl, typedef_decl,
	class_decl::member_class_template, class_decl, type_tparameter,
	template_tparameter, }:#️⃣:operator()): Do not cache the
	computed hash.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-03-13 17:43:08 +01:00
Dodji Seketeli
de8dec2016 From inside the comparison engine re-use IR's equality operators
From inside the comparison engine, I noticed that there were some
discrepancies between some comparison performed there and the
comparison performed from inside the internal representation of
abigail::ir.  This can lead to some change reports in which the
reporter thinks there are changes in the IR where there actually are
not.  This patch re-uses comparison operators from the generic IR, rather
than re-implementing them in the comparison engine.

	* include/abg-ir.h (operator==(scope_decl_sptr, scope_decl_sptr)):
	Declare.
	(operator==(type_decl_sptr, type_decl_sptr)): Likewise.
	(operator==(enum_type_decl_sptr, enum_type_decl_sptr)): Likewise.
	* src/abg-comparison.cc (diff_length_of_decl_bases)
	(diff_length_of_type_bases): Remove these static functions.
	(class_diff::has_changes): Re-use the comparison operator for
	class_decl_sptr.
	(type_decl_diff::has_changes): Re-use the comparison operator for
	type_decl_sptr.
	* src/abg-ir.cc (operator==(scope_decl_sptr, scope_decl_sptr)):
	Define.
	(operator==(type_decl_sptr, type_decl_sptr)): Likewise.
	(operator==(enum_type_decl_sptr, enum_type_decl_sptr)): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-03-13 12:54:25 +01:00
Dodji Seketeli
915042e207 Pass a bunch of smart pointers by reference
Some smart pointers handling got high on performance profiles.  I am
passing those by reference here.

	* include/abg-fwd.h (get_member_is_static, is_member_function)
	(get_member_function_is_ctor, set_member_function_is_ctor)
	(get_member_function_is_dtor, set_member_function_is_dtor)
	(get_member_function_is_const, set_member_function_is_const)
	(get_member_function_vtable_offset)
	(set_member_function_vtable_offset)
	(get_member_function_is_virtual): Declare the smart pointer
	parameter of these as being passed by reference.
	* include/abg-ir.h (get_member_access_specifier)
	(get_member_is_static, get_member_access_specifier)
	(set_member_function_is_ctor, set_member_function_is_const)
	(set_member_function_vtable_offset): Likewise, for these friend
	declarations to the decl_base type.
	* src/abg-ir.cc (get_member_access_specifier)
	(get_member_is_static, is_member_function)
	(get_member_function_is_ctor, set_member_function_is_ctor)
	(get_member_function_is_dtor, set_member_function_is_dtor)
	(get_member_function_is_const, set_member_function_is_const)
	(get_member_function_vtable_offset)
	(set_member_function_vtable_offset)
	(get_member_function_is_virtual): In these definitions, the smart
	pointer parameter is passed by reference.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-03-10 18:41:44 +01:00
Dodji Seketeli
ffeb36eeda Make decl_base::get_context_rel() return a naked pointer
Accessing the context relationship of declarations and setting some
member properties appear to be high in performance profiles due to
shared pointer handling.  This patch makes the context relationship
accessors return a naked pointer and also passes a bunch of shared
pointer as references around.

	* include/abg-fwd.h (set_member_is_static): Add an overload that
	takes the member as a reference to a smart pointer.
	(set_member_function_{is_dtor, is_ctor, is_const, vtable_offset,
	is_virtual}): Pass the member function as a reference.
	(set_member_function_is_const, set_member_function_is_virtual):
	Pass the member function as a non-const reference.
	* include/abg-ir.h (decl_base::get_context_rel): Return a naked
	pointer.
	(set_member_is_static, set_member_function_is_virtual): Adjust
	this friend declaration.
	(set_member_access_specifier): Add an overload that takes a
	reference to the member.  Pass a reference to smart pointer to the
	other overload.
	(set_member_function_is_{is_ctor,is_dtor,is_const,is_virtual,vtable_offset}):
	Take a non-const reference to function_decl.
	* src/abg-ir.cc (decl_base::get_context_rel): Likewise.
	(equals(const decl_base&, const decl_base&, change_kind*)):
	Adjust.
	(equals(const var_decl&, const var_decl&, change_kind*)):
	Likewise.
	(get_member_access_specifier, get_member_is_static)
	(set_data_member_offset, get_data_member_offset)
	(set_data_member_is_laid_out, get_data_member_is_laid_out)
	(get_member_function_is_ctor, set_member_function_is_ctor)
	(get_member_function_is_dtor, set_member_function_is_dtor)
	(get_member_function_is_const, set_member_function_is_const)
	(get_member_function_vtable_offset)
	(set_member_function_vtable_offset)
	(get_member_function_is_virtual, set_member_function_is_virtual):
	Likewise.
	(set_member_access_specifier): Add an overload that takes a
	reference to decl_base.
	(set_member_is_static, set_member_function_{is_dtor, is_ctor,
	is_const, vtable_offset, is_virtual}): Pass the member function as
	a reference.): Add an overload that takes the member as a
	reference, and write the older overload in terms of the new one.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-03-10 16:02:37 +01:00
Dodji Seketeli
d79e9803f4 Make overloads of decl_base::get_qualified_name() return a reference
* incude/abg-ir.h (decl::get_{qualified_name,
	qualified_parent_name}): Return a reference to a string rather
	than a copy of a string.
	(qualified_type_def::get_qualified_name): Likewise.
	(reference_type_def::get_qualified_name): Likewise.
	(array_type_def::get_qualified_name): Likewise.
	(class enum_type_decl::enumerator): Make this is an out-of-line
	pimpled class implementation.
	(enum_type_decl::enumerator::{get, set}_enum_type): Declare new
	method.
	(enum_type_decl::enumerator::get_qualified_name): Change this so
	that it doesn't take the name of the enum type anymore.
	* src/abg-comparison.cc (enum_diff::report): Adjust for
	enum_type_decl::enumerator::get_qualified_name() not taking the
	name of the enum type anymore.
	* src/abg-ir.cc (decl_base::get_qualified_parent_name): Return a
	reference to string.
	(decl_base::get_qualified_name): Likewise.
	(decl_base::get_qualified_name(string&)): Use the new verson of
	decl_base::get_qualified_name() that returns a reference.
	({qualified_type_def, pointer_type_def, reference_type_def,
	array_type_def}::get_qualified_name()): Return a string reference.
	({qualified_type_def, pointer_type_def, reference_type_def,
	array_type_def}::get_qualified_name(string& qualified_name)
	const): Use the new qualified_type_def::get_qualified_name() that
	returns a string reference.
	(class enum_type_decl::priv): New type.
	(enum_type_decl::{get_underlying_type, get_enumerators}): Adjust.
	(enum_type_decl::{enumerator::enumerator, enumerator::operator==,
	enumerator::get_name, enumerator::get_qualified_name,
	enumerator::set_name, enumerator::get_value,
	enumerator::set_value, enumerator::get_enum_type,
	enumerator::set_enum_type}): Define methodes out-of-line here.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-03-09 15:15:36 +01:00
Dodji Seketeli
876dab386e When reading DWARF set member type access where the type is built
The DWARF reader assumes that the DIEs for all member types are seen
by build_class_type_and_add_to_ir(), as member type DIEs of the DIE of
the class.  Well that assumption is not correct because there can be
errors in the DWARF we are looking at.  One of these errors I stumbled
accross is that a DIE for a typedef that should be a member typedef is
actually a child of a *function* DIE.  And that function DIE is a
child of the class.  Go figure.  In any case, get_scope_for_die()
already fixes that up and behaves as if the DIE of the typedef is a
child of the DIE of the class.  A side effect of this is that when
build_class_type_and_add_to_ir() reads the DIE of the class, it never
sees the DIE for that typedef.

The takeaway of this state of affairs is that we cannot rely on
build_class_type_and_add_to_ir() to update the member access specifier
for member types because it does not see all member types.  Rather
build_ir_node_from_die() detects (reliably) that the type is a member
type and updates the access specifier there.

I also realize that the "is_member_type" flag of
build_ir_node_from_die() and friends is useless now because inside
build_ir_node_from_die() to know that that the type we are building is
a member type, we just need to look at the scope and see if it's a
class type.

So by doing all this, this patch fixes the fact that some types were
not being canonicalized because build_class_type_and_add_to_ir() was
not seeing them.  Ahhhh, DWARF.

	* include/abg-fwd.h (is_class(decl_base*)): Return a class_decl*
	rather than just a bool.
	* abg-ir.cc (is_class(decl_base*)): Return a class_decl* rather
	than just a bool.  Simplify the implementation.
	* src/abg-dwarf-reader.cc
	(maybe_set_member_type_access_specifier): Define new static
	function.
	(build_ir_node_from_die): Remove the is_member_type flag.  When
	building member types set their access specifier.  Simplify the
	logic of detecting that a type is a member type; basically
	delegate taht to the new maybe_set_member_type_access_specifier().
	(build_class_type_and_add_to_ir): Do not try to set the member
	type access specifiers anymore.
	(build_qualified_type, build_pointer_type, build_reference_type)
	(build_typedef_type, build_var_decl, build_function_decl): Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-02-24 13:15:10 +01:00
Dodji Seketeli
dc2f054d03 Build the set of exported decls directly during DWARF loading
Until now, after the ABI corpus was built from DWARF, the translation
units of the corpus were walked and each function was considered for
addition into the set of exported decls.  During that walking, a first
version of the set was put into a std::list and then, a set of filters
(user-provided tunables like a list of regular expressions to keep or
remove some functions from the exported decls) is applied to that list
and the final set of exported decls is put in a std::vector.

Profiling has shown that this process of building the set of exported
decls is a hot spot and also that the current use of std::list was a
big memory consumer especially on binaries with large exported symbol
tables.

So this patch builds the set of exported decls "on the fly", during
DWARF reading, as opposed to waiting after the DWARF is read and
having to walk the corpus again.  The corpus defines a policy object
that encapsulates the methods for determining if a function or
variable ought to be part of the set of exported decls.  The DWARF
reader uses that policy object to determine which functions and
variables among those built during the reading ought be part of the
exported decls; the policy object also has a reference to the final
vector (managed by the corpus) that must hold the exported decls, so
the decls are put in that vector directly without unnecessary copying.

Profiling also showed that the string copying done by
{var_decl,function_decl}::get_id() was a hot spot.  So the patch
returns a reference there.

With this patch applied, the peak memory consumption of abidiff on
libabigail.so itself (abidiff libabigail.so libabigail.so) is 54MB of
resident and takes 2 minutes and 16s (on my slow system).  Without the
patch the peak consumption was more than 300MB and it was taking
slightly longer.

For the test of bug
https://sourceware.org/bugzilla/show_bug.cgi?id=17948, memory
consumtion and wall clock time spent is down from 3.4GB and 1m59s to
760MB and 0m43s.

	* include/abg-ir.h ({var,function}_decl::get_id): Return a
	reference.
	* src/abg-ir.cc ({var,function}_decl::get_id): Return a reference
	to the string rather than copying it over.
	* include/abg-corpus.h (class corpus::exported_decls_builder):
	Declare new type.
	(corpus::{sort_functions, sort_variables,
	maybe_drop_some_exported_decls, get_exported_decls_builder}):
	Declare new methods.
	* src/abg-corpus.h (corpus::exported_decls_builder::priv): Define
	new type.
	(class symtab_build_visitor_type): Remove this type that is
	useless now.
	(corpus::exported_decls_builder::{exported_decls_builder,
	exported_functions, exported_variables,
	maybe_add_fn_to_exported_fns, maybe_add_var_to_exported_vars}):
	Define new functions.
	(corpus::priv::is_public_decl_table_built): Remove this data
	member.  It's now useless.
	(corpus::priv::priv): Adjust.
	(corpus::priv::build_public_decl_table): Remove this member
	function.  It's now useless.
	(corpus::{priv::build_unreferenced_symbols_tables, get_functions,
	get_variables}): No need to build the public decls table here.
	It's already built by the time the corpus is read from DWARF now.
	(corpus::{sort_functions, sort_variables,
	maybe_drop_some_exported_decls, get_exported_decls_builder}):
	Define new member functions.
	* src/abg-dwarf-reader.cc (read_context::exported_decls_builder):
	New data member.
	(read_context::read_context): Initialize it.
	(read_context::{exported_decls_builder,
	maybe_add_fn_to_exported_fns, maybe_add_var_to_exported_vars}):
	Define new member functions.
	(read_debug_info_into_corpus): Get the the new
	'exported_decls_builder' object from the corpus and stick it into
	the read context so the DWARF reading code can use it to build the
	exported decls set.  When the DWARF reading is done, sort the set
	of exported functions and variables that was built.
	(build_ir_node_from_die): When a function or variable is built,
	consider putting it into the set of exported decls.
	* tools/abicompat.cc (main): Now that the exported decls is built
	*before* we had a chance to stick the list of symbol IDs to keep,
	call corpus::maybe_drop_some_exported_decls() to update the set of
	exported decls we should consider for the corpus.

was applied to that list and the final

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-02-24 13:15:10 +01:00
Dodji Seketeli
56d958641c Bug 17649 Avoid endless looping on diff graph with cycles
Bug URL: https://sourceware.org/bugzilla/show_bug.cgi?id=17649.

abidiff stumbled accross a diff graph with cycles.  And it kept
walking that graph endlessly.  Of course.

It turned out on such graphs with cycles, the categorizing code that
uses abigail::comparison::diff::traverse() to walk the graph and
categorize the diff nodes was traversing the same class of equivalence
of certain diff nodes more than once without even noticing.

This patch changes the logic of the diff graph traversing code to make
it always call diff_node_visitor::visit_begin() on the visitor for a
diff node prior to visiting it (visiting means calling
diff_node_visitor::visit()) and diff_node_visitor::visit_end() after
visiting it.

But when the diff node has already been visited and it's reached again
by the traversing code (in case of a cycle) then the
diff_node_visitor::visit_begin() is called, but
diff_node_visitor::visit() is *NOT*.  Then
diff_node_visitor::visit_end() is called.  In other words, even when
the diff node is not visited (because it's already been visited) the
pair diff_node_visitor::{visit_begin,visit_end}() is called.

This avoids traversing the diff node (or rather the equivalence class
of the diff node) more than once even in presence of cycles, but still
gives a chance to custom visitors to detect that they are seeing a
cycle and act accordingly if need be.  This is a kind of cycle
detection feature.

Then the code of the (harmless and harmful categorization) filters has
been adapted to always rely on the cycle detection feature.  The code
of the category propagation visitor has also been adapted to propagate
the category of a given diff node to and from its canonical diff node.

	* include/abg-comp-filter.h (harm{less,ful}_filter::visit_end):
	Declare new methods.
	* include/abg-comparison.h (diff_context::maybe_apply_filters):
	Remove the traverse_nodes_once flag.
	* src/abg-comp-filter.cc (apply_filter): Force the traversing to
	operate in cycle avoidance mode.
	(harm{less,ful}_filter::visit): Update the category of the
	canonical node too.
	(harm{less,ful}_filter::visit_end): Define new method.
	* src/abg-comparison.cc (diff_context::maybe_apply_filters):
	Remove the traverse_nodes_once flag.  Adjust.  Simplify logic.
	(diff::traverse): Always call diff_node_visitor::{begin,end}.  If
	the node has already been visited previously then do not call
	diff_node_visitor::visit() and do not visit the children nodes.
	(category_propagation_visitor::visit_end):  If the node has
	already been visited, then propagate the category from the
	canonical nodes of the children nodes.
	(propagate_categories):  Force the traversing to operate in cycle
	avoidance mode.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-02-21 15:16:48 +01:00
Dodji Seketeli
bbf550f493 Add type checking overloads that ease their calling from GDB
* include/abg-fwd.h (is_class_type, is_pointer, is_reference_type)
	(is_qualified_type): Declare overloads that take naked (non-smart)
	pointers.
	* src/abg-ir.cc (is_class_type, is_pointer, is_reference_type)
	(is_qualified_type): Define overloads that take naked (non-smart)
	pointers.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-02-20 14:23:15 +01:00
Dodji Seketeli
cc3f6a86a7 Make strip_typedef() act on canonical types only
strip_typedef(), when constructing new pointers,
references and other composite types was building new types that
weakly referred to their sub-types; for instance, a pointer type
has a weak reference on its pointed-type.  That means the referred-to
type must be 'own' by something else.  That means that strip_typedef()
needs to create types which lifetime is "long enough".  This patch
ensures that strip_typedef() returns a canonical type; and we are sure
that a canonical type is live during the entire life time of the
libabigail library itself.

So that means strip_typedef can only be used after types have been
canonicalized.  To that end, this patch changes is_class_type() to
make it not strip typedefs.  That way, is_class_type() can be used
even when canonicalized types are not yet available.  The patch then
introduces a new is_compatible_with_class_type() function that strips
typedef.  The code of type_size_changed() that wanted to strip
typedefs is then adjusted to use this new
is_compatible_with_class_type() instead.

	* include/abg-fwd.h (is_compatible_with_class_type): Declare new
	function.
	(canonicalize): Move the declaration here, from ...
	* include/abg-ir.h (canonicalize): ... here.
	* src/abg-ir.cc (strip_typedef): Assert that the input type is
	canonicalized.  Make sure that weak references are on
	canonicalized types.  Make sure that the returned type is a
	canonical one.
	(canonicalize): Make this return the canonical type that it has
	computed.
	* src/abg-comp-filter.cc (type_size_changed): Use the new
	is_compatible_with_class_type() function, instead of
	is_class_type().

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-02-19 11:44:11 +01:00
Dodji Seketeli
8b28d171c3 Canonicalize types either early or late after TU reading
While trying to diff two identical files (abidiff foo.so foo.so) it
appeared that canonicalizing types during e.g, the DWARF reading
process was leading to subtle errors because it's extremely hard to
know when a type is complete.  That is, during the building of a class
type C, a pointer to C can be built before C is complete.  Worse, even
after reading the DIE (from DWARF) of class C, there can be DIE seen
later in the translation unit that modifies type C.  In these late
cases, one needs to wait -- not only until C is fully built, but also
sometimes, after the translation unit is fully built -- to
canonicalize C and then the pointer to C.  This kind of things.

So now there are two possible points in time when canonicalization of
a type can happen.  It can happen early, when the type is built.  This
is the case for basic types and composite types for which all
sub-types are canonicalized already.  It can happen late, right after
we've finished reading the debug info for the current translation
unit.

So this patch fixes the IR traversal and uses that to walk the
translation unit (or even types) after it's built.  It does away with
the first attempt to perform early canonicalizing only.

The patch also handles type canonicalizing while reading xml-abi
format.

	* include/abg-fwd.h (is_class_type)
	(type_has_non_canonicalized_subtype): Declare new functions.
	(is_member_type): Remove the overload that takes a decl_base_sptr.
	It's superfluous.  We just need the one that takes a
	type_base_sptr.
	* include/abg-ir.h (translation_unit::{is_constructed,
	set_is_constructed}): Add new methods.
	(class_decl::has_virtual_member_functions): Likewise.
	(class decl_base): Makes it virtually inherit ir_traversable_base.
	(class type_base): Make this virtually inherit traversable_base
	too.
	(type_base::canonicalize): Renamed enable_canonical_equality
	into this.
	(type_base::traverse): Declare new virtual method.
	(canonicalize): Renamed enable_canonical_equality into this.
	(scope_type_decl::traverse): Declare new virtual method.
	(namespace_decl::get_pretty_representation): Declare new virtual
	method.
	(function_type::traverse): Likewise.
	(class_decl::base_spec::traverse): Likewise.
	(ir_node_visitor::visit): Remove the overloads and replace each of
	them with a pair of ...
	(ir_node_visitor::{visit_begin, visit_end}): ... of these.
	* include/abg-traverse.h (traversable_base::visiting): New
	method.
	(traversable_base::visiting_): New data member.
	(traversable_base::traversable_base): New constructor.
	* src/abg-ir.cc ({scope_decl, type_decl, namespace_decl,
	qualified_type_def, pointer_type_def, reference_type_def,
	array_type_def, enum_type_decl, typedef_decl, var_decl,
	function_decl, function_decl::parameter, class_decl,
	class_decl::member_function_template,
	class_decl::member_class_template, function_tdecl,
	class_tdecl}::traverse): Fix this to properly set the
	traversable_base::visiting_ flag and to reflect the new signatures
	of the ir_node_visitor methods.
	({type_base, scope_type_decl, function_type,
	class_decl::base_spec}::traverse): New method.
	(type_base::get_canonical_type_for): Handle the case of the type
	already having a canonical type.  Properly hash the type using the
	dynamic type hasher.  Look through declaration-only classes to
	consider the definition of the class instead.  Fix logic to have a
	single pointer of return, to ease debugging.
	(canonicalize): Renamed enable_canonical_equality into this.
	(namespace_decl::get_pretty_representation): Define new method.
	(ir_node_visitor::visit): Replace each of these overloads with a
	pair of visit_begin/visit_end ones.
	(translation_unit::priv::is_constructed_): New data member.
	(translation_unit::priv::priv): Initialize it.
	(translation_unit::{is_constructed, set_is_constructed}): Define
	new methods.
	(is_member_type(const decl_base_sptr)): Remove.
	(is_class_type(decl_base *d)): Define new function.
	(class_decl::has_virtual_member_functions): Define new method.
	(equals(const class_decl&, const class_decl&, change_kind*)): If
	the containing translation unit is not constructed yet, do not
	take virtual member functions in account when comparing the
	classes.  This is because when reading from DWARF, there can be
	DIEs that change the number of virtual member functions after the
	DIE of the class.  So one needs to start taking virtual members
	into account only after the translation unit has been constructed.
	(class non_canonicalized_subtype_detector): Define new type.
	(type_has_non_canonicalized_subtype): Define new function.
	* src/abg-corpus.cc (symtab_build_visitor_type::visit): Renamed
	this into symtab_build_visitor_type::visit_end.
	* src/abg-dwarf-reader.cc (die_type_map_type): New typedef.
	(die_class_map_type): This is now a typedef on a map of
	Dwarf_Off/class_decl_sptr.
	(read_context::{die_type_map_, alternate_die_type_map_,
	types_to_canonicalize_, alt_types_to_canonicalize_}): New data
	members.
	(read_context::{associate_die_to_decl,
	associate_die_to_decl_primary}): Make these methods public.
	(read_context::{associate_die_to_type,
	lookup_type_from_die_offset, is_wip_class_die_offset,
	types_to_canonicalize, schedule_type_for_canonicalization}):
	Define new methods.
	(build_type_decl, build_enum_type)
	(build_class_type_and_add_to_ir, build_qualified_type)
	(build_pointer_type_def, build_reference_type, build_array_type)
	(build_typedef_type, build_function_decl): Do not canonicalize
	types here.
	(maybe_canonicalize_type): Define new function.
	(build_ir_node_from_die): Take a new flag that says if the ir node
	is a member type/function or not. Early-canonicalize base types.
	Canonicalize composite types that have only canonicalized
	sub-types.  Schedule the other types for late canonicalizing.  For
	class types, early canonicalize those that are non-member types,
	that are fully constructed and that have only canonicalized
	sub-types.  Adjust to the new signature of build_ir_node_from_die.
	(get_scope_for_die, build_namespace_decl_and_add_to_ir)
	(build_qualified_type, build_pointer_type_def)
	(build_reference_type, build_array_type, build_typedef_type)
	(build_var_decl, build_function_decl): Adjust for the new
	signature of build_ir_node_from_die.
	(build_translation_unit_and_add_to_ir): Likewise.  Perform the
	late canonicalizing of the types that have been scheduled for
	that.
	(build_class_type_and_add_to_ir): Return a class_decl_sptr, not a
	decl_base_sptr.  Adjust for the new signature of
	build_ir_node_from_die.  Early canonicalize member types that are
	created and added to a given class, or schedule them for late
	canonicalizing.
	* src/abg-reader.cc (class read_context::{m_wip_classes_map,
	m_types_to_canonicalize}): New data members.
	(read_context::{clear_types_to_canonicalize,
	clear_wip_classes_map, mark_class_as_wip, unmark_class_as_wip,
	is_wip_class, maybe_canonicalize_type,
	schedule_type_for_late_canonicalizing,
	perform_late_type_canonicalizing}): Add new method definitions.
	(read_context::clear_per_translation_unit_data): Call
	read_context::clear_types_to_canonicalize().
	(read_translation_unit_from_input): Call
	read_context::perform_late_type_canonicalizing() at the end of the
	function.
	(build_function_decl): Fix the function type canonicalizing (per
	translation) that was already in place.  Do the canonicalizing of
	these only when the type is fully built.  Oops.  This was really
	brokend.  Also, when the function type is constructed, consider it
	for type canonicalizing.
	(build_type_decl): Early canonicalize basic types.
	(build_qualified_type_decl, build_pointer_type_def)
	(build_pointer_type_def, build_reference_type_def)
	(build_array_type_def, build_enum_type_decl, build_typedef_decl):
	Handle the canonicalizing for these composite types: either early
	or late.
	(build_class_decl): Likewise.  Also, mark this class a 'being
	built' until it's fully built.  This helps the canonicalizing code
	to know that it should leave a class alone until it's fully built.
	* tests/test-ir-walker.cc (struct name_printing_visitor): Adjust
	to the visitor methods naming change.
	* configure.ac: Generate the tests/runtestcanonicalizetypes.sh
	testing script from tests/runtestcanonicalizetypes.sh.in.
	* tests/runtestcanonicalizetypes.sh.in: Add the template for the
	new runtestcanonicalizetypes.sh script that test for type
	canonicalizing.
	* tests/Makefile.am: Add the new runtestcanonicalizetypes.sh
	regression testing script to the build system.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-02-18 21:32:37 +01:00
Dodji Seketeli
d1d4965ee1 Misc style fixes
* include/abg-ir.h (reference_type_def::get_pointed_to_type): use
	type_base_sptr, rather than shared_ptr<type_base>
	(typdef_decl::get_underlying_type): Likewise.
	(function_decl::get_return_type): Likewise.
	(function_decl::set_type): Likewise.
	(class_decl::member_class_template::as_class_tdecl): Likewise.
	* src/abg-comparison.cc (compute_diff): Remove useless vertical
	space.
	(corpus_diff::traverse): Add a vertical space after this.
	* src/abg-dwarf-reader.cc (type_ptr_map): Remove this unused
	typedef.
	(get_version_for_symbol)
	(finish_member_function_reading): Fix the comments of these
	functions.
	* src/abg-reader.cc (build_function_decl): Return a
	function_decl_sptr rather than a shared_ptr<function_decl>.
	(build_qualified_type_decl)
	(build_pointer_type_def, build_reference_type_def)
	(build_array_type_def, build_typedef_decl, build_class_decl): Use
	the is_<someking_of_type> functions here, rather than using the
	dynamic cast.  This increases maintainability.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-02-18 19:15:17 +01:00
Dodji Seketeli
8fbd4f93ba Initial implementation of canonical type comparison in the IR
Comparing types that are equal showed up high in profiles.  This patch
is an answer to that.  It implements the notion of canonical type for
types known to libabigail.  Then when comparing two types, if they
have a canonical types, just comparing the pointer value of their
canonical type is enough.  This speeds up type comparison somewhat;
comparing the Xorg binaries from rhel 6 and 7 goes from more than 20h
(I gave up after that) to under 15 minutes.

	* include/abg-ir.h (class type_base): Pimplify this class.
	(type_base::canonical_types_map_type): New typedef.
	(type_base::{get_canonical_types_map, get_canonical_type_for,
	get_canonical_type}): Declare new member functions.
	(enable_canonical_equality): Declare new function.
	(struct type_base::hash): Declare this functor here.
	* src/abg-ir.cc ():
	* src/abg-dwarf-reader.cc (build_type_decl, build_enum_type)
	(build_class_type_and_add_to_ir, build_qualified_type)
	(build_pointer_type_def, build_reference_type, build_array_type)
	(build_typedef_type, build_function_decl): Enable canonical
	equality for the resulting type returned by these functions.
	* src/abg-hash.cc (type_base:#️⃣:operator()(const type_base&)):
	Adjust as this is now out-of-line.  Also, add two overloads for
	type_base* and type_base_sptr.
	(struct type_base::priv): Define new type for private data of
	type_base.
	(type_base::{get_canonical_types_map, get_canonical_type_for,
	get_canonical_type}): Define new member functions.
	(enable_canonical_equality): Define new function
	(type_base::{type_base, set_size_in_bits, get_size_in_bits,
	set_alignment_in_bits, get_alignment_in_bits}): Adjust.
	({type_decl, scope_type_decl, qualified_type_def,
	pointer_type_def, reference_type_def, array_type_def,
	enum_type_decl, typedef_decl, function_type,
	class_decl}::operator==): If the types being compared have
	canonical type then use them for comparison.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-02-09 17:01:48 +01:00
Dodji Seketeli
34b94a06da Get out as early as possible when comparing different ABI artefacts
When the the of 'equals' overloaded functions was introduced, it was
to get the possibility to have a hint about the kind of difference
(local or sub-type difference) there was between two different ABI
artifacts.  To do that, it was quite common to keep on comparing the
two artifacts even when we knew there were different, because we need
to know all the kinds of the differences there are.

Now, profiling shows that doing this generally is too costly.  So,
this patch adds a way to doing it only when necessary.

	* include/abg-ir.h (equal): Turn the last parameter of type
	change_kind& into a change_kind*.  Do this on all the overloads'
	declarations.
	* src/abg-ir.cc (equal): Do the same for the definitions of the
	overloads and adapt them to report about the kind of changes makes
	the two ABI artifact different -- only if the change_kind pointer
	is non-null.  That way, callers have a way to choose if they want
	to go the expensive route of knowing what kind of changes there
	are.
	({decl_base, scope_decl, type_base, scope_type_decl,
	qualified_type_def, pointer_type_def, pointer_type_def,
	reference_type_def, array_type_def, enum_type_decl, typedef_decl,
	var_decl, function_type, function_decl, function_decl::parameter,
	class_decl::base_spec, class_decl}::operator==): Adjust to the new
	signature of equals; call it with the change_kind* parameter set
	to NULL.
	* src/abg-comparison.cc ({var_diff, pointer_diff, array_diff,
	reference_diff, qualified_type_diff, enum_diff, class_diff,
	base_diff, scope_diff, fn_parm_diff, function_decl_diff,
	type_decl_diff, typedef_diff}::has_local_changes): Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-02-07 11:00:05 +01:00
Dodji Seketeli
3b3dbf6643 Rename diff::length() into diff::has_changes()
Since it turned out that the length of the changes carried by a diff
node has never been used in the algorithms of the comparison engine,
the diff::length() feels wrong.  What we want is rather a name like
diff::has_changes() so this is what this patch does.

	* include/abg-comparison.h (*::has_changes): Rename the ::length()
	method of all the diff types that inherit the diff class into
	this, in the class declarations.
	* src/abg-comparison.cc (*::has_changes): Do the same as in the
	declarations, in the definitions.
	(diff::to_be_reported, distinct_diff::has_local_changes)
	(distinct_diff::report, distinct_diff::, array_diff::has_changes)
	(reference_diff::has_changes, qualified_type_diff::has_changes)
	(enum_diff::has_changes, translation_unit_diff::has_changes)
	(suppression_categorization_visitor::visit_end)
	(redundancy_marking_visitor::visit_begin): Adjust.
	* tests/test-diff-dwarf.cc (main): Adjust.
	* tools/abidiff.cc (main): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-02-05 12:44:59 +01:00
Dodji Seketeli
32352341c5 Add a method to diff_context to dump a diff tree to error output
For debugging purposes it's very convenient to able to dump a diff
tree to error output.  This patch just adds that possibility.

	* include/abg-comparison.h (diff_context::error_output_stream):
	Make this function const.
	(diff_context::{do_dump_diff_tree}): Declare new methods.
	* src/abg-comparison.cc (diff_context::error_output_stream): Make
	this function const.
	(diff_context::do_dump_diff_tree): Define new methods.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-01-27 12:49:40 +01:00
Dodji Seketeli
2173563f3c Keep children nodes of class_diff and scope_diff sorted
I realized that some children nodes of class_diff and scope_diff node
appear in the order laid out by the hash map that contains them.  This
can be quite random depending on various factors.  More over the
reporting code walks sorts the children nodes before walking them to
emit reports, so the walking order of the reporting code is (or can
be) different from the natural walking order used, for instance, by
the categorization or redundancy detection code.  This can have weird
side effects, especially for reporting about redundancy where the
walking other matters.

This patch thus sorts the children nodes of the class_diff and
scope_diff nodes and hopefully udpates all the code that needs
updating to take that in account.

	* include/abg-comparison.h (decl_diff_base, type_diff_base):
	Forward declare these types.
	(diff_sptrs_type, decl_diff_base_sptr, decl_diff_base_sptrs_type)
	(type_diff_base_sptr, type_diff_base_sptrs_type)
	(base_diff_sptrs_type, string_type_diff_base_sptr_map)
	(string_decl_diff_base_sptr_map, string_diff_sptr_map): New
	typedefs.
	(changed_type_or_decl, changed_parm, changed_parms_type)
	(string_changed_type_or_decl_map)
	(unsigned_changed_type_or_decl_map, changed_type_or_decl_vector):
	Remove typedefs.
	(class_diff::changed_base): Make this return a
	base_diff_sptrs_type now.  No more a string_base_diff_sptr_map.
	(class_diff::changed_member_fns): Make this return a
	function_decl_diff_sptrs_type, no more a
	string_changed_member_function_sptr_map.
	(class_diff::changed_types): Make this return a diff_sptrs_type,
	not a string_changed_type_or_decl_map anymore.
	(class_diff::changed_decls): Make this return a diff_sptrs_type,
	not a string_changed_type_or_decl_map anymore.
	* src/abg-comp-filter.cc (has_virtual_mem_fn_change)
	(has_non_virtual_mem_fn_change): Adjust.
	* src/abg-comparison.cc (compute_diff): For the decl_base_sptr and
	type_base_sptr overloads, assert that the resulting diff is
	non-null.
	(class_diff::priv::{sorted_changed_base_,
	sorted_changed_member_types_, sorted_subtype_changed_dm_,
	sorted_changed_dm_, sorted_changed_member_functions_,
	sorted_changed_member_class_tmpls_}): New data members.
	(class_diff::priv::changed_member_types_): Changed the type of
	this from string_changed_type_or_decl_map to string_diff_sptr_map.
	(class_diff::priv::changed_member_functions_): Changed the type of
	this from string_changed_member_function_sptr_map to
	string_function_decl_diff_sptr_map.
	(class_diff::priv::changed_member_class_tmpls_): Changed the type
	of this from string_changed_type_or_decl_map to
	string_diff_sptr_map.
	(class_diff::ensure_lookup_tables_populated): Adjust.  Initialize
	the new sorted members class_diff::priv::{sorted_changed_bases_,
	sorted_subtype_changed_dm_, sorted_changed_dm_,
	sorted_changed_member_functions_, sorted_changed_member_types_}.
	(class_diff::priv::{member_type_has_changed,
	member_class_tmpl_has_changed, count_filtered_bases,
	count_filtered_subtype_changed_dm, count_filtered_changed_mem_fns,
	}): Adjust.
	(class_diff::chain_into_hierarchy): Adjust:  The children nodes of
	class_diff are now laid out in a sorted way.
	(class_diff::{changed_bases, changed_member_fns}): Adjust.
	(base_diff_comp, virtual_member_function_diff_comp): New types.
	(sort_string_base_diff_sptr_map)
	(sort_string_virtual_member_function_diff_sptr_map): New static
	functions.
	(data_member_diff_comp): Renamed var_diff_comp into this.
	(sort_unsigned_data_member_diff_sptr_map): Renamed sort_var_diffs
	into this and adjust.
	(class_diff::report): Do not sort the nodes we are about to emit
	here.  Just use the natural order of the nodes in their parent
	tree as they should now be sorted.
	(scope_diff::priv::{changed_types_, changed_decls_}): Change the
	type of these from string_changed_type_or_decl_map to
	string_diff_sptr_map.
	(scope_diff::priv::{sorted_changed_types_,
	sorted_changed_decls_}): New data members.
	(scope_diff::ensure_lookup_tables_populated): Adjust.  Initialize
	the new scope_diff::priv::sorted_changed_{types_, decls_}.
	(scope_diff::chain_into_hierarchy): Adjust.  The children of
	scope_diff are now sorted.
	(scope_diff::changed_{types, decls}): Return the sorted vectors of
	children nodes.
	(struct changed_type_or_decl_comp): Remove.
	(struct diff_comp): New type.
	(sort_changed_type_or_decl): Remove.
	(sort_string_diff_sptr_map): New static function.
	(scope_diff::report): Adjust.  Do not sort children nodes here
	ourselves before reporting about them.  Rather, use the natural
	topological order of the children as they are now sorted.
	(corpus_diff::priv::sorted_changed_vars_): Renamed
	corpus_diff::priv::changed_vars_ into this to make it more
	explicit that the things it holds are sorted.
	(corpus_diff::changed_variables_sorted): Adjust.
	(corpus_diff::priv::ensure_lookup_tables_populated): Likewise.
	(corpus_diff::priv::apply_filters_and_compute_diff_stats):
	Likewise.
	(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
	Likewise.
	(corpus_diff::priv::clear_redundancy_categorization): Likewise.
	(corpus_diff::priv::maybe_dump_diff_tree): Likewise.
	(corpus_diff::report): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-01-27 12:49:40 +01:00
Dodji Seketeli
29bc673dc0 Fix chaining of descendant node of qualified type diff node
While looking at the abidiff report emitted for two versions of the
TBB library, I noticed that some diff nodes were not marked as
redundant as they should be.  As a result, they were being reported as
having "been reported earlier", which seems to be an acceptable cruft
to me especially now that the comparison IR can do proper redundancy
detection and marking.

I tracked that down and it's because the child node of a
qualified_type_diff is just the underlying type diff node, whereas
during reporting, we report about the leaf underlying type diff node,
which can be different from the just the underlying type diff node
because the later is always non-qualified.

The fix is to make the child node of qualified_type_diff be the leaf
underlying type diff node, so that diff tree walking (for the purpose
of redundancy detection) and reporting are all looking at the same
tree.

	* include/abg-comparison.h
	(qualified_type_diff::leaf_underlying_type_diff): Declare new
	accessor.
	* src/abg-comparison.cc (get_leaf_type): Forward declare this
	static function.
	(qualified_type_diff::priv::leaf_underlying_type_diff): Define new
	data member.
	(qualified_type_diff::leaf_underlying_type_diff): Define this new
	accessor.
	(qualified_type_diff::chain_into_hierarchy): Call
	leaf_underlying_type_diff() here rather than
	underlying_type_diff().
	(qualified_type_diff::report): Use leaf_underlying_type_diff()
	rather than re-computing the diff between the two leaf underlying
	type diff nodes.
	* libtest26-qualified-redundant-node-v{0,1}.so: New binary test
	input files.
	* tests/data/test-diff-filter/test26-qualified-redundant-node-v{0,1}.cc:
	Source code for the binary test inputs above.
	* tests/test-diff-filter.cc (int_out_spec): Add the new test input
	to the vector of test input data over which to run this test
	harness.
	* tests/data/test-diff-filter/test26-qualified-redundant-node-report-{0,1.txt:
	New test input file.
	* tests/data/Makefile.am: Add the new test input data to the
	source distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-01-26 12:12:57 +01:00
Dodji Seketeli
ddfb37ab17 Recognize cyclic diff tree nodes as being redundant
Okay I need to introduce some vocabulary here.  Suppose we have the
version 1 of a library named library-v1.so which source code is:

    struct S
    {
     int m0;
     struct S* m2;
    };

    int
    foo(struct S* ptr)
    {
      return ptr;
    }

And now suppose we have a version 2 of that library named
library-v2.so which source code is modified so that a new data member
is inserted into struct S:

    struct S
    {
     int m0;
     char m1; /* <--- a new data member is inserted here.  */
     struct S* m2;
    };

    int
    foo(struct S* ptr)
    {
      return ptr;
    }

struct S is said to be a cyclic type because it contains a (data)
member which type refers to struct S itself, namely, the type of the
data member S::m2 is struct S*, which refers to struct S.

So, by analogy, the diff node tree that represents the changes of
struct S is also said to be cyclic, for similar reasons: the diff
node of the change of S::m2 refers to the diff node of the change of
the type of S::m2, namely the diff node of struct S*, which refers to
the diff node for the change of struct S itself.

Now let's talk about redundancy.  When walking the diff node tree of
struct S in a depth-first manner, at some point, we look at the diff
node for the data member S::m2, and we end up looking at the diff node
of its type which is the diff node for struct S*; we keep walking and
eventually we look the diff node of the change of the underlying type
of struct S, which is the diff node of struct S, and hah! that is a
redundant node because it's the first node that we visited when
visiting the diff node of ...  struct S!  So the diff tree node for
the change of struct S is not only a cyclic node, it's a redundant
diff node as well, and its second occurrence is located at the point
of appearance of data member S::m2.  Hence the wording "cyclic
redundant diff tree node".  There! We have our vocabulary all set now.

This patch enhances the code of the comparison engine so that a cyclic
diff tree node is marked as redundant from the point of its second
occurrence, onward.

First the patch separates the notion of visiting a diff node from the
notion of traversing it.  Now traversing a diff node means visiting it
and visiting its children nodes.  So one can visit a node without
traversing it, but one can not traverse a node without visiting it.

So, when walking diff node trees, we need to avoid ending up in
infinite loop in presence of cyclic nodes.  This is why re-traversing
a node that is already being traversed is forbidden by this patch, but
visiting a node that is being visited is allowed.  Before this patch,
the notions of visiting and traversing were conflated in one and were
not very clear; and one couldn't visit a node that was currently being
visited.  As a result, in presence of a cyclic node, its redundant
nature wasn't being recognized, and so the diff tree node was not
being flagged as being redundant.  Diff reports were then cluttered by
redundant references to changes involving cyclic types.

	* include/abg-comparison.h (enum visiting_kind): Rename
	enumerator DO_NOT_MARK_VISITED_NODES_AS_TRAVERSED into
	DO_NOT_MARK_VISITED_NODES_AS_VISITED.
	(diff_context::diff_has_been_visited): Rename
	diff_context::diff_has_been_traversed into this.
	(diff_context::mark_diff_as_visited): Rename
	diff_context::mark_diff_as_traversed into this.
	(diff_context::forget_visited_diffs): Rename
	diff_context::forget_traversed_diffs into this.
	(diff_context::forbid_visiting_a_node_twice): Rename
	diff_context::forbid_traversing_a_node_twice into this.
	(diff_context::visiting_a_node_twice_is_forbidden): Rename
	diff_context::traversing_a_node_twice_is_forbidden into this.
	(diff::is_traversing): Move this from protected to public.
	* src/abg-comparison.cc (diff_context::priv::visited_diff_nodes_):
	Rename diff_context::priv::traversed_diff_nodes_ into this.
	(diff_context::priv::forbid_visiting_a_node_twice_): Rename
	diff_context::priv::forbid_traversing_a_node_twice_ into this.
	(diff_context::priv::priv): Adjust.
	(diff_context::diff_has_been_visited): Rename
	diff_context::diff_has_been_traversed into this.  Adjust.
	(diff_context::mark_diff_as_visited): Rename
	diff_context::mark_diff_as_traversed into this.  Adjust.
	(diff_context::forget_visited_diffs): Rename
	diff_context::forget_traversed_diffs into this.  Adjust.
	(diff_context::forbid_visiting_a_node_twice): Rename
	diff_context::forbid_traversing_a_node_twice into this.
	(diff_context::visiting_a_node_twice_is_forbidden): Rename
	diff_context::traversing_a_node_twice_is_forbidden into this.
	(diff_context::maybe_apply_filters): Adjust.
	(diff::end_traversing): Remove the 'mark_as_traversed' parameter
	of this.  Remove the visited-marking code.
	(diff::traverse): This is the crux of the changes of this patch.
	Avoid traversing a node that is being traversed, but one can visit
	a node being visited.  Also, traversing a node means visiting it
	and visiting its children nodes.
	(diff::is_filtered_out):  Simplify logic for filtering redundant
	code.  Basically all nodes that are redundant are filtered.  All
	the complicated logic that was due when diff nodes were shared is
	not relevant anymore.
	(corpus_diff::priv::categorize_redundant_changed_sub_nodes)
	(propagate_categories, apply_suppressions)
	(diff_node_printer::diff_node_printer, print_diff_tree)
	(categorize_redundant_changed_sub_nodes)
	(clear_redundancy_categorization)
	(clear_redundancy_categorization): Adjust.
	(redundancy_marking_visitor::visit_begin): Adjust.  Also, if the
	current diff node is already being traversed (that's a clyclic
	node) then mark it as redundant.
	* src/abg-comp-filter.cc (apply_filter): Adjust.
	* tests/data/test-diff-filter/test16-report-2.txt: New test input data.
	* tests/data/test-diff-filter/libtest25-cyclic-type-v{0,1}.so: New
	test input binaries.
	* tests/data/test-diff-filter/test25-cyclic-type-v{0,1}.cc: Source
	code for the test input binaries.
	* tests/data/test-diff-filter/test25-cyclic-type-report-0.txt: New
	test input data.
	* tests/data/test-diff-filter/test25-cyclic-type-report-1.txt:
	Likewise.
	* tests/test-diff-filter.cc (in_out_specs): Add the new test
	inputs above to the list of test input data over which to run this
	test harness.
	* tests/data/Makefile.am: Add the new test files above to source
	distribution.
	* tests/data/test-diff-filter/test16-report.txt: Adjust.
	* tests/data/test-diff-filter/test17-0-report.txt: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-01-24 22:48:40 +01:00
Dodji Seketeli
19013fd110 Sort functions & variables diff nodes in the diff tree
Since the work on un-sharing diff tree nodes, it looks like some
reports of regression tests on i686 order functions and variables in
different orders, leading to test failures on 32 bits platforms
because they are different fromthe 64 bits platforms that we use as a
reference.  This patch sorts (lexicographically) the children diff
nodes of a given diff node in general, and also sorts the set of diff
nodes for functions and variables that have sub-type changes, in a
given corpus_diff.  That way, the result of the diff report should be
sorted the same way, whatever the platform.

	* include/abg-comparison.h (function_decl_diff_sptrs_type)
	(var_diff_sptrs_type): New typedefs.
	(corpus_diff::{changed_functions, changed_variables}): Declare new
	methods.
	* src/abg-comparison.cc (sort_string_function_decl_diff_sptr_map)
	(sort_string_var_diff_sptr_map): Forward declare these static
	functions there were already defined later.
	(struct diff_less_than_functor): Define new comparison functor.
	(diff::append_child_node): Sort the children diff nodes of a given
	diff node.
	(corpus_diff::priv::changed_fns_map_): Renamed the data member
	corpus_diff::priv::changed_fns_ into this.
	(corpus_diff::priv::changed_fns_): New data member that is a
	sorted vector of changed functions.
	(corpus_diff::priv::{lookup_tables_empty, clear_lookup_tables}):
	Adjust changed_fns_ -> changed_fns_map_ and changed_vars_ ->
	changed_vars_map_.
	(corpus_diff::priv::ensure_lookup_tables_populated): Likewise.
	Sort the changed functions and changed variables.
	(corpus_diff::priv::apply_filters_and_compute_diff_stats): Adjust
	changed_fns_ -> changed_fns_map_ and changed_vars_ ->
	changed_vars_map_.  Also, walk the changed functions and variables
	diff nodes in their sorted order.
	(corpus_diff::priv::{categorize_redundant_changed_sub_nodes,
	clear_redundancy_categorization, maybe_dump_diff_tree}): Walk the
	changed functions and variables diff nodes in their sorted order.
	* include/abg-ir.h
	(function_decl::get_pretty_representation_of_declarator):
	Declarenew method.
	* src/abg-ir.cc
	(function_decl::get_pretty_representation_of_declarator): Define
	new function.  Its content got split out of ...
	(function_decl::get_pretty_representation): ... this one.
	* src/abg-comparison.cc (corpus_diff::chain_into_hierarchy):
	Consider the sorted the children nodes of a diff tree node.
	(corpus_diff::append_child_node): Keep the children nodes of a
	diff tree node sorted.
	(corpus_diff::{changed_functions, changed_variables, length,
	report}): Adjust.
	(corpus_diff::{changed_functions_sorted,
	changed_variables_sorted}): Define new functions.
	(function_comp::operator()): First compare the qualified function
	names along with the parameter declarations, then the rest.
	(sort_string_function_decl_diff_sptr_map)
	(sort_string_var_diff_sptr_map): Adjust.
	* tests/data/test-abicompat/test0-fn-changed-report-0.txt: Adjust.
	* tests/data/test-diff-suppr/test5-fn-suppr-report-0.txt: Adjust.
	* tests/data/test-diff-suppr/test8-redundant-fn-report-0.txt:
	Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-01-09 14:45:11 +01:00
Dodji Seketeli
322b0e7769 Expose a new libabigail::tools_utils namespace
The utilities present in this namespace were previously living in
tools/abg-tools-utils.h and tools/abg-tools-utils.cc.  They were not
exported and were meant to be useful to the tools writting in the
tools/ directory.  I realized that these utilities might be useful to
clients of the libabigail library in general so I am making them
available generally.  Note that the initial name of the namespace was
libabigail::tools; so renaming it to libabigail::tools_utils required
that I adjust some client code.  I have also cleaned up the code,
interfaces and their apidoc a little bit.

	* include/abg-tools-utils.h: Moved tools/abg-tools-utils.h in
	here.  Renamed the namespace tools into tools_utils.  Inject
	std::ostream, std::istream, std::ifstream, and std::string types
	into the tools_utils namespace.  Adjust the function declarations
	accordingly.  Remove the useless dirname() function declaration.
	* include/Makefile.am: Add abg-tools-utils.h to the list of
	exported headers.
	* src/abg-tools-utils.cc: Moved tools/abg-tools-utils.cc in here.
	Renamed the namespace tools into tools_utils.
	(get_stat): Add apidoc.
	(is_dir): Cleanup apidoc.
	(dir_name); Cleanup parameter name.
	(guess_file_type): Cleanup parameter type.
	* src/Makefile.am: Add abg-tools-utils.cc to the list of exported
	headers.
	* tools/Makefile.am: Do not build the temporary library
	libtoolsutils.la anymore as abg-tools-utils.{h,cc} have moved out
	of this directory.
	* tools/abicompat.cc (parse_command_line, main): Adjust for tools
	-> tools_utils namespace change.
	* tools/abidiff.cc (parse_command_line, main): Likewise.
	* tools/abidw.cc (parse_command_line, main): Likewise.
	* tools/abilint.cc (parse_command_line, main): Likewise.
	* tests/test-abicompat.cc (main): Adjust for tools -> tools_utils
	namespace change.
	* tests/test-abidiff.cc (main): Likewise.
	* tests/test-alt-dwarf-file.cc (main): Likewise.
	* tests/test-core-diff.cc (main): Likewise.
	* tests/test-diff-dwarf.cc (main): Likewise.
	* tests/test-diff-filter.cc (main): Likewise.
	* tests/test-diff-suppr.cc (main): Likewise.
	* tests/test-lookup-syms.cc (main): Likewise.
	* tests/test-read-dwarf.cc (main): Likewise.
	* tests/test-read-write.cc (main): Likewise.
	* tests/Makefile.am: Do not reference the libtoolsutils.la private
	library anymore.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-01-08 12:28:14 +01:00
Dodji Seketeli
76837d1cbf Update copyright years
* include/abg-comp-filter.h: Update copyright years.
	* include/abg-comparison.h: Likewise.
	* include/abg-config.h: Likewise.
	* include/abg-corpus.h: Likewise.
	* include/abg-diff-utils.h: Likewise.
	* include/abg-dwarf-reader.h: Likewise.
	* include/abg-fwd.h: Likewise.
	* include/abg-hash.h: Likewise.
	* include/abg-ini.h: Likewise.
	* include/abg-ir.h: Likewise.
	* include/abg-libxml-utils.h: Likewise.
	* include/abg-libzip-utils.h: Likewise.
	* include/abg-reader.h: Likewise.
	* include/abg-sptr-utils.h: Likewise.
	* include/abg-traverse.h: Likewise.
	* include/abg-viz-common.h: Likewise.
	* include/abg-viz-dot.h: Likewise.
	* include/abg-viz-svg.h: Likewise.
	* include/abg-writer.h: Likewise.
	* src/abg-comp-filter.cc: Likewise.
	* src/abg-comparison.cc: Likewise.
	* src/abg-config.cc: Likewise.
	* src/abg-corpus.cc: Likewise.
	* src/abg-diff-utils.cc: Likewise.
	* src/abg-dwarf-reader.cc: Likewise.
	* src/abg-hash.cc: Likewise.
	* src/abg-ini.cc: Likewise.
	* src/abg-ir.cc: Likewise.
	* src/abg-libxml-utils.cc: Likewise.
	* src/abg-libzip-utils.cc: Likewise.
	* src/abg-reader.cc: Likewise.
	* src/abg-traverse.cc: Likewise.
	* src/abg-viz-common.cc: Likewise.
	* src/abg-viz-dot.cc: Likewise.
	* src/abg-viz-svg.cc: Likewise.
	* src/abg-writer.cc: Likewise.
	* tests/print-diff-tree.cc: Likewise.
	* tests/test-abidiff.cc: Likewise.
	* tests/test-alt-dwarf-file.cc: Likewise.
	* tests/test-core-diff.cc: Likewise.
	* tests/test-diff-dwarf.cc: Likewise.
	* tests/test-diff-filter.cc: Likewise.
	* tests/test-diff-suppr.cc: Likewise.
	* tests/test-diff2.cc: Likewise.
	* tests/test-ir-walker.cc: Likewise.
	* tests/test-lookup-syms.cc: Likewise.
	* tests/test-read-dwarf.cc: Likewise.
	* tests/test-read-write.cc: Likewise.
	* tests/test-utils.cc: Likewise.
	* tests/test-utils.h: Likewise.
	* tests/test-write-read-archive.cc: Likewise.
	* tools/abg-tools-utils.cc: Likewise.
	* tools/abg-tools-utils.h: Likewise.
	* tools/abiar.cc: Likewise.
	* tools/abidiff.cc: Likewise.
	* tools/abidw.cc: Likewise.
	* tools/abilint.cc: Likewise.
	* tools/abisym.cc: Likewise.
	* tools/binilint.cc: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-01-07 17:52:10 +01:00
Dodji Seketeli
929db0a880 Detect and report changes in ELF architecture
Libabigail does not take in account the architecture of the ELF file
it reads.  This patch changes that to represent the ELF architecture
as a string, detect when that architecture changes accross two corpora
being compared and emit a report about that change.

	* configure.ac: Detect the presence of libebl.a and add it to the
	list of library we depend on to build libabigail.  Report when
	libelf.so is not found.
	* include/abg-comparison.h:
	(diff_context::show_architecture_change): Declare new accessors.
	(corpus_diff::architecture_changed): Declare new method.
	* include/abg-corpus.h (corpus::{get,set}_architecture_name):
	Declare new accessors.
	* src/abg-comparison.cc
	(diff_context::priv::show_architecture_change_): New data member.
	(diff_context::priv::priv): Initialize it.
	(diff_context::show_architecture_change): Define new accessors.
	(function_decl_diff::report): Report when the size/alignment of
	the function address changes.
	(corpus_diff::priv::architectures_equal_): New data member.
	(corpus_diff::priv::priv): Initialize it.
	(corpus_diff::priv::emit_diff_stats): Take in account changes of
	architecture.
	(corpus_diff::architecture_changed): Define new method.
	(corpus_diff::length): Take in account changes of architecture.
	(corpus_diff::report): Report about changes of architecture.
	(compute_diff): In the overload for corpus_diff_sptr, detect
	changes fo architecture.
	* src/abg-corpus.cc (corpus_priv::architecture_name): Define new
	data member.
	(corpus::{get,set}_architecture_name): Define new method.
	* src/abg-dwarf-reader.cc: Include elfutils/libebl.h to use
	ebl_openbackend() and ebl_backend_name()
	(read_context::elf_architecture_): Define new data member.
	(read_context::elf_architecture): Define new accessor.
	(read_context::{load_elf_architecture, load_remaining_elf_data}):
	Define new methods.
	(read_corpus_from_elf): Use ctxt.load_remaining_elf_data() in lieu
	of ctxt.load_dt_soname_and_needed.  Stick the architecture into
	the corpus.
	* src/abg-reader.cc (read_corpus_from_input): Read the
	'architecture' XML property.
	* src/abg-writer.cc (write_corpus_to_native_xml): Write the
	'architecture' XML property.
	* tests/data/test-diff-dwarf/libtest-23-diff-arch-v0-32.so: New
	test input file.
	* tests/data/test-diff-dwarf/libtest-23-diff-arch-v0-64.so:
	Likewise.
	* tests/data/test-diff-dwarf/test-23-diff-arch-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test-23-diff-arch-v0.cc: Source code
	for the binary test input files above.
	* tests/data/Makefile.am: Add the new test input files to the
	source distribution.
	* tests/test-diff-dwarf.cc (in_out_specs): Add the new test input
	data to the set of input data to run this test harness over.
	* tests/test-read-dwarf.cc (main): Do not take the architecture in
	account during comparisons.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-01-07 17:52:10 +01:00
Dodji Seketeli
0e1d9f9892 Add a --dump-diff-tree to abidiff for debugging purposes
I have felt the need to emit a textual representation of the diff
nodes tree maintained by the comparison engine for changed functions
and variables.  This patch adds that functionality.

	* include/abg-comparison.h (enum visiting_kind): Add new
	DO_NOT_MARK_VISITED_NODES_AS_TRAVERSED enumerator.
	(diff_context::{default_output_stream, error_output_stream,
	dump_diff_tree}): Declare new accessors.
	(diff::end_traversing): Take a new boolean flag.
	(print_diff_tree): Add new overload for diff_sptr.
	* src/abg-comparison.cc
	(diff_context::priv::{default_output_stream_,
	error_output_stream_, dump_diff_tree_}): New data members.
	(priv::priv): Initialize them.
	(diff_context::{default_output_stream_, error_output_stream_,
	dump_diff_tree, dump_diff_tree}): Define new accessors.
	(diff::end_traversing): Take a new flag that control whether or
	not to mark the current diff node as having been traversed.
	(diff::traverse): Take in account the visiting kind carried by the
	visitor to determine if the visited node should be marked as being
	traversed.
	(corpus_diff::priv::maybe_dump_diff_tree): Define new member
	function.
	(corpus_diff::report): Call it.
	(diff_node_printer::visit): Pretty print the diff node just once.
	(print_diff_tree): Define a new overload for diff_sptr.
	* tools/abidiff.cc (options::dump_diff_tree): New data member.
	(options::options): Initialize it.
	(display_usage): Add a help string for the new --dump-diff-tree
	command line switch.
	(parse_command_line): Parse the new --dump-diff-tree command line
	switch.
	(set_diff_context_from_opts): Set the diff context according to
	the --dump-diff-tree presence.
	* doc/manuals/abidiff.rst: Add a bullet point for the new
	--dump-diff-tree command line switch.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-12-28 11:36:52 +01:00
Dodji Seketeli
3ca026b0ee Try harder to handle pointer/reference to void
When a pointer_type_def or reference_type_def is initialized with an
empty pointed-to type, we want consider that as a pointer/reference to
void.

This patch does that.  That helps to avoids to later crash because the
pointed-to-type is empty.  Also, this patch fixes spots where the
pointed-to-type seems nonetheless empty.

I have used the two different versions of libstdc++ from RHEL 6.5 and RHEL
7 to spot and fix these issues.

	* include/abg-fwd.h (type_or_void): Declare new function.
	* src/abg-ir.cc (type_or_void): Define it.
	(pointer_type_def::pointer_type_def)
	(reference_type_def::reference_type_def)
	(reference_type_def::get_qualified_name, strip_typedef): Use it to
	ensure that empty pointed-to-type is considered as a void type.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-12-26 18:45:06 +01:00
Dodji Seketeli
1e82b98af2 Do not mark sibling structurally identical nodes as redundant
Consider the C code below:

    int
    foo(int a, int b)
    {
    }

that is changed as:

    float
    foo(float a, float b)
    {
    }

In this case, we want the 'abidiff' tool to report the three
occurrences of the 'int' -> 'float' change (in the return type and in
the two parameter changes of the function foo).

In the current code, the comparison engine only reports the first
occurrence of the change and consider the two other occurrences as
being redundant.  So, by default, it only reports the first occurrence
of the change.

This patch modifies the comparison engine to make it *NOT* mark the
two later occurrences of change as redundant because the three
occurrences of changes happen at the same logical level: they are all
children of the function diff node in the diff tree.

	* include/abg-comparison.h (diff::parent_node): Declare new
	accessor.
	* src/abg-comparison.cc (diff::priv::parent_): New data member.
	(diff::priv::priv): Initialize it.
	(diff::parent_node): Define new accessor.
	(diff::append_child_node): Set the diff::priv::parent_ data member
	of the added child node.
	(redundancy_marking_visitor::visit_begin): If two (logical)
	sibbling nodes are structurally equivalent, do not mark them as
	being redundant.
	* tests/data/test-diff-suppr/libtest10-changed-parm-c-v0.so: New
	test input binary.
	* tests/data/test-diff-suppr/libtest10-changed-parm-c-v1.so:
	Likewise.
	* tests/data/test-diff-suppr/test10-changed-parm-c-report-0.txt:
	New test input data.
	* tests/data/test-diff-suppr/test10-changed-parm-c-v0.c: Source
	code for the binary input above.
	* tests/data/test-diff-suppr/test10-changed-parm-c-v1.c: Likewise.
	* tests/data/Makefile.am: Add the new test files to source
	distribution.
	* tests/test-diff-suppr.cc (in_out_specs): Add the new test input
	to the vector of test inputs to run this harness over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-12-26 18:45:06 +01:00
Dodji Seketeli
817aa5555e Un-share diff nodes in the comparison IR
Until now, the diff nodes of the comparison IR were shared.  That is,
two diffs about the same subjects were represented by the same diff
node that would appear twice in the tree.

This was preventing us from spotting e.g, the first occurrence of a
diff node that would later (in the tree) turn to be redundant because
all redundant diff nodes are represented by the same diff node
pointer.

This patch now makes each diff node be different, as far of pointer
comparison is concerned.  But it introduces the concept of canonical
diff node to ease the comparison between two diff nodes.  Two diff
nodes that are equal have the same canonical diff node.

With this facility, it's now possible to tell the difference between
diff nodes that are (structurally) equal.  It's not possible to say
things like "this is the first or second occurrence of the redundant
diff node foo'.

	* include/abg-ir.h: Prefix the doc string with "///", rather than
	writing it inside a /**/ comment.
	* include/abg-comparison.h (function_decl_diff)
	(function_decl_diff_sptr, fn_parm_diff, fn_parm_diff_sptr)
	(var_diff_sptr, base_diff, class_diff, class_diff_sptr): Move
	these class & typedef decls to the top of the file.
	(string_changed_base_map, string_changed_parm_map)
	(unsigned_changed_parm_map, changed_function_ptr)
	(string_changed_function_ptr_map): Remove these typedefs.
	(string_base_diff_sptr_map, string_fn_parm_diff_sptr_map)
	(unsigned_fn_parm_diff_sptr_map, string_var_diff_sptr_map)
	(unsigned_var_diff_sptr_map, string_function_decl_diff_sptr_map)
	(string_var_diff_ptr_map): New typedefs.
	(diff_context::{has_diff_for,add_diff}): Make these member
	functions private.
	(diff_context::{set_canonical_diff_for,
	set_or_get_canonical_diff_for}): Declare new private member
	functions.
	(diff_context::{get_canonical_diff_for,
	initialize_canonical_diff}): New public member functions.
	(diff_context::maybe_apply_filters): Set the default value of the
	'traverse_nodes_once' parameter to false.
	(compute_diff): Make the overload for class_decl_sptr friend of
	the diff_context class.
	(class diff): Make the diff_context class a friend of this one.
	(diff::set_canonical_diff): Declare new private member function.
	(diff::get_canonical_diff): Declare new public member function.
	(diff::children_nodes): Make this return a vector<diff_sptr>, rather
	than a vector<diff*>.
	(diff::append_child_node): Make this take a diff_sptr rather than
	a diff*.
	(class fn_parm_diff): Declare new type.
	(compute_diff): Declare new overload for the new
	function_decl::parameter_sptr.
	(function_decl_diff::subtype_changed_parms): Return a
	string_fn_parm_diff_sptr_map rather than a string_changed_parm.
	(function_decl_diff::children_nodes): Return a vector<diff_sptr>.
	(function_decl_diff::append_child_node): Take a diff_sptr.
	(function_decl_diff::changed_functions): Return a
	string_function_decl_diff_sptr_map.
	(function_decl_diff::changed_variables): Return a
	string_var_diff_sptr.
	(class function_decl::parameter): Make this a pimpled class.
	Also, make it inherit decl_base.
	(equals): New overload for function_decl::parameter.
	(struct function_decl::parameter::hash): Declare this.
	(ir_node_visitor::visit): Declare new overload for
	function_decl::parameter.
	* src/abg-comparison.cc: Add doc-string about the internal
	representation of the comparison engine and also about the concept
	of canonical diff of the comparison engine.
	(RETURN_IF_BEING_REPORTED_OR_WAS_REPORTED_EARLIER)
	(RETURN_IF_BEING_REPORTED_OR_WAS_REPORTED_EARLIER2)
	(RETURN_IF_BEING_REPORTED_OR_WAS_REPORTED_EARLIER3): Consider the
	canonical diff when trying to know if the current node was
	reported earlier.
	(diff_context::priv::canonical_diffs): New data member.
	(diff_context::{get_canonical_diff_for, set_canonical_diff_for,
	set_or_get_canonical_diff_for, initialize_canonical_diff}): Define
	new member functions.
	(diff_context::{diff_has_been_traversed, mark_diff_as_traversed):
	Consider canonical diff for these tests and actions.
	(diff::priv::children_): Change the type of this to
	vector<diff_sptr>.
	(diff::canonical_diff_): New data member.
	(diff::diff): Initialize the diff::canonical_diff_ data member.
	(diff::begin_traversing): Mark the canonical diff node too.
	(diff::is_traversing): Consider the canonical diff node in this
	test.
	(diff::end_traversing): Make the canonical diff node too.  Also
	mark the current node as having been traversed.
	(diff::children_nodes): Return a vector<diff_sptr> type.
	(diff::{get_canonical_diff, set_canonical_diff}): Define new
	member functions.
	(diff::append_child_node): Take a diff_sptr type parameter.
	(diff::{reported_once, currently_reporting}): Flag the canonical
	diff node too.  And consider the canonical diff node when checking
	the flag.
	(diff::traverse): No need to mark the node as being traversed
	because the diff::end_traversing() function does it now.  Adjust
	the code because diff::children_nodes() now returns
	vector<diff_sptr>.
	({distinct_diff, var_diff, pointer_diff, array_diff,
	reference_diff, qualified_type_diff, enum_diff, class_diff,
	base_diff, scope_diff, function_decl_diff, typedef_diff,
	corpus_diff}::chain_into_hierarchy): Adjust to the new type that
	diff::append_child_node() takes.  Also, take into account that the
	diff nodes are now un-shared.
	(compute_diff_for_distinct_kinds, compute_diff_for_types)
	(compute_diff): Do not share diff nodes anymore.  Initialize the
	canonical diff node for the new created node.
	(represent): Take a var_diff_sptr rather than two var_decl_sptr.
	Adjust.  Also take in account the fact that diff nodes are not
	shared anymore, and that they do have canonical diffs.
	(var_diff::type_diff): Make the computation of the type_diff of
	the var_diff be lazy.  This avoids infinite (recursive) creation
	of diff nodes when a class diff node has a sub-type of data member
	that is a class diff node too.
	(var_diff::report): Detect redundant reporting of this kind of
	diff node.
	(class_diff::priv::changed_bases_): Change the type of this to
	string_base_diff_sptr_map.
	(class_diff::priv::subtype_changed_dm_): Change the type of this
	to string_var_diff_sptr_map.
	(class_diff::priv::changed_dm_): Change the type of this to
	unsigned_var_diff_sptr_map.
	(class_diff::priv::{count_filtered_subtype_changed_dm,
	count_filtered_bases}): Do not take a diff_context_sptr anymore.
	(class_diff::ensure_lookup_tables_populated): changed_bases_
	subtype_changed_dm_ and changed_dm_ are now *NOT* shared diff
	nodes anymore.
	(class_diff::priv::base_has_changed): Adjust.
	(class_diff::priv::subtype_changed_dm): Adjust.
	(class_diff::priv::count_filtered_bases): Adjust as changed_bases_
	is now a map of un-shared diff nodes.
	(class_diff::priv::count_filtered_subtype_changed_dm): Adjust as
	subtype_changed_dm_ is now a map of un-shared diff nodes.
	(class_diff::priv::{count_filtered_changed_mem_fns,
	count_filtered_inserted_mem_fns, count_filtered_deleted_mem_fns,
	}): Adjust for change of the default parameter value of
	diff_context::maybe_apply_filters().
	(class_diff::~class_diff): New destructor.
	(class_diff::changed_bases): Return a string_base_diff_sptr_map&
	type.
	(class_diff::{inserted_data_members, deleted_data_members,
	changed_member_fns}): Add doc strings.
	(struct changed_data_member_comp): Remove.
	(struct var_diff_comp): New comparison functor.
	(sort_changed_data_members): Remove.
	(sort_var_diffs): Define new sorting function.
	(class_diff::report): Adjust.
	(fn_parm_diff::*): Define member types and functions of the new
	fn_parm_diff type.
	(function_decl_diff::priv::{subtype_changed_parms_,
	changed_parms_by_id_}): Make these take a map of fn_parm_diff_sptr
	nodes.
	(function_decl_diff::ensure_lookup_tables_populated): Adjust to
	the fact that priv_->subtype_changed_parms_ and
	priv_->priv_->changed_parms_by_id_ now are maps of un-shared
	fn_parm_diff_sptr nodes.
	(function_decl_diff::subtype_changed_parms): Adjust.
	(struct changed_parm_comp): Remove.
	(struct fn_parm_diff_comp): New comparison functor.
	(sort_changed_parm_map): Remove.
	(sort_string_fn_parm_diff_sptr_map): New sorting function.
	(function_decl_diff::report): Adjust.
	(corpus_diff::priv::children_): Change the type of this to
	vector<diff_sptr>.
	(corpus_diff::priv::changed_fns_): Changed the type of this to
	string_function_decl_diff_sptr_map.
	(corpus_diff::priv::changed_vars_): Changed the type of this to
	string_var_diff_sptr_map.
	(corpus_diff::priv::ensure_lookup_tables_populated): Adjust.
	(corpus_diff::priv::apply_filters_and_compute_diff_stats}):
	Adjust.  Do not need to clear redundancy categorization anymore
	because the diff nodes are not shared anymore.
	(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
	Adjust.
	(corpus_diff::priv::clear_redundancy_categorization): Adjust.
	(corpus_diff::changed_variables): Adjust.
	(struct changed_function_ptr_comp): Remove.
	(struct function_decl_diff_comp): New comparison functor.
	(sort_string_changed_function_ptr_map): Remove.
	(sort_string_function_decl_diff_sptr_map): Define new sorting
	function.
	(struct changed_vars_comp): Remove.
	(struct var_diff_sptr_comp): New comparison functor.
	(sort_changed_vars): Remove.
	(sort_string_var_diff_sptr_map): Define new sorting function.
	(corpus_diff::report): Adjust.
	(corpus_diff::traverse): Adjust.
	({category_propagation_visitor,
	suppression_categorization_visitor}::visit_end): Adjust.
	(clear_redundancy_categorization): Adjust.
	* src/abg-hash.cc (function_decl::parameter:#️⃣:operator):
	Adjust.
	* src/abg-ir.cc (struct function_decl::parameter::priv): Define
	here as part of pimpl-ifying the function_decl::parameter type.
	(function_decl::parameter::*): Define here the member functions as
	part of pimpl-ifying the function_decl::parameter type.
	(equals): Define the overload for function_decl::parameter here
	too.
	(ir_node_visitor::visit(function_decl::parameter*)): Define this.
	* tests/data/test-abicompat/test0-fn-changed-report-0.txt: Adjust.
	* tests/data/test-diff-suppr/test5-fn-suppr-report-0.txt: Adjust.
	* tests/data/test-diff-dwarf/libtest21-redundant-fn-v0.so: New
	test input data.
	* tests/data/test-diff-dwarf/libtest21-redundant-fn-v1.so:
	Likewise.
	* tests/data/test-diff-dwarf/test21-redundant-fn-v0.cc: Source
	code for test input binary above.
	* tests/data/test-diff-dwarf/test21-redundant-fn-v1.cc: Likewise.
	* tests/data/test-diff-dwarf/test21-redundant-fn-report-0.txt: New
	test input data.
	* tests/data/test-diff-dwarf/libtest22-changed-parm-c-v0.so: New
	test input data.
	* tests/data/test-diff-dwarf/libtest22-changed-parm-c-v1.so:
	Likewise.
	* tests/data/test-diff-dwarf/test22-changed-parm-c-v0.c: Source
	code for test input binary above.
	* tests/data/test-diff-dwarf/test22-changed-parm-c-v1.c: Likewise.
	* tests/test-diff-dwarf.cc (in_out_spec): Add the new test input
	data to the vector the test inputs to run this harness over.
	* tests/data/test-diff-suppr/test8-redundant-fn-report-0.txt: New
	test input data.
	* tests/data/test-diff-suppr/test8-redundant-fn-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/libtest8-redundant-fn-v0.so: New test
	input binary.
	* tests/data/test-diff-suppr/libtest8-redundant-fn-v1.so: Likewise.
	* tests/data/test-diff-suppr/test8-redundant-fn-v0.cc: Source code
	code for binary test input above.
	* tests/data/test-diff-suppr/test8-redundant-fn-v1.cc: Likewise.
	* tests/data/test-diff-suppr/test9-changed-parm-c-report-0.txt:
	New test input data.
	* tests/data/test-diff-suppr/test9-changed-parm-c-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/libtest9-changed-parm-c-v0.so: New
	test input binary.
	* tests/data/test-diff-suppr/libtest9-changed-parm-c-v1.so: New
	test input binary.
	* tests/data/test-diff-suppr/test9-changed-parm-c-v0.c: Source
	code for binary test input above.
	* tests/data/test-diff-suppr/test9-changed-parm-c-v1.c: Likewise.
	* tests/test-diff-suppr.cc (in_out_specs): Add the new test input
	data to the vector the test inputs to run this harness over.
	* tests/data/Makefile.am: Add the new files to the source
	distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-12-26 18:45:06 +01:00
Sinny Kumari
a6897b0fea Add new methods in corpus_diff class
Functions added_unrefed_function_symbols() and
added_unrefed_variable_symbols() are required in order to access
added functions and variables obtained while calculating abi diff
between libraries with no debug information available

	* include/abg-comparison.h
	(corpus_diff::added_unrefed_function_symbols):
	Declare new member function
	(corpus_diff::added_unrefed_variable_symbols):
	Declare new member function
	* src/abg-comparison.cc
	(corpus_diff::added_unrefed_function_symbols):
	Define new member function
	(corpus_diff::added_unrefed_variable_symbols):
	Define new member function

Signed-off-by: Sinny Kumari <skumari@redhat.com>
2014-12-18 15:27:39 +01:00
Sinny Kumari
a95af1c160 Add new corpus_diff::added_variables() method
Function added_variables() is required in order to access the list of
added variables obtained while calculating abi diff between two
libraries outside libabigail

	* include/abg-comparison.h (corpus_diff::added_variables):
	Declare new member function
	* src/abg-comparison.cc (corpus_diff::added_variables):
	Define new member function

Signed-off-by: Sinny Kumari <skumari@redhat.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-12-15 09:23:52 +01:00
Dodji Seketeli
8879d00538 Extend detection of compatible types to arrays
* include/abg-fwd.h (is_array_type): Renamed is_array_type_def()
	into this for consistency.
	* src/abg-comparison.cc (type_suppression::suppresses_diff):
	Adjust.
	* src/abg-dwarf-reader.cc (build_array_type): Remove useless code
	that was trying to read a DW_AT_byte_size attribute from the DIE
	of the array, but then wasn't doing anything with the value.  But
	then if the attribute was not present, the array type wouldn't be
	built.
	* src/abg-ir.cc (strip_typedef): Strip typedefs from sub-types of
	array types too.
	(is_array_type): Rename is_array_def() to this, for consistency.
	(var_decl::get_pretty_representation): Adjust.
	* tests/data/test-diff-filter/libtest24-compatible-vars-v0.so: New
	test input data.
	* tests/data/test-diff-filter/libtest24-compatible-vars-v1.so: Likewise.
	* tests/data/test-diff-filter/test24-compatible-vars-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test24-compatible-vars-v0.c: Source
	code for the first binary above.
	* tests/data/test-diff-filter/test24-compatible-vars-v1.c: Source
	code for the second binary above.
	* tests/data/Makefile.am: Add the new test input data to source
	distribution.
	* tests/test-diff-filter.cc (in_out_specs): Add the new test input
	data to the list of input to run this test harness over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-12-12 14:44:24 +01:00
Dodji Seketeli
1b75fd3eac Make determining of compatible types complete
Until now, two types that are different were considered compatible if
one type is a typedef of the other.  This is useful because two
different types, if compatible, are not ABI-incompatible.  This patch
extends the concept of compatible types to types which might have
sub-types that are typedefs of each others, including function types.

Note implementing this required that I fixed various other things left
and right.  Like style fixes, crash avoiding fixes, etc.

	* include/abg-fwd.h (is_reference_type, is_function_type)
	(is_method_type): Declare new predicates.
	* include/abg-ir.h (class qualified_type_def): Pimpl this class.
	(qualified_type_def::qualified_type_def): Use the convenience
	type_base_sptr typedef.
	(qualified_type_def::{get_cv_quals, set_cv_quals}): Use the
	qualified_type_def::CV type rather than char.
	(qualified_type_def::get_underlying_type): Use the convenience
	type_base_sptr typedef.
	(pointer_type_def::pointer_type_def): Likewise.
	(function_decl::parameter::parameter): Add a new constructor.
	* src/abg-ir.cc (is_reference_type, is_function_type)
	(is_method_type): Define new predicates.
	(class qualified_type_def::priv): Define this new private type,
	for the purpose of Pimpl-ifying the qualified_type_def class.
	(qualified_type_def::{qualified_type_def, build_name,
	get_cv_quals_string_prefix, get_underlying_type}): Adjust for the
	purpose of Pimpl-ifying the qualified_type_def class.
	(equals): In the qualified_type_def, reference_type_def overloads,
	trust the fact that we have operator== overload for the
	type_base_sptr.  This avoids crashes for when the (possible)
	underlying type is null.
	(pointer_type_def::operator==): Likewise.
	(strip_typedef): Make this recursively strip
	typedefs from sub-types.
	(types_are_compatible): Handle null types.
	(qualified_type_def::{get_cv_quals, set_cv_quals}): Handle
	qualified_type_def::CV rather than char.
	(pointer_type_def::pointer_type_def): Use the convenience
	type_base_sptr typedef.
	* include/abg-comparison.h (distinct_diff::compatible_child_diff):
	Declare new member function.
	* src/abg-comparison.cc (distinct_diff::compatible_child_diff):
	Define new member function.
	(distinct_diff::chain_into_hierarchy):
	Chain the compatible child diff node that might be present.
	(distinct_diff::report): Now when a distinct diff carries a
	compatible change, mention it in the report.
	* src/abg-comp-filter.cc (is_compatible_change): A compatible
	change can now involve types that are not typedefs.  Only their
	sub-types need to be involved with typedef-ness.
	* tests/data/test-diff-dwarf/test{2,4,5}-report.txt: Adjust.
	* tests/data/test-diff-filter/libtest21-compatible-vars-v0.so: New
	test data input.
	* tests/data/test-diff-filter/libtest21-compatible-vars-v1.so: Likewise.
	* tests/data/test-diff-filter/test21-compatible-vars-report-0.txt Likewise.
	* tests/data/test-diff-filter/test21-compatible-vars-report-1.txt Likewise.
	* tests/data/test-diff-filter/test21-compatible-vars-v0.cc: Source
	code for the first data input binary above.
	* tests/data/test-diff-filter/test21-compatible-vars-v1.cc: Source
	code for the second data input binary above.
	* tests/data/test-diff-filter/libtest22-compatible-fns-v0.so: New
	test data input.
	* tests/data/test-diff-filter/libtest22-compatible-fns-v1.so Likewise.
	* tests/data/test-diff-filter/test22-compatible-fns-report-0.txt:
	New test data input.
	* tests/data/test-diff-filter/test22-compatible-fns-report-1.txt: Likewise.
	* tests/data/test-diff-filter/test22-compatible-fns-v0.c: Source
	code for the first test data input binary above.
	* tests/data/test-diff-filter/test22-compatible-fns-v1.c: Source
	code for the second test data input binary above.
	* tests/data/Makefile.am: Add the new test input data to source
	distribution.
	* tests/test-diff-filter.cc (in_out_specs): Add the new test data
	input above to the list of test data this harness has to be run
	over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-12-10 08:02:32 +01:00
Dodji Seketeli
775cfcde0c Wire the soname check into abicompat
Now that the comparison engine knows how to take SONAMEs into account
during ABI abi comparison, it's feasible to make abicompat leverage
that capability.  This patch does just that.

	* include/abg-comparison.h (corpus_diff::soname_changed): Declare
	new member function.
	* src/abg-comparison.cc (corpus_diff::soname_changed): Define new
	member function.
	(corpus_diff::length): Use the new corpus_diff::soname_changed()
	method.
	* tests/data/test-abicompat/libtest4-soname-changed-v0.so: New
	test input data.
	* tests/data/test-abicompat/libtest4-soname-changed-v1.so:
	Likewise.
	* tests/data/test-abicompat/test4-soname-changed-app: Likewise.
	* tests/data/test-abicompat/test4-soname-changed-report-0.txt:
	Likewise.
	* tests/data/test-abicompat/test4-soname-changed-app.cc: Source
	code for one of the binaries above.
	* tests/data/test-abicompat/test4-soname-changed-v0.cc: Likewise.
	* tests/data/test-abicompat/test4-soname-changed-v1.cc: Likewise.
	* tests/test-abicompat.cc (in_out_specs): Add the new test input
	data to the list of input data to run this harness over.
	(main): Take the soname change in account to determine if the
	change is ABI incompatible.
	* tests/data/Makefile.am: Add the new test input data above to source
	distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-12-08 13:47:00 +01:00
Dodji Seketeli
721728e7de Support reading and comparing soname from ELF files
Libabigail's DWARF reader doesn't read the DT_SONAME tag from the
.dynamic section.  The abigail::corpus type doesn't have a property
for that tag either.  And the comparison engine doesn't take that tag
in when comparing corpora.

This patch modifies the DWARF reader to read the DT_SONAME and
DT_NEEDED tags from the .dynamic section.  The value of DT_SONAME tag
is then saved in the new corpus property accessed by the new
abigail::corpus::get_soname() accessor.  The comparison engine has
also been modified to compare the sonames of two corpora being
compared.  Note that the value of the DT_NEEDED elf tag is saved in a
new corpus property that is accessed via the new
abigail::corpus::get_needed() getter.  This property is not used yet.

This patch also adds a unit test for this new feature.

	* include/abg-corpus.h (corpus::{get_needed, set_needed,
	get_soname, set_soname}): Declare new accessors.
	* src/abg-corpus.cc (corpus::priv::{needed, soname}): New data
	members.
	(corpus::{get_needed, set_needed, get_soname, set_soname}): Define
	new accessors.
	(corpus::is_empty): Take dt_needed and dt_soname in account in
	computing empty-ness.
	* src/abg-dwarf-reader.cc (read_context::{dt_needed_,
	dt_soname_}): New data members.
	(read_context::{dt_needed, dt_soname}): New accessors.
	(read_context::load_dt_soname_and_needed): New member function.
	(read_corpus_from_elf): Call the new
	read_context::load_dt_soname_and_needed() to read the dt_soname
	and dt_needed tags.  Set them to the corpus.
	* include/abg-comparison.h (diff_context::show_soname_change):
	Declare new accessors.
	* src/abg-comparison.cc (diff_context::priv::show_soname_change_):
	New data member.
	(diff_context::priv::priv): Initialize the new data member
	diff_context::priv::show_soname_change_.
	(diff_context::show_soname_change): Define new accessors.
	(corpus_diff::priv::sonames_equal_): New data member.
	(corpus_diff::priv::priv): Initialize the new data member
	corpus_diff::priv::sonames_equal_.
	(corpus_diff::length): Take the new priv_->sonames_equals_ data
	member in account.
	(corpus_diff::{report, priv::emit_diff_stats}): If the sonames
	changed and we are allowed to report it, then report it.
	(compute_diff): In the variant for corpus_diff, do not forget to
	compare the sonames.
	* src/abg-reader.cc (build_needed, read_elf_needed_from_input):
	Define new static functions.
	(read_corpus_from_input): Read the 'soname' attribute from the
	'abi-corpus' xml element node.
	* src/abg-writer.cc (write_elf_needed): Define new static
	function.
	(write_corpus_to_native_xml): Write a new 'elf-needed' xml element
	node that contains one xml 'dependency' element node per
	dependency to emit.  This uses the new write_elf_needed() function
	above.
	* tests/data/test-diff-dwarf/libtest19-soname-v0.so: New test
	input data.
	* tests/data/test-diff-dwarf/libtest19-soname-v1.so: Likewise.
	* tests/data/test-diff-dwarf/test19-soname-report-0.txt: Likewise.
	* tests/data/test-diff-dwarf/test19-soname-v0.c: Source code of
	the first binary above.
	* tests/data/test-diff-dwarf/test19-soname-v1.c: Source code of
	the second binary above.
	* tests/test-diff-dwarf.cc (in_out_specs): Add the test input
	above to the list of test input to run this harness on.
	* tests/data/Makefile.am: Add the new test input data above.
	* tests/data/test-read-dwarf/test{0,1}.abi: Adjust.
	* tests/data/test-read-dwarf/test{2,3,4,6,}.so.abi: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-12-07 23:42:26 +01:00
Dodji Seketeli
ef7e71febf Initial implementation of the abicompat tool
Given an application A that links to a shared library L of version V
denoted L(V) and a subsequent version of that library denoted L(V+P),
the 'abicompat' tool tells the user if L(V+P) is still ABI compatible
with L(V+P).  And if it is not, abicompat gives a reports that shows
the differences between L(V) and L(V+P) that makes L(V+P)
ABI-incompatible with A.

The source code of this tool is in the tools/abicompat.cc source
file.  To support this new tool, this commit changes the comparison
engine to optionally avoid showing added symbols that were not
referenced by any debug info.  It changes the ABI corpus type to allow
the specification of a list of variables and functions symbols to keep
(and drop all other functions and variables which have other symbols
on the floor even before starting to compare the two libraries).

This is how the abicompat tool itself works.  It basically compares
L(V) and L(V+P) but it only looks at their exported functions and
variables which symbols are undefined in application A.  If the list
of exported and defined variables and functions of L(V) whose symbols
are undefined in A equals that of L(V+P) (including the sub-types of
these variables and functions) A is still compatible with L(V+P).
Otherwise, they might not be compatible depending on the kind of
differences that are found.

	* include/abg-comparison.h
	(diff_context::show_added_symbols_unreferenced_by_debug_info):
	Declare new accessors.
	(corpus_diff::{deleted_variables,
	deleted_unrefed_function_symbols,
	deleted_unrefed_variable_symbols,
	apply_filters_and_suppressions_before_reporting}): Declare new
	methods.
	(corpus_diff::diff_stats): Declare this new type.  Actually this
	was previously corpus_diff::priv::diff_stats, which was a hidden
	internal type..  We are moving it here, in the external API so
	that client code can have more information about changes
	statistics.  Change all the previously publicly accessible data
	members into accessor functions.
	* src/abg-comparison.cc (class corpus_diff::diff_stats::priv): New
	type.
	(diff_context::priv::show_added_syms_unreferenced_by_di_): New
	data member.
	(diff_context::priv::priv): Adjust.
	(diff_context::show_added_symbols_unreferenced_by_debug_info):
	Define this new method.
	(corpus_diff::priv::emit_diff_stats):  Do not show the diff stat
	if the only changes is added function or variables symbols and if
	we were instructed to not show added symbols.
	(corpus_diff::priv::{diff_stats_, filters_and_suppr_applied_}):
	New data members.
	(corpus_diff::priv::priv): Initialize the
	filters_and_suppr_applied_ data member.
	(corpus_diff::priv::diff_stats): Move this type to
	corpus_diff::diff_stats.
	(corpus_diff::priv::{apply_filters_and_compute_diff_stats,
	emit_diff_stats}): Adjust.
	(corpus_diff::apply_filters_and_suppressions_before_reporting):
	Define new member function.
	(corpus_diff::report): Use the new
	apply_filters_and_suppressions_before_reporting() function, rather
	than applying the filters and suppressions by ourselves.  Also
	adjust to the use the accessors of the new corpus_diff::diff_stats
	type.
	(corpus_diff::{deleted_variables,
	deleted_unrefed_function_symbols,
	deleted_unrefed_variable_symbols}): Define new accessors.
	(corpus_diff::diff_stats::{diff_stats, num_func_removed,
	num_func_added, num_func_changed, num_func_filtered_out,
	net_num_func_changed, num_vars_removed, num_vars_added,
	num_vars_changed, num_vars_filtered_out, net_num_vars_changed,
	num_func_sym_removed, num_func_syms_added, num_var_syms_removed,
	num_var_syms_added}): Define new member functions.
	* include/abg-corpus.h (corpus::{get_sym_ids_of_fns_to_keep,
	get_sym_ids_of_vars_to_keep}): Declare new methods.
	* src/abg-corpus.cc (corpus::priv::{sym_id_fns_to_keep,
	sym_id_vars_to_keep}): Added data members.
	(symtab_build_visitor_type::{unrefed_fun_symbols,
	unrefed_var_symbols, sym_id_fns_to_keep, sym_id_vars_to_keep}):
	Added new data members.
	(symtab_build_visitor_type::symtab_build_visitor_type): Take two
	additional parameters for the function and variable symbol ids to
	keep.
	(symtab_build_visitor_type::add_fn_to_wip_fns): Take the function
	symbols to keep in account when building the exported symbol
	table.
	(symtab_build_visitor_type::add_var_to_wip_vars): Likewise, take
	the variable symbols to keep in account when building the exported
	symbol table.
	(corpus::priv::build_public_decl_table): Adjust the initialization
	of the visitor that walks the ABI artifacts to build the exported
	symbol table to know take a list of function/variable symbols to
	keep.
	(corpus::priv::build_unreferenced_symbols_tables): Ensure that the
	public table of functions/variables is built before doing the work
	of this function.  Also, if a list of variable/function symbols to
	keep is given, drop all symbols that are not in that list on the
	floor.
	(corpus::{get_sym_ids_of_fns_to_keep,
	get_sym_ids_of_vars_to_keep}): Define new accessors.
	* tools/abicompat.cc: New abicompat tool.
	* doc/manuals/abicompat.rst: New documentation source for
	abicompat.
	* doc/manuals/libabigail-tools.rst: Add an entry for the abicompat
	doc.
	* tests/test-abicompat.cc: New test harness for the 'abicompat'
	tool.
	* tests/Makefile.am: Build the runtestabicompat test harness and
	add it to the list of tests harnesses that are run by make check.
	* tests/data/test-abicompat/libtest0-fn-changed-libapp-v0.so: New
	test input.
	* tests/data/test-abicompat/libtest0-fn-changed-libapp-v1.so: Likewise.
	* tests/data/test-abicompat/test0-fn-changed-app: Likewise.
	* tests/data/test-abicompat/test0-fn-changed-0.suppr: Likewise
	* tests/data/test-abicompat/test0-fn-changed-report-0.txt: Likewise.
	* tests/data/test-abicompat/test0-fn-changed-report-1.txt: Likewise.
	* tests/data/test-abicompat/test0-fn-changed-app.cc: Likewise.
	* tests/data/test-abicompat/test0-fn-changed-libapp.h: Likewise.
	* tests/data/test-abicompat/test0-fn-changed-libapp-v0.cc: Likewise.
	* tests/data/test-abicompat/test0-fn-changed-libapp-v1.cc: Likewise.
	* tests/data/test-abicompat/libtest1-fn-removed-v0.so: Likewise.
	* tests/data/test-abicompat/libtest1-fn-removed-v1.so: Likewise.
	* tests/data/test-abicompat/test1-fn-removed-app: Likewise.
	* tests/data/test-abicompat/test1-fn-removed-app.cc: Likewise.
	* tests/data/test-abicompat/test1-fn-removed-report-0.txt: Likewise.
	* tests/data/test-abicompat/test1-fn-removed-v0.cc: Likewise.
	* tests/data/test-abicompat/test1-fn-removed-v1.cc: Likewise.
	* tests/data/test-abicompat/libtest2-var-removed-v0.so: Likewise.
	* tests/data/test-abicompat/libtest2-var-removed-v1.so: Likewise.
	* tests/data/test-abicompat/test2-var-removed-app: Likewise.
	* tests/data/test-abicompat/test2-var-removed-app.cc: Likewise.
	* tests/data/test-abicompat/test2-var-removed-report-0.txt: Likewise.
	* tests/data/test-abicompat/test2-var-removed-v0.cc: Likewise.
	* tests/data/test-abicompat/test2-var-removed-v1.cc: Likewise.
	* tests/data/test-abicompat/libtest3-fn-removed-v0.so: Likewise.
	* tests/data/test-abicompat/libtest3-fn-removed-v1.so: Likewise.
	* tests/data/test-abicompat/test3-fn-removed-app: Likewise.
	* tests/data/test-abicompat/test3-fn-removed-app.cc: Likewise.
	* tests/data/test-abicompat/test3-fn-removed-report-0.txt: Likewise.
	* tests/data/test-abicompat/test3-fn-removed-v0.cc: Likewise.
	* tests/data/test-abicompat/test3-fn-removed-v1.cc: Likewise.
	* tests/data/test-abicompat/test3-fn-removed-version-script-0 Likewise.:
	* tests/data/test-abicompat/test3-fn-removed-version-script-1: Likewise.
	* tests/data/Makefile.am: Add the new test inputs above to the
	source distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-12-05 15:43:31 +01:00
Dodji Seketeli
06279598c8 Support reading undefined symbols from an ELF file
In preparation to support the upcoming 'abicompat' tool, we need the
ABI corpus type to capture the symbols that are undefined in a given
ELF file.

This patch changes the ELF reader to capture the undefined symbols as
well as the symbol versions they need to be satisfied.  These
undefined symbols are then stored in the instance ABI corpus build as
a result of the reading of the ELF file.

At the moment, these undefined symbols are not serialized to the
native XML format of libabigail yet.  I guess I'll do that in a
subsequent patch.

	* include/abg-corpus.h (corpus::{set_undefined_fun_symbol_map,
	set_undefined_var_symbol_map, get_undefined_fun_symbol_map_sptr,
	get_undefined_fun_symbol_map, get_sorted_undefined_fun_symbols,
	get_undefined_var_symbol_map_sptr, get_undefined_var_symbol_map,
	get_sorted_undefined_var_symbols}): Declare new methods ...
	* src/abg-corpus.cc (corpus::{set_undefined_fun_symbol_map,
	set_undefined_var_symbol_map, get_undefined_fun_symbol_map_sptr,
	get_undefined_fun_symbol_map, get_sorted_undefined_fun_symbols,
	get_undefined_var_symbol_map_sptr, get_undefined_var_symbol_map,
	get_sorted_undefined_var_symbols}): ... and define them.
	(struct corpus::priv::{undefined_var_symbol_map,
	sorted_undefined_var_symbols, undefined_fun_symbol_map,
	sorted_undefined_fun_symbols}): New data members.
	* src/abg-dwarf-reader.cc (get_symbol_versionning_sections): Also
	return the SHT_GNU_verneed section.
	(get_version_needed_for_versym): New static function.
	(get_version_definition_for_versym): Factorize this function out
	of ..
	(get_version_for_symbol): ... this one.  Take a flag that says if
	we want the definition version or the needed version of a symbol.
	Extend the implementation using the two new function
	get_version_needed_for_versym() and
	get_version_definition_for_versym() above.  This function now
	returns the version either for a defined & exported symbol, or for
	an undefined symbol.
	(lookup_symbol_from_sysv_hash_tab)
	(lookup_symbol_from_gnu_hash_tab, lookup_symbol_from_symtab):
	Adjust for the change of signature of get_version_for_symbol().
	(read_context::{undefined_fun_syms_, undefined_var_syms_}): New
	data members.
	(read_context::lookup_elf_symbol_from_index): Adjust for
	invocation of the new signature of get_version_for_symbol().
	(read_context::{undefined_fun_syms_sptr, undefined_fun_syms,
	undefined_var_syms_sptr, undefined_var_syms}): Define new methods.
	(read_context::load_symbol_maps): Add support for loading
	undefined symbols and their versions.
	(read_context::maybe_load_symbol_maps):  Take in account the need
	to load undefined symbols as well.
	(read_corpus_from_elf): Once the undefined symbols have been read
	from the ELF file, stuff them into the resulting ABI corpus that
	has been built.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-30 19:57:05 +01:00
Dodji Seketeli
6be1218195 Rename elf_symbol::get_is_defined() to elf_symbol::is_defined()
It's let's awkward to type if (elf_symbol->is_defined()); than
...->get_is_defined().  So I am going to the former.  A chance we
still can change ABI here ;-)

	* include/abg-ir.h (elf_symbol::get_is_defined): Rename into
	elf_symbol::is_defined.
	(elf_symbol::set_is_defined): Rename into elf_symbol::is_defined.
	* src/abg-ir.cc (elf_symbol::get_is_defined): Likewise, rename
	this into elf_symbol::is_defined.
	(elf_symbol::set_is_defined): Likewise, rename this into
	elf_symbol::is_defined.
	(elf_symbol::{elf_symbol, is_public}): Adjust.
	* src/abg-writer.cc (write_elf_symbol): Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-30 19:57:04 +01:00
Dodji Seketeli
d6bba81ac0 Update the copyright years of include/abg-corpus.h
* include/abg-corpus.h: Update the copyright years of this file.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-30 19:57:04 +01:00
Dodji Seketeli
3f9b3c0d8a Fix the reference to the IRC channel on the web page
* doc/website/mainpage.txt: The IRC server address is
	irc.oftc.net, not just oftc.net.
	* include/abg-fwd.h: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-18 23:14:49 +01:00
Dodji Seketeli
c8c7bd14f4 Cleanup of the web page
* doc/website/libabigail-website.doxy: Remove the redundant
	information that was appearing on the web page.
	* doc/website/mainpage.txt: Clean-up the text of the web page, add
	information for the new IRC channel #libabigail on oftc.net,
	re-organize the content by putting sections where we had
	paragraphs.  Add a table of content.  Also add a web form to
	subscribe/unsubscribe to the mailing list.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-10 15:47:10 +01:00
Dodji Seketeli
0dd5f64279 Sort elf symbols before serializing them
* include/abg-corpus.h (corpus::{get_sorted_fun_symbols,
	get_sorted_var_symbols}): Declare new member functions.
	* src/abg-corpus.cc (corpus_priv::{sorted_var_symbols,
	sorted_fun_symbols}): New data members.
	(struct elf_symbol_comp_functor): Define new comparison functor.
	(corpus::{get_sorted_fun_symbols, get_sorted_var_symbols}): Define
	new member functions.
	* src/abg-writer.cc (write_elf_symbols_table): Take a sorted
	vector of symbols in parameters, rather than an unsorted map.
	(write_corpus_to_native_xml): Write a sorted vector of symbols,
	rather than an unsorted map of symbols.
	* tests/data/test-read-dwarf/test0.abi: Adjust.
	* tests/data/test-read-dwarf/test1.abi: Likewise.
	* tests/data/test-read-dwarf/test2.so.abi: Likewise.
	* tests/data/test-read-dwarf/test3.so.abi: Likewise.
	* tests/data/test-read-dwarf/test6.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-08 11:22:43 +01:00
Dodji Seketeli
d3b188f859 Fix template parameter hashing: make it know about enclosing template
* include/abg-ir.h (template_parameter_sptr, template_decl_sptr)
	(template_decl_wptr): Declare new typedefs.
	(class template_decl): Make this virtually inherit decl_base and
	pimpl-ify it.
	(class template_parameter): Pimpl-ify this.  Make the constructor
	take the enclosing template parameter.
	(struct template_decl::hash): Declare this here, rather than in
	src/abg-hash.cc
	(class type_tparameter, non_type_tparameter, template_tparameter)
	(class type_composition, function_tdecl, class_tdecl): Pimpl-ify
	this.
	* src/abg-hash.cc (template_parameter:#️⃣:operator()): Hash the
	enclosing template parameter.  Avoid infinite recursion due to the
	loop hash parameter -> hash template -> hash parameter.
	(template_decl:#️⃣:operator()) Define this here, now that it's
	declared in abg-ir.h.  Also, avoid infinite recursion here; this
	is complementary to what is done in the hashing for
	template_parameter.
	({type_tparameter, template_tparameter, }:#️⃣:operator()):
	Cache the calculated hash just as what is done for other types
	hashed.
	(template_decl::priv): Define this new type.
	(template_decl::{add_template_parameter, get_template_parameters,
	~template_decl}): Define these here to pimpl-ify template_decl.
	(template_parameter::priv): Define this new type.
	(template_parameter::template_parameter): Define this here to
	pimpl-ify template_parameter.  Note also that this now takes the
	enclosing template decl.
	(template_parameter::{get_index, get_enclosing_template_decl,
	get_hashing_has_started, set_hashing_has_started, operator::==}):
	Define these here to pimpl-ify template_parameter.
	(type_tparameter::priv): Define this new type.
	(type_tparameter::type_tparameter): Define this here to pimpl-ify
	type_tparameter.   Also, not that this constructor now takes the
	enclosing template decl.
	(class non_type_tparameter::priv): Define new type.
	(non_type_tparameter::{non_type_tparameter, get_type}): Define
	these here to pimpl-ify non_type_tparameter.  The constructor now
	takes the enclosing template.
	(template_tparameter::priv): Define new type.
	(template_tparameter::template_tparameter): Define this here to
	pimpl-ify template_tparameter.  This constructor now takes the
	enclosing template.
	(class type_composition::priv): New type.
	(type_composition::{type_composition, get_composed_type,
	set_composed_type}): Define these here to pimpl-ify
	type_composition.  The constructor now takes the enclosing
	template decl.
	(class function_tdecl::priv): Define new type.
	(function_tdecl::{function_tdecl, set_pattern, get_pattern,
	get_binding}): Define this here to pimpl-ify function_tdecl.
	(class class_tdecl::priv): Define this new type.
	(class_tdecl::class_tdecl): Define this here to pimpl-ify
	class_tdecl.
	(class_tdecl::set_pattern): Adjust to pimpl-ify.
	(class_tdecl::get_pattern): Define new pimpl-ified getter.
	* src/abg-reader.cc (build_function_tdecl, build_class_tdecl):
	Cleanup.  Pass the enclosing template to the template parameters
	that are built.
	(build_type_tparameter, build_type_composition)
	(build_non_type_tparameter, build_template_tparameter)
	(build_template_parameter): Take the enclosing template
	declaration and pass it to the template parameter being created.
	* tests/data/test-read-write/test12.xml: Fix and Adjust.
	* tests/data/test-read-write/test13.xml: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-07 12:16:34 +01:00
Dodji Seketeli
ca8e5e38af Style fix
* include/abg-ir.h (class location): Remove useless white space.
	* src/abg-writer.cc (type_has_existing_id): Use type_base_sptr
	rather than shared_ptr<type_base>.
	(write_template_tparameter): Use template_tparameter_sptr rather
	than shared_ptr<template_tparameter>.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-07 12:15:09 +01:00
Dodji Seketeli
1082520383 Make the use of a C++-11 compiler optional
* configure.ac: Define a new --enable-cxx11 switch to control the
	use of the C++-11 compiler.  Define a WITH_CXX11 C macro and an
	automake ENABLE_CXX11 variable.
	* config.h.in: Initialize the new WITH_CXX11 C macro.
	* src/Makefile.am: Include the files coded in C++-11 only if the
	ENABLE_CXX11 automake variable is defined.
	* tests/Makefile.am: Likewise, build the runtestsvg test program
	only if C++-11 usage is enabled.
	* include/abg-diff-utils.h (class d_path_vec): Remove useless
	usage of the 'typename' keyword.
	* include/abg-fwd.h (is_enum_type): Renamed is_enum into this,
	because of a name clash with a tr1 function when not using C++-11.
	(is_pointer_type): Likewise, renamed is_pointer into this because
	of a name clash with a tr1 function when not using C++-11.
	* src/abg-comp-filter.cc (has_harmless_name_change): Adjust for
	the is_enum -> is_enum_type change.
	* src/abg-comparison.cc (type_suppression::suppresses_diff):
	Likewise.
	(class function_suppression::priv): Add a missing "class" keyword
	in friend declaration.
	(diff_context::diff_has_been_traversed)
	(diff_context::mark_diff_as_traversed): Do not use the C++-11
	specific type uintptr_t.
	* src/abg-dwarf-reader.cc (create_default_dwfl): Do not use
	designated initializers.  Sigh.  This is handy though.
	(expr_result::abs): Cast the argument of std::abs to avoid
	ambiguous call.
	(finish_member_function_reading): Adjust for the is_pointer ->
	is_pointer_type renaming.
	* src/abg-hash.cc (scope_decl:#️⃣:operator)
	(class_decl::base_spec:#️⃣:operator)
	(type_composition:#️⃣:operator): Use std::tr1::hash string,
	rather than the C++-11 specific std::hash function.
	* src/abg-ini.cc (read_sections, write_sections): Make
	std::ifstream constructor take a const char* rather than a string.
	* src/abg-ir.cc (is_enum_type, is_pointer_type): Renamed is_enum
	into is_enum_type and is_pointer into is_pointer_type.
	* src/abg-writer.cc (write_translation_unit): Remove useless
	typename keyword.  Make ofstream take a const char* rather than a
	string.
	(write_namespace_decl): Remove useless typename keyword.
	(write_corpus_to_native_xml_file): Make ofstream take a const
	char* rather than a string.
	* tests/test-abidiff.cc (main): Make ofstream take a const char*
	rather than a string.
	* tests/test-diff-dwarf.cc (main): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-05 10:45:07 +01:00
Dodji Seketeli
f5135b9d38 Fix an apidoc typo
* include/abg-comparison.h (class variable_suppression): Fix a
	typo in the doc string.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-01 15:16:42 +01:00
Dodji Seketeli
074eb74189 Cleanup the mainpage of the API doc
* include/abg-fwd.h: Cleanup text of the API doc mainpage.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-01 13:02:12 +01:00
Dodji Seketeli
2e896ce107 Initial support for variable suppressions
* include/abg-comparison.h (variable_suppression_sptr)
	(variable_suppressions_type): New convenience typedefs.
	(class variable_suppression): Declare new type.
	* src/abg-comparison.cc (is_var_diff): New predicate.
	(read_variable_suppression): Define new static function.
	(class variable_suppression::priv): Define type for the private
	data of the variable_suppression type.
	(variable_suppression::{variable_suppression,
	~variable_suppression, get_name, set_name, get_name_regex_str,
	set_name_regex_str, get_symbol_name, set_symbol_name,
	get_symbol_name_regex_str, set_symbol_name_regex_str,
	get_symbol_version, set_symbol_version,
	get_symbol_version_regex_str, set_symbol_version_regex_str,
	get_type_name, set_type_name, get_type_name_regex_str,
	set_type_name_regex_str, suppresses_diff}): Define new member
	functions for the variable_suppression type.
	* tests/data/test-diff-suppr/libtest7-var-suppr-v0.so: Add new
	test input.
	* tests/data/test-diff-suppr/libtest7-var-suppr-v1.so: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-1.suppr: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-2.suppr: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-3.suppr: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-4.suppr: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-5.suppr: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-6.suppr: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-7.suppr: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-8.suppr: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-report-0.txt: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-report-1.txt: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-report-2.txt: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-report-3.txt: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-report-4.txt: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-report-5.txt: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-report-6.txt: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-report-7.txt: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-report-8.txt:
	Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-version-script: Likewise.
	* tests/data/test-diff-suppr/test7-var-suppr-v0.cc: Source code
	for the librairie above.
	* tests/data/test-diff-suppr/test7-var-suppr-v1.cc: Source code
	for the librairie above.
	* tests/Makefile.am: Add the new test input data to the source
	distribution.
	* tests/test-diff-suppr.cc: Update to make this harness to run
	over the new test input above.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-01 12:22:08 +01:00
Dodji Seketeli
ba77dd98c4 Make var_diff and function_decl_diff extend decl_diff_base
* include/abg-comparison.h (class var_diff, class
	function_decl_diff): Make these types inherit the decl_diff_base
	class.  This is like the fact that all kinds of diff inherit the
	type_diff_base class.
	* src/abg-comparison.cc (var_diff::var_diff)
	(function_decl_diff::function_decl_diff): Adjust to initialize the
	sub-object of decl_diff_base;
	(is_decl_diff): New predicate to know if a diff is about decls.
	(is_function_decl): New predicate to know if a diff is about
	function decls.
	(function_suppression::suppresses_diff): Adjust to use the new
	is_function_decl.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-01 12:15:14 +01:00
Dodji Seketeli
3816b22e6f Remove useless functions from the comparison engine
* include/abg-comparison.h (read_type_suppression): Remove this
	function declaration.
	* src/abg-comparison.cc (read_type_suppressions): Remove this
	static function definition.
	(read_function_suppressions): Remove this static function
	declaration.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-01 12:15:14 +01:00
Dodji Seketeli
4200a7cbb9 Fix various apidoc typos
* include/abg-comparison.h (class function_suppression): Fix typo
	in the doc string.
	* src/abg-comparison.cc (is_type_diff, read_suppressions)
	(diff::reported_once, typedef_diff::report): Fix the doc string.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-11-01 12:15:14 +01:00
Dodji Seketeli
23772b3f8d Initial support for function suppressions
* include/abg-comparison.h (enum visiting_kind): Change the
	meaning of this.  It was to determine if traversal was to be done
	in a pre or post manner.  But with the recent addition of
	diff_node_visitor::visit_{begin,end}() notifiers, the pre/post
	handling is taken care of in a different way.  So now the meaning
	of this enum is changed to handle whether diff node children
	should be visited or not.  So the enumerators are now
	DEFAULT_VISITING_KIND, and SKIP_CHILDREN_VISITING_KIND.  And it's
	a bit-field.
	(operator{&,~}): Declare more bit manipulation operators for the
	enum visiting_kind.
	(function_suppression_sptr, function_suppressions_type): New
	typedefs.
	(function_suppression, function_suppression::parameter_spec):
	Declare new types.
	(read_function_suppressions): Declare new function.
	(diff_node_visitor::diff_node_visitor): Adjust for the enum
	visiting_kind change.  Value-initialize the visiting_kind_ data
	member.
	* src/abg-comparison.cc (operator{&,~}): Define these operators
	for enum visiting_kind.
	(read_type_suppressions): Forward declare this static function.
	(read_function_suppression, read_parameter_spec_from_string):
	Define new static functions.
	(read_suppressions): Update to read function suppressions too,
	using the new read_function_suppression function above.
	(class function_suppression::parameter_spec::priv): Define new
	type.
	(function_suppression::parameter_spec::*): Define the member
	functions of the new function_suppression::parameter_spec type.
	(class function_suppression::priv): Define new type.
	(function_suppression::*): Define the member functions of the new
	function_suppression type.
	(diff::traverse): There is no more {PRE,POST}_VISITING_KIND
	enumerator.  So nuke the code that was dealing with it.
	(redundancy_marking_visitor::skip_children_nodes_): New data
	member flag.
	(redundancy_marking_visitor::visit_begin): If the current diff
	node is not be reported (is filtered out), do not bother visit its
	children nodes for the purpose of marking redundant nodes.  So use
	the new skip_children_nodes_ flag above to know we are in that case.
	(redundancy_marking_visitor::visit_end): Unset the new
	skip_children_nodes_ flag above when appropriate.
	* include/abg-fwd.h (is_function_decl): Declare new function.
	* include/abg-ir.h
	(function_type::get_parm_at_index_from_first_non_implicit_parm):
	Declare new member function.
	* src/abg-ir.cc (is_function_decl): Define new function.
	(function_type::get_parm_at_index_from_first_non_implicit_parm):
	Define new member function.
	* src/abg-comp-filter.cc (apply_filter): Adjust for the enum
	visiting_kind change.  No need to set it for filters anymore
	* doc/suppr-doc.txt: Update examples of function suppression.
	* doc/manuals/libabigail-concepts.rst: Update the manual for the
	function suppression addition.
	* tests/data/test-diff-suppr/libtest5-fn-suppr-v0.so: New test input.
	* tests/data/test-diff-suppr/libtest5-fn-suppr-v1.so: New test input.
	* tests/data/test-diff-suppr/libtest6-fn-suppr-v0.so: New test input.
	* tests/data/test-diff-suppr/libtest6-fn-suppr-v1.so: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-0.suppr: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-1.suppr: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-2.suppr: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-3.suppr: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-4.suppr: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-report-0.txt: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-report-1.txt: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-report-2.txt: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-report-3.txt: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-report-4.txt: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-report-5.txt: New test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-v0.cc: Source code for
	new test input.
	* tests/data/test-diff-suppr/test5-fn-suppr-v1.cc: Source code for
	new test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-0.suppr: New test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-1.suppr: New test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-2.suppr: New test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-3.suppr: New test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-report-0.txt: New test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-report-1.txt: New test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-report-2.txt: New test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-report-3.txt: New test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-report-4.txt: New test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-v0.cc: Source code for
	new test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-v1.cc: Source code for
	new test input.
	* tests/data/test-diff-suppr/test6-fn-suppr-version-script: New
	test input.
	* tests/Makefile.am: Add the new files above to source
	the distribution.
	* tests/test-diff-suppr.cc (in_out_specs): Add the test inputs
	above to the list of tests to be run by this harness.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-28 17:36:32 +01:00
Dodji Seketeli
2f52f72b5a Add missing virtual destructor in comparison engine code
* include/abg-comparison.h (type_suppression::~type_suppression):
	Declare missing virtual destructor.
	* src/abg-comparison.cc (type_suppression::~type_suppression):
	Define missing virtual destructor.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-28 12:05:24 +01:00
Dodji Seketeli
8a3b969f87 Pimplify abigail::ir::function_type
* include/abg-ir.h (function_type::priv_): Declare new data
	member.
	(function_type::<all the methods>): Move the inline methods out of
	line in src/abg-ir.cc.
	(function_type::{return_type_, parms_}): Move these ...
	* src/abg-ir.cc (function_type::priv::{return_type_, parms_}):
	... Here.
	(struct function_type::priv): New type for the private data of
	function_type.
	(function_type::<all the methods>): Move the previously inline
	methods of function_type here.  Adjust them to tap into priv_->*
	to get the private data members.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-27 21:13:59 +01:00
Dodji Seketeli
362d8aa919 Light style fix
* include/abg-ir.h (function_decl::get_type): Change the return
	type from shared_ptr<function_type> to function_type_sptr.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-27 21:13:51 +01:00
Dodji Seketeli
f44110b326 Support comparing symbols not referenced by debug info
* doc/manuals/abidiff.rst: Adjust intro to mention that w/o debug
	info, abidiff now works but just report about added/removed
	symbols.  Add documentation about the new
	--no-unreferenced-symbols option.
	* include/abg-comparison.h (string_elf_symbol_map): New typedef.
	(diff_context::show_symbols_unreferenced_by_debug_info): Declare
	new accessors.
	* src/abg-comparison.cc
	(diff_context::priv::show_syms_unreferenced_by_di_): New data
	member.
	(diff_context::priv::priv): Adjust.
	(diff_context::show_symbols_unreferenced_by_debug_info): Implement
	these accessors.
	(corpus_diff::priv::{unrefed_fn_syms_edit_script_,
	unrefed_var_syms_edit_script_, added_unrefed_fn_syms_,
	deleted_unrefed_fn_syms_, added_unrefed_var_syms_,
	deleted_unrefed_var_syms_}): New data members.
	(corpus_diff::priv::diff_stats::{num_func_syms_removed,
	num_func_syms_added, num_var_syms_removed, num_var_syms_added}):
	New data members.
	(corpus_diff::priv::diff_stats::diff_stats): Adjust.
	(corpus_diff::ensure_lookup_tables_populated): Populate lookup
	tables for added/removed symbols that are not referenced by any
	debug info.
	(corpus_diff::priv::apply_filters_and_compute_diff_stats): Compute
	stats for the added/removed symbols not referenced by any debug
	info.
	(corpus_diff::priv::emit_diff_stats): Emit stats about
	added/removed symbols that are not referenced by any debug info.
	(corpus_diff::length): Adjust to take in account added/removed
	symbols not referenced by any debug info.
	(show_linkage_name_and_aliases): New static function.
	(corpus_diff::report): When emitting a symbol name, emit its
	version too, and tell if it aliases other symbols.  Avoid emitted
	extra new lines.  Report added/removed symbols not referenced by
	any debug info.
	(compute_diff): In the overload for corpus_sptr, compute the diffs
	for symbols not referenced by debug info.
	* include/abg-corpus.h
	(corpus::get_unreferenced_{function,variable}_symbols): Declare
	new member functions.
	* src/abg-corpus.cc (corpus_priv::{unrefed_fun_symbols,
	unrefed_var_symbols}): New data members.
	(corpus_priv::build_unreferenced_symbols_tables): Define new
	member function.
	(struct comp_elf_symbols_functor): New functor.
	(corpus::is_empty): Adjust to take in account added/removed
	symbols not referenced by debug info.
	(corpus::{get_unreferenced_function_symbols,
	corpus::get_unreferenced_variable_symbols}): Define these
	accessors.
	* include/abg-dwarf-reader.h (enum status): Transform this into
	bitfields.  Add a STATUS_UNKNOWN value that has the value 0.
	(operator|(status, status), operator&(status, status))
	(operator|=(status&, status), operator&=(status, status)): New
	bit-wise operators to manipulate instances of the status bit-field.
	* src/abg-dwarf-reader.cc (get_version_for_symbol): Fix this to
	avoid returning garbage version sometimes.
	(read_debug_info_into_corpus): Fix this to return a non-null but
	empty corpus_sptr when there is no debug info available.
	(operator|(status, status), operator&(status, status))
	(operator|=(status&, status), operator&=(status, status)): Define
	these new bitwise operators to manipulate instances of the status
	bit-field.
	(read_corpus_from_elf): Now that the abigail::dwarf_reader::status
	is a bit-field, set it to reflect if debug info and/or symbol
	tables have been found.  Do not bail out if debug info hasn't been
	found.  Rather, keep going, and go look for symbols-only; this is
	a kind of operating in degraded mode.
	* include/abg-ir.h (elf_symbol::get_aliases_id_string): Add a flag
	that says if the current instance of elf_symbol should be included
	in the list of aliases or not.
	* src/abg-ir.cc (elf_symbol::get_aliases_id_string): Define it.
	* tests/data/test-diff-dwarf/test16-syms-only-v{0,1}.o: New test
	input.
	* tools/abidiff.cc
	(options::show_symbols_not_referenced_by_debug_info): New data
	member.
	(options:options): Adjust.
	(display_usage): Add an info string for the new
	--no-unreferenced-symbols command line option.
	(parse_command_line): Parse the new --no-unreferenced-symbols
	command line.
	(set_diff_context_from_opts): Set the diff_context according to
	the presence of --no-unreferenced-symbols.
	(main): Adjust for the fact that abigail::dwarf_reader::status is
	now a bit-field.
	* tools/abilint.cc (main): Adjust for the fact that
	abigail::dwarf_reader::status is now a bit-field..
	():
	* tests/data/test-diff-dwarf/test16-syms-only-report.txt: New test
	reference output.
	* tests/data/test-diff-dwarf/test16-syms-only-v{0,1}.cc: Source code
	for new test input.
	* tests/data/test-diff-dwarf/test17-non-refed-syms-v{0,1}.o: New
	test input.
	* tests/data/test-diff-dwarf/test17-non-refed-syms-v{0,1}.cc: New
	source code for test input.
	* tests/data/test-diff-dwarf/libtest18-alias-sym-v{0,1}.so: New
	test input.
	* tests/data/test-diff-dwarf/test18-alias-sym-report-0.txt:
	Reference output for new test input.
	* tests/data/test-diff-dwarf/test18-alias-sym-v{0,1}.cc: Source
	code for new test input.
	* tests/data/test-diff-dwarf/test18-alias-sym-version-script:
	Source code for new test input.
	* tests/Makefile.am: Add the new test materials to the source
	distribution.
	* tests/test-diff-dwarf.cc(in_out_specs): Add the new input tests
	above to the array of tests to run by this harness.
	(main): Emit empty reports for empty resulting diffs.
	* tests/data/test-diff-dwarf/test{0,8,9,12,14-inline-report,}-report.txt:
	Adjust.
	* tests/data/test-diff-filter/test{0,01,2,4,5,7,8,9,10,12,13,15-0,15-1}-report.txt:
	Likewise.
	* tests/data/test-diff-filter/test{19-enum,20-inline,}-report-0.txt:
	Likewise.
	* tests/data/test-diff-suppr/test0-type-suppr-report-{1,2}.txt:
	Likewise.
	* tests/data/test-diff-suppr/test{1,2}-typedef-suppr-report-1.txt:
	Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-22 23:04:40 +02:00
Dodji Seketeli
5f26c1e459 Allow comparison of shared_ptr of things
* include/abg-diff-utils.h: Adjust copyright years.
	(deep_ptr_eq_functor::operator()(const shared_ptr<T>, const
	shared_ptr<T>)): New comparison operator.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-22 23:04:40 +02:00
Dodji Seketeli
70cb9ba1ae Yet another fix to the DWARF method "static-ness" detection heuristic
* include/abg-fwd.h (is_pointer, is_qualified_type): Declare new
	functions.
	* src/abg-ir.cc (is_pointer, is_qualified_type): Implement these
	new functions.
	* src/abg-dwarf-reader.cc (finish_member_function_reading):
	Sometimes, the this pointer of a non-static method can point to a
	*qualified* version of its containing type.  I am seeing that when
	comparing libstdc++.so from RHEL 6.5 and RHEL 7.  Take that in
	account when trying to detect that the first parameter of a member
	function is the this pointer, and thus detect that the function is
	a non static member function.
	* tests/data/test-read-dwarf/test8-qualified-this-pointer.so.abi:
	New test input.
	* tests/data/test-read-dwarf/test8-qualified-this-pointer.so: New
	test input.
	* tests/data/test-read-dwarf/test8-qualified-this-pointer.cc:
	Source code of new test input.
	* tests/test-read-dwarf.cc: Update copyright year.
	(in_out_spec): Add the new test inputs to this array, so that this
	test harness runs on them.
	* tests/Makefile.am: Add the new test inputs to the source
	distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-16 23:49:41 +02:00
Dodji Seketeli
d4445731bb Gain ability know if a diff node has local changes
* include/abg-comparison.h (diff::has_local_changes): Add new pure
	interface.
	({decl_diff_base, type_diff_base, distinct_type_diff, var_diff,
	pointer_diff, reference_diff, array_diff, qualified_type_diff,
	enum_diff, class_diff, base_diff, scope_diff, function_decl_diff,
	type_decl_diff, typedef_diff,
	translation_unit_diff}::has_local_changes): Declare the
	implementation of the pure interface above.
	* src/abg-comparison.cc ({decl_diff_base, type_diff_base,
	distinct_type_diff, var_diff, pointer_diff, reference_diff,
	array_diff, qualified_type_diff, enum_diff, class_diff, base_diff,
	scope_diff, function_decl_diff, type_decl_diff, typedef_diff,
	translation_unit_diff}::has_local_changes): Define the
	implementation of the pure interface above.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-13 17:44:44 +02:00
Dodji Seketeli
e4c21097fa Write comparison functions that hint at the kind of changes they see
* include/abg-ir.h (enum change_kind): Declare new enum.
	(operator|(change_kind, change_kind), operator&(change_kind,
	change_kind), operator|=(change_kind&, change_kind)): Declare new bit-wise
	operators for the new enum change_kind.
	(equals): Declare this new comparison function for decl_base,
	scope_decl, type_base, type_decl, scope_type_decl,
	qualified_type_def, pointer_type_def, reference_type_def,
	array_type_def, enum_type_decl, typedef_decl, var_decl,
	function_decl, function_type, class_decl, and
	class_decl::base_spec.
	(class_decl::base_spec::operator(const decl_base&)): Declare new
	equality operator.
	* src/abg-ir.cc (operator|(change_kind l, change_kind r))
	(operator&(change_kind l, change_kind r), operator|=(change_kind&
	l, change_kind r), operator&=(change_kind& l, change_kind r)):
	Define these new operators.
	(equals): Define this new comparison function for decl_base,
	scope_decl, type_base, type_decl, scope_type_decl,
	qualified_type_def, pointer_type_def, reference_type_def,
	array_type_def, enum_type_decl, typedef_decl, var_decl,
	function_decl, function_type, class_decl, and
	class_decl::base_spec.
	({decl_base, scope_decl, type_base, type_decl, scope_type_decl,
	qualified_type_def, pointer_type_def, reference_type_def,
	array_type_def, enum_type_decl, typedef_decl, var_decl,
	function_decl, function_type, class_decl,
	class_decl::base_spec}::operator==): Re-write these comparison
	operators in terms of their relevant equal() functions.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-13 17:44:44 +02:00
Dodji Seketeli
ed12dd4b6a Replace is_typedef by type_kind property in type suppressions
* doc/suppr-doc.txt: Add type_kind property "documentation" in the
	type suppression.
	* include/abg-comparison.h (type_suppression::type_kind): New
	enum.
	(type_suppression::{get_consider_typedefness,
	set_consider_typedefness, get_is_typedef, set_is_typedef}):
	Remove.
	(type_suppression::{get_consider_type_kind,
	set_consider_type_kind, get_type_kind, set_type_kind}): Declare
	new methods.
	* Include/abg-fwd.h (is_type_decl): Declare new function.
	(is_enum): Declare new overload that takes a type_base_sptr.
	* src/abg-comparison.cc
	(type_suppression::priv::{consider_typedefness_, is_typedef_}):
	Remove these data members.
	(type_suppression::priv::{consider_type_kind_, type_kind_}): New
	data members.
	(type_suppression::priv::priv): Adjust.
	(type_suppression::{get_consider_typedefness,
	set_consider_typedefness, get_is_typedef, set_is_typedef}): Remove
	these member functions.
	(type_suppression::{get_consider_type_kind,
	set_consider_type_kind, get_type_kind, set_type_kind}): Define
	these new member functions.
	(type_suppression::suppresses_diff): Adjust to consider the kind
	of types more generally than just considering typedef-ness.
	(read_type_kind_string): New static function.
	(read_type_suppression): Use the above to parse the value of the
	new type_kind property.  Adjust the creation of the resulting
	type_suppression object.
	* src/abg-ir.cc (is_type_decl): Define new function.
	* tests/data/test-diff-suppr/test1-typedef-suppr-0.suppr: Adjust.
	* tests/data/test-diff-suppr/test1-typedef-suppr-1.suppr: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-13 17:44:44 +02:00
Dodji Seketeli
feea5df3fe Initial support for type suppressions
* include/abg-comparison.h (diff_category::SUPPRESSED_CATEGORY):
	New enumerator.
	(diff_category::{SIZE_OR_OFFSET_CHANGE_CATEGORY,
	VIRTUAL_MEMBER_CHANGE_CATEGORY): Update the enumerator values for
	these.
	(diff::EVERYTHING_CATEGORY): Adjust.
	(suppression_base, type_suppression): Declare new types.
	(suppression_ptr, suppressions_type, type_suppression_sptr)
	(type_suppressions_type): New typedefs.
	(read_type_suppressions, read_suppressions): Declare new
	functions.
	(diff_context::{suppressions, add_suppression, add_suppressions}):
	Declare new methods.
	(diff::is_suppressed): Declare new member function.
	(apply_suppressions): Declare new function & overloads.
	* src/abg-comparison.cc (is_type_diff): Define new static
	function.
	({suppression_base, type_suppression}::priv): Define new types.
	({suppression_base, type_suppression}::*): Define the methods of the new
	suppression_base, type_suppressions types.
	(read_type_suppression, read_type_suppressions, read_suppressions)
	(read_type_suppressions): Define new static functions.
	(diff_context::priv::supprssions_): New data member.
	(diff_context::{suppressions, add_suppression, add_suppressions}):
	New methods.
	(diff::is_filtered_out): Consider that a diff node that is in the
	SUPPRESSED_CATEGORY is filtered out.
	(diff::is_suppressed): Define new member function.
	(operator<<(ostream& o, diff_category c)): Support the
	SUPPRESSED_CATEGORY category.
	(corpus_diff::report): Apply suppressions before reporting
	anything.
	(category_propagation_visitor::visit_end): Do not propagate
	SUPPRESSED_CATEGORY.  This is just like what we do for
	REDUNDANT_CATEGORY.
	(struct suppression_categorization_visitor): New visitor.
	(apply_suppressions): Define function & overloads.
	* include/abg-ini.h (config::section::find_property): New method.
	(config::section): Fix end of class comment.
	* src/abg-ini.cc (config::section::find_property): Define new
	method.
	* tests/data/test-diff-suppr/test0-type-suppr-{0,1,2}.suppr: New
	test input files.
	* tests/data/test-diff-suppr/test0-type-suppr-report-{0,1,2,3}.txt:
	Likewise.
	* tests/data/test-diff-suppr/test0-type-suppr-v{0,1}.o: Likewise.
	* tests/data/test-diff-suppr/test0-type-suppr-v{0,1}.cc: Source code
	for new test input.
	* tests/data/test-diff-suppr/test1-typedef-suppr-v{0,1}.o: New test
	input files.
	* tests/data/test-diff-suppr/test1-typedef-suppr.h: Source code
	for new test input files.
	* tests/data/test-diff-suppr/test1-typedef-suppr-v{0,1}.c: Likewise
	* tests/data/test-diff-suppr/test1-typedef-suppr-{0,1}.suppr: New
	test input files.
	* tests/data/test-diff-suppr/test1-typedef-suppr-report-0.txt: Likewise.
	* tests/data/test-diff-suppr/test1-typedef-suppr-report-1.txt: Likewise.
	* tests/data/test-diff-suppr/test1-typedef-suppr-report-2.txt: Likewise.
	* tests/test-diff-suppr.cc: New test harness to run type suppression tests
	using the input files above.
	* tests/data/test-diff-suppr/test3-struct-suppr-0.suppr: New test input.
	* tests/data/test-diff-suppr/test3-struct-suppr-1.suppr: Likewise.
	* tests/data/test-diff-suppr/test3-struct-suppr-report-0.txt: Likewise.
	* tests/data/test-diff-suppr/test3-struct-suppr-report-1.txt: Likewise.
	* tests/data/test-diff-suppr/test3-struct-suppr-report-2.txt: Likewise.
	* tests/data/test-diff-suppr/test3-struct-suppr-v0.cc: Likewise.
	* tests/data/test-diff-suppr/test3-struct-suppr-v0.o: Likewise.
	* tests/data/test-diff-suppr/test3-struct-suppr-v1.cc: Likewise.
	* tests/data/test-diff-suppr/test3-struct-suppr-v1.o: Likewise.
	* tests/Makefile.am: Build the new runtestdiffsuppr test harness
	from the test-diff-filter.cc file.  Add the new test files to the
	build system and source distribution.
	* tools/bidiff.cc (options::suppressions): New data member.
	(display_usage): Add a help string for the new
	--suppressions command line switch.
	(parse_command_line): Parse the --suppressions command line
	switch.
	(set_diff_context_from_opts): Read the suppressions provided by
	the --suppression command line switch and stuff them into the diff
	context.
2014-10-13 17:44:44 +02:00
Dodji Seketeli
26869d665c Make all type diff types extend new type_diff_base type
* include/abg-comparison.h (type_diff_base, decl_diff_base): New
	types.
	(type_diff_base_sptr): New typedef.
	(pointer_diff, reference_diff, array_diff, qualified_type_diff)
	(enum_diff, class_diff, type_decl_diff, typedef_diff): Make this
	extend the new type_diff_base.
	* src/abg-comparison.cc (type_diff_base::priv, type_diff_base):
	Define these new types and their methods.
	(pointer_diff::pointer_diff, array_diff::array_diff)
	(reference_diff::reference_diff)
	(qualified_type_diff::qualified_type_diff, enum_diff::enum_diff)
	(class_diff::class_diff, type_decl_diff::type_decl_diff)
	(typedef_diff::typedef_diff): Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-13 17:44:43 +02:00
Dodji Seketeli
c2ca83d62a Rename abigail::ini::config::section_vector to sections_type
* include/abg-ini.h (abigail::ini::config::sections_type): Renamed
	section_vector into this.
	(config::{get_sections, set_sections, read_sections,
	write_sections}): Adjust.
	* src/abg-ini.cc (config::priv::sections_): Adjust.
	(config::priv::priv): Likewise.
	(config::{config, get_sections}): Likewise.
	(read_sections, read_config, write_sections): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-13 17:44:43 +02:00
Dodji Seketeli
74b9337efc Implement the abigail::ini::config abstraction
* include/abg-ini.h (config::config): Add an overload that take a
	path and sections.
	(config::{get,set}_sections): New accessors.
	(read_sections): Rename the previous read_config() functions into
	these.
	(read_config): Add these function declarations to really act on
	instances of abigail::ini::config.
	(write_section): Rename the previous write_config functions into
	these.
	(write_config): Add these function declarations to really act on
	instances of abigail::ini::config.
	* src/abg-ini.cc (class config::priv): Implement this.
	(config::{config, ~config, get_path, set_path, get_sections,
	set_sections}): Define these new methods.
	(read_sections): Rename the former read_config into this.
	(read_config): Add this function definitions to really act on
	instances of abigail::ini::config.
	(write_sections): Rename the former write_config into this.
	(write_config):: Add this function definitions to really act on
	instances of abigail::ini::config.
	* tools/binilint.cc (main): Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-13 17:44:43 +02:00
Dodji Seketeli
284c9e488f Initial support of ini-style file parsing
* include/abg-ini.h: New file.
	* include/Makefile.am: Add include/abg-ini.h to the source
	distribution.
	* src/abg-ini.cc: New file.
	* src/Makefile.am: Add src/abg-ini.cc to the source distribution.
	* tools/binilint.cc: New testing tool.
	* tools/Makefile.am: Add tools/binilint.cc to the source distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-13 17:44:43 +02:00
Dodji Seketeli
fccc516656 Put IR artifacts in the abigail::ir namespace
* include/abg-fwd.h: Wrap IR artifacts into abigail::ir namespace.
	Inject that new abigail::ir namespace into the abigail namespace.
	* include/abg-ir.h: Wrap IR artifacts into abigail::ir namespace.
	(function_decl::parameter::get_type_name): Adjust the call to
	abigail::get_type_name.  It's now a call to
	abigail::ir::get_type_name.
	* src/abg-ir.cc: Wrap IR artifacts into abigail::ir namespace.
	* include/abg-traverse.h: Wrap the ir traversing artifact into the
	abigail::ir namespace too.
	* src/abg-traverse.cc: Adjust.
	* include/abg-corpus.h: Wrap corpus type stuff into abigail::ir.
	* include/abg-dwarf-reader.h: Inject namespace abigail::ir stuff
	into the abigail::dwarf_reader namespace.
	* include/abg-reader.h: Inject namespace abigail::ir stuff into
	the abigail::xml_reader namespace.
	* src/abg-reader.cc: Adjust.
	* include/abg-writer.h: Inject namespace abigail::ir stuff into
	the abigail::xml_writer namespace.
	* src/abg-writer.cc: Inject namespace abigail::ir stuff into
	abigail namespace here too.
	* src/abg-hash.cc: Inject the abigail::ir namespace into the
	abigail namespace.
	* tools/abg-tools-utils.cc: Adjust for the injection of
	abigail::function_decl. It's now abigail::ir::function_decl.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-13 17:44:43 +02:00
Dodji Seketeli
5c67f59f76 constify dm_context_rel::operator==
* include/abg-ir.h (dm_context_rel::operator==): Make this const.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-13 17:41:17 +02:00
Dodji Seketeli
2d51a6429f Remove useless redundant_filter
* include/abg-comp-filter.h (class redundant_filter): Remove this
	now useless type declaration
	* src/abg-comparison.cc (filtering::redundant_filter::visit):
	Remove this useless member function definition.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-13 17:39:26 +02:00
Dodji Seketeli
d09f4de96b Sort diff reports about function parameters by their indexes
* include/abg-comparison.h (changed_parms_type): New convenience
	typedef.
	* src/abg-comparison.cc (struct changed_parm_comp): New comparison
	functor.
	(sort_changed_parm_map): New sorting function.
	(function_decl_diff::report): Use the new sort_changed_parm_map to
	sort the diffs for function parameters by their indexes.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 17:07:16 +02:00
Dodji Seketeli
2a77bead11 Implement generic diff tree walking and port categorization over it
* include/abg-comp-filter.h (apply_filter): Declare new overload
	that takes a corpus_diff_sptr ...
	* src/abg-comp-filter.cc (apply_filter): ... and define it.  On
	the existing overload for diff_sptr, make sure to traverse all
	diff nodes, even those that have already been traversed.
	* include/abg-comparison.h (enum diff_category): Remove
	NOT_REDUNDANT_CATEGORY, add REDUNDANT_CATEGORY.
	(operator&=, +operator<<): Declare new operators for enum diff_category.
	(diff_context::{forbid_traversing_a_node_twice,
	traversing_a_node_twice_is_forbidden):
	(diff_context::categorizing_redundancy): Remove this declaration.
	(diff_context::maybe_apply_filters): Declare a new overload that
	takes a corpus_diff_sptr.  And a take a new flag that says if it
	should visit all nodes including those that have already been
	visited.
	(diff::priv_): Make this data member protected.
	(diff::{begin_traversing, is_traversing, end_traversing,
	finish_diff_type, children_nodes, append_child_node,
	get_pretty_representation, chain_into_hierarchy, traverse}):
	Declare new member functions.
	(distinct_diff::{finish_diff_type, get_pretty_representation,
	chain_into_hierarchy}): Likewise.
	(distinct_diff::traverse): Remove.
	(pointer_diff::pointer_diff): Take the underlying type diff in
	parameter.
	(pointer_diff::{finish_diff_type, get_pretty_representation,
	chain_into_hierarchy}): Declare new member functions.
	(pointer_diff::traverse): Remove.
	(reference_type_def::reference_type_def): Take the underlying type
	diff in parameter.
	({array_type_def, reference_type_def}::{finish_diff_type,
	get_pretty_representation, chain_into_hierarchy}): Declare new
	member functions.
	({array_type_diff, reference_type_def}::traverse): Remove.
	(qualified_type_diff::qualified_type_diff): Take the underlying
	type diff in parameter.
	({enum_diff, qualified_type_diff, class_diff}::{finish_diff_type,
	get_pretty_representation, chain_into_hierarchy}): Declare new
	member functions.
	({enum_diff, qualified_type_diff, class_diff}::traverse): Remove.
	(is_class_diff): Declare new function.
	(base_diff::base_diff): Take the underlying type diff in
	parameter.
	({scope_diff, base_diff}::{finish_diff_type, get_pretty_representation,
	chain_into_hierarchy}): Declare new member functions.
	({scope_diff, base_diff}::traverse): Remove.
	(function_decl_diff::function_decl_diff): Take the return type
	diff as parameter.
	({function_decl_diff, type_decl_diff}::{finish_diff_type,
	get_pretty_representation, chain_into_hierarchy}): Declare new
	member functions.
	({function_decl_diff, type_decl_diff}::traverse): Remove.
	(typedef_diff::typedef_diff): Take the underlying type diff as
	parameter.
	(typedef::{finish_diff_type, get_pretty_representation,
	chain_into_hierarchy}): Declare new member functions.
	({typedef, translation_unit_diff}::traverse): Remove member
	function.
	(corpus_diff::{finish_diff_type, children_nodes,
	append_child_node, changed_variables, get_pretty_representation,
	chain_into_hierarchy}): Declare new member functions.
	(class diff_node_visitor::{visit_begin, visit_end}): Declare new
	member functions.
	(propagate_categories, print_diff_tree, categorizing_redundancy)
	(clear_redundancy_categorization, apply_filters): New functions
	and function overloads.
	* src/abg-comparison.cc (TRY_PRE_VISIT, TRY_PRE_VISIT_CLASS_DIFF)
	(TRY_POST_VISIT, TRY_POST_VISIT_CLASS_DIFF)
	(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
	(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE)
	(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
	(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
	(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY)
	(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
	(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Remove these macros.
	Hurrah.
	(diff_context::priv::categorizing_redundancy_): Remove.
	(diff_context::priv::forbid_traversing_a_node_twice_): Add new
	data member.
	(diff_context::priv::priv): Adjust.
	(diff_context::{forbid_traversing_a_node_twice,
	traversing_a_node_twice_is_forbidden}): Define new member
	functions.
	(diff_context::maybe_apply_filters): Once filters are applied (and
	categories are set to the relevant diff tree nodes, run a pass
	over the diff tree to propagate the categories to the relevant
	diff tree parent nodes.  Add an overload for corpus_diff_sptr.
	(diff_context::categorizing_redundancy): Remove member function.
	(diff_context::maybe_apply_filters): Define a new overload for
	corpus_diff_sptr
	(struct diff::priv::{finished_, traversing_, children_,
	pretty_representation_}):  New data members.
	(diff::priv::priv): Adjust.
	(diff::{begin_traversing, is_traversing, end_traversing,
	finish_diff_type, children_nodes, append_child_node, traverse,
	set_category, get_pretty_representation, chain_into_hierarchy}):
	Define new member functions.
	(diff::is_filtered_out): Do not refer to NOT_REDUNDANT_CATEGORY
	anymore.  Rather, use the new REDUNDANT_CATEGORY.
	({distinct_diff, var_diff, pointer_diff, array_diff,
	reference_diff, qualified_type_diff, enum_diff, class_diff,
	base_diff, scope_diff, function_decl_diff, type_decl_diff,
	typedef_diff}::{get_pretty_representation, chain_into_hierarchy,
	finish_diff_type}): Define new member functions.
	({distinct_diff, var_diff, pointer_diff, array_diff,
	reference_diff, qualified_type_diff, enum_diff, class_diff,
	base_diff, scope_diff, function_decl_diff, type_decl_diff,
	typedef_diff, translation_unit_diff}::traverse): Remove member
	functions.
	(operator&=, operator<<): Define new operators for diff_category.
	({function_decl_diff, typedef_diff}::priv::priv): Add a new
	constructor.
	(pointer_diff::{priv::priv, pointer_diff})
	(reference_diff::{priv::priv, reference_diff})
	(qualified_type_diff::{priv::priv, qualified_type_diff})
	(enum_diff::{priv::priv, enum_diff}, base_diff::{priv::priv,
	base_diff}, function_decl_diff::function_decl_diff): Take the
	underlying type diff in parameter.
	(compute_diff): Adjust the pointer_diff, reference_diff,
	qualified_type_diff, base_diff, function_decl_diff overloads.
	(class_diff::priv::{count_filtered_bases,
	count_filtered_subtype_changed_dm, count_filtered_changed_dm,
	count_filtered_changed_mem_fns, count_filtered_inserted_mem_fns,
	count_filtered_deleted_mem_fns}): Adjust for the call to
	diff_context::maybe_apply_filters.
	(corpus_diff::priv::{finished_, pretty_representation_}): New data
	member.
	(corpus_diff::priv::priv): New constructor.
	(corpus_diff::priv::clear_redundancy_categorization): Define new
	member function.
	(corpus_diff::priv::apply_filters_and_compute_diff_stats):
	Adjust for call to diff_context::maybe_apply_filters.  Also, call
	clear_redundancy_categorization at the end.
	(corpus_diff::priv::categorize_redundant_changed_sub_nodes):
	Revisit logic.
	(corpus_diff::{chain_into_hierarchy, finish_diff_type,
	children_nodes, append_child_node, changed_variables,
	get_pretty_representation}): Define new member functions.
	(corpus_diff::report): Categorize redundancy for every top level
	function/variable diff.
	(corpus_diff::traverse): Adjust to the new traversing interface.
	(diff_node_visitor::{visit_begin, visit_end}): Define new member
	functions.
	(struct category_propagation_visitor, struct diff_node_printer)
	(struct redundancy_marking_visitor, struct
	redundancy_clearing_visitor): New diff tree node visitors.
	(propagate_categories, print_diff_tree, categorize_redundancy)
	(clear_redundancy_categorization, apply_filters): Define new
	functions.
	* tests/Makefile.am: Add the new tests/print-diff-tree.cc to the
	source distribution.  Build it into a tests/printdifftree binary.
	* tools/abidiff.cc (print_diff_tree): Add debugging functions to
	call from within the debugger.  By default, this function and its
	overloads are not compiled.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-10 13:18:04 +02:00
Dodji Seketeli
0161504b68 Mention virtual-ness of member function in their pretty representation
* include/abg-fwd.h (get_member_function_is_virtual): Declare new
	overload for pointers.
	* src/abg-ir.cc (get_member_function_is_virtual): Define it.
	(function_decl::get_pretty_representation): Print virtual-ness of
	the function_decl being pretty printed.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-02 12:30:54 +02:00
Dodji Seketeli
b9d97f21c3 Fixup member functions which virtual-ness has just been set
* include/abg-ir.h (fixup_virtual_member_function): Declare new
	function.
	(class_decl): Declare fixup_virtual_member_function() as a member.
	* src/abg-ir.cc (set_member_function_is_virtual): Ensure that the
	member function that has seen its virtualness set is also put
	correctly put in the vector of virtual member functions of its
	class.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-02 12:17:48 +02:00
Dodji Seketeli
cbf1debeab Fix reading several clones of the same member function from DWARF
* include/abg-fwd.h (set_member_function_is_ctor)
	(set_member_function_is_dtor, set_member_function_is_const)
	(set_member_function_vtable_offset): Declare new functions.
	* include/abg-ir.h (class_decl::sort_virtual_mem_fns): Declare new
	member function.
	(mem_fn_context_rel::{vtable_offset, is_constructor is_destructor,
	is_const}): Add these setters.
	(set_member_function_is_ctor, set_member_function_is_dtor)
	(set_member_function_is_static, set_member_function_is_const)
	(set_member_function_vtable_offset)
	(set_member_function_is_virtual): Declare these new friend
	function to class class_decl::method_decl.
	* src/abg-dwarf-reader.cc (finish_member_function_reading): Split
	this out from build_class_type_and_add_to_ir.  Use the new setters
	for member functions properties introduced above.
	(build_class_type_and_add_to_ir): Factorize the creation of member
	function by using build_ir_node_from_die.  Once that function has
	created the member function in a rather generic way, use the new
	finish_member_function_reading to set the remaining specific
	properties for member functions.
	(build_function_decl): When called to read additional properties
	of a function_decl, allow this to read and update the elf symbol
	properties too.  This is useful for building a clone of a function
	that already has an elf symbol.
	(build_ir_node_from_die):  When building a function decl, consider
	the case of a DIE that has both DW_AT_specification and
	DW_AT_abstract_origin set.  That is, DW_AT_abstract_origin is set,
	and the origin has DW_AT_specification set.  This is basically a
	clone of a function that implements an interface (this happens for
	destructors, for instance).  In this case, really do the cloning
	of the interface implementation.  If the cloned function happens
	to be member function, use finish_member_function_reading to read
	the properties relevant to its method-ness.
	* src/abg-ir.cc (set_member_function_is_ctor)
	(set_member_function_is_dtor, set_member_function_is_const)
	(set_member_function_vtable_offset)
	(class_decl::sort_virtual_mem_fns): Define new functions.
	(sort_virtual_member_functions): Define new static function.
	(struct virtual_member_function_less_than): New functor.
	(class_decl::add_member_function): Keep virtual member functions
	vector sorted.
	* data/test-read-dwarf/test1.abi: Adjust.  Now, both the
	cdtor specification and all the clones that implements the
	different are emitted.
	* data/test-read-dwarf/test2.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-10-02 10:09:23 +02:00
Dodji Seketeli
46dbc9ce41 Rename member_function_is_virtual to get_member_function_is_virtual
* include/abg-fwd.h (get_member_function_is_virtual): Renamed the
	declaration of member_function_is_virtual into this.
	* src/abg-ir.cc (get_member_function_is_virtual): Likewise for its
	definition.
	* include/abg-ir.h (class decl_base): Adjust the friend function
	member_function_is_virtual references.
	* src/abg-comp-filter.cc (has_virtual_mem_fn_change)
	(has_non_virtual_mem_fn_change): Adjust.
	* src/abg-comparison.cc (represent)
	(SKIP_MEM_FN_IF_VIRTUALITY_DISALLOWED, class_diff::report):
	Likewise.
	* src/abg-hash.cc (class_decl:#️⃣:operator()): Likewise.
	(function_decl::clone, class_decl::add_member_function): Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-30 18:16:03 +02:00
Dodji Seketeli
4e44ee383c Factorize a no-op deleter for shared pointer
* include/abg-sptr-utils.h (struct noop_deleter): Move this here
	from ...
	* src/abg-comparison.cc (struct noop_deleter): ... here.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-30 18:04:14 +02:00
Dodji Seketeli
368d192deb Pimplify abigail::comparison::diff type
* include/abg-comparison.h (diff::{priv, sptr}): New types.
	(diff::priv_): New member.
	(diff::*): Remove all the other previous data members and
	transform the inline member function definition into declarations
	only.
	* src/abg-comparison.cc (class diff::priv): New private data type.
	(diff::*): Define the previous inline member functions as
	out-of-line here.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-19 12:28:18 +02:00
Dodji Seketeli
6a3156b5d0 Rename shared_ptr<regex_t> into regex_t_sptr
* include/abg-sptr-utils.h (build_sptr()): Rename the return type
	from shared_ptr<regex_t> to regex_t_sptr.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-19 12:27:45 +02:00
Dodji Seketeli
2ed4525f93 Fix a comment in abg-comparison.h
* include/abg-comparison.h (class base_diff): Fix comment.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-19 12:26:25 +02:00
Dodji Seketeli
5bce089f23 Emit reports about not-yet categorized diff nodes
* include/abg-comparison.h (NO_CHANGE_CATEGORY): Better comment
	this enumerator.
	* src/abg-comparison.cc (diff::is_filtered_out): Not-yet
	categorized changes are not filtered out anymore.
	(distinct_diff::report): Avoid extraneous new line here.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-16 15:14:35 +02:00
Dodji Seketeli
fde3436568 Better support for inline related diffs
* include/abg-comparison.h
	(diff_category::HARMLESS_SYMBOL_ALIAS_CHANGE_CATEORY): New
	enumerator.
	(diff_category::EVERYTHING_CATEGORY): Adjust.
	* include/abg-ir.h (elf_symbol::get_aliases_id_string)
	(elf_symbol::does_alias, elf_symbols_alias)
	(compute_aliases_for_elf_symbol): Declare new functions ...
	* src/abg-ir.cc (elf_symbol::get_aliases_id_string)
	(elf_symbol::does_alias, elf_symbols_alias)
	(compute_aliases_for_elf_symbol): ... and define them.
	(function_decl::operator==): Take in account elf symbol aliases.
	* src/abg-comp-filter.cc (function_name_changed_but_not_symbol):
	Define new static functions.
	(harmless_filter::visit): Categorize function name changes that
n	doesn't impact underlying elf symbols (or the fact that two
	symbols were aliases and are not anymore) as harmless.
	* src/abg-comparison.cc (function_decl_diff::report): Properly
	report function name changes, or symbol aliases changes for that
	matter.  Also report inline-ness declaration changes.
	* src/abg-dwarf-reader.cc (die_is_declared_inline): New static
	function.
	(build_function_decl): Use the above.
	* tools/bidiff.cc (set_diff_context_from_opts): Add
	abigail::comparison::HARMLESS_SYMBOL_ALIAS_CHANGE_CATEORY into the
	harmless change camp.
	* tests/data/test-diff-dwarf/test14-inline-report.txt: New test
	input.
	* tests/data/test-diff-dwarf/test14-inline-v0.o: Likewise.
	* tests/data/test-diff-dwarf/test14-inline-v1.o: Likewise.
	* tests/data/test-diff-dwarf/test14-inline-v0.cc: Source code for
	test input.
	* tests/data/test-diff-dwarf/test14-inline-v1.cc: Source code for
	test input.
	* tests/test-diff-dwarf.cc: Run this test harness over the new
	input above.
	* tests/data/test-diff-filter/test20-inline-report-0.txt: Likewise.
	* tests/data/test-diff-filter/test20-inline-report-1.txt:
	Likewise.
	* tests/data/test-diff-filter/test20-inline-v0.o: New test input.
	* tests/data/test-diff-filter/test20-inline-v1.o: New test input.
	* tests/data/test-diff-filter/test20-inline-v0.cc: Source code for
	test input.
	* tests/data/test-diff-filter/test20-inline-v1.cc: Likewise.
	* tests/test-diff-filter.cc: Run this test harness over the new
	input above.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-16 15:10:41 +02:00
Dodji Seketeli
ba487a2cd9 Better support for enum diffs
* include/abg-comparison.h (changed_enumerator_type): New typedef.
	(diff_category::{HARMLESS_ENUM_CHANGE_CATEGORY}): New enumerator.
	* src/abg-comp-filter.cc (has_type_size_change)
	(has_enumerator_insertion, has_enumerator_removal_or_change)
	(has_harmful_enum_change): New functions.
	(harmless_filter::visit): Categorize enumerator insertions that
	don't change the size of the type into HARMLESS_ENUM_CHANGE_CATEGORY.
	(harmful_filter::visit): Categorize enumerator removal or any enum
	change that changes the size of the type into
	SIZE_OR_OFFSET_CHANGE_CATEGORY.
	* src/abg-comparison.cc (enumerator_value_comp)
	(changed_enumerator_comp): New types.
	(sort_enumerators, sort_changed_enumerators): New static
	functions.
	(enum_diff::report): Sort enum related reports by the value of the
	enumerators.
	* src/abg-dwarf-reader.cc (build_enum_type): Name anonymous enums
	as __anonymous_enum__.
 	* tools/bidiff.cc (set_diff_context_from_opts): Add
	abigail::comparison::HARMLESS_ENUM_CHANGE_CATEGORY into the harmless
	stuff camp.
	* tests/data/test-diff-dwarf/test15-enum-report.txt: New test
	input.
	* tests/data/test-diff-dwarf/test15-enum-v1.o: Likewise.
	* tests/data/test-diff-dwarf/test15-enum-v0.o: Likewise.
	* tests/data/test-diff-dwarf/test15-enum-v0.cc: Source code for
	test input.
	* tests/data/test-diff-dwarf/test15-enum-v1.cc: Likewise.

	* tests/data/test-diff-filter/test19-enum-report-0.txt: New test input.
	* tests/data/test-diff-filter/test19-enum-report-1.txt: Likewise.
	* tests/data/test-diff-filter/test19-enum-v0.o: Likewise.
	* tests/data/test-diff-filter/test19-enum-v1.o: Likewise.
	* tests/data/test-diff-filter/test19-enum-v0.cc: Source code for
	test input.
	* tests/data/test-diff-filter/test19-enum-v1.cc: Likewise.
	* tests/test-diff-dwarf.cc: Run this test harness on the new test
	inputs above.
	* tests/test-diff-filter.cc: Likewise.
	* tests/Makefile.am: Add the new files above to the source distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-16 14:02:27 +02:00
Dodji Seketeli
41cfd5a82b Add constness to elf_symbol::operator==
* include/abg-ir.h (elf_symbol::operator==): Add a const to the
	declaration ...
	* src/abg-ir.cc (elf_symbol::operator==): ... and to the definition.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-16 11:21:47 +02:00
Jan Engelhardt
1708e39fe7 Replace indirect variable assignments
* configure.ac(DEVEL_CFLAGS, DEVEL_CXXFLAGS):  Remove these
	useless variables.
	(CFLAGS, CXXFLAGS): Set these variables directly.
	* include/Makefile.am (pkginclude_HEADERS): Use this predefined
	variable.
	(publicheaders_DATA, publicheadersdir): Remove these.

Signed-off-by: Jan Engelhardt <jengelh@inai.de>
2014-09-12 11:04:54 +02:00
Dodji Seketeli
5f9a3bf4dd Fix memory leaks due to cycles in types ownership
* include/abg-fwd.h (std::tr1::weak_ptr): Inject this type in the
	abigail namespace.
	* include/abg-ir.h: Write a memory management guideline for the IR
	artifacts.
	(Type_base_wptr, function_type_wptr)
	(class_decl_wptr): New typedefs.
	(translation_unit::get_canonical_function_type): Declare new
	member function.
	(qualified_type_def::underlying_type_)
	(reference_type_def::pointed_to_type_)
	(typedef_decl::underlying_type_, function_decl::parameter::type_)
	(function_type::return_type_, method_type::class_type_)
	(non_type_tparameter::type_, type_composition::type_): Make this a
	weak pointer.
	(qualified_type_def::get_pointed_to_type)
	(reference_type_def::get_pointed_to_type)
	(array_type::get_element_type, typedef_decl::get_underlying_type)
	(var_decl::get_type, function_decl::parameter::get_type)
	(function_type::get_return_type, method_type::get_class_type)
	(non_type_tparameter::get_type)
	(type_composition::get_composed_type): Adjust to make this return
	a shared pointer initialized with the content of the weak pointer.
	(function_decl::function_decl, method_decl::method_decl): Remove
	the overload that doesn't take a type.  This is because now,
	function types need to be registered to their containing
	translation unit.
	(struct function_type::hash): Declare here.
	* src/abg-hash.cc (struct function_type::hash): Declare this in
	abg-ir.h and just define the methods here.
	* src/abg-ir.cc (fn_type_ptr_map): New typedef.
	(translation_unit::priv::canonical_types_): Remove this unused
	member.
	(translation_unit::priv::canonical_function_types_): New member.
	(translation_unit::get_canonical_function_type): Define this
	function.
	(array_type_def::priv::element_type_, var_decl::priv::type_)
	(function_decl::priv::type_): Make this a weak pointer.
	(qualified_type_def::get_underlying_type)
	(pointer_type_def::get_pointed_to_type)
	(reference_type_def::get_pointed_to_type)
	(array_type_def::get_element_type)
	(typedef_decl::get_underlying_type, var_decl::get_type)
	(function_decl::get_type): Adjust to make this return a shared
	pointer initialized with the content of the weak pointer.
	(qualified_type_def::build_name)
	(pointer_type_def::get_qualified_name)
	(reference_type_def::get_qualified_name): Adjust.
	(method_type::set_class_type): Cleanup the logic.
	(function_decl::priv::priv): Remove the overload that takes a bare
	pointer to a type.  This should not be used now that we need the
	function type to registered with the translation unit.
	(function_decl::function_decl): Remove the overload that doesn't
	take a type.  This is because now, function types need to be
	registered to their containing translation unit.
	* src/abg-dwarf-reader.cc (build_function_decl): Register the
	function type within its translation type and use its canonical
	version.  This complies with the new memory management rules.
	* src/abg-reader.cc (build_function_decl): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-10 18:08:41 +02:00
Dodji Seketeli
a2f1adb617 Update copyright notice
* include/abg-ir.h: Update year of copyright notice.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-10 17:19:36 +02:00
Dodji Seketeli
d38b2216a4 Sort reported changed data members by increasing offset
* include/abg-comparison.h (changed_type_or_decl_vector): New
	typedef.
	* include/abg-fwd.h (is_data_member): Change the overload that
	takes a decl_base_sptr to make it return the real var_decl_sptr
	rather than just a bool.
	* src/abg-comparison.cc (ChangedDataMemberComp, DataMemberComp):
	New comparison functors.
	(sort_changed_data_members, sort_data_members): Sorting functions
	for changed data members and data members.
	(class_diff::report): Sort reports for deleted, inserted and
	change data members by the increasing value of the offsets of said
	data members.
	* src/abg-ir.cc (is_data_member): Change the overload that takes a
	decl_base_sptr to make it return the real var_decl_sptr rather
	than just a bool.
	* tests/data/test-bidiff/test-struct1-report.txt: Adjust.
	* tests/data/test-diff-dwarf/test13-report.txt: New test input.
	* tests/data/test-diff-dwarf/test13-v0.cc: Source code for new
	test input.
	* tests/data/test-diff-dwarf/test13-v0.o: New test input.
	* tests/data/test-diff-dwarf/test13-v1.cc: Source code for new
	test input.
	* tests/data/test-diff-dwarf/test13-v1.o: New test input.
	* tests/Makefile.am: Add the new test inputs above to the source
	distribution.
	* tests/test-diff-dwarf.cc: Run this test harness on the new test
	input.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-09-03 09:59:03 +02:00
Dodji Seketeli
30b7fb8e5a During comparison use symbol name + version as decl ID
* include/abg-ir.h ({var,function}_decl::get_id): New member
	function declarations.
	* src/abg-ir.cc ({var,function}_decl::get_id): New member function
	definitions.
	* src/abg-comparison.cc
	(corpus_diff::priv::ensure_lookup_tables_populated): Use the
	::get_id() function to get an identifier for the function or
	variable.
	* src/abg-corpus.cc (symtab_build_visitor_type::build_id): Use the
	get_id of the function/variable.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-08-26 14:37:14 +02:00
Dodji Seketeli
b13345fd86 Take symbol versions in account when computing added/removed decls
* include/abg-corpus.h
	(corpus::lookup_{function,variable}_symbol): Add an overload
	declaration that takes the version of the symbol to lookup.
	* src/abg-comparison.cc
	(corpus_diff::priv::ensure_lookup_tables_populated): So when looking
	up the corpora for symbols, take their versions in account.
	* src/abg-corpus.cc (corpus::lookup_{function,variable}_symbol):
	Add an overload definition that takes the version of the symbol to
	lookup.
	(symtab_build_visitor_type::build_id): New
	member functions.
	(corpus::priv::build_public_decl_table): Use the new member
	functions above.
	* src/abg-ir.cc (elf_symbol::version::operator==): Do not take the
	is_default flag in account when comparing two symbol versions.
	* libtest12-v{0,1}.so: New test input files.
	* libtest12-v{0,1}.c: Source code for the test input files.
	* test12-version-script: Version script to build the files above.
	* test12-report.txt: Test input file.
	* tests/Makefile.am: Add the new test input files above to the
	source distribution.
	* tests/test-diff-dwarf.cc (in_out_specs[]): Add an entry to this
	table for the new test input files.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-08-25 23:16:50 +02:00
Dodji Seketeli
5c493339c6 Misc style cleanups
* include/abg-corpus.h (corpus::lookup_function_symbol)
	(corpus::lookup_variable_symbol): Add the name of the function
	parameter in the declaration.
	* include/abg-ir.h (elf_symbol::version::version): Properly indent
	this constructor declaration.
	* src/abg-corpus.cc
	(symtab_build_visitor_type::symtab_build_visitor_type): Properly
	indent constructor parameters.
	* src/abg-ir.cc (function_decl::operator==): Fix typo in
	comments.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-08-25 23:04:53 +02:00
Dodji Seketeli
b6d7fcc515 A builtin type name change is not harmless - fix that
* include/abg-comp-filter.h (has_harmless_name_change): New
	function declaration.
	* include/abg-comparison.h
	(diff_category::DECL_NAME_CHANGE_CATEGORY): Renamed this into
	HARMLESS_DECL_NAME_CHANGE_CATEGORY.
	(diff_category::EVERYTHING_CATEGORY): Update.
	* include/abg-fwd.h (is_enum): New function declaration.
	(is_var_decl): Return the shared_ptr<var_decl> rather than a bool.
	(is_data_member): New overload that takes a shared_ptr<decl_base>.
	* src/abg-comp-filter.cc (decl_name_changed): Consider the
	qualified name here.
	(has_harmless_name_change): Define new function declaration.
	(harmless_filter::visit): Use the new has_harmless_name_change
	function.
	* src/abg-comparison.cc (represent)
	(report_name_size_and_alignment_changes, enum_diff::report)
	(typedef_diff::report, is_data_member): Use the new
	filtering::has_harmless_name_change function to simplify logic of
	emitting the name change related diff
	* tools/bidiff.cc (set_diff_context_from_opts): Adjust
	DECL_NAME_CHANGE_CATEGORY -> HARMLESS_DECL_NAME_CHANGE_CATEGORY.
	* src/abg-ir.cc (is_data_member, is_enum): New function definitions.
	(is_var_decl): Return the var_decl_sptr rather than just a bool.
	* tests/data/test-diff-filter/test13-report.txt: Adjust.
	* tests/data/test-diff-filter/test6-report.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-08-22 17:19:27 +02:00
Ondrej Oprala
055a789abe Support C and C++ array type.
* include/abg-comparison.h (array_diff): Declare new class.
	(array_diff_sptr): Shared pointer to type array_diff.
	(compute_diff): Overload the function to take type
	array_diff_sptr as the first two arguments.
	* include/abg-fwd.h (array_type_def): Declare new class.
	(subrange_type): Likewise.
	(is_array_def): Declare new function.
	* include/abg-ir.h (array_type_def_sptr): Shared pointer
	to type array_type_def.
	(array_type_def): Declare new class.
	(ir_node_visitor::visit): Declare a new virtual function
	taking a pointer to type array_type_def as an argument.
	* src/abg-comparison.cc (compute_diff_for_types): Add
	try_to_diff for two instances of type array_type_def.
	(array_diff::priv): declare struct for holding private members
	of type array_diff.
	(array_diff::array_diff): Define constructor.
	(array_diff::{first,second}_array):Define new
	member functions.
	(array_diff::element_type_diff): Likewise.
	(array_diff::{length,report,traverse}): Likewise.
	(compute_diff): Define function overloaded in
	include/abg-comparison.h.
	* src/abg-dwarf-reader.cc (build_array_type): Define new
	function. Handle DW_TAG_array_type and DW_TAG_subrange type.
	(build_ir_node_from_die): Amend case DW_TAG_array_type with
	a call to build_array_type.
	* src/abg-hash.cc (array_type_def::hash): Declare new struct.
	(type_base::dynamic_hash::operator()): Attempt to dynamic_cast
	the argument to type array_type_def as well.
	(array_type_def::hash): Declare new struct.
	* src/abg-ir.cc (array_type_def::array_type_def): Define
	constructors.
	(array_type_def::priv): declare struct for holding private members
	of type array_type_def.
	(array_type_def::operator==(const decl_base&):
	Define new operator.
	(array_type_def::operator==(const type_base&):
	Likewise.
	(array_type_def::append_subrange{,s}): Define
	new functions.
	(array_type_def::{set,get}_size_in_bits): Likewise.
	(array_type_def::get_dimension_count): Likewise.
	(array_type_def::get_qualified_name): Likewise.
	(array_type_def::get_pretty_representation): Likewise.
	(array_type_def::get_subrange_representation): Likewise.
	(array_type_def::traverse): Likewise.
	(array_type_def::get_{element_type,location,subranges}): Likewise.
	(array_type_def::is_infinite): Likewise.
	(array_type_def::~array_type_def): Define destructor.
	(ir_node_visitor::visit): Define function, taking
	pointer to array_type_def as an argument.
	* src/abg-reader.cc (map_id_and_node): Check if node
	is an array.
	(is_array_def): Check if object is an array.
	(handle_element_node): Handle array_type_def as well.
	(build_subrange_type): Define new function.
	(build_array_type_def): Likewise.
	(build_type): Build type array_type_def as well.
	(build_type_composition): Likewise.
	(handle_array_type_def): Define new function.
	* src/abg-writer.cc: (write_decl): Output arrays
	as well.
	(write_member_type): Likewise.
	(write_type_composition): Likewise.
	(write_array_type_def): Define new function.
	* tests/data/test-diff-dwarf/test{10,11}-v{0,1}.{cc,o}: New test source
	files
	* tests/data/test-diff-dwarf/test{10,11}-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test10-report.txt: New test input.
	* tests/data/test-read-dwarf/test7.cc: New test source
	file.
	* tests/data/test-read-dwarf/test7.so: New input binary
	to read.
	* tests/data/test-read-dwarf/test7.so.abi: New reference
	test to compare against.
	* tests/data/test-read-write/test25.xml: New test source
	file.
	* tests/test-diff-dwarf.cc: Adjust to launch the new test.
	* tests/test-read-dwarf.cc: Likewise.
	* tests/test-read-write.cc: Likewise.
	* test/Makefile.am: Add the new test inputs to the source
	distribution.

Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-08-22 13:07:41 +02:00
Dodji Seketeli
7b126c03a0 Support alternate debug info sections
ABGBZ#17193
	* include/abg-dwarf-reader.h (class read_context)
	(typedef read_context_sptr, create_read_context)
	(has_alt_debug_info): Declare these.
	(read_corpus_from_elf): Declare new overload.
	* src/abg-dwarf-reader.cc (find_alt_debug_info)
	(is_die_attribute_resolved_through_gnu_ref_alt)
	(build_primary_die_parent_relations_under)
	(build_alternate_die_parent_relations_under):
	Define new static functions.
	(read_context::{alt_dwarf_,
	alt_debug_info_path_, alternate_die_decl_map_,
	alternate_die_parent_map_}): New data members.
	(read_context::{alt_dwarf, alt_debug_info_path,
	alternate_die_decl_map, associate_die_to_decl_primary,
	associate_die_to_decl_alternate, associate_die_to_decl,
	lookup_decl_from_die_offset_primary,
	lookup_decl_from_die_offset_alternate,
	lookup_decl_from_die_offset, alternate_die_parent_map}): New
	member functions.
	(read_context::load_debug_info): Painfully Get a handle on the
	alternate debug info section too.  We shouldn't have to do all
	this work; we could use the new dwarf_getalt() function from
	libdw, but we cannot as we want to support supports that predate
	that api.  When a version of elfutils gets released with that api
	though, we should conditionally use that instead.
	(build_ir_node_from_die, get_parent_die, get_scope_for_die)
	(build_namespace_decl_and_add_to_ir)
	(build_class_type_and_add_to_ir, build_qualified_type)
	(build_pointer_type_def, build_reference_type, build_typedef_type)
	(build_var_decl, build_function_decl): Take a new parameter that
	tells if the input DIE is from alternate debug info.  Adjust their
	code accordingly.
	(die_die_attribute): Take a new output parameter that tells if the
	resolved DIE is from alternate debug info.  Also take a new
	parameter that tells if the input DIE is from alternate debug info
	sections.
	(build_die_parent_relations_under): Take the DIE -> parent map to
	act upon.  Also, add a new overload that takes a flag saying if
	the DIE is from alternate debug info or not, and act upon that.
	(build_die_parent_maps): Renamed build_die_parent_map into this
	and make it build DIE -> parent DIE relationship for the alternate
	debug info file as well.
	(find_last_import_unit_point_before_die, ): Adjust to use the
	information about if the relevant DIEs are in alternate debug info
	or not.
	(build_translation_unit_and_add_to_ir): Clear the alternate DIE ->
	decl map, that is per TU just as the primary DIE -> decl map.
	Adjust to use the information about if the relevant DIEs are in
	alternate debug info or not.
	(read_debug_info_into_corpus): Build the two DIE -> DIE parent
	maps (one for the primary debug info and one for the alternate
	debug info).
	(create_read_context, has_alt_debug_info): Define new public entry
	points.
	(read_corpus_from_elf): New entry point overload that takes a
	read_context.
	* tools/bidw.cc (options::{check_alt_debug_info_path,
	show_base_name_alt_debug_info_path}): New data members.
	(display_usage): Update for the two new options
	--check-alternate-debug-info and
	check-alternate-debug-info-base-name.
	(parse_command_line): Parse the two options above.
	(main) Handle the two new options above.
	* tests/Makefile.am: Build the new runtestaltdwarf test.  Add the
	new data/test-alt-dwarf-file/* files to the build system.
	* tests/test-alt-dwarf-file.cc: New test driver.
	* tests/data/test-alt-dwarf-file/test0-common.cc: New test input
	files.
	* tests/data/test-alt-dwarf-file/libtest0-common.so: Likewise.
	* tests/data/test-alt-dwarf-file/test0.cc: Likewise.
	* tests/data/test-alt-dwarf-file/libtest0.so: Likewise.
	* tests/data/test-alt-dwarf-file/test0.h: Likewise.
	* tests/data/test-alt-dwarf-file/test0-common-dwz.debug: Likewise.
	* tests/data/test-alt-dwarf-file/test0-debug-dir/.build-id/16/7088580c513b439c9ed95fe6a8b29496495f26.debug:
	Likewise.
	* tests/data/test-alt-dwarf-file/test0-debug-dir/test0-common-dwz.debug:
	Likewise.
	* tests/data/test-read-dwarf/test1.abi: Adjust. bidw doesn't emit
	an abstract constructor/destructor anymore. It emits just the
	functions matching the cdtor symbols found in the binary.
	* tests/data/test-read-dwarf/test2.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-08-15 18:27:04 +02:00
Dodji Seketeli
01cd814bbc Support reading void* type from DWARF
* include/abg-ir.h (type_decl::get_void_type_decl): Declare new
	static method.
	* src/abg-ir.cc (type_decl::get_void_type_decl): Define it.
	* src/abg-dwarf-reader.cc (build_ir_node_for_void_type): Define
	new static function.
	(build_pointer_type_def): Support void* type nodes here.
	* tests/data/test-read-dwarf/test5.cc: Source code for new test
	input.
	* tests/data/test-read-dwarf/test5.o: New test input.
	* tests/data/test-read-dwarf/test5.o.abi: Likewise.
	* tests/Makefile.am: Add the above to the source distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-06-23 17:31:26 +02:00
Dodji Seketeli
591014bf40 Avoid reporting diff nodes that have already been reported
* include/abg-comp-filter.h (class harmful_filter): Update
	comment.
	(class redundant_filter): Declare new filter.
	* include/abg-comparison.h (enum
	diff_category::NOT_REDUNDANT_CATEGORY): New category.  Update the
	values of the other enumerators.
	(diff_context::{add_diff, diff_has_been_traversed}): New overloads.
	(diff_context::{categorizing_redundancy, show_redundant_changes}):
	Declare new methods.
	(diff_context::remove_from_category): Define new inline method.
	* src/abg-comparison.cc (noop_deleter::operator()): Constify the
	parameter.
	(CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE)
	(UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE): New macros.
	(TRAVERSE_DIFF_NODE_AND_PROPAGATE_CATEGORY)
	(TRAVERSE_MEM_DIFF_NODE_AND_PROPAGATE_CATEGORY)
	(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY): Use the new
	CATEGORIZE_REDUNDANCY_FROM_CHILD_NODE and
	UPDATE_REDUNDANCY_CATEGORIZATION_FROM_NODE_SUBTREE macros above.
	(ENSURE_DIFF_NODE_TRAVERSED_ONCE)
	(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): If the (type_decl or class)
	node hasn't been yet traversed, mark it as non-redundant.
	(diff_context::priv::categorizing_redundancy): New member.
	(diff_context::priv::priv): Initialize it.
	(diff_context::{add_diff, diff_has_been_traversed): Define new
	overloads.
	(diff_context::mark_diff_as_traversed): Intern a diff node that is
	marked as being traversed.
	(diff_context::{categorizing_redundancy, show_redundant_changes}):
	Define new methods.
	(diff::is_filtered_out): A redundant function or top-level
	variable is considered filtered-out.  Otherwise, the new
	NOT_REDUNDANT_CATEGORY doesn't play any role when comparing
	allowed categories with the set of categories a diff node belongs
	to.
	(corpus::priv::categorize_redundant_changed_sub_nodes): Define
	new member function.
	(corpus_diff::priv::apply_filters_and_compute_diff_stats): Change
	this to first walk the changed functions and variables to apply
	filters, then categorize redundant changed functions, and then
	walk the changed functions and variables again to count
	filtered-out diff nodes.
	(filtering::redundant_filter::visit): Define new member function.
	* tools/bidiff.cc (options::show_redundant_changes): New data
	member.
	(options::options): Initialize it.
	(display_usage): Add help string for the --redundant command line
	option.
	(parse_command_line): Add support for the --redundant command line
	option.
	(set_diff_context_from_opts): Take the --redundant command line
	option in account.
	* tests/test-diff-filter.cc: Update this to add new test inputs.
	* tests/data/test-diff-filter/test14-0-report.txt: New test input.
	* tests/data/test-diff-filter/test14-1-report.txt: Likewise.
	* tests/data/test-diff-filter/test14-v0.cc: Likewise.
	* tests/data/test-diff-filter/test14-v0.o: Likewise.
	* tests/data/test-diff-filter/test14-v1.cc: Likewise.
	* tests/data/test-diff-filter/test14-v1.o: Likewise.
	* tests/data/test-diff-filter/test15-0-report.txt: Likewise.
	* tests/data/test-diff-filter/test15-1-report.txt: Likewise.
	* tests/data/test-diff-filter/test15-v0.cc: Likewise.
	* tests/data/test-diff-filter/test15-v0.o: Likewise.
	* tests/data/test-diff-filter/test15-v1.cc: Likewise.
	* tests/data/test-diff-filter/test15-v1.o: Likewise.
	* tests/Makefile.am: Add the above to the build system.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-06-23 13:43:42 +02:00
Dodji Seketeli
f3f2382396 Update copyright notice for a bunch of files
* include/abg-comp-filter.h: Update copyright notice.
	* include/abg-comparison.h: Likewise.
	* src/abg-comparison.cc: Likewise.
	* src/abg-ir.cc: Likewise.
	* tools/bidiff.cc: Likewise.
	* tests/test-diff-filter.cc: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-06-23 13:43:07 +02:00
Dodji Seketeli
c4e7f9792d Harden debug info path management & better error reporting
* include/abg-dwarf-reader.h (enum status): New enum.
	(read_corpus_from_elf): Return an instance of status above, and
	return the corpus by parameter.
	* src/abg-dwarf-reader.cc (create_default_dwfl): Add a comment
	about elfutils wanting the Dwfl_Callbacks::debuginfo_path to be an
	absolute path.
	(read_corpus_from_elf): Return an instance of status above, and
	return the corpus by parameter.
	* tools/abg-tools-utils.h (make_path_absolute): Declare new function.
	* tools/abg-tools-utils.cc (make_path_absolute): New
	implementation.
	* tools/bidiff.cc (options::di_root_path[12]): Make these be
	shared pointers.
	(parse_command_line): ensure the debug info root paths are
	absolute.
	(main): Adjust.  Give meaningful errors when the debug info or
	symbol files couldn't be read.
	* tools/bidw.cc (options::di_root_path): Make this be a shared
	pointer.
	(parse_command_line): Ensure the debug info root path is absolute.
	(main): Adjust.  Give meaningful errors when the debug info or
	symbol files couldn't be read.
	* tools/bilint.cc (options::di_root_path): Make this be a shared
	pointer.
	(parse_command_line): Ensure the debug info root path is absolute.
	(main): Adjust.  Give meaningful errors when the debug info or
	symbol file couldn't be read.
	* tests/test-diff-dwarf.cc (main): Adjust.
	* tests/test-read-dwarf.cc (main): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-06-04 16:30:18 +02:00
Dodji Seketeli
76bfae5aac Ensure added/removed member functions have their symbols added/removed
* include/abg-comparison.h (diff_context::{set_corpora,
	get_first_corpus, get_second_corpus}): Declare new member
	functions.
	* src/abg-comparison.cc (diff_context::{set_corpora,
	get_first_corpus, get_second_corpus}): Define them.
	(compute_diff): In the overload for corpus_sptr stick the corpora
	being compared, into the diff context.
	(class_diff::ensure_lookup_tables_populated): If a member function
	is allegedly removed, check that its underlying symbol is removed
	from the corpus as well.  Otherwise, consider that the member
	function hasn't been removed.  Likewise, if a member function is
	allegedly added, check that its underlying symbol has been added
	to the corpus as well.  Otherwise, consider that the member
	function hasn't been added.  The symbols can now be accessed
	through the two corpora that are now present in the diff context.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-29 18:15:48 +02:00
Dodji Seketeli
e2d450176b Add a symbol database to the ABI Corpus & support symbol aliases
* include/abg-corpus.h (corpus::{g,s}et_{fun,var}_symbol_map{_sptr}):
	Declare new accessors.
	(corpus::lookup_{variable,function}_symbol): Declare new member
	functions.
	* src/abg-corpus.cc (corpus::{g,s}et_{fun,var}_symbol_map{_sptr}):
	Define new accessors.
	(corpus::lookup_{variable,function}_symbol): Define new member
	functions.
	* include/abg-ir.h (string_elf_symbol_sptr_map_type)
	(string_elf_symbol_sptr_map_sptr, elf_symbols)
	(string_elf_symbols_map_type, string_elf_symbols_map_sptr): New
	convenience typedefs.
	(elf_symbol::{get_main_symbol, is_main_symbol, get_next_alias,
	has_aliases, add_alias, get_id_string,
	get_name_and_version_from_id, operator=}): Declare new member
	functions.
	* src/abg-ir.cc (elf_symbol::{get_main_symbol, is_main_symbol,
	get_next_alias, has_aliases, add_alias, get_id_string,
	get_name_and_version_from_id, operator=}): Define new member
	functions.
	* include/abg-reader.h (read_corpus_from_file): Take a shared
	pointer to corpus.
	* src/abg-reader.cc (read_context::{g,s}et_corpus): Define these.
	(build_elf_symbol_db, build_elf_symbol_from_reference)
	(read_symbol_db_from_input): Define new functions.
	(read_corpus_from_input): Adjust.  Make it read symbol databases.
	(build_elf_symbol): Harden this.
	(build_{var,function}_decl): Read the symbol reference.  Do not
	read the local symbol serialization anymore.
	(read_corpus_from_archive): Adjust.
	(read_corpus_from_file): Take a reference to a shared pointer to
	corpus, rather than a reference to the corpus.
	(read_corpus_from_native_xml): Only keep the overload that returns
	a corpus.  Set the current context with the corpus.
	* src/abg-dwarf-reader.cc (addr_elf_symbol_sptr_map_type)
	(addr_elf_symbol_sptr_map_sptr): New convenience typedefs.
	(read_context::{fun_sym_addr_sym_index_map_,
	var_sym_addr_sym_index_map_): Remove.
	(read_context::{fun,var}_addr_sym_map_): New.  Replace the above
	that got removed.
	(read_context::{var,fun}_syms_): New.
	(read_context::lookup_elf_{fn,var}_symbol_from_address): Adjust.
	(read_context::{fun,var}_addr_sym_map{_sptr}): New.
	(read_context::{fun,var}_syms{_sptr}): New.
	(read_context::load_symbol_maps): Replace
	read_context::load_symbol_addr_to_index_maps.  Adjust to load all
	the new maps.
	(read_context::maybe_load_symbol_maps): New.
	(read_debug_info_into_corpus): Renamed build_corpus into this.
	Update to load symbol maps and set it to the corpus.
	* src/abg-writer.cc (write_context::get_fun_symbol_map): New
	accessor.
	(write_elf_symbol_aliases, write_elf_symbol_reference)
	(write_elf_symbols_table): Define new static functions.
	(write_var_decl): Write the reference to the underlying symbol of
	the variable.  Do not write the full symbol here anymore.
	(write_function_decl):  Likewise, write the reference to the
	underlying symbol of the function.  Do not write the full symbol
	here anymore.
	(write_corpus_to_native_xml): Write the symbol databases at the
	beginning of the corpus document.
	* src/abg-comparison.cc
	(corpus_diff::priv::ensure_lookup_tables_populated): Now that the
	corpus has symbols, check if a the symbol of an allegedly deleted
	function (resp. variable) is deleted; if not, then do not report
	the function (resp. variable) as deleted.  Similarly, check if the
	symbol of an allegedly added function (resp. variable) is added.
	if not, the do not report the function (resp. variable) as added.
	* tests/test-write-read-archive.cc (main): Adjust.
	* tools/biar.cc (extract_tus_from_archive): Likewise.
	* tests/data/test-diff-filter/test9-report.txt: Adjust.
	* tests/data/test-read-dwarf/test0.abi: Likewise.
	* tests/data/test-read-dwarf/test1.abi: Likewise.
	* tests/data/test-read-dwarf/test2.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-28 16:33:35 +02:00
Dodji Seketeli
cf80e9d378 Support debug info files being outside the expected system directories
* include/abg-dwarf-reader.h (read_corpus_from_elf): Take a
	debug_info_root_path parameter.
	src/abg-dwarf-reader.cc (create_default_dwfl): Take a
	debug_info_root_path.  Use that to initialize the Dwfl_Callbacks
	structure used by dwfl_begin.
	(create_default_dwfl_sptr, read_corpus_from_elf): Likewise, Take a
	debug_info_root_path parameter.
	* tests/test-diff-dwarf.cc (main): Adjust.
	* tests/test-read-dwarf.cc (main): Likewise.
	* tools/bidiff.cc (options::dir_root_path[12]): New member.
	(options::options): Initialize it.
	(display_usage): Add help string for the --debug-info-dir[12]
	options.
	(parse_command_line): Handle the new --debug-info-dir[12] options.
	(main): Pass the debug info directories to read_corpus_from_elf.
	* bidw.cc (options::::di_root_path): New member.
	(options::options): Initialize it.
	(display_usage): Add help string for the new --debug-info-dir
	option.
	(parse_command_line): Handle the new --debug-info-dir.
	(main): Pass the debug info root path to read_corpus_from_elf.
	* tools/bilint.cc (options::di_root_path): New member.
	(options::options): Initialize it.
	(display_usage): Add help string for the new --debug-info-dir.
	(parse_command_line): Handle --debug-info-dir command line option.
	(main): Pass the debug info root path to read_corpus_from_elf.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-22 13:14:44 +02:00
Dodji Seketeli
4d0de72a85 Support decl cloning when seeing DW_AT_abstract_origin
* include/abg-ir.h ({var,function}_decl::clone): New method.
	* src/abg-dwarf-reader.cc (die_die_attribute): Add a flag to avoid
	looking through DW_AT_abstract_origin attribute here.
	(build_function_decl): Set the linkage name from
	DW_AT_linkage_name if it's not set yet.
	(build_ir_node_from_die): For DW_TAG_{variable,subprogram}, when
	we see DW_AT_abstract_origin, clone the decl they refer to.
	Also, avoid dropping the DIE on the floor just because it doesn't
	have die_is_artificial here.
	* src/abg-ir.cc ({var,function}_decl::clone): Implement this.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-20 18:22:14 +02:00
Dodji Seketeli
335d8786b2 Serialize and de-serialize elf symbols for var & function decls
* abg-ir.h (string_to_elf_symbol_type, string_to_elf_symbol_binding):
	Declare new entry points.
	* src/abg-ir.cc (string_to_elf_symbol_type)
	(string_to_elf_symbol_binding): Define new entry points.
	* include/abg-libxml-utils.h (xml_char_sptr_to_string): Declare
	new entry points.
	* src/abg-libxml-utils.cc (xml_char_sptr_to_string): Define new
	entry points.
	* src/abg-reader.cc (read_elf_symbol_type)
	(read_elf_symbol_binding, build_elf_symbol): Define new static
	functions.
	(build_function_decl, build_var_decl): Use the new
	build_elf_symbol and set the symbol to the function.  Flag the
	function as having a public symbol in the symbol table if the
	symbol is public.
	* src/abg-writer.cc (write_elf_symbol_type)
	(write_elf_symbol_binding, write_elf_symbol): Define new static
	functions.
	(write_var_decl, write_function_decl): Use the new
	write_elf_symbol to serialize the symbol for the decl.
	* tests/data/test-read-dwarf/test[01].abi: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-14 11:19:34 +02:00
Dodji Seketeli
ce1278c3da Initial support for elf symbol (versionning) during decl comparison
* include/abg-fwd.h (get_linkage_name): Remove.
	* include/abg-dwarf-reader.h (enum symbol_type)
	(enum symbol_binding): Move these into abg-ir.h.
	(lookup_symbol_from_elf, lookup_public_function_symbol_from_elf):
	Adjust.
	* src/abg-dwarf-reader.cc (eval_last_constant_dwarf_sub_expr):
	Declare this before using it.
	(die_address_attribute, die_location_address)
	(stt_to_elf_symbol_type, stb_to_elf_symbol_binding)
	(find_hash_table_section_index, find_symbol_table_section)
	(find_symbol_table_section_index, find_text_section)
	(find_bss_section, compare_symbol_name)
	(get_symbol_versionning_sections get_version_for_symbol)
	(lookup_symbol_from_sysv_hash_tab)
	(lookup_symbol_from_gnu_hash_tab, get_elf_class_size_in_bytes)
	(bloom_word_at, setup_gnu_ht, lookup_symbol_from_elf_hash_tab)
	(lookup_symbol_from_symtab, maybe_adjust_fn_sym_address)
	(maybe_adjust_var_sym_address): New static functions.
	(enum hash_table_kind): New enum.
	(struct gnu_ht): New struct.
	(read_context::var_decls_to_add_): Renamed var_decls_to_add into
	this.
	(read_context::{fun, var}_sym_addr_sym_index_map_): New member.
	(read_context::{lookup_symbol_from_elf,
	lookup_elf_symbol_from_index, lookup_elf_fn_symbol_from_address,
	lookup_elf_var_symbol_from_address, fun_sym_addr_sym_index_map,
	var_sym_addr_sym_index_map, load_symbol_addr_to_index_maps,
	get_function_address, get_variable_address}): New member
	functions.
	(read_context::lookup_public_{variable,
	function}_symbol_from_elf): Adjust.
	(op_pushes_constant_value): Fix a bug here.
	(lookup_symbol_from_elf): Adjust.  Support cases where there is no
	elf hash table, e.g, for relocatable files.
	(lookup_public_function_symbol_from_elf)
	(lookup_public_variable_symbol_from_elf): Adjust.
	(build_var_decl): Allow updating the var_decl to associate it with
	its underlying symbol.  In that case, if the linkage name is not
	set, set it to the symbol name.
	(build_function_decl): Likewise for function_decl.
	(operator<<(std::ostream&, symbol_type)):
	(operator<<(std::ostream&, symbol_binding)): Move these do
	abg-ir.cc.
	* include/abg-ir.h (class elf_symbol): Declare new class.  Move
	enum symbol_binding and enum symbol_type (from abg-dwarf-reader.h) to
	elf_symbol::binding and elf_symbol::type here.
	(operator<<(std::ostream&, elf_symbol::type))
	(operator<<(std::ostream&, elf_symbol::binding))
	(operator==(const elf_symbol_sptr, const elf_symbol_sptr)): New
	operators.
	(class elf_symbol::version): Declare new class.
	(class var_decl): Make this pimpl, and add ...
	(var_decl::{g,s}et_symbol): ... new member functions.
	(class function_decl): Likewise, make this pimpl and add ...
	(function_decl::{g,s}et_symbol): ... new member functions.
	* src/abg-ir.cc (struct elf_symbol, elf_symbol::priv): New
	types.
	(elf_symbol::*): Lots of new members and member functions.
	(operator==(const elf_symbol_sptr, const elf_symbol_sptr)): New.
	(operator<<(std::ostream&, elf_symbol::type)): New.
	(operator<<(std::ostream&, elf_symbol::binding)): New.
	(elf_symbol::version::priv): New type.
	(elf_symbol::version::*): Lots of member functions.
	(get_linkage_name): Removed.
	(var_decl::priv): New type.  Pimplify the thing.
	(var_decl::{s,g}et_symbol): New.
	(var_decl::operator==): Take symbols in account in the comparison.
	(function_decl::priv): New type.
	(function_decl::*): Pimplify.
	(function_decl::{s,g}et_symbol): New.
	(function_decl::operator==): Take symbols in account in the
	comparison.
	* include/abg-comparison.h (diff_context::show_linkage_name): New
	member function.
	* src/abg-comparison.cc (diff_context::priv::show_linkage_name_):
	New member.
	(diff_context::priv::priv): Initialize it.
	(diff_context::show_linkage_names): New member function.
	(corpus_diff::report): If the user used --show-linkage-names,
	display the linkage name after the name of the functions.  Add
	missing "'" in the some spots.
	* tools/bidiff.cc (options.show_linkage_names): New member.
	(display_usage, parse_command_line): Support --linkage-names.
	* tools/bisym.cc (show_help): Add '\n' at the end of help string
	for --demangle.  Add --no-absolute-path option.
	(parse_command_line): Support --no-absolute-path.
	(main): Adjust for symbol (versionning) support.  Consider that
	the program successfully completed even when the symbol wasn't
	found.  Support --no-absolute-path.
	* tests/data/test-lookup-syms/test0-report.txt: New.
	* tests/data/test-lookup-syms/test01-report.txt: New.
	* tests/data/test-lookup-syms/test02-report.txt: New.
	* tests/data/test-read-dwarf/test0.abi: Adjust.
	* tests/data/test-read-dwarf/test1.abi: Adjust.
	* tests/data/test-diff-dwarf/test7-report.txt: Adjust.
	* tests/data/test-diff-filter/test10-report.txt: Adjust.
	* tests/data/test-diff-filter/test12-report.txt: Adjust.
	* tests/data/test-lookup-syms/test1-[123]-report.txt: New.
	* tests/data/test-lookup-syms/test1.c: New.
	* tests/data/test-lookup-syms/test1.version-script: New.
	* tests/test-lookup-syms.cc: Adjust for new tests.
	* test/Makefile.am: Adjust makefile.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-12 16:09:47 +02:00
Dodji Seketeli
bdf9e956d8 Rename decl_base::get_mangled_name into decl_base::get_linkage_name
* include/abg-ir.h (decl_base::get_linkage_name): Renamed
	decl_base::get_mangled_name into this.
	* src/abg-comparison.cc
	(class_diff::ensure_lookup_tables_populated)
	(function_decl_diff::report, type_decl_diff::report)
	(corpus_diff::priv::ensure_lookup_tables_populated)
	(corpus_diff::report, compute_diff): Adjust.
	* src/abg-corpus.cc ({var_comp, func_comp}::operator()): Likewise.
	(corpus::priv::build_symbol_table): Likewise.
	* src/abg-dwarf-reader.cc (die_linkage_name): Renamed
	die_mangled_name into this.
	(die_loc_and_name, build_translation_unit_and_add_to_ir)
	(build_namespace_decl_and_add_to_ir, build_type_decl)
	(build_enum_type, build_class_type_and_add_to_ir)
	(build_typedef_type, build_var_decl, build_function_decl, ): Adjust.
	* src/abg-hash.cc (decl_base:#️⃣:operator()): Likewise.
	* src/abg-ir.cc (decl_base::priv::linkage_name_): Renamed
	decl_base::priv::mangled_name_ into this.
	(decl_base::priv::priv, decl_base::{decl_base, operator==})
	(get_linkage_name, typedef_decl::typedef_decl, var_decl::var_decl)
	(function_decl::function_decl, class_decl::base_spec::base_spec)
	(class_decl::method_decl::method_decl): Adjust.
	(decl_base::{g,s}et_linkage_name): Renamed
	decl_base::{g,s}et_mangled_name into this.
	* src/abg-writer.cc (write_decl, write_typedef_decl)
	(write_var_decl, write_function_decl, dump): Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-11 19:22:00 +02:00
Dodji Seketeli
12c777681d Support symbol lookups from ELF
* include/abg-dwarf-reader.h (symbol_type, symbol_binding): New
	enums.
	(operator<<): Declare new overloads for the new enums above.
	(lookup_symbol_from_elf, lookup_public_function_symbol_from_elf):
	Declare new entry points.
	* src/abg-dwarf-reader.cc (lookup_symbol_from_elf)
	(lookup_public_function_symbol_from_elf)
	(lookup_public_variable_symbol_from_elf): Define new static
	functions.
	(read_context::elf_{module_, handle}_): New data members.
	(read_context::{elf_module, elf_handle}): New accessors.
	(read_context::load_debug_info): Store the elf module into
	read_context::_elf_module_.  Adjust.
	(read_context::{lookup_symbol_from_elf,
	lookup_public_function_symbol_from_elf,
	lookup_public_variable_symbol_from_elf}): New member functions.
	(lookup_symbol_from_elf, lookup_public_function_symbol_from_elf)
	(operator<<): Define public entry points.
	* tools/bisym.cc: New tool to lookup a symbol in an elf file.
	* tools/Makefile.am: Add the bisym.cc source file to the
	distribution and arrange to compile it into a 'bisym' executable.
	* tests/test-lookup-syms.cc: New test harness.
	* tests/data/test-lookup-syms/test0-report.txt: New test input
	for the harness above.
	* tests/data/test-lookup-syms/test0.cc: Likewise.
	* tests/data/test-lookup-syms/test0.o: Likewise
	* tests/data/test-lookup-syms/test01-report.txt: Likewise.
	* tests/data/test-lookup-syms/test02-report.txt: Likewise.
	* tests/Makefile.am: Build the new runtestlookupsyms test and add
	the new files to the distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-21 17:56:40 +02:00
Dodji Seketeli
2ce2eff68e Add corpus::{s,g}et_origin accessors
* include/abg-corpus.h (enum corpus::origin): New enum.
	(corpus::{g,s}et_origin): New accessors.
	* src/abg-corpus.cc (corpus::priv::origin): New data member.
	(corpus::priv::is_symbol_table_built): Move this up.
	(corpus::priv::priv): Adjust.
	(corpus::{g,s}et_origin): Define accessors.
	* src/abg-dwarf-reader.cc (read_corpus_from_elf): Set the corpus
	origin.  Also set the path.  Oops.
	* src/abg-reader.cc (read_corpus_from_input)
	(read_corpus_from_archive): Set the corpus origin.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-21 17:22:11 +02:00
Dodji Seketeli
0d55047a4e Add a get_linkage_name function.
* include/abg-fwd.h (is_at_global_scope): Declare a new overload.
	(get_linkage_name): Declare ...
	* src/abg-ir.cc (get_linkage_name): ... these new entry points.
	(is_at_global_scope): Define these new overloads useful for the
	new get_linkage_name.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-21 17:14:30 +02:00
Dodji Seketeli
e2c776f4bc Pimplify decl_base and add decl_base::{s,g}et_is_in_public_symbol_table
* include/abg-ir.h (struct decl_base::priv): New pimpl type.
	(decl_base::priv_): New pimpl.
	(decl_base::{hashing_started, peek_hash_value,
	peek_qualified_name, set_qualified_name}): Declare new protected
	methods.
	(decl_base::{get_context_rel, set_qualified_name, get_location,
	set_location, set_name, set_mangled_name, get_visibility,
	set_visibility}): Move these out-of-line.
	(decl_base::{g,s}et_is_public_symbol_table):
	(class_decl::hashing_started): Remove this as we now have
	decl_base::hashing_started.
	(decl_base::{hash_, hashing_started, location_, context_, name_,
	qualified_parent_name_, qualified_name_, mangled_name_,
	visibility_}): Move all these members into the new ...
	* src/abg-ir.cc (struct decl_base::priv): ... pimpl type.
	(decl_base::decl_base): Move these out-of-line here.  Adjust the
	other overloads.
	(decl_base::{hashing_started, peek_hash_value,
	peek_qualified_name, set_qualified_name}): Define these new
	protected methods.
	(decl_base::{get_context_rel, set_context_rel, get_location,
	set_location, set_name, get_mangled_name, set_mangled_name,
	get_visibility, set_visibility}): Define these out-of-line here.
	(decl_base::{get_hash, set_hash, get_scope,
	get_qualified_parent_name, get_qualified_name, operator==,
	set_scope}): Adjust.
	(qualified_type_def::get_qualified_name): Likewise.
	(pointer_type_def::get_qualified_name): Likewise.
	(reference_type_def::get_qualified_name): Likewise.
	(var_decl::set_scope): Likewise.
	(class_decl::base_spec): Likewise.
	(class_decl::method_decl::set_scope): Likewise.
	(decl_base::{g,s}et_is_in_public_symbol_table): Define new accessors.
	* src/abg-hash.cc ({decl_base, type_decl, scope_decl,
	scope_type_decl, qualified_type_def, pointer_type_def,
	reference_type_def, enum_type_decl, typedef_decl, var_decl,
	class_decl}:#️⃣:operator): Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-21 17:13:46 +02:00
Dodji Seketeli
262c39f763 Categorize base class changes as SIZE_OR_OFFSET_CHANGE_CATEGORY
* include/abg-comparison.h (class_diff::{deleted, inserted,
	changed}_bases): Declare new member functions ...
	* src/abg-comparison.cc ((class_diff::{deleted, inserted,
	changed}_bases)): ... and define them.
	* src/abg-comp-filter.cc (base_classes_added_or_removed): Define
	new static functions.
	(harmless_filter): Categorize base classes added or removed.
	* tests/data/test-diff-dwarf/test8-report.txt: New test input.
	* tests/data/test-diff-dwarf/test8-v0.cc: Likewise.
	* tests/data/test-diff-dwarf/test8-v0.o: Likewise.
	* tests/data/test-diff-dwarf/test8-v1.cc: Likewise.
	* tests/data/test-diff-dwarf/test8-v1.o: Likewise.
	* tests/data/test-diff-filter/test13-report.txt: New test input.
	* tests/data/test-diff-filter/test13-v0.cc: Likewise.
	* tests/data/test-diff-filter/test13-v0.o: Likewise.
	* tests/data/test-diff-filter/test13-v1.cc: Likewise.
	* tests/data/test-diff-filter/test13-v1.o: Likewise.
	* tests/Makefile.am: Add the new files above to the source distribution.
	* tests/test-diff-dwarf.cc: Use the new relevant input above to
	run more tests.
	* tests/test-diff-filter.cc: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-17 15:37:53 +02:00
Dodji Seketeli
e4820f9e33 File static data member changes in STATIC_DATA_MEMBER_CHANGE_CATEGORY
* include/abg-comparison.h
	(diff_category::STATIC_DATA_MEMBER_CHANGE_CATEGORY): New category.
	(diff_category::EVERYTHING_CATEGORY): Update
	* src/abg-comp-filter.cc (static_data_member_type_size_changed)
	(static_data_member_added_or_removed): Define new static
	functions.
	(harmless_filter::visit): Categorize changes to static data
	members as STATIC_DATA_MEMBER_CHANGE_CATEGORY.
	* tools/bidiff.cc (set_diff_context_from_opts):
	STATIC_DATA_MEMBER_CHANGE_CATEGORY is falls into the harmless
	group.
	* tests/data/test-diff-filter/test12-report.txt: New test input.
	* tests/data/test-diff-filter/test12-v0.cc: Likewise.
	* tests/data/test-diff-filter/test12-v0.o: Likewise.
	* tests/data/test-diff-filter/test12-v1.cc: Likewise.
	* tests/data/test-diff-filter/test12-v1.o: Likewise.
	* tools/bidiff.cc: Run this test with the additional input data
	above.
	* tests/Makefile.am: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-17 11:50:45 +02:00
Dodji Seketeli
fc6af95304 Fix typo in comments
* include/abg-comparison.h
	(diff_category::NON_VIRT_MEM_FUN_CHANGE_CATEGORY): Fix typo in
	comments.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-17 11:17:02 +02:00
Dodji Seketeli
c545e58b52 Add dumping routines for declaration location
* include/abg-fwd.h (get_global_scope()): New overload for const
	decl_base&.  Move the other overloads up in the file.
	(get_translation_unit): Add an overload for decl_base&.  Constify
	the others.
	(dump_decl_location): Declare new functions.
	* src/abg-ir.cc (get_global_scope): Define the overload for const
	decl_base&.  Write the other overloads in terms of this one.
	(get_translation_unit): Likewise, define the overload for const
	decl_base&.  Write the other overloads in terms of this one.
	(dump_decl_location): Define these new overloads.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-16 17:09:49 +02:00
Dodji Seketeli
3ae24bafc3 Provide a robust way of getting the size of a qualified type
* include/abg-ir.h (qualified_type_def::get_size_in_bits): Declare
	new member function ...
	* src/abg-ir.cc (qualified_type_def::get_size_in_bits): ... and
	define it.  Keep in mind that some times the size of the
	underlying type can change between the moment the qualified type
	is created and the end of its life time.  That is because a
	subsequent DIE (from DWARF) can alter the size of the underlying
	type.  This overload allows the user to always query the size of
	the underlying type and keep the size of the qualified type in
	sync with it.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-16 11:41:20 +02:00
Dodji Seketeli
8b93472231 Add more pretty printing facilities
* include/abg-comparison.h (get_pretty_representation(diff*)):
	Declare new function.
	* include/abg-fwd.h (get_pretty_representation): Declare functions
	for decl_base*, type_base*, decl_base_sptr and type_base_sptr.
	* src/abg-comparison.cc (get_pretty_representation): Implement
	this for diff*.
	* src/abg-ir.cc (get_pretty_representation): Define
	implementations for decl_base*, type_base*, decl_base_sptr and
	type_base_sptr.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-14 22:46:51 +02:00
Dodji Seketeli
99d3857ddd Recognize virtual member functions better and store them appart
* include/abg-fwd.h (set_member_function_is_virtual): Declare new
	function.
	* include/abg-ir.h (class class_decl): Declare
	set_member_function_is_virtual and member_function_is_virtual as
	friends of class_decl.
	(class_decl::add_member_function): Take an is_virtual flag.
	(class_decl::get_num_virtual_functions): Remove.
	(class_decl::get_virtual_mem_fns): New member function.
	(mem_fn_context_rel::is_virtual_): New member.
	(mem_fn_context_rel::mem_fn_context_rel): Adjust to initialize the
	new is_virtual_ member.
	(mem_fn_context_rel::is_virtual): New member functions.
	* src/abg-comparison.cc (represent): Adjust.
	* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): Adjust.
	* src/abg-ir.cc (member_function_is_virtual): Change this to use
	mem_fn_context_rel::is_virtual.
	(set_member_function_is_virtual): Define this new function.
	(class_decl::priv::virtual_mem_fns_): New member to hold virtual
	member functions.
	(class_decl::get_virtual_mem_fns): Implement this member function.
	(class_decl::get_num_virtual_functions): Remove.
	(class_decl::add_member_function): Take a new is_virtual flag.
	Add virtual member functions to
	class_decl::priv::virtual_mem_fns_.
	* src/abg-reader.cc (build_class_decl): Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-14 14:56:51 +02:00
Dodji Seketeli
305f18e91e Filter non-virtual member fns insertions/deletions from class changes
* include/abg-fwd.h (member_function_is_virtual): Declare new
	function.
	* include/abg-comparison.h
	(diff_category::{NON_VIRT_MEM_FUN_CHANGE_CATEGORY,
	VIRTUAL_MEMBER_CHANGE_CATEGORY}): New enumerators.
	(diff_category::EVERYTHING_CATEGORY): Adjust.
	(class_diff::{changed, deleted, inserted}_member_fns): Declare new
	member functions.
	* src/abg-comp-filter.cc (data_member_added_or_removed): Add
	missing comments.
	(has_non_virtual_mem_fn_change): New static predicate function.
	(harmless_filter::visit): Categorize non-virtual member function
	changes in a diff into NON_VIRT_MEM_FUN_CHANGE_CATEGORY.
	* src/abg-comparison.cc
	(TRAVERSE_MEM_FN_DIFF_NODE_AND_PROPAGATE_CATEGORY): New macro.
	(report_mem_header): Count filtered functions for added/deleted
	functions as well.
	(class_diff::priv::count_filtered_changed_mem_fns): Renamed
	priv::count_filtered_member_functions into this.  Filter out
	changes to non-virtual member functions here.
	(class_diff::priv::count_filtered_{inserted, deleted}_mem_fns):
	New member functions.
	(class_diff::{deleted, inserted, changed}_member_fns): Define new
	member functions.
	(class_diff::report): Adjust count for filtered inserted/deleted
	member functions.  Do not report NON_VIRT_MEM_FUN_CHANGE_CATEGORY
	if it's disallowed.
	(class_diff::traverse): Propagate only
	VIRTUAL_MEMBER_CHANGE_CATEGORY from member functions to their
	enclosing class.
	* src/abg-ir.cc (member_function_is_virtual): Define new
	functions.
	* tools/bidiff.cc (set_diff_context_from_opts): Adjust to add
	NON_VIRT_MEM_FUN_CHANGE_CATEGORY into the harmless group and
	VIRTUAL_MEMBER_CHANGE_CATEGORY into the harmful one.
	* tests/data/test-diff-filter/test0-report.txt: New test input.
	* tests/data/test-diff-filter/test10-report.txt: Likewise.
	* tests/data/test-diff-filter/test10-v0.cc: Likewise.
	* tests/data/test-diff-filter/test10-v0.o: Likewise.
	* tests/data/test-diff-filter/test10-v1.cc: Likewise.
	* tests/data/test-diff-filter/test10-v1.o: Likewise.
	* tests/data/test-diff-filter/test11-report.txt: Likewise.
	* tests/data/test-diff-filter/test11-v0.cc: Likewise.
	* tests/data/test-diff-filter/test11-v0.o: Likewise.
	* tests/data/test-diff-filter/test11-v1.cc: Likewise.
	* tests/data/test-diff-filter/test11-v1.o: Likewise.
	* tests/data/test-diff-filter/test2-report.txt: Likewise.
	* tests/data/test-diff-filter/test9-report.txt: Likewise.
	* tests/data/test-diff-filter/test9-v0.cc: Likewise.
	* tests/data/test-diff-filter/test9-v0.o: Likewise.
	* tests/data/test-diff-filter/test9-v1.cc: Likewise.
	* tests/data/test-diff-filter/test9-v1.o: Likewise.
	* tests/test-diff-filter.cc: Consume the test input above to run
	more tests.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-13 23:09:02 +02:00
Dodji Seketeli
7ac2fe072d Make class_decl pimpl and harden comparison infloop prevention
* include/abg-ir.h (class_decl::{priv}): New private data member.
	(class_decl::{get_is_declaration_only, set_is_declaration_only,
	is_struct, get_definition_of_declaration, get_earlier_declaration,
	add_base_specifier, get_base_specifiers, get_member_types,
	get_data_members, get_member_functions,
	get_member_function_templates, get_member_class_templates}): Move
	these methods out-of-line.
	(class_decl::{comparison_started_,
	declaration_,is_declaration_only_, definition_of_declaration,
	is_struct_, bases_, member_types_, data_members_,
	member_functions_, member_function_template,
	member_class_templates_}): Move these data members into the pimpl
	in ...
	* src/abg-ir.cc
	(class_decl::priv::{declaration_,is_declaration_only_,
	definition_of_declaration, is_struct_, bases_, member_types_,
	data_members_, member_functions_, member_function_template,
	member_class_templates_}): ... here.
	(class_decl::priv::classes_being_compared_): New data member.
	(class_decl::priv::priv): Initialize the data members.
	(class_decl::priv::{mark_as_being_compared,
	unmark_as_being_compared, comparison_started): New methods.
	(class_decl::{get_is_declaration_only, set_is_declaration_only,
	is_struct, get_definition_of_declaration, add_base_specifier,
	get_base_specifiers, get_member_types, get_data_members,
	get_member_functions, get_member_function_templates,
	get_member_class_templates}): Move these out-of-line in here.
	(class_decl::{class_decl, set_definition_of_declaration,
	set_earlier_declaration, insert_member_type, add_member_type,
	add_data_member, add_member_function,
	add_member_function_template, add_member_class_template,
	has_no_base_nor_member}): Adjust.
	(class_decl::operator==): Harden inf-loop prevention during class
	comparison using the new priv::mark/unmark_as_being_compared()
	functions.  Now comparison of a class really compares member
	functions again.  And it is *slooow*.  I should probably change
	this to compare only virtual member functions.  But at least this
	should be correct and robust for now.
	* tests/data/test-diff-filter/test0-report.txt: Adjust.
	* test01-report.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-13 22:09:24 +02:00
Dodji Seketeli
263fb9513c Remove the parent member of the diff node
* include/abg-comparison.h (diff::parent_): Remove.
	(diff::diff): Adjust.
	(diff::{get, set}_parent): Remove.
	* src/abg-comp-filter.cc (harmless_filter::visit): Remove category
	propagation to the parent.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-11 22:14:21 +02:00
Dodji Seketeli
f02768e7a7 Represent a removed+added data member at a given offset as changed
* include/abg-fwd.h (get_data_member_offset): Declare new overload for
	decl_base_sptr.
	* include/abg-comparison.h (unsigned_decl_base_sptr_map)
	(unsigned_changed_type_or_decl_map): New typedefs.
	* src/abg-ir.cc (get_data_member_offset): Define new overload for decl_base_sptr.
	* src/abg-comparison.cc (diff_kind::subtype_change_kind): New
	enumerator for a change about a type or sub-type of a member of a
	structure/enum.
	(report_mem_header): Handle the new enumerator above.
	(class_diff::priv::{deleted_dm_by_offset_, inserted_dm_by_offset_,
	changed_dm_}): New data members.
	(class_diff::priv::subtype_changed_dm_): Renamed
	class_diff::priv::changed_data_members_ into this.
	(class_diff::priv::subtype_changed_dm): Renamed
	class_diff::priv::data_member_has_changed into this. Adjust.
	(class_diff::count_filtered_subtype_changed_dm): Renamed
	count_filtered_data_members into this.  Adjust.
	(class_diff::priv::count_filtered_changed_dm): New member
	function.
	(class_diff::lookup_tables_empty): Adjust.
	(class_diff::ensure_lookup_tables_populated): Adjust.  Detect when
	a data member is deleted and added back to offset N, and be
	prepared to present that as a change of data member at offset N.
	(class_diff::report): Adjust.  Report data members of a given
	offset that have changed.
	* tests/data/test-diff-dwarf/test6-report.txt: New reference
	report for new test input.
	* tests/data/test-diff-dwarf/test6-v0.cc: Source code for new test
	input binary.
	* tests/data/test-diff-dwarf/test6-v0.o: New test input binary.
	* tests/data/test-diff-dwarf/test6-v1.cc: Source code for new test
	input binary.
	* tests/data/test-diff-dwarf/test6-v1.o: New test input binary.
	* tests/test-diff-dwarf.cc: Adjust to include the new test inputs above.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-11 21:55:08 +02:00
Dodji Seketeli
13c6c8ebed Ensure that each diff node is traversed just once
* include/abg-comparison.cc (pointer_map): New typedef.
	(diff_context::{has_diff_for}): New overload for diff*.
	(diff_context::{diff_has_been_traversed, mark_diff_as_traversed,
	forget_traversed_diffs}): Declare new methods.
	* src/abg-comparison.cc (ENSURE_DIFF_NODE_TRAVERSED_ONCE)
	(ENSURE_MEM_DIFF_NODE_TRAVERSED_ONCE): Define new macros.
	(diff_context::priv::traversed_diff_nodes_): New data member.
	(diff_context::has_diff_for): New overload for diff*
	(diff_context::{diff_has_been_traversed, mark_diff_as_traversed,
	forget_traversed_diffs}): Define new member functions.
	(diff_context::maybe_apply_filters): Forget the traversed diffs
	before applying a filter.
	({distinct_diff, var_diff, pointer_diff, reference_diff,
	qualified_type_diff, enum_diff, class_diff, base_diff, scope_diff,
	function_decl_diff, type_decl_diff, typedef_diff,
	translation_unit_diff}::traverse): Ensure that the diff node is
	traversed only once.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-11 21:11:53 +02:00
Dodji Seketeli
bf52d83bfe Consider added/removed data members as changing size or offset
* src/abg-comp-filter.cc (data_member_added_or_removed): New
	static function.
	(harmless_filter::visit): Re-organize logic.  Categorize data
	member addition/removal into SIZE_OR_OFFSET_CHANGE_CATEGORY.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-10 15:07:24 +02:00
Dodji Seketeli
d25c8bbbaa Fix and add missing hashing through the virtual decl_base::get_hash
* include/abg-ir.h (struct {scope_decl, non_type_tparameter,
	type_composition, class_decl}::hash): Declare hashers.
	({scope_decl, var_decl, non_type_tparameter, type_composition,
	class_decl}::get_hash): Provide new overloads of the get_hash.
	* src/abg-hash.cc ({type_decl, scope_type_decl,
	qualified_type_def, pointer_type_def, reference_type_def,
	enum_type_decl, typedef_decl, var_decl,
	function_decl}:#️⃣:operator()): If the hash is being
	calculated, do not use the not-yet fully calculated hash value.
	Rather, calculate the hash, cache it and return the value.
	({class_decl, non_type_tparameter}:#️⃣:operator()): Moved the
	{class_decl, non_type_tparameter}::hash declaration out of here
	and stick it in include/abg-ir.h.  Keep the definition of the
	hashing operators here though.
	(type_composition:#️⃣:operator()): New operator definition.
	* src/abg-ir.cc ({scope_decl, var_decl, class_decl,
	non_type_tparameter, type_composition}::get_hash): Define new
	virtual overload.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-04-09 17:11:32 +02:00