Commit Graph

218 Commits

Author SHA1 Message Date
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
Ondrej Oprala
b2a5bf6389 Bug 19082 - Recognize suppression spec files
When abipkgdiff is invoked on a set of packages, the newer (second) one is also
inspected for files matching the pattern '*.abignore', whose contents are read
and interpreted as suppression specifications.

	* tests/data/Makefile.am: Add new test material to the build system.
	* tests/data/test-diff-pkg/dirpkg-{0-dir1,{1,2}-dir2}/dir.abignore:
	A test suppression specification.
	* tests/data/test-diff-pkg/dirpkg-{2,3}-dir2/.abignore: Likewise.
	* tests/data/test-diff-pkg/dirpkg-3.suppr: Likewise.
	* tests/data/test-diff-pkg/dirpkg-{1,2,3}-dir{1,2}/libobj-v0.so: New
	binary test inputs.
	* tests/data/test-diff-pkg/dirpkg-{1,2,3}-dir{1,2}/obj-v0.cc: New test
	source files
	* tests/data/test-diff-pkg/dirpkg-{1,2,3}-report-{0,1}.txt: New
	reference outputs
	* tests/test-diff-pkg.cc: Adjust to run the new tests.
	* tools/abipkgdiff.cc (prog_options): New static pointer to struct
	opts.
	(file_tree_walker_callback_fn): Rename to
	first_package_tree_walker_callback_fn.
	(second_package_tree_walker_callback_fn): Check for ELF files just
	like the previous function but additionally check for files
	ending with ".abignore", unless disabled from the command line.
	({create_maps_of_package,extract_package_and_map_its}_content):
	Add a callback as a new argument.
	(main) handle the new "--no-abignore" option, which turns off
	the search for suppression files within the new package.

Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
2015-10-13 09:19:47 +02:00
Dodji Seketeli
efeb4e2a8a Bug 19024 - Failing to flag underlying type of enums as anonymous
The for now, the underlying type of an enum type is always assumed to
be anonymous by libabigail.  But then, the code of the DWARF reader
was failing to set the "is-anonymous" flag on it.  So type
canonicalizing code was comparing the enum underlying types by looking
at their names; they all have the same name -- as we forget that they
are anonymous; so they (wrongly) all look the same, within the same
ABI corpus.

This patch sets properly sets the is-anonymous flag on enumerator
underlying types again.

	* src/abg-dwarf-raeder.cc (build_enum_type): Set the is-anonymous
	flag on the underlying type of the enum.
	* tests/data/test-read-dwarf/test0.abi: 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.
	* 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.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-11 13:54:24 +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
Ondrej Oprala
910672f8c2 Bug 19027 - ABI asymmetry with enums over INT_MAX
* src/abg-reader.cc (build_enum_type_decl): Use strtol
	instead of atoi to parse the values and check for overflow.
	* tests/data/Makefile.am: Add the new test material to the build
	system.
	* tests/data/test-read-dwarf/test17-pr19027.so: New test file.
	* tests/data/test-read-dwarf/test17-pr19027.so.abi: Likewise.
	* tests/test-read-dwarf.cc: Adjust to launch the new test.

Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
2015-10-01 11:40:52 +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
Dodji Seketeli
d0b8ef6521 Bug 18535 - abidiff reports false positive ABI difference for libstdc++
When the DWARF reader of libabigail sees a data member for a given
class flagged as being a declaration, it considers the declaration as
being a definition.  The reason why it doesn't strictly trust the
"is_declaration" flag of DWARF is that some DWARF producers sometimes
wrongly emit that flag.

But then, it turns out that a class declaration can have a *static*
data member without loosing its declaration-only property.  This patch
thus changes the behaviour of the DWARF reader to make it consider the
class declaration as being a definition when the class has a
*non-static* data member; a static data member only is not enough to
make the class declaration become a definition.

	* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): The
	presence of a data member shouldn't make a declaration-only class
	loose its declaration-only-ness; the presence of a enon-static*
	data member should.
	* tests/data/test-read-dwarf/test15-pr18892.so.abi: Adjust.
	* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
	* tests/data/test-diff-filter/test31-pr18535-libstdc++-4.8.3.so:
	New binary test input.
	* tests/data/test-diff-filter/test31-pr18535-libstdc++-4.9.2.so:
	Likewise.
	* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-0.txt:
	New test reference output.
	* tests/data/Makefile.am: Add the new test material to the build
	system.
	* tests/test-diff-filter.cc (in_out_specs): Add the new test
	inputs to the set of inputs to consider.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-24 11:51:56 +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
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
113601c062 Compare qualified name in decl_base comparison operator
* src/abg-ir.cc (equals): In the overload for decl_base, compare
	qualified names, not just names.
	* tests/data/test-abidiff/test-PR18791-report0.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-09 08:17:27 +02:00
Dodji Seketeli
4b29b46269 Fix a stupid typo in function sorting code
* src/abg-comparison.cc (function_comp::operator()): Fix a typo
	preventing the proper sorting of function name when their
	declarator names are equal.  Oops.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-08 15:50:25 +02:00
Dodji Seketeli
ba741963b9 Use cache type hash values only after type canonicalization is done
Look at this code:

    struct list;

    struct payload
    {
     int value;
     list* parent_list; //<-- the hash value of struct list when looking
                        //    through this pointer is the non-zero
                        //    value as computed on the struct list
                        //    type below.

    };

    struct list
    {
     payload* p; // <-- While walking the struct list type, the hash
                 // value of the 'struct list' sub-tree node when
		 // looking through this pointer is zero, because we
		 // are still computing the hash value of struct list.
		 // we do it this way to break the otherwise infinite
                 // recursion that might occur here.

     list* next; // <-- likewise here.
     list* prev; // <-- likewise here.
    }; // <-- when we reach this point the hash value of struct list
       // is computed and is different from zero.

