Commit Graph

2512 Commits

Author SHA1 Message Date
Dodji Seketeli
a92a2b9bc7 configure: Bump the CURRENT library number
The interface has changed in an incompatible way since the last
release as the vtable of fe_iface has changed in an incompatible, at
very least.  So bump the LIBABIGAIL_SO_CURRENT version number to
reflect that.

	* configure.ac: Bump LIBABIGAIL_SO_CURRENT to 2.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-02-10 13:18:19 +01:00
Dodji Seketeli
03d8b52fc7 PR30048 - wrong pretty representation of qualified pointers
A qualified type is textually represented as the following:

    <qualifier> <underlying-type>

were "qualifier" is the qualifier carried by the qualified type and
"underlying-type" is the type being qualified.

In this case, the qualifier prefixes the textual representation of the
qualified type.

This is true if the underlying type of the qualified type is a
non-const, non-reference type.  For instance:

    const int;

But when the underlying type is a pointer, then the qualified type is
represented as:

    int* const;

In that later case, the qualifier comes /after/ the textual
representation of the underlying type.

Now suppose the underlying type is itself a qualified type.  In that
case, for a non-const underlying type, we'd have, e.g:

    const volatile int;

where the qualifier precedes the qualified type (which is itself a
qualified type) /IF/ the ultimate underlying type (a.k.a the leaf
underlying type) is itself a non-const, non-reference type.

But if the ultimate underlying type is a pointer, a qualified type
with an underlying qualified type would be textually represented as,
e.g:

    int* const volatile;

In other words, if the leaf type is a pointer, the qualifier suffixes
the textual representation the underlying qualified type.

Libabigail is failing to apply this later rule.

As the type name is used as a key to cache IR nodes of DIEs (among
other things), getting it wrong can lead to a bumpy ride down the
road.

Fixed thus.

	* src/abg-dwarf-reader.cc
	(die_is_pointer_array_or_reference_type): Rename
	die_is_pointer_or_reference_type into this.  This new name
	reflects more what the function does as it tests if a DIE is for
	pointer, an array or a reference.
	(pointer_or_qual_die_of_anonymous_class_type): Adjust to use the
	newly (and better) named die_is_pointer_array_or_reference_type.
	(die_is_pointer_or_reference_type): Make this really test if a DIE
	is for a pointer or a reference.  Now the name matches what the
	function does.
	(die_peel_qualified): Define new function.
	(die_qualified_type_name): When a qualified name Q has another
	qualified name as its underlying type, it's important to know if
	the leaf type is a pointer type or not to know how to construct
	the name of Q.  This change now peels the potential qualifiers
	from the underlying type of the qualified type to see if the leaf
	type is a pointer or not.
	* src/abg-ir.cc (get_name_of_qualified_type): Likewise.  Also, the
	name of array types doesn't follow the same rule as for pointers
	and references.
	* tests/data/test-abidiff-exit/PR30048-test-report-0.txt: Add new
	reference test output.
	* tests/data/test-abidiff-exit/PR30048-test-2-report-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/PR30048-test-v{0,1}.c: Add source
	code of binary input data.
	* tests/data/test-abidiff-exit/PR30048-test-2-v{0,1}.cc: Likewise.
	* tests/data/test-abidiff-exit/PR30048-test-v{0,1}.o: Add binary
	input data.
	* tests/data/test-abidiff-exit/PR30048-test-2-v{0,1}.o: Likewise.
	* tests/data/Makefile.am: Add the new test material above to
	source distribution.
	* tests/test-abidiff-exit.cc (in_out_specs): Add the input
	binaries to this test harness.
	* tests/data/test-abidiff-exit/qualifier-typedef-array-report-1.txt:
	Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-02-10 13:15:27 +01:00
Dodji Seketeli
82973c898a default-reporter: Fix source location in functions change report
While looking at something else, I realized that the default-reporter
mentions the source location of the new function in lieu of the old function
when reporting about a function change.  Fixed thus.

	* src/abg-default-reporter.cc (default_reporter::report): In the
	overload of function_decl, use the source location of the old
	function.
	* tests/data/test-abicompat/test0-fn-changed-report-2.txt: Adjust.
	* tests/data/test-abidiff-exit/qualifier-typedef-array-report-1.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-PR28316-report.txt: Likewise.
	* tests/data/test-abidiff-exit/test-decl-enum-report.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-decl-struct-report.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-fun-param-report.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-headers-dirs/test-headers-dir-report-2.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-loc-with-locs-report.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-member-size-report0.txt:
	Likewise.
	* tests/data/test-abidiff-exit/test-rhbz2114909-report-1.txt:
	Likewise.
	* tests/data/test-diff-filter/libtest45-basic-type-change-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR24731-report-1.txt: Likewise.
	* tests/data/test-diff-filter/test-PR25661-1-report-2.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR25661-2-report-2.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR25661-3-report-2.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR25661-4-report-2.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR25661-5-report-2.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR25661-6-report-3.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR25661-7-report-3.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR26739-2-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR29387-report.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-1.txt:
	Likewise.
	* tests/data/test-diff-filter/test36-report-0.txt: Likewise.
	* tests/data/test-diff-filter/test37-report-0.txt: Likewise.
	* tests/data/test-diff-filter/test39/test39-report-0.txt:
	Likewise.
	* tests/data/test-diff-filter/test41-report-0.txt: Likewise.
	* tests/data/test-diff-filter/test44-anonymous-data-member-report-0.txt:
	Likewise.
	* tests/data/test-diff-pkg/dirpkg-3-report-2.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/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-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-1.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/symlink-dir-test1-report0.txt:
	Likewise.
	* tests/data/test-diff-pkg/tarpkg-1-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/PR28073/PR28073-output-2.txt:
	Likewise.
	* tests/data/test-diff-suppr/libtest48-soname-abixml-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/test30-report-0.txt: Likewise.
	* tests/data/test-diff-suppr/test41-enumerator-changes-report-0.txt:
	Likewise.
	* tests/data/test-diff-suppr/test42-negative-suppr-type-report-0.txt:
	Likewise.
	* tests/data/test-diff-suppr/test42-negative-suppr-type-report-1.txt:
	Likewise.
	* tests/data/test-diff-suppr/test6-fn-suppr-report-0-1.txt:
	Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-02-10 13:15:27 +01:00
Dodji Seketeli
d1af600491 {dwarf,elf_based}-reader,writer: Avoid duplicating corpora in corpus_group
It's been brought to my attention on IRC that running

    abidw --linux-tree <kernel-build-tree>

would result in a corpus group that duplicates every single corpus in
the resulting abixml.  Oops.

This is because both dwarf::reader::read_corpus() and
elf_based_reader::read_and_add_corpus_to_group() add the corpus to the
corpus_group, and yet, the later function calls the former.  So the
corpus is added to the corpus_group twice.

This patch ensures that
elf_based_reader::read_and_add_corpus_to_group() is the only one to
add the corpus to the group.  It also ensures that this happens before
the corpus is constructed from the debug info because that is useful
for sharing types among the various corpora.  Otherwise, those types
are potentially duplicated in the IR of each corpus.

The patch also ensures the abixml writer enforces the fact that each
corpus is emitted only once.

	* src/abg-dwarf-reader.cc (reader::read_debug_info_into_corpus):
	Do not add the corpus to the group here ...
	* src/abg-elf-based-reader.cc
	(elf_based_reader::read_and_add_corpus_to_group): ... because it's
	already added here.  But then, let's add it here /before/ reading
	type & symbols information into the corpus.
	* src/abg-writer.cc (write_context::m_emitted_corpora_set): Add
	new data member.
	(write_context::{corpus_is_emitted, record_corpus_as_emitted}):
	Define new member functions.
	(write_corpus): Invoke the new
	write_context::record_corpus_as_emitted here.
	(write_corpus_group): Ensure that each corpus is emitted only
	once.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-02-02 12:08:02 +01:00
Dodji Seketeli
30407d3258 corpus: Handle empty symbol table cases
There can be cases where the symbol table associated with a given
corpus is empty.  This patch handles those cases to avoid crashes.

	* src/abg-corpus.cc (corpus::priv::{get_sorted_fun_symbols,
	get_sorted_undefined_fun_symbols, get_sorted_var_symbols,
	get_sorted_undefined_var_symbols}): If the symbol is null, then
	return an empty vector of symbols.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-02-02 12:08:02 +01:00
Dodji Seketeli
a25bf55a9d dwarf-reader: Remove unused code
* src/abg-dwarf-reader.cc (reader::{find_symbol_table_section,
	lookup_native_elf_symbol_from_index}): Remove these dead
	functions.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-02-01 17:48:31 +01:00
Dodji Seketeli
02c299c290 fe-iface: Add missing virtual destructor
* include/abg-fe-iface.cc (fe_iface::~fe_iface): Make this
	virtual.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-02-01 17:19:27 +01:00
Aleksei Vetrov
dbd6db1822 symtab: fix getting CRC in relocatable modules
In ELF with ET_REL type symbol value holds not absolute but relative to
section value. This patch applies adjustment to the address, used in CRC
value extraction.

	* src/abg-elf-helpers.cc (get_crc_for_symbol): Rename
	crc_symbol_value to crc_symbol_address and adjust it for
	relocatable ELF types.

Signed-off-by: Aleksei Vetrov <vvvvvv@google.com>
2023-01-31 11:02:10 +01:00
Dodji Seketeli
bea35c9800 Update CTF's ctf_dict_t detection
As ctf_dict_t can be an opaque type depending on the version of
ctf-api.h, using AC_CHECK_TYPE won't work to detect it because that
macro invokes sizeof(ctf_dict_t).

