Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
yaahc committed Feb 5, 2021
1 parent 4d45f69 commit d0e156d
Show file tree
Hide file tree
Showing 7 changed files with 275 additions and 162 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,10 @@ language_item_table! {
// libstd panic entry point. Necessary for const eval to be able to catch it
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn;

BacktraceEnabled, sym::backtrace_enabled, backtrace_enabled, Target::Fn;
BacktraceCreate, sym::backtrace_create, backtrace_create, Target::Fn;
BacktraceStatus, sym::backtrace_status, backtrace_status, Target::Fn;

ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn;
BoxFree, sym::box_free, box_free_fn, Target::Fn;
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn;
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_hir/src/weak_lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,7 @@ weak_lang_items! {
eh_personality, EhPersonality, rust_eh_personality;
eh_catch_typeinfo, EhCatchTypeinfo, rust_eh_catch_typeinfo;
oom, Oom, rust_oom;
backtrace_create, BacktraceCreate, rust_backtrace_create;
backtrace_enabled, BacktraceEnabled, rust_backtrace_enabled;
backtrace_status, BacktraceStatus, rust_backtrace_status;
}
6 changes: 6 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,9 @@ symbols! {
automatically_derived,
avx512_target_feature,
await_macro,
backtrace_create,
backtrace_enabled,
backtrace_status,
bang,
begin_panic,
bench,
Expand Down Expand Up @@ -931,6 +934,9 @@ symbols! {
rust_2015_preview,
rust_2018_preview,
rust_2021_preview,
rust_backtrace_create,
rust_backtrace_enabled,
rust_backtrace_status,
rust_begin_unwind,
rust_eh_catch_typeinfo,
rust_eh_personality,
Expand Down
182 changes: 168 additions & 14 deletions library/core/src/backtrace.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,200 @@
//! hi
#![unstable(feature = "core_backtrace", issue = "74465")]
use crate::fmt;
#![unstable(feature = "backtrace", issue = "74465")]
use crate::{fmt, ptr};

/// The current status of a backtrace, indicating whether it was captured or
/// whether it is empty for some other reason.
#[non_exhaustive]
#[derive(Debug, PartialEq, Eq)]
pub enum BacktraceStatus {
/// Capturing a backtrace is not supported, likely because it's not
/// implemented for the current platform.
Unsupported,
/// Capturing a backtrace has been disabled through either the
/// `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` environment variables.
Disabled,
/// A backtrace has been captured and the `Backtrace` should print
/// reasonable information when rendered.
Captured,
}

// perma(?)-unstable
#[unstable(feature = "core_backtrace", issue = "74465")]
#[unstable(feature = "backtrace", issue = "74465")]
///
pub trait RawBacktraceImpl: fmt::Debug + fmt::Display + 'static {
pub trait RawBacktrace: fmt::Debug + fmt::Display + 'static {
///
unsafe fn drop_and_free(self: *mut Self);
}

#[unstable(feature = "core_backtrace", issue = "74465")]
struct UnsupportedBacktrace;

impl UnsupportedBacktrace {
#[allow(dead_code)]
const fn create() -> Backtrace {
// don't add members to Self
let _ = Self {};

Backtrace {
inner: ptr::NonNull::<Self>::dangling().as_ptr(),
}
}
}

impl RawBacktrace for UnsupportedBacktrace {
unsafe fn drop_and_free(self: *mut Self) {}
}

impl fmt::Display for UnsupportedBacktrace {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str("unsupported backtrace")
}
}

impl fmt::Debug for UnsupportedBacktrace {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str("<unsupported>")
}
}
struct DisabledBacktrace;

impl DisabledBacktrace {
const fn create() -> Backtrace {
// don't add members to Self
let _ = Self {};

Backtrace {
inner: ptr::NonNull::<Self>::dangling().as_ptr(),
}
}
}

impl RawBacktrace for DisabledBacktrace {
unsafe fn drop_and_free(self: *mut Self) {}
}

impl fmt::Display for DisabledBacktrace {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str("disabled backtrace")
}
}

impl fmt::Debug for DisabledBacktrace {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str("<disabled>")
}
}

#[unstable(feature = "backtrace", issue = "74465")]
///
pub struct Backtrace {
inner: *mut dyn RawBacktraceImpl,
///
inner: *mut dyn RawBacktrace,
}

