Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

panic runtime and C-unwind documentation #1226

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
62 changes: 33 additions & 29 deletions src/linkage.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,35 +272,39 @@ binary link:

Passing `rlib`s directly into your foreign linker is currently unsupported.

### Prohibited linkage and foreign unwinding

r[link.foreign-code.prohibited]

Undfined behavior may be caused by foreign code unwinding into a Rust crate
with these characteristics:

* The foreign unwind enters Rust via a function or function pointer declared
with an ABI that permits unwinding, that is, `"Rust"` (the default ABI) or
any `-unwind` ABI
* The Rust crate containing the `-unwind` ABI declaration was compiled with
`panic=unwind`
* The final binary is linked with [the `panic=abort` runtime][panic-runtime]

> **Note**: To protect against this undefined behavior, `rustc` does not permit
> linking the `panic=abort` runtime against any crate that was compiled with
> `panic=unwind` if that crate also contains a call to a foreign function or
> function pointer declared with an `-unwind` ABI. Note that this prohibition
> applies even when linking a static or dynamic library that only includes Rust
> code, since the resulting library may be subsequently linked against another
> library that may unwind. However, use of the `Rust` (default) ABI does not
> cause a link-error, since that ABI is not expected to be used as an
> entrypoint into a static or shared library.

> **Note**: the restriction can only be violated when mixing code with different
> `-C panic` flags. This is not possible in normal use of cargo, so most users
> need not be concerned about this.

r[link.foreign-code.prohibited.lint.ffi_unwind_calls]
> [!NOTE]
> Rust code compiled or linked with a different instance of the Rust runtime counts as a
> "foreign code" for the purpose of this section.

### Prohibited linkage and unwinding

r[link.unwinding]
If you are *not* using `rustc` to link Rust files, you must take care to ensure that unwinding is
handled consistently across the entire binary. This includes using `dlopen` or similar facilities
where linking is done by the system runtime without `rustc` being involved.

r[link.unwinding.potential]
A Rust binary or `staticlib` is called *potentially unwinding* if any of the following conditions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a name for "the final artifact of Rust linkage, with a single Rust runtime included"? Always saying "Rust binary or staticlib" is awkward...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this also needs to account for cdylib?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we really need a proper term for this, not an enumeration. "final Rust artifact"? Or can we say "Rust binary" since staticlib and cdylib are binaries but in some sense rlib is not? Not sure if that makes any sense...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bjorn3 maybe you have a good idea for what to call this?

Copy link
Member

@bjorn3 bjorn3 Dec 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a great name for it either unfortunately. bin, dylib, cdylib and proc-macro are all linked crates, but staticlib isn't.

is met:
- The binary or `staticlib` is linked with [the `panic=unwind` runtime][panic-runtime].
- The binary or `staticlib` contains a crate built with `-Cpanic=unwind` that makes a call
to a function using a `-unwind` ABI.
- The binary or `staticlib` makes a `"Rust"` ABI call to code running in a separately built
`staticlib` (i.e., a separate instance of the Rust runtime), and that other `staticlib` is
potentially unwinding.

> [!NOTE]
> This definition captures whether a `"Rust"` ABI call inside a Rust binary or `staticlib` can ever
> unwind.

r[link.unwinding.prohibited]
If a Rust binary or `staticlib` is potentially unwinding, then all its crates must be built with `-Cpanic=unwind`.

> [!NOTE]
> This restriction can only be violated when mixing code with different `-C panic` flags
> while also using a non-`rustc` linker. Most users to not have to be concerned about this.

r[link.unwinding.prohibited.lint.ffi_unwind_calls]
To guarantee that a library will be sound (and linkable with `rustc`)
regardless of the panic mode used at link-time, the [`ffi_unwind_calls` lint]
may be used. The lint flags any calls to `-unwind` foreign functions or
Expand Down
2 changes: 1 addition & 1 deletion src/panic.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ which will occur:
* The function returns a `Result::Err` containing an opaque type.

> [!NOTE]
> Rust code compiled or linked with a different runtime counts as a
> Rust code compiled or linked with a different instance of the Rust runtime counts as a
> "foreign exception" for the purpose of this guarantee. Thus, a library that
> uses `panic!` and is linked against one version of the Rust standard library,
> invoked from an application that uses a different version of the standard
Expand Down