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

rustc: Implement custom panic runtimes #32900

Merged
merged 2 commits into from May 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 14 additions & 2 deletions mk/crates.mk
Expand Up @@ -53,7 +53,8 @@ TARGET_CRATES := libc std term \
getopts collections test rand \
core alloc \
rustc_unicode rustc_bitflags \
alloc_system alloc_jemalloc
alloc_system alloc_jemalloc \
panic_abort panic_unwind unwind
RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_driver \
rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
rustc_data_structures rustc_platform_intrinsics \
Expand All @@ -72,10 +73,18 @@ DEPS_libc := core
DEPS_rand := core
DEPS_rustc_bitflags := core
DEPS_rustc_unicode := core
DEPS_panic_abort := libc alloc
DEPS_panic_unwind := libc alloc unwind
DEPS_unwind := libc

# FIXME(stage0): change this to just `RUSTFLAGS_panic_abort := ...`
RUSTFLAGS1_panic_abort := -C panic=abort
RUSTFLAGS2_panic_abort := -C panic=abort
RUSTFLAGS3_panic_abort := -C panic=abort

DEPS_std := core libc rand alloc collections rustc_unicode \
native:backtrace \
alloc_system
alloc_system panic_abort panic_unwind unwind
DEPS_arena := std
DEPS_glob := std
DEPS_flate := std native:miniz
Expand Down Expand Up @@ -148,6 +157,9 @@ ONLY_RLIB_rustc_unicode := 1
ONLY_RLIB_rustc_bitflags := 1
ONLY_RLIB_alloc_system := 1
ONLY_RLIB_alloc_jemalloc := 1
ONLY_RLIB_panic_unwind := 1
ONLY_RLIB_panic_abort := 1
ONLY_RLIB_unwind := 1

TARGET_SPECIFIC_alloc_jemalloc := 1

Expand Down
3 changes: 2 additions & 1 deletion mk/tests.mk
Expand Up @@ -23,7 +23,8 @@ DEPS_collectionstest :=
$(eval $(call RUST_CRATE,collectionstest))

TEST_TARGET_CRATES = $(filter-out core rustc_unicode alloc_system libc \
alloc_jemalloc,$(TARGET_CRATES)) \
alloc_jemalloc panic_unwind \
panic_abort,$(TARGET_CRATES)) \
collectionstest coretest
TEST_DOC_CRATES = $(DOC_CRATES) arena flate fmt_macros getopts graphviz \
log rand rbml serialize syntax term test
Expand Down
19 changes: 18 additions & 1 deletion src/bootstrap/rustc.rs
Expand Up @@ -48,10 +48,11 @@ fn main() {
} else {
env::var_os("RUSTC_REAL").unwrap()
};
let stage = env::var("RUSTC_STAGE").unwrap();

let mut cmd = Command::new(rustc);
cmd.args(&args)
.arg("--cfg").arg(format!("stage{}", env::var("RUSTC_STAGE").unwrap()));
.arg("--cfg").arg(format!("stage{}", stage));

if let Some(target) = target {
// The stage0 compiler has a special sysroot distinct from what we
Expand All @@ -78,6 +79,22 @@ fn main() {
cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::<Vec<_>>());
}

// If we're compiling specifically the `panic_abort` crate then we pass
// the `-C panic=abort` option. Note that we do not do this for any
// other crate intentionally as this is the only crate for now that we
// ship with panic=abort.
//
// This... is a bit of a hack how we detect this. Ideally this
// information should be encoded in the crate I guess? Would likely
// require an RFC amendment to RFC 1513, however.
let is_panic_abort = args.windows(2).any(|a| {
&*a[0] == "--crate-name" && &*a[1] == "panic_abort"
});
// FIXME(stage0): remove this `stage != "0"` condition
if is_panic_abort && stage != "0" {
cmd.arg("-C").arg("panic=abort");
}

// Set various options from config.toml to configure how we're building
// code.
if env::var("RUSTC_DEBUGINFO") == Ok("true".to_string()) {
Expand Down
7 changes: 3 additions & 4 deletions src/liballoc_system/lib.rs
Expand Up @@ -18,10 +18,8 @@
form or name",
issue = "27783")]
#![feature(allocator)]
#![feature(libc)]
#![feature(staged_api)]

extern crate libc;
#![cfg_attr(unix, feature(libc))]

// The minimum alignment guaranteed by the architecture. This value is used to
// add fast paths for low alignment values. In practice, the alignment is a
Expand Down Expand Up @@ -72,9 +70,10 @@ pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {

#[cfg(unix)]
mod imp {
extern crate libc;

use core::cmp;
use core::ptr;
use libc;
use MIN_ALIGN;

pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
Expand Down
11 changes: 11 additions & 0 deletions src/libpanic_abort/Cargo.toml
@@ -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" }
135 changes: 135 additions & 0 deletions src/libpanic_abort/lib.rs
@@ -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() {}
}
27 changes: 27 additions & 0 deletions src/libpanic_unwind/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions src/libpanic_unwind/Cargo.toml
@@ -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" }
Expand Up @@ -21,8 +21,7 @@
#![allow(non_upper_case_globals)]
#![allow(unused)]

use prelude::v1::*;
use sys_common::dwarf::DwarfReader;
use dwarf::DwarfReader;
use core::mem;

pub const DW_EH_PE_omit : u8 = 0xFF;
Expand Down
Expand Up @@ -18,7 +18,6 @@

pub mod eh;

use prelude::v1::*;
use core::mem;

pub struct DwarfReader {
Expand Down