With this change, we don't require that ctf_dict_t be fully defined.

	* configure.ac: Use AC_COMPILE_IFELSE to try and compile a code
	snippet that doesn't need that ctf_dict_t be fully defined.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-16 10:07:32 +01:00
Dodji Seketeli
554fea5e87 Better detect suitable libctf version
On some el9 distros, the version of libctf installed might not have
all the necessary features for the libabigail CTF reader, leading to
compilation errors due to missing types from the ctf-api.h header
file.  For instance, the ctf-api.h on some of those distros lacks the
definition of the type struct ctf_dict_t.

This patch adds a configure test for that struct and disables the CTF
support if that type is absent.

	* configure.ac: If the "struct ctf_dict_t" type is not present in
	the version of ctf-api.h that is present, then switch the support
	of CTF off.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-09 18:01:32 +01:00
Giuliano Procida
e6beace109 DWARF reader: avoid C++20 operator!= overload ambiguity
C++20 automatically generates overloads for certain comparison
operators based on others and this can create ambiguity with older
code. The type expr_result has various operators defined and comparing
expr_result != int becomes ambiguous.

This change just avoids this comparison by extracting the underlying
value, rather than making changes to the type itself. There should be
no change in behaviour and no tests are affected.

	* (src/abg-dwarf-reader.cc) op_is_control_flow: In the
	DW_OP_bra case, when testing the popped value, use the
	expr_result's const_value explicitly.

Signed-off-by: Giuliano Procida <gprocida@google.com>
2023-01-09 16:52:24 +01:00
Dodji Seketeli
00e3ac8937 btf-reader: Use abigail::ir::canonicalize_types to canonicalize types
In the btf::reader::canonicalize_types function, this patch now uses
the abigail::ir::canonicalize_types() function to canonicalize types,
just like the other front-ends.  The advantage of this function is
that it can perform some sanity checking for type canonicalization
that might be useful for later debugging purposes.

	* src/abg-btf-reader.cc (btf::reader::canonicalize_types): Use the
	abigail::ir::canonicalize_types function from abg-ir-priv.h
	file to canonicalize types.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-07 01:15:28 +01:00
Dodji Seketeli
a0cc439b28 Update the copyright notice for the BTF reader
* include/abg-btf-reader.h: Update the copyright notice for 2023.
	* src/abg-btf-reader.cc: Likewise.
	* tests/test-read-btf.cc: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-06 21:40:44 +01:00
Dodji Seketeli
12641b1130 Add support for BTF
This adds support for the BTF debug information format.  It provides a
new BTF front-end which can be instantiated by the function
tools::create_best_elf_based_reader().

For now, the BTF front-end supports the basic types (integers,
pointers, qualified types, typedefs, struct and unions and function
pointers) for functions and variables as emitted for the C language by
GCC.  It seems to be able to support the BTF debug information emitted
for the vmlinux kernel by the pahole tool as well.

When configured with the --enable-btf option, the WITH_BTF
pre-processor macro is defined, enabling the BTF support.  That option
is turned on by default if the /usr/include/bpf/btf.h header is found
on the system.  To disable this, one can use the --disable-btf option.

The abidw and abidiff programs have been adapted to use the BTF
front-end when provided with the '--btf' option, or if BTF debug
information is the only one present in the binary.

	* configure.ac: If the header /usr/include/bpf/btf.h exists, then
	define the WITH_BTF pre-processor macro, unless --disable-btf was
	provided.
	* doc/manuals/abidiff.rst: Document the new --btf option.
	* doc/manuals/abidw.rst: Likewise.
	* doc/manuals/kmidiff.rst: Likewise.
	* doc/manuals/abipkgdiff.rst: Likewise.
	* include/abg-btf-reader.h: New header file.  Contains the
	declaration of the new btf::reader class.
	* src/abg-btf-reader.cc: New source file.  Contains the
	definitions of the new btf::reader class.
	* include/Makefile.am: Add the new include/abg-btf-reader.h header
	file to source distribution.
	* include/abg-corpus.h (enum origin): Add a new BTF_ORIGIN
	enumerator.
	* include/abg-tools-utils.h (file_has_btf_debug_info): Declare new
	function.
	* src/abg-tools-utils.cc (file_has_btf_debug_info): Define new
	function.
	(create_best_elf_based_reader): Adapt to support BTF input.  If
	the user requested the BTF front-end, instantiate it.  Otherwise,
	if the input file has only BTF debug info, instantiate the BTF
	front end.
	* include/abg-elf-reader.h (elf::reader::find_btf_section):
	Declare new member function.
	(elf::reader::{function, variable}_symbol_is_exported): Add new
	overloads.
	* src/abg-elf-reader.cc (reader::priv::btf_section): New data
	member.
	(reader::find_btf_section): Define new member function.
	* src/Makefile.am: Add the new abg-ctf-reader.cc file to source
	distribution.
	* tools/abidw.cc (options::use_btf): New data member.
	(display_usage): Add a help string for the new --btf option.
	(parse_command_line): Support the new --btf option.
	(load_corpus_and_write_abixml):  If the user asked to use the btf
	front-end then use that one.
	* tools/abidiff.cc (options::use_btf): New data member.
	(options::options): Initialize it.
	(display_usage):: Add a help string to the new --btf options.
	(parse_command_line): Support the new --btf options.
	(main): If the user asked to use the btf front-end, then use that
	one.
	* tools/abidw.cc (options::use_btf): New data member.
	(options::options): Initialize it.
	(parse_command_line): Add a help string to the new --btf options.
	(load_corpus_and_write_abixml): If the user asked to use the btf
	front-end, then use that one.
	* tools/kmidiff.cc (options::use_btf): New data member.
	(options::options): Initialize it.
	(display_usage): Add a help string to the new --btf options.
	(parse_command_line): Add a help string to the new --btf options.
	(main): If the user asked to use the btf front-end, then use that
	one.
	* tools/abipkgdiff.cc (options::use_btf): New data member.
	(options::options): Initialize it.
	(display_usage): Add a help string to the new --btf options.
	(parse_command_line): Add a help string to the new --btf options.
	(compare, compare_to_self)
	(compare_prepared_linux_kernel_packages): If the user asked to use
	the btf front-end, then use that one.
	* tests/data/test-read-btf/test{0,1}.o: New binary test input
	file.
	* tests/data/test-read-btf/test{0,1}.c: Source code of the binary
	input file above.
	* tests/data/test-read-btf/test{0,1}.o.abi: Reference ABIXML
	output.
	* tests/data/test-abidiff-exit/btf/test0-report-{1,2}.txt: New
	test reference output.
	* tests/data/test-abidiff-exit/btf/test0-v{0,1}.o: New binary test
	input.
	* tests/data/test-abidiff-exit/btf/test0-v{0,1}.c: The source
	files of the binary inputs above.
	* tests/test-read-btf.cc: New test file to run the btf/abixml
	tests.
	* tests/Makefile.am: Add the new test files to the source
	distribution.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-06 21:05:53 +01:00
Dodji Seketeli
5d97da9755 configure: Enable the CTF front-end by default
The patch enables the CTF front-end by default, if the
ctf.h header file and its associated libctf.so shared library are
detected at configure time.  That front-end can of course still be
disabled by using the --disable-ctf option.

	* configure.ac: If --disable-ctf hasn't been passed, test for the
	presence of ctf.h and then for libctf.so.  If both are found then
	enable the CTF front end.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-05 14:04:16 +01:00
Petr Pavlu
250346cace abidiff: Fix handling of linux-kernel-mode
This fixes 08e76022 ("Support Linux Kernel ABI whitelist files") and
8fd02e0a ("Use the CTF reader by default when applicable").

The first commit removed handling of option --no-linux-kernel-mode. The
second one stopped passing opts.linux_kernel_mode down to the library
which also caused changing the default linux-kernel-mode of abidiff from
true to false. Both changes look unintentional as they are not mentioned
in either commit message.

Restore handling of the linux-kernel-mode in abidiff to match what is
described in doc/manuals/abidiff.rst and make it again consistent with
abidw.

	* tools/abidiff.cc (parse_command_line): Recognize
	  --no-linux-kernel-mode.
	  (main): Pass opts.linux_kernel_mode down to the library.

Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-05 13:07:30 +01:00
Dodji Seketeli
24a219d905 fix comparing array subrange DIEs
When looking at something else in the DWARF reader, I noticed that the
DIE comparison algorithm for DW_TAG_subprogram DIEs was not taking
into account non-set DW_AT_upper_bound attributes.

Fixed thus.

	* src/abg-dwarf-reader.cc (compare_dies): For DW_TAG_subprogram,
	non-set DW_AT_{lower,upper}_bound is not the same as when they are
	set to zero.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-01 18:21:56 +01:00
Dodji Seketeli
e02d3b85e3 Bug 29811 - Better categorize harmless unknown array size changes
Let's compile the code snippet:

$ echo "unsigned int is_basic_table[];" | gcc -g -c -o test-v0.o -x c -

Let's see what abidw sees from it:

$ abidw test-v0.o | cat -n

     1	<abi-corpus version='2.1' path='test-v0.o' architecture='elf-amd-x86_64'>
     2	  <elf-variable-symbols>
     3	    <elf-symbol name='is_basic_table' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     4	  </elf-variable-symbols>
     5	  <abi-instr address-size='64' path='&lt;stdin&gt;' comp-dir-path='/home/dodji/git/libabigail/PR29811/prtests' language='LANG_C11'>
     6	    <type-decl name='unsigned int' size-in-bits='32' id='type-id-1'/>
     7	    <array-type-def dimensions='1' type-id='type-id-1' size-in-bits='infinite' id='type-id-2'>
     8	      <subrange length='infinite' id='type-id-3'/>
     9	    </array-type-def>
    10	    <var-decl name='is_basic_table' type-id='type-id-2' mangled-name='is_basic_table' visibility='default' filepath='/home/dodji/git/libabigail/PR29811/prtests/&lt;stdin&gt;' line='1' column='1' elf-symbol-id='is_basic_table'/>
    11	  </abi-instr>
    12	</abi-corpus>

