Files
rust/tests/codegen/sanitizer/cfi/external_weak_symbols.rs
Bastian Kersting b30cf11b96 Emit function declarations for functions with #[linkage="extern_weak"]
Currently, when declaring an extern weak function in Rust, we use the
following syntax:
```rust
unsafe extern "C" {
   #[linkage = "extern_weak"]
   static FOO: Option<unsafe extern "C" fn() -> ()>;
}
```
This allows runtime-checking the extern weak symbol through the Option.

When emitting LLVM-IR, the Rust compiler currently emits this static
as an i8, and a pointer that is initialized with the value of the global
i8 and represents the nullabilty e.g.
```
@FOO = extern_weak global i8
@_rust_extern_with_linkage_FOO = internal global ptr @FOO
```

This approach does not work well with CFI, where we need to attach CFI
metadata to a concrete function declaration, which was pointed out in
https://github.com/rust-lang/rust/issues/115199.

This change switches to emitting a proper function declaration instead
of a global i8. This allows CFI to work for extern_weak functions.

We keep initializing the Rust internal symbol with the function
declaration, which preserves the correct behavior for runtime checking
the Option.

Co-authored-by: Jakob Koschel <jakobkoschel@google.com>
2025-03-17 08:27:53 +00:00

25 lines
786 B
Rust

// Verifies that type metadata identifiers for for weakly-linked symbols are
// emitted correctly.
//
//@ needs-sanitizer-cfi
//@ compile-flags: -Clinker-plugin-lto -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static
#![crate_type = "bin"]
#![feature(linkage)]
unsafe extern "C" {
#[linkage = "extern_weak"]
static FOO: Option<unsafe extern "C" fn(f64) -> ()>;
}
// CHECK: @_rust_extern_with_linkage_FOO = internal global ptr @FOO
fn main() {
unsafe {
if let Some(method) = FOO {
method(4.2);
// CHECK: call i1 @llvm.type.test(ptr {{%method|%0}}, metadata !"_ZTSFvdE")
}
}
}
// CHECK: declare !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} extern_weak void @FOO(double) unnamed_addr #{{[0-9]+}}