Commit Graph

2780 Commits

Author SHA1 Message Date
Dodji Seketeli
ccc71fc0e0 Implement type hashing
The order in which types of the same name & kind (aka homonym types)
are canonicalized does have an impact on the final canonicalization
result.  This variation is at the root of the self-comparison error
happening on the gcc-gnat package in f37.  The command to reproduce
the issue is:

	$ fedabipkgdiff  -a --self-compare --from fc37 gcc-gnat

Note that the binary on which self-comparison is failing is gnat1 for
the s390 arch:

    $ pwd
    ~/git/libabigail/hash-types/prtests/extracts/gcc-gnat-12.3.1-1.fc37.s390x
    $
    $ abidw --debug-abidiff -d usr/lib/debug usr/libexec/gcc/s390x-redhat-linux/12/gnat1

That test is still failing with this patch, but is going to pass with
subsequent patches in the series.

Having persistent hashes that can be serialized along with the types
into ABIXML does help to suppress that variation.

This patch implements that idea.

Learning from the teachings of the DWZ tool, the patch uses the xxhash
algorithm for primitive hashing and hash combination.  The patch
prevents cycling while hashing type graphs by maintaining a hashing
state in objects being hashed, just like what DWZ does.

The patch cleans out the relics of the previous (failed) attempt of
using hashing in the IR.  Now, a virtual
type_or_decl_base::hash_value() is declared and implemented by
decl_base, type_base and descendants of type_base.

Each IR node has a "private" hashing function that knows how to hash
the specific parts of the IR node and combine the hashes of its
sub-type IR children nodes to come up with a hashing value for the
whole IR node, while preventing cycling.  There are some subtleties
introduced during the hashing.  For instance, a typedef hash is the
same as the hash of its underlying type.  This helps the hash value of
a pointer or reference to a typedef of class to be the same as the
hash value of a pointer or reference to the class.  Another subtlety
is to never hash the declaration of a class, if a definition is
present; rather, always hash the definition.  In general, types that
are not canonicalized (for which is_non_canonicalized_type returns
true) are not hashed.

That private hashing function is thus used by the ::hash_value()
of the IR node to compute the hash value for the first time and cache
it for it subsequent invocations.

After building the IR, the patch first sorts all types, then hashes
them and then canonicalizes them.  During the canonicalization phase,
two types with different hashes are deemed different.  Two types with
the same hash are compared structurally.

During ABIXML de-serialization, libabigail reads the hash value back
from each IR node and uses that instead of re-calculating the hash.

Note that calculating the hash of a node read from ABIXML could lead
to a different result than calculating the hash for the same node from
DWARF, because the order in which hashes are calculated counts,
especially for recursive types.  That is one of the reasons why hashes
are not re-calculated when reading from abixml.

In all fairness, I think we would need to test this hypothesis again,
because we now sort types before hashing them, so in theory, the
hashing should yield the same result as when done from ELF.
Regardless, just reading the hash values from ABIXML is faster than
re-calculating it.  We might want to re-calculate the hashes for
debugging purposes, however.  This is left as an exercise for the
astute reader of this patch.

If the hash of an ABIXML node equals the hash of an ELF node, then
during type canonicalization, the two nodes are compared structurally.
If the hashes are different, then the nodes compare different during
canonicalization.  That speeds up canonicalization at ABIXML reading
time.  But this implies that each change in a hashing scheme should
result in a change in the major ABIXML version number, rendering newer
ABIXML files incompatible with previous ones.  It even makes them
incompatible with newer libabigail code altogether.  In that case, we
might want to teach abidiff about ABIXML versioning, even when
comparing an ABIXML input against an ELF one.

Note that the patch uses the hashing during type canonicalization in
general; that is, if the hashes are present and different, then the
types are different.  That helps to do away with the need for the
"canonical type propagation" optimization that I suspect is causing
issues on redundant types.

It turns out that not using that optimization doesn't incur any
noticeable speed penalty so in a subsequent patch, that canonical type
propagation optimization code is going to be entirely removed.

The patch uses an optional value for hashes, to make the difference
between no-hash (for recursive sub-types and types supposed to have no
hash/canonical types) and a hash value of zero which is a valid hash
value.

Note that the patch emits hashes for function-decl elements.  This is
the hash of the type of the function.  When parsing ABIXML, the reader
sets that function-decl hash to the function_type built from it.

Also, note that for types having the same representation (homonym
types) and yet are canonically different, this patch emits a distinct
canonical type index (aka CTI).  That CTI is appended to the hash
value, following a "#" sign.

Later, during type canonicalization, two homonym types T and T' (where
T originates from ELF and T' originates from ABIXML) having the same
hash and CTI will be structurally compared.  If T equals T', then T
and T' will be considered canonically equivalent.  In other words,
CTIs help to match homonym types originating from ABIXML against
homonym types originating from ELF.

