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 文件中。