Basically, when a type refers to itself in one of its sub-type (like
struct list here, where list::p refers to struct list, because its
type contains a pointer to struct list), then we need to devise a way
to break the infinite recursion we might fall into when computing its
hash value.

So, when computing the hash value of struct list, when we look at the
type of list::prev, which is "list*", we say that the hash value of the type
pointed to by the type of list::next (which is struct list itself) is
zero.  This allows us to break the possibly infinite recursion here.

But then, this means that the hash value of "struct list" depends on
*when* we request that hash value.  If we are computing the hash value
of struct list itself, then the temporary value of "struct list" is
zero.  But then once we are done computing the hash value of "struct
list", that value becomes non-zero.

Hence, the hash value of a type depends on when that value is
computed.

But then if we want to cache that hash value and re-use it later,
which value should we cache?  Definitely not the zero value!

So in other words, we can use (and thus cache) the hash value of a
given type T only after the hash values of all types which use T have
been computed.

To satisfy that condition, we decide to use the (cached) hash value of
each type only after we've computed all the hash values of all types
of the system.

So, during type canonicalization, when a type T is canonicalized, this
patch stores the hash value of T.  But then it's only when all types
are canonicalized that the hashing code is allowed to re-use the
cached value of types.

This fixes the issues of spurious type differences introduced when the
same type was read either from DWARF or from abixml.  Those
differences where introduced by differences in the order of hashing
types which sub-types refer to themselves. The patch also updates
regression tests accordingly.

	* src/abg-dwarf-reader.cc (read_debug_info_into_corpus): Before we
	read debug info and build the IR, set a flag in the environment
	saying that type canonicalization isn't finished yet.  But then,
	after type canonicalization is done, flip that flag to say that
	type canonicalization is done.
	* src/abg-reader.cc (read_corpus_from_input): Likewise.
	* src/abg-ir.cc (type_base::get_canonical_type_for): Once a type
	has been canonicalized, cache its hash value.
	* src/abg-hash.cc (type_base::dynamic_hash::operator()): If type
	canonicalization has been done and if the type has a cached value,
	use that one.
	* tests/data/test-read-dwarf/test2.so.abi: 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-07 23:35:30 +02:00
Dodji Seketeli
49759d3be8 Bug 18904 - Fix support for C++ rvalue references
* src/abg-comparison.cc (reference_diff::has_changes): Just
	compare the references, rather than assuming that the change can
	only be on underlying types.
	(reference_diff::report): Describe lvalue/rvalue changes for
	references.
	* src/abg-ir.cc (reference_type_def::reference_type_def): Properly
	set the name for an rvalue reference.
	(equals): For references, compare lvalue-ness too.
	(reference_type_def::get_qualified_name): Properly set rvalue
	reference names.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-liba.so:
	New test input.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-libb.so:
	New test input.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt:
	New test reference output.
	* tests/data/Makefile.am: Add the new files to source
	distribution.
	* tests/test-diff-filter.cc (in_out_specs): Run the new tests.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-09-02 14:42:16 +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
a4b9f670fe Bug 18892 - type degradation from DWARF to abixml on libtsan.so
abidiff-ing libtsan.so again the output of abidw libtsan.so does not
yield the empty set.  This is because some types, especially an enum (in
certain cases) when read (de-serialized) from DWARF doesn't hash the
same as when de-serialized from abixml.

This is because an enum type can have a linkage name, referred to by
the DW_AT_linkage_name DWARF attribute.  This linkage_name was being
read from DWARF but wasn't serialized to abixml.  At de-serialization
time, well, the linkage_name information was lost.  Oops.

Also, I have seen that in some case we can canonicalize enum types too
early, when we de-serialize them from abixml, before we are done
building them.

This patch addresses these issues.

	* src/abg-reader.cc (read_context::maybe_canonicalize_type): Late
	canonicalize enum types.
	(build_enum_type_decl): Read the linkage name of the enum type.
	* src/abg-writer.cc (write_enum_type_decl): Emit the linkage name
	of the enum type.
	* tests/data/test-read-dwarf/test15-pr18892.so: New binary test
	input.
	* tests/data/test-read-dwarf/test15-pr18892.so.abi: New test
	output reference.
	* tests/data/Makefile.am: Add the new test inputs above to source
	distribution.
	* tests/test-read-dwarf.cc (in_out_specs): Run the two tests above.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-30 17:56:19 +02:00
Dodji Seketeli
60cdabd931 Bug 18893 - type degradation from dwarf to abixml on libGLU.so
abidiff-ing libGLU.so against the result of 'abidw libGLU.so' does not
yield the empty set.  This is because hashing certain types when they
are read (de-serialized) from DWARF doesn't give the same result as
when they are de-serialized from abixml.  I call this type
degradation.  And it leads to spurious comparison differences.

This is due to several issues.

  1/ The logical link between a class declaration and its definition
  -- that is built when reading types from DWARF is not preserved in
  abixml.  So, for example, when a class S refers to itself via a
  pointer to its declaration, that type might hash differently when
  read from DWARF and when read from abixml.  When read from abixml
  it's a pointer to S itself.  But then that 'self' can be a copy of S
  that is defined in another file because abixml doesn't enforce the
  One Definition Rule from C++ either.

  2/ As the result of hashing is kept in a cache for var_decl and
  function_decl, hashing those decl before their types are completely
  built caches a value that becomes wrong when their type become
  completely built.

  3/ In DWARF, a class which has a virtual member function can still
  be considered as being declaration-only.  And its definition can
  come later in the DWARF info.  Our DWARF reader removes the
  "declaration-only" flag from a class as soon as it sees virtual
  member functions in that class; that makes us consider that class as
  a definition.  And then later when we read the real definition of
  the class we have two classes of the same name, with different
  layouts/size in the system.  This leads to spurious comparison
  differences too.

