From patchwork Tue Sep 20 11:29:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 57799 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 7E3243858D28 for ; Tue, 20 Sep 2022 11:29:53 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7E3243858D28 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1663673393; bh=vPMspsnKYXCH7FNpIzQ0yebcFYcKaL1u9S9QG798qOg=; h=To:Subject:References:Date:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Help:List-Subscribe:From:Reply-To:Cc:From; b=sjBJ32G0vNMtCeSOUpSXco1G9PPypRpYrrUnDDMoUR8XwzQsLGw1XHkSTBM0olvXc Y9WiYC0g3pubTiBtSbOpCqelbKA/Jx/1sl08gnq6khCw0TyEsOrzxn5dUVcmRhzMSQ ZzSG7qFxbaxQvEffE0ghQV1IjOBWV2+XvEs0Syg4= 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 [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 8E1323858D28 for ; Tue, 20 Sep 2022 11:29:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8E1323858D28 Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-224-duend1ikOTmwTyF5SRFSYA-1; Tue, 20 Sep 2022 07:29:43 -0400 X-MC-Unique: duend1ikOTmwTyF5SRFSYA-1 Received: by mail-qk1-f198.google.com with SMTP id az15-20020a05620a170f00b006cece4cd0beso1659260qkb.22 for ; Tue, 20 Sep 2022 04:29:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:user-agent:message-id:in-reply-to:date:references :organization:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=vPMspsnKYXCH7FNpIzQ0yebcFYcKaL1u9S9QG798qOg=; b=LQ8y0arq+3aAklcqkf3rZkly8Jlzon6lNbFE5NV2NDowtNl+lEN6v1sDIH6HQngtDw z2E3FeLD+IGoLIJMeiwZtmEqJ+iqWehDVhys3wgehsNjBueb6oV2sfvbGduzbo+Yjhce oHWKtSuBN6/nSVcUcx3j0RIvt86IvrNOvlt/pm3C2kMgSAH6/6u6+e91Xb/xtazn2U1h x/htMRGE75YSirdd0OJQOUaDvCkUji3CB1vZfemTSBclYRKadodtaQwLL3fzwZS/wI9F cspZeJDHTM7zOyGaxXFgMBapqQ8l4Zvy8HO/kIJNRs1bzfDheHBqNFaxYX4Uh6J0RwSG 9d/g== X-Gm-Message-State: ACrzQf2yL8QBD6C5R1TFefnY4iGhlnEKth0wGG1bAPX0XLmKN89od1r1 WmflTNQOBW6UC8y2BxNwdkM+GGGgvPEEmEYGdmjcW2o4fWwzIX8/cPJQWTI1YFvgPbRymKheArb bWjS0E5lgyenK86/sZELs X-Received: by 2002:a05:620a:1905:b0:6ce:fe9a:f79f with SMTP id bj5-20020a05620a190500b006cefe9af79fmr6918130qkb.204.1663673381431; Tue, 20 Sep 2022 04:29:41 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6taOYegJrYafR0LHh69gIGK4P7F+TVqQt9cnPVHSnOoCxYlXtQF4GmboBJiZXGH0vqUQ3pgA== X-Received: by 2002:a05:620a:1905:b0:6ce:fe9a:f79f with SMTP id bj5-20020a05620a190500b006cefe9af79fmr6918095qkb.204.1663673380528; Tue, 20 Sep 2022 04:29:40 -0700 (PDT) Received: from localhost ([88.120.130.27]) by smtp.gmail.com with ESMTPSA id o20-20020a05620a229400b006ced5d3f921sm859686qkh.52.2022.09.20.04.29.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Sep 2022 04:29:39 -0700 (PDT) Received: by localhost (Postfix, from userid 1000) id 2B0655802BD; Tue, 20 Sep 2022 13:29:38 +0200 (CEST) To: libabigail@sourceware.org Subject: [PATCH 2/4, applied] Allow restricting analyzed decls to exported symbols Organization: Red Hat / France References: <87tu525ngh.fsf@seketeli.org> X-Operating-System: Fedora 38 X-URL: http://www.redhat.com Date: Tue, 20 Sep 2022 13:29:37 +0200 In-Reply-To: <87tu525ngh.fsf@seketeli.org> (Dodji Seketeli's message of "Tue, 20 Sep 2022 12:50:38 +0200") Message-ID: <87h7125lni.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, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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 Cc: dodji@redhat.com Errors-To: libabigail-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libabigail" Hello, Profiling showed that the DWARF reader scans too much data. Basically, in build_translation_unit_and_add_to_ir, build_ir_node_from_die is called on every single DIE that is seen, for a given translation unit. There are interfaces (function and variable decls) that are not associated with exported ELF symbols and that are analyzed by build_ir_node_from_die nonetheless. For instance, interfaces that are visible outside of their translation units are analyzed and the types that are reachable from those interfaces are analyzed as well. Once that is done, an ABI corpus is built with the subset of interfaces that have exported ELF symbol (strictly those that are part of the ABI), but types that are not necessarily reachable from those ABI interfaces can also be put into the ABI corpus. Some tools make use of this "lose" behaviour of libabigail. For instance, abicompat precisely wants to analyze interfaces with undefined symbols. For an application, those interfaces represents the interfaces that the application expects to be provided by some shared library. When analyzing the exported interface of the Linux Kernel (or any other huge application) however, analyzing more types than necessary appears to incur a huge time penalty. So, this patch introduces an optional behaviour whereby build_translation_unit_and_add_to_ir is restricted to analyzing interfaces that have exported ELF symbols only. So only the types reachable from those interfaces are analyzed. This more than halves the time spent by "abidw --noout vmlinux". Strictly speaking, this new behaviour is triggered by a new option named --exported-interfaces-only, supported by the tools abidw, abidiff, abipkgdiff and kmidiff. When looking at the Linux Kernel however, this option is enabled by default. Note that an option --allow-non-exported-interfaces is also introduce to function under the previous model of operations. This option is enabled by default on all the tools when they are not looking at the Linux Kernel. With this enabled, analyzing the Linux Kernel is back to taking less than a minute on a reasonable machine. * doc/manuals/tools-use-libabigail.txt: New doc text. * doc/manuals/Makefile.am: Add the new tools-use-libabigail.rst tool to the source distribution. * doc/manuals/abidiff.rst: Include the new tools-use-libabigail.rst. Document the --exported-interfaces-only and --allow-non-exported-interfaces. * doc/manuals/abidw.rst: Likewise. * doc/manuals/abipkgdiff.rst: Likewise. * doc/manuals/kmidiff.rst: Likewise. * include/abg-ir.h (environment::{user_set_analyze_exported_interfaces_only, analyze_exported_interfaces_only}): Declare new accessors. * src/abg-ir.cc (environment::{user_set_analyze_exported_interfaces_only, analyze_exported_interfaces_only}): Define new accessors. * src/abg-dwarf-reader.cc (die_is_variable_decl) (die_is_function_decl): Define new static functions. (read_context::is_decl_die_with_exported_symbol): Define new member function. (read_context::get_{function,variable}_address): Const-ify the Dwarf_Die* parameter. (build_translation_unit_and_add_to_ir): If the user asks to analyze exported interfaces only, the analyze only interfaces that have exported ELF symbols. (read_debug_info_into_corpus): If we are looking at the Linux Kernel, then only analyze exported interfaces unless the user asks otherwise. * src/abg-ir-priv.h (environment::priv::analyze_exported_interfaces_only_): Define new data member. * tools/abidiff.cc (options::exported_interfaces_only): Define new data member. (display_usage): Add new help strings for --exported-interfaces-only and --allow-non-exported-interfaces. (parse_command_line): Parse the new options --exported-interfaces-only and --allow-non-exported-interfaces. (main): Pass the value of opts.exported_interfaces_only to the environment. * tools/abidw.cc (options::exported_interfaces_only): Define new data member. (display_usage): Add new help strings for --exported-interfaces-only and --allow-non-exported-interfaces. (parse_command_line): Parse the new options (load_corpus_and_write_abixml) (load_kernel_corpus_group_and_write_abixml): Pass the value of opts.exported_interfaces_only onto the environment. * tools/abipkgdiff.cc (options::exported_interfaces_only): Define new data member. (display_usage): Add new help strings for --exported-interfaces-only and --allow-non-exported-interfaces. (parse_command_line): Parse the new options (compare_task::perform, self_compare_task::perform): Pass the value of opts.exported_interfaces_only onto the environment. (compare_prepared_linux_kernel_packages): Likewise. * tools/kmidiff.cc(options::exported_interfaces_only): Define new data member. (display_usage): Add new help strings for --exported-interfaces-only and --allow-non-exported-interfaces. (parse_command_line): Parse the new options (main): Pass the value of opts.exported_interfaces_only onto the environment. Signed-off-by: Dodji Seketeli --- doc/manuals/Makefile.am | 3 +- doc/manuals/abidiff.rst | 52 ++++++++++++ doc/manuals/abidw.rst | 82 ++++++++++++++++--- doc/manuals/abipkgdiff.rst | 51 ++++++++++++ doc/manuals/kmidiff.rst | 52 +++++++++++- doc/manuals/tools-use-libabigail.txt | 16 ++++ include/abg-ir.h | 9 +++ src/abg-dwarf-reader.cc | 113 ++++++++++++++++++++++++--- src/abg-ir-priv.h | 2 + src/abg-ir.cc | 36 +++++++++ tools/abidiff.cc | 12 +++ tools/abidw.cc | 15 ++++ tools/abipkgdiff.cc | 21 +++++ tools/kmidiff.cc | 12 +++ 14 files changed, 449 insertions(+), 27 deletions(-) create mode 100644 doc/manuals/tools-use-libabigail.txt diff --git a/doc/manuals/Makefile.am b/doc/manuals/Makefile.am index 894b38f1..e2813785 100644 --- a/doc/manuals/Makefile.am +++ b/doc/manuals/Makefile.am @@ -14,7 +14,8 @@ libabigail-concepts.rst \ libabigail-overview.rst \ libabigail-tools.rst \ fedabipkgdiff.rst \ -kmidiff.rst +kmidiff.rst \ +tools-use-libabigail.txt # You can set these variables from the command line. SPHINXOPTS = diff --git a/doc/manuals/abidiff.rst b/doc/manuals/abidiff.rst index a15515be..0c711d9e 100644 --- a/doc/manuals/abidiff.rst +++ b/doc/manuals/abidiff.rst @@ -18,6 +18,8 @@ be accompanied with their debug information in `DWARF`_ format. Otherwise, only `ELF`_ symbols that were added or removed are reported. +.. include:: tools-use-libabigail.txt + .. _abidiff_invocation_label: Invocation @@ -197,6 +199,56 @@ Options consumption of the tool on binaries with a lot of publicly defined and exported types. + * ``--exported-interfaces-only`` + + By default, when looking at the debug information accompanying a + binary, this tool analyzes the descriptions of the types reachable + by the interfaces (functions and variables) that are visible + outside of their translation unit. Once that analysis is done, an + ABI corpus is constructed by only considering the subset of types + reachable from interfaces associated to `ELF`_ symbols that are + defined and exported by the binary. It's those final ABI Corpora + that are compared by this tool. + + The problem with that approach however is that analyzing all the + interfaces that are visible from outside their translation unit + can amount to a lot of data, especially when those binaries are + applications, as opposed to shared libraries. One example of such + applications is the `Linux Kernel`_. Analyzing massive ABI + corpora like these can be extremely slow. + + To mitigate that performance issue, this option allows libabigail + to only analyze types that are reachable from interfaces + associated with defined and exported `ELF`_ symbols. + + Note that this option is turned on by default when analyzing the + `Linux Kernel`_. Otherwise, it's turned off by default. + + * ``--allow-non-exported-interfaces`` + + When looking at the debug information accompanying a binary, this + tool analyzes the descriptions of the types reachable by the + interfaces (functions and variables) that are visible outside of + their translation unit. Once that analysis is done, an ABI corpus + is constructed by only considering the subset of types reachable + from interfaces associated to `ELF`_ symbols that are defined and + exported by the binary. It's those final ABI Corpora that are + compared by this tool. + + The problem with that approach however is that analyzing all the + interfaces that are visible from outside their translation unit + can amount to a lot of data, especially when those binaries are + applications, as opposed to shared libraries. One example of such + applications is the `Linux Kernel`_. Analyzing massive ABI + Corpora like these can be extremely slow. + + In the presence of an "average sized" binary however one can + afford having libabigail analyze all interfaces that are visible + outside of their translation unit, using this option. + + Note that this option is turned on by default, unless we are in + the presence of the `Linux Kernel`_. + * ``--stat`` Rather than displaying the detailed ABI differences between diff --git a/doc/manuals/abidw.rst b/doc/manuals/abidw.rst index bdd6204d..a3055c7e 100644 --- a/doc/manuals/abidw.rst +++ b/doc/manuals/abidw.rst @@ -12,14 +12,19 @@ defined ELF symbols of the file. The input shared library must contain associated debug information in `DWARF`_ format. When given the ``--linux-tree`` option, this program can also handle a -Linux kernel tree. That is, a directory tree that contains both the -vmlinux binary and Linux kernel modules. It analyses those Linux -kernel binaries and emits an XML representation of the interface -between the kernel and its module, to standard output. In this case, -we don't call it an ABI, but a KMI (Kernel Module Interface). The -emitted KMI includes all the globally defined functions and variables, -along with a complete representation of their types. The input -binaries must contain associated debug information in `DWARF`_ format. +`Linux kernel`_ tree. That is, a directory tree that contains both +the vmlinux binary and `Linux Kernel`_ modules. It analyses those +`Linux Kernel`_ binaries and emits an XML representation of the +interface between the kernel and its module, to standard output. In +this case, we don't call it an ABI, but a KMI (Kernel Module +Interface). The emitted KMI includes all the globally defined +functions and variables, along with a complete representation of their +types. The input binaries must contain associated debug information +in `DWARF`_ format. + +.. include:: tools-use-libabigail.txt + +.. _abidiff_invocation_label: Invocation ========== @@ -92,7 +97,7 @@ Options * ``--kmi-whitelist | -kaw`` <*path-to-whitelist*> - When analyzing a Linux kernel binary, this option points to the + When analyzing a `Linux Kernel`_ binary, this option points to the white list of names of ELF symbols of functions and variables which ABI must be written out. That white list is called a " Kernel Module Interface white list". This is because for the @@ -105,7 +110,7 @@ Options If this option is not provided -- thus if no white list is provided -- then the entire KMI, that is, all publicly defined and - exported functions and global variables by the Linux Kernel + exported functions and global variables by the `Linux Kernel`_ binaries is emitted. * ``--linux-tree | --lt`` @@ -115,9 +120,10 @@ Options In that case, this program emits the representation of the Kernel Module Interface (KMI) on the standard output. - Below is an example of usage of ``abidw`` on a Linux Kernel tree. + Below is an example of usage of ``abidw`` on a `Linux Kernel`_ + tree. - First, checkout a Linux kernel source tree and build it. Then + First, checkout a `Linux Kernel`_ source tree and build it. Then install the kernel modules in a directory somewhere. Copy the vmlinux binary into that directory too. And then serialize the KMI of that kernel to disk, using ``abidw``: :: @@ -171,6 +177,56 @@ Options representation build by Libabigail to represent the ABI and will not end up in the abi XML file. + * ``--exported-interfaces-only`` + + By default, when looking at the debug information accompanying a + binary, this tool analyzes the descriptions of the types reachable + by the interfaces (functions and variables) that are visible + outside of their translation unit. Once that analysis is done, an + ABI corpus is constructed by only considering the subset of types + reachable from interfaces associated to `ELF`_ symbols that are + defined and exported by the binary. It's that final ABI corpus + which textual representation is saved as ``ABIXML``. + + The problem with that approach however is that analyzing all the + interfaces that are visible from outside their translation unit + can amount to a lot of data, especially when those binaries are + applications, as opposed to shared libraries. One example of such + applications is the `Linux Kernel`_. Analyzing massive ABI + corpora like these can be extremely slow. + + To mitigate that performance issue, this option allows libabigail + to only analyze types that are reachable from interfaces + associated with defined and exported `ELF`_ symbols. + + Note that this option is turned on by default when analyzing the + `Linux Kernel`_. Otherwise, it's turned off by default. + + * ``--allow-non-exported-interfaces`` + + When looking at the debug information accompanying a binary, this + tool analyzes the descriptions of the types reachable by the + interfaces (functions and variables) that are visible outside of + their translation unit. Once that analysis is done, an ABI corpus + is constructed by only considering the subset of types reachable + from interfaces associated to `ELF`_ symbols that are defined and + exported by the binary. It's that final ABI corpus which textual + representation is saved as ``ABIXML``. + + The problem with that approach however is that analyzing all the + interfaces that are visible from outside their translation unit + can amount to a lot of data, especially when those binaries are + applications, as opposed to shared libraries. One example of such + applications is the `Linux Kernel`_. Analyzing massive ABI + corpora like these can be extremely slow. + + In the presence of an "average sized" binary however one can + afford having libabigail analyze all interfaces that are visible + outside of their translation unit, using this option. + + Note that this option is turned on by default, unless we are in + the presence of the `Linux Kernel`_. + * ``--no-linux-kernel-mode`` Without this option, if abipkgiff detects that the binaries it is @@ -308,4 +364,4 @@ standard `here .. _ELF: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format .. _DWARF: http://www.dwarfstd.org .. _GNU: http://www.gnu.org - +.. _Linux Kernel: https://kernel.org/ diff --git a/doc/manuals/abipkgdiff.rst b/doc/manuals/abipkgdiff.rst index 15ea9072..9114775a 100644 --- a/doc/manuals/abipkgdiff.rst +++ b/doc/manuals/abipkgdiff.rst @@ -19,6 +19,7 @@ information directly in a section of said binaries. In those cases, obviously, no separate debug information package is needed as the tool will find the debug information inside the binaries. +.. include:: tools-use-libabigail.txt .. _abipkgdiff_invocation_label: @@ -277,6 +278,56 @@ Options global functions and variables are analyzed, so the tool detects and reports changes on these reachable types only. + * ``--exported-interfaces-only`` + + By default, when looking at the debug information accompanying a + binary, this tool analyzes the descriptions of the types reachable + by the interfaces (functions and variables) that are visible + outside of their translation unit. Once that analysis is done, an + ABI corpus is constructed by only considering the subset of types + reachable from interfaces associated to `ELF`_ symbols that are + defined and exported by the binary. It's those final ABI Corpora + that are compared by this tool. + + The problem with that approach however is that analyzing all the + interfaces that are visible from outside their translation unit + can amount to a lot of data, especially when those binaries are + applications, as opposed to shared libraries. One example of such + applications is the `Linux Kernel`_. Analyzing massive ABI + corpora like these can be extremely slow. + + To mitigate that performance issue, this option allows libabigail + to only analyze types that are reachable from interfaces + associated with defined and exported `ELF`_ symbols. + + Note that this option is turned on by default when analyzing the + `Linux Kernel`_. Otherwise, it's turned off by default. + + * ``--allow-non-exported-interfaces`` + + When looking at the debug information accompanying a binary, this + tool analyzes the descriptions of the types reachable by the + interfaces (functions and variables) that are visible outside of + their translation unit. Once that analysis is done, an ABI corpus + is constructed by only considering the subset of types reachable + from interfaces associated to `ELF`_ symbols that are defined and + exported by the binary. It's those final ABI Corpora that are + compared by this tool. + + The problem with that approach however is that analyzing all the + interfaces that are visible from outside their translation unit + can amount to a lot of data, especially when those binaries are + applications, as opposed to shared libraries. One example of such + applications is the `Linux Kernel`_. Analyzing massive ABI + Corpora like these can be extremely slow. + + In the presence of an "average sized" binary however one can + afford having libabigail analyze all interfaces that are visible + outside of their translation unit, using this option. + + Note that this option is turned on by default, unless we are in + the presence of the `Linux Kernel`_. + * ``--redundant`` In the diff reports, do display redundant changes. A redundant diff --git a/doc/manuals/kmidiff.rst b/doc/manuals/kmidiff.rst index ce8168ae..53010189 100644 --- a/doc/manuals/kmidiff.rst +++ b/doc/manuals/kmidiff.rst @@ -55,6 +55,10 @@ command line looks like: :: linux/v4.5/build/modules \ linux/v4.6/build/modules + +.. include:: tools-use-libabigail.txt + + Invocation ========== @@ -67,8 +71,8 @@ Environment By default, ``kmidiff`` compares all the interfaces (exported functions and variables) between the Kernel and its modules. In -practice, though, users want to compare a subset of the those -interfaces. +practice, though, some users might want to compare a subset of the +those interfaces. Users can then define a "white list" of the interfaces to compare. Such a white list is a just a file in the "INI" format that looks @@ -91,8 +95,11 @@ function or variable. Only those interfaces along with the types reachable from their signatures are going to be compared by ``kmidiff`` recursively. -Note that kmidiff compares the interfaces exported by the ``vmlinux`` -binary and by the all of the compiled modules. +Note that by default kmidiff analyzes the types reachable from the +interfaces associated with `ELF`_ symbols that are defined and +exported by the `Linux Kernel`_ as being the union of the ``vmlinux`` +binary and all its compiled modules. It then compares those +interfaces (along with their types). Options ======= @@ -180,6 +187,38 @@ Options exported interfaces. This is the default kind of report emitted by tools like ``abidiff`` or ``abipkgdiff``. + * ``--exported-interfaces-only`` + + When using this option, this tool analyzes the descriptions of the + types reachable by the interfaces (functions and variables) + associated with `ELF`_ symbols that are defined and exported by + the `Linux Kernel`_. + + Otherwise, the tool also has the ability to analyze the + descriptions of the types reachable by the interfaces associated + with `ELF`_ symbols that are visible outside their translation + unit. This later possibility is however much more resource + intensive and results in much slower operations. + + That is why this option is enabled by default. + + + * ``--allow-non-exported-interfaces`` + + When using this option, this tool analyzes the descriptions of the + types reachable by the interfaces (functions and variables) that + are visible outside of their translation unit. Once that analysis + is done, an ABI Corpus is constructed by only considering the + subset of types reachable from interfaces associated to `ELF`_ + symbols that are defined and exported by the binary. It's that + final ABI corpus which is compared against another one. + + The problem with that approach however is that analyzing all the + interfaces that are visible from outside their translation unit + can amount to a lot of data, leading to very slow operations. + + Note that this option is turned off by default. + * ``--show-bytes`` Show sizes and offsets in bytes, not bits. This option is @@ -198,3 +237,8 @@ Options * ``--show-dec`` Show sizes and offsets in decimal base. + + +.. _ELF: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format +.. _ksymtab: http://en.wikipedia.org/wiki/Executable_and_Linkable_Format +.. _Linux Kernel: https://kernel.org diff --git a/doc/manuals/tools-use-libabigail.txt b/doc/manuals/tools-use-libabigail.txt new file mode 100644 index 00000000..43edf296 --- /dev/null +++ b/doc/manuals/tools-use-libabigail.txt @@ -0,0 +1,16 @@ +This tool uses the libabigail library to analyze the binary as well as its +associated debug information. Here is its general mode of operation. + +When instructed to do so, a binary and its associated debug +information is read and analyzed. To that effect, libabigail analyzes +by default the descriptions of the types reachable by the interfaces +(functions and variables) that are visible outside of their +translation unit. Once that analysis is done, an Application Binary +Interface Corpus is constructed by only considering the subset of +types reachable from interfaces associated to `ELF`_ symbols that are +defined and exported by the binary. It's that final ABI corpus which +libabigail considers as representing the ABI of the analyzed binary. + +Libabigail then has capabilities to generate textual representations +of ABI Corpora, compare them, analyze their changes and report about +them. diff --git a/include/abg-ir.h b/include/abg-ir.h index a857d041..61338edb 100644 --- a/include/abg-ir.h +++ b/include/abg-ir.h @@ -197,6 +197,15 @@ public: const config& get_config() const; + bool + user_set_analyze_exported_interfaces_only() const; + + void + analyze_exported_interfaces_only(bool f); + + bool + analyze_exported_interfaces_only() const; + #ifdef WITH_DEBUG_SELF_COMPARISON void set_self_comparison_debug_input(const corpus_sptr& corpus); diff --git a/src/abg-dwarf-reader.cc b/src/abg-dwarf-reader.cc index f1b1cf55..09e0704a 100644 --- a/src/abg-dwarf-reader.cc +++ b/src/abg-dwarf-reader.cc @@ -402,6 +402,12 @@ die_is_decl(const Dwarf_Die* die); static bool die_is_declaration_only(Dwarf_Die* die); +static bool +die_is_variable_decl(const Dwarf_Die *die); + +static bool +die_is_function_decl(const Dwarf_Die *die); + static bool die_has_size_attribute(const Dwarf_Die *die); @@ -5303,6 +5309,44 @@ public: return symbol; } + /// Test if a DIE represents a decl (function or variable) that has + /// a symbol that is exported, whatever that means. This is + /// supposed to work for Linux Kernel binaries as well. + /// + /// This is useful to limit the amount of DIEs taken into account to + /// the strict limit of what an ABI actually means. Limiting the + /// volume of DIEs analyzed this way is an important optimization to + /// keep big binaries "manageable" by libabigail. + /// + /// @param DIE the die to consider. + bool + is_decl_die_with_exported_symbol(const Dwarf_Die *die) + { + if (!die || !die_is_decl(die)) + return false; + + bool result = false, address_found = false, symbol_is_exported = false;; + Dwarf_Addr decl_symbol_address = 0; + + if (die_is_variable_decl(die)) + { + if ((address_found = get_variable_address(die, decl_symbol_address))) + symbol_is_exported = + !!variable_symbol_is_exported(decl_symbol_address); + } + else if (die_is_function_decl(die)) + { + if ((address_found = get_function_address(die, decl_symbol_address))) + symbol_is_exported = + !!function_symbol_is_exported(decl_symbol_address); + } + + if (address_found) + result = symbol_is_exported; + + return result; + } + /// Getter for the symtab reader. Will load the symtab from the elf handle if /// not yet set. /// @@ -5580,16 +5624,18 @@ public: /// /// @return true if the function address was found. bool - get_function_address(Dwarf_Die* function_die, Dwarf_Addr& address) const + get_function_address(const Dwarf_Die* function_die, Dwarf_Addr& address) const { - if (!die_address_attribute(function_die, DW_AT_low_pc, address)) + if (!die_address_attribute(const_cast(function_die), + DW_AT_low_pc, address)) // So no DW_AT_low_pc was found. Let's see if the function DIE // has got a DW_AT_ranges attribute instead. If it does, the // first address of the set of addresses represented by the // value of that DW_AT_ranges represents the function (symbol) // address we are looking for. - if (!get_first_exported_fn_address_from_DW_AT_ranges(function_die, - address)) + if (!get_first_exported_fn_address_from_DW_AT_ranges + (const_cast(function_die), + address)) return false; address = maybe_adjust_fn_sym_address(address); @@ -5611,11 +5657,12 @@ public: /// /// @return true if the variable address was found. bool - get_variable_address(Dwarf_Die* variable_die, + get_variable_address(const Dwarf_Die* variable_die, Dwarf_Addr& address) const { bool is_tls_address = false; - if (!die_location_address(variable_die, address, is_tls_address)) + if (!die_location_address(const_cast(variable_die), + address, is_tls_address)) return false; if (!is_tls_address) address = maybe_adjust_var_sym_address(address); @@ -7155,6 +7202,40 @@ die_is_declaration_only(Dwarf_Die* die) return false; } +/// Test if a DIE is for a function decl. +/// +/// @param die the DIE to consider. +/// +/// @return true iff @p die represents a function decl. +static bool +die_is_function_decl(const Dwarf_Die *die) +{ + if (!die) + return false; + + int tag = dwarf_tag(const_cast(die)); + if (tag == DW_TAG_subprogram) + return true; + return false; +} + +/// Test if a DIE is for a variable decl. +/// +/// @param die the DIE to consider. +/// +/// @return true iff @p die represents a variable decl. +static bool +die_is_variable_decl(const Dwarf_Die *die) +{ + if (!die) + return false; + + int tag = dwarf_tag(const_cast(die)); + if (tag == DW_TAG_variable) + return true; + return false; +} + /// Test if a DIE has size attribute. /// /// @param die the DIE to consider. @@ -12696,9 +12777,13 @@ build_translation_unit_and_add_to_ir(read_context& ctxt, result->set_is_constructed(false); do - build_ir_node_from_die(ctxt, &child, - die_is_public_decl(&child), - dwarf_dieoffset(&child)); + // Analyze all the DIEs we encounter unless we are asked to only + // analyze exported interfaces and the types reachables from them. + if (!ctxt.env()->analyze_exported_interfaces_only() + || ctxt.is_decl_die_with_exported_symbol(&child)) + build_ir_node_from_die(ctxt, &child, + die_is_public_decl(&child), + dwarf_dieoffset(&child)); while (dwarf_siblingof(&child, &child) == 0); if (!ctxt.var_decls_to_re_add_to_tree().empty()) @@ -15705,6 +15790,16 @@ read_debug_info_into_corpus(read_context& ctxt) origin |= corpus::LINUX_KERNEL_BINARY_ORIGIN; ctxt.current_corpus()->set_origin(origin); + if (origin & corpus::LINUX_KERNEL_BINARY_ORIGIN + && !ctxt.env()->user_set_analyze_exported_interfaces_only()) + // So we are looking at the Linux Kernel and the user has not set + // any particular option regarding the amount of types to analyse. + // In that case, we need to only analyze types that are reachable + // from exported interfaces otherwise we get such a massive amount + // of type DIEs to look at that things are just too slow down the + // road. + ctxt.env()->analyze_exported_interfaces_only(true); + ctxt.current_corpus()->set_soname(ctxt.dt_soname()); ctxt.current_corpus()->set_needed(ctxt.dt_needed()); ctxt.current_corpus()->set_architecture_name(ctxt.elf_architecture()); diff --git a/src/abg-ir-priv.h b/src/abg-ir-priv.h index 45b711b7..21734b25 100644 --- a/src/abg-ir-priv.h +++ b/src/abg-ir-priv.h @@ -26,6 +26,7 @@ namespace ir { using std::string; +using abg_compat::optional; /// The result of structural comparison of type ABI artifacts. enum comparison_result @@ -443,6 +444,7 @@ struct environment::priv bool decl_only_class_equals_definition_; bool use_enum_binary_only_equality_; bool allow_type_comparison_results_caching_; + optional analyze_exported_interfaces_only_; #ifdef WITH_DEBUG_SELF_COMPARISON bool self_comparison_debug_on_; #endif diff --git a/src/abg-ir.cc b/src/abg-ir.cc index b3bec8fa..42442791 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -3674,6 +3674,42 @@ const config& environment::get_config() const {return priv_->config_;} +/// Getter for a property that says if the user actually did set the +/// analyze_exported_interfaces_only() property. If not, it means +/// the default behaviour prevails. +/// +/// @return tru iff the user did set the +/// analyze_exported_interfaces_only() property. +bool +environment::user_set_analyze_exported_interfaces_only() const +{return priv_->analyze_exported_interfaces_only_.has_value();} + +/// Setter for the property that controls if we are to restrict the +/// analysis to the types that are only reachable from the exported +/// interfaces only, or if the set of types should be more broad than +/// that. Typically, we'd restrict the analysis to types reachable +/// from exported interfaces only (stricto sensu, that would really be +/// only the types that are part of the ABI of well designed +/// libraries) for performance reasons. +/// +/// @param f the value of the flag. +void +environment::analyze_exported_interfaces_only(bool f) +{priv_->analyze_exported_interfaces_only_ = f;} + +/// Getter for the property that controls if we are to restrict the +/// analysis to the types that are only reachable from the exported +/// interfaces only, or if the set of types should be more broad than +/// that. Typically, we'd restrict the analysis to types reachable +/// from exported interfaces only (stricto sensu, that would really be +/// only the types that are part of the ABI of well designed +/// libraries) for performance reasons. +/// +/// @param f the value of the flag. +bool +environment::analyze_exported_interfaces_only() const +{return priv_->analyze_exported_interfaces_only_.value_or(false);} + #ifdef WITH_DEBUG_SELF_COMPARISON /// Setter of the corpus of the input corpus of the self comparison /// that takes place when doing "abidw --debug-abidiff ". diff --git a/tools/abidiff.cc b/tools/abidiff.cc index 97b036cb..e0bb35ac 100644 --- a/tools/abidiff.cc +++ b/tools/abidiff.cc @@ -29,6 +29,7 @@ using std::ostream; using std::cout; using std::cerr; using std::shared_ptr; +using abg_compat::optional; using abigail::ir::environment; using abigail::ir::environment_sptr; using abigail::translation_unit; @@ -74,6 +75,7 @@ struct options vector headers_dirs2; vector header_files2; bool drop_private_types; + optional exported_interfaces_only; bool linux_kernel_mode; bool no_default_supprs; bool no_arch; @@ -197,6 +199,9 @@ display_usage(const string& prog_name, ostream& out) << " --header-file2|--hf2 the path to one header of file2\n" << " --drop-private-types drop private types from " "internal representation\n" + << " --exported-interfaces-only analyze exported interfaces only\n" + << " --allow-non-exported-interfaces analyze interfaces that " + "might not be exported\n" << " --no-linux-kernel-mode don't consider the input binaries as " "linux kernel binaries\n" << " --kmi-whitelist|-w path to a " @@ -403,6 +408,10 @@ parse_command_line(int argc, char* argv[], options& opts) } else if (!strcmp(argv[i], "--drop-private-types")) opts.drop_private_types = true; + else if (!strcmp(argv[i], "--exported-interfaces-only")) + opts.exported_interfaces_only = true; + else if (!strcmp(argv[i], "--allow-non-exported-interfaces")) + opts.exported_interfaces_only = false; else if (!strcmp(argv[i], "--no-default-suppression")) opts.no_default_supprs = true; else if (!strcmp(argv[i], "--no-architecture")) @@ -1130,6 +1139,9 @@ main(int argc, char* argv[]) t2_type = guess_file_type(opts.file2); environment_sptr env(new environment); + if (opts.exported_interfaces_only.has_value()) + env->analyze_exported_interfaces_only(*opts.exported_interfaces_only); + #ifdef WITH_DEBUG_SELF_COMPARISON if (opts.do_debug) env->self_comparison_debug_is_on(true); diff --git a/tools/abidw.cc b/tools/abidw.cc index 9a27a029..f38d6048 100644 --- a/tools/abidw.cc +++ b/tools/abidw.cc @@ -40,6 +40,7 @@ using std::ostream; using std::ofstream; using std::vector; using std::shared_ptr; +using abg_compat::optional; using abigail::tools_utils::emit_prefix; using abigail::tools_utils::temp_file; using abigail::tools_utils::temp_file_sptr; @@ -114,6 +115,7 @@ struct options bool do_log; bool drop_private_types; bool drop_undefined_syms; + optional exported_interfaces_only; type_id_style_kind type_id_style; #ifdef WITH_DEBUG_SELF_COMPARISON string type_id_file_path; @@ -187,6 +189,9 @@ display_usage(const string& prog_name, ostream& out) << " --short-locs only print filenames rather than paths\n" << " --drop-private-types drop private types from representation\n" << " --drop-undefined-syms drop undefined symbols from representation\n" + << " --exported-interfaces-only analyze exported interfaces only\n" + << " --allow-non-exported-interfaces analyze interfaces that " + "might not be exported\n" << " --no-comp-dir-path do not show compilation path information\n" << " --no-elf-needed do not show the DT_NEEDED information\n" << " --no-write-default-sizes do not emit pointer size when it equals" @@ -368,6 +373,10 @@ parse_command_line(int argc, char* argv[], options& opts) opts.drop_private_types = true; else if (!strcmp(argv[i], "--drop-undefined-syms")) opts.drop_undefined_syms = true; + else if (!strcmp(argv[i], "--exported-interfaces-only")) + opts.exported_interfaces_only = true; + else if (!strcmp(argv[i], "--allow-non-exported-interfaces")) + opts.exported_interfaces_only = false; else if (!strcmp(argv[i], "--no-linux-kernel-mode")) opts.linux_kernel_mode = false; else if (!strcmp(argv[i], "--abidiff")) @@ -606,6 +615,9 @@ load_corpus_and_write_abixml(char* argv[], } } + if (opts.exported_interfaces_only.has_value()) + env->analyze_exported_interfaces_only(*opts.exported_interfaces_only); + t.start(); corp = dwarf_reader::read_corpus_from_elf(ctxt, s); t.stop(); @@ -813,6 +825,9 @@ load_kernel_corpus_group_and_write_abixml(char* argv[], timer t, global_timer; suppressions_type supprs; + if (opts.exported_interfaces_only.has_value()) + env->analyze_exported_interfaces_only(*opts.exported_interfaces_only); + if (opts.do_log) emit_prefix(argv[0], cerr) << "going to build ABI representation of the Linux Kernel ...\n"; diff --git a/tools/abipkgdiff.cc b/tools/abipkgdiff.cc index 551080b9..656d5882 100644 --- a/tools/abipkgdiff.cc +++ b/tools/abipkgdiff.cc @@ -106,6 +106,7 @@ using std::set; using std::ostringstream; using std::shared_ptr; using std::dynamic_pointer_cast; +using abg_compat::optional; using abigail::workers::task; using abigail::workers::task_sptr; using abigail::workers::queue; @@ -205,6 +206,7 @@ public: bool fail_if_no_debug_info; bool show_identical_binaries; bool self_check; + optional exported_interfaces_only; #ifdef WITH_CTF bool use_ctf; #endif @@ -868,6 +870,9 @@ display_usage(const string& prog_name, ostream& out) "full impact analysis report rather than the default leaf changes reports\n" << " --non-reachable-types|-t consider types non reachable" " from public interfaces\n" + << " --exported-interfaces-only analyze exported interfaces only\n" + << " --allow-non-exported-interfaces analyze interfaces that " + "might not be exported\n" << " --no-linkage-name do not display linkage names of " "added/removed/changed\n" << " --redundant display redundant changes\n" @@ -2076,6 +2081,10 @@ public: abigail::elf_reader::status detailed_status = abigail::elf_reader::STATUS_UNKNOWN; + if (args->opts.exported_interfaces_only.has_value()) + env->analyze_exported_interfaces_only + (*args->opts.exported_interfaces_only); + status |= compare(args->elf1, args->debug_dir1, args->private_types_suppr1, args->elf2, args->debug_dir2, args->private_types_suppr2, args->opts, env, diff, ctxt, &detailed_status); @@ -2142,6 +2151,10 @@ public: diff_context_sptr ctxt; corpus_diff_sptr diff; + if (args->opts.exported_interfaces_only.has_value()) + env->analyze_exported_interfaces_only + (*args->opts.exported_interfaces_only); + abigail::elf_reader::status detailed_status = abigail::elf_reader::STATUS_UNKNOWN; @@ -3024,6 +3037,10 @@ compare_prepared_linux_kernel_packages(package& first_package, string dist_root2 = second_package.extracted_dir_path(); abigail::ir::environment_sptr env(new abigail::ir::environment); + if (opts.exported_interfaces_only.has_value()) + env->analyze_exported_interfaces_only + (*opts.exported_interfaces_only); + suppressions_type supprs; corpus_group_sptr corpus1, corpus2; corpus1 = build_corpus_group_from_kernel_dist_under(dist_root1, @@ -3326,6 +3343,10 @@ parse_command_line(int argc, char* argv[], options& opts) else if (!strcmp(argv[i], "--full-impact") ||!strcmp(argv[i], "-f")) opts.show_full_impact_report = true; + else if (!strcmp(argv[i], "--exported-interfaces-only")) + opts.exported_interfaces_only = true; + else if (!strcmp(argv[i], "--allow-non-exported-interfaces")) + opts.exported_interfaces_only = false; else if (!strcmp(argv[i], "--no-linkage-name")) opts.show_linkage_names = false; else if (!strcmp(argv[i], "--redundant")) diff --git a/tools/kmidiff.cc b/tools/kmidiff.cc index 8fd3fed9..f3332765 100644 --- a/tools/kmidiff.cc +++ b/tools/kmidiff.cc @@ -29,6 +29,7 @@ using std::vector; using std::ostream; using std::cout; using std::cerr; +using abg_compat::optional; using namespace abigail::tools_utils; using namespace abigail::dwarf_reader; @@ -60,6 +61,7 @@ struct options bool show_hexadecimal_values; bool show_offsets_sizes_in_bits; bool show_impacted_interfaces; + optional exported_interfaces_only; #ifdef WITH_CTF bool use_ctf; #endif @@ -120,6 +122,9 @@ display_usage(const string& prog_name, ostream& out) << " --impacted-interfaces|-i show interfaces impacted by ABI changes\n" << " --full-impact|-f show the full impact of changes on top-most " "interfaces\n" + << " --exported-interfaces-only analyze exported interfaces only\n" + << " --allow-non-exported-interfaces analyze interfaces that " + "might not be exported\n" << " --show-bytes show size and offsets in bytes\n" << " --show-bits show size and offsets in bits\n" << " --show-hex show size and offset in hexadecimal\n" @@ -262,6 +267,10 @@ parse_command_line(int argc, char* argv[], options& opts) else if (!strcmp(argv[i], "--full-impact") || !strcmp(argv[i], "-f")) opts.leaf_changes_only = false; + else if (!strcmp(argv[i], "--exported-interfaces-only")) + opts.exported_interfaces_only = true; + else if (!strcmp(argv[i], "--allow-non-exported-interfaces")) + opts.exported_interfaces_only = false; else if (!strcmp(argv[i], "--show-bytes")) opts.show_offsets_sizes_in_bits = false; else if (!strcmp(argv[i], "--show-bits")) @@ -408,6 +417,9 @@ main(int argc, char* argv[]) environment_sptr env(new environment); + if (opts.exported_interfaces_only.has_value()) + env->analyze_exported_interfaces_only(*opts.exported_interfaces_only); + corpus_group_sptr group1, group2; string debug_info_root_dir; corpus::origin origin = From patchwork Tue Sep 20 11:30:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 57800 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 683AC3858283 for ; Tue, 20 Sep 2022 11:30:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 683AC3858283 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1663673441; bh=W3yi9PSAlI76isyCUo1EopZxFCVeuQULxcdN8dt2kT0=; h=To:Subject:References:Date:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Help:List-Subscribe:From:Reply-To:Cc:From; b=tllekKx1pChUtkGQIprlCuxQVXJYmrmn3cIejNmxn71U42omCzv0VEOP5X7Tjvexi oCJQ1GvxNekzYtzmpg/37LO8VFSpb7YRKXqqTCf9EQgBh9paUZyDDCcNv/qhEghiVO CJM4u/qcCgaCDUspWVuBGoao+VTPMKU/K0/on+i0= 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 [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 145203858D28 for ; Tue, 20 Sep 2022 11:30:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 145203858D28 Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-25-Y5LFRXA2Mz6oE6SIMNzHCw-1; Tue, 20 Sep 2022 07:30:30 -0400 X-MC-Unique: Y5LFRXA2Mz6oE6SIMNzHCw-1 Received: by mail-qk1-f198.google.com with SMTP id s17-20020a05620a255100b006c9cefbc68eso1691909qko.3 for ; Tue, 20 Sep 2022 04:30:30 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:user-agent:message-id:in-reply-to:date:references :organization:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date; bh=W3yi9PSAlI76isyCUo1EopZxFCVeuQULxcdN8dt2kT0=; b=xaSX6jnD7ah6m4Zc6EK4AJZL0F4fufKt0b5GjU8ir2GH03SpA92cU7woB7KMow6N9p P/fKatPXoBjJvENDnhZbPlt3IZ20p/Fx9XHjYng7R75LM/yRyAP2mh00g6yEcQonorgQ NPiP0wPGGeotmi5CBde4BXRqVYPxwpdz6GV9XrCOOa3IqJXM61AEBuL4gjOxjEIf8cDK Dnn+mxW89higr9LmPzquRkphHambPpl7+trJSEMyLMiSSjNbZjeI+4BgNamBOdq8JqaI NtsEKTVBRpxG2jwPorwMXkMIrC5BFzshFjhq2eONv7mkRioJYBlcftvtmOXRteMv0A87 HZ7g== X-Gm-Message-State: ACrzQf1i3I9S5B8O/bqVMpJ3KGHCxp5OoUBVZRpuGoGeca5Plk5kSi89 CqcgnbjOcUZT0LP5VjjVY29z7g9eeVMqXhQUaLuszVZR2+HYAwERFAaHma21lesjHWUxHnsymrB 49bcrovtbQbjHCrM2lYFy X-Received: by 2002:a37:63d1:0:b0:6ce:5f67:47bc with SMTP id x200-20020a3763d1000000b006ce5f6747bcmr15187182qkb.682.1663673428529; Tue, 20 Sep 2022 04:30:28 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4xGEYuv8h0+aJo0SGA6DNey7wbmD3zxfQ58FNP46X9UiXqDoRjnjVPbZB/2CLbJAyr0kzeuA== X-Received: by 2002:a37:63d1:0:b0:6ce:5f67:47bc with SMTP id x200-20020a3763d1000000b006ce5f6747bcmr15187152qkb.682.1663673427899; Tue, 20 Sep 2022 04:30:27 -0700 (PDT) Received: from localhost ([88.120.130.27]) by smtp.gmail.com with ESMTPSA id m15-20020a05620a24cf00b006b8f4ade2c9sm924136qkn.19.2022.09.20.04.30.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Sep 2022 04:30:27 -0700 (PDT) Received: by localhost (Postfix, from userid 1000) id C7CD45802BD; Tue, 20 Sep 2022 13:30:25 +0200 (CEST) To: libabigail@sourceware.org Subject: [PATCH 3/4] Fix IR comparison result caching and canonical type propagation tracking Organization: Red Hat / France References: <87tu525ngh.fsf@seketeli.org> X-Operating-System: Fedora 38 X-URL: http://www.redhat.com Date: Tue, 20 Sep 2022 13:30:25 +0200 In-Reply-To: <87tu525ngh.fsf@seketeli.org> (Dodji Seketeli's message of "Tue, 20 Sep 2022 12:50:38 +0200") Message-ID: <87czbq5lm6.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, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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 Cc: dodji@redhat.com Errors-To: libabigail-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libabigail" Hello, Caching the result of IR comparison cannot happen on IR nodes that are being compared in the context of type canonicalization if one of the nodes is the target of canonical type propagation. This is especially true if the recursive IR node which comparison "temporarily" did yield true (to avoid an infinite loop) at least until the comparison of the rest of the sub-tree of the recursive type is done. In that case, we should not cache the result the comparison as it might change later. The patch adds a way to track recursive types so that we know when not to cache their comparison result. As we now have a facility to track recursive types during canonical type propagation (rather than just types that depend on recursive types) we can be a bit more precise when confirming or cancelling types that have been subject to canonical type propagation. Also the patch cleans up the detection of comparison cycle to make it more typesafe so that the macro RETURN_TRUE_IF_COMPARISON_CYCLE_DETECTED can be used for class_decl and union_decl, not just class_or_union. It makes the code more readable/maintainable is the equals overload for class_decl and union_decl all have their proper call to RETURN_TRUE_IF_COMPARISON_CYCLE_DETECTED. The same is true for mark_types_as_being_compared. Doing that cleans up the detection of recursive types as well as the types that depends on those recursive types. * src/abg-ir-priv.h (environment::priv::recursive_types_): Define new data member. (environment::priv::cache_type_comparison_result): Cache results only non-recursive and not dependant types, or when the result is "false". In all these cases, the result, once cached, will not change. (environment::priv::mark_dependant_types_compared_until): Mark types as recursive at the same time others are marked as dependant. (environment::priv::{is_recursive_type, set_is_not_recursive}): Define new member functions. (environment::priv::{confirm_ct_propagation, cancel_ct_propagation}): Confirming canonical type propagation should happen for recursive types as well as their dependant types. * src/abg-ir.cc (return_comparison_result): Keep up with the book-keeping at all time when type canonicalization process is on-going. Whenever we expect types that depends on recursive types, expect recursive types too, obviously. (type_base::get_canonical_type_for): Do not erase the comparison result cache between the canonicalization of two different types. (is_comparison_cycle_detected) (mark_types_as_being_compared, unmark_types_as_being_compared): Define new overloads for class_decl; (equals): In the overloads for class_decl and union_decl, use RETURN_COMPARISON_RESULT and mark_types_as_being_compared without casting it to class_or_union. * tests/data/test-abidiff/test-PR18791-report0.txt: Adjust. * tests/data/test-diff-dwarf/PR25058-liblttng-ctl-report-1.txt: Adjust. * tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt: Adjust. * tests/data/test-diff-pkg/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-report-2.txt: Adjust. * tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt: Adjust. * tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt: Adjust. Signed-off-by: Dodji Seketeli --- src/abg-ir-priv.h | 46 +++- src/abg-ir.cc | 96 ++++++-- .../test-abidiff/test-PR18791-report0.txt | 225 +++--------------- .../PR25058-liblttng-ctl-report-1.txt | 7 +- .../nss-3.23.0-1.0.fc23.x86_64-report-0.txt | 6 +- ...l7.x86_64-0.12.8-1.el7.x86_64-report-2.txt | 82 ++++++- ...bb-4.3-3.20141204.fc23.x86_64-report-0.txt | 47 +--- ...bb-4.3-3.20141204.fc23.x86_64-report-1.txt | 13 +- 8 files changed, 251 insertions(+), 271 deletions(-) diff --git a/src/abg-ir-priv.h b/src/abg-ir-priv.h index 21734b25..b6f9354e 100644 --- a/src/abg-ir-priv.h +++ b/src/abg-ir-priv.h @@ -419,6 +419,7 @@ struct environment::priv // the canonical type propagation is cancelled, the canonical types // must be cleared. pointer_set types_with_non_confirmed_propagated_ct_; + pointer_set recursive_types_; #ifdef WITH_DEBUG_SELF_COMPARISON // This is used for debugging purposes. // When abidw is used with the option --debug-abidiff, some @@ -518,11 +519,19 @@ struct environment::priv void cache_type_comparison_result(T& first, T& second, bool r) { - if (allow_type_comparison_results_caching()) - type_comparison_results_cache_.emplace - (std::make_pair(reinterpret_cast(&first), - reinterpret_cast(&second)), - r); + if (allow_type_comparison_results_caching() + && (r == false + || + (!is_recursive_type(&first) + && !is_recursive_type(&second) + && !is_type(&first)->priv_->depends_on_recursive_type() + && !is_type(&second)->priv_->depends_on_recursive_type()))) + { + type_comparison_results_cache_.emplace + (std::make_pair(reinterpret_cast(&first), + reinterpret_cast(&second)), + r); + } } /// Retrieve the result of comparing two sub-types from the cache, @@ -749,9 +758,30 @@ struct environment::priv result |= mark_dependant_types(right, right_type_comp_operands_); + recursive_types_.insert(reinterpret_cast(right)); return result; } + /// Test if a type is a recursive one. + /// + /// @param t the type to consider. + /// + /// @return true iff @p t is recursive. + bool + is_recursive_type(const type_base* t) + { + return (recursive_types_.find(reinterpret_cast(t)) + != recursive_types_.end()); + } + + + /// Unflag a type as being recursive + /// + /// @param t the type to unflag + void + set_is_not_recursive(const type_base* t) + {recursive_types_.erase(reinterpret_cast(t));} + /// Propagate the canonical type of a type to another one. /// /// @param src the type to propagate the canonical type from. @@ -786,7 +816,8 @@ struct environment::priv for (auto i : types_with_non_confirmed_propagated_ct_) { type_base *t = reinterpret_cast(i); - ABG_ASSERT(t->priv_->depends_on_recursive_type()); + ABG_ASSERT(t->get_environment()->priv_->is_recursive_type(t) + || t->priv_->depends_on_recursive_type()); t->priv_->set_does_not_depend_on_recursive_type(dependant_type); if (!t->priv_->depends_on_recursive_type()) to_remove.insert(i); @@ -858,7 +889,8 @@ struct environment::priv for (auto i : to_remove) { type_base *t = reinterpret_cast(i); - ABG_ASSERT(t->priv_->depends_on_recursive_type()); + ABG_ASSERT(t->get_environment()->priv_->is_recursive_type(t) + || t->priv_->depends_on_recursive_type()); type_base_sptr canonical = t->priv_->canonical_type.lock(); if (canonical) { diff --git a/src/abg-ir.cc b/src/abg-ir.cc index 42442791..905d1b43 100644 --- a/src/abg-ir.cc +++ b/src/abg-ir.cc @@ -382,7 +382,9 @@ bool mark_dependant_types_compared_until(const type_base &r) { const environment * env = r.get_environment(); - return env->priv_->mark_dependant_types_compared_until(&r); + if (env->do_on_the_fly_canonicalization()) + return env->priv_->mark_dependant_types_compared_until(&r); + return false; } /// @brief the location of a token represented in its simplest form. @@ -920,6 +922,22 @@ is_comparison_cycle_detected(T& l, T& r) return result ; } +/// Detect if a recursive comparison cycle is detected while +/// structurally comparing two @ref class_decl types. +/// +/// @param l the left-hand-side operand of the current comparison. +/// +/// @param r the right-hand-side operand of the current comparison. +/// +/// @return true iff a comparison cycle is detected. +template<> +bool +is_comparison_cycle_detected(const class_decl& l, const class_decl& r) +{ + return is_comparison_cycle_detected(static_cast(l), + static_cast(r)); +} + /// This macro is to be used while comparing composite types that /// might recursively refer to themselves. Comparing two such types /// might get us into a cyle. @@ -968,6 +986,22 @@ mark_types_as_being_compared(T& l, T&r) push_composite_type_comparison_operands(l, r); } +/// Mark a pair of @ref class_decl types as being compared. +/// +/// This is helpful to later detect recursive cycles in the comparison +/// stack. +/// +/// @param l the left-hand-side operand of the comparison. +/// +/// @parm r the right-hand-side operand of the comparison. +template<> +void +mark_types_as_being_compared(const class_decl& l, const class_decl &r) +{ + return mark_types_as_being_compared(static_cast(l), + static_cast(r)); +} + /// Mark a pair of types as being not compared anymore. /// /// This is helpful to later detect recursive cycles in the comparison @@ -987,6 +1021,26 @@ unmark_types_as_being_compared(T& l, T&r) pop_composite_type_comparison_operands(l, r); } +/// Mark a pair of @ref class_decl types as being not compared +/// anymore. +/// +/// This is helpful to later detect recursive cycles in the comparison +/// stack. +/// +/// Note that the types must have been passed to +/// mark_types_as_being_compared prior to calling this function. +/// +/// @param l the left-hand-side operand of the comparison. +/// +/// @parm r the right-hand-side operand of the comparison. +template<> +void +unmark_types_as_being_compared(const class_decl& l, const class_decl &r) +{ + return unmark_types_as_being_compared(static_cast(l), + static_cast(r)); +} + /// Return the result of the comparison of two (sub) types. /// /// The function does the necessary book keeping before returning the @@ -1020,7 +1074,7 @@ return_comparison_result(T& l, T& r, bool value, unmark_types_as_being_compared(l, r); const environment* env = l.get_environment(); - if (propagate_canonical_type && env->do_on_the_fly_canonicalization()) + if (env->do_on_the_fly_canonicalization()) // We are instructed to perform the "canonical type propagation" // optimization, making 'r' to possibly get the canonical type of // 'l' if it has one. This mostly means that we are currently @@ -1028,8 +1082,8 @@ return_comparison_result(T& l, T& r, bool value, // the 'r' argument. { if (value == true - && is_type(&r)->priv_->depends_on_recursive_type() - && !env->priv_->right_type_comp_operands_.empty() + && (is_type(&r)->priv_->depends_on_recursive_type() + || env->priv_->is_recursive_type(&r)) && is_type(&r)->priv_->canonical_type_propagated()) { // Track the object 'r' for which the propagated canonical @@ -1048,10 +1102,12 @@ return_comparison_result(T& l, T& r, bool value, // sub-types that were compared during the comparison of // 'r'. env->priv_->confirm_ct_propagation(&r); - if (is_type(&r)->priv_->depends_on_recursive_type()) + if (is_type(&r)->priv_->depends_on_recursive_type() + || env->priv_->is_recursive_type(&r)) { is_type(&r)->priv_->set_does_not_depend_on_recursive_type(); env->priv_->remove_from_types_with_non_confirmed_propagated_ct(&r); + env->priv_->set_is_not_recursive(&r); } } else if (value == false) @@ -1062,7 +1118,8 @@ return_comparison_result(T& l, T& r, bool value, // should see their tentatively propagated canonical type // cancelled. env->priv_->cancel_ct_propagation(&r); - if (is_type(&r)->priv_->depends_on_recursive_type()) + if (is_type(&r)->priv_->depends_on_recursive_type() + || env->priv_->is_recursive_type(&r)) { // The right-hand-side operand cannot carry any tentative // canonical type at this point. @@ -14051,10 +14108,10 @@ compare_types_during_canonicalization(const type_base_sptr& canonical_type, 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; + env->priv_->use_canonical_type_comparison_ = true; + canonical_equality = canonical_type == candidate_type; if (canonical_equality != structural_equality) { std::cerr << "structural & canonical equality different for type: " @@ -14208,7 +14265,6 @@ type_base::get_canonical_type_for(type_base_sptr t) // the decl-only-class-being-equal-to-a-matching-definition // flags. env->priv_->allow_type_comparison_results_caching(false); - env->priv_->clear_type_comparison_results_cache(); env->do_on_the_fly_canonicalization(false); env->decl_only_class_equals_definition (saved_decl_only_class_equals_definition); @@ -23626,8 +23682,7 @@ equals(const class_decl& l, const class_decl& r, change_kind* k) static_cast(r), k)); - RETURN_TRUE_IF_COMPARISON_CYCLE_DETECTED(static_cast(l), - static_cast(r)); + RETURN_TRUE_IF_COMPARISON_CYCLE_DETECTED(l, r); bool had_canonical_type = !!r.get_naked_canonical_type(); bool result = true; @@ -23640,13 +23695,9 @@ equals(const class_decl& l, const class_decl& r, change_kind* k) ABG_RETURN(result); } - mark_types_as_being_compared(static_cast(l), - static_cast(r)); + mark_types_as_being_compared(l, r); -#define RETURN(value) \ - return return_comparison_result(static_cast(l), \ - static_cast(r), \ - value); +#define RETURN(value) return return_comparison_result(l, r, value); // If comparing the class_or_union 'part' of the type led to // canonical type propagation, then cancel that because it's too @@ -24768,10 +24819,19 @@ union_decl::~union_decl() bool equals(const union_decl& l, const union_decl& r, change_kind* k) { + + RETURN_TRUE_IF_COMPARISON_CYCLE_DETECTED(l, r); + +#define RETURN(value) \ + return return_comparison_result(l, r, value); + bool result = equals(static_cast(l), static_cast(r), k); - ABG_RETURN(result); + + mark_types_as_being_compared(l, r); + + RETURN(result); } /// Copy a method of a @ref union_decl into a new @ref diff --git a/tests/data/test-abidiff/test-PR18791-report0.txt b/tests/data/test-abidiff/test-PR18791-report0.txt index 367929c7..9cefdfc2 100644 --- a/tests/data/test-abidiff/test-PR18791-report0.txt +++ b/tests/data/test-abidiff/test-PR18791-report0.txt @@ -1,4 +1,4 @@ -Functions changes summary: 1 Removed, 60 Changed, 1 Added functions +Functions changes summary: 1 Removed, 36 Changed, 1 Added functions Variables changes summary: 0 Removed, 0 Changed, 0 Added variable 1 Removed function: @@ -9,113 +9,7 @@ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable [A] 'method void std::__cxx11::_List_base >::_M_clear()' -60 functions with some indirect sub-type change: - - [C] 'method bool sigc::connection::block(bool)' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::connection*' has sub-type changes: - in pointed to type 'struct sigc::connection': - type size hasn't changed - 1 data member change: - type of 'sigc::slot_base* slot_' changed: - in pointed to type 'class sigc::slot_base': - type size hasn't changed - 1 data member change: - type of 'sigc::slot_base::rep_type* rep_' changed: - in pointed to type 'typedef sigc::slot_base::rep_type': - underlying type 'struct sigc::internal::slot_rep' changed: - type size hasn't changed - 1 base class change: - 'struct sigc::trackable' changed: - type size hasn't changed - 1 data member change: - type of 'sigc::internal::trackable_callback_list* callback_list_' changed: - in pointed to type 'struct sigc::internal::trackable_callback_list': - type size changed from 192 to 256 (in bits) - 2 data member changes: - type of 'sigc::internal::trackable_callback_list::callback_list callbacks_' changed: - underlying type 'class std::list >' changed: - type name changed from 'std::list >' to 'std::__cxx11::list >' - type size changed from 128 to 192 (in bits) - 1 base class change: - 'class std::_List_base >' changed: - type name changed from 'std::_List_base >' to 'std::__cxx11::_List_base >' - type size changed from 128 to 192 (in bits) - 1 data member change: - type of 'std::_List_base >::_List_impl _M_impl' changed: - type name changed from 'std::_List_base >::_List_impl' to 'std::__cxx11::_List_base >::_List_impl' - type size changed from 128 to 192 (in bits) - 1 data member change: - type of 'std::__detail::_List_node_base _M_node' changed: - type name changed from 'std::__detail::_List_node_base' to 'std::_List_node' - type size changed from 128 to 192 (in bits) - 1 base class insertion: - struct std::__detail::_List_node_base - 2 data member deletions: - 'std::__detail::_List_node_base* _M_next', at offset 0 (in bits) - 'std::__detail::_List_node_base* _M_prev', at offset 64 (in bits) - 1 data member insertion: - 'unsigned long int _M_data', at offset 128 (in bits) - and name of 'std::_List_base >::_List_impl::_M_node' changed to 'std::__cxx11::_List_base >::_List_impl::_M_node' - and name of 'std::_List_base >::_M_impl' changed to 'std::__cxx11::_List_base >::_M_impl' - 'bool clearing_' offset changed from 128 to 192 (in bits) (by +64 bits) - - [C] 'method bool sigc::connection::blocked()' has some indirect sub-type changes: - implicit parameter 0 of type 'const sigc::connection*' has sub-type changes: - in pointed to type 'const sigc::connection': - unqualified underlying type 'struct sigc::connection' changed, as reported earlier - - [C] 'method sigc::connection::connection(const sigc::connection&)' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::connection*' has sub-type changes: - pointed to type 'struct sigc::connection' changed, as reported earlier - parameter 1 of type 'const sigc::connection&' has sub-type changes: - in referenced type 'const sigc::connection': - unqualified underlying type 'struct sigc::connection' changed, as reported earlier - - [C] 'method sigc::connection::connection()' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::connection*' has sub-type changes: - pointed to type 'struct sigc::connection' changed, as reported earlier - - [C] 'method sigc::connection::connection(sigc::slot_base&)' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::connection*' has sub-type changes: - pointed to type 'struct sigc::connection' changed, as reported earlier - parameter 1 of type 'sigc::slot_base&' has sub-type changes: - referenced type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method void sigc::connection::disconnect()' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::connection*' has sub-type changes: - pointed to type 'struct sigc::connection' changed, as reported earlier - - [C] 'method bool sigc::connection::empty()' has some indirect sub-type changes: - implicit parameter 0 of type 'const sigc::connection*' has sub-type changes: - in pointed to type 'const sigc::connection': - unqualified underlying type 'struct sigc::connection' changed, as reported earlier - - [C] 'method bool sigc::connection::operator bool()' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::connection*' has sub-type changes: - pointed to type 'struct sigc::connection' changed, as reported earlier - - [C] 'method sigc::connection& sigc::connection::operator=(const sigc::connection&)' has some indirect sub-type changes: - return type changed: - referenced type 'struct sigc::connection' changed, as reported earlier - implicit parameter 0 of type 'sigc::connection*' has sub-type changes: - pointed to type 'struct sigc::connection' changed, as reported earlier - parameter 1 of type 'const sigc::connection&' has sub-type changes: - in referenced type 'const sigc::connection': - unqualified underlying type 'struct sigc::connection' changed, as reported earlier - - [C] 'method void sigc::connection::set_slot(sigc::slot_base*)' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::connection*' has sub-type changes: - pointed to type 'struct sigc::connection' changed, as reported earlier - parameter 1 of type 'sigc::slot_base*' has sub-type changes: - pointed to type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method bool sigc::connection::unblock()' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::connection*' has sub-type changes: - pointed to type 'struct sigc::connection' changed, as reported earlier - - [C] 'method sigc::connection::~connection(int)' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::connection*' has sub-type changes: - pointed to type 'struct sigc::connection' changed, as reported earlier +36 functions with some indirect sub-type change: [C] 'method void sigc::internal::signal_impl::block(bool)' has some indirect sub-type changes: implicit parameter 0 of type 'sigc::internal::signal_impl*' has sub-type changes: @@ -134,7 +28,16 @@ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable type name changed from 'std::_List_base >::_List_impl' to 'std::__cxx11::_List_base >::_List_impl' type size changed from 128 to 192 (in bits) 1 data member change: - type of 'std::__detail::_List_node_base _M_node' changed, as reported earlier + type of 'std::__detail::_List_node_base _M_node' changed: + type name changed from 'std::__detail::_List_node_base' to 'std::_List_node' + type size changed from 128 to 192 (in bits) + 1 base class insertion: + struct std::__detail::_List_node_base + 2 data member deletions: + 'std::__detail::_List_node_base* _M_next', at offset 0 (in bits) + 'std::__detail::_List_node_base* _M_prev', at offset 64 (in bits) + 1 data member insertion: + 'unsigned long int _M_data', at offset 128 (in bits) and name of 'std::_List_base >::_List_impl::_M_node' changed to 'std::__cxx11::_List_base >::_List_impl::_M_node' and name of 'std::_List_base >::_M_impl' changed to 'std::__cxx11::_List_base >::_M_impl' @@ -150,9 +53,6 @@ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable [C] 'method sigc::internal::signal_impl::iterator_type sigc::internal::signal_impl::connect(const sigc::slot_base&)' has some indirect sub-type changes: implicit parameter 0 of type 'sigc::internal::signal_impl*' has sub-type changes: pointed to type 'struct sigc::internal::signal_impl' changed, as reported earlier - parameter 1 of type 'const sigc::slot_base&' has sub-type changes: - in referenced type 'const sigc::slot_base': - unqualified underlying type 'class sigc::slot_base' changed, as reported earlier [C] 'method sigc::internal::signal_impl::iterator_type sigc::internal::signal_impl::erase(sigc::internal::signal_impl::iterator_type)' has some indirect sub-type changes: implicit parameter 0 of type 'sigc::internal::signal_impl*' has sub-type changes: @@ -161,9 +61,6 @@ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable [C] 'method sigc::internal::signal_impl::iterator_type sigc::internal::signal_impl::insert(sigc::internal::signal_impl::iterator_type, const sigc::slot_base&)' has some indirect sub-type changes: implicit parameter 0 of type 'sigc::internal::signal_impl*' has sub-type changes: pointed to type 'struct sigc::internal::signal_impl' changed, as reported earlier - parameter 2 of type 'const sigc::slot_base&' has sub-type changes: - in referenced type 'const sigc::slot_base': - unqualified underlying type 'class sigc::slot_base' changed, as reported earlier [C] 'method sigc::internal::signal_impl::signal_impl()' has some indirect sub-type changes: implicit parameter 0 of type 'sigc::internal::signal_impl*' has sub-type changes: @@ -183,12 +80,31 @@ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable pointed to type 'struct sigc::internal::signal_impl' changed, as reported earlier [C] 'method void sigc::internal::slot_rep::disconnect()' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::internal::slot_rep*' has sub-type changes: - pointed to type 'struct sigc::internal::slot_rep' changed, as reported earlier + implicit parameter 0 of type 'sigc::internal::slot_rep*' changed: + in pointed to type 'struct sigc::internal::slot_rep': [C] 'method void sigc::internal::trackable_callback_list::add_callback(void*)' has some indirect sub-type changes: implicit parameter 0 of type 'sigc::internal::trackable_callback_list*' has sub-type changes: - pointed to type 'struct sigc::internal::trackable_callback_list' changed, as reported earlier + in pointed to type 'struct sigc::internal::trackable_callback_list': + type size changed from 192 to 256 (in bits) + 2 data member changes: + type of 'sigc::internal::trackable_callback_list::callback_list callbacks_' changed: + underlying type 'class std::list >' changed: + type name changed from 'std::list >' to 'std::__cxx11::list >' + type size changed from 128 to 192 (in bits) + 1 base class change: + 'class std::_List_base >' changed: + type name changed from 'std::_List_base >' to 'std::__cxx11::_List_base >' + type size changed from 128 to 192 (in bits) + 1 data member change: + type of 'std::_List_base >::_List_impl _M_impl' changed: + type name changed from 'std::_List_base >::_List_impl' to 'std::__cxx11::_List_base >::_List_impl' + type size changed from 128 to 192 (in bits) + 1 data member change: + type of 'std::__detail::_List_node_base _M_node' changed, as reported earlier + and name of 'std::_List_base >::_List_impl::_M_node' changed to 'std::__cxx11::_List_base >::_List_impl::_M_node' + and name of 'std::_List_base >::_M_impl' changed to 'std::__cxx11::_List_base >::_M_impl' + 'bool clearing_' offset changed from 128 to 192 (in bits) (by +64 bits) [C] 'method void sigc::internal::trackable_callback_list::clear()' has some indirect sub-type changes: implicit parameter 0 of type 'sigc::internal::trackable_callback_list*' has sub-type changes: @@ -208,7 +124,10 @@ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable type size hasn't changed 1 base class change: 'struct sigc::trackable' changed: - details were reported earlier + type size hasn't changed + 1 data member change: + type of 'sigc::internal::trackable_callback_list* callback_list_' changed: + pointed to type 'struct sigc::internal::trackable_callback_list' changed, as reported earlier 1 data member change: type of 'sigc::internal::signal_impl* impl_' changed: pointed to type 'struct sigc::internal::signal_impl' changed, as reported earlier @@ -225,9 +144,6 @@ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable [C] 'method sigc::signal_base::iterator_type sigc::signal_base::connect(const sigc::slot_base&)' has some indirect sub-type changes: implicit parameter 0 of type 'sigc::signal_base*' has sub-type changes: pointed to type 'struct sigc::signal_base' changed, as reported earlier - parameter 1 of type 'const sigc::slot_base&' has sub-type changes: - in referenced type 'const sigc::slot_base': - unqualified underlying type 'class sigc::slot_base' changed, as reported earlier [C] 'method sigc::signal_base::iterator_type sigc::signal_base::erase(sigc::signal_base::iterator_type)' has some indirect sub-type changes: implicit parameter 0 of type 'sigc::signal_base*' has sub-type changes: @@ -243,9 +159,6 @@ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable [C] 'method sigc::signal_base::iterator_type sigc::signal_base::insert(sigc::signal_base::iterator_type, const sigc::slot_base&)' has some indirect sub-type changes: implicit parameter 0 of type 'sigc::signal_base*' has sub-type changes: pointed to type 'struct sigc::signal_base' changed, as reported earlier - parameter 2 of type 'const sigc::slot_base&' has sub-type changes: - in referenced type 'const sigc::slot_base': - unqualified underlying type 'class sigc::slot_base' changed, as reported earlier [C] 'method sigc::signal_base& sigc::signal_base::operator=(const sigc::signal_base&)' has some indirect sub-type changes: return type changed: @@ -280,68 +193,6 @@ Variables changes summary: 0 Removed, 0 Changed, 0 Added variable implicit parameter 0 of type 'sigc::signal_base*' has sub-type changes: pointed to type 'struct sigc::signal_base' changed, as reported earlier - [C] 'method void sigc::slot_base::add_destroy_notify_callback(void*)' has some indirect sub-type changes: - implicit parameter 0 of type 'const sigc::slot_base*' has sub-type changes: - in pointed to type 'const sigc::slot_base': - unqualified underlying type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method bool sigc::slot_base::block(bool)' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::slot_base*' has sub-type changes: - pointed to type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method void sigc::slot_base::disconnect()' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::slot_base*' has sub-type changes: - pointed to type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method bool sigc::slot_base::operator bool()' has some indirect sub-type changes: - implicit parameter 0 of type 'const sigc::slot_base*' has sub-type changes: - in pointed to type 'const sigc::slot_base': - unqualified underlying type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method sigc::slot_base& sigc::slot_base::operator=(const sigc::slot_base&)' has some indirect sub-type changes: - return type changed: - referenced type 'class sigc::slot_base' changed, as reported earlier - implicit parameter 0 of type 'sigc::slot_base*' has sub-type changes: - pointed to type 'class sigc::slot_base' changed, as reported earlier - parameter 1 of type 'const sigc::slot_base&' has sub-type changes: - in referenced type 'const sigc::slot_base': - unqualified underlying type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method void sigc::slot_base::remove_destroy_notify_callback(void*)' has some indirect sub-type changes: - implicit parameter 0 of type 'const sigc::slot_base*' has sub-type changes: - in pointed to type 'const sigc::slot_base': - unqualified underlying type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method void sigc::slot_base::set_parent(void*)' has some indirect sub-type changes: - implicit parameter 0 of type 'const sigc::slot_base*' has sub-type changes: - in pointed to type 'const sigc::slot_base': - unqualified underlying type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method sigc::slot_base::slot_base(sigc::slot_base::rep_type*)' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::slot_base*' has sub-type changes: - pointed to type 'class sigc::slot_base' changed, as reported earlier - parameter 1 of type 'sigc::slot_base::rep_type*' has sub-type changes: - pointed to type 'typedef sigc::slot_base::rep_type' changed, as reported earlier - - [C] 'method sigc::slot_base::slot_base()' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::slot_base*' has sub-type changes: - pointed to type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method sigc::slot_base::slot_base(const sigc::slot_base&)' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::slot_base*' has sub-type changes: - pointed to type 'class sigc::slot_base' changed, as reported earlier - parameter 1 of type 'const sigc::slot_base&' has sub-type changes: - in referenced type 'const sigc::slot_base': - unqualified underlying type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method bool sigc::slot_base::unblock()' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::slot_base*' has sub-type changes: - pointed to type 'class sigc::slot_base' changed, as reported earlier - - [C] 'method sigc::slot_base::~slot_base(int)' has some indirect sub-type changes: - implicit parameter 0 of type 'sigc::slot_base*' has sub-type changes: - pointed to type 'class sigc::slot_base' changed, as reported earlier - [C] 'method void sigc::trackable::add_destroy_notify_callback(void*)' has some indirect sub-type changes: implicit parameter 0 of type 'const sigc::trackable*' has sub-type changes: in pointed to type 'const sigc::trackable': diff --git a/tests/data/test-diff-dwarf/PR25058-liblttng-ctl-report-1.txt b/tests/data/test-diff-dwarf/PR25058-liblttng-ctl-report-1.txt index 02879fcb..328ce804 100644 --- a/tests/data/test-diff-dwarf/PR25058-liblttng-ctl-report-1.txt +++ b/tests/data/test-diff-dwarf/PR25058-liblttng-ctl-report-1.txt @@ -89,7 +89,12 @@ Variables changes summary: 0 Removed, 0 Changed, 3 Added variables parameter 1 of type 'lttng_action*' has sub-type changes: in pointed to type 'struct lttng_action': type size hasn't changed - 2 data member changes: + 3 data member changes: + type of 'action_validate_cb validate' changed: + underlying type 'bool (lttng_action*)*' changed: + in pointed to type 'function type bool (lttng_action*)': + parameter 1 of type 'lttng_action*' has sub-type changes: + pointed to type 'struct lttng_action' changed, as being reported type of 'action_serialize_cb serialize' changed: underlying type 'typedef ssize_t (lttng_action*, char*)*' changed: in pointed to type 'function type typedef ssize_t (lttng_action*, char*)': diff --git a/tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt b/tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt index 546942fe..57b11a8a 100644 --- a/tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt +++ b/tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt @@ -68,7 +68,7 @@ ================ end of changes of 'libssl3.so'=============== ================ changes of 'libsmime3.so'=============== - Functions changes summary: 0 Removed, 1 Changed (127 filtered out), 0 Added functions + Functions changes summary: 0 Removed, 1 Changed (146 filtered out), 0 Added functions Variables changes summary: 0 Removed, 0 Changed, 0 Added variable 1 function with some indirect sub-type change: @@ -82,12 +82,12 @@ type of 'NSSCMSContent content' changed: underlying type 'union NSSCMSContentUnion' at cmst.h:118:1 changed: type size hasn't changed - 1 data member changes (3 filtered): + 1 data member changes (4 filtered): type of 'NSSCMSEncryptedData* encryptedData' changed: in pointed to type 'typedef NSSCMSEncryptedData' at cmst.h:65:1: underlying type 'struct NSSCMSEncryptedDataStr' at cmst.h:468:1 changed: type size hasn't changed - 1 data member changes (1 filtered): + 1 data member changes (2 filtered): type of 'NSSCMSAttribute** unprotectedAttr' changed: in pointed to type 'NSSCMSAttribute*': in pointed to type 'typedef NSSCMSAttribute' at cmst.h:69:1: diff --git a/tests/data/test-diff-pkg/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-report-2.txt b/tests/data/test-diff-pkg/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-report-2.txt index 290ad869..c0e8a3e1 100644 --- a/tests/data/test-diff-pkg/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-report-2.txt +++ b/tests/data/test-diff-pkg/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-report-2.txt @@ -29,7 +29,87 @@ in pointed to type 'typedef QXLState' at spice-qxl.h:35:1: underlying type 'struct QXLState' at reds.h:93:1 changed: type size hasn't changed - 1 data member change: + 2 data member changes: + type of 'QXLInterface* qif' changed: + in pointed to type 'typedef QXLInterface' at spice-qxl.h:33:1: + underlying type 'struct QXLInterface' at spice.h:230:1 changed: + type size hasn't changed + 15 data member changes: + type of 'void (QXLInstance*, QXLWorker*)* attache_worker' changed: + in pointed to type 'function type void (QXLInstance*, QXLWorker*)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'void (QXLInstance*, int)* set_compression_level' changed: + in pointed to type 'function type void (QXLInstance*, int)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'void (QXLInstance*, typedef uint32_t)* set_mm_time' changed: + in pointed to type 'function type void (QXLInstance*, typedef uint32_t)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'void (QXLInstance*, QXLDevInitInfo*)* get_init_info' changed: + in pointed to type 'function type void (QXLInstance*, QXLDevInitInfo*)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'int (QXLInstance*, QXLCommandExt*)* get_command' changed: + in pointed to type 'function type int (QXLInstance*, QXLCommandExt*)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'int (QXLInstance*)* req_cmd_notification' changed: + in pointed to type 'function type int (QXLInstance*)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'void (QXLInstance*, struct QXLReleaseInfoExt)* release_resource' changed: + in pointed to type 'function type void (QXLInstance*, struct QXLReleaseInfoExt)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'int (QXLInstance*, QXLCommandExt*)* get_cursor_command' changed: + in pointed to type 'function type int (QXLInstance*, QXLCommandExt*)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'int (QXLInstance*)* req_cursor_notification' changed: + in pointed to type 'function type int (QXLInstance*)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'void (QXLInstance*, typedef uint32_t)* notify_update' changed: + in pointed to type 'function type void (QXLInstance*, typedef uint32_t)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'int (QXLInstance*)* flush_resources' changed: + in pointed to type 'function type int (QXLInstance*)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'void (QXLInstance*, typedef uint64_t)* async_complete' changed: + in pointed to type 'function type void (QXLInstance*, typedef uint64_t)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'void (QXLInstance*, typedef uint32_t, QXLRect*, typedef uint32_t)* update_area_complete' changed: + in pointed to type 'function type void (QXLInstance*, typedef uint32_t, QXLRect*, typedef uint32_t)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'void (QXLInstance*, typedef uint8_t, uint8_t*)* set_client_capabilities' changed: + in pointed to type 'function type void (QXLInstance*, typedef uint8_t, uint8_t*)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported + type of 'int (QXLInstance*, VDAgentMonitorsConfig*)* client_monitors_config' changed: + in pointed to type 'function type int (QXLInstance*, VDAgentMonitorsConfig*)': + parameter 1 of type 'QXLInstance*' has sub-type changes: + in pointed to type 'typedef QXLInstance' at spice-qxl.h:34:1: + underlying type 'struct QXLInstance' changed, as being reported type of 'RedDispatcher* dispatcher' changed: in pointed to type 'struct RedDispatcher' at red_dispatcher.c:55:1: type size changed from 3264 to 3328 (in bits) diff --git a/tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt b/tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt index 51341ddb..afe77511 100644 --- a/tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt +++ b/tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-0.txt @@ -1,5 +1,5 @@ ================ changes of 'libtbb.so.2'=============== - Functions changes summary: 0 Removed, 10 Changed (92 filtered out), 17 Added functions + Functions changes summary: 0 Removed, 8 Changed (67 filtered out), 17 Added functions Variables changes summary: 0 Removed, 0 Changed, 0 Added variable Function symbols changes summary: 0 Removed, 0 Added function symbol not referenced by debug info Variable symbols changes summary: 3 Removed, 0 Added variable symbols not referenced by debug info @@ -24,26 +24,7 @@ [A] 'method void tbb::internal::concurrent_queue_base_v8::move_content(tbb::internal::concurrent_queue_base_v8&)' {_ZN3tbb8internal24concurrent_queue_base_v812move_contentERS1_} [A] 'method void tbb::task_group_context::capture_fp_settings()' {_ZN3tbb18task_group_context19capture_fp_settingsEv} - 10 functions with some indirect sub-type change: - - [C] 'method void tbb::filter::set_end_of_input()' at pipeline.cpp:700:1 has some indirect sub-type changes: - implicit parameter 0 of type 'tbb::filter*' has sub-type changes: - in pointed to type 'class tbb::filter' at pipeline.h:65:1: - type size hasn't changed - 1 member function deletion: - 'method virtual tbb::filter::~filter(int)' at pipeline.cpp:698:1 - 1 member function insertion: - 'method virtual tbb::filter::~filter(int)' at pipeline.cpp:688:1 - no member function changes (4 filtered); - 1 data member changes (4 filtered): - type of 'tbb::internal::input_buffer* my_input_buffer' changed: - in pointed to type 'class tbb::internal::input_buffer' at pipeline.cpp:52:1: - type size hasn't changed - 1 data member change: - type of 'tbb::spin_mutex array_mutex' changed: - type size hasn't changed - 1 base class insertion: - class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1 + 8 functions with some indirect sub-type change: [C] 'method tbb::task& tbb::internal::allocate_root_with_context_proxy::allocate(std::size_t) const' at task.h:135:1 has some indirect sub-type changes: implicit parameter 0 of type 'const tbb::internal::allocate_root_with_context_proxy*' has sub-type changes: @@ -70,16 +51,7 @@ 2 data member insertions: 'volatile intptr_t* my_ref_top_priority', at offset 576 (in bits) at scheduler.h:96:1 'volatile uintptr_t* my_ref_reload_epoch', at offset 640 (in bits) at scheduler.h:99:1 - 3 data member changes: - type of 'tbb::internal::arena_slot* my_arena_slot' changed: - in pointed to type 'struct tbb::internal::arena_slot' at scheduler_common.h:316:1: - type size hasn't changed - 2 base class deletions: - struct tbb::internal::padded at tbb_stddef.h:261:1 - struct tbb::internal::padded at tbb_stddef.h:261:1 - 2 base class insertions: - struct tbb::internal::padded at tbb_stddef.h:251:1 - struct tbb::internal::padded at tbb_stddef.h:251:1 + 2 data member changes (2 filtered): type of 'tbb::internal::arena* my_arena' changed: in pointed to type 'class tbb::internal::arena' at arena.h:160:1: type size hasn't changed @@ -87,7 +59,6 @@ struct tbb::internal::padded at tbb_stddef.h:261:1 1 base class insertion: struct tbb::internal::padded at tbb_stddef.h:251:1 - no data member change (1 filtered); type of 'tbb::internal::mail_inbox my_inbox' changed: type size hasn't changed 1 data member change: @@ -180,7 +151,7 @@ type of 'tbb::internal::concurrent_queue_rep* my_rep' changed: in pointed to type 'class tbb::internal::concurrent_queue_rep' at concurrent_queue.cpp:129:1: type size hasn't changed - 1 data member changes (2 filtered): + 1 data member changes (1 filtered): type of 'tbb::internal::concurrent_monitor items_avail' changed: type size hasn't changed 1 data member change: @@ -221,7 +192,6 @@ type size hasn't changed 1 base class insertion: class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1 - no data member change (1 filtered); [C] 'method void tbb::queuing_rw_mutex::internal_construct()' at queuing_rw_mutex.h:146:1 has some indirect sub-type changes: implicit parameter 0 of type 'tbb::queuing_rw_mutex*' has sub-type changes: @@ -229,7 +199,6 @@ type size hasn't changed 1 base class insertion: class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1 - no data member change (1 filtered); [C] 'method void tbb::recursive_mutex::internal_construct()' at recursive_mutex.h:224:1 has some indirect sub-type changes: implicit parameter 0 of type 'tbb::recursive_mutex*' has sub-type changes: @@ -238,14 +207,6 @@ 1 base class insertion: class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1 - [C] 'method tbb::thread_bound_filter::result_type tbb::thread_bound_filter::process_item()' at pipeline.cpp:712:1 has some indirect sub-type changes: - implicit parameter 0 of type 'tbb::thread_bound_filter*' has sub-type changes: - in pointed to type 'class tbb::thread_bound_filter' at pipeline.h:197:1: - type size hasn't changed - 1 base class change: - 'class tbb::filter' at pipeline.h:74:1 changed: - details were reported earlier - 3 Removed variable symbols not referenced by debug info: [D] _ZTVN3rml16versioned_objectE diff --git a/tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt b/tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt index a2247eb8..a8611476 100644 --- a/tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt +++ b/tests/data/test-diff-pkg/tbb-4.1-9.20130314.fc22.x86_64--tbb-4.3-3.20141204.fc23.x86_64-report-1.txt @@ -1,5 +1,5 @@ ================ changes of 'libtbb.so.2'=============== - Functions changes summary: 0 Removed, 8 Changed (94 filtered out), 17 Added functions + Functions changes summary: 0 Removed, 7 Changed (68 filtered out), 17 Added functions Variables changes summary: 0 Removed, 0 Changed, 0 Added variable Function symbols changes summary: 0 Removed, 0 Added function symbol not referenced by debug info Variable symbols changes summary: 3 Removed, 0 Added variable symbols not referenced by debug info @@ -24,7 +24,7 @@ [A] 'method void tbb::internal::concurrent_queue_base_v8::move_content(tbb::internal::concurrent_queue_base_v8&)' {_ZN3tbb8internal24concurrent_queue_base_v812move_contentERS1_} [A] 'method void tbb::task_group_context::capture_fp_settings()' {_ZN3tbb18task_group_context19capture_fp_settingsEv} - 8 functions with some indirect sub-type change: + 7 functions with some indirect sub-type change: [C] 'method tbb::task& tbb::internal::allocate_root_with_context_proxy::allocate(std::size_t) const' at task.h:135:1 has some indirect sub-type changes: implicit parameter 0 of type 'const tbb::internal::allocate_root_with_context_proxy*' has sub-type changes: @@ -64,7 +64,6 @@ type size hasn't changed 1 base class insertion: class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1 - no data member change (1 filtered); [C] 'method void tbb::queuing_rw_mutex::internal_construct()' at queuing_rw_mutex.h:146:1 has some indirect sub-type changes: implicit parameter 0 of type 'tbb::queuing_rw_mutex*' has sub-type changes: @@ -72,7 +71,6 @@ type size hasn't changed 1 base class insertion: class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1 - no data member change (1 filtered); [C] 'method void tbb::recursive_mutex::internal_construct()' at recursive_mutex.h:224:1 has some indirect sub-type changes: implicit parameter 0 of type 'tbb::recursive_mutex*' has sub-type changes: @@ -81,13 +79,6 @@ 1 base class insertion: class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1 - [C] 'method void tbb::spin_mutex::internal_construct()' at spin_mutex.h:138:1 has some indirect sub-type changes: - implicit parameter 0 of type 'tbb::spin_mutex*' has sub-type changes: - in pointed to type 'class tbb::spin_mutex' at spin_mutex.h:40:1: - type size hasn't changed - 1 base class insertion: - class tbb::internal::mutex_copy_deprecated_and_disabled at tbb_stddef.h:334:1 - [C] 'method void tbb::spin_rw_mutex_v3::internal_acquire_reader()' at spin_rw_mutex.h:53:1 has some indirect sub-type changes: implicit parameter 0 of type 'tbb::spin_rw_mutex_v3*' has sub-type changes: in pointed to type 'class tbb::spin_rw_mutex_v3' at spin_rw_mutex.h:42:1: