gpt4 book ai didi

Rust:在 LLVM Bitcode 中包含依赖项

转载 作者:行者123 更新时间:2023-12-04 14:51:20 34 4
gpt4 key购买 nike

我正在使用 SAW 验证一些 Rust 代码. SAW 要求您编译为 LLVM bitcode ,然后您可以导入并验证。我知道您可以使用 --emit=llvm-bc 生成位码标记为 rustc,这对于没有依赖项的项目非常有用。
尝试编译使用外部 crate 的项目时会出现问题。这是 Cargo.toml 文件的示例:

[package]
name = "foobar"
version = "0.1.0"
edition = "2018"

[dependencies]
pythagoras = "0.1.1"
这是一个基本的 src/lib.rs我们可能想要编译和验证:
pub use pythagoras;

#[no_mangle]
pub extern "C" fn calc_hypot(a: u32, b: u32) -> f64 {
pythagoras::theorem(a, b)
}
我们可以把它编译成这样的位码: RUSTFLAGS="--emit=llvm-bc" cargo build --release .问题是当前模块的位码及其依赖项是单独生成的(在 target/release/deps/foobar-something.bctarget/release/deps/pythagoras-somethingelse.bc 中)。它们仅在生成实际编译库时组合。
有没有办法生成包含当前模块及其所有依赖项的单个位码文件,以便可以导入该文件,并且不会引用任何外部名称?我意识到这是一个非常小众的案例,因此 hacky 解决方案(例如:编译为 C 静态库,然后以某种方式将其转换回 LLVM 位码)也是完全合理的。
谢谢!

最佳答案

扩展在 Aiden4评论:

  • 删除当前目标目录以防止使用任何旧工件:rm -r target/
  • RUSTFLAGS="--emit=llvm-bc" cargo build --release 编译它
  • 将位码文件与 llvm-link target/release/deps/*.bc > withdeps.bc 链接在一起

  • 这将为您提供几乎所有的依赖项。事实证明,所有 Rust 程序都隐含依赖于 corestd虽然(虽然你可以通过不稳定的 #![no_core] 避免这种情况,但祝你好运,实际上可以通过这种方式编译),所以你可能也想获得比特码。
    最简单的方法是将标准库从源代码编译为位码。 cargo has experimental support for building the standard libraries from source ,所以只需追加 -Z build-std --target x86_64-unknown-linux-gnu (并在需要时更新目标)到您的 cargo构建命令。使用时 --target ,这是 -Z build-std 所要求的,构建文件放在特定于目标的目录中, target/x86_64-unknown-linux-gnu/release/deps/在这种情况下。 targetless 目录包含标准库的构建依赖项:我们不想要那个!
    我们不想链接所有标准库。我们真的只需要 std及其依赖项: proc_macro这里不需要,因为我们正在编译为二进制文件,而不是 proc 宏。我们还需要链接到 proc_abortpanic_unwind ,将其与我们选择的展开代码生成设置相匹配。默认是展开,所以让我们删除另一个, proc_abort .让我们将这些库发送到砧板: rm target/x86_64-unknown-linux-gnu/release/deps/{panic_abort,proc_macro}-*.bc .
    这次让我们尝试真正的链接:
    rm -r target/
    RUSTFLAGS="--emit=llvm-bc" cargo build --release -Z build-std --target x86_64-unknown-linux-gnu
    rm target/x86_64-unknown-linux-gnu/release/deps/{panic_abort,proc_macro}-*.bc
    llvm-link target/x86_64-unknown-linux-gnu/release/deps/*.bc > withalldeps.bc
    是的,它奏效了!好吧,除了对那里的未定义函数的调用仍然设法通过。 __rust_alloc , __rust_dealloc , __rust_realloc , 和 __rust_alloc_zeroed是使用 Rust 的 LLVM 分支定义的魔法函数。标准库还依赖于 libpthread dlsym 它们是通常用 C 实现的语言无关库/函数。您可以使用 clang和一个 libc支持使用 Clang 编译的实现(GNU libc 不支持,我认为 musl 可能在这里工作?)以在需要时获得它。此外,如果您正在编译为可执行文件,则很难找到 main来自 _start .

    关于Rust:在 LLVM Bitcode 中包含依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69042049/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com