应用二进制接口 (ABI)

本节介绍影响 crate 编译输出的 ABI 的特性。

关于指定导出函数 ABI 的信息,请参阅 外部函数。关于指定链接外部库 ABI 的信息,请参阅 外部块

used 属性

used 属性只能应用于 static。这个 属性强制编译器将变量保留在输出对象文件(.o、.rlib 等,不包括最终二进制文件)中,即使该变量未被 crate 中的任何其他项使用或引用。然而,链接器仍然可以自由地移除此类项。

下面是一个示例,展示了编译器在何种条件下将 static 项保留在输出对象文件中。

#![allow(unused)]
fn main() {
// foo.rs

// This is kept because of `#[used]`:
#[used]
static FOO: u32 = 0;

// This is removable because it is unused:
#[allow(dead_code)]
static BAR: u32 = 0;

// This is kept because it is publicly reachable:
pub static BAZ: u32 = 0;

// This is kept because it is referenced by a public, reachable function:
static QUUX: u32 = 0;

pub fn quux() -> &'static u32 {
    &QUUX
}

// This is removable because it is referenced by a private, unused (dead) function:
static CORGE: u32 = 0;

#[allow(dead_code)]
fn corge() -> &'static u32 {
    &CORGE
}
}
$ rustc -O --emit=obj --crate-type=rlib foo.rs

$ nm -C foo.o
0000000000000000 R foo::BAZ
0000000000000000 r foo::FOO
0000000000000000 R foo::QUUX
0000000000000000 T foo::quux

no_mangle 属性

no_mangle 属性可用于任何 ,以禁用标准的符号名称修饰(mangling)。该项的符号将是该项名称的标识符。

此外,该项将从生成的库或对象文件中公开导出,类似于 used 属性

此属性不安全,因为未修饰的符号可能与同名的另一个符号(或与一个周知符号)发生冲突,从而导致未定义行为。

#![allow(unused)]
fn main() {
#[unsafe(no_mangle)]
extern "C" fn foo() {}
}

版本差异:在 2024 版本之前,允许在不加 unsafe 限定词的情况下使用 no_mangle 属性。

link_section 属性指定了 函数static 的内容将放入的目标文件段(section)。它使用 MetaNameValueStr 语法来指定段名称。

此属性不安全,因为它允许用户将数据和代码放置到不期望它们存在的内存段中,例如将可变数据放入只读区域。

#![allow(unused)]
fn main() {
#[unsafe(no_mangle)]
#[unsafe(link_section = ".example_section")]
pub static VAR1: u32 = 1;
}

版本差异:在 2024 版本之前,允许在不加 unsafe 限定词的情况下使用 link_section 属性。

export_name 属性

export_name 属性指定了 函数static 将导出的符号名称。它使用 MetaNameValueStr 语法来指定符号名称。

此属性不安全,因为具有自定义名称的符号可能与同名的另一个符号(或与一个周知符号)发生冲突,从而导致未定义行为。

#![allow(unused)]
fn main() {
#[unsafe(export_name = "exported_symbol_name")]
pub fn name_in_rust() { }
}

版本差异:在 2024 版本之前,允许在不加 unsafe 限定词的情况下使用 export_name 属性。