Hello.

Would like to have comments on the attached patch. There could be another
option for checking both gcc and glibc versions. Just wanted comments before
doing anything further. I am not on the mailing list, so please CC: on any
replies. Thank you.

-Steve


>From b1ac0805d70aaa2e1500a071f63c88bcaa76754e Mon Sep 17 00:00:00 2001
From: "Steven J. Hill" <[email protected]>
Date: Tue, 23 Sep 2025 18:21:09 -0500
Subject: [PATCH] gcc-plugins: Relax constraints on plugin compatibility.

The compatibility check for gcc plugins is too inflexible,
and a lot of times wrong. Add ability to let the user choose
how stringent compatibility is.

Signed-off-by: Steven J. Hill <[email protected]>
---
 scripts/gcc-plugins/Kconfig                   | 36 +++++++++++++++++++
 scripts/gcc-plugins/Makefile                  | 15 +++++++-
 scripts/gcc-plugins/compare-libc-versions.sh  | 28 +++++++++++++++
 scripts/gcc-plugins/gcc-common.h              | 18 ++++++++++
 scripts/gcc-plugins/latent_entropy_plugin.c   |  2 +-
 scripts/gcc-plugins/randomize_layout_plugin.c |  2 +-
 scripts/gcc-plugins/sancov_plugin.c           |  2 +-
 scripts/gcc-plugins/stackleak_plugin.c        |  2 +-
 scripts/gcc-plugins/structleak_plugin.c       |  2 +-
 9 files changed, 101 insertions(+), 6 deletions(-)
 create mode 100755 scripts/gcc-plugins/compare-libc-versions.sh

diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig
index 929997fb5e45..626a9200f2a1 100644
--- a/scripts/gcc-plugins/Kconfig
+++ b/scripts/gcc-plugins/Kconfig
@@ -19,6 +19,42 @@ menuconfig GCC_PLUGINS

 if GCC_PLUGINS

+choice
+       prompt "Version checking"
+       help
+         Each plugin is required to call plugin_default_version_check() in
+         its init function. This check can at times be too stringent or
+         just plain wrong, especially when cross-compiling. See source file
+         gcc/plugin.cc in the gcc repository for more details. This option
+         allows for the user to choose how stringent the check should be.
+
+       config GCC_PLUGIN_VERSION_CHECK_DEFAULT
+               bool "Default behavior"
+               help
+                 Just calls plugin_default_version_check() like before.
+
+       config GCC_PLUGIN_VERSION_CHECK_NONE
+               bool "Disable checking"
+               help
+                 Plugins will be built without any incompatibilities
+                 being reported to the user.
+
+       config GCC_PLUGIN_VERSION_CHECK_GCC
+               bool "Check only GCC versions"
+               help
+                 Compare only the GCC version strings of the host and
+                 target compilers.
+
+       config GCC_PLUGIN_VERSION_CHECK_LIBC
+               bool "Check C library versions"
+               help
+                 Compares only C library versions. Checks the
+                 version strings and the highest library API versions
+                 supported in each toolchain. Only glibc-based tools
+                 are currently supported.
+
+endchoice
+
 config GCC_PLUGIN_SANCOV
        bool
        # Plugin can be removed once the kernel only supports GCC 6+
diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile
index 320afd3cf8e8..48d50a3fe362 100644
--- a/scripts/gcc-plugins/Makefile
+++ b/scripts/gcc-plugins/Makefile
@@ -24,6 +24,19 @@ targets += randomize_layout_seed.h

 always-y += $(GCC_PLUGIN)

+ifdef CONFIG_GCC_PLUGIN_VERSION_CHECK_DEFAULT
+GCC_PLUGINS_CHECK_VERSION = -DGCC_PLUGIN_VERSION_DEFAULT
+endif
+ifdef CONFIG_GCC_PLUGIN_VERSION_CHECK_NONE
+GCC_PLUGINS_CHECK_VERSION = -DGCC_PLUGIN_VERSION_NONE
+endif
+ifdef CONFIG_GCC_PLUGIN_VERSION_CHECK_GCC
+GCC_PLUGINS_CHECK_VERSION = -DGCC_PLUGIN_VERSION_GCC
+endif
+ifdef CONFIG_GCC_PLUGIN_VERSION_CHECK_LIBC
+GCC_PLUGINS_CHECK_VERSION = $(shell 
$(srctree)/scripts/gcc-plugins/compare-libc-versions.sh "$(HOSTCXX)" "$(CC)")
+endif
+
 GCC_PLUGINS_DIR = $(shell $(CC) -print-file-name=plugin)

 plugin_cxxflags        = -Wp,-MMD,$(depfile) $(KBUILD_HOSTCXXFLAGS) -fPIC \
@@ -32,7 +45,7 @@ plugin_cxxflags       = -Wp,-MMD,$(depfile) 
$(KBUILD_HOSTCXXFLAGS) -fPIC \
                  -I $(GCC_PLUGINS_DIR)/include -I $(obj) \
                  -fno-rtti -fno-exceptions -fasynchronous-unwind-tables \
                  -ggdb -Wno-narrowing -Wno-unused-variable \
-                 -Wno-format-diag
+                 $(GCC_PLUGINS_CHECK_VERSION) -Wno-format-diag

 plugin_ldflags = -shared