/// Global implementation of backtrace functionality. Called to create
/// `RawBacktrace` trait objects.
extern "Rust" {
#[lang = "backtrace_create"]
fn backtrace_create(ip: usize) -> *mut dyn RawBacktrace;

#[lang = "backtrace_enabled"]
fn backtrace_enabled() -> bool;

#[lang = "backtrace_status"]
fn backtrace_status(raw: *mut dyn RawBacktrace) -> BacktraceStatus;
}

impl Backtrace {
fn create(ip: usize) -> Backtrace {
let inner = unsafe { backtrace_create(ip) };
Backtrace { inner }
}

/// Returns whether backtrace captures are enabled through environment
/// variables.
fn enabled() -> bool {
unsafe { backtrace_enabled() }
}

/// Capture a stack backtrace of the current thread.
///
/// This function will capture a stack backtrace of the current OS thread of
/// execution, returning a `Backtrace` type which can be later used to print
/// the entire stack trace or render it to a string.
///
/// This function will be a noop if the `RUST_BACKTRACE` or
/// `RUST_LIB_BACKTRACE` backtrace variables are both not set. If either
/// environment variable is set and enabled then this function will actually
/// capture a backtrace. Capturing a backtrace can be both memory intensive
/// and slow, so these environment variables allow liberally using
/// `Backtrace::capture` and only incurring a slowdown when the environment
/// variables are set.
///
/// To forcibly capture a backtrace regardless of environment variables, use
/// the `Backtrace::force_capture` function.
#[inline(never)] // want to make sure there's a frame here to remove
pub fn capture() -> Backtrace {
if !Backtrace::enabled() {
return Backtrace::disabled();
}

Self::create(Backtrace::capture as usize)
}

/// Forcibly captures a full backtrace, regardless of environment variable
/// configuration.
///
/// This function behaves the same as `capture` except that it ignores the
/// values of the `RUST_BACKTRACE` and `RUST_LIB_BACKTRACE` environment
/// variables, always capturing a backtrace.
///
/// Note that capturing a backtrace can be an expensive operation on some
/// platforms, so this should be used with caution in performance-sensitive
/// parts of code.
#[inline(never)] // want to make sure there's a frame here to remove
pub fn force_capture() -> Backtrace {
Self::create(Backtrace::force_capture as usize)
}

/// Forcibly captures a disabled backtrace, regardless of environment
/// variable configuration.
pub const fn disabled() -> Backtrace {
DisabledBacktrace::create()
}

/// Returns the status of this backtrace, indicating whether this backtrace
/// request was unsupported, disabled, or a stack trace was actually
/// captured.
pub fn status(&self) -> BacktraceStatus {
unsafe { backtrace_status(self.inner) }
}
}

#[unstable(feature = "core_backtrace", issue = "74465")]
#[unstable(feature = "backtrace", issue = "74465")]
unsafe impl Send for Backtrace {}

#[unstable(feature = "core_backtrace", issue = "74465")]
#[unstable(feature = "backtrace", issue = "74465")]
unsafe impl Sync for Backtrace {}

#[unstable(feature = "core_backtrace", issue = "74465")]
#[unstable(feature = "backtrace", issue = "74465")]
impl Drop for Backtrace {
fn drop(&mut self) {
unsafe { RawBacktraceImpl::drop_and_free(self.inner) }
unsafe { RawBacktrace::drop_and_free(self.inner) }
}
}

#[unstable(feature = "core_backtrace", issue = "74465")]
#[unstable(feature = "backtrace", issue = "74465")]
impl fmt::Debug for Backtrace {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
let imp: &dyn RawBacktraceImpl = unsafe { &*self.inner };
let imp: &dyn RawBacktrace = unsafe { &*self.inner };
fmt::Debug::fmt(imp, fmt)
}
}

#[unstable(feature = "core_backtrace", issue = "74465")]
#[unstable(feature = "backtrace", issue = "74465")]
impl fmt::Display for Backtrace {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
let imp: &dyn RawBacktraceImpl = unsafe { &*self.inner };
let imp: &dyn RawBacktrace = unsafe { &*self.inner };
fmt::Display::fmt(imp, fmt)
}
}
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(linkage)]
#![feature(link_llvm_intrinsics)]
#![feature(llvm_asm)]
#![feature(negative_impls)]
Expand Down
Loading

0 comments on commit d0e156d

Please sign in to comment.