From: Giuliano Procida <gprocida@google.com>
To: libabigail@sourceware.org
Cc: dodji@seketeli.org, kernel-team@android.com, gprocida@google.com,
maennich@google.com, woodard@redhat.com
Subject: [RFC PATCH 9/9] Add pass to resolve stray forward type declarations
Date: Thu, 25 Mar 2021 21:51:46 +0000 [thread overview]
Message-ID: <20210325215146.3597963-10-gprocida@google.com> (raw)
In-Reply-To: <20210325215146.3597963-1-gprocida@google.com>
This can be used to improve the precision of ABI reporting for C++ and
Linux kernel which both have some kind of One Definition Rule when it
comes to types.
TODO: handle naming-typedef-id references as well
* scripts/abitidy.pl (substitute_type_ids): New function to
perform renaming of type-id attributes within XML elements.
(resolve_forward_declarations): New function that resolves
forward declarations of types to their definitions, assuming a
consistent universe of type names.
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
scripts/abitidy.pl | 62 ++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 57 insertions(+), 5 deletions(-)
diff --git a/scripts/abitidy.pl b/scripts/abitidy.pl
index 67fe3a69..d45a82bb 100755
--- a/scripts/abitidy.pl
+++ b/scripts/abitidy.pl
@@ -464,11 +464,8 @@ sub eliminate_duplicate_types($dom) {
my @losers = grep { $_ != $candidate } (0..$#$types);
for my $ix (@losers) {
unless (sub_tree($types->[$ix], $types->[$candidate])) {
- warn "conflicting duplicate types with id $id\n";
my @strs = map { $types->[$_]->toString() } ($ix, $candidate);
- map { $_ =~ s;><;>\n<;g } @strs;
- my @lines = map { [split("\n", $_)] } @strs;
- warn Dumper(diff(@lines));
+ warn "conflicting duplicate types with id $id:\n", map { " $_\n" } @strs, "\n";
$candidate = undef;
last;
}
@@ -572,6 +569,55 @@ sub stabilise_types_and_declarations($dom) {
}
}
+# Substitute a set of type ids with another.
+sub substitute_type_ids($winner, $losers, $dom) {
+ for my $ref ($dom->findnodes('//*[@type-id]')) {
+ my $type_id = $ref->getAttribute('type-id');
+ $ref->setAttribute('type-id', $winner) if exists $losers->{$type_id};
+ }
+}
+
+# Find definitions and declarations for the same thing and replace
+# references to the latter with the former. naming-typedef-id may be
+# an added complication.
+sub resolve_forward_declarations($dom) {
+ for my $corpus ($dom->findnodes('//abi-corpus')) {
+ my %synonyms;
+ # Safe to extend to deeper-nested types? Need get_scopes.
+ for my $type ($corpus->findnodes('abi-instr/*[@id]')) {
+ my $kind = $type->getName();
+ my $name = $type->getAttribute('name');
+ next unless defined $name;
+ next if $name =~ m;^__anonymous_;;
+ my $key = "$kind:$name";
+ $synonyms{$key} //= [];
+ push @{$synonyms{$key}}, $type;
+ }
+
+ for my $key (keys %synonyms) {
+ my $types = $synonyms{$key};
+ next if scalar(@$types) == 1;
+ my @decls = grep { $_->hasAttribute('is-declaration-only') } @$types;
+ my @defns = grep { !$_->hasAttribute('is-declaration-only') } @$types;
+ next unless @decls and @defns;
+ # Have declarations and definitions, check that top-level ids
+ # are the only differences.
+ my ($kind, $name) = split(':', $key);
+ my @decl_strs = uniq map { my $str = $_->toString(); my $id = $_->getAttribute('id'); $str =~ s; id='$id';;g; $str } @decls;
+ my @defn_strs = uniq map { my $str = $_->toString(); my $id = $_->getAttribute('id'); $str =~ s; id='$id';;g; $str } @defns;
+ unless (scalar @decl_strs == 1 && scalar @defn_strs == 1) {
+ warn "cannot resolve duplicate $kind types with name $name\n";
+ next;
+ }
+ my $winner = $defns[0]->getAttribute('id');
+ my @losers = grep { $_ ne $winner } map { $_->getAttribute('id') } @$types;
+ warn "resolved $kind $name: substituting @losers with $winner\n";
+ substitute_type_ids($winner, {map { $_ => undef } @losers}, $dom);
+ map { remove_node($_) } (@defns[1..$#defns], @decls);
+ }
+ }
+}
+
# Parse arguments.
my $input_opt;
my $output_opt;
@@ -582,18 +628,20 @@ my $prune_opt;
my $normalise_opt;
my $eliminate_opt;
my $stabilise_opt;
+my $forward_opt;
my $report_opt;
GetOptions('i|input=s' => \$input_opt,
'o|output=s' => \$output_opt,
's|symbols=s' => \$symbols_opt,
'a|all' => sub {
- $drop_opt = $prune_opt = $normalise_opt = $eliminate_opt = $stabilise_opt = $report_opt = 1
+ $drop_opt = $prune_opt = $normalise_opt = $eliminate_opt = $stabilise_opt = $forward_opt = $report_opt = 1
},
'd|drop-empty!' => \$drop_opt,
'p|prune-unreachable!' => \$prune_opt,
'n|normalise-anonymous!' => \$normalise_opt,
'e|eliminate-duplicates!' => \$eliminate_opt,
't|stabilise-order!' => \$stabilise_opt,
+ 'f|resolve-forward!' => \$forward_opt,
'r|report-duplicates!' => \$report_opt,
) and !@ARGV or die("usage: $0",
map { (' ', $_) } (
@@ -606,6 +654,7 @@ GetOptions('i|input=s' => \$input_opt,
'[-n|--[no-]normalise-anonymous]',
'[-e|--[no-]eliminate-duplicates]',
'[-t|--[no-]stabilise-order]',
+ '[-f|--[no-]resolve-forward]',
'[-r|--[no-]report-duplicates]',
), "\n");
@@ -631,6 +680,9 @@ eliminate_duplicate_types($dom) if $eliminate_opt;
# Check for duplicate types.
report_duplicate_types($dom) if $report_opt;
+# Check for types which are both declared and defined.
+resolve_forward_declarations($dom) if $forward_opt;
+
# Prune unreachable elements.
prune_unreachable($dom) if $prune_opt;
--
2.31.0.291.g576ba9dcdaf-goog
prev parent reply other threads:[~2021-03-25 21:52 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-11 11:53 [RFC PATCH] Add an experimental ABI pruning utility Giuliano Procida
2021-03-11 20:39 ` Ben Woodard
2021-03-12 16:51 ` Giuliano Procida
2021-03-12 18:41 ` Ben Woodard
2021-03-15 11:08 ` Giuliano Procida
2021-03-12 16:59 ` [RFC PATCH v2] " Giuliano Procida
2021-03-16 16:55 ` [RFC PATCH v3] " Giuliano Procida
2021-03-25 21:51 ` [RFC PATCH 0/9] Utility to manipulate ABI XML Giuliano Procida
2021-03-25 21:51 ` [RFC PATCH 1/9] Add ABI tidying utility Giuliano Procida
2021-03-25 21:51 ` [RFC PATCH 2/9] Add pass to drop empty XML elements Giuliano Procida
2021-03-25 21:51 ` [RFC PATCH 3/9] Add pass to prune unreachable parts of the ABI Giuliano Procida
2021-03-25 21:51 ` [RFC PATCH 4/9] Add pass to filter symbols Giuliano Procida
2021-03-25 21:51 ` [RFC PATCH 5/9] Add pass to normalise anonymous type names Giuliano Procida
2021-03-25 21:51 ` [RFC PATCH 6/9] Add pass to report duplicate type ids Giuliano Procida
2021-03-25 21:51 ` [RFC PATCH 7/9] Add pass to eliminate duplicate member-type fragments Giuliano Procida
2021-03-25 21:51 ` [RFC PATCH 8/9] Add pass to stabilise types and declarations Giuliano Procida
2021-03-25 21:51 ` Giuliano Procida [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210325215146.3597963-10-gprocida@google.com \
--to=gprocida@google.com \
--cc=dodji@seketeli.org \
--cc=kernel-team@android.com \
--cc=libabigail@sourceware.org \
--cc=maennich@google.com \
--cc=woodard@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).