Emit function declarations for functions with `#[linkage="extern_weak"]` by 1c3t3a · Pull Request #138349 · rust-lang/rust

bjorn3

bjorn3

compiler-errors

rcvalle

@bors bors added S-waiting-on-bors

Status: Waiting on bors to run and complete tests. Bors will change the label on completion.

and removed S-waiting-on-review

Status: Awaiting review from the assignee but also interested parties.

labels

Mar 14, 2025

fmease added a commit to fmease/rust that referenced this pull request

Mar 14, 2025
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 rust-lang#115199.

This change switches to emitting a proper function declaration instead of a global i8. This allows CFI to work for extern_weak functions. Example:
```
`@_rust_extern_with_linkage_FOO` = internal global ptr `@FOO`
...
declare !type !61 !type !62 !type !63 !type !64 extern_weak void `@FOO(double)` unnamed_addr #6
```

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

r? `@rcvalle`

cc `@jakos-sec`

bors added a commit to rust-lang-ci/rust that referenced this pull request

Mar 14, 2025

@bors bors added S-waiting-on-author

Status: This is awaiting some action (such as code changes or more information) from the author.

and removed S-waiting-on-bors

Status: Waiting on bors to run and complete tests. Bors will change the label on completion.

labels

Mar 14, 2025

@1c3t3a @jakos-sec

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
rust-lang#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>

bors added a commit to rust-lang-ci/rust that referenced this pull request

Mar 17, 2025
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 rust-lang#115199.

This change switches to emitting a proper function declaration instead of a global i8. This allows CFI to work for extern_weak functions. Example:
```
`@_rust_extern_with_linkage_FOO` = internal global ptr `@FOO`
...
declare !type !61 !type !62 !type !63 !type !64 extern_weak void `@FOO(double)` unnamed_addr rust-lang#6
```

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

r? `@rcvalle`

cc `@jakos-sec`

try-job: test-various

@bors bors added S-waiting-on-bors

Status: Waiting on bors to run and complete tests. Bors will change the label on completion.

and removed S-waiting-on-author

Status: This is awaiting some action (such as code changes or more information) from the author.

labels

Mar 17, 2025

bors added a commit to rust-lang-ci/rust that referenced this pull request

Mar 17, 2025
…iaskrgr

Rollup of 7 pull requests

Successful merges:

 - rust-lang#133870 (Stabilize `asm_goto` feature gate)
 - rust-lang#137449 (Denote `ControlFlow` as `#[must_use]`)
 - rust-lang#137465 (mir_build: Avoid some useless work when visiting "primary" bindings)
 - rust-lang#138349 (Emit function declarations for functions with `#[linkage="extern_weak"]`)
 - rust-lang#138412 (Install licenses into `share/doc/rust/licenses`)
 - rust-lang#138577 (rustdoc-json: Don't also include `#[deprecated]` in `Item::attrs`)
 - rust-lang#138588 (Avoid double lowering of idents)

Failed merges:

 - rust-lang#138321 ([bootstrap] Distribute split debuginfo if present)

r? `@ghost`
`@rustbot` modify labels: rollup

rust-timer added a commit to rust-lang-ci/rust that referenced this pull request

Mar 17, 2025
Rollup merge of rust-lang#138349 - 1c3t3a:external-weak-cfi, r=rcvalle

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 rust-lang#115199.

This change switches to emitting a proper function declaration instead of a global i8. This allows CFI to work for extern_weak functions. Example:
```
`@_rust_extern_with_linkage_FOO` = internal global ptr `@FOO`
...
declare !type !61 !type !62 !type !63 !type !64 extern_weak void `@FOO(double)` unnamed_addr rust-lang#6
```

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

r? `@rcvalle`

cc `@jakos-sec`

try-job: test-various

This was referenced

Apr 10, 2025

matthiaskrgr pushed a commit to matthiaskrgr/rust that referenced this pull request

Apr 16, 2025
Previously (rust-lang#115200,
rust-lang#138002), we
added `#[no_sanitize(cfi)]` to all code paths that call to a weakly
linked function.

In rust-lang#138349 we fixed the root cause
for this issue, which means we can now remove the corresponding
attributes.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request

Apr 16, 2025
cfi: Remove #[no_sanitize(cfi)] for extern weak functions

Previously (rust-lang#115200, rust-lang#138002), we added `#[no_sanitize(cfi)]` to all code paths that call to a weakly linked function.

In rust-lang#138349 we fixed the root cause for this issue, which means we can now remove the corresponding attributes.

r? `@rcvalle`

rust-timer added a commit to rust-lang-ci/rust that referenced this pull request

Apr 17, 2025
Rollup merge of rust-lang#139667 - 1c3t3a:remove-no-sanitize, r=m-ou-se

cfi: Remove #[no_sanitize(cfi)] for extern weak functions

Previously (rust-lang#115200, rust-lang#138002), we added `#[no_sanitize(cfi)]` to all code paths that call to a weakly linked function.

In rust-lang#138349 we fixed the root cause for this issue, which means we can now remove the corresponding attributes.

r? `@rcvalle`

github-actions bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request

Apr 19, 2025
cfi: Remove #[no_sanitize(cfi)] for extern weak functions

Previously (rust-lang/rust#115200, rust-lang/rust#138002), we added `#[no_sanitize(cfi)]` to all code paths that call to a weakly linked function.

In rust-lang/rust#138349 we fixed the root cause for this issue, which means we can now remove the corresponding attributes.

r? `@rcvalle`

github-actions bot pushed a commit to model-checking/verify-rust-std that referenced this pull request

Apr 19, 2025
Previously (rust-lang#115200,
rust-lang#138002), we
added `#[no_sanitize(cfi)]` to all code paths that call to a weakly
linked function.

In rust-lang#138349 we fixed the root cause
for this issue, which means we can now remove the corresponding
attributes.

github-actions bot pushed a commit to model-checking/verify-rust-std that referenced this pull request

Apr 19, 2025
cfi: Remove #[no_sanitize(cfi)] for extern weak functions

Previously (rust-lang#115200, rust-lang#138002), we added `#[no_sanitize(cfi)]` to all code paths that call to a weakly linked function.

In rust-lang#138349 we fixed the root cause for this issue, which means we can now remove the corresponding attributes.

r? `@rcvalle`