C2Rust Linux Kernel Module尝试-实践篇
cargo install --force c2rust --version 0.14.0
报错❌
error: failed to compile `c2rust v0.14.0`, intermediate artifacts can be found at `/tmp/cargo-installNnW8Ru`
Caused by:
failed to parse manifest at `/root/.cargo/registry/src/github.com-1ecc6299db9ec823/once_cell-1.17.2/Cargo.toml`
Caused by:
feature `edition2021` is required
this Cargo does not support nightly features, but if you
switch to nightly channel you can add
`cargo-features = ["edition2021"]` to enable this feature
这个错误表明,c2rust v0.14.0
依赖的once_cell
库需要使用Rust 2021 edition的功能,但是你当前使用的Rust版本可能不支持。你需要切换到nightly版本的Rust才能使用这个特性。
可以使用以下命令切换到Rust的nightly版本:✅🌃
rustup default nightly
然后你可以再次尝试安装c2rust v0.14.0
。
如果你之后想要切换回稳定版的Rust,可以使用:
rustup default stable
值得注意的是,nightly版本的Rust包含一些尚未稳定的功能,可能会有一些不稳定和未预料到的行为。只有当你确实需要这些特性时,才建议使用nightly版本。
└─$ c2rust transpile ./compile_commands.json --emit-no-std \
--emit-modules -o bareflank-rs "$@"
--emit-no-std: 这个选项告诉c2rust生成的Rust代码不应该依赖于Rust的标准库,也就是说生成的代码可以在不提供Rust标准库的环境中运行,比如裸机或嵌入式环境。
--emit-modules: 这个选项告诉c2rust为每个转换的C源文件生成一个单独的Rust模块。这样的话,每个C源文件就会对应一个.rs文件,而不是全部合并到一个.rs文件中。
-o bareflank-rs: 这个选项指定了转换后的Rust源代码文件的输出目录,即生成的Rust代码会被保存在bareflank-rs这个目录中。
"$@": 这是一个bash脚本的特殊参数,代表所有传递给脚本的参数。在这个上下文中,它代表所有额外传递给c2rust命令的参数。
这个命令的总体目标是将compile_commands.json中描述的C源代码转换成不依赖Rust标准库的Rust源代码,并将结果保存在bareflank-rs目录中,每个C源文件对应一个Rust模块(.rs文件)。
bear -- make -j
bear -- make -j8 CC=clang -C /home/kali/linux-4.19.288 M=/home/kali/hypervisor-2.0/bfdriver/src/platform/linux modules
# -C DIRECTORY, --directory=DIRECTORY
# Change to DIRECTORY before doing anything.
这个命令实际上由两部分组成:bear --
以及其后面的 make
命令。下面我分别对这两部分进行解释:
bear --
:Bear 是一个命令行工具,它的全称是 Build EAR,用于生成编译数据库,通常这个数据库是一个名为compile_commands.json
的 JSON 文件。这个文件详细地列出了每个文件的编译命令,这对于很多工具(包括一些代码编辑器、静态分析工具、重构工具等)非常有用,因为它们需要知道如何为每个文件构建正确的编译命令。--
是 Bear 的一个选项,用于告诉 Bear 后面的参数应该被当作是要运行并拦截其编译命令的构建系统。make -j8 -C /home/kali/linux-4.19.288 M=/home/kali/hypervisor-2.0/bfdriver/src/platform/linux modules
:这部分是用 make 工具来构建一个项目。具体来说,-j8
告诉 make 在同一时间最多可以有 8 个任务并行执行;-C /home/kali/linux-4.19.288
告诉 make 切换到/home/kali/linux-4.19.288
目录,并在这个目录下读取Makefile
;M=/home/kali/hypervisor-2.0/bfdriver/src/platform/linux
是传递给Makefile
的一个参数,通常M=
被用于指定外部模块的路径;modules
是一个 make 的目标,通常这个目标会在你的Makefile
中定义,用于构建项目中的所有模块。
所以,总的来说,这个命令的意思是:“使用 Bear 工具运行 make 命令,以并行的方式(最多 8 个任务)在指定的目录下构建所有模块,并生成一个名为 compile_commands.json
的编译数据库。”
转换1
bear
是一个工具,用于生成编译命令的数据库,
└─$ clang --version
Debian clang version 14.0.6
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
└─$ gcc --version
gcc (Debian 12.2.0-14) 12.2.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-mfunction-return=thunk-extern
:这是一个GCC的编译选项,用于改变函数的返回方式。然而,在你的情况下,你正在使用clang编译器,它不支持这个选项,因此需要删除。-fconserve-stack
:这个选项在GCC中用于尽可能地减小栈的使用。同样,clang并不支持这个选项,所以需要移除。-mrecord-mcount
:这个选项用于支持GCC的一个功能,即ftrace框架。ftrace允许在运行时跟踪和记录函数调用。然而,clang并不支持这个选项,所以需要删除。-ftrivial-auto-var-init=zero
:这是一个clang选项,用于将自动变量初始化为0。然而,这个选项在你的情况下被禁用了,提示你需要手动开启。所以我们将它替换为了开启选项-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang
sed -i -e 's/-mfunction-return=thunk-extern//g' \
-e 's/-fconserve-stack//g' \
-e 's/-mrecord-mcount//g' \
-e 's/-ftrivial-auto-var-init=zero/-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang/g' \
compile_commands.json
└─$ bear -- make -j8 CC=clang
make -C /lib/modules/6.1.0-kali7-amd64/build M=/home/kali/hypervisor-2.0/bfdriver/src/platform/linux modules
make[1]: Entering directory '/usr/src/linux-headers-6.1.0-kali7-amd64'
CC [M] /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.o
CC [M] /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/entry.o
AS [M] /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/intrinsics.o
CC [M] /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/../../common.o
clang: error: unknown argument: '-mfunction-return=thunk-extern'
clang: error: unknown argument: '-fconserve-stack'
clang: error: unknown argument: '-mfunction-return=thunk-extern'
clang: error: unsupported option '-mrecord-mcount' for target 'x86_64-unknown-linux-gnu'
clang: error: '-ftrivial-auto-var-init=zero' hasn't been enabled; enable it at your own peril for benchmarking purpose only with '-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang'
clang: error: unknown argument: '-fconserve-stack'
clang: error: unsupported option '-mrecord-mcount' for target 'x86_64-unknown-linux-gnu'
clang: error: '-ftrivial-auto-var-init=zero' hasn't been enabled; enable it at your own peril for benchmarking purpose only with '-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang'
clang: error: unknown argument: '-mfunction-return=thunk-extern'
clang: error: unknown argument: '-fconserve-stack'
clang: error: unsupported option '-mrecord-mcount' for target 'x86_64-unknown-linux-gnu'
clang: error: '-ftrivial-auto-var-init=zero' hasn't been enabled; enable it at your own peril for benchmarking purpose only with '-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang'
转换2
-mpreferred-stack-boundary=3
:这是一个用于优化的GCC选项,它设置堆栈边界对齐。这在 Rust 中是不被支持的,因为 Rust 有自己的内存模型和堆栈管理方式。- 告诉 gcc 编译器生成的代码应该尽可能使栈边界对齐到2的3次方(也就是8字节)。这样可以提高程序的性能。但是这个选项在 clang 和 c2rust 中并不被支持。
-mindirect-branch=thunk-extern
和-mindirect-branch-register
:这两个选项都是用于控制间接跳转的方式。这是 Intel CPU 对抵抗某种漏洞的控制,如 Spectre 漏洞。这在 Rust 中是不被支持的。- 这两个选项是为了支持 Intel 的 Control-flow Enforcement Technology (CET)。CET 是一种防止控制流劫持攻击的技术,如跳转/调用指令劫持(Jump/Call Oriented Programming, JOP/COP)以及返回指令劫持(Return Oriented Programming, ROP)。这两个选项在 clang 和 c2rust 中并不被支持。
-fno-allow-store-data-races
:这是一个 Clang 的选项,用于禁止在编译期间假定没有数据竞态条件。这在 Rust 中不被支持,因为 Rust 有自己的并发和同步原语。- 用于在多线程程序中防止数据竞争。这个选项在 clang 和 c2rust 中并不被支持。
-fno-var-tracking-assignments
:这是一个用于优化的GCC选项,用于关闭变量跟踪,可以减少调试信息,加快编译速度。这在 Rust 中是不被支持的。- 关闭 gcc 的变量跟踪功能。变量跟踪可以帮助调试,但是在某些情况下可能会增加编译时间和内存使用。这个选项在 clang 和 c2rust 中并不被支持。
-fconserve-stack
:这是一个GCC选项,尽可能减少堆栈使用,用于在内存受限的环境下编译。这在 Rust 中是不被支持的。- 应该尽可能少地使用栈空间。这对于栈空间有限的环境非常有用,例如嵌入式系统或内核代码。这个选项在 clang 和 c2rust 中并不被支持。
-mrecord-mcount
:这个选项在 gcc 中用于 ftrace 功能,但在 rust 中并不支持。- 告诉 gcc 在每个函数入口处生成特定的代码,这些代码在运行时可以用于记录函数的调用次数。这对于性能分析和代码覆盖率分析非常有用。然而,这个选项在 clang 和 c2rust 中并不被支持。
sed -i \
-e 's/-mpreferred-stack-boundary=3//g' \
-e 's/-mindirect-branch=thunk-extern//g' \
-e 's/-mindirect-branch-register//g' \
-e 's/-fno-allow-store-data-races//g' \
-e 's/-fno-var-tracking-assignments//g' \
-e 's/-fconserve-stack//g' \
-e 's/-mrecord-mcount//g' \
compile_commands.json
-falign-jumps=1
和-fmerge-constants
:这两个是优化标志,分别用于控制跳转指令的对齐和合并相同的常量。在 clang 中,这些标志并不被支持。-mrecord-mcount
:这个选项告诉 gcc 在每个函数入口处生成特定的代码,这些代码在运行时可以用于记录函数的调用次数。这对于性能分析和代码覆盖率分析非常有用。然而,这个选项在 clang 和 c2rust 中并不被支持。
添加 -fPIC
选项是因为它让编译器生成位置无关代码(Position Independent Code),这对于生成动态链接库或者被动态链接的代码非常重要。在某些系统中,例如许多 Linux 发行版,使用位置无关代码是强制的。
添加 -std=c99
是因为它指定了你要用的 C 语言标准。因为 C 语言的不同版本之间有一些差异,所以这是必要的。c2rust 可能需要这个信息来正确地转换你的代码。
二次错误
-Wno-format-truncation
: 此选项告诉编译器忽略可能会导致字符串截断的格式化字符串警告。如果在c2rust
中不受支持,那就需要移除。-Wno-format-overflow
: 此选项告诉编译器忽略可能会导致字符串溢出的格式化字符串警告。如果在c2rust
中不受支持,那就需要移除。-Wno-dangling-pointer
: 此选项告诉编译器忽略悬空指针警告。如果在c2rust
中不受支持,那就需要移除。-Wno-stringop-truncation
: 此选项告诉编译器忽略可能会导致字符串截断的字符串操作警告。如果在c2rust
中不受支持,那就需要移除。-Wno-zero-length-bounds
: 此选项告诉编译器忽略零长度数组边界警告。如果在c2rust
中不受支持,那就需要移除。-Wno-stringop-overflow
: 此选项告诉编译器忽略可能会导致字符串溢出的字符串操作警告。如果在c2rust
中不受支持,那就需要移除。-Wno-restrict
: 此选项告诉编译器忽略restrict限定符相关警告。如果在c2rust
中不受支持,那就需要移除。-Wno-maybe-uninitialized
: 此选项告诉编译器忽略可能会导致使用未初始化变量的警告。如果在c2rust
中不受支持,那就需要移除。-Werror=designated-init
: 此选项告诉编译器将设计的初始化警告视为错误。如果在c2rust
中不受支持,那就需要移除。-Wno-packed-not-aligned
: 此选项告诉编译器忽略打包但未对齐的警告。如果在c2rust
中不受支持,那就需要移除。-falign-jumps=1
: 此选项告诉编译器跳转对齐设置为1。如果在c2rust
中不受支持,那就需要移除。-fmerge-constants
: 此选项告诉编译器合并常量。如果在c2rust
中不受支持,那就需要移除。
所有这些选项被移除的原因是,c2rust
可能不支持这些选项,或者对这些选项的解释和你使用的C编译器不同。如果不移除这些选项,可能会导致c2rust
无法正确地解析和转换你的C代码。
└─$ c2rust transpile compile_commands.json
warning: Skipping existing file /home/kali/hypervisor-2.0/bfdriver/src/common.rs
warning: unknown warning option '-Wno-format-truncation' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-format-overflow'; did you mean '-Wno-shift-overflow'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-dangling-pointer' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-stringop-truncation'; did you mean '-Wno-string-concatenation'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-zero-length-bounds'; did you mean '-Wno-zero-length-array'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-stringop-overflow'; did you mean '-Wno-shift-overflow'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-restrict' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-maybe-uninitialized'; did you mean '-Wno-uninitialized'? [-Wunknown-warning-option]
warning: unknown warning option '-Werror=designated-init' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-packed-not-aligned'; did you mean '-Wno-over-aligned'? [-Wunknown-warning-option]
warning: optimization flag '-falign-jumps=1' is not supported [-Wignored-optimization-argument]
warning: optimization flag '-fmerge-constants' is not supported [-Wignored-optimization-argument]
warning: unknown warning option '-Wno-format-truncation' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-format-overflow'; did you mean '-Wno-shift-overflow'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-dangling-pointer' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-stringop-truncation'; did you mean '-Wno-string-concatenation'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-zero-length-bounds'; did you mean '-Wno-zero-length-array'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-stringop-overflow'; did you mean '-Wno-shift-overflow'? [-Wunknown-warning-option]
warning: unknown warning option '-Wno-restrict' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-maybe-uninitialized'; did you mean '-Wno-uninitialized'? [-Wunknown-warning-option]
warning: unknown warning option '-Werror=designated-init' [-Wunknown-warning-option]
warning: unknown warning option '-Wno-packed-not-aligned'; did you mean '-Wno-over-aligned'? [-Wunknown-warning-option]
In file included from /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c:29:
./include/linux/mm.h:2106:15: error: passing 'const char[14]' to parameter of type 'char *' discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
poison, "unused kernel");
^~~~~~~~~~~~~~~
./include/linux/mm.h:2060:24: note: passing argument to parameter 's' here
int poison, char *s);
^
In file included from /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c:29:
In file included from ./include/linux/mm.h:10:
In file included from ./include/linux/gfp.h:6:
In file included from ./include/linux/mmzone.h:8:
In file included from ./include/linux/spinlock.h:58:
./include/linux/bottom_half.h:19:24: warning: c2rust: Cannot translate GNU address of label expression
__local_bh_disable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
^~~~~~~~~
./include/linux/kernel.h:205:64: note: expanded from macro '_THIS_IP_'
#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
^~
In file included from /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c:29:
In file included from ./include/linux/mm.h:10:
In file included from ./include/linux/gfp.h:6:
In file included from ./include/linux/mmzone.h:8:
In file included from ./include/linux/spinlock.h:58:
./include/linux/bottom_half.h:32:23: warning: c2rust: Cannot translate GNU address of label expression
__local_bh_enable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
^~~~~~~~~
./include/linux/kernel.h:205:64: note: expanded from macro '_THIS_IP_'
#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
^~
In file included from /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c:29:
In file included from ./include/linux/mm.h:10:
In file included from ./include/linux/gfp.h:6:
In file included from ./include/linux/mmzone.h:8:
In file included from ./include/linux/spinlock.h:58:
./include/linux/bottom_half.h:19:24: warning: c2rust: Cannot translate GNU address of label expression
__local_bh_disable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
^~~~~~~~~
./include/linux/kernel.h:205:64: note: expanded from macro '_THIS_IP_'
#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
^~
In file included from /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c:29:
In file included from ./include/linux/mm.h:10:
In file included from ./include/linux/gfp.h:6:
In file included from ./include/linux/mmzone.h:8:
In file included from ./include/linux/spinlock.h:58:
./include/linux/bottom_half.h:32:23: warning: c2rust: Cannot translate GNU address of label expression
__local_bh_enable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
^~~~~~~~~
./include/linux/kernel.h:205:64: note: expanded from macro '_THIS_IP_'
#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
^~
14 warnings and 1 error generated.
Error while processing /home/kali/hypervisor-2.0/bfdriver/src/platform/linux/platform.c.
sed -i \
-e 's/-Wno-format-truncation//g' \
-e 's/-Wno-format-overflow//g' \
-e 's/-Wno-dangling-pointer//g' \
-e 's/-Wno-stringop-truncation//g' \
-e 's/-Wno-zero-length-bounds//g' \
-e 's/-Wno-stringop-overflow//g' \
-e 's/-Wno-restrict//g' \
-e 's/-Wno-maybe-uninitialized//g' \
-e 's/-Werror=designated-init//g' \
-e 's/-Wno-packed-not-aligned//g' \
-e 's/-falign-jumps=1//g' \
-e 's/-fmerge-constants//g' \
compile_commands.json