Clang-tidy flags those name inconsistencies and they are trivial to fix,
hence just do it. No functional change.
* src/abg-comparison-priv.h
(corpus_diff::priv::count_unreachable_types): use consistent
parameter naming.
* tools/abidiff.cc(main): Likewise.
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
There was an inconsistency in the way the diff context was used for
different file types. This change eliminates this and so .bi files now
have all the command line options applied to their diffs.
* tests/data/Makefile.am: Add test case files.
* tests/data/test-abidiff-exit/test-loc-*: New test cases.
* tests/test-abidiff-exit.cc (in_out_specs): Add new test cases.
* tools/abidiff.cc (main): Use populated ctxt for translation unit
diff.
Signed-off-by: Giuliano Procida <gprocida@google.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This patch adds the Catch [1] unit test framework in version v1.12.2 [2]
along with its integration into the existing build and test definition.
While there is version v2 available, v1 still supports C++98, hence we
can make use of it. The framework is distributed as a single header
file. And since it is less then 500k and it comes with a permissive
license, I decided to directly add the file rather than requiring
users/developers/distributors to satisfy the new dependency.
The integration is fairly simple: A new library libcatch.a provides the
`main` for the tests that run with Catch. The tests themselves require
to include the header as well and to link against said library.
As an example I migrated the test-kmi-whitelist test to Catch. The test
becomes a bit more structured and error reporting significantly
improved. E.g. see this intentional breakage:
| --- a/tests/test-kmi-whitelist.cc
| +++ b/tests/test-kmi-whitelist.cc
| @@ -140,5 +140,5 @@ TEST_CASE("WhitelistWithTwoSections", "[whitelists]")
| suppressions_type suppr
| = gen_suppr_spec_from_kernel_abi_whitelists(abi_whitelist_paths);
| REQUIRE(!suppr.empty());
| - test_suppressions_are_consistent(suppr, "^test_symbol1$|^test_symbol2$");
| + test_suppressions_are_consistent(suppr, "^test_symbol$|^test_symbol2$");
It leads to this test output:
| ---------------------------------------------------------------------------
| WhitelistWithTwoSections
| ---------------------------------------------------------------------------
| ../../tests/test-kmi-whitelist.cc:136
| ...........................................................................
|
| ../../tests/test-kmi-whitelist.cc:81: FAILED:
| REQUIRE( left->get_symbol_name_not_regex_str() == expr )
| with expansion:
| "^test_symbol1$|^test_symbol2$"
| ==
| "^test_symbol$|^test_symbol2$"
|
| ===========================================================================
| test cases: 6 | 5 passed | 1 failed
| assertions: 41 | 40 passed | 1 failed
[1] https://github.com/catchorg/Catch2
[2] https://github.com/catchorg/Catch2/releases/tag/v1.12.2
* tests/.gitignore: Add entry for .dirstamp
* tests/Makefile.am: Add libcatch test library and use it for
runtestkmiwhitelist.
* tests/lib/catch.cc: New test driver implementation.
* tests/lib/catch.hpp: Add Catch v1.12.2 header only test library.
* tests/test-kmi-whitelist.cc: Migrate to use Catch test framework.
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
This declaration has already been done some lines above. Drop the
duplicate.
* include/abg-fwd.h: drop superfluous forward declaration.
Signed-off-by: Matthias Maennich <maennich@google.com>
Fix the include guards of abg-dwarf-reader.h and abg-reporter-priv.h by
moving them before any other includes where they actually belongs.
Add missing include guards for abg-libxml-utils.h and abg-libzip-utils.h.
* include/abg-dwarf-reader.h: Move include guard to the beginning.
* include/abg-reporter-priv.h: Likewise.
* include/abg-libxml-utils.h: Add include guard.
* include/abg-libzip-utils.h: Likewise.
Signed-off-by: Matthias Maennich <maennich@google.com>
A broken elf file might not have a valid symtab. As of now we would hit
an ABG_ASSERT and crash. Let's catch that case and bail out instead.
* src/abg-dwarf-reader.cc (load_symbol_maps_from_symtab_section):
Handle elf file with missing symtab.
* tests/test-read-dwarf.cc (InOutSpec): add test case.
* tests/data/test-read-dwarf/test26-bogus-binary.elf: new test data.
Signed-off-by: Matthias Maennich <maennich@google.com>
A broken elf file with a sh_entsize of 0 makes the dwarf reader crash
due to a division by zero. Fix this by validating the input and exiting
early in that case.
* src/abg-dwarf-reader.cc (load_symbol_maps_from_symtab_section):
Handle elf file with invalid sh_entsize.
* tests/test-read-dwarf.cc (test_task::perform): handle empty
in_abi_path and out_abi_path as 'read only' test.
(InOutSpec): add test case.
* tests/data/test-read-dwarf/test25-bogus-binary.elf: new test data.
Signed-off-by: Matthias Maennich <maennich@google.com>
The project style requires assignment operators to be on the first line
of two if the line needs to break. Reflect that in the .clang-format
configuration to approximate the style better when using clang-format.
* .clang-format: Add BreakBeforeBinaryOperators option.
Signed-off-by: Matthias Maennich <maennich@google.com>
The previous commit introduces a new (tested) way of creating function
and variable suppressions from multiple whitelist definitions. Migrate
to this new way of processing KMI whitelists.
* include/abg-tools-utils.h
(gen_suppr_spec_from_kernel_abi_whitelist): Delete declaration.
* src/abg-tools-utils.cc
(gen_suppr_spec_from_kernel_abi_whitelist): Delete definition
and migrate users to gen_suppr_spec_from_kernel_abi_whitelists.
* tools/abidiff.cc (set_suppressions): Migrate from using
gen_suppr_spec_from_kernel_abi_whitelist to
gen_suppr_spec_from_kernel_abi_whitelists.
* tools/abidw.cc (set_suppressions): Likewise.
* tools/abipkgdiff.cc: Drop unused using definition.
* tools/kmidiff.cc: Likewise.
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
If multiple KMI whitelists are specified, either by passing
--kmi-whitelist several times or by having multiple whitelist sections
in the whitelist files, the generated suppressions are created as an
intersection of symbols. That is rather unusual, as whitelisting should
rather work additive. That means that the symbols (or expressions
thereof) defined across several sections or files shall be considered a
union of symbols. This patch combines the whitelist parsing to create
exactly one function_suppression and one variable suppression. A test
case has been added to ensure the functionality is working.
Please note, migrating the existing code to this new functionality is
done in a separate commit.
* include/abg-tools-utils.h
(gen_suppr_spec_from_kernel_abi_whitelists): New function.
* src/abg-tools-utils.cc
(gen_suppr_spec_from_kernel_abi_whitelists): Likewise.
* tests/.gitignore: Ignore new test executable.
* tests/Makefile.am: Add new test executable.
* tests/data/test-kmi-whitelist/whitelist-with-another-single-entry:
New test input file.
* tests/data/test-kmi-whitelist/whitelist-with-duplicate-entry:
Likewise.
* tests/data/test-kmi-whitelist/whitelist-with-single-entry:
Likewise.
* tests/data/test-kmi-whitelist/whitelist-with-two-sections:
Likewise.
* tests/data/Makefile.am: Add above test material.
* tests/test-kmi-whitelist.cc: Add new test executable.
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
A corpus that has no symbols contributing to the ABI surface (e.g.
because of an exhaustive suppression), will not contribute in a later
comparison via abidiff and friends. Hence, there is no need for such
entries to appear in the ABI xml representation. This patch completely
suppresses empty corpora.
* src/abg-writer.cc (write_corpus): completely skip empty
corpora rather than creating an empty entry for them.
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
A corpus with completely filtered out symbols (exhaustive whitelist),
still contains compilation units, but they are empty. A list of empty
translation units shall be considered empty as no entries need to be
considered. That is useful to skip empty corpora when writing out the
xml for them.
Hence, teach is_empty() to have a look at the actual translation units.
* src/abg-corpus.cc (corpus::is_empty): consider a list of
empty members to be empty.
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
An abi-corpus might be part of the representation, but might (due to
filters like whitelisting) not contain actual symbols to be considered.
In that case, `abidw` produces an empty abi-corpus node.
Valid ways of representing this in XML are
- <abi-corpus path='vmlinux' architecture='elf-arm-aarch64'/>
- <abi-corpus path='vmlinux' architecture='elf-arm-aarch64'></abi-corpus>
- <abi-corpus path='vmlinux' architecture='elf-arm-aarch64'>
</abi-corpus>
abg-reader could currently only handle the last format and crashed upon
processing the first two ones. The crash happened due to the XMLNode
having no children, but that was assumed. The last case succeeded so
far as this form actually contains a text node (with the newline
character) as a child.
Fix this by handling the case of a node not having children by exiting
early with an empty node.
* src/abg-reader.cc (read_corpus_from_input): when assigning a
corpus node, assure the node actually has children.
* tests/test-abidiff.cc (main): Add test for variants of empty
xml nodes to the test harness.
* tests/data/test-abidiff/test-empty-corpus-0.xml: Test input
containing an empty xml node that closes immediately.
* tests/data/test-abidiff/test-empty-corpus-0.xml: Test input
containing an empty xml node that closes immediately with a tag.
* tests/data/test-abidiff/test-empty-corpus-0.xml: Test input
containing an empty xml node that closes with a tag on a new line.
* tests/data/test-abidiff/test-empty-corpus-report.txt:
Expected test output (empty abidiff) for diffing xml with itself.
* tests/data/Makefile.am: Add the new test input material above
to source distribution.
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
In the abixml format, when reading the value of the
'layout-offset-in-bits' attribute of the data-member child element of
a class-decl element, we wrongly use atoi. The reason why atoi is
wrong is that it can only read an 'int' but layout-offset-in-bits can
be a 64 bits unsigned value which comes fromt the DWARF
DW_AT_bit_offset attribute.
We are thus using stroull instead, in this patch.
* src/abg-reader.cc (read_offset_in_bits): Fix comment. Use
stroull rather than atoi.
* tests/data/test-diff-dwarf-abixml/PR25409-librte_bus_dpaa.so.20.0:
Add new binary test input.
* tests/data/test-diff-dwarf-abixml/PR25409-librte_bus_dpaa.so.20.0-report-0.txt:
Add new reference output.
* tests/data/test-diff-dwarf-abixml/PR25409-librte_bus_dpaa.so.20.0.abi:
Add new abixml representation for the binary test input above.
* tests/data/Makefile.am: Add the new test material above to
source distribution.
* tests/test-diff-dwarf-abixml.cc (in_out_specs): Add the test
input above to the test harness.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
kmidiff and abidiff do filter out added symbols (vars, functions and
symbols without debug info) by default when dealing with kernel
binaries. The reason for this is that the ABI could be considered
compatible and not broken when adding symbols. In practice, this is
confusing as there is no possibility for a symmetric comparison (i.e. a
deleted function when comparing left to right is an added function when
comparing right to left). Furthermore, there is no option available to
actually report these added symbols. I thought of adding an option to
report added symbols, but in the end came to the conclusion that we
should behave consistent across the various ways you can diff an ABI
with abidiff and kmidiff and should not change default behaviour for a
particular type of binary. Hence, remove the default behaviour of
filtering out added symbols when comparing kernel binaries. To restore
the current behaviour, the user needs to parametrize with the tools with
--no-added-syms --no-unreferenced-symbols.
Adjusted test cases accordingly and add a new test that covers the old
behaviour new available with additional flags to abidiff.
* tools/abidiff.cc (adjust_diff_context_for_kmidiff): Drop
default suppression of added symbols.
* tools/kmidiff.cc (set_diff_context): Likewise.
* tests/data/test-diff-suppr/test46-PR25128-report-1.txt: Adjust
test expectation.
* tests/data/test-diff-suppr/test46-PR25128-report-2.txt: Add
test case for abidiff with flag --no-added-syms.
* tests/data/Makefile.am: add new testcase.
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
Allow appending arbitrary text to the libabigail version string
representation. That is useful to identify custom versions of the
library (e.g. development versions or versions of a particular origin).
The feature can be enabled by passing VERSION_SUFFIX to `configure`,
e.g.
$ configure VERSION_SUFFIX="-dev"
That will extend the version string to (currently) 1.7.0-dev.
The behaviour before this patch remains the default behaviour of not
appending any additional text.
The feature stays intentionally undocumented as the main release of
libabigail will usually not carry a version suffix.
* configure.ac: add substitution for VERSION_SUFFIX
* include/abg-version.h.in: add define for ABIGAIL_VERSION_SUFFIX
* include/abg-config.h(abigail_get_library_version): add support
for a version suffix
* src/abg-config.cc(abigail_get_library_version): Likewise.
* src/abg-tools-utils.cc(get_library_version_string): Likewise.
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
Commit 43679a6103 ("dwarf-reader: refactor
try_reading_first_ksymtab_entry_using{pre,}_v4_19_format") introduced an
assertion to ensure the absence of ksymtab relocation sections as they
are an unhandled case for try_reading_first_ksymtab_entry. This
assertion turns out to be too strict as relocation sections might be
present (e.g. on x86_64), but not affecting the functionality of this
function (i.e. helping to detect the ksymtab format). Hence, remove the
assertion and document that case.
* src/abg-dwarf-reader.cc (try_reading_first_ksymtab_entry):
remove assertion and update documentation
Fixes: 43679a6103 ("dwarf-reader: refactor try_reading_first_ksymtab_entry_using{pre,}_v4_19_format")
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
Looking up relocation sections by name introduces a dependency to the
linker in use. Relocation sections might be named differently. For
instance, linking kernel modules with the bfd linker leads to a
.rela__ksymtab section corresponding to the __ksymtab section. Using lld
as a linker leads to .rela___ksymtab as section name. Both are valid.
When the kernel loads these, it simply applies all relocations from all
sections it finds. Tools should not depend on the concrete name (even
though I would prefer consistency among them). Libabigail hit an
assertion when trying to extract the ABI from a kernel module linked
with lld.
Hence, resolve the relocation sections for __ksymtab and __ksymtab_gpl
by iterating over the ELF sections, searching for relocation sections
and identifying the one that points to the respective ksymtab.
* src/abg-dwarf-reader.cc (find_relocation_section): New function.
(find_ksymtab_reloc_section): Use find_relocation_section to
resolve the ksymtab's relocation section.
(find_ksymtab_gpl_reloc_section): Likewise.
Fixes: e6870326e0 ("Support pre and post v4.19 ksymtabs for Linux kernel modules")
Cc: Jessica Yu <jeyu@kernel.org>
Cc: Android Kernel Team <kernel-team@android.com>
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
This patch adds the ability to compare all types of a binary,
including those types that are not reachable from global functions and
variables.
This implies that for types that are not reachable from public
interfaces, we want compare them against each others directly, without
first comparing global functions/variables and walking the graph of
reachable types from there.
The patch adds the --non-reachable-types option to abidiff and
abipkgdiff, instructing them to also compare types that are
non-reachable from global variables and functions.
Using that option, for instance, here is what the summary of
abipkgdiff now looks like, in the test case attached added by this
patch:
================ changes of 'libflatpak.so.0.10204.0'===============
Functions changes summary: 0 Removed, 0 Changed (16 filtered out), 16 Added functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
Unreachable types summary: 3 removed (2 filtered out), 1 changed (15 filtered out), 3 added (1 filtered out) types
You can see that there is a new summary line which starts with the
string: "Unreachable types summary:"
Then in the body of the report, those unreachable types are reported
separately.
In practise, we want to limit the unreachable types to compare
somehow, otherwise we'll end up comparing all the types of the types
of the binary and that can be huge. So we want to limit the
unreachable type analysis to types that are defined in public headers.
So, for abipkgdiff, one can limit the analysis of non-reachable types
to those defined in public headers by supplying the --devel{1,2}
options that specifies the development packages that contain said
public headers. For abidiff however, you'll want to use the
--headers-dir{1,2} options for that.
The patch comes with appropriate regression tests.
* include/abg-comparison.h (string_type_base_sptr_map): Define new
typedef.
(diff_context::show_unreachable_types): Declare new member
functions.
(corpus_diff::{deleted_unreachable_types,
deleted_unreachable_types_sorted, added_unreachable_types,
added_unreachable_types_sorted, changed_unreachable_types,
changed_unreachable_types_sorted}): Likewise.
(maybe_report_unreachable_type_changes): Declare this function a
friend of class corpus_diff.
(corpus_diff::diff_stats::{num_added_unreachable_types,
num_added_unreachable_types_filtered_out,
net_num_added_unreachable_types, num_removed_unreachable_types,
num_removed_unreachable_types_filtered_out,
net_num_removed_unreachable_types, num_changed_unreachable_types,
num_changed_unreachable_types_filtered_out,
net_num_changed_unreachable_types}): Likewise.
* src/abg-comparison-priv.h
(diff_context::priv::show_unreachable_types_): Define new data
member.
(diff_context::priv::priv): Initialize the new data member.
(diff_comp::operator()): Use pretty representation of diff
subjects to sort them, rather than just their name. Also, add
comment to the other member functions of diff_comp.
(corpus_diff::{unreachable_types_edit_script_,
deleted_unreachable_types_, deleted_unreachable_types_sorted_,
suppressed_deleted_unreachable_types_, added_unreachable_types_,
added_unreachable_types_sorted_,
suppressed_added_unreachable_types_, changed_unreachable_types_,
changed_unreachable_types_sorted_}): Define new data members.
(corpus_diff::priv::apply_supprs_to_added_removed_fns_vars_unreachable_types):
Changed the name of
corpus_diff::priv::apply_suppressions_to_added_removed_fns_vars into
this.
(corpus_diff::priv::{added_unreachable_type_is_suppressed,
deleted_unreachable_type_is_suppressed,
changed_unreachable_types_sorted, count_unreachable_types}):
Declare new member functions.
(corpus_diff::diff_stats::priv::{num_added_unreachable_types,
num_added_unreachable_types_filtered_out,
num_removed_unreachable_types,
num_removed_unreachable_types_filtered_out,
num_changed_unreachable_types,
num_changed_unreachable_types_filtered_out}): Define new data
members.
(sort_string_type_base_sptr_map): Declare new function.
* src/abg-comparison.cc (sort_string_type_base_sptr_map)
(diff_context::show_unreachable_types): Define new functions.
(corpus_diff::diff_stats::{num_added_unreachable_types,
num_added_unreachable_types_filtered_out,
net_num_added_unreachable_types,
net_num_removed_unreachable_types,
num_removed_unreachable_types_filtered_out,
num_removed_unreachable_types}): Define new member functions.
(diff_maps::insert_diff_node): Do not update the map "diff ->
impacted interfaces" if the current impacted interface is nil.
This happens if we are looking at a diff node for a change on a
type that is not reachable from any interfaces.
(corpus_diff::priv::ensure_lookup_tables_populated): Handle the
edit script for unreachable types.
(corpus_diff::priv::apply_supprs_to_added_removed_fns_vars_unreachable_types):
Rename
corpus_diff::priv::apply_suppressions_to_added_removed_fns_vars
into this. Apply suppression specifications to added and removed
unreachable types as well.
(corpus_diff::priv::{added,deleted}_unreachable_type_is_suppressed):
Define new member functions.
(corpus_diff::priv::{count_unreachable_types,
changed_unreachable_types_sorted}): Likewise.
(corpus_diff::priv::apply_filters_and_compute_diff_stats): Update
statistics (including walking changed unreachable types to apply
categorization and redundancy filters to them) related to
unreachable types.
(corpus_diff::priv::emit_diff_stats): Emit diff stats related to
unreachable types.
(corpus_diff::priv::maybe_dump_diff_tree): Dump diff tree nodes
related to unreachable types.
(corpus_diff::{deleted_unreachable_types,
deleted_unreachable_types_sorted, added_unreachable_types,
added_unreachable_types_sorted, changed_unreachable_types,
changed_unreachable_types_sorted): Define new member functions.
(corpus_diff::has_changes): Take deleted/added/changed unreachable
types into account.
(corpus_diff::has_incompatible_changes): Take net removed/changed
unreachable types into account.
(corpus_diff::has_net_subtype_changes): Take net removed and
changed unreachable types into account.
(corpus_diff::has_net_changes): Take net removed/added/changed
unreachable types into account.
(corpus_diff::traverse): When traversing the components of a
corpus_diff node, make sure to traverse the changed unreachable
types of the corpus.
(leaf_diff_node_marker_visitor::visit_begin): Arrange for the fact
that the current topmost interface can be nil if we are looking at
types not reachable from global functions/variables. Also, make
sure that only leaf nodes that are reachable from a global
function/variable are recorded as leaf nodes.
(compute_diff): In the overload for corpus_sptr, compute the
changes between types not reachable from global functions and
variables, if the user wishes that we do so. Also, add more
comments.
(apply_suppressions): Update for the name change of the function
apply_suppressions_to_added_removed_fns_vars to
apply_supprs_to_added_removed_fns_vars_unreachable_types.
* include/abg-corpus.h
(corpus::{record_type_as_reachable_from_public_interfaces,
type_is_reachable_from_public_interfaces,
get_types_not_reachable_from_public_interfaces}): Declare new
member functions.
(corpus::recording_types_reachable_from_public_interface_supported):
Declare new virtual member function.
(corpus_group::get_public_types_pretty_representations): Declare
new member functons.
(corpus_group::recording_types_reachable_from_public_interface_supported):
Declare new virtual member function.
* src/abg-corpus-priv.h
(corpus::priv::{types_not_reachable_from_pub_ifaces_,
pub_type_pretty_reprs_}): Define new data members.
(corpus::priv::priv): Initialize the pub_type_pretty_reprs_ data
member because it's a pointer.
(corpus::priv::get_public_types_pretty_representations): Declare
new member function.
(corpus::priv::~priv): Declare a destructor.
* src/abg-corpus.cc
(corpus::priv::get_public_types_pretty_representations): Define
new member function.
(corpus::priv::~priv): Define new destructor to delete the new
pub_type_pretty_reprs_ member pointer.
(corpus::{record_type_as_reachable_from_public_interfaces,
type_is_reachable_from_public_interfaces,
get_types_not_reachable_from_public_interfaces,
recording_types_reachable_from_public_interface_supported}):
Define new member functions
(corpus_group::get_public_types_pretty_representations): Likewise.
* include/abg-diff-utils.h (struct deep_ptr_eq_functor): Document
the equality operator. Also, add an overload to the equality
operator, for weak_ptr<T>. The existing equality operator
overload was just for shared_ptr<T>.
* include/abg-fwd.h (is_user_defined_type): Declare function.
* include/abg-ir.h (operator!=(const decl_base_sptr&, const
decl_base_sptr&)): Declare new operator.
(type_maps::get_types_sorted_by_name): Declare
new member function.
(decl_base::{g,s}et_is_artificial): Declare new member function.
(function_decl::parameter::{g,s}et_artificial): Remove these
member functions.
* src/abg-ir.cc (operator!=(const decl_base_sptr&, const
decl_base_sptr&)): Define new operator.
(decl_base::priv::is_artificial_): Define new data
member.
(type_maps::priv::sorted_types_): Define new data member.
(struct type_name_comp): Define new comparison functor to sort
types based on their pretty representations.
(decl_base::priv::priv): Initialize it.
(decl_base::{g,s}et_is_artificial): Define new member functions.
(type_maps::get_types_sorted_by_name): Define new member function.
(is_user_defined_type): Define new function overloads.
(strip_typedef, function_type::{function_type, set_parameters}):
Adjust using decl_base::get_is_artificial rather than
function_decl::parameter::get_artificial.
(function_decl::parameter::priv::artificial_): Remove this data
member.
(function_decl::parameter::priv::priv): Adjust to the removal of
function_decl::parameter::priv::artificial_. This constructor
does not take an "is_artificial" flag anymore.
(function_decl::parameter::parameter): Adjust to the removal of
the is_artificial flag from the arguments of the constructor of
function_decl::parameter::parameter::priv.
(function_decl::parameter::get_artificial): Remove this member
function.
* src/abg-reporter-priv.h (maybe_report_unreachable_type_changes):
Declare new function.
* src/abg-reporter-priv.cc
(maybe_report_unreachable_type_changes): Define new function.
* src/abg-default-reporter.cc (default_reporter::report): In the
overload for corpus_diff&, report added/removed/changed types that
are not reachable from global functions and variables using the
new function maybe_report_unreachable_type_changes.
* src/abg-leaf-reporter.cc (leaf_reporter::report): In the
overload for corpus_diff, report changes to types unreachable from
global functions or variables, using the new function
maybe_report_unreachable_type_changes.
* src/abg-dwarf-reader.cc (build_ir_node_from_die): When the user
requests that all types be loaded, record relevant types as
reachable from global functions and variables.
(build_enum_type, add_or_update_class_type)
(add_or_update_union_type): Read the 'is-artificial' DWARF
attribute and set the corresponding decl_base property
accordingly.
(finish_member_function_reading, strip_typedef)
(function_type::function_type): Adjust using
decl_base::get_is_artificial, rather than
function_decl::parameter::get_artificial.
* include/abg-reader.h
(consider_types_not_reachable_from_public_interfaces): Declare new
function.
* src/abg-reader.cc
(read_context::m_tracking_non_reachable_types): Add new data
member.
(read_context::read_context): Initialize it.
(read_context::tracking_non_reachable_types): Define accessors for
the new data member above.
(read_is_declaration_only): Re-indent.
(read_is_artificial): Define new helper function.
(build_function_parameter): Use the new read_is_artificial
function here, rather than open-coding it.
(build_enum_type_decl, build_class_decl, build_union_decl):
Support reading the 'is-artificial' property by using the new
read_is_artificial function.
(read_corpus_from_input): If the user wants us to take
non-reachable types into account, then make sure we do so.
(read_tracking_non_reachable_types, read_is_non_reachable_type):
Define new static functions.
(handle_element_node, build_type): Read the "is-non-reachable"
attribute on type element nodes if the user wants us to track
non-reachable types.
(consider_types_not_reachable_from_public_interfaces): Define new
function.
* src/abg-writer.cc (write_is_artificial): Define new static
helper function.
(annotate): Adjust using decl_base::get_is_artificial rather than
function_decl::parameter::get_artificial.
(write_enum_type_decl, write_class_decl_opening_tag)
(write_union_decl_opening_tag): Support writing the
"is-artificial" property, using the new write_is_artificial
function.
(write_function_type): Adjust this to use the new
write_is_artificial rather than open-coding writing the
'is-artificial' attribute.
(write_is_non_reachable)
(write_tracking_non_reachable_types): Define new static functions.
(write_enum_type_decl, write_class_decl_opening_tag)
(write_union_decl_opening_tag): Write the 'is-no-reachable'
attribute when applicable.
(write_corpus, write_corpus_group): Write the
'tracking-non-reachable-types' attribute when applicable.
* tools/abidiff.cc (options::options): Initialize ...
(options::show_all_types): ... new data member.
(display_usage): Add help string from the new
--non-reachable-types option.
(parse_command_line): Parse the new --non-reachable-types option.
(set_diff_context_from_opts): Set the
dwarf_reader::read_context::show_unreachable_types property.
(set_native_xml_reader_options): Define new
static function.
(main): Load all types when analyzing the DWARF or the ABIXML
files, if the user wants us to do so.
* tools/abipkgdiff.cc (options::show_all_types): Define new data
member.
(options::options): Initialize it.
(parse_command_line): Parse the --non-reachable-types option to
set the options::show_all_types data member.
(display_usage): Add a help string for the new
--non-reachable-types option.
(set_diff_context_from_opts): Set the
dwarf_reader::read_context::show_unreachable_types property based
on the options::show_all_type data member.
(compare): Configure the read context to load all types while
analyzing the DWARF info, depending on the options::show_all_type
data member.
* doc/manuals/abidiff.rst: Document the new --non-reachable-types
option added to abidiff above.
* doc/manuals/abipkgdiff.rst: Add documentation for the
--non-reachable-types option.
* tests/data/test-diff-suppr/test47-non-reachable-types-v{0,1}.c:
Source code files of test binary input.
* tests/data/test-diff-suppr/test47-non-reachable-types-suppr-{1,2,3,4,5}.txt:
New test input files.
* tests/data/test-diff-suppr/test47-non-reachable-types-report-{1,2,3,4,5,6,7,8,9,10}.txt:
New test reference output files.
* tests/data/test-diff-suppr/test47-non-reachable-types-v{0,1}.o.alltypes.abixml:
New test input abixml.
* tests/data/Makefile.am: Add the new test material to source
distribution.
* tests/test-diff-suppr.cc (in_out_specs): Add the new tests above
to this test harness.
* tests/data/test-abidiff/test-struct1-report.txt: Adjust.
* tests/data/test-diff-pkg/PR24690/flatpak-debuginfo-1.2.4-3.fc30.x86_64.rpm:
New input binary RPM.
* tests/data/test-diff-pkg/PR24690/flatpak-debuginfo-1.4.0-1.fc30.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/PR24690/flatpak-devel-1.2.4-3.fc30.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/PR24690/flatpak-devel-1.4.0-1.fc30.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/PR24690/flatpak-libs-1.2.4-3.fc30.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/PR24690/flatpak-libs-1.4.0-1.fc30.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/PR24690/flatpak-libs-debuginfo-1.2.4-3.fc30.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/PR24690/flatpak-libs-debuginfo-1.4.0-1.fc30.x86_64.rpm:
Likewise.
* tests/data/test-diff-pkg/PR24690/PR24690-report-0.txt: New test
reference output.
* tests/data/Makefile.am: Add the new test material above to
source distribution.
* tests/test-diff-pkg.cc (in_out_specs): Add the new test material
above to this test harness.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Break a line longer than 80 characters.
* src/abg-default-reporter.cc (default_reporter::report): In the
overload for corpus_diff, break a line longer than 80 characters.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Kernel v5.4 introduces Symbol Namespaces [1]. That changes the layout of
ksymtab entries in Kernel binaries. In particular, the kernel_symbol
entry gains a new member to represent the namespace. That change affects
binaries that have position relative relocations (we name that format
here V4_19_KSYMTAB_FORMAT) as well as those that don't
(PRE_V4_19_KSYMTAB_FORMAT). In any case there is an additional entry
that has the same size as the previous entries.
Since we iterate over the ksymtab entries to collect them, we need to
determine the correct size of these entries even though we do not
grab the namespace for ABI analysis purposes at this time.
In order to determine the size, we attempt to find the beginning of the
next entry by trying to read symbols with an increasing offset. Once we
succeed, we have the offset and therefore the size of one entry.
Since try_reading_first_ksymtab_entry() does already everything we need
to attempt to read a symbol from a beginning of a ksymtab, we only
needed to teach it to operate on an offset to read the potential second
entry.
'load_kernel_symbol_table' was determining the number of entries
unconditionally, even when we do have the unsupported case of a ksymtab
with relocations. Hence only load when needed.
* src/abg-dwarf-reader.cc
(read_context::try_reading_first_ksymtab_entry): Add
symbol_offset parameter.
(read_context::get_ksymtab_entry_size): Add support for variable
size ksymtab entries due to symbol namespaces.
(load_kernel_symbol_table): only load nb_entries when needed
[1] https://lore.kernel.org/lkml/20190906103235.197072-1-maennich@google.com/
Signed-off-by: Matthias Maennich <maennich@google.com>
Avoid code duplication and increase maintainebility of these helper
functions. As their only difference was the application of position
relative relocations, consolidate them and add a flag for exactly this
feature.
This is purely stylistic and not changing functionality.
* src/abg-dwarf-reader.cc(try_reading_first_ksymtab_entry):
New function to consolidate functionality for
try_reading_first_ksymtab_entry_using_{pre,}v4_19_format functions.
(try_reading_first_ksymtab_entry_using_v4_19_format,
try_reading_first_ksymtab_entry_using_pre_v4_19_format):
refactor to use try_reading_first_ksymtab_entry
Signed-off-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Because DWARF sometimes emit decl-only classes (real one, with no
members) with a size property, and the rest of the time, would emit
the same decl-only class without a size property, comparing the two
might yield some false positives.
This patch handles those beasts when comparing classes.
* include/abg-comp-filter.h (is_decl_only_class_with_size_change):
Declare an overload.
* include/abg-fwd.h (look_through_decl_only_class): Declare an
overload.
* src/abg-comp-filter.cc (is_decl_only_class_with_size_change):
Define an overload that takes class_or_union& type. Re-write the
previous overload in terms of this new one.
* src/abg-ir.cc (look_through_decl_only_class): Define a new
overload that takes a class_or_union&. Rewrite the previous
overload in terms of this one.
(equals): In the overload for class_or_union&, use
is_decl_only_class_with_size_change to detect cases of decl-only
classes that differ only by their size attribute and avoid
comparing them.
* tests/data/test-annotate/test21-pr19092.so.abi: Adjust.
* tests/data/test-read-dwarf/test21-pr19092.so.abi: Likewise.
* tests/data/test-diff-filter/test41-report-0.txt: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
The leaf_diff_node_marker_visitor pass which collects leaf diff nodes
for the leaf diff reporter considers bogus decl-only classes (that have the
is-declaration-only flag set, are empty, and yet have a non-nil size
property) originated from bogus DWARF.
The leaf reporter thus potentially reports size changes among
decl-only classes, which does not make sense. Two decl-only classes
of the same name should always be considered equal, in this context.
This patch thus teaches the leaf_diff_node_marker_visitor to avoid
collecting a leaf diff node that is about a size change on a true
decl-only class.
* include/abg-comp-filter.h (is_decl_only_class_with_size_change):
Declare new function.
* src/abg-comp-filter.cc (is_decl_only_class_with_size_change):
Define new function.
* src/abg-comparison.cc
(leaf_diff_node_marker_visitor::visit_begin): Use the newly
defined is_decl_only_class_with_size_change above to ignore bogus
decl-only classes with a size change.
* tests/data/test-diff-suppr/test45-abi-report-1.txt: New test input.
* tests/data/test-diff-suppr/test45-abi-wl.xml: Likewise.
* tests/data/test-diff-suppr/test45-abi.xml: Likewise.
* tests/data/test-diff-suppr/test45-abi.suppr.txt: New reference
output for the test input above.
* tests/data/test-diff-suppr/test46-PR25128-base.xml: New test input.
* tests/data/test-diff-suppr/test46-PR25128-new.xml: Likewise.
* tests/data/test-diff-suppr/test46-PR25128-report-1.txt: New
reference input for the test input above.
* tests/data/Makefile.am: Add the new test material to source distribution.
* tests/test-diff-suppr.cc (in_out_spec): Add the new test input
above to this test harness.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Right now, the symbol names that are part of a Linux Kernel ABI
white list are matched against function and variable names that appear
in the DWARF information.
In other words, when Libabigail processes the Linux Kernel ABI
whitelist, it generates a suppression specifications which keeps
functions and variables (as described by DWARF) whose names match the
symbol names specified in the white list. All other functions and
variables are dropped. But that doesn't apply to ELF symbols.
Libabigail generates no suppression at all for ELF symbols. It only
considers variables and functions described in the debug information.
With this patch, Libabiagil now generates a suppression specification
which keeps functions and variables whose ELF symbol name match the
symbol names specified in the whitelist. The suppression
specification also drops ELF symbols whose name don't match the names
specified in the white list.
Note that this patch uses the previous commit which description is:
"Support symbol_name_not_regexp in [suppress_{function, variable}]"
* src/abg-tools-utils.cc (gen_suppr_spec_from_kernel_abi_whitelist):
Generate a suppression specification which considers the name of
the symbol associated to a function/variable, rather than just the
name of said function/variable.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
In the suppress_function and suppress_variable directives of the
suppression specification language, we lack the
'symbol_name_not_regexp' properties, that would allow users to specify
which (function/variable) symbols to *keep* as opposed to specifying
which symbols to suppress.
This patch adds that feature. That will later allow us to make the
linux kernel symbol white lists[1] functionality use this feature;
that is, upon analysing the content of a kernel symbol whitelist which
lists a symbol named "foo", Libabigail would automatically generate a
suppression specification which contains, e.g a 'suppress_function"
directive that has this new 'symbol_name_not_regexp' property which
value is set to "foo".
Note that the patch makes sure that feature is supported when
analyzing both abixml and DWARF formats.
[1]: You can learn about what a Linux Kernel symbols white list is by
reading about it at
https://sourceware.org/libabigail/manual/kmidiff.html#environment.
* doc/manuals/libabigail-concepts.rst: Document the new
symbol_name_not_regexp properties for the
suppress_{function,variable} directives.
* include/abg-suppression.h
({function,variable}_suppression::{g,s}et_symbol_name_not_regex_str):
Declare new member functions.
* src/abg-dwarf-reader.cc
(read_context::is_elf_symbol_suppressed): Define new member functions.
(read_context::{load_symbol_maps_from_symtab_section,
populate_symbol_map_from_ksymtab,
populate_symbol_map_from_ksymtab_reloc}): Drop suppressed symbols
when reading symbol tables.
({function,variable}_is_suppressed): Consider that in C, the
linkage name is _by default_ the same as the function/variable
name. Remove local variable.
* include/abg-ir.h (elf_symbol_is_{function,variable}): Add ...
* src/abg-ir.cc (elf_symbol_is_{function,variable}): ... new
functions.
* src/abg-reader.cc (build_elf_symbol): Take an additional boolean
to detect and drop suppressed symbols.
(build_elf_symbol_db): Adjust the call to build_elf_symbol to make
it detect and drop suppressed symbols.
(read_corpus_from_input): Be mindful that the set of symbols for a
given corpus can be empty because of suppression specifications.
* src/abg-suppression-priv.h
({function,variable}_suppression::priv::symbol_name_not_regex[_str_]):
Add new data members.
(function,variable}_suppression::priv::get_symbol_name_not_regex):
Add new member functions.
({function,variable}_is_suppressed): Guard against empty name.
(is_elf_symbol_suppressed): Define new function template.
* src/abg-suppression.cc
({function,variable}_suppression::{g,s}et_symbol_name_not_regex_str):
Define new member functions.
({function,variable}_suppression::suppresses_function)
(suppression_matches_{function,variable}_sym_name)
(read_{function,variable}_suppression): Support the new
"symbol_name_not_regex" property.
* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-1.txt:
New test reference report.
* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-report-2.txt:
Likewise.
* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v{0,1}.c:
Sources of the new test input.
* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v{0,1}.o:
New test input binaries.
* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp-v{0,1}.o.abi:
New test input abixml files.
* tests/data/test-diff-suppr/test44-suppr-sym-name-not-regexp.suppr.txt:
Next test suppression specification.
* tests/data/Makefile.am: Add the new test material above to
source distribution.
* tests/test-diff-suppr.cc (in_out_specs): Add the input tests
above to the test harness.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Add the missing line breaks.
* tools/kmidiff.c (display_usage): add missing line breaks to
help text
Signed-off-by: Matthias Maennich <maennich@google.com>
When loading the corpus from elf while specifying a whitelist, we might
be able to ignore the symbol table. In any case we have to load the elf
properties into the context, such as the binary's architecture.
Otherwise they are missing from the internal / xml representation.
Previously, elf properties were not loaded when a whitelist was
specified. Fix that.
* src/abg-dwarf-reader.cc (read_corpus_from_elf):
unconditionally load elf properties into context
Signed-off-by: Matthias Maennich <maennich@google.com>
In the previous commit 2f7248f, we were just taking the first address
referred to by the DW_AT_ranges attribute as being the address of the
symbol of the function we are looking at. But there can be cases
where this is not true, as explained at
https://sourceware.org/bugzilla/show_bug.cgi?id=25058#c7.
We really need to get the first address that represents an exported
and defined function symbol, which is pointed to by the DW_AT_ranges
attribute.
And this is what this patch does.
* src/abg-dwarf-reader.cc
(read_context::get_first_exported_fn_address_from_DW_AT_ranges):
Rename read_context::get_first_address_from_DW_AT_ranges into
this. Walk through the addresses referred to by the DW_AT_ranges
attribute until we find one that is for an exported function
symbol, rather than just picking the first address of the set.
(read_context::get_function_address): Adjust.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Usually, function DIEs (DW_TAG_subprogram) refer to the address of the
underlying ELF symbol by using the DW_AT_low_pc attribute. However,
there are cases where it does so by using the DW_AT_ranges attribute.
In those cases, the first address of the sequence defined in the value
of that attribute is the address of the ELF symbol.
The problem is that the DWARF reader of Libabigail fails to get the
address of the underlying ELF symbol when the DW_AT_low_pc attribute
is missing. Rather, it should then look at the value of the
DW_AT_ranges attribute instead.
This is what this patch does.
* src/abg-dwarf-reader.cc
(read_context::get_first_address_from_DW_AT_ranges): Define new
member function.
(read_context::get_function_address): Use the new
read_context::get_first_address_from_DW_AT_ranges here.
* tests/data/test-diff-dwarf/PR25058-liblttng-ctl-report-1.txt:
New reference test output.
* tests/data/test-diff-dwarf/PR25058-liblttng-ctl.so: New test
input binary.
* tests/data/test-diff-dwarf/PR25058-liblttng-ctl2.10.so: New test
input binary.
* tests/data/Makefile.am: Add the new test materials above to
source distribution.
* tests/test-diff-dwarf.cc (in_out_specs): Add the new input test
input binary files to this test harness.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
My patch "568dee1 PR25042 - Support string form DW_FORM_strx{1,4} from
DWARF 5" introduced a thinko in configure.ac. The thinko triggers a
regression test issue on old systems where we don't support
DW_FORM_strx from DWARF 5. Fixed thus.
* configure.ac: Fix thinko when setting the HAVE_DW_FORM_strx
macro.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* src/abg-dwarf-reader.cc (compare_dies_string_attribute_value):
Fix a typo in the comment of this function.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
* configure.ac: Detect the presence of the DW_FORM_strx{1,4}
enumerators.
* src/abg-dwarf-reader.cc (form_is_DW_FORM_strx): Define new
function.
(compare_dies_string_attribute_value): Use the new
form_is_DW_FORM_strx here.
* tests/data/Makefile.am: Add the new test input files below to
source distribution.
* tests/data/test-read-dwarf/PR25042-libgdbm-clang-dwarf5.so.6.0.0:
New binary test input file.
* tests/data/test-read-dwarf/PR25042-libgdbm-clang-dwarf5.so.6.0.0.abi:
Reference output of the new binary test input file.
* tests/test-read-dwarf.cc (in_out_specs): Add the input test
files above to the test harness, for platforms that support the
DW_FORM_strx form.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
When writting a suppression specification in which the user wants to
keep a family of types (whose names set is specified by a regular
expression) and suppress/drop all other types, one needs to write
something like:
[suppress_type]
name_regexp = (?!the-regexp-of-the-types-to-keep)
It would be nicer (like what is done for other properties that take
regular expressions as value in suppression specifications) to be able
to write:
[suppress_type]
name_not_regexp = the-regexp-of-types-to-keep
This patch does just that.
It augments the abigail::suppr::type_suppression type to make it carry
the new 'name_not_regex' property. It updates the suppression engine
to take the 'name_not_regex' property into account when interpreting
instances of abigail::suppr::type_suppression. The parser for type
suppression directives is updated to recognize the new name_not_regexp
property. The manual has been updated accordingly to describe the new
property. New regression tests have been added.
* doc/manuals/libabigail-concepts.rst: Update this to document the
new name_not_regexp property of the suppress_type directive.
* include/abg-suppression.h
(type_suppression::{g,s}et_type_name_not_regex_str): Declare new accessors.
* src/abg-suppression-priv.h
(type_suppression::priv::{type_name_not_regex_str_,
type_name_not_regex_}): Define new data members.
(type_suppression::priv::{get_type_name_not_regex,
set_type_name_not_regex, get_type_name_not_regex_str,
set_type_name_not_regex_str}): Define new member functions.
* src/abg-suppression.cc
(type_suppression::get_type_name_regex_str): Fix comments.
(type_suppression::{set_type_name_not_regex_str,
get_type_name_not_regex_str}): Define new data members.
(suppression_matches_type_name): Adapt to support the new
type_name_not_regex property.
(read_type_suppression): Support parsing the type_name_not_regexp
property.
* tests/data/test-diff-suppr/test42-negative-suppr-type-report-0.txt:
New test reference output.
* tests/data/test-diff-suppr/test42-negative-suppr-type-report-1.txt: Likewise.
* tests/data/test-diff-suppr/test42-negative-suppr-type-suppr-1.txt:
New test input.
* tests/data/test-diff-suppr/test42-negative-suppr-type-suppr-2.txt: Likewise.
* tests/data/test-diff-suppr/test42-negative-suppr-type-v0.{cc, o}: Likewise.
* tests/data/test-diff-suppr/test42-negative-suppr-type-v1.{cc,
o}: Likewise.
* tests/data/Makefile.am: Add the test files above to source
distribution.
* tests/test-diff-suppr.cc (int_out_specs): Add the new tests to
the harness.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
In the comparison engine, when a sub-type of a function type (say, a
parameter type size change) has been suppressed, this suppression is
not necessarily well propagated to the function carrying the function
type, because the parameter type size, for instance, is considered as
a type local change to that function; and we generally don't propagate
suppression to a non-suppressed parent diff node that already carries
a local change.
This leads to an empty change report for the function we are looking
at because the only sub-type change has been suppressed.
This patch properly propagates the suppressed-ness in that case, so
that the parent function diff node is suppressed as well.
* src/abg-comparison.cc
(suppression_categorization_visitor::visit_end): Propagate
suppression-ness from suppressed function type diff node to its
parent function node if the latter doesn't have any local non-type
change.
* tests/data/test-diff-suppr/test43-suppr-direct-fn-subtype-report-1.txt:
New test reference output.
* tests/data/test-diff-suppr/test43-suppr-direct-fn-subtype-suppr-1.txt:
New test input suppression file.
* tests/data/test-diff-suppr/test43-suppr-direct-fn-subtype-v{0,1}.cc:
Source code of input binary file.
* tests/data/test-diff-suppr/test43-suppr-direct-fn-subtype-v{0,1}.o:
Input binary files.
* tests/data/Makefile.am: Add the new test input files above to
source distribution.
* tests/test-diff-suppr.cc (in_out_specs): Add the test input to
test harness.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
While looking at something else, I noticed that we could be missing
type size changes on function parameters when using has_type_change.
Fixed thus.
* src/abg-comp-filter.cc (has_type_change): Support function
parameters.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
When the endianness of the ELF binary differs from the endianness of
the host, some byte swapping needs to happen when we read the reloc
section to either determine the format of the kernel symbol table or
to get the set of symbols referenced by the kernel symbol table.
So we need to use elf_getdata rather than elf_rawdata to read the data
from the reloc section, because the former handles the proper byte
swapping for us.
This patch does just that and thus fixes the build breakage that is
occuring when running the testreaddwarf test on s390x (big endian),
especially when trying to read the AARCH64 little endian binary
data/test-read-dwarf/PR25007-sdhci.ko.
* src/abg-dwarf-reader.cc
(read_context::{get_ksymtab_format_module,
populate_symbol_map_from_ksymtab_reloc}): Use elf_getdata rather
than elf_rawdata.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
When analyzing an AARCH64 linux kernel module built with support for
either R_AARCH64_ABS64 or R_AARCH64_PREL32 relocations, we need these
macros to be defined in elf.h (i.e a recent enough version of libelf),
otherwise we cannot properly support those kernel modules using the
scheme that uses the relocation table of the __ksymtab and
__ksymtab_gpl sections to read those sections.
In the future, I think we should automatically fallback to another way
of trying to read those sections if those macros are not defined, and
emit a message hinting at what is happening, when in verbose mode. I
am keeping it as is for the moment, so that we can get a better case
of the when these macros are not defined and whatnot.
In the mean time, this patch conditionalizes the test that reads a
kernel module build with support for these relocations to avoid
running it on platform that support these relocations.
* tests/test-read-dwarf.cc: Do not run the test on
PR25007-sdhci.ko if the macros R_AARCH64_PREL32 and
R_AARCH64_ABS64 are not defined.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Now that there are proper facilities to lookup ELF symbols inside the
ELF/DWARF reader and get a native GElf_Sym type instance (from
libelf), we don't need to carry the value of the symbol (that is
relevant only that low level anyway) in the abigail::ir::elf_symbol
type.
This patch removes that property.
* include/abg-ir.h (elf_symbol::{elf_symbol, create}): Remove the
'val' parameter.
* src/abg-dwarf-reader.cc (elf_symbol::get_value): Remove this
member function declaration.
(lookup_symbol_from_sysv_hash_tab)
(lookup_symbol_from_gnu_hash_tab, lookup_symbol_from_symtab)
(create_default_var_sym, create_default_fn_sym)
(read_context::lookup_elf_symbol_from_index): Adjust calls to
creating elf_symbol instances.
* src/abg-ir.cc (elf_symbol::priv::value_): Remove this data
member.
(elf_symbol::{priv::priv, elf_symbol, create): Adjust.
* src/abg-reader.cc (build_elf_symbol): Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
In relocatable files, two symbols listed in the .symtab section can
have the same value and yet be different. That is because those
symbols can be *defined* in different sections. And the value of
those symbols represent addresses (offsets) within their own
respective sections (a.k.a section-relative addresses).
In the same time, symbol address as referred-to in the DWARF
information are *not* section-relative, rather, they are relative to
the beginning of the whole binary.
Until now, the DWARF-referred-to symbol addresses were translated into
section-relative addresses, so that they could be compared to the
other section-relative addresses we were getting from listing the
symbols and their values from the .symtab section. The problem with
that approach is that, during the translation from binary-relative to
section-relative addresses we were wrongly assuming that all symbols
referenced from the DWARF were defined in the .text section. This is
wrong especially for ET_REL files because they could be defined in
sections named .foo.text or .bar.text, for instance.
This leads to issues where we wrongly consider that two symbols having the
same value are the same. Because we wrongly assume that they are all
defined in the same .text section.
This patch fixes this problem by translating the section-relative
addresses we see in .symtab into binary-relative addresses by adding
the address of the section to the section-relative address. Those
binary-addresses can thus safely be compared to the binary-relative
addresses we see in the DWARF. And also, when two symbols have the
same binary-relative address, we can now safely assume that they are
the same -- they are aliases, basically.
* src/abg-dwarf-reader.cc
(read_context::{lookup_native_elf_symbol_from_index,
maybe_adjust_et_rel_sym_addr_to_abs_addr}): Define new member
functions.
(read_context::lookup_elf_symbol_from_index): Add a new overload.
Write the old overloads in terms of the new one.
(read_context::{load_symbol_maps_from_symtab_section,
populate_symbol_map_from_ksymtab_reloc}): Use the new
maybe_adjust_et_rel_sym_addr_to_abs_addr function to translate the
symbol value/address into a binary-relative address before adding
it to the addr->sym maps.
(read_context::maybe_adjust_{fn, var}_sym_address): Do not adjust
DWARF-referred-to addresses of ET_REL symbols anymore.
* tests/data/test-read-dwarf/PR25007-sdhci.ko: New binary test input.
* tests/data/test-read-dwarf/PR25007-sdhci.ko.abi: ABI
representation of the above.
* tests/test-read-dwarf.cc: Add the new test input to the harness.
* tests/data/test-diff-dwarf/test28-vtable-changes-report-0.txt: Adjust.
* tests/data/test-diff-filter/test20-inline-report-0.txt: Likewise.
* tests/data/test-diff-filter/test20-inline-report-1.txt: Likewise.
* tests/data/test-diff-filter/test41-report-0.txt: Likewise.
* tests/data/test-diff-filter/test9-report.txt: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
The patch:
"e687032 Support pre and post v4.19 ksymtabs for Linux kernel modules"
introduces the use of the R_AARCH64_{ABS64, PREL32} macros. However,
some older "elf.h" don't define these. When compiling on these older
platforms, we thus need to avoid using these new macros.
With this patch, the configure system detects the presence of these
macros and defines the HAVE_R_AARCH64_{ABS64, PREL32}_MACRO macros
accordingly.
Note that just to comply with what's in there in the code already, we
don't directly do "#ifdef R_AARCH64_ABS64", but rather "#ifdef
HAVE_R_AARCH64_ABS64_MACRO", to allow cases where we want to
artificially disable the "feature" at configure time, in the future.
* configure.ac: Define macros HAVE_R_AARCH64_{ABS64, PREL32}_MACRO
if the macros R_AARCH64_{ABS64, PREL32} are present.
* src/abg-dwarf-reader.cc
(read_context::get_ksymtab_format_module): Conditionalize the use
of R_AARCH64_{ABS64, PREL32} using HAVE_R_AARCH64_{ABS64, PREL32}_MACRO.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
As described in commit ad8c2531fb, the format of the Linux kernel
ksymtab changed in v4.19 to use relative references instead of absolute
references. This changes the type of relocations emitted for ksymtab
sections to be place-relative 32-bit relocations instead of absolute
relocations. One side-effect of this is that libdwfl will not relocate
the ksymtab sections due to the PC-relative relocations. This breaks
load_kernel_symbol_table() for kernel modules because it only reads in
zeros from the unrelocated ksymtab section and is subsequently unable to
determine what exported symbols it refers to. Since a vmlinux binary is
already fully linked and relocated (and therefore we can read its
ksymtab section just fine), this problem is only relevant to Linux
kernel modules.
To work around this, we utilize the ksymtab relocation sections to
determine which symbols the ksymtab entries refer to. We do this by
inspecting each relocation's r_info field for the symbol table index and
from there we are able to read each symbol's value and subsequently add
that to the set of exported symbols.
In addition, for Linux kernel modules, we can utilize relocation types
to implement a new heuristic to determine the ksymtab format we have.
The presence of PC-relative relocations suggest the new v4.19 format,
and absolute relocation types suggest the old pre v4.19 format.
* include/abg-ir.h (elf_symbol::{elf_symbol, create}): Take new
symbol value and shndx parameters.
(elf_symbol::{get_value, get_shndx}): Declare new accessors.
* src/abg-ir.cc (elf_symbol::priv::{value_, shndx_}): New data
members.
(elf_symbol::priv::priv): Adjust.
(elf_symbol::elf_symbol): Take new value and is_linux_string_cst
parameters.
(elf_symbol::create): Likewise.
(elf_symbol::{get_value, get_is_linux_string_cst}): Define new
accessors.
* src/abg-reader.cc (build_elf_symbol): Adjust.
* src/abg-dwarf-reader.cc (binary_is_linux_kernel)
(binary_is_linux_kernel): New static functions.
(lookup_symbol_from_sysv_hash_tab)
(lookup_symbol_from_gnu_hash_tab)
(lookup_symbol_from_symtab): Adjust.
(read_context::{ksymtab_reloc_section_,
ksymtab_gpl_reloc_section_, ksymtab_strings_section_}): New data
members.
(read_context::read_context): Initialize ksymtab_reloc_section_,
ksymtab_gpl_reloc_section_, ksymtab_strings_section_.
(read_context::{find_ksymtab_reloc_section,
find_ksymtab_gpl_reloc_section, find_ksymtab_strings_section,
find_any_ksymtab_reloc_section, get_ksymtab_format_module,
populate_symbol_map_from_ksymtab,
populate_symbol_map_from_ksymtab_reloc, is_linux_kernel_module}):
New member functions.
(read_context::load_kernel_symbol_table): Adjust to call either
populate_symbol_map_from_ksymtab{_reloc,} depending on ksymtab
format.
(read_context::get_ksymtab_format): Adjust to call
get_ksymtab_format_module for linux kernel modules.
(read_context::lookup_elf_symbol_from_index): Adjust.
(create_default_var_sym, create_default_fn_sym): Adjust.
Signed-off-by: Jessica Yu <jeyu@kernel.org>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
When emitting abixml, profiling shows that we spend a great deal of
time testing if a given type has been emitted already, to avoid
emitting a given type more than once. This makes the serialization
phase take more time than the binary analysis phase!
This patch leverages the fact that we already have the set of
canonical types in the system. While emitting that set entirely, we
don't need to test if a type has been emitted already because we know
by definition that every type is present just once in that set, more
or less. OK, because there are also types that don't have canonical
types (for instance, declaration-only class/structs), we'll still have
to check of those types have already been emitted, but this is a very
small set to handle.
The patch thus organizes the canonical types per scope, so that when
emitting a scope and the canonical types within it, the type is
emitted in its correct namespace.
Then, when emitting a translation unit and each namespaces in it, the
patch emits the canonical types of those namespaces.
The patch arranges for some ancillary things that are needed to make
the whole picture be coherent enough for things to keep working.
Testing shows that we gained ~ 30% of performance by doing this, while
analysing the whole linux kernel 5.1 version. We went from ~ 3m30s
minutes to less than 2m30s.
With this patch, the serialization phase now takes less time than the
analysis time.
* include/abg-fwd.h (is_decl_slow)
(peel_pointer_or_reference_type): Declare new functions.
* include/abg-ir.h (struct canonical_type_hash): Define new type.
(type_base_ptr_set_type, type_base_ptrs_type)
(type_base_sptrs_type, canonical_type_sptr_set_type): Define new
typedefs.
(environment::get_canonical_types_map): Declare new member
function.
(scope_decl::{get_canonical_types, get_sorted_canonical_types}):
Declare new member functions.
* src/abg-ir.cc (is_ptr_ref_or_qual_type)
(peel_pointer_or_reference_type, is_decl_slow): Define new
functions.
(environment::{get_canonical_types_map}): Define new member
functions.
(canonical_type_hash::operator()): Likewise.
(scope_decl::{get_canonical_types, get_sorted_canonical_types}):
Likewise.
(struct type_topo_comp): Define new comparison functor type.
(environment::{sorted_canonical_types_}): Define new data member.
(scope_decl::priv::{canonical_types_, sorted_canonical_types_}):
Likewise.
(scope_decl::is_empty): Take the presence of canonical types into
account when determining if a scope is empty or not.
(is_decl): Make this work for cases where the artifact at hand is
a type which has a declaration, as opposed to being a pure
declaration like a variable or a function.
(canonicalize): Add the canonical type the list of canonical types
of its scope.
* src/abg-dwarf-reader.cc (read_context::die_is_in_cplus_plus):
Define new member function.
* src/abg-writer.cc (write_type, write_canonical_types_of_scope):
Define new static functions.
(fn_type_ptr_set_type): Define new typedef.
(write_context::{m_referenced_fn_types_set,
m_referenced_non_canonical_types_set}): Add new data members.
(write_context::m_referenced_types_set): Renamed
m_referenced_types_map into this.
(write_context::get_referenced_types): Adjust.
(write_context::get_referenced_{function_types,
non_canonical_types}):
(write_context::record_type_as_referenced): Adjust to add the
referenced type in the proper set which would be one of the three
following: write_context::{get_referenced_types,
get_referenced_function_types,
get_referenced_non_canonical_types}.
(write_context::{type_is_referenced, clear_referenced}): Adjust.
(write_translation_unit): Use the new
write_canonical_types_of_scope. Also emit declaration-only
classes that have member types. Do not test if a given type of a
given scope has been emitted, in general, as this was super slow
given the number of types. Emit referenced function types (as
these don't belong to any scope). Rather than using the expensive
"is_function_type" on *all* the referenced types, just walk the
set write_context::get_referenced_function_types. Likewise,
rather than using type_base::get_naked_canonical_type on
*all* the referenced types, just walk the set
write_context::get_referenced_non_canonical_types
(write_class): Use write_canonical_types_of_scope here.
* tools/abilint.cc (main): Support linting corpus group abixml
files.
* tests/data/test-annotate/libtest23.so.abi: Adjust.
* 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/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/test4.so.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-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/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/test0.abi: Likewise.
* tests/data/test-read-dwarf/test1.abi: Likewise.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
* tests/data/test-read-dwarf/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/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/test4.so.abi: Likewise.
* tests/data/test-read-dwarf/test6.so.abi: Likewise.
* tests/data/test-read-dwarf/test7.so.abi: Likewise.
* tests/data/test-read-dwarf/test8-qualified-this-pointer.so.abi: Likewise.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
* tests/data/test-read-write/test10.xml: Likewise.
* tests/data/test-read-write/test14.xml: Likewise.
* tests/data/test-read-write/test15.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/test6.xml: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Kernel modules without exported symbols (no use of EXPORT_SYMBOL*()),
will not have a __ksymtab_strings section. Libabigail will therefore
assume they are usual ELF binaries. That leads to wrong results as
now all ELF symbols are considered part of the ABI. That is obviously
wrong. Instead consider binaries having a .modinfo section to be kernel
binaries. We keep the __ksymtab_strings condition as vmlinux has no
.modinfo section but a __ksymtab_strings if symbols are exported.
One case is still open (and requires maybe some documentation): if a
kernel does not export symbols (no module support), none of the
conditions apply. But, who would be interested in the ABI of a kernel
that does not expose any?
* src/abg-dwarf-reader.cc(is_linux_kernel_binary): consider
binaries only having a .modinfo section to be kernel binaries
Co-developed-by: Alessio Balsini <balsini@android.com>
Signed-off-by: Alessio Balsini <balsini@android.com>
Signed-off-by: Matthias Maennich <maennich@google.com>
On older compilers (such as g++ 4.8), the default C++ standard is set to
gnu++98. When compiling libabigail with --enable-cxx11=yes, src/ and
tests/ where compiled with the correct flag, while tools/ was compiled
without specifying a standard. With a compiler falling back to gnu++98
that leads to unresolved references when linking the tools against the
libabigail library. Fix that by consistently using the std= flag across
the code base.
* configure.ac: add -std=c++11 flag to CXXFLAGS when compiling
for C++11
* src/Makefile.am: drop now obsolete setting of the -std flag
* tests/Makefile.am: likewise
Reported-by: Chun-Hung Wu <Chun-hung.Wu@mediatek.com>
Signed-off-by: Matthias Maennich <maennich@google.com>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
Libabigail's filtering engine fails to recognize an enum changing into
a compatible integer (or vice versa) as a harmless change.
This patch fixes that.
* include/abg-comparison.h (peel_typedef_or_qualified_type_diff):
Declare new function.
(peel_pointer_or_qualified_type_diff): Rename
peel_pointer_or_qualified_type into this.
* include/abg-fwd.h (is_enum_type): Declare a new overload for
type_or_decl_base*.
* src/abg-comp-filter.cc (has_harmless_enum_to_int_change): Define
new static function.
* src/abg-comparison.cc (categorize_harmless_diff_node): Use the
new has_harmless_enum_to_int_change here.
(peel_pointer_or_qualified_type_diff): Renamed
peel_pointer_or_qualified_type into this.
(is_diff_of_basic_type): Adjust.
(peel_typedef_or_qualified_type_diff): Define new function.
* test-diff-filter/PR24787-lib{one, two}.so: New test input
binaries.
* test-diff-filter/PR24787-{one, two}.c: Source files of the test
input binaries above.
* test-diff-filter/PR24787-report-0.txt: Test output reference.
* tests/data/Makefile.am: Add the new testing material to source
distribution.
* tests/test-diff-filter.cc (in_out_specs): Add the new test to
the test harness.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>