See how the at line 7, the array type of ID 'type-id-2' has an unknown
size.  This is the type of the 'is_basic_table' variable defined at
line 10.  Note however that the symbol size of the is_basic_table
symbol is 4 bytes (32 bits).

Now, let's compile a similar code where the is_basic_table variable is
now initialized:

$ echo "unsigned int is_basic_table[] = {0};" | gcc -g -c -o test-v1.o -x c -

$ $ abidw test-v1.o | cat -n

     1	<abi-corpus version='2.1' path='test-v1.o' architecture='elf-amd-x86_64'>
     2	  <elf-variable-symbols>
     3	    <elf-symbol name='is_basic_table' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     4	  </elf-variable-symbols>
     5	  <abi-instr address-size='64' path='&lt;stdin&gt;' comp-dir-path='/home/dodji/git/libabigail/PR29811/prtests' language='LANG_C11'>
     6	    <type-decl name='unsigned int' size-in-bits='32' id='type-id-1'/>
     7	    <array-type-def dimensions='1' type-id='type-id-1' size-in-bits='32' id='type-id-2'>
     8	      <subrange length='1' type-id='type-id-3' id='type-id-4'/>
     9	    </array-type-def>
    10	    <type-decl name='unsigned long int' size-in-bits='64' id='type-id-3'/>
    11	    <var-decl name='is_basic_table' type-id='type-id-2' mangled-name='is_basic_table' visibility='default' filepath='/home/dodji/git/libabigail/PR29811/prtests/&lt;stdin&gt;' line='1' column='1' elf-symbol-id='is_basic_table'/>
    12	  </abi-instr>
    13	</abi-corpus>

Now, see like at line 7, the array type is now of 4 bytes (32 bits).
Note that the size of is_basic_table is still 32 bits.

Normally, abidiff-ing test-v0 and test-v1 should tell us that the two
versions of the is_basic_table variable are compatible because
fundamentally the structure and the size of the ELF symbol
is_basic_table hasn't changed, even if in the first case, it's an
array of unknown size.  It's ELF symbol size was already 32 bits.

Here is what abidiff says:

$ abidiff test-v0.o test-v1.o
Functions changes summary: 0 Removed, 0 Changed, 0 Added function
Variables changes summary: 0 Removed, 1 Changed, 0 Added variable

1 Changed variable:

  [C] 'unsigned int is_basic_table[]' was changed to 'unsigned int is_basic_table[1]' at <stdin>:1:1:
    type of variable changed:
      type name changed from 'unsigned int[]' to 'unsigned int[1]'
      array type size changed from infinity to 32
      array type subrange 1 changed length from infinity to 1

$

This is because the comparison engine doesn't recognize we are looking
at a type change that is harmless because the ELF size hasn't changed
and because this is an array of one dimension so fundamentally, the
"meaning" of the type of the array hasn't fundamentally changed for
ABI-related purposes.

This patch teaches the diff node categorizer to recognise that we are
in a case where the (one dimension) array of unknown size actually is
the type of an array which symbol size is 4 bytes.  In the second
case, the one dimension array has a size of 4 bytes, just as its ELF
symbol size.  The diff node categorizer then categorizes the diff node
into the existing category BENIGN_INFINITE_ARRAY_CHANGE_CATEGORY,
which is a harmless diff node category.  Everything then falls into
place to filter the change out.  Also, the patch adapts the diff
reporter to better describe this type of harmless array variable type
changes.

The output then becomes:

$ abidiff test-v0.o test-v1.o
Functions changes summary: 0 Removed, 0 Changed, 0 Added function
Variables changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added variable

$

The change is filtered out.

To have details about the change that has been filtered out, one has
to use "--harmless" option:

$ abidiff --harmless test-v0.o test-v1.o
Functions changes summary: 0 Removed, 0 Changed, 0 Added function
Variables changes summary: 0 Removed, 1 Changed, 0 Added variable

1 Changed variable:

  [C] 'unsigned int is_basic_table[]' was changed to 'unsigned int is_basic_table[1]' at <stdin>:1:1:
    size of variable symbol ( 32 (in bits)) hasn't changed
    but it does have a harmless type change
    type of variable changed:
      type name changed from 'unsigned int[]' to 'unsigned int[1]'
      array type size changed from 'unknown' to 32
      array type subrange 1 changed length from 'unknown' to 1

$

	* include/abg-comp-filter.h
	(is_var_1_dim_unknown_size_array_change): Declare new function.
	* src/abg-comp-filter.cc (is_var_1_dim_unknown_size_array_change):
	Define new function.
	(has_benign_array_of_unknown_size_change): Rename
	has_benign_infinite_array_change into this.  Make this call the
	new is_var_1_dim_unknown_size_array_change.
	(categorize_harmless_diff_node): Adjust the call to
	has_benign_infinite_array_change into the new
	has_benign_array_of_unknown_size_change.
	* include/abg-ir.h (var_equals_modulo_types): Declare new
	function.  Make it friend of class decl_base.
	* src/abg-default-reporter.cc (default_reporter::report): In the
	overload for var_diff, call the new
	maybe_report_diff_for_variable.
	* src/abg-ir.cc (var_equals_modulo_types): Factorize this out of
	the equals() function for var_decl.
	(equals): In the overload for var_decl, call the new
	var_equals_modulo_types.
	* src/abg-reporter-priv.h (maybe_report_diff_for_variable):
	Declare new function.
	* src/abg-reporter-priv.cc (maybe_report_diff_for_variable):
	Define new function.
	* tests/data/test-diff-filter/test-PR29811-0-report-0.txt: Add
	new reference test output.
	* tests/data/test-diff-filter/test-PR29811-0-report-1.txt:
	Likewise.
	* tests/data/test-diff-filter/test-PR29811-0-v{0,1}.o: Add new
	binary test inputs.
	* tests/data/test-diff-filter/test-PR29811-0-v{0,1}.c: Add source
	code of the binary test inputs.
	* tests/data/Makefile.am: Add new test input files above to source
	distribution.
	* tests/test-diff-filter.cc (in_out_specs): Add new tests to
	harness.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-01 18:21:56 +01:00
Dodji Seketeli
4545e9a23a dwarf-reader: Bug 29811 - Support updating of variable type
Let's look at the source code reported at
https://sourceware.org/bugzilla/show_bug.cgi?id=29811:

    extern unsigned int is_basic_table[];

    unsigned int is_basic_table[] = {0};

Let's look at the DWARF output from GCC.  The variable is_basic_table
is described by the DIE at offset 0x51:

 [    51]    variable             abbrev: 7
             specification        (ref4) [    2f]
             decl_line            (data1) 3
             decl_column          (data1) 14
             type                 (ref4) [    3b]
             location             (exprloc)
              [ 0] addr .bss+0 <is_basic_table>

The type of the variable is defined at the offset 0x3b:

 [    3b]    array_type           abbrev: 1
             type                 (ref4) [    29]
             sibling              (ref4) [    4b]
 [    44]      subrange_type        abbrev: 6
               type                 (ref4) [    4b]
               upper_bound          (data1) 0

But then, we see that the DIE at 0x51 has a DW_AT_specification
attribute that refers to the DIE at offset 0x2f:

 [    2f]    variable             abbrev: 5
             name                 (strp) "is_basic_table"
             decl_file            (data1) test-v2.c (1)
             decl_line            (data1) 1
             decl_column          (data1) 21
             type                 (ref4) [    1e]
             external             (flag_present) yes
             declaration          (flag_present) yes

That DIE at offset 0x2f represents the first external variable
declared in the source code.  It's type is an array defined at offset
0x1e:

 [    1e]    array_type           abbrev: 1
             type                 (ref4) [    29]
             sibling              (ref4) [    29]
 [    27]      subrange_type        abbrev: 4

This array has one dimension of 'unknown' size; this is because the
dimension is described by the DIE at offset 0x27 of kind
DW_TAG_subrange_type and has no DW_AT_upper_bound DIE.

But then, I said earlier, the real type of the is_basic_table variable
is the DIE at offset 0x3b, which is an array which single dimension
described by the DIE at offset 0x44 of kind DW_TAG_subrange_type with
a DW_AT_upper_bound attribute of value 0.

Let's see the output of abidw on this program, from the DWARF debug info:

     1	<abi-corpus version='2.1' path='test-PR29811-unknown-size-array-dwarf-ctf-DWARF.o' architecture='elf-amd-x86_64'>
     2	  <elf-variable-symbols>
     3	    <elf-symbol name='is_basic_table' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     4	  </elf-variable-symbols>
     5	  <abi-instr address-size='64' path='test-PR29811-unknown-size-array-dwarf-ctf.c' comp-dir-path='/home/dodji/git/libabigail/PR29811/prtests' language='LANG_C11'>
     6	    <type-decl name='unsigned int' size-in-bits='32' id='type-id-1'/>
     7	    <array-type-def dimensions='1' type-id='type-id-1' size-in-bits='32' id='type-id-2'>
     8	      <subrange length='1' type-id='type-id-3' id='type-id-4'/>
     9	    </array-type-def>
    10	    <array-type-def dimensions='1' type-id='type-id-1' size-in-bits='infinite' id='type-id-5'>
    11	      <subrange length='infinite' id='type-id-6'/>
    12	    </array-type-def>
    13	    <type-decl name='unsigned long int' size-in-bits='64' id='type-id-3'/>
    14	    <var-decl name='is_basic_table' type-id='type-id-5' mangled-name='is_basic_table' visibility='default' filepath='/home/dodji/git/libabigail/PR29811/prtests/test-PR29811-unknown-size-array-dwarf-ctf.c' line='10' column='1' elf-symbol-id='is_basic_table'/>
    15	  </abi-instr>
    16	</abi-corpus>

