-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #32900 - alexcrichton:panic2abort, r=nikomatsakis
rustc: Implement custom panic runtimes This commit is an implementation of [RFC 1513] which allows applications to alter the behavior of panics at compile time. A new compiler flag, `-C panic`, is added and accepts the values `unwind` or `panic`, with the default being `unwind`. This model affects how code is generated for the local crate, skipping generation of landing pads with `-C panic=abort`. [RFC 1513]: https://github.com/rust-lang/rfcs/blob/master/text/1513-less-unwinding.md Panic implementations are then provided by crates tagged with `#![panic_runtime]` and lazily required by crates with `#![needs_panic_runtime]`. The panic strategy (`-C panic` value) of the panic runtime must match the final product, and if the panic strategy is not `abort` then the entire DAG must have the same panic strategy. With the `-C panic=abort` strategy, users can expect a stable method to disable generation of landing pads, improving optimization in niche scenarios, decreasing compile time, and decreasing output binary size. With the `-C panic=unwind` strategy users can expect the existing ability to isolate failure in Rust code from the outside world. Organizationally, this commit dismantles the `sys_common::unwind` module in favor of some bits moving part of it to `libpanic_unwind` and the rest into the `panicking` module in libstd. The custom panic runtime support is pretty similar to the custom allocator support with the only major difference being how the panic runtime is injected (takes the `-C panic` flag into account). Closes #32837
- Loading branch information
Showing
81 changed files
with
2,322 additions
and
931 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[package] | ||
authors = ["The Rust Project Developers"] | ||
name = "panic_abort" | ||
version = "0.0.0" | ||
|
||
[lib] | ||
path = "lib.rs" | ||
|
||
[dependencies] | ||
core = { path = "../libcore" } | ||
libc = { path = "../rustc/libc_shim" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
//! Implementation of Rust panics via process aborts | ||
//! | ||
//! When compared to the implementation via unwinding, this crate is *much* | ||
//! simpler! That being said, it's not quite as versatile, but here goes! | ||
|
||
#![no_std] | ||
#![crate_name = "panic_abort"] | ||
#![crate_type = "rlib"] | ||
#![unstable(feature = "panic_abort", issue = "32837")] | ||
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", | ||
html_favicon_url = "https://doc.rust-lang.org/favicon.ico", | ||
html_root_url = "https://doc.rust-lang.org/nightly/", | ||
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] | ||
#![cfg_attr(not(stage0), deny(warnings))] | ||
|
||
#![feature(staged_api)] | ||
|
||
#![cfg_attr(not(stage0), panic_runtime)] | ||
#![cfg_attr(not(stage0), feature(panic_runtime))] | ||
#![cfg_attr(unix, feature(libc))] | ||
#![cfg_attr(windows, feature(core_intrinsics))] | ||
|
||
// Rust's "try" function, but if we're aborting on panics we just call the | ||
// function as there's nothing else we need to do here. | ||
#[no_mangle] | ||
pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8), | ||
data: *mut u8, | ||
_data_ptr: *mut usize, | ||
_vtable_ptr: *mut usize) -> u32 { | ||
f(data); | ||
0 | ||
} | ||
|
||
// "Leak" the payload and shim to the relevant abort on the platform in | ||
// question. | ||
// | ||
// For Unix we just use `abort` from libc as it'll trigger debuggers, core | ||
// dumps, etc, as one might expect. On Windows, however, the best option we have | ||
// is the `__fastfail` intrinsics, but that's unfortunately not defined in LLVM, | ||
// and the `RaiseFailFastException` function isn't available until Windows 7 | ||
// which would break compat with XP. For now just use `intrinsics::abort` which | ||
// will kill us with an illegal instruction, which will do a good enough job for | ||
// now hopefully. | ||
#[no_mangle] | ||
pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 { | ||
return abort(); | ||
|
||
#[cfg(unix)] | ||
unsafe fn abort() -> ! { | ||
extern crate libc; | ||
libc::abort(); | ||
} | ||
|
||
#[cfg(windows)] | ||
unsafe fn abort() -> ! { | ||
core::intrinsics::abort(); | ||
} | ||
} | ||
|
||
// This... is a bit of an oddity. The tl;dr; is that this is required to link | ||
// correctly, the longer explanation is below. | ||
// | ||
// Right now the binaries of libcore/libstd that we ship are all compiled with | ||
// `-C panic=unwind`. This is done to ensure that the binaries are maximally | ||
// compatible with as many situations as possible. The compiler, however, | ||
// requires a "personality function" for all functions compiled with `-C | ||
// panic=unwind`. This personality function is hardcoded to the symbol | ||
// `rust_eh_personality` and is defined by the `eh_personality` lang item. | ||
// | ||
// So... why not just define that lang item here? Good question! The way that | ||
// panic runtimes are linked in is actually a little subtle in that they're | ||
// "sort of" in the compiler's crate store, but only actually linked if another | ||
// isn't actually linked. This ends up meaning that both this crate and the | ||
// panic_unwind crate can appear in the compiler's crate store, and if both | ||
// define the `eh_personality` lang item then that'll hit an error. | ||
// | ||
// To handle this the compiler only requires the `eh_personality` is defined if | ||
// the panic runtime being linked in is the unwinding runtime, and otherwise | ||
// it's not required to be defined (rightfully so). In this case, however, this | ||
// library just defines this symbol so there's at least some personality | ||
// somewhere. | ||
// | ||
// Essentially this symbol is just defined to get wired up to libcore/libstd | ||
// binaries, but it should never be called as we don't link in an unwinding | ||
// runtime at all. | ||
#[cfg(not(stage0))] | ||
pub mod personalities { | ||
|
||
#[no_mangle] | ||
#[cfg(not(all(target_os = "windows", | ||
target_env = "gnu", | ||
target_arch = "x86_64")))] | ||
pub extern fn rust_eh_personality() {} | ||
|
||
// On x86_64-pc-windows-gnu we use our own personality function that needs | ||
// to return `ExceptionContinueSearch` as we're passing on all our frames. | ||
#[no_mangle] | ||
#[cfg(all(target_os = "windows", | ||
target_env = "gnu", | ||
target_arch = "x86_64"))] | ||
pub extern fn rust_eh_personality(_record: usize, | ||
_frame: usize, | ||
_context: usize, | ||
_dispatcher: usize) -> u32 { | ||
1 // `ExceptionContinueSearch` | ||
} | ||
|
||
// Similar to above, this corresponds to the `eh_unwind_resume` lang item | ||
// that's only used on Windows currently. | ||
// | ||
// Note that we don't execute landing pads, so this is never called, so it's | ||
// body is empty. | ||
#[no_mangle] | ||
#[cfg(all(target_os = "windows", target_env = "gnu"))] | ||
pub extern fn rust_eh_unwind_resume() {} | ||
|
||
// These two are called by our startup objects on i686-pc-windows-gnu, but | ||
// they don't need to do anything so the bodies are nops. | ||
#[no_mangle] | ||
#[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))] | ||
pub extern fn rust_eh_register_frames() {} | ||
#[no_mangle] | ||
#[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))] | ||
pub extern fn rust_eh_unregister_frames() {} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
authors = ["The Rust Project Developers"] | ||
name = "panic_unwind" | ||
version = "0.0.0" | ||
|
||
[lib] | ||
path = "lib.rs" | ||
|
||
[dependencies] | ||
alloc = { path = "../liballoc" } | ||
core = { path = "../libcore" } | ||
libc = { path = "../rustc/libc_shim" } | ||
unwind = { path = "../libunwind" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,6 @@ | |
|
||
pub mod eh; | ||
|
||
use prelude::v1::*; | ||
use core::mem; | ||
|
||
pub struct DwarfReader { | ||
|
Oops, something went wrong.