From patchwork Mon Oct 18 08:38:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 46325 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 6BDD83858431 for ; Mon, 18 Oct 2021 08:38:49 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6BDD83858431 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1634546329; bh=4HMQe9iyEdIPp53vtQ2Y7vO/boSm620h+5spKh6pFXQ=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Help: List-Subscribe:From:Reply-To:From; b=FC3oudy5cjqOsePYCL0Fs7Zo6EQlYLWA4d1ahElDOwN7mnyixkKDuvo17y6HCeKrc E7BdYIfGXgf+BkB1tFcZb7uT2xIv3367fyAE5KnUTcU935nlS3kXln3/dPt4tVR8Jo 577bMphseeZLwvJVBORZcKQ+ua6l9OZUYPEwWlXI= X-Original-To: libabigail@sourceware.org Delivered-To: libabigail@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTPS id A37C53858431 for ; Mon, 18 Oct 2021 08:38:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org A37C53858431 Received: from mail-qv1-f70.google.com (mail-qv1-f70.google.com [209.85.219.70]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-267-KXb2W94kPIuOs2ZV73PxlA-1; Mon, 18 Oct 2021 04:38:28 -0400 X-MC-Unique: KXb2W94kPIuOs2ZV73PxlA-1 Received: by mail-qv1-f70.google.com with SMTP id gi5-20020a056214248500b00382f7a7c7e6so14185691qvb.21 for ; Mon, 18 Oct 2021 01:38:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:organization:date:message-id :user-agent:mime-version; bh=4HMQe9iyEdIPp53vtQ2Y7vO/boSm620h+5spKh6pFXQ=; b=vOxKHvA+0EZkCXzl6WnKAyPeFmVZ2e5ktZF2wi/lV2UG0brFM8OVgqEiNNEtmEut0O yzgqRck/lLSnwOl9nW8W85bLQall+AcPJhZz8vc1KCvUad8bZKY3/xVRo5Pn8Tj+rm3q Evf8UH6EGsIpDS18JOkOirAQKmTXdhlVSh4LjZKsahHyDdENwaK7ZEnq++pp7HQybjUB vTSMx1BXIm4g/PaGLP7DpJIWHz9czRPdr197umo7zcHgcbn0tZKRvf9xN96ZKtjjbdfU GZrEmL/uZyW9pkXZ/QcQlUbQ8REogsnjXursHa0D8fORlt8Z1Ww6y4p5lKvr2d/Mo+AU 7vjA== X-Gm-Message-State: AOAM532mfaCSdAZsNZsAUKFXmMj2JiOKIzkCCeZV6dX1ulclHlkhIyrD t2QLTcqAbABRwHPPj/ONdS5GM1kwY/sXDJehYbkB+TiZiKJqIoo5tx/06S92+TH9EF/VV/1FUYS oTRCWZ5tcZ0IplTqGt1IMUK3UHggtXPY2vO6Oc7JHo1RC9oFC4nqdcVgW5vaS+8fFmMds X-Received: by 2002:a05:622a:188a:: with SMTP id v10mr28347979qtc.302.1634546307392; Mon, 18 Oct 2021 01:38:27 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyEl1Po8jRJs8A3KOuzkF67owv+SxbTTCz5i0lI7eplVEjdk+LO5WkUhXZMz6VFylpfDi88eA== X-Received: by 2002:a05:622a:188a:: with SMTP id v10mr28347950qtc.302.1634546306827; Mon, 18 Oct 2021 01:38:26 -0700 (PDT) Received: from localhost ([88.120.130.27]) by smtp.gmail.com with ESMTPSA id f77sm6225898qke.133.2021.10.18.01.38.26 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 18 Oct 2021 01:38:26 -0700 (PDT) Received: by localhost (Postfix, from userid 1000) id 872AD5802BD; Mon, 18 Oct 2021 10:38:23 +0200 (CEST) To: libabigail@sourceware.org Subject: [PATCH, applied] Add --enable-debug-type-canonicalization to configure Organization: Red Hat / France X-Operating-System: Fedora 36 X-URL: http://www.redhat.com Date: Mon, 18 Oct 2021 10:38:23 +0200 Message-ID: <87ee8id8xs.fsf@redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Dodji Seketeli via Libabigail From: Dodji Seketeli Reply-To: Dodji Seketeli Errors-To: libabigail-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libabigail" Hello, This configure option adds the possibility to debug the type canonicalization process specifically. When this new configure option is turned on, in ir::get_canonical_type_for, when the type T, candidate for canonicalization is compared to a given canonical type C, the comparison is done twice; once using structural equality and once using canonical equality whenever it's possible. For all the sub-types of T and C, structural equality and canonical equality must yield the same result. Otherwise, an error message is emitted and the process aborts. This all happens when using the abidw program with the --enable-tc or --enable-type-canonicalization option. This has proven to be very helpful to detect type canonicalization issues. For instance, here is a trace of canonicalization issue that was detected thanks to this patch: $ build/tools/abidw --debug-tc /usr/lib64/libwiretap.so.11.0.8 structural & canonical equality different for type: function type void (wtap*) in compare_types_during_canonicalization at: /home/dodji/git/libabigail/PR28364/src/abg-ir.cc:13575: execution should not have reached this point! Abandon (core dumped) This means that right after canonicalizing the type "void (wtap*)", structural and canonical equality yield different results. So it means there is a problem with that type specifically that makes its canonicalization "go wrong". This requires further debugging to understand, but at least, we are super close to the root cause of the canonicalization problem. * configure.ac: Support the new --enable-debug-type-canonicalization option. Define macro WITH_DEBUG_TYPE_CANONICALIZATION accordingly. * doc/manuals/abidw.rst: Update documentation. * include/abg-ir.h (environment::debug_type_canonicalization_is_on): Declare new member function if WITH_DEBUG_TYPE_CANONICALIZATION is defined. * src/abg-ir-priv.h (environment::priv::{use_canonical_type_comparison_, debug_type_canonicalization_}): Define new data members if WITH_DEBUG_TYPE_CANONICALIZATION is defined. (environment::priv::priv): Initialize them. * src/abg-ir.cc (try_canonical_compare): When WITH_DEBUG_TYPE_CANONICALIZATION is defined, perform comparison using either structural or canonical equality depending on the environment::priv::use_canonical_type_comparison_ flag. (environment::debug_type_canonicalization_is_on): Define member function when WITH_DEBUG_TYPE_CANONICALIZATION is defined. (compare_types_during_canonicalization): Define new function. (type_base::get_canonical_type_for): Use the new function compare_types_during_canonicalization. * tools/abidw.cc (options::debug_type_canonicalization): Define new data member. (option::option): Initialize it. (display_usage): Add help string for --debug-tc. (parse_command_line): Support new option --debug-tc or --debug-type-canonicalization. (load_corpus_and_write_abixml): Turn type canonicalization debugging on if --enable-tc is provided. Signed-off-by: Dodji Seketeli Applied to master. --- configure.ac | 19 ++++++++ doc/manuals/abidw.rst | 13 +++++ include/abg-ir.h | 8 +++ src/abg-ir-priv.h | 20 ++++++++ src/abg-ir.cc | 110 +++++++++++++++++++++++++++++++++++++++++- tools/abidw.cc | 19 ++++++++ 6 files changed, 187 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 9e91f496..950e2704 100644 --- a/configure.ac +++ b/configure.ac @@ -72,6 +72,12 @@ AC_ARG_ENABLE(debug-self-comparison, ENABLE_DEBUG_SELF_COMPARISON=$enableval, ENABLE_DEBUG_SELF_COMPARISON=no) +AC_ARG_ENABLE(debug-type-canonicalization, + AS_HELP_STRING([--enable-debug-type-canonicalization=yes|no], + [enable debugging of type canonicalization 'abidw --debug-tc'(default is no)]), + ENABLE_DEBUG_TYPE_CANONICALIZATION=$enableval, + ENABLE_DEBUG_TYPE_CANONICALIZATION=no) + AC_ARG_ENABLE(deb, AS_HELP_STRING([--enable-deb=yes|no|auto], [enable the support of deb in abipkgdiff (default is auto)]), @@ -313,6 +319,18 @@ fi AM_CONDITIONAL(ENABLE_DEBUG_SELF_COMPARISON, test x$ENABLE_DEBUG_SELF_COMPARISON = xyes) +dnl enable the debugging of type canonicalization when doing abidw --debug-tc +if test x$ENABLE_DEBUG_TYPE_CANONICALIZATION = xyes; then + AC_DEFINE([WITH_DEBUG_TYPE_CANONICALIZATION], + 1, + [compile support of debugging type canonicalization while using abidw --debug-tc]) + AC_MSG_NOTICE([support of debugging type canonicalization is enabled]) +else + AC_MSG_NOTICE([support of debugging type canonicalization is disabled]) +fi + +AM_CONDITIONAL(ENABLE_DEBUG_TYPE_CANONICALIZATION, test x$ENABLE_DEBUG_TYPE_CANONICALIZATION = xyes) + dnl Check for the dpkg program if test x$ENABLE_DEB = xauto -o x$ENABLE_DEB = xyes; then AC_CHECK_PROG(HAS_DPKG, dpkg, yes, no) @@ -931,6 +949,7 @@ AC_MSG_NOTICE([ Enable rpm support in abipkgdiff : ${ENABLE_RPM} Enable rpm 4.15 support in abipkgdiff tests : ${ENABLE_RPM415} Enable self comparison debugging : ${ENABLE_DEBUG_SELF_COMPARISON} + Enable type canonicalization debugging : ${ENABLE_DEBUG_TYPE_CANONICALIZATION} Enable deb support in abipkgdiff : ${ENABLE_DEB} Enable GNU tar archive support in abipkgdiff : ${ENABLE_TAR} Enable bash completion : ${ENABLE_BASH_COMPLETION} diff --git a/doc/manuals/abidw.rst b/doc/manuals/abidw.rst index 4b110d6b..d7545899 100644 --- a/doc/manuals/abidw.rst +++ b/doc/manuals/abidw.rst @@ -250,6 +250,19 @@ Options it the libabigail package needs to be configured with the --enable-debug-self-comparison option. + * ``--debug-type-canonicalization | --debug-tc`` + + Debug the type canonicalization process. This is done by using + structural and canonical equality when canonicalizing every single + type. Structural and canonical equality should yield the same + result. If they don't yield the same result for a given type, + then it means that the canonicalization of that type went wrong. + In that case, an error message is emitted and the execution of the + program is aborted. + + This option is available only if the package was configured with + the --enable-debug-type-canonicalization option. + * ``--annotate`` diff --git a/include/abg-ir.h b/include/abg-ir.h index 81147144..a651d1b7 100644 --- a/include/abg-ir.h +++ b/include/abg-ir.h @@ -217,6 +217,14 @@ public: self_comparison_debug_is_on() const; #endif +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + void + debug_type_canonicalization_is_on(bool flag); + + bool + debug_type_canonicalization_is_on() const; +#endif + vector* get_canonical_types(const char* name); type_base* get_canonical_type(const char* name, unsigned index); diff --git a/src/abg-ir-priv.h b/src/abg-ir-priv.h index 18623ceb..a01a1b2c 100644 --- a/src/abg-ir-priv.h +++ b/src/abg-ir-priv.h @@ -389,6 +389,21 @@ struct environment::priv #ifdef WITH_DEBUG_SELF_COMPARISON bool self_comparison_debug_on_; #endif +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + // This controls whether to use canonical type comparison during + // type comparison or not. This is only used for debugging, when we + // want to ensure that comparing types using canonical or structural + // comparison yields the same result. + bool use_canonical_type_comparison_; + // Whether we are debugging type canonicalization or not. When + // debugging type canonicalization, a type is compared to its + // potential canonical type twice: The first time with canonical + // comparison activated, and the second time with structural + // comparison activated. The two comparison should yield the same + // result, otherwise, canonicalization is "broken" for that + // particular type. + bool debug_type_canonicalization_; +#endif priv() : canonicalization_is_done_(), @@ -398,6 +413,11 @@ struct environment::priv #ifdef WITH_DEBUG_SELF_COMPARISON , self_comparison_debug_on_(false) +#endif +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + , + use_canonical_type_comparison_(true), + debug_type_canonicalization_(false) #endif {} diff --git a/src/abg-ir.cc b/src/abg-ir.cc index 3a1fbdd1..a79dca92 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -864,10 +864,41 @@ template bool try_canonical_compare(const T *l, const T *r) { +#if WITH_DEBUG_TYPE_CANONICALIZATION + // We are debugging the canonicalization of a type down the stack. + // 'l' is a subtype of a canonical type and 'r' is a subtype of the + // type being canonicalized. We are at a point where we can compare + // 'l' and 'r' either using canonical comparison (if 'l' and 'r' + // have canonical types) or structural comparison. + // + // Because we are debugging the process of type canonicalization, we + // want to compare 'l' and 'r' canonically *AND* structurally. Both + // kinds of comparison should yield the same result, otherwise type + // canonicalization just failed for the subtype 'r' of the type + // being canonicalized. + // + // In concrete terms, this function is going to be called twice with + // the same pair {'l', 'r'} to compare: The first time with + // environment::priv_->use_canonical_type_comparison_ set to true, + // instructing us to compare them canonically, and the second time + // with that boolean set to false, instructing us to compare them + // structurally. + const environment *env = l->get_environment(); + if (env->priv_->use_canonical_type_comparison_) + { + if (const type_base *lc = l->get_naked_canonical_type()) + if (const type_base *rc = r->get_naked_canonical_type()) + ABG_RETURN_EQUAL(lc, rc); + } + return equals(*l, *r, 0); +#else if (const type_base *lc = l->get_naked_canonical_type()) if (const type_base *rc = r->get_naked_canonical_type()) ABG_RETURN_EQUAL(lc, rc); return equals(*l, *r, 0); +#endif + + } /// Detect if a recursive comparison cycle is detected while @@ -3667,6 +3698,26 @@ environment::self_comparison_debug_is_on() const {return priv_->self_comparison_debug_on_;} #endif +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION +/// Set the "type canonicalization debugging" mode, triggered by using +/// the command: "abidw --debug-tc". +/// +/// @param flag if true then the type canonicalization debugging mode +/// is enabled. +void +environment::debug_type_canonicalization_is_on(bool flag) +{priv_->debug_type_canonicalization_ = flag;} + +/// Getter of the "type canonicalization debugging" mode, triggered by +/// using the command: "abidw --debug-tc". +/// +/// @return true iff the type canonicalization debugging mode is +/// enabled. +bool +environment::debug_type_canonicalization_is_on() const +{return priv_->debug_type_canonicalization_;} +#endif // WITH_DEBUG_TYPE_CANONICALIZATION + /// Get the vector of canonical types which have a given "string /// representation". /// @@ -13535,6 +13586,61 @@ types_defined_same_linux_kernel_corpus_public(const type_base& t1, return false; } + +/// Compare a type T against a canonical type. +/// +/// This function is called during the canonicalization process of the +/// type T. T is called the "candidate type" because it's in the +/// process of being canonicalized. Meaning, it's going to be +/// compared to a canonical type C. If T equals C, then the canonical +/// type of T is C. +/// +/// The purpose of this function is to allow the debugging of the +/// canonicalization of T, if that debugging is activated by +/// configuring the libabigail package with +/// --enable-debug-type-canonicalization and by running "abidw +/// --debug-tc". In that case, T is going to be compared to C twice: +/// once with canonical equality and once with structural equality. +/// The two comparisons must be equal. Otherwise, the +/// canonicalization process is said to be faulty and this function +/// aborts. +/// +/// This is a sub-routine of type_base::get_canonical_type_for. +/// +/// @param canonical_type the canonical type to compare the candidate +/// type against. +/// +/// @param candidate_type the candidate type to compare against the +/// canonical type. +/// +/// @return true iff @p canonical_type equals @p candidate_type. +/// +static bool +compare_types_during_canonicalization(const type_base_sptr& canonical_type, + const type_base_sptr& candidate_type) +{ +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + environment *env = canonical_type->get_environment(); + if (env->debug_type_canonicalization_is_on()) + { + bool canonical_equality = false, structural_equality = false; + env->priv_->use_canonical_type_comparison_ = true; + canonical_equality = canonical_type == candidate_type; + env->priv_->use_canonical_type_comparison_ = false; + structural_equality = canonical_type == candidate_type; + if (canonical_equality != structural_equality) + { + std::cerr << "structural & canonical equality different for type: " + << canonical_type->get_pretty_representation(true, true) + << std::endl; + ABG_ASSERT_NOT_REACHED; + } + return structural_equality; + } +#endif //end WITH_DEBUG_TYPE_CANONICALIZATION + return canonical_type == candidate_type; +} + /// Compute the canonical type for a given instance of @ref type_base. /// /// Consider two types T and T'. The canonical type of T, denoted @@ -13665,8 +13771,8 @@ type_base::get_canonical_type_for(type_base_sptr t) // Compare types by considering that decl-only classes don't // equal their definition. env->decl_only_class_equals_definition(false); - bool equal = types_defined_same_linux_kernel_corpus_public(**it, *t) - || *it == t; + bool equal = (types_defined_same_linux_kernel_corpus_public(**it, *t) + || compare_types_during_canonicalization(*it, t)); // Restore the state of the on-the-fly-canonicalization and // the decl-only-class-being-equal-to-a-matching-definition // flags. diff --git a/tools/abidw.cc b/tools/abidw.cc index 54bf3aa4..240ed095 100644 --- a/tools/abidw.cc +++ b/tools/abidw.cc @@ -102,6 +102,9 @@ struct options bool abidiff; #ifdef WITH_DEBUG_SELF_COMPARISON bool debug_abidiff; +#endif +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + bool debug_type_canonicalization; #endif bool annotate; bool do_log; @@ -132,6 +135,9 @@ struct options abidiff(), #ifdef WITH_DEBUG_SELF_COMPARISON debug_abidiff(), +#endif +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + debug_type_canonicalization(), #endif annotate(), do_log(), @@ -195,6 +201,9 @@ display_usage(const string& prog_name, ostream& out) << " --abidiff compare the loaded ABI against itself\n" #ifdef WITH_DEBUG_SELF_COMPARISON << " --debug-abidiff debug the process of comparing the loaded ABI against itself\n" +#endif +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + << " --debug-tc debug the type canonicalization process\n" #endif << " --annotate annotate the ABI artifacts emitted in the output\n" << " --stats show statistics about various internal stuff\n" @@ -348,6 +357,11 @@ parse_command_line(int argc, char* argv[], options& opts) opts.abidiff = true; opts.debug_abidiff = true; } +#endif +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + else if (!strcmp(argv[i], "--debug-tc") + || !strcmp(argv[i], "debug-type-canonicalization")) + opts.debug_type_canonicalization = true; #endif else if (!strcmp(argv[i], "--annotate")) opts.annotate = true; @@ -498,6 +512,11 @@ load_corpus_and_write_abixml(char* argv[], env->self_comparison_debug_is_on(true); #endif +#ifdef WITH_DEBUG_TYPE_CANONICALIZATION + if (opts.debug_type_canonicalization) + env->debug_type_canonicalization_is_on(true); +#endif + read_context& ctxt = *context; corpus_sptr corp; dwarf_reader::status s = dwarf_reader::STATUS_UNKNOWN;