The variable is_basic_table is described by the element at line 14:

    14	    <var-decl name='is_basic_table' type-id='type-id-5' mangled-name='is_basic_table' visibility='default' filepath='/home/dodji/git/libabigail/PR29811/prtests/test-PR29811-unknown-size-array-dwarf-ctf.c' line='10' column='1' elf-symbol-id='is_basic_table'/>

Its type has the ID 'type-id-5' which is defined at line 10:

    10	    <array-type-def dimensions='1' type-id='type-id-1' size-in-bits='infinite' id='type-id-5'>
    11	      <subrange length='infinite' id='type-id-6'/>
    12	    </array-type-def>

Which has an unknown size.

But the, at line 7, there is another array type defined with a size of
32 bits:

     7	    <array-type-def dimensions='1' type-id='type-id-1' size-in-bits='32' id='type-id-2'>
     8	      <subrange length='1' type-id='type-id-3' id='type-id-4'/>
     9	    </array-type-def>

So, libabigail links the is_basic_table variable to the wrong array
type.

This is because when the DWARF reader builds the internal
representation for the DW_TAG_variable DIE at offset 0x51, it first
builds it with the type (and the other properties such as the name for
instance) of the "declaration" DIE specified by the
DW_AT_specification attribute.  But then, this DW_TAG_variable DIE has
its own type at offset 0x3b ; libabigail should update the internal
representation it just built to set the type to the one referred to at
offset 0x3b.  It's that updating that is not being done.  So the
variable wrongly points to the type of the "declaration" DIE at offset
0x2f.

This patch fixes build_var_decl to make it update the type of the
variable when necessary.

	* include/abg-ir.h (var_decl::set_type): Declare new member
	function.
	* src/abg-ir.cc (var_decl::priv::set_type): Define new member
	function.
	(var_decl::set_type): Likewise.
	* src/abg-dwarf-reader.cc (build_var_decl): In "updating mode",
	update the type of the variable as well.
	* tests/data/test-diff-filter/test-PR29811-unknown-size-array-dwarf-ctf-CTF.o:
	Add new test binary input.
	* tests/data/test-diff-filter/test-PR29811-unknown-size-array-dwarf-ctf-DWARF.o:
	Likewise.
	* tests/data/test-diff-filter/test-PR29811-unknown-size-array-dwarf-ctf-report.txt:
	Add test reference output.
	* tests/data/test-diff-filter/test-PR29811-unknown-size-array-dwarf-ctf.c:
	Add source code of the new test binary input.
	* tests/data/Makefile.am: Add the new files above to source
	distribution.
	* tests/test-diff-filter.cc (in_out_specs): Add the input binaries
	to the test harness.
	* tests/data/test-annotate/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Adjust.
	* tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-01 18:21:56 +01:00
Dodji Seketeli
aef4f0fd1b Don't use the "infinite" keyword for arrays of unknown size
In the ABIXML format and in diff reports, array dimensions of unknown
size are described with the "infinite" keyword.  This is not explicit
enough.  This patch uses the keyword "unknown" instead.  Note that the
keyword "infinite" is still recognized by the ABIXML reader.

	* src/abg-reader.cc (build_subrange_type, build_array_type_def):
	Support the "unknown" keyword, as well as the "infinite" keyword.
	* src/abg-reporter-priv.cc (report_size_and_alignment_changes):
	Emit the "unknown" keyword, not the "infinity" one.
	* src/abg-writer.cc (write_array_size_and_alignment): Likewise.
	* tests/data/test-annotate/libtest24-drop-fns-2.so.abi: Adjust.
	* tests/data/test-annotate/libtest24-drop-fns.so.abi: Likewise.
	* tests/data/test-annotate/test14-pr18893.so.abi: Likewise.
	* tests/data/test-annotate/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Likewise.
	* tests/data/test-annotate/test7.so.abi: Likewise.
	* tests/data/test-read-ctf/test-array-size.abi: Likewise.
	* tests/data/test-read-ctf/test-dynamic-array.o.abi: Likewise.
	* tests/data/test-read-dwarf/PR25007-sdhci.ko.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-libandroid.so.abi: Likewise.
	* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
	* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
	* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
	* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
	* tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Likewise.
	* tests/data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.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/test9-pr18818-clang.so.abi: Likewise.
	* tests/data/test-read-write/test25.xml: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-01 18:21:56 +01:00
Dodji Seketeli
64e7901956 Update copyright year for 2023
Update the copyright years for 2023, using the script update-copyright.sh.

	* update-copyright.sh: Update the copyright years in this script.
	* include/abg-comp-filter.h: Update copyright year for 2023.
	* include/abg-comparison.h: Likewise.
	* include/abg-config.h: Likewise.
	* include/abg-corpus.h: Likewise.
	* include/abg-ctf-reader.h: Likewise.
	* include/abg-cxx-compat.h: Likewise.
	* include/abg-diff-utils.h: Likewise.
	* include/abg-dwarf-reader.h: Likewise.
	* include/abg-elf-based-reader.h: Likewise.
	* include/abg-elf-reader.h: Likewise.
	* include/abg-fe-iface.h: Likewise.
	* include/abg-fwd.h: Likewise.
	* include/abg-hash.h: Likewise.
	* include/abg-ini.h: Likewise.
	* include/abg-interned-str.h: Likewise.
	* include/abg-ir.h: Likewise.
	* include/abg-libxml-utils.h: Likewise.
	* include/abg-reader.h: Likewise.
	* include/abg-regex.h: Likewise.
	* include/abg-reporter.h: Likewise.
	* include/abg-sptr-utils.h: Likewise.
	* include/abg-suppression.h: Likewise.
	* include/abg-tools-utils.h: Likewise.
	* include/abg-traverse.h: Likewise.
	* include/abg-viz-common.h: Likewise.
	* include/abg-viz-dot.h: Likewise.
	* include/abg-viz-svg.h: Likewise.
	* include/abg-workers.h: Likewise.
	* include/abg-writer.h: Likewise.
	* src/abg-comp-filter.cc: Likewise.
	* src/abg-comparison-priv.h: Likewise.
	* src/abg-comparison.cc: Likewise.
	* src/abg-config.cc: Likewise.
	* src/abg-corpus-priv.h: Likewise.
	* src/abg-corpus.cc: Likewise.
	* src/abg-ctf-reader.cc: Likewise.
	* src/abg-default-reporter.cc: Likewise.
	* src/abg-diff-utils.cc: Likewise.
	* src/abg-dwarf-reader.cc: Likewise.
	* src/abg-elf-based-reader.cc: Likewise.
	* src/abg-elf-helpers.cc: Likewise.
	* src/abg-elf-helpers.h: Likewise.
	* src/abg-elf-reader.cc: Likewise.
	* src/abg-fe-iface.cc: Likewise.
	* src/abg-hash.cc: Likewise.
	* src/abg-ini.cc: Likewise.
	* src/abg-internal.h: Likewise.
	* src/abg-ir-priv.h: Likewise.
	* src/abg-ir.cc: Likewise.
	* src/abg-leaf-reporter.cc: Likewise.
	* src/abg-libxml-utils.cc: Likewise.
	* src/abg-reader.cc: Likewise.
	* src/abg-regex.cc: Likewise.
	* src/abg-reporter-priv.cc: Likewise.
	* src/abg-reporter-priv.h: Likewise.
	* src/abg-suppression-priv.h: Likewise.
	* src/abg-suppression.cc: Likewise.
	* src/abg-symtab-reader.cc: Likewise.
	* src/abg-symtab-reader.h: Likewise.
	* src/abg-tools-utils.cc: Likewise.
	* src/abg-traverse.cc: Likewise.
	* src/abg-viz-common.cc: Likewise.
	* src/abg-viz-dot.cc: Likewise.
	* src/abg-viz-svg.cc: Likewise.
	* src/abg-workers.cc: Likewise.
	* src/abg-writer.cc: Likewise.
	* tests/print-diff-tree.cc: Likewise.
	* tests/test-abicompat.cc: Likewise.
	* tests/test-abidiff-exit.cc: Likewise.
	* tests/test-abidiff.cc: Likewise.
	* tests/test-alt-dwarf-file.cc: Likewise.
	* tests/test-core-diff.cc: Likewise.
	* tests/test-cxx-compat.cc: Likewise.
	* tests/test-diff-dwarf-abixml.cc: Likewise.
	* tests/test-diff-dwarf.cc: Likewise.
	* tests/test-diff-filter.cc: Likewise.
	* tests/test-diff-pkg.cc: Likewise.
	* tests/test-diff-suppr.cc: Likewise.
	* tests/test-diff2.cc: Likewise.
	* tests/test-dot.cc: Likewise.
	* tests/test-elf-helpers.cc: Likewise.
	* tests/test-ini.cc: Likewise.
	* tests/test-ir-walker.cc: Likewise.
	* tests/test-kmi-whitelist.cc: Likewise.
	* tests/test-lookup-syms.cc: Likewise.
	* tests/test-read-ctf.cc: Likewise.
	* tests/test-read-dwarf.cc: Likewise.
	* tests/test-read-write.cc: Likewise.
	* tests/test-svg.cc: Likewise.
	* tests/test-symtab-reader.cc: Likewise.
	* tests/test-symtab.cc: Likewise.
	* tests/test-tools-utils.cc: Likewise.
	* tests/test-types-stability.cc: Likewise.
	* tests/test-utils.cc: Likewise.
	* tests/test-utils.h: Likewise.
	* tools/abicompat.cc: Likewise.
	* tools/abidiff.cc: Likewise.
	* tools/abidw.cc: Likewise.
	* tools/abilint.cc: Likewise.
	* tools/abipkgdiff.cc: Likewise.
	* tools/abisym.cc: Likewise.
	* tools/binilint.cc: Likewise.
	* tools/kmidiff.cc: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2023-01-01 18:19:30 +01:00
