Commit Graph

57 Commits

Author SHA1 Message Date
Dodji Seketeli
09de4435ce Bug 19092 - abidw aborts on types that violate the ODR
It appears that two different types from two different translation
units might have the same name in a DSO, like in the example of this
bug.  This violates the One Definition Rule, which we rely on to go
fast, and more importantly, it introduces type canonicalization errors.

This patch recognizes more of these ODR violation cases by looking at
the size of the types.  That is, if two types (from the same DSO) with
the same name have different sizes, then they are different.

	* src/abg-ir.cc (type_base::get_canonical_type_for): Look at the
	size of types with the same name which could be considered
	ODR-equal, to spot possible violations that would induce a type
	canonicalization error.
	* tests/data/test-read-dwarf/test21-pr19092.so: New test input
	binary.
	* tests/data/test-read-dwarf/test21-pr19092.so.abi: New reference
	abixml for the binary above.
	* tests/data/Makefile.am: Add the new test input above to source
	distribution.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Adjust.
	* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
	* tests/data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi:
	Likewise.
	* tests/test-read-dwarf.cc (int_out_specs): Add the two test input
	above.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-10-15 16:22:14 +02:00
Dodji Seketeli
33b4badd03 Adjust tests for the patchset
This is the last patch of the series of patches whose titles are
(including this one):

    Force late canonicalizing of function types read from abixml
    Fix strip_typedef issues
    Do not compare access specs for member types & functions
    Fix "is-anonymous" abixml property impact on some tests
    Fix const-ness of a function parameter
    Handle aliased function decls when comparing decls in general
    Make canonicalization non sensitive to struct-ness of subtypes
    Set the corpus of all ABI artifact reads from abixml
    Implement fast type lookup in a corpus
    Accelerate a slow path in hash_type_or_decl()
    A series of small speed optimizations here and there
    Allow only one definition of a given type per corpus in abixml
    Make abidw --abidiff not show definitely harmless changes
    Adjust tests for the patchset

This patch carries the numerous adjustments necessary for the
regresion tests output after this patch set.

	* 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/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.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.

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

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

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2015-06-04 13:30:16 +02:00
Dodji Seketeli
a05384675c Type read from DWARF don't have alignment information
Types read from DWARF don't have any alignment information so we
shouldn't try to guess it, especially for structures.  So this patch
sets the alignment to zero in that case.  This helps remove some
spurious alignment changes detected by abidiff just because in some
cases we fail to guess that.

