Commit Graph

374 Commits

Author SHA1 Message Date
Dodji Seketeli
d50882bf4f Make class_decl::base_spec class follow the pimpl pattern
* include/abg-ir.h (class_decl::base_spec::priv): Declare new
	private data type.
	(class_decl::base_spec::priv_): Declare new pimpl data member.
	(class_decl::base_spec::{base_class_, offset_in_bits_,
	is_virtual_}): Remove.
	(class_decl::base_spec::{get_base_class, get_is_virtual,
	get_offset_in_bits}): Make these member functions out of line.
	* src/abg-ir.cc (struct class_decl::base_spec::priv): New type.
	(class_decl::base_spec::{get_base_class, get_is_virtual,
	get_offset_in_bits}): Define these functions here.
	(class_decl::base_spec::base_spec): Adjust because now there is
	only one pimpl data member to initialize.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2016-01-04 19:57:45 +01:00
Ondrej Oprala
6a7566d513 Add the option of printing the file, line and column information about a type being reported.
* bash-completion/abicompat: Complete the new "--no-show-locs" option.
	* bash-completion/abidiff: Likewise.
	* bash-completion/abidw: Likewise.
	* bash-completion/abipkgdiff: Likewise.
	* doc/manuals/abicompat.rst: Mention the new "--no-show-locs" option.
	* doc/manuals/abidiff.rst: Likewise.
	* doc/manuals/abidw.rst: Likewise.
	* doc/manuals/abipkgdiff.rst: Likewise.
	* include/abg-comparison.h (show_locs): Add declarations.
	* src/abg-comparison.cc: (diff_context::priv): Add a new switch
	called "show_locs_" and set its default value to false.
	(report_loc_info): New function. Outputting the extra information
	is conditionalized based on the associated diff contexts settings.
	(show_locs): define a getter/setter for
	diff_context::priv::show_locs_.
	({distinct,pointer,reference,qualified_type,enum,class,scope,fn_parm,
	typedef,corpus}_diff::report): Call report_loc_info when
	appropriate.
	(maybe_report_diff_for_member): Likewise.
	(represent): Accept a const reference to a diff_context_sptr as a first
	argument and call report_loc_info on its second argument.
	* src/abg-dwarf-reader.cc:
	* tests/data/Makefile.am: Add the new test reference files.
	* tests/data/test-abicompat/test0-fn-changed-report-2.txt: New test
	reference output.
	* tests/data/test-abicompat/test5-fn-changed-report-1.txt: Likewise.
	* tests/data/test-abicompat/test6-var-changed-report-1.txt: Likewise.
	* tests/data/test-abicompat/test7-fn-changed-report-2.txt: Likewise.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report1.txt:
	Likewise.
	* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-1.txt:
	Likewise.
	* tests/data/test-diff-pkg/dirpkg-3-report-2.txt: Likewise.
	* tests/data/test-diff-suppr/test6-fn-suppr-report-0-1.txt: Likewise.
	* tests/test-abidiff.cc: Explicitly create a diff context and turn off
	location emitting.
	* tests/test-diff-dwarf.cc: Likewise.
	* tests/test-abicompat.cc: Add --no-show-locs to all existing test
	arguments. Run a few of the existing tests again, but without this
	option.
	* tests/test-diff-filter.cc: Likewise.
	* tests/test-diff-pkg.cc: Likewise.
	* tests/test-diff-suppr.cc: Likewise.
	* tools/abicompat.cc: Handle the new "--no-show-locs" option.
	* tools/abidiff.cc: Likewise.
	* tools/abidw.cc: Likewise.
	* tools/abipkgdiff.cc: Likewise.

Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
2015-12-15 12:32:55 +01:00
Dodji Seketeli
b017143876 [PERF] Access naked pointers for canonical types and function types
Performance profiling has shown that accessing shared_ptr to canonical
types and function type during type comparison was noticeable slowing
down the process.  This patch thus access naked pointers for canonical
types and function types at these performance hot spots.

The profiling took place while running abidw --abidiff on the
r300_dri.so binary.

	* include/abg-ir.h (type_base::get_naked_canonical_type): Declare
	new accessor.
	(function_decl::get_naked_canonical_type): Likewise.
	(function_decl::set_type): Pass a reference to the shared_ptr.
	* src/abg-ir.cc (type_base::priv::naked_canonical_type): New data
	member.
	(type_base::priv::priv): Initialize it.
	(canonicalize): Set the naked canonicalize type when we set its
	shared pointer.
	(type_base::get_naked_canonical_type): Define new accessor.
	({pointer_type_def,reference_type_def,function_type,class_decl}::operator==):
	Use naked canonical pointers rather than the slower shared_ptr to
	canonical pointers.
	(function_decl::priv::naked_type_): New data member.
	(function_decl::priv::priv): Initialize it.
	(function_decl::get_naked_type): Define new accessor.
	(function_decl::set_type): Pass a reference to the shared_ptr .
	(equals): In the overload for function_decl, use the faster naked
	pointers to the type of the function.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-12-11 11:19:57 +01:00
Dodji Seketeli
c0de97846c [PERF] Turn some pimpl pointers into naked pointers
The private data pointers of libabigail IR types are usually managed
using shared_ptr.  But performance profiling has shown that
de-referencing some of these private data shared_ptr can have a
noticeable performance impact.  This is because de-referencing
shared_ptr involves some locking that show up on some performance
profile.

So, for decl_base, type_base, and function_decl, this patch replaces
the private data shared pointers by naked pointers.  This speeds up
the access to private data members, especially during comparison of
class pointer, reference and function types.  And that has a
noticeable impact when libabigail handles huge binaries with lots of
functions an type, like r300_dri.so.

	* include/abg-ir.h ({decl_base, type_base, function_decl}::priv_)
	Make this a naked pointer to priv, rather than a shared_ptr<priv>.
	* src/abg-ir.cc (decl_base::~decl_base): Destroy the private data
	pointer, aka pimpl pointer.
	(type_base::~type_base): Likewise.
	(function_decl::~function_decl): Likewise.
	(class_decl::~class_decl): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-12-11 11:19:57 +01:00
Dodji Seketeli
1466510881 [PERF] Pass a bunch of perf-sensitive smart pointers by reference
* include/abg-fwd.h (lookup_type_in_corpus, lookup_type_in_scope)
	(lookup_var_decl_in_scope): Pass the decls smart pointers by
	reference.
	* src/abg-ir.cc (lookup_type_in_corpus, lookup_type_in_scope)
	(lookup_var_decl_in_scope): Pass the decls smart pointers by
	reference, for performance reasons.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-12-11 11:19:57 +01:00
Dodji Seketeli
0ec2416837 Bug 19126 - abidw segv on a dwz compressed version of r300_dri.so
Suppose a declaration D (which locus is in a file F) is imported at an
offset offset of O1 into a compilation unit C1 and at an offset O2
(using DW_TAG_imported_unit) into a compilation unit C2.

When the DWARF reader creates the ABI artifact for D in O1, its
location is encoded by a location manager that is handled by C1.

At O2 (in C2) the ABI artifact for D (created at O1, in C1) is
re-used.  But then, to decode the location of D, the DWARF reader
wrongly uses the location manager that is handled by C2.  It should
use the location manager of C1, because that is the one used to encode
the location of D.

It picks the wrong location manager because it picks the wrong
translation unit for D. Right now, the translation unit for a given
declaration is the "current" translation unit at the moment the DIE
was being inspected.  And that is wrong when imported type units kick
in.

1/ More generally, each ABI artifact should be associated with its
translation unit, which is the current translation unit when the
artifact was created.  As there is just one copy of D, its translation
unit should always be the same.

2/ Also, the location should ensure that about the location manager used
to encode it is the same one used to decode it, so that this kind of
bug cannot arise.

This patch fixes the issue by doing 1/ and 2/.  The r300_dri.so test
case on which is was failing is not added to the test suite because
it's too big.  It was taking more than 55 minutes to have complete
abidw --abidiff complete on that binary, on my machine.  So I am going
to work on the performance side of things, I think.

	* include/abg-ir.h (class location_manager): Forward declare it
	before class location.
	(location::loc_manager_): New data member.
	(location::location): Take the location manager in one overload
	and initialize the new loc_managers_ in all the overloads.
	(location::get_location_manager): New getter.
	(location::expand): New member function.
	(location::*): Add API doc to all entry points.
	(location_manager::expand_location): Take a const location.
	(type_or_decl_base::set_corpus): Remove.
	(type_or_decl_base::{get,set}_translation): New accessors.
	(decl_base::{decl_base,get_location}): Take or return a reference
	on location.
	(scope_decl::scope_decl): Likewise.
	(type_decl::type_decl): Likewise.
	(namespace_decl::namespace_decl): Likewise.
	(qualified_type_def::qualified_type_def): Likewise.
	(pointer_type_def::pointer_type_def): Likewise.
	(reference_type_def::reference_type_def): Likewise.
	(array_type_def::subrange_type::{subrange_type,
	get_location}): Likewise.
	(enum_type_decl::enum_type_decl): Likewise.
	(typedef_decl::typedef_decl): Likewise.
	(var_decl::var_decl): Likewise.
	(function_decl::function_decl): Likewise.
	(function_decl::parameter::parameter): Likewise.
	(template_decl::template_decl): Likewise.
	(type_tparameter::type_tparameter): Likewise.
	(non_type_tparameter::non_type_tparameter): Likewise.
	(function_tdecl::function_tdecl): Likewise.
	(class_tdecl::class_tdecl): Likewise.
	(class_decl::class_decl): Likewise.
	(class_decl::method_decl::method_decl): Likewise.
	* src/abg-ir.cc (location::expand_location): Define new member
	function.
	(type_or_decl_base::priv::corpus_): Remove.
	(type_or_decl_base::priv::translation_unit_): New data member.
	(type_or_decl_base::priv::priv): Adjust.
	(type_or_decl_base::set_corpus): Remove.
	(type_or_decl_base::get_corpus): Adjust.
	(type_or_decl_base::{get,set}_translation_unit): New member
	functions.
	(decl_base::priv::priv): Take a reference to location.
	(decl_base::decl_base): Likewise.
	(decl_base::get_location): Return a reference to location.
	(location_manager::create_new_location): Adjust.
	(location_manager::expand_location): Take a reference to location.
	(translation_unit::get_global_scope()): Adjust.
	(translation_unit::bind_function_type_life_time): Likewise.
	(scope_decl::{add,insert}_member_decl): Adjust.
	(get_translation_unit): Likewise.
	(type_decl::type_decl): Take a reference to location.
	(namespace_decl::namespace_decl): Likewise.
	(qualified_type_def::qualified_type_def): Likewise.
	(pointer_type_def::pointer_type_def): Likewise.
	(reference_type_def::reference_type_def): Likewise.
	(array_type_def::subrange_type::priv::priv): Likewise.
	(array_type_def::subrange_type::{subrange_type,
	get_location}): Likewise.
	(enum_type_decl::enum_type_decl): Likewise.
	(typedef_decl::typedef_decl): Likewise.
	(var_decl::var_decl): Likewise.
	(function_decl::function_decl): Likewise.
	(function_decl::parameter::parameter): Likewise.
	(template_decl::template_decl): Likewise.
	(type_tparameter::type_tparameter): Likewise.
	(non_type_tparameter::non_type_tparameter): Likewise.
	(function_tdecl::function_tdecl): Likewise.
	(class_tdecl::class_tdecl): Likewise.
	(class_decl::class_decl): Likewise.
	(class_decl::method_decl::method_decl): Likewise.
	* src/abg-writer.cc (write_location): Take a reference to
	location and adjust.
	(write_array_type_def, write_function_decl, dump_decl_location):
	Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-12-10 16:47:18 +01:00