Note that 2 tests are still failing. They are fall-outs that are
addressed in subsequent patches.  This patch XFAIL them until they get
fixed by subsequent patches of the series.

	* configure.ac: Bump ABIXML version to 4.0.  Detect the new xxhash
	dependency and require the 0.8.0 version at minimum.
	* include/abg-fwd.h (look_through_decl_only_type): Declare new
	functions.
	(is_scope_decl): Const-ify the parameter and
	the returned value.  Also, do not include "abg-hash.h" here.
	* include/abg-hash.h: Make this include cstdint (for uint64_t) and
	abg-ir.h, instead of stdint.h.
	(enum hashing_state): Define new enum in the abigail::hashing
	namespace.
	(combine_hashes, fnv_has, hash, get_hashing_state)
	(set_hashing_state, is_recursive_artefact): Declare new functions
	in the abigail::hashing namespace.
	(struct {decl_base, type_base, type_decl, qualified_type_def,
	pointer_type_def, reference_type_def, ptr_to_mbr_type,
	array_type_def, enum_type_decl, typedef_decl, function_type,
	method_type, member_base, class_or_union, class_decl::base_spec,
	class_decl, union_decl}::hash): Declare new hash functors in the
	abigail::ir namespace.
	* include/abg-ir.h: Remove the inclusion of abg-hash.h from this
	header.
	(typedef hash_t): Define new type.
	(peek_hash_value): Declare new function.
	(get_canonical_types): Return a pointer to const vector.
	({type_or_decl_base, type_base, qualified_type_def,
	pointer_type_def, reference_type_def, ptr_to_mbr_type,
	array_type_def::subrange_type, typedef_decl, function_type,
	method_type, class_or_union, class_decl, class_decl::base_spec,
	union_decl}::hash_value): Add new virtual member functions.
	(type_or_decl_base::set_hash_value): Add new member function.
	(type_or_decl_base::priv_): Make this data member public.
	(peek_hash_value, set_or_get_cached_hash_value): Declare these
	functions as friends of class type_or_decl_base.
	({decl_base, scope_decl, var_decl, function_decl,
	function_decl::parameter}::get_hash): Remove member functions.
	* src/abg-comparison-priv.h (types_or_decls_hash::operator()):
	Adjust to using the new hash_t type.
	* src/abg-ctf-reader.cc
	(reader::{additional_types_to_canonicalize, types}): Add new data
	members.
	(reader::add_type(): Add new member function.
	(reader::canonicalize_all_types): Use the new types vector data
	member to stash types to be canonicalized and pass them to
	ir::hash_and_canonicalize_types for canonicalization.
	(process_ctf_base_type)
	(build_ir_node_for_variadic_parameter_type)
	(build_ir_node_for_void_type, build_ir_node_for_void_pointer_type)
	(build_array_ctf_range, process_ctf_enum_type): Do not use
	canonicalize anymore.  Rather, rely on reader::add_type to
	schedule types for canonicalization, doing the generic sorting and
	hashing before doing the actually canonicalization.
	* src/abg-dwarf-reader.cc ({dwarf_offset_pair_hash,offset_hash,
	offset_pair_hash}::operator()): Use the new hashing function.
	(reader::read_debug_info_into_corpus): Improve logging.  Use
	ir::hash_and_canonicalize_types in lieu of ir::canonicalize_types.
	(reader::types_to_canonicalize): Add
	non-const overload.
	(reader::canonicalize_types_scheduled): Add better logs & misc
	obvious cleanup.
	(maybe_canonicalize_type): Force scheduling canonicalization of
	all types at the end of the DWARF processing.
	* src/abg-hash.cc (combine_hashes, hash, get_hashing_state)
	(set_hashing_state, is_recursive_artefact): Define new functions.
	(MAYBE_RETURN_EARLY_FROM_HASHING_TO_AVOID_CYCLES)
	(MAYBE_FLAG_TYPE_AS_RECURSIVE)
	(MAYBE_RETURN_EARLY_IF_HASH_EXISTS): Define new macros.
	(struct {decl_base, type_base, type_decl, qualified_type_def,
	pointer_type_def, reference_type_def, ptr_to_mbr_type,
	array_type_def, ptr_to_mbr_type, enum_type_decl, typedef_decl,
	function_decl, function_type, method_type, member_base,
	class_or_union, class_decl::base_spec, class_decl,
	union_decl}:#️⃣:operator): Define new hash functors.
	({template_parameter, template_decl, non_type_tparameter,
	template_tparameter, type_composition, type_composition,
	function_tdecl}::{hash, dynamic_hash, shared_ptr_hash): Remove.
	* src/abg-ir-priv.h: Don't include abg-ir.h anymore, rather
	include abg-hash.h.
	(struct type_or_decl_base::priv): Move this here, from abg-ir.cc.
	(type_or_decl_base::priv::{hashing_state_, hash_value_,
	is_recursive_artefact_}): Define new data members.
	(type_or_decl_base::priv::{get_hashing_state, set_hashing_state,
	set_hash_value, force_set_hash_value, is_recursive_artefact}):
	Define new member functions.
	(struct sort_for_hash_functor): Define new functor.
	(do_hash_value, set_or_get_cached_hash_value)
	(hash_and_canonicalize_types, sort_and_canonicalize_types): Define
	new function templates.
	(type_is_suitable_for_hash_computing)
	(sort_types_for_hash_computing_and_c14n)
	(get_canonical_type_index, get_decl_name_for_comparison): Declare
	new functions.
	(type_base::priv::canonical_type_index): New data member.
	(type_base::priv::{priv, clear_propagated_canonical_type}):
	Initialize it.
	(uint64_t_pair_hash::operator()): Adjust.
	(environment::priv::number_of_canonical_types): New data member.
	(environment::priv::priv): Initialize it.
	(environment::priv::get_new_canonical_type_index): New member
	function.
	(environment::priv::propagate_ct): Propagate the CTI too.
	(environment::priv::{confirm_ct_propagation_for_types_dependant_on,
	confirm_ct_propagation}): Assert that canonical type has been
	propagated and thus we have a canonical type.
	(struct type_topo_comp::operator()): Beef up sorting of types.
	Take into account the absolute path of the TU, the hash value, the
	CTI)
	(struct sort_for_hash_functor): Define new functor.
	(sort_types_for_hash_computing_and_c14n): Declare new function
	template and new overload.
	(canonicalize_types): Take new do_log and show_stats parameters.
	Improve logging.  Do not sort types in here.
	(hash_and_canonicalize_types): Define new function template.  This
	one does the sorting before the hashing and the canonicalization.
	(sort_and_canonicalize_types): Likewise, but this one does no
	hashing.
	(cache_type_comparison_result): Cache the result of the comparison
	now, unconditionally.  As we don't do canonical type propagation
	anymore, we should not get canonical types and equality to
	disagree anymore.
	(* src/abg-ir.cc (try_canonical_compare): If hash values are
	present and different then the two types are different.
	(environment::get_canonical_types): Constify return value.
	(environment::get_canonical_type): Adjust.
	(struct type_or_decl_base::priv): Move this to abg-ir-priv.h.
	(type_or_decl_base::hashing_started): Remove.
	({decl_base, scope_decl, var_decl, function_decl,
	function_decl::parameter, class_decl::base_spec,
	non_type_tparameter, type_composition}::get_hash): Likewise.
	({template_parameter}::get_hashing_has_started)
	(template_parameter::set_hashing_has_started): Likewise.
	(type_or_decl_base::{hash_value, set_hash_value})
	({type_base, type_decl, qualified_type_def, pointer_type_def,
	reference_type_def, ptr_to_mbr_type,
	array_type_def::subrange_type, array_type_def, enum_type_decl,
	typedef_decl, function_type, method_type, class_or_union,
	class_decl::base_spec, class_decl, union_decl}::hash_value):
	Define new member functions.
	(type_or_decl_base::set_hash_value): Likewise.
	(get_decl_name_for_comparison): Make this non-static.
	(is_scope_decl): Constify.
	(type_is_suitable_for_hash_computing)
	(peek_hash_value, read_type_hash, read_hash_and_stash)
	(look_through_decl_only_type)
	(candidate_matches_a_canonical_type_hash)
	(sort_types_for_hash_computing_and_c14n): Define new functions.
	(lookup_pointer_type, lookup_reference_type)
	(pointer_type_def::get_qualified_name)
	(reference_type_def::get_qualified_name)
	(reference_type_def::get_pretty_representation): Adjust.
	(get_type_name):  Better handle naming of anonymous type decls,
	used for enums.
	(get_debug_representation): Adjust to emit hashes & CTI of types
	as well as member types while debugging.
	(look_through_decl_only_type): Rename look_through_decl_only into
	this.
	(lookup_pointer_type, lookup_reference_type)
	(reference_type_def::get_qualified_name): Adjust.
	(compare_canonical_type_against_candidate): Stop doing canonical
	type propagation during type canonicalization.
	(type_base::get_canonical_type_for): Use the new
	candidate_matches_a_canonical_type_hash.  Set the canonical type
	index for homophone canonical types.  In debug mode, check that if
	a type equals a canonical type, their hash value must match.
	(canonicalize): Take new do_log and show_stats parameter.  Improve
	logging.  Also, a type must have the same CTI as its canonical
	type.
	(hash_type_or_decl): Adjust to use the new type
	hash_t.
	(type_topo_comp::operator()): Add an overload for type_base_wptr.
	If the two pointers are equal, get out early.  Otherwise, if
	everything else is equal, sort using the absolute path of the
	containing translation unit.
	(maybe_propagate_canonical_type): Propagate canonical type only if
	their CTI match.
	* src/abg-reader.cc (maybe_canonicalize_type): Improve logging.
	Schedule all types for late canonicalization.
	(reader::perform_type_canonicalization): Improve logging.  Call
	hash_and_canonicalize_types to hash and canonicalize types.
	(read_type_hash_and_cti, read_hash_and_stash): Define new static
	functions.
	(build_function_decl, build_type_decl)
	(build_qualified_type_decl)
	(build_pointer_type_def, build_reference_type_def)
	(build_ptr_to_mbr_type, build_function_type, build_subrange_type)
	(build_array_type_def, build_enum_type_decl, build_typedef_decl)
	(build_class_decl, build_union_decl): Read and set the hash value
	from ABIXML.
	(build_function_decl, build_qualified_type_decl)
	(build_pointer_type_def, build_reference_type_def)
	(build_function_type, build_subrange_type, build_array_type_def)
	(build_enum_type_decl, build_typedef_decl, build_class_decl)
	(build_union_decl): Read the hash and CTI and set them to the
	type.
	(build_reference_type_def): Build the referenced type before-hand.
	(build_class_tdecl, build_type_tparameter, build_type_composition)
	(build_template_tparameter, build_type, handle_type_decl)
	(handle_qualified_type_decl, handle_pointer_type_def)
	(handle_reference_type_def, handle_function_type)
	(handle_array_type_def, handle_enum_type_decl)
	(handle_typedef_decl, handle_class_decl, handle_union_decl):
	Adjust to the use of the new maybe_canonicalize_type signature.
	* src/abg-btf-reader.cc (reader::canonicalize_types): Use the new
	hash_and_canonicalize_types defined above.  Log the time taken by
	type canonicalization.
	* src/abg-ctf-reader.cc (reader::{types,
	additional_types_to_canonicalize}): New data members
	(reader::add_types): New member functions.
	(reader::canonicalize_all_types): Use the new
	hash_and_canonicalize_types defined above.
	(process_ctf_base_type): Do not call canonicalize here.
	(build_ir_node_for_variadic_parameter_type)
	(build_ir_node_for_void_type)
	(build_ir_node_for_void_pointer_type, process_ctf_enum_type):
	Likewise, and call reader::add_type instead.
	* src/abg-dwarf-reader.cc ({dwarf_offset_pair_hash, offset_hash,
	offset_pair_hash}::operator()): Adjust to using the new hash_t
	type.
	(reader::canonicalize_types_scheduled): Use the new
	hash_and_canonicalize_types above.
	(maybe_canonicalize_type): Schedule all types for late
	canonicalization.
	* src/abg-writer.cc (reader::get_id_for_type): Constify the
	parameter.
	(write_type_hash_and_cti, write_common_type_info)
	(write_fn_parm_and_return_types): Define new static functions.
	(write_type_decl, write_qualified_type_def)
	(write_pointer_type_def, write_reference_type_def)
	(write_array_subrange_type, write_array_type_def)
	(write_enum_type_decl, write_typedef_decl, write_function_decl)
	(write_function_type, write_class_decl_opening_tag)
	(write_union_decl_opening_tag): Emit hash value and CTI to the
	ABIXML.
	* tests/Makefile.am: XFAIL the tests runtestdifffilter and
	runtestabidiffexit for now.
	* tests/data/test-abidiff-exit/PR30329/PR30329-report-1.txt:
	Adjust.
	* tests/data/test-annotate/PR29443-missing-xx.o.annotated.abi:
	Likewise.
	* tests/data/test-annotate/libtest23.so.abi: Likewise.
	* tests/data/test-annotate/libtest24-drop-fns-2.so.abi: Likewise.
	* tests/data/test-annotate/libtest24-drop-fns.so.abi: Likewise.
	* tests/data/test-annotate/test-anonymous-members-0.o.abi:
	Likewise.
	* tests/data/test-annotate/test-pointer-to-member-1.o.annotated.abi:
	Likewise.
	* tests/data/test-annotate/test0.abi: Likewise.
	* tests/data/test-annotate/test1.abi: Likewise.
	* tests/data/test-annotate/test13-pr18894.so.abi: Likewise.
	* tests/data/test-annotate/test14-pr18893.so.abi: Likewise.
	* tests/data/test-annotate/test15-pr18892.so.abi: Likewise.
	* tests/data/test-annotate/test17-pr19027.so.abi: Likewise.
	* tests/data/test-annotate/test18-pr19037-libvtkRenderingLIC-6.1.so.abi:
	Likewise.
	* tests/data/test-annotate/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Likewise.
	* tests/data/test-annotate/test2.so.abi: Likewise.
	* tests/data/test-annotate/test20-pr19025-libvtkParallelCore-6.1.so.abi:
	Likewise.
	* tests/data/test-annotate/test21-pr19092.so.abi: Likewise.
	* tests/data/test-annotate/test3.so.abi: Likewise.
	* tests/data/test-annotate/test4.so.abi: Likewise.
	* tests/data/test-annotate/test5.o.abi: Likewise.
	* tests/data/test-annotate/test6.so.abi: Likewise.
	* tests/data/test-annotate/test7.so.abi: Likewise.
	* tests/data/test-annotate/test8-qualified-this-pointer.so.abi:
	Likewise.
	* tests/data/test-diff-dwarf-abixml/PR25409-librte_bus_dpaa.so.20.0.abi:
	Likewise.
	* tests/data/test-diff-dwarf-abixml/test0-pr19026-libvtkIOSQL-6.1.so.1.abi:
	Likewise.
	* tests/data/test-diff-filter/test-PR26739-2-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test3-report.txt: Likewise.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt:
	Likewise.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report1.txt:
	Likewise.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report2.txt:
	Likewise.
	* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-1.txt:
	Likewise.
	* tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt:
	Likewise.
	* tests/data/test-diff-filter/test43-decl-only-def-change-leaf-report-0.txt:
	Likewise.
	* tests/data/test-diff-pkg-ctf/gmp-6.x.x86_64-report-0.txt:
	Likewise.
	* tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt:
	Likewise.
	* tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt:
	Likewise.
	* tests/data/test-read-btf/test0.o.abi: Likewise.
	* tests/data/test-read-btf/test1.o.abi: Likewise.
	* tests/data/test-read-ctf/PR27700/test-PR27700.abi: Likewise.
	* tests/data/test-read-ctf/test-PR26568-1.o.abi: Likewise.
	* tests/data/test-read-ctf/test-PR26568-2.o.abi: Likewise.
	* tests/data/test-read-ctf/test-alias.o.abi: Likewise.
	* tests/data/test-read-ctf/test-ambiguous-struct-A.o.hash.abi:
	Likewise.
	* tests/data/test-read-ctf/test-ambiguous-struct-B.o.hash.abi:
	Likewise.
	* tests/data/test-read-ctf/test-anonymous-fields.o.abi: Likewise.
	* tests/data/test-read-ctf/test-array-mdimension.abi: Likewise.
	* tests/data/test-read-ctf/test-array-of-pointers.abi: Likewise.
	* tests/data/test-read-ctf/test-array-size.abi: Likewise.
	* tests/data/test-read-ctf/test-bitfield-enum.abi: Likewise.
	* tests/data/test-read-ctf/test-bitfield.abi: Likewise.
	* tests/data/test-read-ctf/test-callback.abi: Likewise.
	* tests/data/test-read-ctf/test-callback2.abi: Likewise.
	* tests/data/test-read-ctf/test-conflicting-type-syms-a.o.hash.abi:
	Likewise.
	* tests/data/test-read-ctf/test-conflicting-type-syms-b.o.hash.abi:
	Likewise.
	* tests/data/test-read-ctf/test-const-array.abi: Likewise.
	* tests/data/test-read-ctf/test-dynamic-array.o.abi: Likewise.
	* tests/data/test-read-ctf/test-enum-many.o.hash.abi: Likewise.
	* tests/data/test-read-ctf/test-enum-symbol.o.hash.abi: Likewise.
	* tests/data/test-read-ctf/test-enum.o.abi: Likewise.
	* tests/data/test-read-ctf/test-fallback.abi: Likewise.
	* tests/data/test-read-ctf/test-forward-type-decl.abi: Likewise.
	* tests/data/test-read-ctf/test-functions-declaration.abi:
	Likewise.
	* tests/data/test-read-ctf/test-linux-module.abi: Likewise.
	* tests/data/test-read-ctf/test-list-struct.abi: Likewise.
	* tests/data/test-read-ctf/test0.abi: Likewise.
	* tests/data/test-read-ctf/test0.hash.abi: Likewise.
	* tests/data/test-read-ctf/test1.so.abi: Likewise.
	* tests/data/test-read-ctf/test1.so.hash.abi: Likewise.
	* tests/data/test-read-ctf/test2.so.abi: Likewise.
	* tests/data/test-read-ctf/test2.so.hash.abi: Likewise.
	* tests/data/test-read-ctf/test3.so.abi: Likewise.
	* tests/data/test-read-ctf/test3.so.hash.abi: Likewise.
	* tests/data/test-read-ctf/test4.so.abi: Likewise.
	* tests/data/test-read-ctf/test4.so.hash.abi: Likewise.
	* tests/data/test-read-ctf/test5.o.abi: Likewise.
	* tests/data/test-read-ctf/test7.o.abi: Likewise.
	* tests/data/test-read-ctf/test8.o.abi: Likewise.
	* tests/data/test-read-ctf/test9.o.abi: Likewise.
	* tests/data/test-read-dwarf/PR22015-libboost_iostreams.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/PR22122-libftdc.so.abi: Likewise.
	* tests/data/test-read-dwarf/PR24378-fn-is-not-scope.abi:
	Likewise.
	* tests/data/test-read-dwarf/PR25007-sdhci.ko.abi: Likewise.
	* tests/data/test-read-dwarf/PR25042-libgdbm-clang-dwarf5.so.6.0.0.abi:
	Likewise.
	* tests/data/test-read-dwarf/PR26261/PR26261-exe.abi: Likewise.
	* tests/data/test-read-dwarf/PR27700/test-PR27700.abi: Likewise.
	* tests/data/test-read-dwarf/PR28584/PR28584-smv.clang.o.abi:
	Likewise.
	* tests/data/test-read-dwarf/PR29443-missing-xx.o.abi: Likewise.
	* tests/data/test-read-dwarf/PR29692-kdelibs3-libkjava.so.1.0.0.abi:
	Likewise.
	* tests/data/test-read-dwarf/libtest23.so.abi: Likewise.
	* tests/data/test-read-dwarf/libtest24-drop-fns-2.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/libtest24-drop-fns.so.abi: Likewise.
	* tests/data/test-read-dwarf/test-PR26568-1.o.abi: Likewise.
	* tests/data/test-read-dwarf/test-PR26568-2.o.abi: Likewise.
	* tests/data/test-read-dwarf/test-fallback.abi: Likewise.
	* tests/data/test-read-dwarf/test-libaaudio.so.abi: Likewise.
	* tests/data/test-read-dwarf/test-libandroid.so.abi: Likewise.
	* tests/data/test-read-dwarf/test-pointer-to-member-1.o.abi:
	Likewise.
	* tests/data/test-read-dwarf/test-suppressed-alias.o.abi:
	Likewise.
	* tests/data/test-read-dwarf/test0.abi: Likewise.
	* tests/data/test-read-dwarf/test0.hash.abi: Likewise.
	* tests/data/test-read-dwarf/test1.abi: Likewise.
	* tests/data/test-read-dwarf/test1.hash.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/test2.so.abi: Likewise.
	* tests/data/test-read-dwarf/test2.so.hash.abi: Likewise.
	* tests/data/test-read-dwarf/test20-pr19025-libvtkParallelCore-6.1.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test21-pr19092.so.abi: Likewise.
	* tests/data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test3-alias-1.so.hash.abi: Likewise.
	* tests/data/test-read-dwarf/test3-alias-2.so.hash.abi: Likewise.
	* tests/data/test-read-dwarf/test3-alias-3.so.hash.abi: Likewise.
	* tests/data/test-read-dwarf/test3-alias-4.so.hash.abi: Likewise.
	* tests/data/test-read-dwarf/test3.so.abi: Likewise.
	* tests/data/test-read-dwarf/test3.so.hash.abi: Likewise.
	* tests/data/test-read-dwarf/test4.so.abi: Likewise.
	* tests/data/test-read-dwarf/test4.so.hash.abi: Likewise.
	* tests/data/test-read-dwarf/test5.o.abi: Likewise.
	* tests/data/test-read-dwarf/test5.o.hash.abi: Likewise.
	* tests/data/test-read-dwarf/test6.so.abi: Likewise.
	* tests/data/test-read-dwarf/test6.so.hash.abi: Likewise.
	* tests/data/test-read-dwarf/test7.so.abi: Likewise.
	* tests/data/test-read-dwarf/test7.so.hash.abi: Likewise.
	* tests/data/test-read-dwarf/test8-qualified-this-pointer.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test8-qualified-this-pointer.so.hash.abi:
	Likewise.
	* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
	* tests/data/test-read-write/test-crc.xml: Likewise.
	* tests/data/test-read-write/test0.xml: Likewise.
	* tests/data/test-read-write/test1.xml: Likewise.
	* tests/data/test-read-write/test10.xml: Likewise.
	* tests/data/test-read-write/test11.xml: Likewise.
	* tests/data/test-read-write/test12.xml: Likewise.
	* tests/data/test-read-write/test13.xml: Likewise.
	* tests/data/test-read-write/test14.xml: Likewise.
	* tests/data/test-read-write/test15.xml: Likewise.
	* tests/data/test-read-write/test16.xml: Likewise.
	* tests/data/test-read-write/test17.xml: Likewise.
	* tests/data/test-read-write/test18.xml: Likewise.
	* tests/data/test-read-write/test19.xml: Likewise.
	* tests/data/test-read-write/test2.xml: Likewise.
	* tests/data/test-read-write/test20.xml: Likewise.
	* tests/data/test-read-write/test21.xml: Likewise.
	* tests/data/test-read-write/test22.xml: Likewise.
	* tests/data/test-read-write/test23.xml: Likewise.
	* tests/data/test-read-write/test24.xml: Likewise.
	* tests/data/test-read-write/test25.xml: Likewise.
	* tests/data/test-read-write/test26.xml: Likewise.
	* tests/data/test-read-write/test27.xml: Likewise.
	* tests/data/test-read-write/test28-without-std-fns-ref.xml:
	Likewise.
	* tests/data/test-read-write/test28-without-std-vars-ref.xml:
	Likewise.
	* tests/data/test-read-write/test3.xml: Likewise.
	* tests/data/test-read-write/test4.xml: Likewise.
	* tests/data/test-read-write/test5.xml: Likewise.
	* tests/data/test-read-write/test6.xml: Likewise.
	* tests/data/test-read-write/test7.xml: Likewise.
	* tests/data/test-read-write/test8.xml: Likewise.
	* tests/data/test-read-write/test9.xml: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-29 17:15:43 +02:00
Dodji Seketeli
dc870a640b abipkgdiff: Make --verbose enable the library's logging
Up until now, --verbose would triggers logging inside the abipkgdiff
tool itself.  This patch allows it to see the logs of the library too.

	* tools/abipkgdiff.cc (set_generic_options): Make --verbose
	trigger the logs of the library.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-29 15:20:42 +02:00
Dodji Seketeli
ae57c22115 dwarf-reader: Do not fix ELF symbols for virtual destructors
There are cases in DWARF emitted by old producers where some member
function DIEs lack reference to the ELF symbol they relate to.  To
address that issue the DWARF reader sets some functions (with linkage
name and no ELF symbol) to the ELF symbol matching that linkage name.

We should not do that destructors however, because of false positives
and because it seems destructors are well handled even by the old
producers that I had access to.

This finishes to fix the self-comparison of the llvm-libs package of fc37.

	* src/abg-dwarf-reader.cc (finish_member_function_reading): Do not
	schedule virtual destructors for ELF symbol-related function
	fixup.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-29 15:09:18 +02:00
Dodji Seketeli
5e9896dd2e ctf-reader: Make logging more obvious
Prefix the logs of the CTF reader with "CTF Reader:" so that it is
obvious to see where the logs come from.

	* src/abg-ctf-reader.cc (reader::read_corpus): Prefix the logs
	with "CTF Reader".

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-29 15:09:09 +02:00
Dodji Seketeli
44ba857592 dwarf-reader: Fix support of suppression specifications
While looking at something else, I realized that when functions and
variables are to be dropped on the floor by a suppression
specification, there are time where the function is suppressed but not
dropped from the ABI corpus.  This is due to some thinkos in the DWARF
reader code.  Fixed thus.

	* src/abg-dwarf-reader.cc (function_is_suppressed)
	(variable_is_suppressed): Do not return too early when the
	function doesn't seem suppressed, yet.
	* tests/data/test-diff-suppr/test31-report-0.txt: Adjust.
	* tests/data/test-diff-suppr/test32-report-1.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-29 13:59:05 +02:00
Dodji Seketeli
b6e616cc92 btf-reader: Add logging methods
* src/abg-btf-reader.cc (reader::{do_log, show_stats}): Add new
	methods.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-29 13:58:54 +02:00
Dodji Seketeli
bcdb42782c dwarf-reader: Better support concrete instance functions DIEs
abidiff wrongly reports this change while comparing two binaries[1]:

  [C] 'function void g_cclosure_marshal_VOID__BOOLEAN(GClosure*, GValue*, guint, const GValue*, gpointer, gpointer)' at gmarshal.c:188:1 has some indirect sub-type changes:
    parameter 2 of type 'GValue*' changed:
      entity changed from 'GValue*' to 'typedef guint' at gtypes.h:61:1
      type size changed from 64 to 32 (in bits)
    parameter 3 of type 'typedef guint' changed:
      entity changed from 'typedef guint' to 'GValue*'
      type size changed from 32 to 64 (in bits)
    parameter 4 of type 'const GValue*' changed:
      in pointed to type 'const GValue' at gclosure.h:77:1:
        entity changed from 'const GValue' to 'typedef GClosure' at gclosure.h:77:1
        type size changed from 192 to 256 (in bits)
    parameter 6 of type 'typedef gpointer' changed:
      typedef name changed from gpointer to guint at gtypes.h:61:1
      underlying type 'void*' changed:
        entity changed from 'void*' to 'unsigned int'
        type size changed from 0 to 32 (in bits)
    parameter 7 of type 'const GValue*' was added
    parameter 8 of type 'typedef gpointer' was added
    parameter 9 of type 'typedef gpointer' was added

Let's look at the DWARF of the newer binary:

The abstract DIE for the g_cclosure_marshal_VOID__BOOLEAN is:
 [ 62c87]    subprogram           abbrev: 100
             external             (flag_present) yes
             name                 (strp) "g_cclosure_marshal_VOID__BOOLEAN"
             decl_file            (implicit_const) gmarshal.c (19)
             decl_line            (data1) 188
             decl_column          (implicit_const) 1
             prototyped           (flag_present) yes
             sibling              (ref_udata) [ 62d20]
 [ 62c8f]      formal_parameter     abbrev: 28
               name                 (GNU_strp_alt) "closure"
               decl_file            (data1) gmarshal.c (19)
               decl_line            (data1) 188
               decl_column          (data1) 49
               type                 (ref_addr) [   b10]
 [ 62c9b]      formal_parameter     abbrev: 28
               name                 (GNU_strp_alt) "return_value"
               decl_file            (data1) gmarshal.c (19)
               decl_line            (data1) 189
               decl_column          (data1) 49
               type                 (ref_addr) [   9db]
 [ 62ca7]      formal_parameter     abbrev: 28
               name                 (GNU_strp_alt) "n_param_values"
               decl_file            (data1) gmarshal.c (19)
               decl_line            (data1) 190
               decl_column          (data1) 49
               type                 (ref_addr) [   4e8]
 [ 62cb3]      formal_parameter     abbrev: 28
               name                 (GNU_strp_alt) "param_values"
               decl_file            (data1) gmarshal.c (19)
               decl_line            (data1) 191
               decl_column          (data1) 49
               type                 (ref_addr) [   9dd]
 [ 62cbf]      formal_parameter     abbrev: 28
               name                 (GNU_strp_alt) "invocation_hint"
               decl_file            (data1) gmarshal.c (19)
               decl_line            (data1) 192
               decl_column          (data1) 49
               type                 (ref_addr) [   3a0]
 [ 62ccb]      formal_parameter     abbrev: 28
               name                 (GNU_strp_alt) "marshal_data"
               decl_file            (data1) gmarshal.c (19)
               decl_line            (data1) 193
               decl_column          (data1) 49
               type                 (ref_addr) [   3a0]

Let's focus on its second parameter.  Its DIE is:
 [ 62c9b]      formal_parameter     abbrev: 28
               name                 (GNU_strp_alt) "return_value"
               decl_file            (data1) gmarshal.c (19)
               decl_line            (data1) 189
               decl_column          (data1) 49
               type                 (ref_addr) [   9db]

Of type:

 [   9db]    pointer_type         abbrev: 43
             byte_size            (implicit_const) 8
             type                 (ref_udata) [   9aa]
[...]
 [   9aa]    typedef              abbrev: 36
             name                 (GNU_strp_alt) "GValue"
             decl_file            (data1) gtype.h (9)
             decl_line            (data2) 431
             decl_column          (data1) 41
             type                 (ref_udata) [   9b6]

So it's a "GValue*" type.

Now, the concrete instance of that abstract DIE, which represent the
concrete function is:

 [ 12125]    subprogram           abbrev: 87
             abstract_origin      (ref_addr) [ 62c87]
             low_pc               (addr) +0x000000000001c450 <g_cclosure_marshal_VOID__BOOLEAN.part.0>
             high_pc              (udata) 100 (+0x000000000001c4b4)
             frame_base           (exprloc)
              [ 0] call_frame_cfa
             sibling              (ref_udata) [ 121de]
 [ 12138]      formal_parameter     abbrev: 58
               abstract_origin      (ref_addr) [ 62c8f]
               location             (sec_offset) location list [  c2dc]
               GNU_locviews         (sec_offset) location list [  c2d2]
 [ 12145]      formal_parameter     abbrev: 58
               abstract_origin      (ref_addr) [ 62cb3]
               location             (sec_offset) location list [  c317]
               GNU_locviews         (sec_offset) location list [  c30d]
 [ 12152]      formal_parameter     abbrev: 58
               abstract_origin      (ref_addr) [ 62ccb]
               location             (sec_offset) location list [  c354]
               GNU_locviews         (sec_offset) location list [  c348]
 [ 1218b]      formal_parameter     abbrev: 58
               abstract_origin      (ref_addr) [ 62cbf]
               location             (sec_offset) location list [  c3f9]
               GNU_locviews         (sec_offset) location list [  c3f7]
 [ 12198]      formal_parameter     abbrev: 58
               abstract_origin      (ref_addr) [ 62ca7]
               location             (sec_offset) location list [  c40a]
               GNU_locviews         (sec_offset) location list [  c408]
 [ 121a5]      formal_parameter     abbrev: 58
               abstract_origin      (ref_addr) [ 62c9b]
               location             (sec_offset) location list [  c41b]
               GNU_locviews         (sec_offset) location list [  c419]

Note how the formal parameters of that concrete instance are all in a
different order than the ones of the concrete instance ...

In this case, when reading the concrete instance, we need to get the
IR of the function from the abstract instance DIE and then only read
the potential complementary attributes from this concrete instance.

The DWARF reader mistakenly builds the IR for the function from the
concrete instance in this case, hence the wrong change reported down
the road.

This patch fixes that.

Note that artifacts coming from that bug, reported on IRC have been
added to the libabigail-tests.git test suite.

[1]: https://gitlab.com/freedesktop-sdk/freedesktop-sdk/-/merge_requests/21393#note_2077175107

	* src/abg-dwarf-reader.cc (build_ir_node_from_die):  If the DIE is
	a concrete instance of an abstract one, then get the IR from the
	abstract one as it has all the types right.
	* tests/data/test-annotate/test14-pr18893.so.abi: Adjust.
	* tests/data/test-diff-pkg/PR24690/PR24690-report-0.txt: Likewise.
	* tests/data/test-diff-pkg/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-report-2.txt:
	Likewise.
	* tests/data/test-diff-pkg/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-report-3.txt:
	Likewise.
	* tests/data/test-read-dwarf/test-libandroid.so.abi: Likewise.
	* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-28 17:52:02 +02:00
Dodji Seketeli
3c33437ddf ctf-reader: Enumerate dicts in the archive rather than using their name
ctf::reader::process_ctf_archive calls ctf_dict_open with the name of
the (parent) dictionary to open.  If that parent dictionary is set to
an unexpected name, then the call to ctf_dict_open fails.  This can
happen for instance when at link time, the name of the parent
dictionary is set to an arbitrary name using the
"ctf_link_set_memb_name_changer" function.

This patch enumerates the dictionaries of the archive to avoid having
to know the name of the parent dictionary.  The enumeration is done
using the ctf_archive_next function of libctf.

There is currently no binary with an unexpected dictionary name in the
test suite so this patch cannot be tested for that particular case.
I'd be glad to have such binaries added to the test suite.

In the mean time this patch has been tested successfully using "make
fullcheck" on the existing test suite.

	* src/abg-ctf-reader.cc (reader::process_ctf_archive):  Do not use
	ctf_dict_open to open the dictionary by name.  Rather, enumerate
	the dictionaries of the current archive by using ctf_archive_next
	just like what lookup_symbol_in_ctf_archive does.  Set the
	argument of the skip_parent parameter to "false" to ensure we get
	the parent dictionary.
	(lookup_symbol_in_ctf_archive): Clean this up to properly
	initialize the parameters and to document the arguments to the
	parameters of ctf_archive_next.  Use nullptr instead of NULL.
	* tests/data/test-diff-pkg-ctf/test-rpm-report-1.txt: Adjust.
	* tests/data/test-diff-pkg-ctf/test-rpm-report-2.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-20 19:37:56 +02:00
Dodji Seketeli
0278493b72 ir: Handle ptr to fn type member with empty void return type
If a pointer to member type points to a function type that has an
empty return type, sometimes that can lead to a crash.  This patch
considers that the empty return type is a void type.

	* src/abg-ir.cc (add_outer_ptr_to_mbr_type_expr): If the function
	type has no return type, consider it as void type.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-16 20:44:21 +02:00
Dodji Seketeli
2e1dbb2a6f reader: Avoid empty return type node for a function type IR
Sometimes, the function type IR can have an empty node as return type,
to represent void.  This can wreak havoc on some part of the code that
don't expect that.  This patch uses a proper void type node for that
instead.

	* src/abg-reader.cc (build_function_type): If the return type node
	is empty, use a void type node.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-16 20:43:46 +02:00
Dodji Seketeli
798c013de0 ir: Don't cache internal name of non-canonicalized function types
When a function type is not yet canonicalized, do not cache its name,
otherwise, the name can capture the state of the function in a too
early state.

	* src/abg-ir.cc (function_type::get_cached_name): Do not cache
	internal name for non-canonicalized function types.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-16 20:39:56 +02:00
Dodji Seketeli
dcce841c54 ir: Improve legibility of set_member_function_is_virtual
* src/abg-ir.cc (set_member_function_is_virtual): Remove
	useless white space and use clearer helper function.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-16 20:38:44 +02:00
Dodji Seketeli
7de9d769bc abidw: Make generic options like --verbose work with the ABIXML front-end
* tools/abidw.cc (set_generic_options): Take a fe_iface in
	parameter, not an elf_based_reader.
	(perform_self_comparison): Call set_generic_options.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-14 14:24:27 +02:00
Dodji Seketeli
7a62ac1526 reader: Fix building of reference type
This patch ensures that the built reference type IR node is always associated
with the type-id used in the ABIXML.

	* src/abg-reader.cc (build_reference_type_def): Remove unnecessary
	condition.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-14 14:24:22 +02:00
Dodji Seketeli
de03c87c50 reader: Avoid crashing on empty scopes in reader::push_decl_to_scope
When abixml::reader::push_decl_to_scope gets a nullptr scope, it can
sometimes abort.  Fixed thus.

	* src/abg-reader.cc (reader::push_decl_to_scope): It's only if
	there is a non-nil scope that the assert can be reached.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-14 14:24:17 +02:00
Dodji Seketeli
fbb1240451 ir: Fix comment for translation_unit::get_global_scope
* src/abg-ir.cc (translation_unit::get_global_scope): Fix comment.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-14 14:24:13 +02:00
Dodji Seketeli
e9a59beefe ir: Speed up enum comparison
When two enums are naively equal, comparing then member-wise should be
fast.  This patch does just that.  This speeds up things a lot, in the
context of self-comparison and type canonicalization (from DWARF) when
there are huge enums in the binary.

	* src/abg-ir.cc (equals): In the overload for enums, compare
	enumerators naively for the case both enums are naively equal.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-14 14:21:56 +02:00
Dodji Seketeli
d1bba71063 ir: Support comparing a class_decl against a class_or_union
When a class_decl is compared against a class_or_union type using
class_decl::operator==, that operator systematically fails.  This
patch fixes that by comparing the common parts between the two
objects.

	* src/abg-ir.cc (class_decl::operator==): Support comparing
	against a class_or_union.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-14 14:21:49 +02:00
Dodji Seketeli
0284239bb1 ir: Support canonical type adjustments for decl-only class types
When a decl-only class 'D' type (which has an associated class type) is
canonicalized and its canonical type is being adjusted to make sure it
contains all the member functions of 'D', the member functions are not
being taken into account.  Fixed thus.

	* src/abg-ir.cc (maybe_adjust_canonical_type): Look through
	decl-only classes to get their definition.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-14 14:11:00 +02:00
Dodji Seketeli
4f8f981b90 ir: Make odr_is_relevant support support artifacts with no TU set yet
* src/abg-ir.cc (odr_is_relevant): Consider that an artifact with
	no associated TU is not relevant for ODR considerations.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-14 14:10:53 +02:00
Dodji Seketeli
6cd7005ca0 ir: add_decl_to_scope shouldn't abort on nullptr scopes
* src/abg-ir.cc (add_decl_to_scope): Do not abort on an empty
	scope.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-14 14:10:46 +02:00
Dodji Seketeli
90dae34855 ir: Fix getting the translation unit for an ABI artifact
Sometimes when the current translation unit is not yet set for a given
artifact, we can infer it by getting the translation unit of the scope
of the artifact.  This patch performs that inference when the
translation unit is not yet set for the current artifact.

	* include/abg-fwd.h (get_translation_unit): Take a
	type_or_decl_base parameter, not a decl_base.
	* src/abg-ir.cc (get_translation_unit): Likewise.  If no
	translation has yet been associated with the ABI artifact, get it
	from its scope.
	(type_or_decl_base::get_corpus): Use the new get_translation_unit.
	(maybe_set_translation_unit): Assert that the translation unit is
	non-nil.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-14 14:10:33 +02:00
Dodji Seketeli
f68ae8cb36 Use smart pointers for variables exported from the ABI corpus
It turned out that for some applications using the library, being able
to share the variables returned by
libabigail::ir::corpus::lookup_variable is useful.  This patch changes
the API to use shared pointer for variables exported from the ABI
corpus.  For the sake of consistency, we should do the same for
function decls, but given the churn, I thought I'd do it for variables
first and see the impact.  If it's OK then I'll do it for function
decls too.

	* include/abg-comparison.h (string_var_ptr_map): Use a
	var_decl_sptr rather than a var_decl*.
	* include/abg-corpus.h (corpus::{variable, variables_set}):
	Likewise.
	(corpus::lookup_variable): Return a var_decl_sptr not a var_decl*.
	(corpus::exported_decls_builder::maybe_add_var_to_exported_vars):
	Take a var_decl_sptr, not a var_decl*.
	* include/abg-fe-iface.h
	(fe_iface::add_var_to_exported_or_undefined_decls): Likewise.
	* include/abg-ir.h (istring_var_decl_ptr_map_type): Use a
	var_decl_sptr rather than a var_decl*.
	* src/abg-btf-reader.cc (reader::build_ir_node_from_btf_type):
	Adjust call to add_var_to_exported_or_undefined_decls.
	* src/abg-comparison-priv.h (var_comp::operator()()): Add a new
	overload for var_decl_sptr.
	(corpus_diff::priv::{deleted_variable_is_suppressed,
	deleted_variable_is_suppressed}): Take a var_decl_sptr not a
	var_decl*.
	(sort_string_var_ptr_map): Take ...
	* src/abg-comparison.cc (sort_string_var_ptr_map): ... a
	vector<var_decl_sptr> rather than a vector<var_decl*>.
	(corpus_diff::priv::ensure_lookup_tables_populated): Adjust.
	(variable_is_suppressed): Likewise.
	(corpus_diff::priv::{deleted_variable_is_suppressed,
	added_variable_is_suppressed}): Likewise.
	* src/abg-corpus-priv.h (str_var_ptr_map_type)
	(istr_var_ptr_map_type): Use a var_decl_sptr rather than a
	var_decl*.
	(corpus::exported_decls_builder::priv::{add_var_to_map,
	keep_wrt_id_of_vars_to_keep, keep_wrt_regex_of_vars_to_suppress,
	keep_wrt_regex_of_vars_to_keep}): Likewise.
	(corpus::exported_decls_builder::priv::vars): Likewise.
	* src/abg-corpus.cc
	(corpus::exported_decls_builder::maybe_add_var_to_exported_vars):
	Likewise.
	(var_comp::operator()()): Add an overload for var_decl_sptr.
	(corpus::lookup_variable): Return var_decl_sptr rather than
	var_decl*.
	* src/abg-ctf-reader.cc (reader::process_ctf_archive): Adjust.
	* src/abg-dwarf-reader.cc (build_ir_node_from_die): Adjust.
	* src/abg-fe-iface.cc
	(fe_iface::add_var_to_exported_or_undefined_decls): Take a
	var_decl_sptr rather than a var_decl*.
	* src/abg-reader.cc (build_class_decl, handle_var_decl): Adjust.
	* src/abg-writer.cc (write_translation_unit): Likewise.
	* tools/abicompat.cc (var_change::decl, var_change::var_change):
	Likewise.
	(compare_expected_against_provided_variables): Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-14 14:05:54 +02:00
Dodji Seketeli
d8441af5a2 configure.ac: Fix typo triggered when --enable-big-tests is used
* configure.ac: It's "cd $ac_abs_top_srcdir/big-tests", not
	"cd ac_abs_top_srcdir/big-tests"

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-08-08 12:12:15 +02:00
Dodji Seketeli
3e93b0f222 configure: Support the optional 'big-tests' sub-directory
If the 'big-tests' sub-directory (or a symbolic link to it) is present
then this patch configures it.

By default, the patch defines a new git sub-module into the
'big-tests' sub-directory.  That git sub-module is the repository
git://sourceware.org/git/libabigail-tests.  Users can now add the
--recurse-submodules option to git clone when they clone
git://sourceware.org/git/libabigail, so that it clones git big-tests
submodule as well.

The patch adds a new 'big-tests' target (to the top-most Makefile.am)
which runs "make check" in the big-tests sub-directory.

The patch also adds a new 'full-check' target that runs targets check,
check-self-compare and big-tests.

        * Makefile.am: Add big-tests,clean-big-tests and full-check
	targets.
        * configure.ac: Add an --enable-big-tests option.  For now, this
	option is mandatory to handle the optional 'big-tests' support.
	If the --enable-big-tests option is provided and if the
	'big-tests' sub-directory is present, configure the big-tests/
	sub-package.
	* .gitmodules: New sub-module configuration to get
	git://sourceware.org/git/libabigail-tests and stick into ...
	* big-tests: ... this directory as a sub-module.
	* CONTRIBUTING: Update this to explain how to get the Big Tests
	going.
	* tests/Makefile.am: Update the test summary for the
	check-self-compare target.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 12:59:03 +02:00
Dodji Seketeli
5fb6df40ea abidw: Support the --abidiff option for Linux Kernel trees
It turned out abidw --abidiff (self-comparison) doesn't work when
analyzing a Linux Kernel tree.  In other words, abidw cannot
self-compare a Linux Kernel tree.  Embarrassing.  Fixed thus.

	* include/abg-corpus.h (is_corpus_group): Declare ...
	* src/abg-corpus.cc (is_corpus_group): ... new function.
	* src/abg-ctf-reader.cc (create_reader): Support --debug-abidiff
	when the package is configured with --enable-debug-self-comparison.
	* tools/abidw.cc (load_corpus_and_write_abixml): Factorize self
	comparison code out into ...
	(perform_self_comparison): ... this.
	(load_kernel_corpus_group_and_write_abixml): Use the new
	perform_self_comparison to perform self comparison when the
	--abidiff option is provided.  Also, support --debug-abidiff when
	the package is configured with --enable-debug-self-comparison.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 12:53:30 +02:00
Dodji Seketeli
86a1a1168e ir,comparison,default-reporter: Consider sub-ranges in array diffs
It appears that the comparison engine does not take changes in the
underlying types of sub-ranges into account when looking for sub-range
changes.

This patch fixes that issue.

Then the patch amends the diff model of array_diff to make it take
into account sub-range diffs as children diff nodes.  Then it updates
redundancy propagation to make sure changes to sub-ranges are always
reported even when they are redundant.  The patch filters out harmless
name changes to integral types, by default.

	* include/abg-comparison.h (array_diff::array_diff): Take a vector
	of sub-range diffs as children diff nodes.
	(array_diff::{subrange_diffs, any_subrange_diff_to_be_reported}):
	Declare new methods.
	(is_anonymous_subrange_diff): Declare new function.
	* src/abg-comp-filter.cc (integral_type_has_harmless_name_change):
	Define new function.
	(has_harmless_name_change): Use the new
	integral_type_has_harmless_name_change.
	* src/abg-comparison-priv.h (array_diff::priv::subrange_diffs_):
	Define new data member.
	* src/abg-comparison.cc (is_anonymous_class_or_union_diff): Fix
	comment.
	(is_anonymous_subrange_diff): Define new function.
	(array_diff::chain_into_hierarchy): Append sub-range diffs as
	children nodes of the array_diff node.
	(array_diff::array_diff): Take a vector of sub-range diffs as
	children diff nodes.
	(array_diff::{subrange_diffs, any_subrange_diff_to_be_reported}):
	Define new methods.
	(array_diff::has_changes): Take sub-range diffs into account.
	(compute_diff): In the overload for array_type_def, compute diffs
	for sub-ranges as part of the diff for array_type_defs.
	(leaf_diff_node_marker_visitor::visit_begin): Do not consider an
	anonymous sub-range diff node as being a leaf diff node to report
	about.
	(redundancy_marking_visitor::visit_end): Report all sub-range diff
	nodes changes; do not propagate their (potential) redundancy to
	their array_diff node parent.
	* src/abg-default-reporter.cc (default_reporter::report): In the
	overload for array_diff, if there is a sub-range change to be
	reported, then report it.
	* src/abg-ir-priv.h (real_type::base_type): Add SIZE_BASE_TYPE,
	SSIZE_BASE_TYPE, BIT_SIZE_BASE_TYPE, SBIT_SIZE_BASE_TYPE,
	ARRAY_SIZE_BASE_TYPE enumerators to this enum.
	* src/abg-ir.cc (parse_base_real_type): Support parsing real type
	names that are __ARRAY_SIZE_TYPE__, sizetype, ssizetype,
	bitsizetype and sbitsizetype.
	(real_type::to_string): Support IZE_BASE_TYPE, SSIZE_BASE_TYPE,
	BIT_SIZE_BASE_TYPE, SBIT_SIZE_BASE_TYPE and ARRAY_SIZE_BASE_TYPE
	enumerators.
	(equals): In the overload for array_type_def::subrange_type,
	compare the underlying types of the sub-ranged.  In the overload
	for array_type_def, consider sub-range changes mismatch as a local
	non-type change.  This is so that changes to sub-ranges don't get
	filtered out because changes to element types are redundant.
	* src/abg-reporter-priv.cc (represent): In the overload for
	subrange_diff, clean up reporting of change of bound values.
	Also, add reports of changes from non-finite to finite size.
	* tests/data/test-abidiff-exit/ada-subrange/test1-ada-subrange/test1-ada-subrange-report-1.txt:
	Adjust.
	* Tests/data/test-abidiff-exit/ada-subrange/test1-ada-subrange/test1-ada-subrange-report-2.txt:
	Likewise.
	* tests/data/test-abidiff-exit/ada-subrange/test2-ada-subrange-redundant/test2-ada-subrange-redundant-report-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/ada-subrange/test2-ada-subrange-redundant/test2-ada-subrange-redundant-report-2.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-allow-type-array-v0--v1-report-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-allow-type-array-v0--v3-report-1.txt:
	Likewise.
	* tests/data/test-abidiff/test-PR27985-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test10-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test11-report.txt: Likewise.
	* tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-clang-report-0.txt:
	Likewise.
	* tests/data/test-diff-dwarf/test35-pr19173-libfoo-long-gcc-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/PR24430-fold-qualified-array-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR29811-0-report-1.txt:
	Likewise.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt:
	Likewise.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report1.txt:
	Likewise.
	* tests/data/test-diff-filter/test30-pr18904-rvalueref-report2.txt:
	Likewise.
	* tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt:
	Likewise.
	* tests/data/test-diff-pkg/libICE-1.0.6-1.el6.x86_64.rpm--libICE-1.0.9-2.el7.x86_64.rpm-report-0.txt:
	Likewise.
	* tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt:
	Likewise.
	* tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt:
	Likewise.
	* tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/test-has-data-member-inserted-at-1-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/test-has-strict-flexible-array-data-member-conversion-report-2.txt:
	Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 12:49:51 +02:00
Dodji Seketeli
a645a7b681 ir: Rename integral_type into real_type
It turns out what we call integral_type in the libabigail IR is
actually a real_type because it includes real types (float and
double).  This patch rights that wrong.

	* include/abg-fwd.h (is_real_type): Declare new function.
	* src/abg-ctf-reader.cc (process_ctf_base_type): Adjust.
	* src/abg-dwarf-reader.cc (die_qualified_type_name)
	(build_type_decl): Adjust.
	* src/abg-ir-priv.h (class real_type): Rename class integral_type
	into this.
	* src/abg-ir.cc (get_internal_real_type_name, operator|)
	(operator&, operator~, operator|=, operator&=)
	(parse_real_type_modifier, parse_base_real_type, parse_real_type)
	(real_type::{real_type, get_base_type, get_modifiers,
	set_modifiers, to_string, operator string()}):
	s/integral_type/real_type.
	(type_decl::{type_decl, get_qualified_name,
	get_pretty_representation}): Adjust.
	(is_real_type): Define new function.
	(is_integral_type): Use the new is_real_type.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 12:45:43 +02:00
Dodji Seketeli
a21f40be2c ir: Don't strip typedefs from parms and return type when comparing fns
As we are now sorting types so that they are
always compared in the same order during canonicalization,
irrespective of the front-end, I believe stripping typedefs from
function parameteres and return types during comparison is no more
necessary.  And also, that removes so spurious changes reports.

	* src/abg-ir.cc (equals): In the overloads from function_type and
	function_decl::parameter, do not strip typedefs off of types
	becore comparing them.
	* tests/data/test-abidiff-exit/PR30329/PR30329-report-1.txt:
	Adjust.
	* tests/data/test-abidiff-exit/PR30503/libsdl/libsdl-1.2.60-1.2.64-report.txt:
	Adjust.
	* tests/data/test-abidiff-exit/PR31513/reported/PR31513-reported-report-1.txt:
	Adjust.
	* tests/data/test-abidiff-exit/PR31513/reported/PR31513-reported-report-2.txt:
	Adjust.
	* tests/data/test-annotate/test14-pr18893.so.abi: Adjust.
	* tests/data/test-annotate/test15-pr18892.so.abi: Adjust.
	* tests/data/test-annotate/test17-pr19027.so.abi: Adjust.
	* tests/data/test-annotate/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Adjust.
	* tests/data/test-diff-dwarf/test2-report.txt: Adjust.
	* tests/data/test-diff-filter/test3-report.txt: Adjust.
	* tests/data/test-diff-pkg-ctf/gmp-6.x.x86_64-report-0.txt:
	Adjust.
	* tests/data/test-read-dwarf/PR25007-sdhci.ko.abi: Adjust.
	* tests/data/test-read-dwarf/test-libandroid.so.abi: Adjust.
	* tests/data/test-read-dwarf/test14-pr18893.so.abi: Adjust.
	* tests/data/test-read-dwarf/test15-pr18892.so.abi: Adjust.
	* tests/data/test-read-dwarf/test17-pr19027.so.abi: Adjust.
	* tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Adjust.
	* tests/data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi:
	Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 12:32:32 +02:00
Dodji Seketeli
907f8962a5 reader: Fix building of variadic parameter type
variadic parameter type is not added to its proper scope, leading to
issues down the road.  Fixed thus.

	* src/abg-ir-priv.h (type_topo_comp::operator()): Do not compare
	types using their location anymore.  It's unnecessary (now that
	types are sorted before canonicalization) and it wreaks havoc with
	the new properly constructed variadic parameter types.
	* src/abg-reader.cc (build_ir_node_for_variadic_parameter_type):
	Define new function.  Add variadic parameter type to the global
	scope of the current translation unit.
	(build_function_parameter, build_type_decl): Use the new
	build_ir_node_for_variadic_parameter_type.
	* tests/data/test-read-write/test17.xml: Adjust.
	* tests/data/test-read-write/test19.xml: Likewise.
	* tests/data/test-read-write/test20.xml: Likewise.
	* tests/data/test-read-write/test21.xml: Likewise.
	* tests/data/test-read-write/test22.xml: Likewise.
	* tests/data/test-read-write/test23.xml: Likewise.
	* tests/data/test-read-write/test25.xml: Likewise.
	* tests/data/test-read-write/test26.xml: Likewise.
	* tests/data/test-read-write/test28-without-std-fns-ref.xml:
	Likewise.
	* tests/data/test-read-write/test28-without-std-vars-ref.xml:
	Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 12:29:14 +02:00
Dodji Seketeli
16bc399d58 reader: Fix building of void and void pointer types
build_ir_node_for_void_pointer_type and build_ir_node_for_void_type
get the type IR from the environment, add it to the global scope of
the current translation unit and schedule it for type
canonicalization.

This patch change the code of these functions so that the adding to
the scope and the canonicalization are done only on the first
invocation of these functions.  Subsequent invocations just return the
type IR.

Otherwise, subsequent invocations were unnecessarily trying to add the
type IR to yet another global scope and were trying to canonicalize it
again.

	* src/abg-reader.cc (build_ir_node_for_void_pointer_type)
	(build_ir_node_for_void_type): Add the type to its scope and
	schedule it for canonicalization just once.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 12:26:12 +02:00
Dodji Seketeli
e0b3499d34 reader: Simplify logic of get_or_read_and_add_translation_unit
* src/abg-reader.cc (get_or_read_and_add_translation_unit):
	Simplify logic.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 12:11:21 +02:00
Dodji Seketeli
dceb396bdb reader: Simplify type canonicalization invocation
The ABIXML reader currently canonicalizes some (simple) types directly
and schedules canonicalization of other types for after the corpus has
been built.  This dual mode of operation was used back then when
ABIXML types were not aggressively de-duplicated as they are now.
Today, type canonicalization needs to happen in the same way for all
readers.

This patch thus schedules type canonicalization for after the creation
of the corpus, in the ABIXML reader.

	* src/abg-reader.cc (reader::maybe_canonicalize_type): Remove.
	(reader::schedule_type_for_canonicalization): Do not schedule
	nullptr types for canonicalization.
	(reader::perform_type_canonicalization): Rename
	perform_late_type_canonicalizing into this.
	(reader::{read_corpus, build_or_get_type_decl}): Adjust call to
	maybe_canonicalize_type into schedule_type_for_canonicalization.
	(read_translation_unit_from_file)
	(read_translation_unit_from_buffer, read_translation_unit)
	(build_function_decl, build_ir_node_for_void_type)
	(build_array_type_def, build_ir_node_for_void_pointer_type)
	(build_class_decl, build_union_decl)
	(build_class_tdecl, build_type_tparameter, build_type_composition)
	(build_template_tparameter, build_type, handle_type_decl)
	(handle_qualified_type_decl, handle_pointer_type_def)
	(handle_reference_type_def, handle_function_type)
	(handle_array_type_def, handle_enum_type_decl)
	(handle_typedef_decl, handle_class_decl, handle_union_decl):
	Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 12:07:15 +02:00
Dodji Seketeli
960d3c2d56 reader: Fix corpus group reading
Reading of corpus group is broken in the ABIXML reader.  Only the main
corpus is read and then, abixml::reader::read_corpus_group_from_input
fails to read subsequent corpora.

This patch fixes abixml::reader::read_corpus_group_from_input and
makes it call a new abixml::reader::initialize function, much like
what the ELF based readers are doing.

	* src/abg-fe-iface.cc (fe_iface::priv::initialize): Do not clear
	the corpus group upon initialization.
	* src/abg-reader.cc (reader::initialize): Define new function.
	Make it call fe_iface::initialize.
	(reader::clear_per_corpus_data): Remove.
	(reader::read_corpus): Remove call to clear_per_corpus_data.
	(reader::read_corpus_group_from_input): After calling
	reader::read_corpus and adding the resulting corpus to the group,
	get the next sibling XML element node.  If it's an "abi-corpus"
	node then re-initialize the reader by invoking the new
	reader::initialize and move on to read it by invoking
	reader::read_corpus again.
	* tests/data/test-diff-suppr/test45-abi-report-1.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 12:03:51 +02:00
Dodji Seketeli
a08a60fcd9 ctf-reader: Fix analyzing single kernel binaries
Analyzing a single kernel binary has been broken for a long time, it
seems.  For the record, I mean this:

    $ abidw --ctf vmlinux > vmlinux.ctf.abi

Doesn't work.

This patch fixes ctf::reader::slurp_elf_info to make it not crash on
binaries that have no CTF sections because there is a .ctfa file in
the same directory.

Also, it fixes ctf::reader::read_corpus to support loading the CTF
archive for individual kernel binaries and not just for entire trees
(corpus groups).  In the case of individual kernel binaries, the
archive can be built from the CTF sections of the binary.

	* src/abg-ctf-reader.cc (reader::slurp_elf_info): Do not crash on
	a kernel binary that has no CTF section because the CTF
	information is in a .ctfa file in the same directory.
	(reader::read_corpus): Support loading a CTF archive for a single
	kernel binary.  Also, support loading the CTF archive from the CTF
	sections in the binary itself not necessarily from a .ctfa file in
	the same directory.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 11:47:04 +02:00
Dodji Seketeli
57a7eb6011 ctf-reader: During re-initialization, only clear canonicalize-able types
The patch
https://sourceware.org/git/?p=libabigail.git;a=commit;h=666555665cc4fcfc8ae19661c489822e0df00ae3
introduced a mistake: It frees the CTF archive object during the
re-initialization of the reader between each binary (kernel or
module).  The archive contains CTF type information for a kernel and
all its modules.  So it should be kept around until all those binaries
are analyzed.  Instead, that patch frees the CTF archive object after
handling each binary.  Oops.

This patch fixes that problem by free-ing the CTF archive only when
the reader itself is freed, presumably, after analyzing all binaries.

Similarly, the type map maintained by the reader contains types for
the kernel and all its modules.  So it should not be freed at
re-initialization time.  Rather, what should be freed is only the
types that are to be canonicalized at the end of processing of a given
binary.  So the patch makes the reader maintain types to be
canonicalized in a vector and clears that vector at each
re-initialization.

At re-initialization time, the patch also avoids resetting the corpus
group that the current reader feeds.

	* src/abg-ctf-reader.cc (reader::types_to_canonicalize): Add data
	member.
	(reader::add_type): Add the new type to the vector of types to be
	canonicalized.  Update comment.
	(reader::canonicalize_all_types): Now that the reader maintains
	the vector of types to be canonicalized, just pass that vector to
	canonicalize_types.  reader::types_map contains all the types that
	have been created in all the binaries processed by this reader so
	far.  Many of these types have already been canonicalized at the
	end of the analysis of binaries that have already been processed.
	Only the types created during the processing of the current binary
	have not yet be canonicalized and reader::types_to_canonicalize is
	where they are maintained.  So reader::types_map should be left
	alone by this function.
	(reader::initialize): Do not close the CTF archive here.  Do not
	clear reader::{types_map, corpus_group} either.
	(reader::read_corpus): Use nullptr, not NULL.  Make sure to not
	re-open an archive that has already been opened.
	(reader::~reader): Mark a closed archive.  This is more cosmetic
	than anything else.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 11:39:38 +02:00
Dodji Seketeli
2031bde6eb ctf-reader: Do not set data member offsets for unions
All union data members should have an offset set to 0.  It turns out
the CTF reader unnecessarily sets the data member offset.  This patch
fixes that.

	* src/abg-ctf-reader.cc (process_ctf_sou_members): Do not set any
	union data member offset.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 11:35:14 +02:00
Dodji Seketeli
582af21243 corpus: Support adding translation units with empty path
The CTF front-end produces an artificial translation unit with an
empty path for all the types in a given ABI corpus.  Adding such a
translation unit to its corpus is conditioned on it having a non-empty
path.  Oops.  Fixed thus.

	* src/abg-corpus.cc (corpus::add): Do not require that the path of
	the translation unit be non-empty.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 11:33:53 +02:00
Dodji Seketeli
904c8eafcc tools-utils,btf-reader: Take modules into account for corpus group
It turns out the BTF front-end won't take kernel modules into account
when analyzing a linux kernel build tree.

This is because it doesn't support split and base BTF objects.

Please note that the BTF API is not yet documented in
https://docs.kernel.org/bpf/btf.html, so my understanding of how it
works comes the source code of the bpftool program available at
https://github.com/libbpf/bpftool and https://github.com/libbpf/libbpf.

When analyzing the vmlinux binary, the btf__parse function returns a
"base BTF object" which contains the type information contained in the
.BTF section of that binary.  The memory of the BTF types describing
the types of vmlinux lives in the base BTF object.  So the base BTF
object must be kept around for the entire time of the analysis of the
Linux kernel tree (vmlinux + modules).

When analyzing a kernel module however, it's the btf__parse_split
function that is used.  That function takes into parameter the "base
BTF object" representing the type information of the corresponding
vmlinux binary and returns a "split BTF object" which contains the
type information contained in the .BTF section of the kernel module.
Please note that the split BTF object does reference the base BTF
object as well.  The memory of the BTF types describing the types the
kernel module lives in the split BTF object.  Because some types and
decls might be exported by a kernel module and used by another one,
the memory of a given split BTF object might be needed to be kept
alive for the entire time of the analysis of the Linux kernel tree as
well.

It's this base/split model of BTF that is not supported by the BTF
front-end.

This patch introduces support for that model.

At any point in time, the BTF front-end now has one handle to the base
BTF object and one handle to the current split BTF object if we are
looking at kernel module.  The base and split BTF objects are kept
around for the entire lifetime of the front-end.

For a given binary, each type is identified by a type ID.  The
validity of a given type ID is effective only for that binary.  The
same type ID in another binary might designate another type.  So
rather than maintaining a map that associates a type ID with a libabigail
IR artifact, the front-end now maintains a map that associates a
*type* with libabigail IR artifact.

With this changes, abidw can now analyze and emit the ABIXML for a
linux kernel tree in 28 seconds, using BTF.  It can self-compare a
kernel tree in 36 seconds.

	* src/abg-btf-reader.cc (btf_type_to_abi_artifact_map_type):
	Rename btf_type_id_to_abi_artifact_map_type into this.  Make it
	associate a btf_type* to a libabigail IR, rather than a type ID to
	a libabigail IR.
	(reader::{base_btf_handle_, base_btf_file_name_,
	split_btf_handle_, split_btf_file_name_, split_btfs_to_free_}):
	Define new data members.
	(reader::{btf_handle_}): Remove.
	(reader::base_btf_handle): Renamed btf_handle into this.  Create
	the BTF object using btf__parse.  Store the name of the binary
	into reader::base_btf_file_name_.
	(reader::read_split_btf): Define new member function.
	(reader::btf_handle): This is new code for an existing member
	function name.  Return the current split BTF object handle if
	applicable, otherwise create the base BTF object handle.
	(reader::btf_type_to_artifacts_): Renamed
	btf_type_id_to_artifacts into this.
	(reader::associate_artifact_to_btf_type): Renamed
	associate_artifact_to_btf_type_id into this.
	(reader::schedule_type_for_canonicalization): Do not schedule a
	type that has already been canonicalized.
	(reader::nr_btf_types): Take a BTF* parameter.
	(reader::~reader): Free all the allocated split BTF objects.
	(reader::read_debug_info_into_corpus): If we are looking at a
	split BTF, then set the first type ID as the one right after the
	last type ID of the base BTF.
	(reader::build_ir_node_from_btf_type): Clean-up the logic for
	building type void type.
	(reader::{build_ir_node_for_void_type,
	build_ir_node_for_void_pointer_type,
	build_ir_node_for_variadic_parameter_type,
	build_enum_underlying_type, build_array_type}): Schedule type for
	canonicalization at the end of the IR construction, not right
	away.
	* src/abg-tools-utils.cc (create_best_elf_based_reader): Pass
	show_all_types and linux_kernel_mode arguments to
	btf::create_reader.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 11:33:53 +02:00
Dodji Seketeli
71e9ae575d elf-based-reader: Clean up logic of elf_based_reader::read_and_add_corpus_to_group
While looking at something else, I noticed the logic of
elf_based_reader::read_and_add_corpus_to_group wasn't clear.  The
corpus should be read (thus created) first, then added to the reader.
Fixed thus.

	* src/abg-elf-based-reader.cc
	(elf_based_reader::read_and_add_corpus_to_group): Fix logic.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 11:25:38 +02:00
Dodji Seketeli
9d14151e15 ir: Fix a potential crash in canonicalize_types
I noticed crashes in canonicalize_types when it deals with nullptr
types.  Fixed thus.

	* src/abg-ir-priv.h (canonicalize_types): Avoid crashing when
	de-referencing an iterator to a nullptr type.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-16 11:04:06 +02:00
Ross Burton
076985bbe9 configure.ac: improve fts checks
The current code checks explicitly for musl and if so uses pkg-config to
find fts-standalone. This is suboptimal because musl may not be the only
libc to need a standalone fts implementation, and fts-standalone is an
old gentoo-specific name[1] so libabigail won't build on any other system
against musl.

Instead, use AC_SEARCH_LIBS to look for fts_open in libc then libfts. Do
this before the check for behaviour just in case someone has a standalone
and broken implementation.  I assume that the standalone fts is installed
on the standard search path, which should be a fair assumption.

As we're not using pkg-config anymore the required link flags are now in
LIBS, so remove all instances of FTS_CFLAGS and FTS_LIBS.

[1] https://gitweb.gentoo.org/repo/gentoo.git/commit/sys-libs/fts-standalone?id=a403fe6c61d1aaeecd58d521f3def2f6d3513449

	* configure.ac: Use AC_SEARCH_LIBS to look for fts_open in libc
	and in libfts if necessary.  Remove the use of FTS_LIBS which is
	now unnecessary.
	* src/Makefile.am: Do not use FTF_LIBS as it's now unnecessary.
	* tools/Makefile.am: Likewise.

Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-07-12 17:40:25 +02:00
Dodji Seketeli
e769a204dc btf-reader: Add missing data members reset to reader::initialize
btf::reader::initialize forgets to reset a few data members used
during binary type information loading.  This resetting is key to get
the reader ready for being re-used to load a new binary, like a kernel
module.  Otherwise, the working set just keeps growing unnecessarily.

	* src/abg-btf-reader.cc (btf::reader::initialize): Clear
	types_to_canonicalize_, btf_type_id_to_artifacts_ and cur_tu_.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-06-21 18:46:35 +02:00
Dodji Seketeli
dc11165cfb dwarf-reader: Fix reader::initialize to clear per corpus data
After cleaning up re-initialization sequence of the the CTF reader ,
Claudiu Ianculescu suggested that I look into the DWARF reader's
initialization sequence as well.  Lo and behold, the
dwarf::reader::read_debug_info_into_corpus calls
reader::clear_per_corpus_data while reader::initialize does not.

This patch moves the call to reader::clear_per_corpus_data into
reader::initialize.  It makes the code consistent with what we are now
doing in the CTF reader.

	* src/abg-dwarf-reader.cc (reader::initialize):  Call
	clear_per_corpus_data.
	(reader::read_debug_info_into_corpus): Remove the call to
	clear_per_corpus_data from here.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-06-21 18:45:22 +02:00
Dodji Seketeli
1add2fea50 ir: Cache the pretty representation used during pre-canonicalization type sorting
Profiling showed that during pre-canonicalization types sorting (which
uses type_topo_comp and decl_topo_comp sorting functors) we spend a
lot of time computing the pretty representation of types and decls
invoked from type_topo_comp::operator() and
decl_topo_comp::operator().

This patch thus uses type_base::get_cached_pretty_representation and
introduces a new similar decl_base::get_cached_pretty_representation
to cache the pretty representation of types and decls and re-use that
representation instead of computing it over and over.

Together with the previous patch of this series, the time spent to
analyze a Linux Kernel tree went from ~ 55 minutes to around 1m15s
using a non-optimized build of libabigail.

	* include/abg-ir.h (decl_base::get_cached_pretty_representation):
	Declare new member function.
	* src/abg-ir-priv.h ({type,decl}_topo_comp::operator()): Use
	{type,decl}_base::get_cached_pretty_representation instead of
	get_pretty_representation.:
	* src/abg-ir.cc (decl_base::priv::{internal_cached_repr_,
	cached_repr}): Define new data members.
	(decl_base::get_cached_pretty_representation):
	Define new member function.
	(type_base::get_cached_pretty_representation): Cache pretty
	representation even for non-canonicalized types.  Fix comments.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-06-21 18:43:53 +02:00
Dodji Seketeli
666555665c ctf-reader: Fix re-initialization of the CTF reader
When analyzing a Linux Kernel tree made of vmlinux and loadable module
binaries, the same (CTF) binary reader is re-used to load every single
binaries in a loop.  That can be seen, for instance, by reading the
code of load_vmlinux_corpus in abg-tools-utils.cc.

As part of that process, abigail::ctf::reader::initialize is invoked
prior to using the reader to read type information from each binary.

But then, looking at things a bit closer, I realized that
ctf::reader::initialize is failing to reset the reader::ctfa data
member.  That leads to a memory leak that was making things grow
out of proportion.

Also, the resetting code fails to actually clear out the map of types
that are to be sorted and canonicalized.  That leads to unnecessarily
sorting huge amounts of types.

The patch address the two points above.

Apart from the obvious gain in code integrity, this patch
significantly reduces the time taken to analyze a Linux Kernel tree.
Please note that the subsequent patch coming after this one will
reduce that time even further.

	* src/abg-ctf-reader.cc (reader::reader): Initialize ctfa,
	ctf_sect, symtab_sect and strtab_sect data members.
	(reader::initialize): In the overload taking no argument, make
	sure to free the ctfa data member before setting it to nullptr.
	In the overload that takes arguments, make sure to invoke
	reader::initialize() to really free the data used.  Also, improve
	the comments.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-06-21 18:38:35 +02:00
Claudiu Zissulescu
544bddf594 ctf-reader: Add time logging to CTF reader
Log the time spent while reading the CTF archive and canonicalizing it.

    * src/abg-ctf-reader.cc (do_log()): Getter of the do_log flag.
    (read_corpus()): Add time logging.

Signed-off-by: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-06-21 14:29:16 +02:00
Claudiu Zissulescu
23e7c68afc ctf-reader: Optimize calling sorting function for functions and variables.
Sorting the functions and variables is done twice. First in the
process_ctf_archive() and second in read_corpus().  However, we need
to call them only once when we do the canonicalization of all types
and functions.  Thus, move canonicalization of types in read_corpus()
and perfom only once sorting the functions and types.

	* abg-ctf-reader.cc (process_ctf_archive()): Move
	canonicalize_all_types(), sort_functions() and sort_variables()...
	(read_corpus()): ...here, just after calling process_ctf_archive().

Signed-off-by: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-06-21 14:28:26 +02:00
Romain Geissler
2b2fa6ff14 leaf-reporter: Fix build with gcc 4.9.
* src/abg-leaf-reporter.cc (leaf_reporter::report): In the
	overload for corpus_diff, avoid using auto type deduction in
	for-each loop.

Signed-off-by: Romain Geissler <romain.geissler@amadeus.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-06-19 11:43:49 +02:00
Dodji Seketeli
19a4ae130d btf-reader: Fix re-use of the BTF reader for several binaries in a row
When analyzing a Linux Kernel tree, the BTF reader needs to be reset
after each binary (vmlinux or module) read.  It turns out the reset
was not being done properly.  Fixed thus.  Also, I noticed that
reader::read_debug_info_into_corpus would not return an empty corpus
when no BTF information was found in the binary.  Fixed as well.

	* src/abg-btf-reader.cc (reader::initialize): Free the btf handle
	first thing as part of the re-initialization.
	(reader::~reader): Once the BTF handle has been freed, set it to
	nil to show that it's been deleted.
	(reader::read_debug_info_into_corpus): If no BTF handle could be
	retrieved then it means no BTF data was found on the binary.
	Thus, return an empty corpus.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2024-05-31 17:56:41 +02:00