From 4d45f69b33a8884327db25e080894347df622c88 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Tue, 2 Feb 2021 11:44:32 -0800 Subject: [PATCH 1/6] start PR over again --- library/core/src/backtrace.rs | 46 +++++++++++++++++++++++++++++++++++ library/core/src/lib.rs | 1 + library/std/src/backtrace.rs | 10 +++++--- library/std/src/lib.rs | 1 + 4 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 library/core/src/backtrace.rs diff --git a/library/core/src/backtrace.rs b/library/core/src/backtrace.rs new file mode 100644 index 0000000000000..5b09c92146098 --- /dev/null +++ b/library/core/src/backtrace.rs @@ -0,0 +1,46 @@ +//! hi +#![unstable(feature = "core_backtrace", issue = "74465")] +use crate::fmt; + +// perma(?)-unstable +#[unstable(feature = "core_backtrace", issue = "74465")] +/// +pub trait RawBacktraceImpl: fmt::Debug + fmt::Display + 'static { + /// + unsafe fn drop_and_free(self: *mut Self); +} + +#[unstable(feature = "core_backtrace", issue = "74465")] +/// +pub struct Backtrace { + inner: *mut dyn RawBacktraceImpl, +} + +#[unstable(feature = "core_backtrace", issue = "74465")] +unsafe impl Send for Backtrace {} + +#[unstable(feature = "core_backtrace", issue = "74465")] +unsafe impl Sync for Backtrace {} + +#[unstable(feature = "core_backtrace", issue = "74465")] +impl Drop for Backtrace { + fn drop(&mut self) { + unsafe { RawBacktraceImpl::drop_and_free(self.inner) } + } +} + +#[unstable(feature = "core_backtrace", issue = "74465")] +impl fmt::Debug for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let imp: &dyn RawBacktraceImpl = unsafe { &*self.inner }; + fmt::Debug::fmt(imp, fmt) + } +} + +#[unstable(feature = "core_backtrace", issue = "74465")] +impl fmt::Display for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let imp: &dyn RawBacktraceImpl = unsafe { &*self.inner }; + fmt::Display::fmt(imp, fmt) + } +} \ No newline at end of file diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a69b840e4bf14..55c0393249387 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -241,6 +241,7 @@ pub mod ops; pub mod any; pub mod array; pub mod ascii; +pub mod backtrace; pub mod cell; pub mod char; pub mod ffi; diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 0aae4674b2942..dd00af485a32e 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -104,16 +104,20 @@ use crate::sync::Once; use crate::sys_common::backtrace::{lock, output_filename}; use crate::vec::Vec; +pub use core::backtrace::Backtrace; + /// A captured OS thread stack backtrace. /// /// This type represents a stack backtrace for an OS thread captured at a /// previous point in time. In some instances the `Backtrace` type may /// internally be empty due to configuration. For more information see /// `Backtrace::capture`. -pub struct Backtrace { +struct BacktraceImpl { inner: Inner, } +impl core::backtrace::RawBacktraceImpl for BacktraceImpl {} + /// The current status of a backtrace, indicating whether it was captured or /// whether it is empty for some other reason. #[non_exhaustive] @@ -173,7 +177,7 @@ enum BytesOrWide { Wide(Vec), } -impl fmt::Debug for Backtrace { +impl fmt::Debug for BacktraceImpl { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let capture = match &self.inner { Inner::Unsupported => return fmt.write_str(""), @@ -372,7 +376,7 @@ impl<'a> Backtrace { } } -impl fmt::Display for Backtrace { +impl fmt::Display for BacktraceImpl { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let capture = match &self.inner { Inner::Unsupported => return fmt.write_str("unsupported backtrace"), diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index b6929f5939576..055802bc2c5e0 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -249,6 +249,7 @@ #![feature(const_raw_ptr_deref)] #![feature(const_ipv4)] #![feature(container_error_extra)] +#![feature(core_backtrace)] #![feature(core_intrinsics)] #![feature(custom_test_frameworks)] #![feature(decl_macro)] From d0e156d62460808e78c9c458716b1ae3c8fe6ff9 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Thu, 4 Feb 2021 13:06:54 -0800 Subject: [PATCH 2/6] WIP --- compiler/rustc_hir/src/lang_items.rs | 4 + compiler/rustc_hir/src/weak_lang_items.rs | 3 + compiler/rustc_span/src/symbol.rs | 6 + library/core/src/backtrace.rs | 182 ++++++++++++++-- library/core/src/lib.rs | 1 + library/std/src/backtrace.rs | 239 +++++++++------------- library/std/src/lib.rs | 2 +- 7 files changed, 275 insertions(+), 162 deletions(-) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 26ce30cb51177..738c79bce1afd 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -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; diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs index b8cd15e7f00d6..d9529a32790e6 100644 --- a/compiler/rustc_hir/src/weak_lang_items.rs +++ b/compiler/rustc_hir/src/weak_lang_items.rs @@ -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; } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f2f975c0cf9e5..fbc4e15703c79 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -289,6 +289,9 @@ symbols! { automatically_derived, avx512_target_feature, await_macro, + backtrace_create, + backtrace_enabled, + backtrace_status, bang, begin_panic, bench, @@ -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, diff --git a/library/core/src/backtrace.rs b/library/core/src/backtrace.rs index 5b09c92146098..b0e609d105ab2 100644 --- a/library/core/src/backtrace.rs +++ b/library/core/src/backtrace.rs @@ -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::::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("") + } +} +struct DisabledBacktrace; + +impl DisabledBacktrace { + const fn create() -> Backtrace { + // don't add members to Self + let _ = Self {}; + + Backtrace { + inner: ptr::NonNull::::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("") + } +} + +#[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) } } \ No newline at end of file diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 55c0393249387..54ec5aee7503b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -116,6 +116,7 @@ #![feature(fundamental)] #![feature(intrinsics)] #![feature(lang_items)] +#![feature(linkage)] #![feature(link_llvm_intrinsics)] #![feature(llvm_asm)] #![feature(negative_impls)] diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index dd00af485a32e..cc22f30bd6499 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -105,6 +105,83 @@ use crate::sys_common::backtrace::{lock, output_filename}; use crate::vec::Vec; pub use core::backtrace::Backtrace; +pub use core::backtrace::BacktraceStatus; +use core::backtrace::RawBacktrace; + +/// Returns whether backtrace captures are enabled through environment +/// variables. +#[export_name = "__rust_backtrace_enabled"] +pub fn enabled() -> bool { + // Cache the result of reading the environment variables to make + // backtrace captures speedy, because otherwise reading environment + // variables every time can be somewhat slow. + static ENABLED: AtomicUsize = AtomicUsize::new(0); + match ENABLED.load(SeqCst) { + 0 => {} + 1 => return false, + _ => return true, + } + let enabled = match env::var("RUST_LIB_BACKTRACE") { + Ok(s) => s != "0", + Err(_) => match env::var("RUST_BACKTRACE") { + Ok(s) => s != "0", + Err(_) => false, + }, + }; + ENABLED.store(enabled as usize + 1, SeqCst); + enabled +} + +// Capture a backtrace which start just before the function addressed by +// `ip` +#[export_name = "__rust_backtrace_create"] +/// +pub fn create(ip: usize) -> *mut dyn RawBacktrace { + // SAFETY: We don't attempt to lock this reentrantly. + let _lock = unsafe { lock() }; + let mut frames = Vec::new(); + let mut actual_start = None; + unsafe { + backtrace_rs::trace_unsynchronized(|frame| { + frames.push(BacktraceFrame { + frame: RawFrame::Actual(frame.clone()), + symbols: Vec::new(), + }); + if frame.symbol_address() as usize == ip && actual_start.is_none() { + actual_start = Some(frames.len()); + } + true + }); + } + + // If no frames came out assume that this is an unsupported platform + // since `backtrace` doesn't provide a way of learning this right now, + // and this should be a good enough approximation. + let inner = if frames.is_empty() { + Inner::Unsupported + } else { + Inner::Captured(LazilyResolvedCapture::new(Capture { + actual_start: actual_start.unwrap_or(0), + frames, + resolved: false, + })) + }; + + let bt: Box = Box::new(StdBacktrace { inner }); + Box::into_raw(bt) +} + +/// Returns the status of this backtrace, indicating whether this backtrace +/// request was unsupported, disabled, or a stack trace was actually +/// captured. +#[export_name = "__rust_backtrace_status"] +pub fn status(_backtrace: *mut dyn RawBacktrace) -> BacktraceStatus { + todo!() + // match backtrace.inner { + // Inner::Unsupported => BacktraceStatus::Unsupported, + // Inner::Captured(_) => BacktraceStatus::Captured, + // } +} /// A captured OS thread stack backtrace. /// @@ -112,31 +189,18 @@ pub use core::backtrace::Backtrace; /// previous point in time. In some instances the `Backtrace` type may /// internally be empty due to configuration. For more information see /// `Backtrace::capture`. -struct BacktraceImpl { +struct StdBacktrace { inner: Inner, } -impl core::backtrace::RawBacktraceImpl for BacktraceImpl {} - -/// 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, +impl RawBacktrace for StdBacktrace { + unsafe fn drop_and_free(self: *mut Self) { + todo!() + } } enum Inner { Unsupported, - Disabled, Captured(LazilyResolvedCapture), } @@ -148,7 +212,7 @@ struct Capture { fn _assert_send_sync() { fn _assert() {} - _assert::(); + _assert::(); } /// A single frame of a backtrace. @@ -177,11 +241,10 @@ enum BytesOrWide { Wide(Vec), } -impl fmt::Debug for BacktraceImpl { +impl fmt::Debug for StdBacktrace { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let capture = match &self.inner { Inner::Unsupported => return fmt.write_str(""), - Inner::Disabled => return fmt.write_str(""), Inner::Captured(c) => c.force(), }; @@ -251,136 +314,18 @@ impl fmt::Debug for BytesOrWide { } } -impl Backtrace { - /// Returns whether backtrace captures are enabled through environment - /// variables. - fn enabled() -> bool { - // Cache the result of reading the environment variables to make - // backtrace captures speedy, because otherwise reading environment - // variables every time can be somewhat slow. - static ENABLED: AtomicUsize = AtomicUsize::new(0); - match ENABLED.load(SeqCst) { - 0 => {} - 1 => return false, - _ => return true, - } - let enabled = match env::var("RUST_LIB_BACKTRACE") { - Ok(s) => s != "0", - Err(_) => match env::var("RUST_BACKTRACE") { - Ok(s) => s != "0", - Err(_) => false, - }, - }; - ENABLED.store(enabled as usize + 1, SeqCst); - 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 { inner: Inner::Disabled }; - } - Backtrace::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 { - Backtrace::create(Backtrace::force_capture as usize) - } - - /// Forcibly captures a disabled backtrace, regardless of environment - /// variable configuration. - pub const fn disabled() -> Backtrace { - Backtrace { inner: Inner::Disabled } - } - - // Capture a backtrace which start just before the function addressed by - // `ip` - fn create(ip: usize) -> Backtrace { - // SAFETY: We don't attempt to lock this reentrantly. - let _lock = unsafe { lock() }; - let mut frames = Vec::new(); - let mut actual_start = None; - unsafe { - backtrace_rs::trace_unsynchronized(|frame| { - frames.push(BacktraceFrame { - frame: RawFrame::Actual(frame.clone()), - symbols: Vec::new(), - }); - if frame.symbol_address() as usize == ip && actual_start.is_none() { - actual_start = Some(frames.len()); - } - true - }); - } - - // If no frames came out assume that this is an unsupported platform - // since `backtrace` doesn't provide a way of learning this right now, - // and this should be a good enough approximation. - let inner = if frames.is_empty() { - Inner::Unsupported - } else { - Inner::Captured(LazilyResolvedCapture::new(Capture { - actual_start: actual_start.unwrap_or(0), - frames, - resolved: false, - })) - }; - - Backtrace { inner } - } - - /// 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 { - match self.inner { - Inner::Unsupported => BacktraceStatus::Unsupported, - Inner::Disabled => BacktraceStatus::Disabled, - Inner::Captured(_) => BacktraceStatus::Captured, - } - } -} - -impl<'a> Backtrace { - /// Returns an iterator over the backtrace frames. - #[unstable(feature = "backtrace_frames", issue = "79676")] - pub fn frames(&'a self) -> &'a [BacktraceFrame] { - if let Inner::Captured(c) = &self.inner { &c.force().frames } else { &[] } - } -} +// impl<'a> StdBacktrace { +// /// Returns an iterator over the backtrace frames. +// #[unstable(feature = "backtrace_frames", issue = "79676")] +// pub fn frames(&'a self) -> &'a [BacktraceFrame] { +// if let Inner::Captured(c) = &self.inner { &c.force().frames } else { &[] } +// } +// } -impl fmt::Display for BacktraceImpl { +impl fmt::Display for StdBacktrace { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let capture = match &self.inner { Inner::Unsupported => return fmt.write_str("unsupported backtrace"), - Inner::Disabled => return fmt.write_str("disabled backtrace"), Inner::Captured(c) => c.force(), }; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 055802bc2c5e0..d81bebfeb173d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -230,6 +230,7 @@ #![feature(asm)] #![feature(associated_type_bounds)] #![feature(atomic_mut_ptr)] +#![feature(backtrace)] #![feature(box_syntax)] #![feature(c_variadic)] #![feature(cfg_accessible)] @@ -249,7 +250,6 @@ #![feature(const_raw_ptr_deref)] #![feature(const_ipv4)] #![feature(container_error_extra)] -#![feature(core_backtrace)] #![feature(core_intrinsics)] #![feature(custom_test_frameworks)] #![feature(decl_macro)] From 23fa6c6a735592e5445bc678e20879f3d01bd7d2 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Mon, 15 Feb 2021 11:18:07 -0800 Subject: [PATCH 3/6] disable hooks in bootstrap --- library/core/src/backtrace.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/backtrace.rs b/library/core/src/backtrace.rs index b0e609d105ab2..e1496d9da5bf7 100644 --- a/library/core/src/backtrace.rs +++ b/library/core/src/backtrace.rs @@ -94,13 +94,13 @@ pub struct Backtrace { /// Global implementation of backtrace functionality. Called to create /// `RawBacktrace` trait objects. extern "Rust" { - #[lang = "backtrace_create"] + #[cfg_attr(not(bootstrap), lang = "backtrace_create")] fn backtrace_create(ip: usize) -> *mut dyn RawBacktrace; - #[lang = "backtrace_enabled"] + #[cfg_attr(not(bootstrap), lang = "backtrace_enabled")] fn backtrace_enabled() -> bool; - #[lang = "backtrace_status"] + #[cfg_attr(not(bootstrap), lang = "backtrace_status")] fn backtrace_status(raw: *mut dyn RawBacktrace) -> BacktraceStatus; } From 3a9037dd85ec355051eb5f2dd8eaaea3be436e73 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Fri, 26 Feb 2021 18:19:14 -0800 Subject: [PATCH 4/6] make stage0 compiler build --- library/core/src/backtrace.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/library/core/src/backtrace.rs b/library/core/src/backtrace.rs index e1496d9da5bf7..fd49fbfa84155 100644 --- a/library/core/src/backtrace.rs +++ b/library/core/src/backtrace.rs @@ -93,17 +93,33 @@ pub struct Backtrace { /// Global implementation of backtrace functionality. Called to create /// `RawBacktrace` trait objects. +#[cfg(not(bootstrap))] extern "Rust" { - #[cfg_attr(not(bootstrap), lang = "backtrace_create")] + #[lang = "backtrace_create"] fn backtrace_create(ip: usize) -> *mut dyn RawBacktrace; - #[cfg_attr(not(bootstrap), lang = "backtrace_enabled")] + #[lang = "backtrace_enabled"] fn backtrace_enabled() -> bool; - #[cfg_attr(not(bootstrap), lang = "backtrace_status")] + #[lang = "backtrace_status"] fn backtrace_status(raw: *mut dyn RawBacktrace) -> BacktraceStatus; } +#[cfg(bootstrap)] +unsafe fn backtrace_create(_ip: usize) -> *mut dyn RawBacktrace { + UnsupportedBacktrace::create().inner +} + +#[cfg(bootstrap)] +unsafe fn backtrace_enabled() -> bool { + false +} + +#[cfg(bootstrap)] +unsafe fn backtrace_status(_raw: *mut dyn RawBacktrace) -> BacktraceStatus { + BacktraceStatus::Unsupported +} + impl Backtrace { fn create(ip: usize) -> Backtrace { let inner = unsafe { backtrace_create(ip) }; From ca45768cdd40fa87dc1124d53ded9b8a00ab290f Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Mon, 3 May 2021 16:35:42 -0700 Subject: [PATCH 5/6] get build working using lang items properly --- library/core/src/backtrace.rs | 34 ++++++++++++++++++---------------- library/std/src/backtrace.rs | 6 +++--- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/library/core/src/backtrace.rs b/library/core/src/backtrace.rs index fd49fbfa84155..8e27ea23c54ce 100644 --- a/library/core/src/backtrace.rs +++ b/library/core/src/backtrace.rs @@ -1,5 +1,5 @@ //! hi -#![unstable(feature = "backtrace", issue = "74465")] +#![unstable(feature = "backtrace", issue = "53487")] use crate::{fmt, ptr}; /// The current status of a backtrace, indicating whether it was captured or @@ -19,7 +19,7 @@ pub enum BacktraceStatus { } // perma(?)-unstable -#[unstable(feature = "backtrace", issue = "74465")] +#[unstable(feature = "backtrace", issue = "53487")] /// pub trait RawBacktrace: fmt::Debug + fmt::Display + 'static { /// @@ -28,15 +28,13 @@ pub trait RawBacktrace: fmt::Debug + fmt::Display + 'static { struct UnsupportedBacktrace; -impl UnsupportedBacktrace { +impl UnsupportedBacktrace { #[allow(dead_code)] const fn create() -> Backtrace { // don't add members to Self let _ = Self {}; - Backtrace { - inner: ptr::NonNull::::dangling().as_ptr(), - } + Backtrace { inner: ptr::NonNull::::dangling().as_ptr() } } } @@ -62,9 +60,7 @@ impl DisabledBacktrace { // don't add members to Self let _ = Self {}; - Backtrace { - inner: ptr::NonNull::::dangling().as_ptr(), - } + Backtrace { inner: ptr::NonNull::::dangling().as_ptr() } } } @@ -84,7 +80,7 @@ impl fmt::Debug for DisabledBacktrace { } } -#[unstable(feature = "backtrace", issue = "74465")] +#[unstable(feature = "backtrace", issue = "53487")] /// pub struct Backtrace { /// @@ -122,6 +118,7 @@ unsafe fn backtrace_status(_raw: *mut dyn RawBacktrace) -> BacktraceStatus { impl Backtrace { fn create(ip: usize) -> Backtrace { + // SAFETY: trust me let inner = unsafe { backtrace_create(ip) }; Backtrace { inner } } @@ -129,6 +126,7 @@ impl Backtrace { /// Returns whether backtrace captures are enabled through environment /// variables. fn enabled() -> bool { + // SAFETY: trust me unsafe { backtrace_enabled() } } @@ -182,35 +180,39 @@ impl Backtrace { /// request was unsupported, disabled, or a stack trace was actually /// captured. pub fn status(&self) -> BacktraceStatus { + // SAFETY: trust me unsafe { backtrace_status(self.inner) } } } -#[unstable(feature = "backtrace", issue = "74465")] +#[unstable(feature = "backtrace", issue = "53487")] unsafe impl Send for Backtrace {} -#[unstable(feature = "backtrace", issue = "74465")] +#[unstable(feature = "backtrace", issue = "53487")] unsafe impl Sync for Backtrace {} -#[unstable(feature = "backtrace", issue = "74465")] +#[unstable(feature = "backtrace", issue = "53487")] impl Drop for Backtrace { fn drop(&mut self) { + // SAFETY: trust me unsafe { RawBacktrace::drop_and_free(self.inner) } } } -#[unstable(feature = "backtrace", issue = "74465")] +#[unstable(feature = "backtrace", issue = "53487")] impl fmt::Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + // SAFETY: trust me let imp: &dyn RawBacktrace = unsafe { &*self.inner }; fmt::Debug::fmt(imp, fmt) } } -#[unstable(feature = "backtrace", issue = "74465")] +#[unstable(feature = "backtrace", issue = "53487")] impl fmt::Display for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + // SAFETY: trust me let imp: &dyn RawBacktrace = unsafe { &*self.inner }; fmt::Display::fmt(imp, fmt) } -} \ No newline at end of file +} diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index cc22f30bd6499..fc2285a66d154 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -110,7 +110,7 @@ use core::backtrace::RawBacktrace; /// Returns whether backtrace captures are enabled through environment /// variables. -#[export_name = "__rust_backtrace_enabled"] +#[cfg_attr(not(bootstrap), lang = "backtrace_enabled")] pub fn enabled() -> bool { // Cache the result of reading the environment variables to make // backtrace captures speedy, because otherwise reading environment @@ -134,7 +134,7 @@ pub fn enabled() -> bool { // Capture a backtrace which start just before the function addressed by // `ip` -#[export_name = "__rust_backtrace_create"] +#[cfg_attr(not(bootstrap), lang = "backtrace_create")] /// pub fn create(ip: usize) -> *mut dyn RawBacktrace { // SAFETY: We don't attempt to lock this reentrantly. @@ -174,7 +174,7 @@ pub fn create(ip: usize) -> *mut dyn RawBacktrace { /// Returns the status of this backtrace, indicating whether this backtrace /// request was unsupported, disabled, or a stack trace was actually /// captured. -#[export_name = "__rust_backtrace_status"] +#[cfg_attr(not(bootstrap), lang = "backtrace_status")] pub fn status(_backtrace: *mut dyn RawBacktrace) -> BacktraceStatus { todo!() // match backtrace.inner { From 7ec9f8bb5648cd7d3798eaeff38617990ad534ad Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Tue, 4 May 2021 16:52:25 -0700 Subject: [PATCH 6/6] fix drop impl --- library/std/src/backtrace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index fc2285a66d154..76f8d2683d308 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -195,7 +195,7 @@ struct StdBacktrace { impl RawBacktrace for StdBacktrace { unsafe fn drop_and_free(self: *mut Self) { - todo!() + let _ = Box::from_raw(self); } }