Dodji Seketeli
49fcc8d3ff ir: Add sanity checking to canonical type propagation confirmation
To understand the problem reported at
https://sourceware.org/bugzilla/show_bug.cgi?id=29934 where a type was
left non-canonicalized when analysing the binary
/usr/lib64/dovecot/libdovecot-sieve.so.0.0.0 from
https://vault.centos.org/7.6.1810/os/x86_64/Packages/dovecot-2.2.36-3.el7.x86_64.rpm
and
http://debuginfo.centos.org/7/x86_64/dovecot-debuginfo-2.2.36-3.el7.x86_64.rpm,
I had to add some sanity checking code to ensure that types that have
seen their propagated canonical cleared during the canonicalization
process are fully canonicalized at the end of the canonicalization
process.

In order to performg that sanity checking this patch tracks the set of
types which propagated canonical type has been cleared during the
canonicalization of a particular type.  When a type with such a
cleared propagated canonical type is finally canonicalized, it is
removed from the set of tracked types.  At the end of the
canonicalization process, the set of tracked types must be empty.

This sanity check is compiled in only if the WITH_DEBUG_CT_PROPAGATION
preprocessor macro is defined.  That macro is defined if the
--enable-debug-ct-propagation configure switch is used.

	* configure.ac: Add a new --enable-debug-ct-propagation configure
	flag that defines the WITH_DEBUG_CT_PROPAGATION preprocessor
	macro.
	* src/abg-ir-priv.h
	(environment::priv::types_with_cleared_propagated_ct_): Define new
	data member for tracking types with cleared propagated canonical
	type.
	(environment::priv::types_with_cleared_propagated_ct): Add getter
	and setter for the new data member above.
	(environment::priv::{record_type_with_cleared_propagated_canonical_type,
	erase_type_with_cleared_propagated_canonical_type}): Add
	book-keeping functions for the set of types with cleared
	propagated canonical type.
	(type_base::priv::clear_propagated_canonical_type): Make this
	return true if the propagated canonical type is cleared.
	(environment::priv::clear_propagated_canonical_type): Define a new
	function that takes a type_base* and clears its propagated
	canonical type.  This also adds the type to the set of tracked
	types returned by
	environment::priv::types_with_cleared_propagated_ct().
	(environment::priv::{cancel_ct_propagation_for_types_dependant_on,
	cancel_ct_propagation}): Call the new
	environment::priv::clear_propagated_canonical_type() rather than
	calling the now low-level
	type_base::priv::clear_propagated_canonical_type().
	(environment::priv::propagate_ct): Remove the type which just
	gained a propagated canonical type from the set of tracked types
	returned by environment::priv::types_with_cleared_propagated_ct.
	(canonicalize_types): Define new function that canonicalizes all
	the types of the system (passed in parameter) and performs sanity
	checking to make sure all types with cleared propagated canonical
	types have been canonicalized.
	* include/abg-ir.h (string_type_base_sptr_map_type): Define new
	typedef for an unordered_map<string, type_base_sptr>.
	* src/abg-ir.cc (canonicalize): Remove the type which has just
	been canonicalized from the set of tracked types returned by
	environment::priv::types_with_cleared_propagated_ct.
	* src/abg-ctf-reader.cc (reader::types_map): Use the new
	string_type_base_sptr_map_type typedef for the type of this map.
	(reader::canonicalize_all_types): Use the new function
	abigail::ir::canonicalize_types to canonicalize the types of the
	system and perform necessary sanity checking.
	* src/abg-dwarf-reader.cc (reader::canonicalize_types_scheduled):
	Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-29 11:28:51 +01:00
Dodji Seketeli
4f4ab2b1d6 ir: Bug 29934 - Fix propagated canonical type confirmation
When canonicalization a type T, it can happen that one subtype S of T
compares equal to a type S' where S' is already canonicalized.  In
that case, we can deduce that the canonical type of S equals the
canonical type of S', even if we are currently in the process of
canonicalizing T.

In other words, the canonical type of S' is "propagated to S", in the
process of canonicalizing T.

This optimization is called "canonical type propagation" and is meant
to spead up the overall canonicalization process.

However, in some cases, the propagated canonical type can be
"cancelled" for the optimization to be correct.  In those cases, the
propagated canonical type is set to nil.

When analysing the binary libdovecot-sieve.so from the problem
reported at https://sourceware.org/bugzilla/show_bug.cgi?id=29934, we
encounter a case where a function type's propagated type is
erroneously cancelled.  That leaves the canonical type of that
function type not set and that later violates the assert

    ABG_ASSERT(is_non_canonicalized_type(t)) in
    abigail::ir::hash_as_canonical_type_or_constant.

I tracked this down to return_comparison_result which fails to confirm
a case of propagated canonical type and thus, some of them can end up
being erroneously cancelled.

Fixed thus.

	* src/abg-ir.cc (return_comparison_result): A type whose canonical
	type has been propagated must have its canonical type confirmed if
	that type is not recursive and is not dependant on any recursive
	type.  In that case, the canonical type will never be cancelled.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-29 11:28:15 +01:00
Dodji Seketeli
5a32ff22c2 ir: misc cleanups
When looking at something else, I noticed some useless friend function
declaration.  Namely, the "canonicalize()" function is declared friend
to the decl_base and scope_decl clases, which is now useless.

This patch removes those declarations.

	* include/abg-ir.h (decl_base, scope_decl): Remove the declaration
	of canonicalize() as friend to these classes.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-29 11:27:57 +01:00
Dodji Seketeli
315dff674a elf-reader: Don't free CTF resources too early
elf::reader::locate_alt_ctf_debug_info frees the memory for the
alternate CTF debug info too early, leading to some segmentation
violation down the road, when the rest of the code tries to access the
CTF section afterwards.  Many thanks to the Valgrind tool and its
hackers for showing me this.

This patch thus keeps the file descriptor and ELF data structure of
the alternate CTF debug info around for the lifetime of the reader.

	* src/abg-elf-reader.cc (reader::priv::{alt_ctf_fd,
	alt_ctf_handle}): Add new data members.
	(reader::priv::clear_alt_ctf_debug_info_data): Define new member
	function.
	(reader::priv::~priv): Call the new
	priv::clear_alt_ctf_debug_info_data
	(reader::priv::initialize): Likewise.  Initialize the new
	alt_ctf_handle and alt_ctf_fd data members.
	(reader::priv::locate_alt_ctf_debug_info): Do not free the fd and
	ELF resources early here.  Store them in the new
	reader::priv::alt_ctf_{fd,handle} instead.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-29 11:27:34 +01:00
Dodji Seketeli
de45f1e69b dwarf-reader: Bug 29932 - Handle function DIE as type as needed
When building the IR for a function type, the DWARF reader considers
the function DIE we are looking at as a type DIE.

In dwarf::reader::lookup_fn_type_from_die_repr_per_tu, the call to
get_die_pretty_representation doesn't enforce the fact that the DIE we
are looking at must be considered as a type.  This is usually not a
problem because even if get_die_pretty_representation considers the
function DIE as a decl, the representation of a function and a
function type are almost the same.

In this particular case, we run into a function DIE that has an empty
name:

 [ 51e54]    subprogram           abbrev: 18
             external             (flag_present) yes
             name                 (strp) ""
             decl_file            (data1) catgets.c (1)
             decl_line            (data1) 89
             prototyped           (flag_present) yes
             type                 (ref4) [ 51ac5]
             low_pc               (addr) +0x0000000000034cc0
             high_pc              (data8) 133 (+0x0000000000034d45)
             frame_base           (exprloc)
              [ 0] call_frame_cfa
             GNU_all_call_sites   (flag_present) yes
             sibling              (ref4) [ 51edb]

Note that this is from the /lib64/libc-2.17.so from the
https://vault.centos.org/7.6.1810/os/x86_64/Packages/glibc-2.17-260.el7.x86_64.rpm
package, associated with the debuginfo package at http://debuginfo.centos.org/7/x86_64/glibc-debuginfo-2.17-260.el7.x86_64.rpm.

In that case, get_die_pretty_representation returns an empty string
because it doesn't expects a function decl with an empty name.

If we make dwarf::reader::lookup_fn_type_from_die_repr_per_tu
explicitly be in the context of a type by invoking
get_die_pretty_type_representation instead, the problem disapears as
the latter function treats the DIE as a function type DIE, so it
doesn't need its name.

Thus, this patch makes
dwarf::reader::lookup_fn_type_from_die_repr_per_tu invoke
get_die_pretty_type_representation instead.

	* src/abg-dwarf-reader.cc
	(reader::lookup_fn_type_from_die_repr_per_tu): Invoke
	get_die_pretty_type_representation instead of
	get_die_pretty_representation when looking at a function DIE
	without a name.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-26 13:27:46 +01:00
Dodji Seketeli
e3725f1b96 Bug 29934 - Handle buggy data members with empty names
When handling the changes between two ABI corpora, the diff graph
building pass chokes on a data member which seems to erroneously have
an empty name.

The steps to reproduce the issue are explained in the problem report
at https://sourceware.org/bugzilla/show_bug.cgi?id=29934.