In the process, I noticed that when calculating the hash value of a
given data member, we were not including the hash value of its
context.  This led to mistakenly considering some data member changes
as redundant.  So the patch fixes that too.

	* src/abg-dwarf-reader.cc (build_type_decl)
	(build_class_type_and_add_to_ir, build_pointer_type_def)
	(build_reference_type, build_function_decl): Set the alignment for
	native types, class, reference and function type to zero,
	effectively meaning that they don't have alignment information.
	* src/abg-hash.cc (var_decl:#️⃣:operator): Take the hash value
	of the data member context in account when computing the hash
	value of a given data member.
	* tests/data/test-diff-dwarf/test-23-diff-arch-report-0.txt:
	Adjust.
	* tests/data/test-diff-dwarf/test10-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test13-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test22-changed-parm-c-report-0.txt: Likewise.
	* tests/data/test-diff-dwarf/test26-added-parms-before-variadic-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test8-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test9-report.txt: Likewise.
	* tests/data/test-diff-filter/test13-report.txt: Likewise.
	* tests/data/test-diff-filter/test6-report.txt: Likewise.
	* tests/data/test-diff-suppr/test9-changed-parm-c-report-0.txt: Likewise.
	* tests/data/test-read-dwarf/test0.abi: Likewise.
	* tests/data/test-read-dwarf/test1.abi: Likewise.
	* tests/data/test-read-dwarf/test2.so.abi: Likewise.
	* 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-05-24 17:16:41 +02:00
Dodji Seketeli
a102a2f032 Add support for abicompat weak mode
This patch implements the weak mode of abicompat.  In this mode, just
the application and the new version of the library are provided.  The
types of functions and variables of the library that are consumed by
the application are compared to the types of the functions and
variables expected by the application.  The goal is to check if the
types of the declarations consumed by the application and provided by
the library are compatible with what the application expects.

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

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

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

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

To do this a number of changes were necessary.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

This is what this patch does.

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

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

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

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

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

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

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

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

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

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

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-08-15 18:27:04 +02:00
Dodji Seketeli
3b6d0ec0a9 Correctly write the name of a const reference type
* src/abg-dwarf-reader.cc (maybe_strip_qualification): Define new
	function.
	(build_ir_node_from_die): Use the maybe_strip_qualification when
	building a qualified type.
	* src/abg-ir.cc (qualified_type_def::build_name): Fix the
	representation of the name of a reference that is const.
	* tests/data/test-read-dwarf/test1.abi: Adjust.
	* tests/data/test-diff-dwarf/test0-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test1-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test6-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test7-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test8-report.txt: Likewise.
	* tests/data/test-diff-filter/test0-report.txt: Likewise.
	* tests/data/test-diff-filter/test01-report.txt: Likewise.
	* tests/data/test-diff-filter/test2-report.txt: Likewise.
	* tests/data/test-diff-filter/test3-report.txt: Likewise.
	* tests/data/test-diff-filter/test9-report.txt: Likewise.
	* tests/data/test-diff-filter/test10-report.txt: Likewise.
	* tests/data/test-diff-filter/test13-report.txt: Likewise.
	* tests/data/test-diff-filter/test14-0-report.txt: Likewise.
	* tests/data/test-diff-filter/test14-1-report.txt: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-07-18 18:55:23 +02:00
Sinny Kumari
fe6b9fb61b Consider symbols with STB_GNU_UNIQUE binding as public
* src/abg-ir.cc (is_public): Change in function to consider
	symbols with STB_GNU_UNIQUE binding as public
	* tests/data/test-read-dwarf/test6.cc: Test file to generate
	STB_GNU_UNIQUE binding symbols
	* tests/data/test-read-dwarf/test6.so: Test shared library having
	STB_GNU_UNIQUE binding symbols
	* tests/data/test-read-dwarf/test6.so.abi: XML file containing
	dwarf information from test6.so
	* tests/test-read-dwarf.cc (in_out_specs): Add the new test above
	* tests/Makefile.am: Add tests/data/test-read-dwarf/test6.cc,
	tests/data/test-read-dwarf/test6.so and
	tests/data/test-read-dwarf/test6.so.abi to the distribution

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

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-06-23 17:31:26 +02:00
Mark Wielaard
453ed93d01 Handle C99 restrict qualifier and DWARFv3 DW_TAG_restrict_type.
* src/abg-dwarf-reader.cc (build_qualified_type): Handle
	DW_TAG_restrict_type by adding CV_RESTRICT.
	(build_ir_node_from_die): Call build_qualified_type for
	DW_TAG_restrict_type.
	* src/abg-reader.cc (build_qualified_type_decl): Handle
	"restrict" attribute by adding CV_RESTRICT.
	* src/abg-writer.cc (write_qualified_type_def): Output
	"restrict" attribute for CV_RESTRICT.
	* tests/data/test-read-dwarf/test4.c: New test file.
	* tests/data/test-read-dwarf/test4.so: Likewise.
	* tests/data/test-read-dwarf/test4.so.abi: Likewise.
	* tests/data/test-read-write/test24.xml: Likewise.
	* tests/test-read-dwarf.cc (in_out_specs): Add test4.
	* tests/test-read-write.cc (in_out_specs): Add test24.xml.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
2014-06-23 15:55:37 +02:00
Sinny Kumari
64bd3adce5 Keep symbol's multiple aliases within single attribute separated by comma
* src/abg-writer.cc (write_elf_symbol_aliases): Changing function
	to keep multiple symbol aliases within one alias attribute
	* src/abg-reader.cc (build_elf_symbol_db): Changing function to read
	symbol's alias attribute and split if multiple alias exist with comma(,)
	asi a delimiter and add all aliases to main symbol
	* tests/data/test-read-dwarf/test3.c: Test file to generate multiple aliases
	* tests/data/test-read-dwarf/test3.so: Test shared library having multiple
	aliases of a symbol
	* tests/data/test-read-dwarf/test3.so.abi: XML file containing dwarf
	information from test3.so
	* tests/test-read-dwarf.cc (in_out_specs): Add the new test above
	* tests/Makefile.am: Add tests/data/test-read-dwarf/test3.c,
	tests/data/test-read-dwarf/test3.so and tests/data/test-read-dwarf/test3.so.abi
	to the distribution

Signed-off-by: Sinny Kumari <skumari@redhat.com>
2014-06-20 11:56:49 +02:00
Dodji Seketeli
5350583ec1 Fix scope for DIEs with specification or abstract_origin attributes
* src/abg-dwarf-reader.cc (get_scope_for_die): If the DIE has a
	DW_AT_specification or DW_AT_abstract_origin attribute, get the
	scope of the referred-to DIE.
	(build_ir_node_from_die): For a variable DIE that has a
	DW_AT_{specification,abstract_origin} attribute, do not add the
	built variable IR node to its scope because it is already in a
	scope.  It's in a scope because that built variable is for the DIE
	that is referred-to by the DW_AT_{specification,abstract_origin}
	attribute.  Likewise for member functions.  Also, now,
	get_scope_for_die can return a class for a function DIE because
	get_scope_for_die now returns the *logical* scope of the DIE; that
	is, it follows DW_AT_{specification,abstract_origin} attributes.
	* tests/data/test-read-dwarf/test1.abi: Adjust.

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

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-28 16:33:35 +02:00
Dodji Seketeli
0237455e57 Add clone in the scope of the cloned decl they logically belong to
* src/abg-dwarf-reader.cc (build_ir_node_from_die): Do not try to
	add the cloned function/variable to the current scope because
	cloning should have added the decl into the scope of the cloned
	target.
	* src/abg-ir.cc ({var,function}_decl::clone): Insert the clone
	decl into the scope of the cloned decl.  My understanding is that
	it's where they belong.
	* tests/data/test-read-dwarf/test1.abi: Update this to incorporate
	all the abstract constructors/destructors *and* their clones into
	the classes where they belong.
	* tests/data/test-read-dwarf/test1.abi: Adjust for the abstract
	cdtor being added to the class, as well as their cloned concrete
	instances.
	* tests/data/test-read-dwarf/test2.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-21 12:25:45 +02:00
Dodji Seketeli
c91461a8c8 Don't share types across TUs when DW_TAG_partial_unit are involved
* src/abg-dwarf-reader.cc (build_translation_unit_and_add_to_ir):
	Clear the part of the context that needs to be per TU.
	(build_ir_node_from_die): Assert that this should not be called
	for partial and imported unit because for now our practical
	assumption is that DIEs under partial unit are lazily read only
	when referenced by DIEs that are under DW_TAG_compile_unit.
	* tests/Makefile.am: Add the new test files to the build system.
	* tests/data/test-read-dwarf/test2.so.abi: Fix the reference
	output here to avoid sharing types across TUs, making the output
	valid for bilint.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-19 21:35:56 +02:00
Dodji Seketeli
c469546e45 Initial support for DW_TAG_partial_unit
* src/abg-dwarf-reader.cc (read_context::cur_tu_die_): New member.
	(read_context::read_context): Initialize the new member.
	(read_context::cur_tu_die): New accessors.
	(find_last_import_unit_point_before_die): New static function.
	(get_parent_die): Take a logical current die offset parameter.  If
	the die we want the parent for is a partial unit, then find the
	last DW_TAG_imported_unit that imports that partial unit before
	the logical current die and return the parent of that
	DW_TAG_imported_unit die.
	(get_scope_for_die): Take a logical current die offset parameter.
	Adjust.
	(build_translation_unit_and_add_to_ir): Set/unset the current
	translation unit DIE in the context.  Adjust.
	(build_namespace_decl_and_add_to_ir)
	(build_class_type_and_add_to_ir, build_qualified_type)
	(build_pointer_type_def, build_reference_type, build_typedef_type)
	(build_var_decl, build_function_decl, build_ir_node_from_die):
	Take a logical current die offset parameter.  Adjust.
	(build_corpus): Accept that we can have DIE that are not
	DW_TAG_compile_unit at the top level, because, well, we can now
	have DW_TAG_partial_unit too.
	* tests/data/test-read-dwarf/test2-{0,1}.cc: New test source
	files.
	* tests/data/test-read-dwarf/test2.h: Likewise.
	* tests/data/test-read-dwarf/test2.so: New input binary to read.
	* tests/data/test-read-dwarf/test2.so.abi: New reference test to
	compare against.
	* tests/test-read-dwarf.cc: Adjust to launch the new test.

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

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

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-05-12 16:09:47 +02:00
Dodji Seketeli
04a1e27258 Follow DW_AT_abstract_origin and add missing mangled name
* src/abg-dwarf-reader.cc (build_function_decl): Change signature
	to take function_decl to which one shall add properties that got
	added by subsequent DIEs later.
	(build_class_type_and_add_to_ir): Adjust.
	(build_function_decl): Allow adding new properties to an existing
	function_decl.  Add the mangled name in particular.
	* tests/data/test-read-dwarf/test1.abi: Update test.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2014-03-24 12:22:05 +01:00