【问题标题】:How to export a symbol from a Rust executable?如何从 Rust 可执行文件中导出符号?
【发布时间】:2017-05-01 01:05:29
【问题描述】:

我正在尝试从 Rust 可执行文件中导出符号:

#[allow(non_upper_case_globals)]
#[no_mangle]
pub static exported_symbol: [u8; 1] = *b"\0";

fn main() {
    println!("Hello, world!");
}

exported_symbol 似乎没有被生成的二进制文件导出:

$ cargo build
$ nm ./target/debug/test_export| grep exported_symbol

另一方面,如果我使用相同的源构建一个库,则该符号确实会被导出:

$ rustc --crate-type cdylib src/main.rs
$ nm libmain.so| grep exported_symbol
0000000000016c10 R exported_symbol

我在 Linux x86-64 上使用 Rust 1.18.0。

【问题讨论】:

  • 为什么可执行文件要导出符号?
  • 我希望它模拟一个加载插件的现有 C 二进制文件,部分接口是二进制文件使插件可以使用符号。
  • Rust 1.17 是当前的稳定版本,如果您使用的是 1.18,您可能应该包含 beta / nightly date 和 git hash。

标签: rust


【解决方案1】:

您可以将链接器选项传递给 rustc,例如:

$ rustc src/main.rs --crate-type bin -C link-args=-Wl,-export-dynamic
$ nm main|grep export
00000000000d79c4 R exported_symbol

您可能希望将其放在 .cargo/config 的 rustflags 中,例如:

[target.x86_64-unknown-linux-gnu]
rustflags = [ "-C", "link-args=-Wl,-export-dynamic" ]

【讨论】:

  • cargo rustc 也可用。
  • 太棒了,谢谢。有没有办法在 Cargo.toml 中记录?
  • 现在我很好奇:为什么 Rust 默认不导出这些符号?你能详细说明一下吗? :)
  • 在导出符号blog.flameeyes.eu/2008/02/…时可能会出现性能影响或其他问题
【解决方案2】:

我会在.cargo/config 文件中推荐这个而不是上面的:

[build]
rustflags = ["-C", "link-args=-rdynamic"]

-rdynamic 更便携。特别是,它适用于 Linux 和 MacOS。

此外,在当前的 Rust/LLVM 版本中,除非实际使用了符号,否则链接器很可能会删除它。

为了避免这种情况,应调用引用导出函数的虚拟函数(在任何时间点,例如在main 函数中)。

这样的函数的一个例子可能是:

pub fn init() {
    let funcs: &[*const extern "C" fn()] = &[
        exported_function_1 as _,
        exported_function_2 as _,
        exported_function_3 as _      
    ];
    std::mem::forget(funcs);
}

当然,导出的函数应该具有#[no_mangle] 属性:

#[no_mangle]
pub extern "C" fn exported_function_1() {
  // ...
}

【讨论】:

    猜你喜欢
    • 2011-04-26
    • 2013-04-27
    • 2011-01-23
    • 1970-01-01
    • 2018-01-31
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多