diff --git a/scripts/gcc-plugins/compare-libc-versions.sh 
b/scripts/gcc-plugins/compare-libc-versions.sh
new file mode 100755
index 000000000000..592e501575f2
--- /dev/null
+++ b/scripts/gcc-plugins/compare-libc-versions.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+#
+# glibc version comparison script
+
+if test $# -ne 2; then
+       echo "Usage: $0 <hostcxx> <targetcxx>"
+       exit 1
+fi
+
+#
+# Get paths of base C libraries.
+#
+HOSTLIBPATH=$("$1" -print-file-name=libc.so.6)
+TARGLIBPATH=$("$2" -print-file-name=libc.so.6)
+
+#
+# Find the highest library version supported in each.
+#
+HOSTVER=$(readelf -V "$HOSTLIBPATH" | grep "Parent 1: GLIBC_2" | \
+         sed -e's/.*Parent 1: GLIBC_2\.//g' | sort -rn | head -1)
+TARGVER=$(readelf -V "$TARGLIBPATH" | grep "Parent 1: GLIBC_2" | \
+         sed -e's/.*Parent 1: GLIBC_2\.//g' | sort -rn | head -1)
+
+#
+# If we get a match, emit the pre-processor flag.
+#
+[ "${HOSTVER}" = "${TARGVER}" ] && echo "-DGCC_PLUGIN_VERSION_LIBC"
diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
index 3222c1070444..5a747895d8e6 100644
--- a/scripts/gcc-plugins/gcc-common.h
+++ b/scripts/gcc-plugins/gcc-common.h
@@ -439,4 +439,22 @@ static inline void debug_gimple_stmt(const_gimple s)
 #define last_stmt(x)                   last_nondebug_stmt(x)
 #endif

+static inline int plugin_version_check(struct plugin_gcc_version *plugin_ver,
+                                      struct plugin_gcc_version *gcc_ver)
+{
+#ifdef GCC_PLUGIN_VERSION_DEFAULT
+       return plugin_default_version_check(plugin_ver, gcc_ver);
+#endif
+#ifdef GCC_PLUGIN_VERSION_NONE
+       return 1;
+#endif
+#ifdef GCC_PLUGIN_VERSION_GCC
+       return (strcmp(plugin_ver->basever, gcc_ver->basever) == 0);
+#endif
+#ifdef GCC_PLUGIN_VERSION_LIBC
+       return 1;
+#endif
+       return 0;
+}
+
 #endif
diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c 
b/scripts/gcc-plugins/latent_entropy_plugin.c
index ff0b192be91f..e1899f16bf22 100644
--- a/scripts/gcc-plugins/latent_entropy_plugin.c
+++ b/scripts/gcc-plugins/latent_entropy_plugin.c
@@ -596,7 +596,7 @@ __visible int plugin_init(struct plugin_name_args 
*plugin_info,

        PASS_INFO(latent_entropy, "optimized", 1, PASS_POS_INSERT_BEFORE);

-       if (!plugin_default_version_check(version, &gcc_version)) {
+       if (!plugin_version_check(version, &gcc_version)) {
                error(G_("incompatible gcc/plugin versions"));
                return 1;
        }
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c 
b/scripts/gcc-plugins/randomize_layout_plugin.c
index 5694df3da2e9..fd8220c6daeb 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -851,7 +851,7 @@ __visible int plugin_init(struct plugin_name_args 
*plugin_info, struct plugin_gc
        find_bad_casts_pass_info.ref_pass_instance_number       = 1;
        find_bad_casts_pass_info.pos_op                 = PASS_POS_INSERT_AFTER;

-       if (!plugin_default_version_check(version, &gcc_version)) {
+       if (!plugin_version_check(version, &gcc_version)) {
                error(G_("incompatible gcc/plugin versions"));
                return 1;
        }
diff --git a/scripts/gcc-plugins/sancov_plugin.c 
b/scripts/gcc-plugins/sancov_plugin.c
index b76cb9c42cec..78e1e38d3922 100644
--- a/scripts/gcc-plugins/sancov_plugin.c
+++ b/scripts/gcc-plugins/sancov_plugin.c
@@ -106,7 +106,7 @@ __visible int plugin_init(struct plugin_name_args 
*plugin_info, struct plugin_gc
        /* BBs can be split afterwards?? */
        PASS_INFO(sancov, "asan", 0, PASS_POS_INSERT_BEFORE);

-       if (!plugin_default_version_check(version, &gcc_version)) {
+       if (!plugin_version_check(version, &gcc_version)) {
                error(G_("incompatible gcc/plugin versions"));
                return 1;
        }
diff --git a/scripts/gcc-plugins/stackleak_plugin.c 
b/scripts/gcc-plugins/stackleak_plugin.c
index d20c47d21ad8..2d3129ad2507 100644
--- a/scripts/gcc-plugins/stackleak_plugin.c
+++ b/scripts/gcc-plugins/stackleak_plugin.c
@@ -560,7 +560,7 @@ __visible int plugin_init(struct plugin_name_args 
*plugin_info,
         */
        PASS_INFO(stackleak_cleanup, "*free_cfg", 1, PASS_POS_INSERT_BEFORE);

-       if (!plugin_default_version_check(version, &gcc_version)) {
+       if (!plugin_version_check(version, &gcc_version)) {
                error(G_("incompatible gcc/plugin versions"));
                return 1;
        }
diff --git a/scripts/gcc-plugins/structleak_plugin.c 
b/scripts/gcc-plugins/structleak_plugin.c
index d8c744233832..7128889979f5 100644
--- a/scripts/gcc-plugins/structleak_plugin.c
+++ b/scripts/gcc-plugins/structleak_plugin.c
@@ -216,7 +216,7 @@ __visible int plugin_init(struct plugin_name_args 
*plugin_info, struct plugin_gc

        PASS_INFO(structleak, "early_optimizations", 1, PASS_POS_INSERT_BEFORE);

-       if (!plugin_default_version_check(version, &gcc_version)) {
+       if (!plugin_version_check(version, &gcc_version)) {
                error(G_("incompatible gcc/plugin versions"));
                return 1;
        }
--
2.29.0


Reply via email to