Dodji Seketeli
2eda63d0f2 Fix internal name for pointers, typedefs and arrays
Internal names (and pretty representation) of types are used for type
canonicalization.  These were not being correctly computed for
pointers typedefs and arrays because we were forgetting sometimes to
use internal names of the underlying types, especially because of caching issues.

This patch addresses that.

Note that I noticed this while comparing the two versions of
libgromacs_d.so.0.0.0 involved in the comparison referenced by bug
https://bugzilla.redhat.com/show_bug.cgi?id=1283906.  But then that
library is too big (and takes too much time) to be included as a non
regression test :(

	* include/abg-ir.h (pointer_type_def::priv_): New data structure.
	The type is now pimpled.
	(typedef_decl::priv_): Likewise.
	* src/abg-ir.cc (struct pointer_type_def::priv): New struct.
	(pointer_type_def::pointer_type_def): Adjust.
	(pointer_type_def::get_pointed_to_type): Likewise.
	(pointer_type_def::get_qualified_name): Store temporary/internal
	names into different caches.
	(array_type_def::priv::{temp_internal_qualified_name_,
	internal_qualified_name_}): New data members.
	(get_type_representation): In the overload for array_type_def,
	take requests for internal names into account.
	(array_type_def::get_qualified_name): Take requests for internal
	names into account.  Store temporary/internal names into different
	caches.
	(typedef_decl::priv): New struct.
	(typedef_decl::typedef_decl): Adjust.
	(typedef_decl::get_underlying_type): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-12-08 14:14:09 +01:00
Dodji Seketeli
fa4b7c8069 Fix comparison in qualified_type_diff::has_changes
* src/abg-comparison.cc (qualified_type_diff::has_changes): Make
	this stupid and simple, now that we have (fast) canonical type
	based comparison.
	* include/abg-ir.h (qualified_type_diff::operator==): Add an
	overload for qualified_type_diff here.
	(operator==): Likewise.
	* src/abg-ir.cc (qualified_type_diff::operator==): Define it.
	(operator==): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-12-08 14:14:08 +01:00
Dodji Seketeli
43c908ed15 Bug 19336 - Better handle redundantly qualified reference types
Sometimes we can see const references in DWARF.  But then, a reference
is always const, so that qualified reference is redundant.
Furthermore, having that construct make its way into the internal
representation can cause awkward diagnostics.

The DWARF reader was thus eliding such redundant qualifiers in the
function "maybe_strip_qualification".  It was doing so by stripping
the qualifier from the qualified type. So const reference, for
instance, becomes a (non-qualified) reference.  In that case, we are
turning a qualified type into a non-qualified one.

But as the accompanying problem report suggests, this can cause issues
during the DWARF parsing.  This is because a given Debug Information
Entry (DIE) of qualified type kind can be referenced elsewhere, by
another type.  That other type expects that DIE to be a qualified
type.  And libabigail's DWARF reader code enforces that.  So the
internal representation of a type resulting from a qualified type DIE
must be a qualified type itself.

So the way the function "maybe_strip_qualification" was doing the
redundancy elision was wrong.  This patch fixes that by keeping the
type qualified, but introducing a "no-op" qualifier.  Actually, the IR
already has that "no-op" qualifier: abigail::ir::qualified_type_def::CV_NONE.

So now "maybe_strip_qualification" just turns the CV_CONST qualifier
into a CV_NONE one when the former is redundant.

Now that the libabigail type system actually *has* types qualified
with this no-op qualifier, we need to handle things like printing the
name of such qualified types.  When we are printing the name of the
type for internal reasons (i.e, for type canonicalization purposes) we
need to make a difference between the name of a no-op qualified type
and the name of the underlying type of the qualified type, otherwise,
the canonicalizer wrongly considers the two types as being equal.  But
then when we are printing the name of the no-op qualified type for
diagnostics reasons, then the name is the same as the name of its
underlying unqualified type.

	* src/abg-dwarf-reader.cc (maybe_strip_qualification): Do not nuke
	the qualified type.  Rather, just turn the redundant const
	qualifier into a no-op one.
	* src/abg-comparison.cc (compute_diff_for_types): Look through
	no-op qualified types.
	* include/abg-ir.h
	(decl_base::{peek,set}_temporary_qualified_name): Declare new
	accessors.
	* src/abg-ir.cc (decl_base::priv::temporary_qualified_name_): New
	data member.
	(decl_base::{peek,set}_temporary_qualified_name): Define new
	accessors.
	(qualified_type_def::priv::{temporary_internal_name_,
	internal_name}): New data members.
	(qualified_type_def::build_name): For a no-op qualified type, the
	internal name (which contains the 'none' qualifier) is different
	from the non-internal name.
	(qualified_type_def::get_qualified_name): Handle temporary names
	and non-temporary names in two different caches.  Also handle
	internal and non-internal names in two different caches.  This
	makes four different caches.
	(qualified_name_setter::do_update): Do not touch the non-internal,
	non-temporary qualified name cache if the qualified parent name is
	empty.
	* tools/abidw.cc (main): change --check-alternate-debug-info to
	make it *not* display the name/path to the alternate debug info,
	when it's found.  Rather, only
	--check-alternate-debug-info-base-name keeps displaying the base
	name of the alternate debug info.
	* tests/data/test-alt-dwarf-file/test1-libgromacs-debug-dir/*: New
	test material.
	* tests/data/Makefile.am: Add the new test material to the build
	system.
	* tests/test-alt-dwarf-file.cc (in_out_specs): Take the new test
	input into account.
	* tests/data/test-read-dwarf/test1.abi: Adjust.
	* tests/data/test-read-dwarf/test7.so.abi: Likewise.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
	* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
	* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
	* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
	* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
	* tests/data/test-read-dwarf/test17-pr19027.so.abi: Likewise.
	* tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi:
	Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-12-08 14:11:22 +01:00
Dodji Seketeli
1bee40c075 Do not forget to peel qualified type off when peeling types
When peeling off typedefs, references and pointers to see if a type is
made of a class type, we forget to peel qualified types off.

This is in the context of parsing type info from DWARF and to
determine if we should delay type canonicalization (because a given
type is made of a class) or not.

Fixed thus.

	* include/abg-fwd.h (peel_qualified_type): Declare new function
	...
	* src/abg-ir.cc (peel_qualified_type): ... and define it.
	(peel_typedef_pointer_or_reference_type): Peel qualified types
	here too.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-12-06 17:29:50 +01:00
Dodji Seketeli
35dd76bc69 Constify is_qualified_type()
* include/abg-fwd.h (is_qualified_type): Make this take a const
	parameter.
	* src/abg-ir.cc (is_qualified_type): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-12-06 17:12:43 +01:00
Dodji Seketeli
86ec69a86d Read enum values in the size_t and write them in ssize_t
Make sure to read enum values in the widest possible integer (size_t)
but write them (in abixml writer) using a signed type to ease
comparison.

This makes the runtestreaddwarf pass on 32 bit x86, because we were
losing some precision reading enum values using a signed integer.

	* include/abg-ir.h (enum_type_def::enumerator::get_value): Return
	a size_t.
	* src/abg-ir.cc (enum_type_decl::enumerator::get_value): Likewise.
	* src/abg-dwarf-reader.cc (die_signed_constant_attribute): #if-out
	this static function that is not used anymore.
	(build_enum_type): Read the value of the enumerator using a size_t
	value.
	* src/abg-reader.cc (build_enum_type_decl): Read the enum value
	using a long long int.
	* src/abg-writer.cc (write_enum_type_decl): Write using a ssize_t.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-11-17 16:01:23 +01:00
Dodji Seketeli
266fa9288e Add --version option to several libabigail tools
This patch changed the revision number of the libabigail library to
make it reflect the fact that we are not in "release candidate" mode,
before the first 1.0 release.  So the revision number is now "rc0".

The configuration manager has been updated to support version numbers
that are strings, so that it can supports things like "rc0".

Then, several libabigail tools have been modified to support the
--version option to display their version number.

	* configure.ac: Set the version revision to "rc0".
	* doc/manuals/abicompat.rst: Adjust manual for new --version
	option.
	* doc/manuals/abidiff.rst: Likewise.
	* doc/manuals/abidw.rst: Likewise.
	* doc/manuals/abilint.rst: Likewise.
	* doc/manuals/abipkgdiff.rst: Likewise.
	* include/abg-config.h (config::{m_format_minor, m_format_major}):
	Make these be strings.
	(config::{get,set}_format_minor_version_number): Make these return
	strings.
	(config::{get,set}_format_major_version_number): Make these return
	or take strings.
	(abigail_get_library_version): Make this take strings.
	* src/abg-config.cc (config::config): Adjust.
	(config::{get,set}_format_major_version_number): Make these return
	or take strings.
	(config::{get,set}_format_minor_version_number): Make these return
	strings.
	(abigail_get_library_version): Make this take strings.
	* include/abg-version.h.in: Make the version variables be strings.
	* src/abg-writer.cc (write_translation_unit): The version numbers
	are now strings so adjust.
	* tools/{abicompat,abidiff,abidw,abilint,abipkgdiff,abisym}.cc
	(options::display_version): New data member.
	(options::options): Initialize it.
	(display_usage): Add documentation for new --version option.
	(parse_command_line): Parse new --version option.
	(main): Support --version.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-11-16 12:54:10 +01:00
Dodji Seketeli
ba980025fb Bug 19173 - Abidiff doesn't detect symbol size change in library
It appears that libabigail does not represent the size of ELF symbols,
so it doesn't detect when a symbol size changes without impacting the
size of the type of said symbol, as described by debug info.

It appears that Address Sanitizer as implemented by Clang does change
the size of variable symbols when it instruments those variables.  And
of course, the size of type of said symbols (as described by debug
information) remains unchanged.

This patch makes Libabigail become aware of symbol sizes, especially
for variables.  Symbol sizes for functions are ignored for now,
because a change in a function symbol size is not an ABI change.

The patch makes libabigail detect and report symbol size changes for
variables, but looking at the ELF information, independently from the
debug information.

The patch adjusts the existing tests and adds a new test using the
binaries that were filed in the bug report.

	* include/abg-ir.h (elf_symbol::{elf_symbol, create}): Take a size
	parameter.
	(elf_symbol::{get,set}_size): New accessors.
	* src/abg-ir.cc (elf_symbol::priv::size_): New data member.
	(elf_symbol::priv::priv): Initialize it.
	(elf_symbol::{elf_symbol, create}) Take a size parameter.
	(textually_equals): Compare the size of variable symbols.
	(elf_symbol::{get, set}_size): New accessors.
	* src/abg-comparison.cc (maybe_report_diff_for_symbol): New static
	function.
	({function_decl_diff,var_diff}::report): Use it.
	* src/abg-dwarf-reader.cc (lookup_symbol_from_sysv_hash_tab)
	(lookup_symbol_from_gnu_hash_tab, lookup_symbol_from_symtab)
	(read_context::lookup_elf_symbol_from_index): Set the size of the
	elf symbols' internal representation.
	* src/abg-reader.cc (build_elf_symbol): Read the size attribute if
	present.
	* src/abg-writer.cc (write_elf_symbol): Write the size attribute
	for variable symbols, if it's not zero.
	* tests/data/test-diff-dwarf/test34-pr19173-libfoo.so: New test
	input binary.
	* tests/data/test-diff-dwarf/test34-pr19173-libfoo2.so: Likewise.
	* tests/data/test-diff-dwarf/test34-pr19173-libfoo-report-0.txt:
	New reference test output.
	* tests/data/Makefile.am: Add the new test input binaries to the
	build system.
	* tests/test-diff-dwarf.cc (in_out_specs): Add the new test input
	above to the test harness.
	* tests/data/test-diff-dwarf/test9-report.txt: Adjust.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt: Likewise.
	* tests/data/test-read-dwarf/test0.abi: Likewise.
	* tests/data/test-read-dwarf/test1.abi: Likewise.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
	* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
	* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
	* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
	* tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi: Likewise.
	* tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test21-pr19092.so.abi: Likewise.
	* tests/data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test6.so.abi: Likewise.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-11-07 23:22:18 +01:00
Dodji Seketeli
4adbafaa43 Pass a bunch of parameters by reference as they ought to be
* include/abg-ir.h (operator==): In the overload for
	elf_symbol_sptr, pass the parameters by reference.
	* src/abg-ir.cc (operator==): Do the same at definition site.
	* src/abg-comparison.cc (maybe_report_diff_for_member): Pass
	parameters by reference.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-11-07 23:22:17 +01:00
Dodji Seketeli
7b35e89315 Bug 19139 - DWARF reader doesn't handle garbage in function names
In this bug, the DWARF debug info of the binary (generated by Intel's
ICC compiler) has interesting constructs like:

     [ 6b5a0]    subprogram
		 decl_line            (data2) 787
		 decl_column          (data1) 15
		 decl_file            (data1) 46
		 declaration          (flag)
		 accessibility        (data1) public (1)
		 type                 (ref4) [ 6b56a]
		 prototyped           (flag)
		 name                 (string) "ldiv"
		 MIPS_linkage_name    (string) "ldiv"
     [ 6b5b6]      formal_parameter
		   type                 (ref4) [ 5f2aa]
		   name                 (string) "$Ë2"
     [ 6b5bf]      formal_parameter
		   type                 (ref4) [ 5f2aa]
		   name                 (string) "$Ë3"

Note the strings that make up the name of the formal parameters of the
function, near the end:

     [ 6b5b6]      formal_parameter
		   type                 (ref4) [ 5f2aa]
		   name                 (string) "$Ë2"
     [ 6b5bf]      formal_parameter
		   type                 (ref4) [ 5f2aa]
		   name                 (string) "$Ë3"

The strings "$Ë2" and $Ë3" (which are the names of the
parameters of the function) are garbage.

Libabigail's DWARF reader naively uses those strings as names for the
function parameters, in the type of the function.

Then, the abixml writer emits an XML document, with these strings as
property values, representing the name of the type of the function.

And of course, the XML later chokes when it tries to read that XML
document, saying that the property is not valid UTF-8.

This patch addresses the issue by dropping those garbage names on the
floor, for function type names.  In that context, any string that is
not made of ASCII characters is considered as being garbage, for now.

The patch, in the abixml writer, also escapes function parameters
names so that they don't contain characters that are not allowed in
XML.  The abixml reader already handles the un-escaping of the names
it reads, so I think there is nothing to do there.

Ultimately, I guess I should get the unicode value of the characters
of that string, encode the string into UTF-8 and use the result as the
name for the parameter.  That would mean using UTF-8 strings for
function parameter names, and, for all declarations names.  But that
is too much for worfk too little gain for now.  The great majority of
the binaries we are dealing with are still using ASCII for declaration
names.

The patch also introduces a new test harness that runs "abidw
--abidiff" on a bunch of input binaries.  This harness runs over the
binaries that were submitted in this bug report.

	* include/abg-tools-utils.h (string_is_ascii): Declare new
	function ...
	* src/abg-tools-utils.cc (string_is_ascii): ... and define it.
	* src/abg-writer.cc (write_function_type): Escape forbidden XML
	characters in function type names.
	* src/abg-dwarf-reader.cc (build_function_type):  If a parameter
	name is not ascii, drop it on the floor.
	* tests/data/test-types-stability/pr19139-DomainNeighborMapInst.o:
	New test input binary.
	* tests/data/test-types-stability/pr19202-libmpi_gpfs.so.5.0:
	Likewise.
	* tests/data/Makefile.am: Add the new binaries above to the build
	system.
	* tests/test-types-stability.cc: New test harness.
	* tests/Makefile.am: Add the new test harness to the build system.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-11-05 16:40:22 +01:00
Dodji Seketeli
089b3fc762 Support updating a class in the abixml reader
In DWARF, the same class declaration can be present several times but
with different "views", that is, it can be present in a first
translation unit, but without any member type; then in a subsequent
translation unit, its member types are defined.  In another, it'll be
completely defined, with all its data members and base classes.  The
DWARF reader knows how to amend the class to add new members to it, as
they show up in the debug information.

This patch adds the same functionality to the abixml reader.  The
writer has already started to write class declarations with different
"views" too, since it's started to avoid duplicating full class
definitions in every translation unit that uses them.

Without this patch, abixml misses some class members, and that is a
bug.

	* include/abg-ir.h (class_decl::{find_base_class,
	find_member_type, find_data_member}): Declare new member functions ..
	* src/abg-ir.cc (class_decl::{find_base_class,
	find_member_type, find_data_member}): ... and define them.
	* src/abg-reader.cc (build_class_decl): Add the ability to update
	a class to add new data members, member types and base classes to
	it, if necessary.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-17 16:09:50 +02:00
Dodji Seketeli
caaeaea10b Misc style cleanup
* include/abg-fwd.h: Remove unnecessary declaration of class
	parameter.
	* src/abg-ir.cc: Remove trailing space in a comment.
	* src/abg-reader.cc: Fix a comment.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-15 13:50:56 +02:00
Dodji Seketeli
093bc5da06 Pass some more parameters in reference
Profiling as shown that we might gain some precious cycles by passing
some well chosen parameters by reference.

	* include/abg-ir.h (operator==): For the type_base_sptr and
	decl_base_sptr overloads, pass the parameters by reference.
	({var,function}_decl::{set,get}_symbol): Pass the elf_symbol_ptr
	by reference.
	* src/abg-ir.cc (operator==): For the type_base_sptr and
	decl_base_sptr overloads, pass the parameters by reference, now in
	the definition.
	({var,function}_decl::{set,get}_symbol): Pass the elf_symbol_ptr
	by reference, now in the definition.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-15 13:50:55 +02:00
Dodji Seketeli
7bb65377a5 Accelerate a slow path in hash_type_or_decl()
Profiling shows that hash_type_or_decl() is very slow when hashing
function parameters and base class specifications.  This is because in
those two cases we use the slow recursive hashing algorithm to hash
types, rather than using the faster one based on using the pointer
values of canonical types when possible.

This was making corpora comparison very slow, as it uses
hash_type_or_decl() to hash diffs of ABI artifacts.

This patch fixes that.

	* include/abg-ir.h (is_function_parameter, is_class_base_spec):
	Declare new functions.
	* src/abg-ir.cc (is_function_parameter, is_class_base_spec):
	Define them.
	(hash_type_or_decl): Handle hashing of function parameters are
	class base specifications with the fast path of type hashing.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-15 13:50:48 +02:00
Dodji Seketeli
60425d2996 Implement fast type lookup in a corpus
Profiling has shown that on libraries with a lot of class types
declarations (more than 10K types), the phase of resolving those
declarations to their definition was a hot spot.  The lookup of the
type definition inside the entire corpus was the bottleneck.

This patch removes (or loosen) that bottleneck by doing away with the
graph-walking-based type lookup algorithm that was used.  Rather, maps
of name -> types are maintained by each scope, in each translation
unit. Those maps are updated each time a type is added to a scope.
And looking up a type amounts to a lookup in a map.  Way faster.

	* include/abg-fwd.h (components_to_type_name): Declare new
	function.
	* include/abg-ir.h (string_type_base_wptr_map_type): New typedef.
	(translation_unit::{get,set}_types): Declare new member functions.
	* src/abg-ir.cc (translation_unit::priv::types_): New data member.
	(translation_unit::{get,set}_types): Define these member
	functions.
	(maybe_update_types_lookup_map): Define new static function.
	(components_to_type_name): Define new function.
	(scope_decl::{add_member_decl, insert_member_decl}): Call the new
	maybe_update_types_lookup_map.
	(scope_decl::find_iterator_for_member): Fix logic.
	(class_decl::set_is_declaration_only): When a class declaration
	becomes a definition, update the name -> type map maintained in
	the scope of the class.
	(lookup_type_in_translation_unit): Use the hash map of qualified
	name -> types that is now maintained in the translation unit.
	This is way faster than the previous walking algorithm.
	* src/abg-dwarf-reader.cc (build_translation_unit_and_add_to_ir):
	When fixing up global variable declarations that need to be
	re-added to the translation unit, use the new fast type lookup
	function.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-15 13:50:48 +02:00
Dodji Seketeli
4b754229d1 Make canonicalization non sensitive to struct-ness of subtypes
In a previous patch, we made canonicalization independant from
struct-ness of class types.  This was in this commit:

    0e3416e Bug 19023 - Type canonicalization is sensitive to struct-ness

But then, that didn't handle the case of composite types which have a
subtype of class type T, where the same T was declared as "struct" and
as "class" in the same binary.

This patch handles that case by passing a flag to the functions that
build the pretty representation of types.  Note that the pretty
representation is used as a key in the hash map that contains
canonical types.  That flag is passed all the way down to the function
that builds the pretty representation for class types, which decides
to use either "struct" or "class" as a previx for the representation.

The type canonicalization code then passes that flag (properly set) to
the pretty representation function.

	* include/abg-fwd.h (get_type_name, get_function_type_name)
	(get_method_type_name, get_pretty_representation): Add an
	"internal" flag to all overoads.
	* include/abg-ir.h
	({type_or_decl_base, decl_base, type_decl, scope_type_decl,
	qualified_type_def, array_type_def, enum_type_decl, typedef_decl,
	var_decl, function_decl, function_decl::parameter, function_type,
	method_type, class_decl}::get_pretty_representation): Add an
	'internal' flag.
	({decl_base, qualified_type_def, pointer_type_def,
	reference_type_def, array_type_def, enum_type_decl::enumerator,
	function_decl::parameter}::get_qualified_name): Likewise.
	(qualified_type_def::build_name): Likewise.
	* src/abg-ir.cc ({decl_base, qualified_type_def, pointer_type_def,
	reference_type_def, array_type_def, enum_type_decl,
	enum_type_decl::enumerator,
	function_decl::parameter}::get_qualified_name): Take an "internal"
	flag.
	(qualified_type_def::build_name): Likewise.
	({decl_base, type_decl, namespace_decl, array_type_def,
	enum_type_decl, typedef_decl, var_decl, function_type,
	method_type, function_decl,
	class_decl}::get_pretty_representation): Likewise.
	(get_type_name, get_function_type_name, get_method_type_name)
	(get_pretty_representation): Likewise.
	(type_base::get_canonical_type_for): Call
	get_pretty_representation() with the "internal" flag set to
	"true", to get a pretty representation that is independant from
	the struct-ness of the subtypes of the type being canonicalized.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-15 13:50:48 +02:00
Dodji Seketeli
f1c48fe80f Handle aliased function decls when comparing decls in general
When comparing two declarations, we look at their linkage name. When
the linkage names are different, then we infer that the two decls are
different.

But then, for *function* decls, it can happen that two different
linkage names are actually for different symbols that do alias; the
(ELF) symbols are different but they have the same address; so they
point to the same "thing".  The two functions are not different, then.

And we were not supporting this last case of diffent linkage names
that are aliases of each other.

This patch adds support for that.

	* include/abg-ir.h (is_function_decl): Add a const to the
	reference parameter, making it comply with the definition.
	* src/abg-ir.cc (equals): In the overload for decl_base, when the
	two linkage names are different, consider the case of the decls
	being aliased functions.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-15 13:50:48 +02:00
Dodji Seketeli
1a6b957401 Fix const-ness of a function parameter
* include/abg-fwd.h (is_function_decl): Add a const to the
	parameter to make it comply with the definition in abg-ir.cc.
	Woops.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-15 13:50:48 +02:00
Dodji Seketeli
f95af3a89a Do not compare access specs for member types & functions
It turns that in some DWARF (e.g, from the r300_dri.so binary in bug
libabigail/19024) the same class Foo can be declared as a struct, and
later defined as a class.  Or the other way around.

In some cases, Foo can be declared as a struct, have a member type
Foo::Type with no access specifier, and later that member type is
still present with no access specifier when Foo is defined as a class.
So when comparing Foo::Type (from struct Foo) against Foo::Type (from
class Foo) we must not consider the access specification of Type,
otherwise, as in the first case it's 'public' and in the second case
it's 'private', the two member types would be considered different.

And something similar happens for member function declarations too.

This patch thus avoids comparing access specifiers for member types
and functions.  Though it can be considered as a regression compared
to what was being done before, access specifiers don't have an impact
on ABI per se.  And they can cause noise in the result, as we are
seeing here.

	* include/abg-fwd.h (is_function_decl): Declare a new overload.
	* src/abg-ir.cc (is_function_decl): Define a new overload.
	(equals): In the overload for decl_base, do not compare access
	specifiers when comparing member functions and types.
	* tests/data/test-diff-dwarf/test0-report.txt: Adjust.
	* tests/data/test-diff-filter/test0-report.txt: Likewise.
	* tests/data/test-diff-filter/test01-report.txt: Likewise.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt: Likewise.
	* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-0.txt: Likewise.
	* tests/data/test-diff-filter/test4-report.txt: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-15 13:50:48 +02:00
Dodji Seketeli
e9bdb488b3 Bug 19025 - abixml writer forgets to emit some member types
When a member type (a type that is a member of a class) M is
referenced by some types emitted by abixml, but the context of M (the
class type which M is a member of) is not itself referenced by any ABI
artifact, then abixml forgets to emit the context of M and thus M
itself.

With this patch, when the abixml writer has emitted almost all ABI
artifacts for the current translation unit, it looks for types that
have been referenced by the emitted ABI artifacts, but that haven't
been emitted themselves.

It then emits those referenced-but-not-emitted types, and makes sure
their contexts are emitted as well.

	* include/abg-fwd.h (is_namespace): Fix prototype.
	* src/abg-writer.cc (struct type_ptr_comp_functor): New internal
	type.
	(sort_type_ptr_map): New static function.
	(write_context::m_referenced_types_map): Renamed
	m_referenced_fntypes_map data member into this.
	(write_context::get_referenced_types): New member function.
	(write_context::record_type_as_referenced): Renamed
	record_fntype_as_referenced member function into this.  Adjust.
	(write_context::type_is_referenced): Renamed fntype_is_referenced
	into this.
	(write_context::clear_referenced_types_map): Renamed
	clear_referenced_fntypes_map member function into this.  Adjust.
	(write_decl_in_scope): New static function.
	(write_translation_unit): Use it here to emit types that are
	referenced by other types in the TU, but that are not emitted.
	Adjust.
	(write_pointer_type_def, write_reference_type_def)
	(write_typedef_decl): Record the underlying types referenced by
	the emitted types as being, well, referenced.
	* tests/data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so:
	New test binary input.
	* tests/data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi:
	New reference output of the binary input above.
	* tests/data/Makefile.am: Add the new test material above to the
	source distribution.
	* tests/test-read-dwarf.cc (in_out_spec): Add the new test inputs.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
	* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
	* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
	* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
	* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
	* tests/data/test-read-dwarf/test17-pr19027.so.abi: Likewise.
	* tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-08 13:50:49 +02:00
Dodji Seketeli
0e3416e7e2 Bug 19023 - Type canonicalization is sensitive to struct-ness
In some debug info of some shared library, the same type can be
present as a struct in some translation units, and as a class in
others.  As we are using the "pretty representation" of types to hash
types during type canonicalization, a "class foo" and "struct foo"
are (wrongly) considered different, because those pretty
representations are different.

This patch changes the canonicalization code to make it independent
from the struct-ness of the class being canonicalized.

	* include/abg-ir.h (class_decl::is_struct): Declare a setter for the
	"is-struct" property.
	* src/abg-ir.cc (class_decl::is_struct): And define that setter
	here.
	(type_base::get_canonical_type_for): Temporarily set the
	'is-struct' flag of the class type to 'false' before building its
	pretty representation.
	* tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so:
	New test input binary.
	* tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	New test reference output.
	* tests/data/Makefile.am: Add the new test material above to the
	source distribution.
	* tests/test-read-dwarf.cc (in_out_specs): Add the two new test
	inputs to the list of test inputs to consider.
	* tests/data/test-read-dwarf/test14-pr18893.so.abi: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-07 00:41:32 +02:00
Dodji Seketeli
48801d23e4 Bug 19037 - Make ABI corpus support several functions with same symbol
It turns out that, in DWARF, there can be function template
instantiations foo<int>(int) and foo<TypedefOfInt>(TypedefOfInt) which
have the same symbol name, if TypedefOfInt is a typedef of int.

An ABI corpus retains only one function declaration per symbol
name.  So in the example of the bug the input DWARF has the two
instantiations, but libabigail is just keeping one of the two; so the
abixml only has one of the two template instantiations.

This patch changes the ABI corpus model so that it represents the fact
that there can be several function declarations for a given symbol.
The patch then adjust the comparison engine to make it know about this
new model.

	* include/abg-corpus.h
	(corpus::exported_decls_builder::str_{fn,var}_ptr_map_type):
	Remove these typedefs from here as they only used internally in
	abg-corpus.cc.  So we move them there instead.
	* src/abg-corpus.cc (str_fn_ptrs_map_type): New typedef.
	(str_var_ptr_map_type): Moved the typedef that was in
	corpus::exported_decls_builder here.
	(corpus::exported_decls_builder::id_fns_map_): Rename the fns_
	data member into this.  Make it have a str_fn_ptrs_map_type as a
	type.
	(corpus::exported_decls_builder::id_fns_map): Renamed the
	fns_map() accessor into this one.
	(corpus::exported_decls_builder::{fn_id_is_in_id_fns_map,
	fn_is_in_fns}): New member functions.
	(corpus::exported_decls_builder::fn_is_in_id_fns_map): Rename
	fn_is_in_map into this.
	(corpus::exported_decls_builder::add_fn_to_id_fns_map): Rename
	add_fn_to_map into this.
	(corpus::exported_decls_builder::add_fn_to_exported): Adjust.
	(corpus::exported_decls_builder::maybe_add_fn_to_exported_fns):
	Adjust.
	* src/abg-comparison.cc (function_decl_diff::report): Emit reports
	about function name changes (for a given function ID) only if
	there are sub-type changes to be reported for the function.  In
	that case, do not forget to emit the sub-type changes after the
	name changes have been reported.
	(corpus_diff::priv::ensure_lookup_tables_populated): Several
	functions of the same ID can be removed or added from/to the
	corpus.
	* tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so:
	New test input binary.
	* tests/data/test-read-dwarf/test18-pr19037-libvtkRenderingLIC-6.1.so.abi:
	New test output reference.
	* tests/data/Makefile.am: Add the new test materials to the source
	distribution.
	* tests/test-read-dwarf.cc (in_out_specs): Adjust to add the new
	test inputs above.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-06 13:32:12 +02:00
Dodji Seketeli
9a0abd846b Use the ODR to speed up type canonicalization
This is the last patch of the series of 11 patches that started at the
patch with the subject:

    constify is_class_type()

And below starts the cover letter of this patch.

While analyzing some libraries like libmozjs.so[1] it appeared that
type canonicalization takes a significant time to comparing composite
types that are re-defined in each translation units again and again.

The One Definition Rule[2] says that two types with the same name
shall designate the same thing; so when a type T being canonicalized
has the same name of a canonical type C in the same ABI corpus, then
this patch considers C as being the canonical type of T, without
comparing T and C structurally.  This saves us from comparing T and C.

Before this patch, `abidw --noout libmozjs.so` was taking
approximatively 5 minutes; with the patch, it takes 1 minutes and 30
seconds.

To do this, the patch changes ABI artifacts to carry a pointer to the
corpus it belongs to.  Whenever an ABI artifact is added to a given
context, the corpus of that context is propagated to the artifact;
that is now possible as the artifact now carries the property of the
corpus it belongs to.

During type canonicalization the ODR-based optimization outlined above
is performed as we can now compare the corpus of a given type again
the one of another type; it's now possible to know if two types come
from the same corpus.

There are a few cases though were the optimization is not performed:
  - anonymous struct; when a struct is anonymous (it has no name, as
    described in the DWARF), the DWARF reader gives it a name
    nonetheless, so that diagnostics can refer to that anonymous type.
    But then all anonymous types in the system have the same name.  So
    when faced with two anonymous types (with the same name) from the
    same corpus, it's wrong to consider that they name the same thing.
    The patch added an "is_anonymous" property to types created by the
    DWARF reader so that such anonymous types can be detected by the
    type canonicalizer; they are thus not involved in this
    optimization.  Note that the abixml writer and reader have been
    updated to emit and read this property.
  - typedefs.  I have seen in some boost code two typedefs of the same
    name refer to different underlying types.  I believe this is a
    violation of ODR.  I'll need to investigate on this later.  And I
    think we really need to detect these ODR violations as part of
    this enhancement request:
    https://sourceware.org/bugzilla/show_bug.cgi?id=18941.
  - pointers, references, arrays and function types, as they can refer
    to the two exceptions above.

This is the last patch of the series which aimed at speeding up type
canonicalization in the context of types being re-defined a lot in
translation units.

[1]: Instruction to build libmozjs.so from the mongodb sources:
	- git clone https://github.com/mongodb/mongo.git
	- cd mongo
	- scons --link-model=dynamic build/opt/third_party/mozjs-38/libmozjs.so

[2] One Definition Rule: https://en.wikipedia.org/wiki/One_Definition_Rule

	* include/abg-fwd.h (class corpus): Forward-declare this.
	(is_anonymous_type): Declare this new function.
	* include/abg-ir.h (corpus_sptr, corpus_wptr): Declare these
	typedefs here too.
	(translation_unit::{g,s}et_corpus): Declare new member functions.
	(type_or_decl_base::{g,s}et_corpus): Likewise.
	* src/abg-ir.cc (translation_unit::priv::corpus): New data member.
	(translation_unit::priv::priv): Initialize it.
	(translation_unit::{g,s}et_corpus): Define new accessors.
	(translation_unit::get_global_scope): Propagate the corpus of the
	translation unit to its newly created global scope.
	(translation_unit::bind_function_type_life_time): Propagate the
	corpus of the translation_unit to the added function type.
	(type_or_decl_base::priv::corpus_): Add new data member.
	(type_or_decl_base::priv::priv): Initialize it.
	(type_or_decl_base::{g,s}et_corpus): Define new accessors.
	(scope_decl::{add,insert}_member_decl): Propagate the context's
	corpus to the member added to the context.
	(decl_base::priv::is_anonymous_): Add new data member.
	(decl_base::priv::priv): Initialize it.
	(decl_base::{s,g}et_is_anonymous): Define accessors.
	(is_anonymous_type): Define a new test function.
	(decl_base::set_name): Update the "is_anonymous" property.
	(type_base::get_canonical_type_for): Implement the ODR-based
	optimization to type canonicalization.
	* src/abg-corpus.cc (corpus::add): When a translation unit is
	added to a corpus, set the corpus of the translation unit.
	* src/abg-dwarf-reader.cc (build_enum_type)
	(build_class_type_and_add_to_ir): Set the "is_anonymous" flag on
	anonymous enums and classes.
	* src/abg-reader.cc (read_is_anonymous): Define new static
	function.
	(build_type_decl, build_enum_type, build_class_decl): Call the new
	read_is_anonymous function and set the "is_anonymous" property on
	the built type declaration.
	* src/abg-writer.cc (write_is_anonymous): Define new static
	function.
	(write_type_decl, write_enum_type_decl, write_class_decl): Write
	the "is_anonymous" property.
	* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-0.txt:
	Adjust.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
	* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
	* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
	* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
	* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
	* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
	* tests/data/test-read-dwarf/test17-pr19027.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-04 13:52:25 +02:00
Dodji Seketeli
6e36a4381d Late canonicalize all types that reference classes when reading DWARF
Until now, the DWARF reader would late canonicalize typedefs to
classes, as well as classes.  That is not enough.  Let's also
late-canonicalize pointers, references and array of classes too.  This
is because classes that might not be finished yet might be referenced
by those types, and so we want to wait until they are finished before
we canonicalize them.

	* include/abg-fwd.h (peel_array_type): Declare new function.
	* src/abg-ir.cc (peel_array_type): Define it.
	(peel_typedef_pointer_or_reference_type): Peel arrays too, to get
	the type of its element.
	* src/abg-dwarf-reader.cc (maybe_canonicalize_type): If a pointer,
	reference, array or typedef references a class, then do
	late-canonicalize this type.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-04 13:51:25 +02:00
Dodji Seketeli
38e17e0e07 Cleanup some IR type comparison operators
* include/abg-ir.h (operator==): In the overloads for type_decl,
	enum and class_decl, turn the shared_ptr parameter into a const
	reference to the shared_ptr.
	* src/abg-ir.cc (operator==): Do the same in the definitions.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-04 13:51:24 +02:00
Dodji Seketeli
da4aaf467a Add missing deep equality operator for pointer and reference types
I noticed that abigail::ir::pointer_type_def_sptr and
abigail::ir::reference_type_def_sptr did not have any free form
operator '==' defined.  So writing a == b with a and b being either
pointer_type_def_sptr or reference_type_def_sptr was using pointer
value comparison, as opposed to deeply comparing the pointer and
reference instances.

This patch adds those two missing operators.

	* include/abg-ir.h (pointer_type_def::operator==): Add an overload
	for pointer_type_def.
	(reference_type_def::operator==) Add an overload for
	reference_type_def.
	(operator==): Add an overload for pointer_type_def_sptr and
	reference_type_def_sptr.
	* src/abg-ir.cc (pointer_type_def::operator==): Make the overload
	for type_base& use the overload for decl_base&.  Add a new
	overload for pointer_type_def& and make is use the overload for
	decl_base& too.
	(operator==): Add free form overloads for pointer_type_def& and
	reference_type_def&.
	(reference_type_def::operator==): Add comments. Add an overload
	for reference_type_def&.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-04 13:51:24 +02:00
Dodji Seketeli
db02f0bdb4 constify is_class_type()
This the first patch of a series of 11 patches which aims at speeding
up the time taken by "abidw --noout libmozjs.so".  That shared library
is built among by the mongodb project, among others.  And abidw is
taking around 5 minutes on my old Lenovo X220 laptop.  After the
series of patches, the same command is taking one minute and a half.

The core of the optimization is to speed up type canonicalization that
happens at the end of DWARF reading, once libabigail has built the IR
or the ABI of the entire elf binary.  The optimization comes from an
insight derived from the One Definition Rule of C++, as explained at
https://en.wikipedia.org/wiki/One_Definition_Rule.

But before being able to perform that optimization, several fixes and
code massaging were necessary.  I have split those changes up in the
first 10 patches of the series.  The last patch thus contains the crux
of the optimization.  Its cover letter also contains instructions on
how to build libmozjs.so, from mongodb, for those who want to
replicate the results I have seen.

Note that some of the first 10 patches incur adjustment in the test
suite, but don't carry those necessary adjustments.  All test suite
adjustments are carried by the last, 11Th patch.

The short description of the patches of the series are:

    constify is_class_type()
    Add missing deep equality operator for pointer and reference types
    Cleanup some IR type comparison operators
    Do not overly canonicalize types during typedef stripping
    Fix detection of changes in pointer diff in the comparison engine
    Prevent build_function_type from not canonicalizing certain types
    Do not use recursive type hashing when writing out function types
    Try harder to hash_type_or_decl avoid the slow path
    Fix infinite loop in peel_typedef_pointer_or_reference_type
    Late canonicalize all types that reference classes when reading DWARF
    Use the ODR to speed up type canonicalization

And below is the ChangeLog of this first patch.

	* include/abg-fwd.h (is_class_type): Take a pointer to const.
	* src/abg-ir.cc (is_class_type): Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-04 13:40:51 +02:00
Ondrej Oprala
9cb146a013 Bug 17340 - Support pointers and references to functions
* include/abg-comparison.h (compute_diff_for_distinct_kinds): Take the
	first two arguments of type const type_or_decl_base_sptr instead.
	* include/abg-ir.h (translation_unit::get_function_types): Declare new
	method.
	(function_types): Declare new typedef.
	* src/abg-comparison.cc (compute_diff_for_types): Take the first two
	arguments of type const type_or_decl_base_sptr instead of a const
	decl_base_sptr.
	(try_to_diff): Likewise.
	(try_to_diff<class_decl>): Likewise.
	(try_to_diff_distinct_kinds): Likewise.
	(compute_diff_for_distinct_kinds): Likewise. Also remove a variant
	accepting arguments of type const type_base_sptr.
	* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): Skip
	building a pointer if it points to the beginning of a vptr.
	(build_pointer_type_def): Declare utype_decl of type
	type_or_decl_base_sptr and adjust assignments to it accordingly.
	(build_function_type): New function definition.
	(build_function_decl): Call build_function_type instead of building
	an ftype manually.
	(build_ir_node_from_die): Amend case DW_TAG_subroutine_type with
	appropriate calls to build a function type.
	* src/abg-ir.cc (translation_unit::get_function_types): New method
	definition.
	({pointer,reference}_type_def::pointer_type_def): Expect that
	pointed_to might not have an accompanying declaration and set a type's
	name in this case as well.
	({pointer,reference}_type_def::get_qualified_name): Generate a
	qualified name even if the pointed-to type has no declaration.
	* src/abg-reader.cc (build_function_type): New function definition.
	(handle_element_node): Return a type_or_decl_base_sptr instead and
	try calling handle_function_type in addition to others.
	(handle_function_type): New function definition that calls
	build_function_type.
	(build_type): Try calling build_function_type as well.
	* src/abg-writer.cc (fn_shared_ptr_map): Declare new typedef.
	(write_context::{clear_referenced_fntypes_map,fntype_is_referenced,
	record_fntype_as_referenced}): New member functions.
	(write_translation_unit): Call the new clear_referenced_fntypes_map.
	* tests/data/Makefile.am: Add the new test material to the build
        system.
	(write_translation_unit): Separately write function types that have
	been recorded to emit by write_{pointer,reference}_type_def.
	(write_{pointer,reference}_type_def): Record the type pointed to as
	a type to be emitted if type == function type.
	(write_function_type): Write the details of a function type in the
	abixml format and unmark the type.
	* tests/data/test-diff-dwarf/test32-fnptr-changes-report-0.txt: New
	test reference report.
	* tests/data/test-diff-dwarf/test32-fnptr-changes-v{0,1}.cc: New test
	source files.
	* tests/data/test-diff-dwarf/test32-fnptr-changes-v{0,1}.o: New binary
	test inputs.
	* tests/data/test-diff-dwarf/test33-fnref-changes-report-0.txt: New
	test reference report.
	* tests/data/test-diff-dwarf/test33-fnref-changes-v{0,1}.cc: New test
	source files.
	* tests/data/test-diff-dwarf/test33-fnref-changes-v{0,1}.o: New binary
	test inputs.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt:
	Adjust.
	* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-0.txt:
	Likewise.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
	* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
	* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
	* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
	* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
	* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
	* tests/data/test-read-write/test27.xml: New test source file.
	* tests/test-diff-dwarf.cc: Adjust to launch the new tests.
	* tests/test-read-write.cc: Likewise.

Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
2015-09-30 21:20:42 +02:00
Ondrej Oprala
4ec793b9d0 Move a constructor declaration
* include/abg-ir.h (decl_base): Change the decl_base() declaration's
	visibility to private.

Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
2015-09-29 11:26:08 +02:00
Dodji Seketeli
4173b2a421 Add a missing function declaration
* include/abg-tools-utils.h (dir_name): Add missing function
	declaration.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-21 15:22:35 +02:00
Dodji Seketeli
912eb7e36b Speed up type canonicalization by avoiding recursive hashing
Recursive type hashing was showing up as the major hot spot of
performance profiles.  After spending a few days on trying to speed it
up, I have officially declared recursive tree node hashing as a slow
process and I am giving up.

I have thus decided to not use that at type canonicalization time.

Rather, I am proposing a new type canonicalization routine where types
are first hashed by hashing their pretty representation string.

Basically, if T is the total number of types in the system and C the
number of classes of equivalences (or the number of canonical types),
the number of type comparisons done by a naive type canonicalization
routine is N x C.  With the worse C being equal to N itself, that
worse number of comparisons is N*N.

By using a hash table to store the canonical types, keyed by a hash of
their pretty representation string, the number of type comparisons can
be brought down to N*P, where P is a the greater number of which
pretty representation string hash collide.  That number P is usually
small; my measurements show that N usually goes from 1 to 3.  And
moreover, computing the hash of the pretty representation string of
the function is way faster than using the recursive type hash!

As a result, running abidw on the libcilkrts.so library, from GCC goes
from 12 minutes to 0.4 seconds!

Incidentally, now that we are not trying to speed up the recursive
type hashing process, all the complicated business we had around
caching the result of the hashing is gone!  I was thinking that hash
cashing was inherently a bad idea, especially for recursive types --
that refer to themselves directly or indirectly, because in those
case, depending on when you cached the hash value, the value of the
hashing can be different.

The abixml writer's code doesn't use the recursive type hash anymore
either; it uses the pointer value of the canonical type as hash.
Super fast too!

The patch had to fix pieces here and there to comply with the fact
that canonical types are now used across the board in a mandatory
fashion.

	* include/abg-ir.h (canonical_types_map_type): Adjust this typedef
	to make it point to an unordered_map which the key is now a string
	and the value is a vector of types.
	(type_or_decl_base::{get_cached_hash_value, set_cached_hash_value,
	cached_hash}): Remove these member functions and type.
	(struct type_base::cached_hash): Remove.
	* src/abg-ir.cc (struct type_or_decl_base::priv::hash_): Remove.
	(type_or_decl_base::priv::priv): Adjust.
	(type_or_decl_base::{g,s}et_cached_hash_value): Remove.
	(type_base::get_canonical_type_for): For declaration-only classes,
	look at their definition for the canonical_type.  Do not use
	recursive type hashing anymore.  Rather, use the pretty
	representation string, and hash that.
	(class_decl::base_spec::get_hash): Do away with hash value caching
	here.
	(class_decl::operator==): For decl-only classes, look at their
	definitions for canonical types.
	(hash_type_or_decl): Adjust comment.  Use the canonical type
	pointer value for type hash.  That's the fast path.  Otherwise, if
	not available, fall back to a slow path which is the recursive
	type hash we were using before.
	* src/abg-dwarf-reader.cc (maybe_canonicalize_type): Schedule all
	classes and typedef to classes for late canonicalization.
	* src/abg-hash.cc (type_base::dynamic_hash::operator()): There is
	no hash value cashing anymore.
	(type_base::cached_hash::operator()): Remove.
	* src/abg-reader.cc (read_context::get_type): Slight style
	adjustment.
	(read_translation_unit_from_file)
	(read_translation_unit_from_buffer): Do not forget to canonicalize
	types when reading just one translation unit.
	(build_type_tparameter, build_template_tparameter): Canonicalize
	the type.
	* src/abg-writer.cc (struct type_hasher): New hasher type.
	(type_ptr_map): Use a deep pointer comparison equal operator
	functor, and canonical types as type hash values.
	(write_class_decl): Do not write size and alignment on decl-only
	classes.  Do not record decl-only classes as being emitted.  Their
	definition must be emitted before.
	* tests/test-read-write.cc (main): Do not do abi testing on
	translation units (as opposed to doing it on abi corpora) as that
	code is not wet yet.  We need to know how to diff namespaces.
	* tests/data/test-abidiff/test-PR18791-report0.txt: Adjust.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
	* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
	* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
	* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
	* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-21 13:51:31 +02:00
Dodji Seketeli
3e146f14ba Update qualified name of a decl when it's added to its context
The building of the qualified name of a declaration is showing up in
performance profile as a hot spot.  This patch addresses that
performance issue by updating the qualified name of a declaration
whenever the declaration is added to its context and saving the
result.  Getting the qualified name later is just a matter of a string
copy.  I guess we can do something about those string copies later as
they don't show up high performance profiles at the moment.

	* include/abg-ir.h (decl_base::priv_): Make this be public, so
	that the qualified name updater function can access it.
	(class class_decl): Make set_member_is_static() a friend function.
	* src/abg-ir.cc (class ::qualified_name_setter): New tree walking
	type.
	(decl_base::get_qualified_parent_name): Do not do any computation
	here.  Just return the pre-computed qualified parent name string.
	(decl_base::get_qualified_name): Likewise, for qualified name.
	(scope_decl::{add,insert}_member_decl): Update the qualified name of the
	newly added member.  Set the scope of the member here.  It's not
	going to be set elsewhere, from now on.
	(add_decl_to_scope): Do not set the scope here anymore.  Just call
	scope_decl::add_member_decl and let it do the work.
	(insert_decl_into_scope): Likewise, just call
	scope_decl::insert_member_decl and let it do the work.
	(class_decl::{add_data_member, add_member_function}): Do not
	handle details of context setting at this point.  Let
	scope_decl::add_member_decl do it.  Adjust the properties of the
	context relation afterwards.  In add_data_member, when a data
	member changes its static-ness, move the data member into the
	class_decl::priv::non_static_data_members_ or out of it, as
	necessary.
	(class_decl::insert_member_decl): By default, a data member is
	considered static.
	(set_member_is_static): Move this definition after the definitions
	of class_decl, so that this function can see those.  Also, when a
	data member changes its static-ness, move the data member into the
	class_decl::priv::non_static_data_members_ or out of it, as
	necessary.
	(class_decl::add_member_function_template):  As we the
	underlying function template decl to the context, do not do any
	scope adding for it here.
	(::qualified_name_setter::{do_update, visit_begin}): Define new
	member functions.
	(update_qualified_name): Define new static function.
	* src/abg-reader.cc (build_class_decl): Make build_function_decl,
	build_var_decl, build_function_tdecl and build_class_tdecl
	automatically add the created decl to their context, and then
	update the properties of the resulting member decl later, just
	like what we do in the DWARF reader.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-21 12:58:06 +02:00
Dodji Seketeli
0cc38b2327 Add new test functions
This patch adds a new set of test functions that are going to be used
in subsequent patches to come.

	* include/abg-fwd.h (is_function_decl, is_decl, is_namespace)
	(is_scope_decl): Declare new function overloads.
	* src/abg-ir.cc (is_function_decl, is_decl, is_namespace)
	(is_scope_decl): Define them.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-21 10:53:33 +02:00
Dodji Seketeli
46c263fbae Constify some diff-utils functor operators
* include/abg-diff-utils.h (deep_ptr_eq_functor::operator()): Make
	the overloads be const.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-21 10:46:06 +02:00
Dodji Seketeli
16299395d7 Support source_location_not_in and source_location_not_regexp suppressions
This patch adds support for properties source_location_not_in and
source_location_not_regexp in the [suppress_type] section of
suppression specifications.  So the suppression specification:

  [suppress_type]
    source_location_not_in = foo1.h, foo2.h bar1.h bar2.h

suppresses ABI change reports about types that are *NOT* defined in
files foo{1,2}.h and bar{1,2}.h.  The intended use of this construct is to
constrain abi change reports to types that are part of the API of a
given shared library.  The API of the library is supposed to be
defined in foo.h and bar.h only.

Similarly, the suppression specification:

  [suppress_type]
    source_location_not_regexp = (foo|bar){1,2}\\.h

suppresses ABI change reports about types that are not defined in the
same set of files foo1.h, foo2.h, bar1.h and bar2.h.

	* include/abg-ini.h (enum property_value::value_kind): Add a
	LIST_PROPERTY_VALUE kind.
	(class {list_property_value, list_property}): Declare new types.
	(is_list_property, is_list_property_value): Declare new functions.
	* src/abg-ini.cc (struct list_property_value::priv): Define new
	type.
	(list_property_value::{list_property_value, get_content,
	set_content, as_string}): Define new member functions.
	(is_list_property_value): Define new function.
	(struct list_property::priv): Define new type.
	(list_property::{list_property, get_value, set_value,
	handle_escape}): Define new member functions.
	(is_list_property): Define new function.
	(read_context::buf_): New data member.
	(read_context::{peek, get, put_back, good, eof, read_string,
	read_list_property_value}): New member functions.
	(read_context::read_next_char): Use the new read_context::{get,
	good, eof} member function, rather than using the input stream
	directly.
	(read_context::{skip_white_spaces, skip_comments,
	skip_white_spaces_or_comments, read_property_name,
	read_function_name, read_function_argument,
	read_function_call_expr, read_property_value,
	read_tuple_property_value, read_section_name, read_section}):
	Adjust to use the new member functions of read_context rather than
	using the input stream directly.
	(read_context::read_string_property_value): Likewise.  Use the new
	read_context::read_string() method.
	(read_context::{read, write}_property): Support reading list_property.
	* include/abg-comparison.h
	(type_suppression::{get_source_locations_to_keep,
	set_source_locations_to_keep,
	set_source_location_to_keep_regex_str,
	get_source_location_to_keep_regex_str}): Add new member functions.
	* src/abg-comparison.cc
	(type_suppression::priv::{source_location_to_keep_,
	source_location_to_keep_regex_str_,
	source_location_to_keep_regex_}): Add new data members.
	(type_suppression::priv::{g,s}et_source_location_to_keep_regex):
	Define new member functions.
	(type_suppression::{g,s}et_source_locations_to_keep): Define new
	member functions.
	(type_suppression::{g,s}et_source_location_to_keep_regex_str):
	Likewise.
	(type_suppression::suppresses_type): Support
	"source_location_not_regexp" and "source_location_not_in"
	properties of suppression specifications.
	(read_type_suppression): Likewise. Also adjust to the fact that
	ta tuple property value that is a list of strings is not a list
	property value.
	* doc/manuals/libabigail-concepts.rst: Add documentation for
	source_location_not_in and source_location_not_regexp.
	* tests/data/test-diff-suppr/libtest26-loc-suppr-v{0,1}.so: New
	binary test inputs.
	* tests/data/test-diff-suppr/test26-loc-suppr-{0,1,2}.suppr: New
	suppression specification test inputs.
	* tests/data/test-diff-suppr/test26-loc-suppr-report-{0,1,2,3}.txt:
	New test reference reports.
	* tests/data/test-diff-suppr/test26-loc-suppr-v{0,1}.cc: Source
	code of the test binary input above.
	* tests/data/test-diff-suppr/test26-loc-suppr.h: Likewise.
	* tests/data/Makefile.am: Add the new test material to source
	distribution.
	* tests/test-diff-suppr.cc (in_out_specs): Add the new test inputs above.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-16 20:54:40 +02:00
Dodji Seketeli
110494af94 Pass simple property data by reference
* include/abg-ini.h (simple_property::{simple_property,
	set_value}): Pass the value shared pointer by reference.
	* src/abg-ini.cc (simple_property::{simple_property, set_value):
	Pass the value shared pointer by reference.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-16 18:48:54 +02:00
Dodji Seketeli
a717ca6faf Adjust {s,g}et_show_stats() to use a reference
* include/abg-dwarf-reader.h ({s,g}et_show_stats): Use a reference
	to the reader.
	* tools/abidiff.cc (main): Adjust.
	* tools/abidw.cc (main): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-07 23:42:17 +02:00
Dodji Seketeli
b2e5366d3f Introduce the concept of environment
There are resources needed by the type system and other artifacts of
libabigail.  Today, when the life time of those resources need to be
greater than all of artifacts of Abigail, then said resources are made
global.

But then global resources are not great, if anything because they
complicate the future use of the library in concurrent computing
setups.

As I was in the need to add one resource to be used by the type
system, I decided to sit down and first overhaul how these long lived
resources needed to be handled.

And here comes the concept of "environment".  An environment is a
place where one can put resources that need to live longer than all
the other artifacts of the Abigail system.  And so, the code that
creates Abigail artifacts needs and environment of for said artifacts
to use.  In other words, artifacts now use an environment.

This has interesting and strong implications.  We can only compare two
artifacts if they use the same environment.  This is quite a strong
requirement.

But then when this requirement is fulfilled, comparing two types
amounts to just comparing two pointer values; hash values for types
can also be cached.  Now *that* is great for speed of comparison, is
it not?

This patch introduce the concept environment (which is basically a new
abigail::ir::environment type), removes the global variables and uses
the environment instead.  Each ABI artifact (either type or decl) now
has a ::get_environment() member function to get its environment.

This patch also disables the caching of hash values because the
caching must happen only *after* all types have been canonicalized.
We were not respecting that requirement until now, and that introduces
wrong hash values.  A subsequent patch is going to re-introduce hash
value caching again, once the infrastructure is in place to set a flag
in the environment (hah!) once type canonicalization is done, and then
later read that flag when some client code requests a hash value, to
know if we should look in the hash value cache or not.

The patch obviously changes the output of numerous regression tests
(if anything b/c it disables hash value caching) so 'make check'
yields regressions.  But then, it's only the subsequent patch that
updates the tests.

	* include/abg-ir.h: Adjust note about memory management.
	(class environment): Declare new class.
	(translation_unit::translation_unit): Take an environment in
	parameter.
	(translation_unit::{g,s}et_environment): Declare new member
	functions.
	(type_or_decl_base::{g,s}et_environment): Likewise.
	(type_or_decl_base::{get_cached_hash_value,
	set_cached_hash_value}): Change the name of
	decl_base::peek_hash_value() and decl_base::set_hash() here into
	these and move them here.
	(type_or_decl_base::hashing_started): Move
	decl_base::hashing_started() here.
	({g,s}et_environment_for_artifact): Declare new functions.
	(class decl_base): Move member functions hashing_started(),
	peek_hash_value() and set_hash() on to the type_or_decl_base base
	class.
	(scope_decl::scope_decl): Initialize the virtual member
	type_or_decl_base().
	(type_decl::{get_void_type_decl,
	get_variadic_parameter_type_decl}): Remove these static member
	functions.  They are now non-static member functions of the new
	environment type.
	* src/abg-ir.cc (class environment_setter): New internal class.
	(get_canonical_types_map): Remove.  This now becomes a member
	function of the environment type.
	(class usage_watchdog): Remove.
	(usage_watchdog_{s,w}ptr): Remove these typedefs.
	(get_usage_watchdog_wptr, ref_usage_watchdog)
	(maybe_cleanup_type_system_data): Remove these functions.
	(translation_unit::priv::usage_watchdog_): Remove data member.
	(translation_unit::priv::env_): New data member.
	(translation_unit::priv::priv): Take an environment and initialize
	the new env_ data member.  Do not initialize the removed
	usage_watchdog_.
	(translation_unit::translation_unit): Take an environment
	parameter.
	(translation_unit::get_global_scope): Set the environment of a new
	global scope.
	(translation_unit::{g,s}et_environment): New accessors.
	(translation_unit::bind_function_type_life_time): Set the
	environment of the function type.
	(struct environment::priv): New class.
	(environment::{environment, ~environment, get_canonical_types_map,
	get_variadic_parameter_type_decl, canonicalization_is_done}): New
	member functions.
	(struct type_or_decl_base::priv): New class.
	(type_or_decl_base::{type_or_decl_base, hashing_started,
	get_cached_hash_value, set_cached_hash_value, set_environment,
	get_environment, traverse}): New member functions.
	({s,g}get_environment_for_artifact): New functions.
	(decl_base::priv::{hash_, hashing_started}): Remove.
	(decl_base::priv::priv): Adjust.
	(decl_base::decl_base): In the copy constructor, initialize the
	virtual base type_or_decl_base.  Do not initialize hash_ and
	hashing_started data member that got removed.
	(decl_base::{hashing_started, peek_hash_value, set_hash}): Remove
	member functions.
	(strip_typedef): Set the environment of the new type which has its
	typedefs stripped off.  Adjust the call to type_or_void().
	(scope_decl::{add, insert}_member_decl): Set the environment of
	the new member decl to the environment of its scope.
	(synthesize_type_from_translation_unit)
	(synthesize_function_type_from_translation_unit): Set the
	environment for the newly synthesized type. Adjust calls to
	type_or_void().
	(type_or_void): Take an environment in parameter.  Get the void
	type from the environment.
	(get_canonical_types_map): Remove.
	(type_base::get_canonical_type_for): Get the canonical types map
	from the environment, not from a global variable.
	(type_decl::{get_void_type_decl,
	get_variadic_parameter_type_decl}): Remove.
	(pointer_type_def::pointer_type_def): Adjust call to type_or_void.
	(reference_type_def::reference_type_def): Likewise.
	(function_decl::parameter::get_pretty_representation): Get the
	variadic parameter type decl from the environment.
	(class_decl::priv::classes_being_compared_): Remove static data
	member.
	(class_decl::priv::{mark_as_being_compared,
	unmark_as_being_compared, comparison_started): Use the "classes
	being compared" map from the environment.
	(class_decl::base_spec::get_hash): Adjust.
	(keep_type_alive): Get the alive types array from the environment)
	not from a global variable anymore.
	(get_next_string): Put the counter in thread-local storage.
	* src/abg-hash.cc (scope_decl:#️⃣:operator())
	(function_decl:#️⃣:operator()): Do not handle caching (here).
	* include/abg-corpus.h (corpus::{g,s}et_environment): Declare new
	accessors.
	* src/abg-corpus.cc (corpus::priv::env): New data member.
	(corpus::priv::priv): Initialize it.
	(corpus::corpus):  Take an environment in parameter.
	(corpus::{g,s}et_environment): Define new member functions
	(corpus::add): Set the environment of the newly added translation
	unit, if it's not set already set.  In any case, assert that the
	translation unit must use the same environment as the corpus.
	* include/abg-dwarf-reader.h (create_read_context)
	(read_corpus_from_elf): Take an environment parameter.
	({s,g}et_debug_info_root_path, {s,g}et_environment): Declare new
	functions.
	* src/abg-dwarf-reader.cc (read_context::{env_,
	offline_callbacks_}): New data members.
	(read_context::read_context): Initialize them.
	(read_context::clear_per_translation_unit_data): Do not touch the
	void type declaration, it doesn't belong to the translation unit.
	(read_context::{env, offline_callbacks}): New accessors.
	(read_context::{create_default_dwfl}): New member function.
	(read_context::dwfl_handle): Add a setter overload.
	({s,g}et_debug_info_root_path): Define new accessors.
	(create_default_dwfl, create_dwfl_sptr, create_default_dwfl_sptr):
	Remove these.
	(build_translation_unit_and_add_to_ir): Adjust to pass the
	environment to the newly created translation unit.
	(build_function_decl): Adjust to pass the environment to the
	created function and parameter types.  Get variadic parameter type
	node from the current environment, not from a global variable.
	And do not try to canonicalize function types here.
	(read_debug_info_into_corpus): Set the environment of the newly
	created corpus.
	(build_ir_node_for_void_type): Get the void type node from the
	current environment, rather than from a global variable.
	(create_read_context): Take the environment in parameter.
	Create the default dwarf front end library handle using the new
	member function of the read context.  Set the current environment
	used by the reader.
	(read_corpus_from_elf): Take an environment in
	parameter. Overhaul.  This is now simpler.
	(has_alt_debug_info): Adjust the call to create_read_context() to
	make it pass an empty environment.
	* include/abg-fwd.h (class environment): Forward declare.
	* include/abg-reader.h (read_translation_unit_from_file)
	(read_translation_unit_from_buffer)
	(read_translation_unit_from_istream)
	(read_corpus_from_native_xml): Take an environment in parameter.
	* src/abg-reader.cc (read_context::m_env): New data member.
	(read_context::read_context): Initialize it.
	(read_context::{get_environment, set_environment}): New data
	member.
	(read_translation_unit): Set environment of the new translation
	unit.
	(read_corpus_from_input): Set the environment of the new corpus.
	(read_translation_unit_from_file)
	(read_translation_unit_from_buffer)
	(read_translation_unit_from_istream, read_corpus_from_native_xml):
	Take an environment in parameter.
	(build_function_parameter): Get variadic parameter type from the environment.
	* src/abg-comparison.cc (compute_diff): Add asserts in all the
	overloads to ensure that the artifact being compared come from the
	same environment.
	* tests/print-diff-tree.cc (main): Create an env for the ABI
	artifacts to use.
	* tests/test-abidiff.cc (main): Likewise.
	* 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.
	* tools/abipkgdiff.cc (main): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-07 23:35:29 +02:00
Dodji Seketeli
bb5085741b Fix redundant const qualifier stripping
In the DWARF reader, we strip the const qualifier when it applies to
reference types because a reference is always const.  Those redundant
const qualifiers can later introduce spurious changes in type
comparison.

But then we were forgetting to add the stripped type to the IR, in
some cases.  This patch fixes that.

	* include/abg-ir.h (operator&, operator~): Add overloaded bitwise
	operators for qualified_type_def::CV.
	* src/abg-ir.cc (operator&, operator~): Define them.
	* src/abg-dwarf-reader.cc (maybe_strip_qualification): Fix
	comment.  If there are multiple qualifiers, only strip the const
	one.
	(build_ir_node_from_die): Once we've built a qualified type, if
	the 'const' qualifier is stripped, then add the new (stripped)
	type to the set of new types.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-07 23:35:08 +02:00
Dodji Seketeli
3b6bada297 More type degradation fixes (from DWARF to abixml)
The series of fixes to make

 "abidw foo > foo.abi && abidiff foo foo.abi"
work continues.

On a binary submitted as part of bug 18904, I am still seeing type
degradation.  This patch addresses the different cases of degradation
that are happening.

	* include/abg-fwd.h (get_type_scope): Declare new function.
	* src/abg-hash.cc (var_decl:#️⃣:operator()): Do not cache the
	hash because that can alter the hash computing of a larger type
	which embeds a var decl as a member declaration.  This is
	especially true if the var decl indirectly references the larger
	type.  The only way to cache the value of a var decl would be to
	wait after all canonical types have been computed.  We'd then seal
	all types.  After that sealing happens, we can cache var decls
	starting from the top-level ones.
	(function_decl:#️⃣:operator()): Likewise.
	* src/abg-ir.cc (get_type_scope): Define new functions.
	* src/abg-reader.cc (read_is_declaration_only): Declare this
	function earlier.
	(typedef const_types_map_it): Adjust this to make it point to a
	map of string and vector of types, as opposed to a map to string
	and type as it was before.
	(typedef types_map_it): New typedef.
	(read_context::map_id_and_node): Map a type id to the last
	xmlNodePtr that represent a *declaration*.  That gives more leeway
	to the declaration resolution code to choose the right definition
	later.  Otherwise, there are cases where the wrong definition.  By
	wrong definition, I mean a definition that is different from the
	one chosen by the DWARF reading code, for a given declaration.
	Basically for a given ABI corpus, a type declaration resolve to
	the first definition seen in the corpus.
	(read_context::get_all_type_decls): Define new member function.
	(read_context::types_equal): Use qualified names only if both
	types have a scope.
	(read_context::key_type_decl): Now a given ID is associated to
	*all* the declarations and definition that have that ID.
	(read_translation_unit_from_input): Make sure the current corpus
	node points to the right node.
	(build_class_decl): Resolve class declarations to the first
	definition seen in the corpus.  Key a type decl before reading its
	members as a reading a member can request the current decl.  No
	need to try and canonicalize a member type, as build_class_decl()
	does that already.
	* tests/data/test-read-dwarf/test16-pr18904.so: New test binary
	input.
	* tests/data/test-read-dwarf/test16-pr18904.so.abi: New test
	output reference.
	* tests/test-read-dwarf.cc: Run the test above.
	* tests/data/Makefile.am: Add the new test input to source
	distribution.
	* tests/data/test-abidiff/test-PR18791-report0.txt: Adjust.
	* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
	* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
	* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-02 14:15:58 +02:00
Dodji Seketeli
5822798dd1 Bug 18894 - Fix representation of enumerators in abixml format
It turns out that using a size_t to serialize an enumerator is not
enough to represent things like enum foo {value = -3}; We need to
represent it using ssize_t.

Also, the patch avoids early canonicalization (when reading DWARF) of
types that refer to themselves.  This was leading to type degradation
(serializing the type from IR to abixml and de-serializing it back to
IR leads to a different type).

	* include/abg-ir.h (enum_type_decl::enumerator::get_value()):
	Change the type of this from size_t to ssize_t.
	* src/abg-ir.cc (enum_type_decl::enumerator::get_value): Do the
	same on the definition side.
	(non_canonicalized_subtype_detector::visit_begin): If a type
	refers to itself, late canonicalize it to have a similar hashing
	result as what the abixml reader does.
	* src/abg-reader.cc (build_enum_type_decl): Use ssize_t to read
	the value of enumerators.
	* tests/data/test-read-dwarf/test13-pr18894.so.abi: New test input.
	* tests/data/Makefile.am: Add the new test inputs above to source
	distribution.
	* tests/test-read-dwarf.cc (in_out_specs): Add new test inputs.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
	* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-29 17:17:48 +02:00
Dodji Seketeli
425f8a4ec4 Detect vtable changes from member function changes
This patch adds vtable changes detection based on the detection of
virtual member function changes.  That is, when a member function
changes, if that member function is virtual, then infer if the change
implies changes to the vtable of the containing class.

Before that patch, we were doing the vtable change detection when we
were comparing two classes; we were then comparing their virtual
member functions.  But as for a given class all its virtual member
functions are not necessarily emitted in the DWARF debug info (only
the virtual member functions that are used in a given translation unit
are emitted in that translation unit) it's not reliable to compare
virtual member functions as part of comparing a given class.  We thus
decided some patches ago to stop comparing virtual member functions
when we compare two classes.

So with this patch now, we still detect changes to the vtable and emit
an appropriate message to the user.

	* include/abg-ir.h (class_decl::{has_virtual_base, has_vtable}):
	Declare new member functions.
	* src/abg-comp-filter.cc (has_virtual_mem_fn_change): New overload
	for function_decl_diff.
	(has_virtual_mem_fn_change): In the overload for diff*, support
	virtual member function changes detection for function_decl_diff*.
	* src/abg-comparison.cc (function_decl_diff::report): Detect and
	report changes to a vtable by looking a changes that can happen to
	a given member function.
	(corpus_diff::report): Detect and report changes to vtables by
	looking at changes change to member functions.
	* tests/data/test-diff-dwarf/test29-vtable-changes-report-0.txt:
	New text input.
	* tests/data/test-diff-dwarf/test29-vtable-changes-v{0,1}.cc: Source
	code of new test input binaries.
	* tests/data/test-diff-dwarf/test29-vtable-changes-v{0,1}.o: New
	test input binaries.
	* tests/data/test-diff-dwarf/test30-vtable-changes-report-0.txt:
	New text input.
	* tests/data/test-diff-dwarf/test30-vtable-changes-v{0,1}.cc: New
	test input.
	* tests/data/test-diff-dwarf/test30-vtable-changes-v{0,1}.o: New
	test input binaries.
	* tests/data/test-diff-dwarf/test31-vtable-changes-report-0.txt:
	New test input.
	* tests/data/test-diff-dwarf/test31-vtable-changes-v{0,1}.cc:
	Source code of new test input binary.
	* tests/data/test-diff-dwarf/test31-vtable-changes-v{0,1}.o: New
	test input binary.
	* tests/data/Makefile.am: Add the new test input files above to
	source distribution.
	* tests/test-diff-dwarf.cc (in_out_specs): Consume the new test
	inputs above.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-29 16:23:17 +02:00
Dodji Seketeli
fbba4bf0ed Fix template comparison operators
There are two issues in comparing templates currently.

One is that comparing member class template recurses for ever (oops).

The other is that the logic of comparing function templates is wrong
and leads to false comparisons.

	* include/abg-ir.h (function_tdecl::operator==): Introduce a new
	virtual member operator that takes a function_tdecl&.
	* src/abg-ir.cc
	(class_decl::member_function_template::operator==): Avoid the
	static cast in the overload for member_base.  In the overload for
	member_class_template, avoid infinite recursion.
	(function_tdecl::operator==): In the overload for decl_base, do
	not do the real work here in the overload for decl_base Rather,
	the real work is done in the new overload for function_tdecl, and
	all other overloads call that one.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-29 16:23:15 +02:00
Dodji Seketeli
9ab2c3a3fd Use size/alignment of class definition when requested on declaration
Sometimes during hashing the "type sub-object" of a class can be
queried for its size or alignment.  In those case, if the class is a
declaration that happens to be accompanied with a definition, its the
size/alignment of the definition that we want, not the one of the
declaration, that is zero.  Otherwise, this can cause spurious hashing
changes between two class types that are otherwise equivalent modulo
the use of a class declaration.

This patch being part of a series that aims at fixing a number of type
hashing issues, the regression tests are adjusted at the end of the
series, not here.

	* include/abg-ir.h (type_base::{set_size_in_bits,
	set_alignment_in_bits}): Make these member functions virtual.
	(class_decl::{set_size_in_bits, get_size_in_bits,
	get_alignment_in_bits, set_alignment_in_bits}): Declare these
	virtual member functions.
	* src/abg-ir.cc (class_decl::{set_size_in_bits, get_size_in_bits,
	get_alignment_in_bits, set_alignment_in_bits}): Define these
	virtual functions.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-29 16:23:15 +02:00