GCC 插件基础设施¶
简介¶
GCC 插件是可加载的模块,为编译器提供额外的功能 [1]。它们对于运行时检测和静态分析很有用。我们可以通过回调 [2]、GIMPLE [3]、IPA [4] 和 RTL 传递 [5] 在编译期间分析、更改和添加更多代码。
内核的 GCC 插件基础设施支持构建树外模块、交叉编译和在单独的目录中构建。插件源文件必须可由 C++ 编译器编译。
目前,GCC 插件基础设施仅支持某些架构。 grep “select HAVE_GCC_PLUGINS” 以找出哪些架构支持 GCC 插件。
此基础设施从 grsecurity [6] 和 PaX [7] 移植而来。
--
目的¶
GCC 插件旨在提供一个场所来试验潜在的编译器功能,这些功能既不在 GCC 中,也不在上游 Clang 中。 一旦证明了它们的实用性,目标是将该功能上游到 GCC(和 Clang)中,然后在所有支持的 GCC 版本中都提供该功能后,最终将其从内核中删除。
具体来说,新插件应该只实现没有上游编译器支持(在 GCC 或 Clang 中)的功能。
当某个功能存在于 Clang 中但不存在于 GCC 中时,应努力将该功能引入上游 GCC(而不仅仅是作为内核特定的 GCC 插件),以便整个生态系统都可以从中受益。
同样,即使 GCC 插件提供的功能在 Clang 中 *不* 存在,但该功能被证明是有用的,也应该花费精力将该功能上游到 GCC(和 Clang)。
在某个功能在上游 GCC 中可用之后,该插件将被设置为对相应的 GCC 版本(以及更高版本)不可构建。 一旦所有内核支持的 GCC 版本都提供了该功能,该插件将从内核中删除。
文件¶
$(src)/scripts/gcc-plugins
这是 GCC 插件的目录。
$(src)/scripts/gcc-plugins/gcc-common.h
这是 GCC 插件的兼容性头文件。 它应该始终包含,而不是单独的 gcc 头文件。
$(src)/scripts/gcc-plugins/gcc-generate-gimple-pass.h, $(src)/scripts/gcc-plugins/gcc-generate-ipa-pass.h, $(src)/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h, $(src)/scripts/gcc-plugins/gcc-generate-rtl-pass.h
这些头文件自动生成 GIMPLE、SIMPLE_IPA、IPA 和 RTL 传递的注册结构。 应该优先使用它们,而不是手动创建结构。
用法¶
您必须为您的 gcc 版本安装 gcc 插件头文件,例如,在 Ubuntu 上对于 gcc-10
apt-get install gcc-10-plugin-dev
或者在 Fedora 上
dnf install gcc-plugin-devel libmpc-devel
或者在使用包含插件的交叉编译器时,在 Fedora 上
dnf install libmpc-devel
启用 GCC 插件基础设施和您想要在内核配置中使用的某些插件
CONFIG_GCC_PLUGINS=y
CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y
...
运行 gcc(本机或交叉编译器)以确保检测到插件头文件
gcc -print-file-name=plugin
CROSS_COMPILE=arm-linux-gnu- ${CROSS_COMPILE}gcc -print-file-name=plugin
单词 “plugin” 表示未检测到它们
plugin
完整路径表示已检测到它们
/usr/lib/gcc/x86_64-redhat-linux/12/plugin
要编译包含插件的最小工具集
make scripts
或者只运行内核 make 并使用圈复杂度 GCC 插件编译整个内核。
4. 如何添加新的 GCC 插件¶
GCC 插件位于 scripts/gcc-plugins/ 中。 您需要将插件源文件直接放在 scripts/gcc-plugins/ 下。 不支持创建子目录。 必须将其添加到 scripts/gcc-plugins/Makefile、scripts/Makefile.gcc-plugins 和相关的 Kconfig 文件中。