This patch addresses issues 1, 2 and 3.

	* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir): Do not
	consider that virtual member functions disqualify a class from
	being declaration-only.
	* src/abg-hash.cc (var_decl:#️⃣:operator()): Do not cache the
	result of hashing before we are done building the type of the
	var_decl.
	(function_decl:#️⃣:operator()): Likewise, do not cache the
	result of hashing before we are done building the type of the
	function_decl.
	* src/abg-reader.cc (build_class_decl): Build the link between a
	class declaration and its definition.  If there are several
	definitions of a class in the corpus, keep just one.
	* src/abg-writer.cc (write_class_is_declaration_only): Emit the
	link between a class declaration and its definition.
	(write_class_decl): Emit a class declaration even if it has a
	definition.  The definition is going to be emitted
	separately.
	* tests/data/test-read-dwarf/test14-pr18893.so: New binary test
	input.
	* tests/data/test-read-dwarf/test14-pr18893.so.abi: New test
	reference output.
	* tests/data/Makefile.am: Add the new test input files to source
	distribution.
	* tests/test-read-dwarf.cc (in_out_specs): Run the new tests.
	* 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/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.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-30 17:11:36 +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
d8af43b827 Do not hash or compare virtual member functions as par of classes
When comparing two classes, do not compare their virtual member
functions anymore, because DWARF might not represent all the virtual
member functions of a class, in a given translation unit.

We still detect changes to virtual member functions (adding or
removing) because the index of a given member function in a vtable is
a property of the member function itself.  So if a vtable index
changes on a function, we detect it as part of comparing the exported
member functions themselves.  Likewise, if a member function is added
or removed, we detect it; and so if it's a virtual member function
then we detect it too.  In a subsequent patch, we'll add a dedicated
section to the report emitted by abidiff for changes to the vtable of
classes, I guess.

For now, this patch fixes some crashes we were having due to
discrepancies in hash values of classes, due to the fact that not all
of their virtual member functions were present in the debug info,
depending on the translation unit of the classes in question.

	* src/abg-ir.cc (equals): When comparing two classes, do not
	compare their virtual member functions.
	* src/abg-hash.cc (class_decl:#️⃣:operator()): Do not hash
	virtual member functions when hashing a class.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-29 16:23:16 +02:00
Dodji Seketeli
540370c9d1 Adjust many reference output for the non-regression test suite
So the last series of patches have changed the test output a lot.
This patch adjusts the reference output to have "make check" work
again.  There is still one test that fails:
./build/tests/runtestreaddwarf.  It'll be addressed in subsequent
patches from now.

	* tests/data/test-abidiff/test-enum0-report.txt: Adjust.
	* tests/data/test-abidiff/test-enum1-report.txt: Adjust.
	* tests/data/test-abidiff/test-qual-type0-report.txt: Adjust.
	* tests/data/test-abidiff/test-struct0-report.txt: Adjust.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Adjust.
	* tests/data/test-read-dwarf/test11-pr18828.so.abi: Adjust.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Adjust.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
	* tests/data/test-read-write/test17.xml: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-29 16:23:16 +02:00
Dodji Seketeli
585fc4c33c Make abipkgdiff compare tar archives containing binaries
This patch adds support for comparing the ABI of binaries contained in
a tar archive.

If the archive is compressed with gzip, bzip2, lzip, lzma or xz, then
abipkgdiff recognizes the usual relevant file extensions and lets the
GNU tar program handle the decompression.

If the archive is not compressed, abipkgdiff recognizes the UStar
(Uniform Standard Tape ARchive) format, even if the archive file name
doesn't end with the .tar extension, and lets the GNU tar program
handle the extraction.  If the file ends up with the .tar extension
anyway (even if it's not in the UStar format, abipkgdiff lets the GNU
tar program handle its extraction.

	* config.h.in (WITH_TAR): New configuration preprocessor macro.
	* configure.ac: Add a new --enable-tar option.  It's turned on
	automatically if the tar program is found in the PATH.  Adjust the
	build configuration report to add the tar archive support.
	* include/abg-tools-utils.h (string_ends_with): Declare new
	function.
	(enum file_type): Add a new FILE_TYPE_TAR enumerator.
	* src/abg-tools-utils.cc (string_ends_with): Define new function.
	(operator<<(ostream&, file_type)): Serialize the new FILE_TYPE_TAR
	enumerator.
	(guess_file_type): Detect UStar format file by reading its magic
	number.  Detect compressed tar files based on the file path
	extension.
	* tools/abipkgdiff.cc (extract_tar): Define new function.
	(extract_package): Handle tar packages.
	(main): Handle tar archives.
	* tools/abidiff.cc (main): Handle the new FILE_TYPE_TAR
	enumerator.
	* tools/abilint.cc (main): Likewise.
	* tests/data/test-diff-pkg/tarpkg-0-dir{1,2}.ta{,r,.bz2, gz}: New
	test input tarballs.
	* tests/data/test-diff-pkg/tarpkg-0-report-0.txt: New test output
	reference.
	* tests/data/Makefile.am: Add the new test data file above to
	source distribution.
	* tests/test-diff-pkg.cc (in_out_specs): Add new tests cases.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-22 14:32:20 +02:00
Dodji Seketeli
d7dbbf0d50 Make abipkgdiff compare directories containing binaries
abipkgdiff knows how to compare the ABI of binaries contained in .deb
and .rpm files.  This patch adds support for comparing the ABI of
binaries contained in two directories.

	* include/abg-tools-utils.h (enum file_type): Add a new
	FILE_TYPE_DIR enumerator.
	* src/abg-tools-utils.cc (operator<<(ostream&, file_type)):
	Support serialization of the new FILE_TYPE_DIR enumerator.
	(guess_file_type): Detect that the path given is a directory.
	* tools/abipkgdiff.cc (package::package): If the package is a
	directory, then set its extracted directory path to the path of
	the directory.
	(package::erase_extraction_directory): Do not erase the extraction
	directory if the package is a directory provided by the user.
	(extract_package): If the package is a directory provided by the
	user, then there is nothing to extract.
	(main): If the first package is a directory, then the second one
	should be a directory as well.
	* tools/abidiff.cc (main): Support directories as input.
	* tools/abilint.cc (main): Likewise.
	* tests/data/test-diff-pkg/dirpkg-0-dir{1,2}/libobj-v0.so: New
	binary test inputs.
	* test/data/test-diff-pkg/dirpkg-0-report-0.txt: New input test
	file.
	* tests/data/test-diff-pkg/dirpkg-1-dir{1,2}/obj-v0.cc: Source
	code of the binary test inputs above.
	* tests/data/Makefile.am: Add the new files above to the source
	distribution.
	* tests/test-diff-pkg.cc (in_out_specs): Add the new test input
	files above to the set of tests this harness has to run over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-22 12:19:27 +02:00
Dodji Seketeli
ae5e1be5c3 [dwarf reader] Support reference types without explicit DW_AT_byte_size
On x86_64 at least, in the debug info emitted by Clang, reference
types don't necessarily have the DW_AT_byte_size property.  In that
case, assume the size of the pointer type is the address size of the
current translation unit, rather than giving up and not building the
type.

	* src/abg-dwarf-reader.cc (build_reference_type): If the type DIE
	has no DW_AT_byte_size, assume the type size is the translation
	unit's address size.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-22 09:41:23 +02:00
Dodji Seketeli
12123aede6 [dwarf reader] Support pointer types without explicit DW_AT_byte_size
On x86_64 at least, in the debug info emitted by Clang, pointer types
don't necessarily have the DW_AT_byte_size property.  In that case,
assume the size of the pointer type is the address size of the
current translation unit, rather than giving up and not building the
type.

	* abg-dwarf-reader.cc (build_pointer_type_def): If the type DIE
	has no DW_AT_byte_size, assume the type size is the translation
	unit's address size.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-21 20:16:38 +02:00
Dodji Seketeli
ddb17eddba Hash a class declaration the same as its definition
A class declaration hashes differently from its definition.

Since the abixml format can now use a class element id before defining
it, it's more consistent to stop representing class declarations in
the abixml format, when the class is actually defined in the corpus.

So this patch now hashes a class declaration the same as its
definition, when the definition is present.  If the definition is not
present then the hash value of the declaration is just zero.  This is
consistent with what is done elsewhere in the code as a hash value of
zero means the hash could not be computed, somehow, as the type
comparison code knows that a type with hash value zero can be equal to
a type with a hash value that is different from zero.

As a result, many tests which use the abixml format have been adjusted
to reflect the new form of abixml where class declarations are now
omitted when these declarations are accompanied with their definition.
I made sure that abidiff reports that former abixml output and the new
one are equivalent.

After this change abixml outputs should contain less redundant type
declarations.  This is another step toward normalizing the abixml
output.

	* src/abg-hash.cc (class_decl:#️⃣:operator()(const class_decl&)):
	If the class declaration has a definition, hash its definition
	instead.  Otherwise, if the class declaration has no definition,
	just return a zero hash, like what we were doing before.
	* src/abg-reader.cc (read_context::maybe_canonicalize_type): Do
	not early canonicalize method types because most of the time, when
	this function is called, the method hasn't been added to its
	parent class yet.  So wait until late before canonicalizing.
	* src/abg-writer.cc (write_class_is_declaration_only): Do not emit
	the "is-declaration-only" property if the declaration has a
	definition.
	(write_class_decl): If the class declaration has a definition,
	emit the definition instead.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Adjust.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
	* tests/data/test-read-write/test18.xml: Likewise.
	* tests/data/test-read-write/test20.xml: Likewise.
	* tests/data/test-read-write/test21.xml: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-21 12:07:19 +02:00
Dodji Seketeli
4f5c0326a4 Canonicalize all types that got scheduled for late canonicalization
Until now, when late type canonicalization time come (after having
read all of the ABI corpus), the types scheduled for late
canonicalization were considered and only those that don't have
non-canonicalized sub-types were canonicalized.

This patch just canonicalizes all the scheduled type.  As a result,
all types should now be canonicalized, so type comparison should be as
fast as a pointer comparison now.  But then, loading DWARF is now even
longer, type canonicalization needs to happen.

	* src/abg-dwarf-reader.cc
	(read_context::canonicalize_types_scheduled): Canonicalize all
	types scheduled for late canonicalization.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-20 11:44:45 +02:00
Dodji Seketeli
39b2e8b7d5 Make decl_base::get_qualified_name() work when decl context changes
decl_base::get_qualified_name() caches its result.  So when it's
first called on a decl that is not added to a scope, what is returned
is a non-qualified name.  Which is all right.  But then when the decl
is later added to a scope, the cached result of
decl_base::get_qualified_name() is not longer correct.

This patch resets the cache of decl_base::get_qualified_name() when
the decl gets added to a new scope.

	* include/abg-ir.h (class decl_base): Make class scope_decl a
	friend of decl_base.
	(type_base::priv_): Make this protected, rather than private.
	* src/abg-ir.cc (scope_decl::add_member_decl)
	(scope_decl::insert_member_decl): Reset the cache of the result of
	decl_base::get_qualified_name().
	* tests/data/test-abidiff/test-PR18791-report0.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-19 18:09:29 +02:00
Dodji Seketeli
ba5b4452d5 Bug 18844 - assert failure in abidw at abg-dwarf-reader.cc:6537
The DWARF reader is not scheduling a declaration-only class for
resolution when the class has member types.  When reading the code of
build_class_type_and_add_to_ir(), we see that the scheduling is done
before getting out of the function.  But then, building members of the
class can trigger another invocation of
build_class_type_and_add_to_ir() before the current invocation
returns.  In that case, the declaration-only class being built appears
as not being scheduled for resolution.  And that is what violates the
assertion that declaration-only classes should be scheduled for
resolution whenever they are used.

This patch addresses the issue by scheduling the resolution earlier, when
we know we are dealing with a declaration-only class, and before
dealing with members of that classes.

	* src/abg-dwarf-reader.cc (build_class_type_and_add_to_ir):
	Schedule declaration-only class resolution before the class
	appears as usable as to other types being built.
	* tests/data/test-read-dwarf/test12-pr18844.so: Add a new binary
	test input.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: The reference
	ABI XML output for the binary above.
	* tests/data/Makefile.am: Add the new test inputs above to the
	source distribution.
	* tests/test-read-dwarf.cc (in_out_specs): Add the new test inputs
	above to the set of input this test harness has to run over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-18 12:33:57 +02:00
Dodji Seketeli
f38c19f8da Bug 18828 - Handle force-resolving of multiple declarations-only of the same type
When a declaration-only type that is used in a context where it needs
to be complete (and no definition is present for that type in the ABI
corpus) handle cases where that type is was actually declared several
times.

	* src/abg-dwarf-reader.cc
	(read_context::resolve_declaration_only_classes): Accept that a
	class that needs to be force-resolved might have been declared
	several times.  In that case, some instances of that
	declaration-only class might have already been resolved (or
	completed).
	* tests/data/test-read-dwarf/test11-pr18828.so: New binary input.
	It comes from bug https://sourceware.org/bugzilla/show_bug.cgi?id=18828.
	* tests/data/test-read-dwarf/test11-pr18828.so.abi: The reference
	output for the binary above.
	* tests/data/Makefile.am: Add the test input files above to source
	distribution.
	* tests/test-read-dwarf.cc (in_out_specs): Add the test inputs
	above to the set of input this test harness has to run over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-15 00:26:39 +02:00
Dodji Seketeli
88ae73fdf9 Avoid declaring a type several times in the same TU in the XML format
It appears a lot of duplicated type declarations can appear in a given
translation unit.  This patch avoids that.

	* src/abg-writer.cc (write_context::{record_type_id_as_emitted,
	record_type_as_emitted, type_id_is_emitted, type_is_emitted,
	clear_emitted_types_map}): New member functions.
	(write_context::m_emitted_type_id_map): New data member.
	(write_translation_unit): Clear the per-translation unit map of
	emitted types.  Do not emit a type that has already been emitted
	in this translation unit.
	(write_namespace_decl): Do not emit a type that has already been
	emitted in this translation unit.
	(write_type_decl, write_qualified_type_def)
	(write_pointer_type_def, write_reference_type_def)
	(write_array_type_def, write_typedef_decl, write_class_decl)
	(write_type_tparameter, write_template_tparameter): Record the
	type we've just written as having been written out.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust as
	duplicated declarations got removed.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-15 00:03:07 +02:00
Dodji Seketeli
160961f3cb Bug 18818 - abidw aborts on a class with a non-complete base class
On some binaries with debug info emitted by "Ubuntu clang version
3.6.0-2ubuntu1" and "GNU C++ 4.9.2" (as the value of the
DW_AT_producer property), it seems some classes can have a base class
that is not complete.  E.g, the debug info (that I have extracted
using the command eu-readelf --debug-dump=info
<the-binary-attached-to-the-bug>) has these relevant pieces:

    [...]

     [  5ff7]        class_type
		     containing_type      (ref4) [  7485]
		     name                 (strp) "system_error"
		     byte_size            (data1) 40
		     decl_file            (data1) 46
		     decl_line            (data1) 22
     [  6003]          inheritance
		       type                 (ref4) [  7480]
    [...]

Here, we are looking at the type system_error (actually
boost::system::system_error) that inherits the type which DIE is
referred to as offset '7480'.

Then the definition of the DIE at offset 7480 is:

    [...]

     [  7480]      class_type
		   name                 (strp) "runtime_error"
		   declaration          (flag_present)
     [  7485]      class_type
		   name                 (strp) "exception"
		   declaration          (flag_present)
    [...]

You can see that the type "runtime_error" (actually
std::runtime_error) has the flag DW_AT_declaration set, marking it as
a declaration (with no definition yet).  And no other DIE in the same
translation unit
(src/third_party/boost-1.56.0/libs/filesystem/src/codecvt_error_category.cpp)
or in the same DSO provides the definition for that declaration.

I believe this is ill-formed.  A base class should be defined and have
a layout completed expressed and accessible from the translation unit
it's used in.

The patch I am proposing detects that the base class is still
incomplete when we finish loading the current binary.  In that case,
the base class is made complete with a size of 1.  Meaning it's an
empty class (with no data member and no base class).  This works as a
viable work-around *if* the producer only omitted definitions for
empty classes.  We'll need to fix the producers eventually.

	* src/abg-dwarf-reader.cc
	(read_context::decl_only_classes_to_force_defined_map_): New data
	member.
	(read_context::declaration_only_classes_to_force_defined): New
	accessors.
	(read_context::schedule_declaration_only_class_for_forced_resolution):
	New member function.
	(build_class_type_and_add_to_ir): If a base class is a
	declaration-only class then mark it as needing to be force-defined
	*if* it's still not defined at the end of the abi corpus loading.
	(read_context::resolve_declaration_only_classes): If
	declaration-only classes that need to force-defined are present
	and not defined (when we reach the end of the ABI corpus) then
	force-define them as empty classes.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so: New test
	binary input file.  This comes from a user binary submitted to bug
	https://sourceware.org/bugzilla/show_bug.cgi?id=18818.  The
	original URL to the binary is
	https://sourceware.org/bugzilla/attachment.cgi?id=8518.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so: New binary
	input file.  This comes from the same bug report as above.  The
	original URL to the binary is
	https://sourceware.org/bugzilla/attachment.cgi?id=8511.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: New
	reference output file.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
	* tests/data/Makefile.am: Add the new files above to the source
	distribution.
	* tests/test-read-dwarf.cc (in_out_specs): Add the test inputs
	above the set of tests input this harness has to run over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-14 16:22:14 +02:00
Matthias Klose
4df0a4d952 Add support for .deb files to abipkgdiff
This lets abipkgdiff compare debian binary packages.

The patch contains test cases for debian package with split debug info
that is referenced by the build-id scheme.  These test cases come from
the bug report https://sourceware.org/bugzilla/show_bug.cgi?id=18792,
more particularly from the attachment
https://sourceware.org/bugzilla/attachment.cgi?id=8516.

	* include/abg-tools-utils.h (file_type): Add FILE_TYPE_DEB.
	* tools/abipkgdiff.cc (extract_deb): New.
	(extract_package, main): Handle FILE_TYPE_DEB.
	* src/abg-tools-utils.cc (operator<<): Handle FILE_TYPE_DEB.
	(guess_file_type): Detect FILE_TYPE_DEB.
	* tools/abidiff.cc (main): Handle FILE_TYPE_DEB.
	* tools/abilint.cc (main): Handle FILE_TYPE_DEB.
	* tests/data/test-diff-pkg/libsigc++-2.0-0c2a-dbgsym_2.4.0-1_amd64.ddeb:
	Input debian debug info package; to be compared by the test
	harness runtestdiffpkg.
	* tests/data/test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64.deb:
	Input debian package; to be compared by the test harness
	runtestdiffpkg.
	* tests/data/test-diff-pkg/libsigc++-2.0-0v5-dbgsym_2.4.1-1ubuntu2_amd64.ddeb:
	Input debug info package
	* tests/data/test-diff-pkg/libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64.deb:
	Input debian package; to be compared by the test harness
	runtestdiffpkg.
	* tests/data/test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64--libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64-report-0.txt:
	Reference output for the comparison of the packages above.
	* tests/data/Makefile.am: Add the new files above to the source distribution.
	* tests/test-diff-pkg.cc (in_out_specs): Add the input packages
	above to the set of files to be compared by this test harness.

Signed-off-by: Matthias Klose <doko@debian.org>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-14 13:36:23 +02:00
Dodji Seketeli
242e49a321 Bug 18791 - libabigail fails to read the output of abidw
The reader fails to set the access specifier for a member type.  Fixed
thus.

	* src/abg-reader.cc (read_context::get_scope_for_node): Take an
	access_specifier output parameter to set the access specifier of
	the current node in its scope.  Update the function to set the
	access_specifier.
	(read_context::build_or_get_type_decl): Adjust to set the access
	specifier of the type we are building, in case it's a member type.
	* tests/data/test-abidiff/test-PR18791-v{0,1}.so.abi: New test input files.
	* tests/data/test-abidiff/test-PR18791-report0.txt: New test
	output reference.
	* tests/data/Makefile.am: Add the new test material to the source
	distribution.
	* tests/test-abidiff.cc (specs): Add the new test inputs to the set of
	input files this test harness has to run over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-09 02:11:17 +02:00
Dodji Seketeli
9f7c07460d Add --no-added-syms to abipkgdiff
With this new option the tool ignores added functions, variables and
their symbols.

	* tools/abipkgdiff.cc (options::show_added_syms): New data member.
	(options::options): Initialize it.
	(parse_command_line): Parse the new --no-added-syms option and set
	the options::show_added_syms flag accordingly.
	(display_usage): Add a help string for the new option.
	(set_diff_context_from_opts): Set the diff context according to
	the state of the new options::show_added_syms flag.
	* doc/manuals/abipkgdiff.rst: Add manual entry for the new
	--no-added-syms options.
	* tests/data/test-diff-pkg/test-rpm-report-5.txt: New test
	reference input file.
	* tests/data/Makefile.am: Add the new file above to source
	distribution.
	* tests/test-diff-pkg.cc (InOutSpec::prog_options): New data
	member.
	(in_out_specs): Adjust.  Add a new input to run the test again
	with --no-added-syms.
	(main): Adjust to pass the program options contained in
	InOutSpec::prog_options to abipkgdiff.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>

fixup! Add --no-added-syms to abipkgdiff

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-06 15:22:38 +02:00
Dodji Seketeli
a746f4afee Make applying supp specs through pointer access look through typedefs
Consider the declaration of the exported function bar() below:

    struct _OpaqueType {int member;};

    typedef struct _OpaqueType Type;

    void bar(Type*);

Once the *definition of struct _OpaqueType and bar() are compiled into
a shared library, if a layout change happens to struct _OpaqueType,
then abidiff rightfully reports that bar() is impacted by the layout
change to struct _OpaqueType.

But then, the following suppression specification won't silence the
ABI change report:

    [suppress_type]
      name = _OpaqueType
      type_kind = struct
      accessed_through = pointer

This is because strictly speaking, it's not struct _OpaqueType that is
accessed through a pointer, from function bar(); it's the type 'Type',
(which is a typedef of struct _OpaqueType) that is accessed though a
pointer.

But then, as 'Type' and 'struct _OpaqueType' are the same type (modulo
the typedef), this behaviour is not super useful.  It would be more
interesting if the suppression specification could silence the ABI
change report.

And this is what this patch does.

	* include/abg-comparison.h (type_suppression::suppresses_type):
	Declare new member function.
	(get_typedef_diff_underlying_type_diff): Declare new function.
	* include/abg-fwd.h (get_typedef_underlying_type): Likewise.
	* src/abg-comparison.cc (type_suppression::suppresses_type):
	Define new member function.
	(get_typedef_diff_underlying_type_diff): Define new function.
	(type_suppression::suppresses_diff): After looking through the
	different kind of access methods, use the new
	type_suppression::suppresses_type(), rather than doing lots of
	stuff ourselves here.  But then, if the suppression doesn't apply
	to the subjects of the diff, look through typedefs and try to
	apply the suppression again.
	* src/abg-ir.cc (get_typedef_underlying_type): Define new
	function.
	* tests/data/test-diff-suppr/libtest25-typedef-v{0,1}.so: New
	binary test input files.
	* tests/data/test-diff-suppr/test25-typedef-v{0,1}.c: Source code
	for the binary test input files above.
	* tests/data/test-diff-suppr/test25-typedef-report-{0, 1}.txt: New test
	input files.
	* tests/data/test-diff-suppr/test25-typedef-suppr-0.txt: New test
	input file.
	* tests/data/Makefile.am: Add the new test material to the source
	distribution.
	* tests/test-diff-suppr.cc (in_out_specs): Add the test inputs
	above to the set of test inputs this harness has to run over.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-08-01 14:34:46 +02:00
Dodji Seketeli
88a1e8d6a0 Make the name of the removed variable section be consistent
The removed functions section is introduced by the string "Removed
functions", whereas the removed variables section is introduced by the
string "Deleted variables".  This patch makes the latter be "Removed
variables" just like for the functions.

	* src/abg-comparison.cc (corpus_diff::report): Introduce the
	section of removed variables with the string "Removed variable",
	rather than with the string "Deleted variable".
	* tests/data/test-abicompat/test2-var-removed-report-0.txt: Adjust.
	* tests/data/test-diff-suppr/test18-suppr-removed-var-report-0.txt: Likewise.
	* tests/data/test-diff-suppr/test18-suppr-removed-var-report-3.txt: Likewise.
	* tests/data/test-diff-suppr/test18-suppr-removed-var-report-5.txt: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-24 14:06:29 +02:00
Dodji Seketeli
e5cf9d1f60 Consider default symbol versions when computing added/removed fns/vars
When computing the set of added function or variable symbols, if a
symbol S with no version symbol was present in a given corpus and that
symbol gained a *DEFAULT* version V in the second corpus, we should
not consider that a new symbol S was added (and that the former S was
removed) because:

  1/ S was already present in the first corpus
  2/ applications linked to the first corpus and that were using S
  (with no version) there, will automatically use the S with version V
  in the second corpus, without needing any re-linking; the
  power of symbol versioning!

Rather, it's just that S gained a default symbol version.

This patch implements that.

	* include/abg-corpus.h (corpus::{lookup_function_symbol,
	lookup_variable_symbol}): Take a elf_symbol::version object,
	rather than a string representing the version.  Add an overload
	that takes an elf_symbol.
	* src/abg-corpus.cc (find_symbol_by_version): New static function.
	(corpus::{lookup_function_symbol, lookup_variable_symbol}): Take a
	elf_symbol::version object, rather than a string representing the
	version.  Add an overload that takes an elf_symbol.  If the looked
	up symbol has no version and if the corpus contains a symbol with
	the same name and with a default version, then return that latter
	symbol if the corpus doesn't contain a symbol with the same name
	and empty version.
	* src/abg-comparison.cc
	(class_diff::ensure_lookup_tables_populated): Adjust.
	(corpus_diff::priv::ensure_lookup_tables_populated): Before
	deciding that a symbol has been added, if the symbol has a default
	version, make sure no symbol with the same name and without
	version was present in the former corpus.  Similarly, before
	deciding that a symbol has been removed, if the symbol has no
	version, make sure the latter corpus has no symbol with the same
	name and with a default version.
	* tests/data/test-diff-dwarf/test12-report.txt: Adjust.  The
	function should not be considered as added, because its symbol
	(and version) was already present in the former DSO.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-24 14:04:11 +02:00
Dodji Seketeli
819f8941cf Show linkage names in abipkgdiff output
With this patch abipkgdiff now shows the linkage names of
added/removed functions and variables.  In addition, there now is a
--no-linkage-name option to avoid seeing linkage names.

	* doc/manuals/abipkgdiff.rst: Document the new --no-linkage-name
	options.
	* tools/abipkgdiff.cc (options::show_linkage_names): New data
	member.
	(options::options): Initialize it.
	(display_usage): Display a usage string for --no-linkage-name.
	(parse_command_line): Parse the --no-linkage-name option.
	(set_diff_context_from_opts): Set the diff context accordingly.
	* tests/data/test-diff-pkg/test-rpm-report-0.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-21 16:09:53 +02:00
Dodji Seketeli
0cf1828a90 Fix type synthesis to fix abicompat weak mode
While looking further in the issue Sinny Kumari reported, I realized
that the weak mode wasn't working in that example either.

It turned out that synthesizing qualified types was not working
because we were just looking them up in the binary, rather than
looking up the un-qualified underlying type and then synthezing the
resulting qualified type.

This patch just does that.

	* include/abg-fwd.h
	(synthesize_type_from_translation_unit): Declare new function.
	(synthesize_function_type_from_translation_unit): Make the
	translation_unit parameter non-const because the function needs to
	bind the life time of the synthesized function to the life time of
	the translation unit.  Make this function be a friend of
	abigail::ir::translation_unit.
	(synthesize_function_type_from_translation_unit):
	* src/abg-ir.cc (translation_unit::priv::synthesized_types_): New
	data member.
	(synthesize_type_from_translation_unit): Define new function.
	(synthesize_function_type_from_translation_unit): Make the
	translation_unit parameter non-const.  If the return is void, then
	take that in account carefuly.  Rather than just looking up the
	type of parameters and return value, synthesize them too,
	especially when they are qualified types.  Bind the life time of
	the synthesized function type to the lifetime of the translation
	unit.
	* tests/data/test-abicompat/test7-fn-changed-report-1.txt: New
	test reference output.
	* tests/test-abicompat.cc (in_out_spec): Run the harness on the
	exisiting test7-fn-changed-app and libtest7-fn-changed-libapp-v1
	but in weak mode this time.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-20 17:11:32 +02:00
Dodji Seketeli
92b821034a Clean up the output of abicompat weak mode
Remove ugly vertical spaces from the output of abicompat in weak
mode and adjust regression tests accordingly.

	* tools/abicompat.cc (perform_compat_check_in_weak_mode): Remove
	disgracious vertical spaces in the wording.
	* tests/data/test-abicompat/test5-fn-changed-report-0.txt: Adjust.
	* tests/data/test-abicompat/test6-var-changed-report-0.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-20 16:01:27 +02:00
Dodji Seketeli
af2a94defa Fix computing the set of exported functions and varible symbols
Sinny Kumari reported that abicompat is failing to report ABI changes
on a library linked to a small test program.  It turned out that the
code that compute if a given exported function is to be kept by
looking at the white list of symbols to keep has a bug in which the
versions of the symbols of the white list were not being reset as they
should.  Fixed thus.

	* src/abg-ir.cc (elf_symbol::get_name_and_version_from_id): Always
	set the version and name of the symbol.
	*  src/abg-corpus.cc
	(corpus::exported_decls_builder::{keep_wrt_id_of_fns_to_keep,
	keep_wrt_id_of_vars_to_keep}): Reset the symbol name *and* version
	before passing it.  This is redundant with the fix in
	elf_symbol::get_name_and_version_from_id() that always set the
	symbol name and version now, but I felt it makes it easier to
	understand the fix overall.
	* tests/data/test-abicompat/libtest7-fn-changed-libapp-v{0,1}.so:
	New test input binaries.
	* tests/data/test-abicompat/test7-fn-changed-app: Likewise.
	* tests/data/test-abicompat/test7-fn-changed-{app, libapp-v0,
	libapp-v1}.c: Source code of the binary test inputs above.
	* * tests/data/test-abicompat/test7-fn-changed-{libapp-v0,
	libapp-v1}.h: Likewise.
	* tests/data/test-abicompat/test7-fn-changed-report-0.txt: Test
	input.
	* tests/data/Makefile.am: Add the new test material above to
	source distribution.
	* tests/test-abicompat.cc (int_out_specs): Add the test inputs
	above to the set of inputs this test harness has to run over.

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

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

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

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

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-19 19:48:51 +02:00
Sinny Kumari
260b92f5df Add regression tests for abipkgdiff tool
Add tests for the abipkgdiff tool.  The tests runs abipkgdiff on RPM
packages. RPMs for test data are taken from Fedora koji build with
build id - 106158 and 648058

	* tests/Makefile.am: Build new runtestdiffpkg regression test
	* tests/data/Makefile.am: Add new test files to source
	* tests/data/test-diff-pkg/dbus-glib-0.104-3.fc23.x86_64.rpm:
	Test data for abipkgdiff tool
	* tests/data/test-diff-pkg/dbus-glib-0.80-3.fc12.x86_64.rpm: Likewise
	* tests/data/test-diff-pkg/dbus-glib-debuginfo-0.104-3.fc23.x86_64.rpm:
	Likewise
	* tests/data/test-diff-pkg/dbus-glib-debuginfo-0.80-3.fc12.x86_64.rpm:
	Likewise
	* tests/data/test-diff-pkg/test-rpm-report-0.txt: Expected test output
	* tests/data/test-diff-pkg/test-rpm-report-1.txt: Likewise
	* tests/data/test-diff-pkg/test-rpm-report-2.txt: Likewise
	* tests/data/test-diff-pkg/test-rpm-report-3.txt: Likewise
	* tests/data/test-diff-pkg/test-rpm-report-4.txt: Likewise
	* tests/test-diff-pkg.cc: New file

Signed-off-by: Sinny Kumari <sinny@redhat.com>
2015-07-17 10:10:21 +02:00
Dodji Seketeli
f154ff8db1 Remove extra vertical spaces from diff report
* src/abg-comparison.cc (class_diff::report): Do not emit new line
	unless the diff is to be reported.
	* tests/data/test-diff-filter/test25-cyclic-type-report-0.txt: Adjust.
	* tests/data/test-diff-filter/test26-qualified-redundant-node-report-0.txt: Adjust.
	* tests/data/test-diff-filter/test27-redundant-and-filtered-children-nodes-report-1.txt:
	: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-16 12:27:24 +02:00
Dodji Seketeli
f2175b70cc Adjust some tests for output changes
After commit "8a4b0c9 Fix missing newlines in diff report", I forgot
to adjust some test reference outputs, leading to some test failures.

Fixed thus.

	* tests/data/test-abidiff/test-struct1-report.txt: Adjust.
	* tests/data/test-diff-dwarf/test10-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test11-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test13-report.txt: Likewise.
	* tests/data/test-diff-filter/test2-report.txt: Likewise.
	* tests/data/test-diff-filter/test26-qualified-redundant-node-report-0.txt: Likewise.
	* tests/data/test-diff-filter/test26-qualified-redundant-node-report-1.txt: Likewise.
	* tests/data/test-diff-filter/test27-redundant-and-filtered-children-nodes-report-1.txt: Likewise.
	* tests/data/test-diff-filter/test27-redundant-and-filtered-children-nodes-report-2.txt: Likewise.

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

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

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

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

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-07-02 17:15:35 +02:00