The root cause of the problem is that the "struct mailbox" data
structure from the binary /usr/lib64/dovecot/libdovecot-storage.so.0
coming from the dovecot-2.2.36-3.el7.x86_64.rpm package contains a
data member that has an empty name.  The source code of that data
structure can be browsed at
https://github.com/dovecot/core/blob/release-2.2.36/src/lib-storage/mail-storage-private.h

We see that the mailbox::storage data structure at line 352 ends up in
the DWARF debug info with an empty name.  Let's look at the DWARF
dump as emitted by "eu-readelf --debug-dump=info" on the
/usr/lib/debug//usr/lib64/dovecot/libdovecot-storage.so.0.debug file
from the dovecot-debuginfo-2.2.36-3.el7.x86_64.rpm package.

A relevant DIE for the "struct mailbox" is the following:

 [  3e3e]    structure_type       abbrev: 9
             name                 (strp) "mailbox"
             byte_size            (data2) 768
             decl_file            (data1) mail-storage-private.h (24)
             decl_line            (data2) 348
             sibling              (ref_udata) [  41f9]
 [  3e4a]      member               abbrev: 59
               name                 (strp) "name"
               decl_file            (data1) mail-storage-private.h (24)
               decl_line            (data2) 349
               type                 (ref_addr) [    84]
               data_member_location (data1) 0
 [  3e57]      member               abbrev: 59
               name                 (strp) "vname"
               decl_file            (data1) mail-storage-private.h (24)
               decl_line            (data2) 351
               type                 (ref_addr) [    84]
               data_member_location (data1) 8
 [  3e64]      member               abbrev: 47
               name                 (strp) ""
               decl_file            (data1) mail-storage-private.h (24)
               decl_line            (data2) 352
               type                 (ref_udata) [  3bee]
               data_member_location (data1) 16

[...]

You can see here that the DW_TAG_member DIE at offset 0x3e64 has an
empty name.  Its DW_AT_type attribute references the DIE at offset
0x3bee.

The DIE at offset 0x3bee is this one:

 [  3bee]    pointer_type         abbrev: 95
             byte_size            (data1) 8
             type                 (ref_udata) [  3a90]

[...]

It's a pointer to the type which DIE is at offset 0x3a90, which is:

 [  3a90]    structure_type       abbrev: 48
             name                 (strp) "mail_storage"
             byte_size            (data2) 352
             decl_file            (data1) mail-storage-private.h (24)
             decl_line            (data1) 132
             sibling              (ref_udata) [  3bee]

So, the data member of "struct mailbox" which has an empty name has a
type "pointer to struct mail_storage", aka "struct mail_storage*".
That indeed corresponds to the "storage" data member that we see at
line 352 of the mail-storage-private.h file, browsable at
https://github.com/dovecot/core/blob/release-2.2.36/src/lib-storage/mail-storage-private.h.

The fact that this data member has an empty name seems to me as a bug
of the DWARF emitter.

Libabigail ought to gently handle this bug instead of choking.

This patch assigns an artificial name to that empty data member to
handle this kind of cases in the future. The names looks like
"unnamed-@-<location>" where "location" is the location of the data
member.

Please note that there can be normal cases of anonymous data members
where the data member has an empty name.  In those cases, the data
member must be of type union or struct.  This is to describe the
"unnamed fields" C feature described at
https://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html.

The buggy case we are seeing here is different from the "unnamed
field" case because the type of the anonymous data member is neither
struct nor union.

	* src/abg-dwarf-reader.cc (die_is_anonymous_data_member): Define
	new static function.
	(die_member_offset): Move the declaration of this up so that it
	can be used more generally.
	(reader::build_name_for_buggy_anonymous_data_member): Define new
	member function.
	(add_or_update_class_type): Generate an artificial name for buggy
	data members with empty names.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-24 14:57:35 +01:00
