ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

自建 rustc 如何启用 Sanitizer 支持:build.sanitizers 配置与 -Z sanitizer 使用

自建 rustc 如何启用 Sanitizer 支持:build.sanitizers 配置与 -Z sanitizer 使用 自建 rustc 如何启用 Sanitizer 支持build.sanitizers 配置与 -Z sanitizer 使用【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust如果你从 rust 仓库源码编译出 rustc自建工具链想让编译出的程序带 Sanitizer 插桩比如用 AddressSanitizer 抓内存越界、用 ThreadSanitizer 抓数据竞争需要做两件事一是在 bootstrap 配置里启用build.sanitizers true让构建流程从 compiler-rt 编译出 sanitizer 运行时库并放进目标 libdir二是在编译自己的代码时传-Zsanitizer...选项。本文基于仓库内的 Sanitizers 开发者指南 和 Unstable Book 的 sanitizer 旗标文档给出从配置、构建到验证的完整操作路径适用环境为支持目标 Sanitizer 的架构各 Sanitizer 支持的目标清单见下文。rustc 中 Sanitizer 的分工先明确两个配置各自的作用后文步骤都依赖这个分工build.sanitizers truebootstrap 配置构建 sanitizer 的运行时库。这些运行时来自 compiler-rt 项目在 bootstrap 的构建步骤 中通过 CMake 编译产物被复制到目标 libdir命名形如librustc-channel_rt.sanitizer.lib。-Zsanitizer...rustc 编译旗标对目标代码做编译期插桩。生成可执行文件时rustc 会从目标 libdir 链接对应的 sanitizer 运行时库查找顺序是先相对于 sysroot override再相对于默认系统根这样用 cargo-Z build-std构造的 sysroot 也能找到运行时。如果只插桩不构建运行时链接阶段会找不到 sanitizer 运行时库这也是为什么自建 rustc 场景下必须先做第一步。rustc 支持的 Sanitizer 及取值来自 sanitizer 旗标文档-Zsanitizer取值用途文档列出的支持目标address内存错误检测越界、use after free、泄漏等aarch64-apple-darwin、aarch64-unknown-fuchsia、aarch64-unknown-linux-gnu、x86_64-apple-darwin、x86_64-unknown-fuchsia、x86_64-unknown-freebsd、x86_64-unknown-linux-gnuthread数据竞争检测aarch64-apple-darwin、aarch64-unknown-linux-gnu、x86_64-apple-darwin、x86_64-unknown-freebsd、x86_64-unknown-linux-gnuleak运行时内存泄漏检测aarch64-unknown-linux-gnu、x86_64-apple-darwin、x86_64-unknown-linux-gnumemory未初始化读取检测aarch64-unknown-linux-gnu、x86_64-unknown-freebsd、x86_64-unknown-linux-gnuhwaddress基于硬件辅助的 ASan 变体内存占用更低aarch64-linux-android、aarch64-unknown-linux-gnucfi/kcfi前向控制流完整性CFI / 内核 KCFIKCFIaarch64-linux-android、aarch64-unknown-linux-gnu、x86_64-linux-android、x86_64-unknown-linux-gnumemtag基于 Armv8.5-A MTE 的快速内存错误检测aarch64-linux-android、aarch64-unknown-linux-gnu需-C target-featuremterealtime实时上下文中非确定性耗时调用检测文档未列出目标清单shadow-call-stack后向控制流保护aarch64 / RISC-Vriscv64imac-unknown-none-elf、riscv64gc-unknown-none-elf、riscv64gc-unknown-fuchsia等注意开发者指南 的取值列表只写了address、cfi、hwaddress、kcfi、leak、memory、thread七个是基础子集以 Unstable Book 的完整清单为准。第一步在 bootstrap.toml 中启用 sanitizer 运行时构建自建 rustc 的入口是仓库根目录的 bootstrap 构建系统./x/x.py配置参考 bootstrap.example.toml。在bootstrap.toml的[build]段加入[build] sanitizers true对应关系在 bootstrap.example.toml 中有注释说明#build.sanitizers false默认不构建 sanitizer 运行时注释为 Build the sanitizer runtimes。如果你只为特定交叉目标构建 sanitizer 运行时可以用目标级配置覆盖[build]段的值[target.你的目标三元组] sanitizers true示例配置中的注释写明该选项会覆盖[build]段中的同名选项。第二步构建 rustc 并确认运行时产物启用配置后执行常规构建即可./x build构建过程中bootstrap 会为支持该 sanitizer 的目标从src/llvm-project/compiler-rt构建运行时CMake Release 配置COMPILER_RT_BUILD_SANITIZERSON并把产物复制进目标 libdir——这一步由 compile 构建步骤 在 stage1 及以上完成。构建完成后build/x86_64-unknown-linux-gnu/rust-std-sanitizers以你的 host 目标为准目录下应能找到librustc-channel_rt.address.lib等运行时文件目录名和命名规则来自开发者指南描述的 runtimes are placed into target libdir。第三步用 -Zsanitizer 编译并运行你的程序在你的 cargo 项目里启用 sanitizer文档给出的标准做法是通过RUSTFLAGS传入-Zsanitizer并搭配-Zbuild-std --target$ RUSTFLAGS-Zsanitizeraddress cargo build -Zbuild-std --target x86_64-unknown-linux-gnu几个必须保留的参数说明均来自 sanitizer 文档--target必须显式传文档明确要求 always remember to pass--targetflag否则RUSTFLAGS会作用到 build scripts 和 procedural macros 上而 proc macro 需要插桩版本的 rustc实际使用中应尽量回避。-Zbuild-std用当前工具链重新编译并插桩标准库。文档对多数 sanitizer 强烈建议这样做对 MemorySanitizer 则是硬性要求——MSan 需要全部程序代码被插桩否则必然产生误报。运行期额外选项各 sanitizer 的运行时选项如ASAN_OPTIONSdetect_leaks1属于运行时行为通过环境变量传递编译期额外选项可以经llvm-argscodegen 旗标传给 LLVM例如-Cllvm-args-dfsan-combine-pointer-labels-on-loadfalse。以 AddressSanitizer 的越界示例为例文档示例代码fn main() { let xs [0, 1, 2, 3]; let _y unsafe { *xs.as_ptr().offset(4) }; }$ export RUSTFLAGS-Zsanitizeraddress RUSTDOCFLAGS-Zsanitizeraddress $ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu结果验证如何判断 Sanitizer 生效验证方式分两层程序层面的报告输出和编译器测试层面的回归测试。1. 程序运行时出现 sanitizer 报告上面 ASan 示例运行时文档给出的示例输出文档示例具体地址和 pc 值会随环境变化37882ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe400e6250 at pc 0x5609a841fb20 bp 0x7ffe400e6210 sp 0x7ffe400e6208 READ of size 4 at 0x7ffe400e6250 thread T0 #0 0x5609a841fb1f in example::main::h628ffc6626ed85b2 /.../src/main.rs:3:23 ... SUMMARY: AddressSanitizer: stack-buffer-overflow /.../src/main.rs:3:23 in example::main::h628ffc6626ed85b2 ... 37882ABORTING看到ERROR: AddressSanitizer: ...加SUMMARY行即说明插桩和运行时都工作正常。类似地ThreadSanitizer 的示例输出以WARNING: ThreadSanitizer: data race开头MemorySanitizer 以WARNING: MemorySanitizer: use-of-uninitialized-value开头均为文档示例。一个影响可读性的前提sanitizer 只有在llvm-symbolizer位于PATH中时才产生带符号的堆栈否则堆栈只有地址。2. 用仓库自带测试验证你的工具链如果你想确认自建工具链本身能跑 sanitizer 测试用 开发者指南 给出的命令测试目录实际为tests/ui/sanitizer/codegen 测试为tests/codegen-llvm/sanitizer/./x test --force-rerun tests/ui/sanitizer/这些测试依赖build.sanitizers true构建的运行时当某个 sanitizer 在你的目标上不受支持时带needs-sanitizer-*指令的测试会被 compiletest 自动忽略而不是失败——如果测试大面积被跳过说明目标不在该 sanitizer 的支持清单里回查上表即可。细粒度控制按函数和按 sanitizer 条件编译插桩粒度默认是函数级、默认全部插桩。文档提供两个不稳定特性做精细化控制都需要 nightly feature gatesanitize属性文档在函数、模块或 impl 块上开关插桩用于避开性能热点或 sanitizer 不支持的构造#![feature(sanitize)] #[sanitize(address off)] mod foo { fn unsanitized() { /* 不插桩 */ } #[sanitize(address on)] fn sanitized() { /* 恢复插桩 */ } }cfg_sanitize文档按当前启用的 sanitizer 条件编译不同代码路径#![feature(cfg_sanitize)] #[cfg(sanitize thread)] fn a() { /* 仅 TSan 构建下编译 */ }已知限制目标支持是硬边界rustc --target ... -Zsanitizer...只认识该目标定义中supported_sanitizers列表里的 sanitizer不在清单中的组合会被拒绝。ThreadSanitizer不支持std::sync::atomic::fence也不支持内联汇编中的同步未插桩的同步路径可能产生误报。MemorySanitizer要求全部代码插桩C/C 依赖需用 Clang-fsanitizememory重编否则误报。AddressSanitizer能与未插桩代码共存但会降低部分 bug 的检出能力。与 C 等混合语言项目链接时Rust 自带的 compiler runtime 可能与对方的运行时冲突不稳定选项-Zexternal-clangrt可让 rustc 跳过链接自带运行时改链外部如 clang 的运行时。Sanitizer 会带来运行时代价且不能覆盖所有问题文档建议与测试、fuzzing 等实践配合使用。可选分支为新目标启用某个 sanitizer如果你的目标是 LLVM 已支持但 rustc 目标定义还没声明的 sanitizer 组合开发者指南 给出五步在目标定义位于compiler/rustc_target/src/spec/下的对应目标文件的supported_sanitizers列表中加入该 sanitizer此后rustc --target .. -Zsanitizer..会识别它为受支持构建该目标的 sanitizer 运行时并放进 libdir即本文第一步的机制让 compiletest 知道该目标支持此 sanitizer使needs-sanitizer-*标记的测试能在该目标上运行运行./x test --force-rerun tests/ui/sanitizer/验证在 CI 配置中加--enable-sanitizers让发布流程构建并分发 sanitizer 运行时。完成到这里你的自建 rustc 工具链具备了完整的 sanitizer 能力build.sanitizers提供运行时-Zsanitizer...触发插桩运行输出和./x test提供两级验证。【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表