如何将带依赖的Rust项目编译为单个LLVM bitcode文件用于SAW验证
方案1:直接使用llvm-link合并已生成的分散bitcode(最简便)
这是改动最小的方案,无需调整现有编译流程:
- 按照你现有命令编译,生成所有crate对应的bitcode文件:
RUSTFLAGS="--emit=llvm-bc" cargo build --release - 安装匹配rustc版本的LLVM工具链,避免版本不兼容:
工具默认路径为rustup component add llvm-tools-preview~/.rustup/toolchains/<当前使用的工具链名>/lib/rustlib/<目标架构>/bin/,后续执行工具时直接调用该路径下的二进制文件即可。 - 进入bitcode生成目录,执行合并操作:
其中cd target/release/deps # 替换路径为你实际的llvm-link路径 <llvm-tools路径>/llvm-link -internalize -only-needed -o merged_full.bc foobar-*.bc pythagoras-*.bc-internalize参数会将非导出符号标记为内部链接,-only-needed会过滤未使用的符号,最终生成的merged_full.bc就是包含所有依赖、无外部引用的单bitcode文件。
如果你的项目用到了标准库且需要将标准库逻辑也合并进bitcode,需要使用nightly工具链开启标准库编译:
RUSTFLAGS="--emit=llvm-bc" cargo +nightly build -Z build-std --release
生成的标准库bitcode也会出现在deps目录下,合并时一并加入即可。
方案2:静态库提取bitcode(兼容性更好的hack方案)
如果方案1出现依赖缺失、符号引用异常的问题,可以用静态库内嵌bitcode的方式实现:
- 修改Cargo.toml,将库类型指定为静态库:
[lib] crate-type = ["staticlib"] - 开启bitcode嵌入编译:
编译完成后生成的RUSTFLAGS="-C embed-bitcode=yes" cargo build --releasetarget/release/lib<你的项目名>.a静态库中已经内嵌了所有依赖的bitcode段。 - 提取静态库中的bitcode并合并:
mkdir temp && cd temp # 解压静态库 <llvm-tools路径>/llvm-ar x ../target/release/libfoobar.a # 提取每个目标文件中的bitcode段 for obj in *.o; do <llvm-tools路径>/llvm-objcopy --dump-section .llvmbc=${obj%.o}.bc "$obj" done # 合并所有bitcode <llvm-tools路径>/llvm-link -internalize -only-needed -o merged_full.bc *.bc
内容的提问来源于stack exchange,提问作者ouroboring
相关产品推荐
相关产品推荐