Guillermo E. Martinez
9af85a7032 ctf-reader: Fix missing initializer for member in test suite
With -Werror=missing-field-initializers on, the compiler chokes on CTF
test suite.  Fixed thus.

	* tests/test-read-ctf.cc (in_out_specs): Add initializer for
	`option' field in test entry.
	* tests/data/test-read-ctf/test-alias.o.abi: Adjust.

Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-23 11:45:37 +01:00
Guillermo E. Martinez
4cf2ef8f97 ctf-front-end: Add test for alias symbols
This patch adds a new test case in the ctf-front-end test suite to
to test for alias symbols support.

	* tests/data/test-read-ctf/test-alias.o: New binary test input file.
	* tests/data/test-read-ctf/test-alias.o.abi: New exported abixml file.
	* tests/data/Makefile.am: Add the new test input above
	* tests/test-read-ctf.cc: Add the new test input above to the test
	harness.

Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-22 10:59:05 +01:00
Xiaole He
83bbc679e5 elf-reader: reclaim fd and mem before break
In elf::reader::priv::locate_alt_ctf_debug_info from
src/abg-elf-reader.cc, the resources held by the hdl and fd variables
aren't necessary released because the control-flow gets out of the
loop too early.  This patch fixes the problem.

        * src/abg-elf-reader.cc
	(elf::reader::priv::locate_alt_ctf_debug_info): Reclaim fd and mem
	before break.  Also, do not try to locate the debug info it's
	already been located.

Signed-off-by: Xiaole He <hexiaole@kylinos.cn>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-21 11:15:23 +01:00
Dodji Seketeli
e1aadfa576 Bug 29901 - abidiff hangs when comparing libgs.so.10 with itself
This is a follow-up patch to this one:
    88c6e080 Bug 29857 - Better detect comparison cycles in type graph

When looking at the type comparison stack, it looks like a type that
is on the left-hand side of the comparison can appear on the
right-hand side later, in the comparison stack.  The cycle detection
algorithm doesn't take that scenario into account and so that cycle in
the graph of types being compared is not detected.

This patch takes that case into account.

	* src/abg-ir-priv.h (environment::priv::comparison_started): Look
	for each operand of the comparison in both the right-hand and
	left-hand operand stacks.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-20 16:30:52 +01:00
Dodji Seketeli
3c6a461bc0 Update website documentation for 2.2
* mainpage.txt: Update for 2.2.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-19 18:46:45 +01:00
Dodji Seketeli
73d8782c96 configure: Bump version number to 2.3
* configure.ac: Bump version number to 2.3

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-19 18:46:45 +01:00
Dodji Seketeli
7a7a00c397 ChangeLog: Update for 2.2 release
* ChangeLog: Update by doing "make update-changelog".

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-19 18:46:45 +01:00
Dodji Seketeli
4e7da18a81 NEWS: Update for 2.2 release
* NEWS: Update for 2.2 release, with the output of
	`git shortlog libabigail-2.1..HEAD`

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-19 18:46:45 +01:00
Petr Pavlu
d3bc68b8d8 Fix de-initialization of elf::reader::priv
This fixes 7bd69830 ("Make Front Ends first class citizens").

Add a destructor for elf::reader::priv which releases any allocated alt
DWARF data and fix the initialize() method to fully reset the object.

The latter fixes a crash observed when handling multiple files. For
instance, when reading the Linux kernel tree, load_vmlinux_corpus()
processes vmlinux and all modules. Member dwarf_handle was never reset
after setting it for the first file which could later result in use of
invalid DWARF data in dwarf::reader::build_die_parent_maps().

	* src/abg-elf-reader.cc (priv::~priv): Release alt debug
	information.
	(priv::initialize): Reset all members.
	(priv::clear_alt_dwarf_debug_info_data): New helper function.

Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-19 18:44:59 +01:00
Dodji Seketeli
2a54f0ab5e ir: Cache more aggregate type comparison results
In the aftermath of
https://sourceware.org/bugzilla/show_bug.cgi?id=29857, I figured
caching comparison results at one place (in a macro) leads to better
maintainability.  Also, using that macro in the equal() overload for
class_decl, union_decl and function_type results in slightly more
results of aggregate type comparison being cached during type
canonicalization.  And that might speed things up.

When measuring the impact on the comparison of the bug mentionned
above, comparison that takes ~ 43 minutes, we gain 30secs with this
patch.  We went from:

    $ time ~/build/tools/abidiff --d1 ghostscript-9.07-31.el7.x86_64/usr/lib/debug --d2 ghostscript-9.52-5.oe1.x86_64/usr/lib/debug/ ghostscript-9.07-31.el7.x86_64/usr/lib64/libgs.so.9 ghostscript-9.52-5.oe1.x86_64/usr/lib64/libgs.so.9

    Functions changes summary: 342 Removed, 940 Changed (2084 filtered out), 586 Added functions
    Variables changes summary: 70 Removed, 432 Changed (333 filtered out), 81 Added variables
    Function symbols changes summary: 2 Removed, 19 Added function symbols not referenced by debug info
    Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referenced by debug info

    (...)

    real	42m33,633s
    user	41m54,699s
    sys	0m1,381s
    $

to:

    $ time ~/build/tools/abidiff --d1 ghostscript-9.07-31.el7.x86_64/usr/lib/debug --d2 ghostscript-9.52-5.oe1.x86_64/usr/lib/debug/ ghostscript-9.07-31.el7.x86_64/usr/lib64/libgs.so.9 ghostscript-9.52-5.oe1.x86_64/usr/lib64/libgs.so.9

    Functions changes summary: 342 Removed, 940 Changed (2084 filtered out), 586 Added functions
    Variables changes summary: 70 Removed, 432 Changed (333 filtered out), 81 Added variables
    Function symbols changes summary: 2 Removed, 19 Added function symbols not referenced by debug info
    Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referenced by debug info

    (...)

    real	42m2,364s
    user	41m23,911s
    sys	0m0,326s
    $

	* src/abg-ir.cc (CACHE_AND_RETURN_COMPARISON_RESULT): Define new
	macro.
	(equals): In the overloads for function_type, class_decl, and
	union_decl use the new CACHE_AND_RETURN_COMPARISON_RESULT.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-19 18:15:48 +01:00
Dodji Seketeli
88c6e080b6 Bug 29857 - Better detect comparison cycles in type graph
When comparing two aggregates A and B, it can happen that has a
sub-type of A is itself; similarly for B.  This is a cycle in the type
graph, obviously.  Also, A and B are said to be recursive types.

Structally comparing two recursive types (i.e, comparing them
member-wise) can lead to an endless loop.

So, during type canonicalization, comparison cycles must be detected
to avoid those endless loop.

This is currently done in the equals() overload for class_decl,
union_decl, class_or_union as well as function_type.  Those are the
aggregate types that are subject to these cycles when comparing
recursive types.

Currently, detecting comparison cycles is based on
ir::environment::priv::mark_as_being_compared(),
ir::environment::priv::priv::unmark_as_being_compared(),
ir::environment::priv::comparison_started() considering the pair of
pointer to aggregate types being currently compared.  If that pair
appears more than once in the stack of aggregates being compared a
cycle is detected.

But then, watching the stack of aggregates during the analsysis of the
/usr/lib64/libgs.so.9 binary from the ghostscript-9.52-5.oe1.x86_64
package from https://sourceware.org/bugzilla/show_bug.cgi?id=29857 it
appears that the stack of aggregates (structs) was growing endlessly,
when comparing the "struct gs_memory_s" type, and the same struct
gs_memory_s aggregate was appearing several times on the right-hand
side of the comparison stack.  Clearly, this is a comparison cycle.

The gs_memory struct is appearing several times as the right hand side
operand in the stack of operands being compared, even though no pair
of operands being compared was present more than once.

This prompted me to use another heuristic to detect comparison cycles:
If the same aggregate type is appearing several times on either the
left or right hand side of the comparison stack then a cycle is
detected.

This fixes the cycle detection failure above and comparing the two
binaries completes in ~ 43 minutes on my laptop, with a non optimized
libabigail build.

	* src/abg-ir-priv.h (class_set_type, fn_set_type): Define new typedefs.
	* src/abg-ir.cc (environment::priv::{left_classes_being_compared_,
	right_classes_being_compared_, left_fn_types_being_compared_,
	right_fn_types_being_compared_}): Define new data members.
	(environment::priv::{classes_being_compared_,
	fn_types_being_compared_}): Erase data members.
	(environment::priv::{dump_classes_being_compared,
	dump_fn_types_being_compared}): Erase member functions.
	(environment::priv::{mark_as_being_compared,
	unmark_as_being_compared, comparison_started}): Change this to use
	the left-hand-side and right-hand-side comparison stack introduced
	above.
	(dump_classes_being_compared, dump_fn_types_being_compared):
	Remove functions.

Signed-off-by: Dodji Seketeli <dodji@seketeli.org>
2022-12-19 17:52:10 +01:00
Dodji Seketeli
fc71e519bb Bug 29857 - dwarf-reader: Resolve decl-only unions
When looking at https://sourceware.org/bugzilla/show_bug.cgi?id=29857
I noticed that decl-only unions where not resolved to their definition
union, unlike what is done for classes and enums.

At type canonicalization, a type A defined in a translation unit TU,
that depends on a decl-only union U will compare different from a type
A defined in a translation unit TU', that depends on the definition of
U, even though the types A should be equal.

This patch teaches the decl-only class resolver to also resolve
decl-only unions, as opposed to resolving just decl-only classes.

	* include/abg-fwd.h (typedef classes_or_unions_type): Declare new
	typedef.
	(lookup_union_types): Declare new function.
	* src/abg-dwarf-reader.cc (reader::decl_only_classes_map_): Change
	the type of this from string_classes_map to
	string_classes_or_unions_map.
	(reader::declaration_only_classes): Return a
	string_classes_or_unions_map, no more a string_classes_map.
	(reader::{maybe_schedule_declaration_only_class_for_resolution,
	is_decl_only_class_scheduled_for_resolution}): Handle
	class_or_union, not just class_decl.  This is a way to make this
	handle unions as well as classes.
	(get_opaque_version_of_type): Adjust.
	* src/abg-ir.cc (lookup_union_types): Define new function.
	* tests/data/test-annotate/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Adjust.
	* tests/data/test-read-dwarf/test19-pr19023-libtcmalloc_and_profiler.so.abi:
	Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-19 17:52:10 +01:00
Dodji Seketeli
10dd604e18 Bug 29857 - Don't pop comparison operands that haven't been pushed
While looking at bug
https://sourceware.org/bugzilla/show_bug.cgi?id=29857, I noticed a
crash that is happening due to the fact that the equal overload for
classes tries pop comparison operands that haven't been pushed to the
stack of comparison operands.  Oops.  Fixed thus.

	* src/abg-ir.cc (equals): In the overload for class_or_union,
	don't try to pop, operands that haven't been pushed.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-19 17:52:10 +01:00
Dodji Seketeli
fd821dd4db ir: Add a debug_comp_stack debugging function
When debugging type comparison, it can useful to see what the
comparison stack is.  This patch adds the a debug_comp_stack to dump
the comparison stack as a string.

	* include/abg-fwd.h (debug_comp_stack): Declare function.
	* src/abg-ir.cc (debug_comp_vec, print_comp_stack): Define static
	functions.
	(debug_comp_stack): Define new function.

Signed-off-by: Dodji Seketeli <dodji@seketeli.org>
2022-12-19 17:05:31 +01:00
Dodji Seketeli
c2cab36429 ir: Improve get_debug_representation
* src/abg-ir.cc (get_debug_representation): Prefix
	classes/structs/unions with the 'classes/struct/union' prefix.

Signed-off-by: Dodji Seketeli <dodji@seketeli.org>
2022-12-19 17:04:57 +01:00
Dodji Seketeli
1f51b9e85d Bug 29829 - dwarf-reader: Allow DIEs to be in a lexical block
Normally, ABI-relevant DWARF DIEs (types and decls) should be at
namespace level.  There are real-life cases where such a DIE might be
defined in a lexical block.

This patch teaches the DWARF reader to handle such cases.

	* src/abg-dwarf-reader.cc (get_scope_for_die): Support
	DW_TAG_lexical_block as DIE scope.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-02 17:13:13 +01:00
Dodji Seketeli
ac53e88bdb dwarf-reader: Make die_peel_{qual_ptr,typedef} always set peeled type
When die_peel_{qual_ptr,typedef} don't actually peel anything, they
don't set the peeled type output argument.  So callers expecting that
argument to be set can be surprised by the fact the peeled argument
might not be set.

	* src/abg-dwarf-reader.cc (die_peel_qual_ptr, die_peel_typedef):
	If the function returned true, then set the peeled argument even
	if the function hasn't peeled anything.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-12-02 17:12:59 +01:00
Dodji Seketeli
4bdaf30bbb dwarf-reader: Avoid duplicating member functions
Depending on how the DWARF DIEs are encountered, it can happen that
the reader mistakenly adds the same member function several times.

This is because due to DIE canonicalization, when we encounter the
class DIE C' that is equivelent to a class C that we have already
encountered, C' is dropped on the floor and C is kept.  But then, the
member functions of C' should not added to C, rather, if they are
already present in C, we shouldn't add them anymore.  This is what
build_or_get_fn_decl_if_not_suppressed is supposed to do, but fails to
do in a subtle way.

This patch fixes it.

	* src/abg-dwarf-reader.cc
	(build_or_get_fn_decl_if_not_suppressed): Fix the code that is
	supposed to avoid duplicating a member function.
	* tests/data/test-annotate/test14-pr18893.so.abi: Adjust.
	* 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/test20-pr19025-libvtkParallelCore-6.1.so.abi:
	Likewise.
	* tests/data/test-annotate/test21-pr19092.so.abi: Likewise.
	* tests/data/test-read-dwarf/PR22122-libftdc.so.abi: Likewise.
	* tests/data/test-read-dwarf/test-libandroid.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/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/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/test9-pr18818-clang.so.abi: Likewise.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-30 17:24:20 +01:00
Dodji Seketeli
d222b44733 dwarf-reader: Leverage ODR & DWZ
When DWARF debug info has been preprocessed with the DWZ tool, I think
we can assume that if two DIEs originating from the .gnu_debugaltlink
section have different offset, it means they are different, even if
they represent two types of the same nature and of the same name.
This is the whole point of DWZ.

When we process two DIEs originating from C++, it's possible "in
general" to assume that the One Definition Rule is in effect, meaning
that if two types of the same nature have the same name, they ought to
represent the same entity, meaning, they are the same type.

These two observations can lead to faster comparison of two aggregate
types of the same nature and of the same name.

This patch implements these two optimizations and use them by
default.

The first one is used by default on binaries that contains a
.gnu_debugaltlink section, which is the hint we use to detect that DWZ
was used to factorize DWARF DIEs.

The second of is used by default on DWARF DIEs originating from C++.

These optimizations can be de-activated on abidw and abidiff using the
--no-leverage-dwarf-factorization and --no-assume-odr-for-cplusplus.

	* doc/manuals/abidiff.rst: Add documentation for
	--no-leverage-dwarf-factorization and
	--no-assume-odr-for-cplusplus
	* doc/manuals/abidw.rst: Likewise.
	* doc/manuals/abipkgdiff.rst: Likewise.
	* include/abg-fe-iface.h (options::{leverage_dwarf_factorization,
	assume_odr_for_cplusplus}): New data members.
	* src/abg-dwarf-reader.cc (reader::leverage_dwarf_factorization_):
	New data member.
	(reader::leverage_dwarf_factorization): New accessor.
	(compare_dies): If we are allowed to leverage the DWARF
	factorization and if two type DIEs coming from the
	.gnu_debugaltlink DWARF section have different offset, then they
	are different.  Also, if we are allowed to assume ODR, use it to
	speed up class/struct/unions comparisons.
	* tools/abidiff.cc (options::{assume_odr_for_cplusplus,
	leverage_dwarf_factorization}): Define new data members.
	(options::options): Initialize them.
	(display_usage): Add new help strings for
	--no-leverage-dwarf-factorization and
	--no-assume-odr-for-cplusplus.
	(parse_command_line): Parse these new options.
	(set_generic_options): New function.
	(main): Use the new set_generic_options function.
	* tools/abidw.cc (options::{assume_odr_for_cplusplus,
	leverage_dwarf_factorization}): Define new data members.
	(options::options): Initialize them.
	(display_usage): Add new help strings for
	--no-leverage-dwarf-factorization and
	--no-assume-odr-for-cplusplus.
	(parse_command_line): Parse these new options.
	(set_generic_options): New function.
	(load_corpus_and_write_abixml): Use the new set_generic_options
	function.
	* tools/abipkgdiff.cc (options::{assume_odr_for_cplusplus,
	leverage_dwarf_factorization}): Define new data members.
	(options::options): Initialize them.
	(display_usage): Add new help strings for
	--no-leverage-dwarf-factorization and
	--no-assume-odr-for-cplusplus.
	(parse_command_line): Parse these new options.
	(set_generic_options): New function.
	(compare): Use it.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-30 17:17:15 +01:00
Dodji Seketeli
754364d5ca Fix spurious deleted/added virtual destructor change report
While looking at something else, I noticed this spurious change
report:

    1 member function deletion:
      'method virtual tbb::internal::concurrent_queue_base_v3::~concurrent_queue_base_v3(int)' at concurrent_queue.cpp:361:1
    1 member function insertion:
		'method virtual tbb::internal::concurrent_queue_base_v3::~concurrent_queue_base_v3(int)' at concurrent_queue.cpp:370:1

This is when running tests/runtestdiffpkg and the result is in
tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt.

To understand what is going on, one need to refer to the definitions
of the C++ ABI at
https://itanium-cxx-abi.github.io/cxx-abi/abi.html#definitions.

When a class has a virtual destructor, historically, there might be 3
different and co-existing actual implementations of the destructors:
the D0, D1 and D2 destructors.  There might even be a D3 destructor,
actually.

In https://github.com/itanium-cxx-abi/cxx-abi/issues/73, one can see
that there might be new D4 and D5 destructors.  Each one of them might
replace the set of the D0,D1,D2 destructors.

So, in a new version of a binary, the virtual D4 destructor might
replace the previous ones, without it being an ABI issue.

The switch to the D4 virtual destructor is what libabigail is naively
reporting in the change report above.

This patch detects this kind of changes in the pipeline when the edit
script from the diff2 algorithm is interpreted for virtual member
functions and drops it on the floor.

	* src/abg-comparison.cc (find_virtual_dtor_in_map): Define new
	static function.
	(class_diff::ensure_lookup_tables_populated): If a virtual
	destructor is removed from the old binary version but is added to
	the new one (but through a different name), let's assume the
	virtual destructor is still there so there is no ABI issue
	from that point of view.
	* tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt: Adjust.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-30 17:12:32 +01:00
Guillermo E. Martinez via Libabigail
77ae314176 ctf-reader: Fix array size representation
A variable length array (VLA), or a flexible array member (with its
size set to zero to recognize such cases) is represented in the
libabigail IR as an array with "non-finite" length.  This is a way to
say that the length of the array is not statically known.

The ABIXML array-type-def element looks like:

<array-type-def dimensions='1' ... size-in-bits='infinite' ...>
    <subrange length='infinite' type-id='type-id-3' .../>
</array-type-def>

The patch teaches the ctf-reader to correctly set the size of the
array for VLAs.

	* src/abg-ctf-reader.cc (build_array_ctf_range): Use
	* tests/data/Makefile.am: Add new test.
	`upper_bound' and number of elements to indicate infinite
	array size.
	* tests/data/test-read-ctf/test-array-size.abi: New test.
	* tests/data/test-read-ctf/test-array-size.c: Likewise.
	* tests/data/test-read-ctf/test-array-size.o: Likewise.
	* tests/test-read-ctf.cc: Update testsuite.

Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-30 10:49:22 +01:00
Guillermo E. Martinez
e33a74fb8c ctf-reader: Fix representation of multidimensional arrays
To build an IR for multidimensional array the CTF front-end iterates
over the element types recursively.

