From patchwork Thu Mar 25 21:51:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuliano Procida X-Patchwork-Id: 42781 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3EFDE385802E; Thu, 25 Mar 2021 21:52:30 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3EFDE385802E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1616709150; bh=wM1L44w1X6HU2wCWTA+LIWhl361jehAOeFiIsQdyteA=; h=Date:In-Reply-To:References:Subject:To:List-Id:List-Unsubscribe: List-Archive:List-Help:List-Subscribe:From:Reply-To:Cc:From; b=wSHjxYQHnsCogvEJJMfQxRKiOjJjRsoPkk0YDhvrZSITVPRGDjO6ZHKN34l0FgIwu h5YVSXSZP+YNxa6TnUczE5k3AOPtkR0N/YivpL6Zm9Jv/CexJFUWhvVI7fbmrNpYiB WNyzBzvZvcgDzT4/KEJkZPFqHvFSoHRvnr5y/Dx8= X-Original-To: libabigail@sourceware.org Delivered-To: libabigail@sourceware.org Received: from mail-qt1-x84a.google.com (mail-qt1-x84a.google.com [IPv6:2607:f8b0:4864:20::84a]) by sourceware.org (Postfix) with ESMTPS id 31C0A3857C73 for ; Thu, 25 Mar 2021 21:52:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 31C0A3857C73 Received: by mail-qt1-x84a.google.com with SMTP id f26so4092323qtq.17 for ; Thu, 25 Mar 2021 14:52:23 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=wM1L44w1X6HU2wCWTA+LIWhl361jehAOeFiIsQdyteA=; b=qyJB+UwQ6yQTfNSBOJus/zJHFFL+RuBdOSBFFG8HK8qjd8ABwweN2HZEdPiUTcmhE1 stFtn/T6/fCwEFa+XO11nZOFbngGLuiiNJFHvCsNPMlAn2huWD3cRsqQGtflayKHRBHf 23kvUJ3k7nXjZnwIh0h2qvgJ3m5DAHU/4ZIz1vktPFnrp4W9fV5WeqwGe/RqONY2OSIw NRJKcnyIuSs/q3B7aBr85beIT/NQIDXeJdJCRm1LimLOyw5un6lV8kn6FUNJbExadlwu WEGVB8h4rg0mmpUOTYtW12Ji9Qw2cilNpaF2Zch1B0GDx43R/BtgvBSm2hoyO49OdUKm qMPw== X-Gm-Message-State: AOAM532mpOeT21BYPwGMxpBhkhvBc5Vh28Tb+jUsEpdUYWF3/7jWYUeX W/iQtodhh87AX3LwlEnQnVZqCpNcGcqTmWrDWeuKb6m1LCjTZy/cgt4zNNefNRIycje7YEp7J7m U9lIMSk7VD7rn3QcpktkarZBNm1a7W/kirts5qYgUZp+1Q4WsIaxIe2I2xsN9SVu52e4sfWg= X-Google-Smtp-Source: ABdhPJwvWkYJWAVgZKpRnYldSZ7kwavW+1yqfa3zq49L7mYS/mWHN48FvjjvdTkS4hi6XIHuNP0eNXW20WSWiQ== X-Received: from tef.lon.corp.google.com ([2a00:79e0:d:110:2df6:f24a:7f54:86a8]) (user=gprocida job=sendgmr) by 2002:ad4:4c4c:: with SMTP id cs12mr10333922qvb.35.1616709142805; Thu, 25 Mar 2021 14:52:22 -0700 (PDT) Date: Thu, 25 Mar 2021 21:51:46 +0000 In-Reply-To: <20210325215146.3597963-1-gprocida@google.com> Message-Id: <20210325215146.3597963-10-gprocida@google.com> Mime-Version: 1.0 References: <20210316165509.2658452-1-gprocida@google.com> <20210325215146.3597963-1-gprocida@google.com> X-Mailer: git-send-email 2.31.0.291.g576ba9dcdaf-goog Subject: [RFC PATCH 9/9] Add pass to resolve stray forward type declarations To: libabigail@sourceware.org X-Spam-Status: No, score=-22.5 required=5.0 tests=BAYES_00, DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libabigail@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list of the Libabigail project List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-Patchwork-Original-From: Giuliano Procida via Libabigail From: Giuliano Procida Reply-To: Giuliano Procida Cc: maennich@google.com, kernel-team@android.com Errors-To: libabigail-bounces@sourceware.org Sender: "Libabigail" 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 --- 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;