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