So, consider the array definition:

  char a[2][3][4][5];

It's represented as

  'char[2][3][4] a[5]'

instead of:

  'char a[2][3][4][5]'

It always considers multidimensional arrays as unidimensional creating
a `array-type-def' node for each dimension:

  <array-type-def dimensions='1' type-id='type-id-1' ... >
    <subrange length='2' type-id='type-id-3' id='type-id-4'/>
  </array-type-def>
  <array-type-def dimensions='1' type-id='type-id-2' ... >
    <subrange length='3' type-id='type-id-3' id='type-id-6'/>
  </array-type-def>
  ...

Instead of:

  <array-type-def dimensions='4' type-id='type-id-1' ... >
     <subrange length='2' type-id='type-id-3' id='type-id-4'/>
     <subrange length='3' type-id='type-id-3' id='type-id-5'/>
     ...
  </array-type-def>

Fixed thus.

	* src/abg-ctf-reader.cc (+build_array_ctf_range): New definition.
	* tests/data/Makefile.am: Add new testcase.
	* tests/data/test-read-ctf/test-array-mdimension.abi: New testcase.
	* tests/data/test-read-ctf/test-array-mdimension.c: Likewise.
	* tests/data/test-read-ctf/test-array-mdimension.o: Likewise.
	* tests/data/test-read-ctf/test9.o.abi: Adjust.
	* tests/test-read-ctf.cc: Update testsuite.

Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-30 10:39:51 +01:00
Guillermo E. Martinez
916f541a9a ctf-reader: Strip qualification from a qualified array type
Sometimes, GCC emits some redundant const qualifiers around arrays.

For instance, consider this function:

    $ cat -n test.c
	 1	const char a[32];
	 2
	 3	char
	 4	foo()
	 5	{
	 6	  return a[0];
	 7	}
    $

Notice how at line 1, the type of the variable 'a' is "array of const
char".

Let's compile the function and emit CTF debug info:

    $ gcc -gctf -c test.c
    $

Let's see what IR libabigail emits from the CTF information:

    $ abidw --ctf --annotate test.o  | cat -n
	 1	<abi-corpus version='2.1' path='test.o' architecture='elf-amd-x86_64'>
	 2	  <elf-function-symbols>
	 3	    <!-- foo -->
	 4	    <elf-symbol name='foo' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
	 5	  </elf-function-symbols>
	 6	  <elf-variable-symbols>
	 7	    <!-- signed char -->
	 8	    <elf-symbol name='a' size='32' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
	 9	  </elf-variable-symbols>
	10	  <abi-instr address-size='64' language='LANG_C'>
	11	    <!-- char -->
	12	    <type-decl name='char' size-in-bits='8' alignment-in-bits='8' id='type-id-1'/>
	13	    <!-- const char[32] -->
	14	    <array-type-def dimensions='1' type-id='type-id-2' size-in-bits='256' alignment-in-bits='8' id='type-id-3'>
	15	      <!-- <anonymous range>[32] -->
	16	      <subrange length='32' type-id='type-id-4' id='type-id-5'/>
	17	    </array-type-def>
	18	    <!-- unsigned long int -->
	19	    <type-decl name='unsigned long int' size-in-bits='64' alignment-in-bits='64' id='type-id-4'/>
	20	    <!-- const char -->
	21	    <qualified-type-def type-id='type-id-1' const='yes' id='type-id-2'/>
	22	    <!-- const char[32] const -->
	23	    <qualified-type-def type-id='type-id-3' const='yes' id='type-id-6'/>
	24	    <!-- const char[32] const a -->
	25	    <var-decl name='a' type-id='type-id-6' mangled-name='a' visibility='default' elf-symbol-id='a'/>
	26	    <!-- char foo() -->
	27	    <function-decl name='foo' visibility='default' binding='global' size-in-bits='64' alignment-in-bits='8' elf-symbol-id='foo'>
	28	      <!-- char -->
	29	      <return type-id='type-id-1'/>
	30	    </function-decl>
	31	  </abi-instr>
	32	</abi-corpus>
    $

Notice how at line 25, the variable 'a' is described as having the
type which ID is 'type-id-6' defined at line 23.  It's a "const array
of const char".

GCC has thus added a redundant "const" qualifier to the array.

The C language specification in paragraph [6.7.3]/8 says:

    If the specification of an array type includes any type
    qualifiers, the element type is so- qualified, not the array type.

This means that a "const array of char" is the same as an "array of
const char".  So a "const array of const char" is the same an "array
of const char".

This patch performs that removal of redundant qualifier.

	* src/abg-ctf-reader.cc (maybe_strip_qualification): New
	definition.
	(process_ctf_qualified_type): Strip redundant qualifiers.
	* tests/data/test-read-ctf/test-const-array.abi: New test.
	* tests/data/test-read-ctf/test-const-array.c: Likewise.
	* tests/data/test-read-ctf/test-const-array.o: Likewise.
	* tests/Makefile.am: Add the new test material to source
	distribution.

Signed-off-by: Guillermo E. Martinez <guillermo.e.martinez@oracle.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
2022-11-30 10:22:45 +01:00