Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d0e156d

Browse files
committedFeb 5, 2021
WIP
1 parent 4d45f69 commit d0e156d

File tree

7 files changed

+275
-162
lines changed

7 files changed

+275
-162
lines changed
 

‎compiler/rustc_hir/src/lang_items.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ language_item_table! {
271271
// libstd panic entry point. Necessary for const eval to be able to catch it
272272
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn;
273273

274+
BacktraceEnabled, sym::backtrace_enabled, backtrace_enabled, Target::Fn;
275+
BacktraceCreate, sym::backtrace_create, backtrace_create, Target::Fn;
276+
BacktraceStatus, sym::backtrace_status, backtrace_status, Target::Fn;
277+
274278
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn;
275279
BoxFree, sym::box_free, box_free_fn, Target::Fn;
276280
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn;

‎compiler/rustc_hir/src/weak_lang_items.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,7 @@ weak_lang_items! {
4848
eh_personality, EhPersonality, rust_eh_personality;
4949
eh_catch_typeinfo, EhCatchTypeinfo, rust_eh_catch_typeinfo;
5050
oom, Oom, rust_oom;
51+
backtrace_create, BacktraceCreate, rust_backtrace_create;
52+
backtrace_enabled, BacktraceEnabled, rust_backtrace_enabled;
53+
backtrace_status, BacktraceStatus, rust_backtrace_status;
5154
}

‎compiler/rustc_span/src/symbol.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,9 @@ symbols! {
289289
automatically_derived,
290290
avx512_target_feature,
291291
await_macro,
292+
backtrace_create,
293+
backtrace_enabled,
294+
backtrace_status,
292295
bang,
293296
begin_panic,
294297
bench,
@@ -931,6 +934,9 @@ symbols! {
931934
rust_2015_preview,
932935
rust_2018_preview,
933936
rust_2021_preview,
937+
rust_backtrace_create,
938+
rust_backtrace_enabled,
939+
rust_backtrace_status,
934940
rust_begin_unwind,
935941
rust_eh_catch_typeinfo,
936942
rust_eh_personality,

‎library/core/src/backtrace.rs

Lines changed: 168 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,200 @@
11
//! hi
2-
#![unstable(feature = "core_backtrace", issue = "74465")]
3-
use crate::fmt;
2+
#![unstable(feature = "backtrace", issue = "74465")]
3+
use crate::{fmt, ptr};
4+
5+
/// The current status of a backtrace, indicating whether it was captured or
6+
/// whether it is empty for some other reason.
7+
#[non_exhaustive]
8+
#[derive(Debug, PartialEq, Eq)]
9+
pub enum BacktraceStatus {
10+
/// Capturing a backtrace is not supported, likely because it's not
11+
/// implemented for the current platform.
12+
Unsupported,
13+
/// Capturing a backtrace has been disabled through either the
14+
/// `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` environment variables.
15+
Disabled,
16+
/// A backtrace has been captured and the `Backtrace` should print
17+
/// reasonable information when rendered.
18+
Captured,
19+
}
420

521
// perma(?)-unstable
6-
#[unstable(feature = "core_backtrace", issue = "74465")]
22+
#[unstable(feature = "backtrace", issue = "74465")]
723
///
8-
pub trait RawBacktraceImpl: fmt::Debug + fmt::Display + 'static {
24+
pub trait RawBacktrace: fmt::Debug + fmt::Display + 'static {
925
///
1026
unsafe fn drop_and_free(self: *mut Self);
1127
}
1228

13-
#[unstable(feature = "core_backtrace", issue = "74465")]
29+
struct UnsupportedBacktrace;
30+
31+
impl UnsupportedBacktrace {
32+
#[allow(dead_code)]
33+
const fn create() -> Backtrace {
34+
// don't add members to Self
35+
let _ = Self {};
36+
37+
Backtrace {
38+
inner: ptr::NonNull::<Self>::dangling().as_ptr(),
39+
}
40+
}
41+
}
42+
43+
impl RawBacktrace for UnsupportedBacktrace {
44+
unsafe fn drop_and_free(self: *mut Self) {}
45+
}
46+
47+
impl fmt::Display for UnsupportedBacktrace {
48+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
49+
fmt.write_str("unsupported backtrace")
50+
}
51+
}
52+
53+
impl fmt::Debug for UnsupportedBacktrace {
54+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
55+
fmt.write_str("<unsupported>")
56+
}
57+
}
58+
struct DisabledBacktrace;
59+
60+
impl DisabledBacktrace {
61+
const fn create() -> Backtrace {
62+
// don't add members to Self
63+
let _ = Self {};
64+
65+
Backtrace {
66+
inner: ptr::NonNull::<Self>::dangling().as_ptr(),
67+
}
68+
}
69+
}
70+
71+
impl RawBacktrace for DisabledBacktrace {
72+
unsafe fn drop_and_free(self: *mut Self) {}
73+
}
74+
75+
impl fmt::Display for DisabledBacktrace {
76+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
77+
fmt.write_str("disabled backtrace")
78+
}
79+
}
80+
81+
impl fmt::Debug for DisabledBacktrace {
82+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
83+
fmt.write_str("<disabled>")
84+
}
85+
}
86+
87+
#[unstable(feature = "backtrace", issue = "74465")]
1488
///
1589
pub struct Backtrace {
16-
inner: *mut dyn RawBacktraceImpl,
90+
///
91+
inner: *mut dyn RawBacktrace,
92+
}
93+
94+
/// Global implementation of backtrace functionality. Called to create
95+
/// `RawBacktrace` trait objects.
96+
extern "Rust" {
97+
#[lang = "backtrace_create"]
98+
fn backtrace_create(ip: usize) -> *mut dyn RawBacktrace;
99+
100+
#[lang = "backtrace_enabled"]
101+
fn backtrace_enabled() -> bool;
102+
103+
#[lang = "backtrace_status"]
104+
fn backtrace_status(raw: *mut dyn RawBacktrace) -> BacktraceStatus;
105+
}
106+
107+
impl Backtrace {
108+
fn create(ip: usize) -> Backtrace {
109+
let inner = unsafe { backtrace_create(ip) };
110+
Backtrace { inner }
111+
}
112+
113+
/// Returns whether backtrace captures are enabled through environment
114+
/// variables.
115+
fn enabled() -> bool {
116+
unsafe { backtrace_enabled() }
117+
}
118+
119+
/// Capture a stack backtrace of the current thread.
120+
///
121+
/// This function will capture a stack backtrace of the current OS thread of
122+
/// execution, returning a `Backtrace` type which can be later used to print
123+
/// the entire stack trace or render it to a string.
124+
///
125+
/// This function will be a noop if the `RUST_BACKTRACE` or
126+
/// `RUST_LIB_BACKTRACE` backtrace variables are both not set. If either
127+
/// environment variable is set and enabled then this function will actually
128+
/// capture a backtrace. Capturing a backtrace can be both memory intensive
129+
/// and slow, so these environment variables allow liberally using
130+
/// `Backtrace::capture` and only incurring a slowdown when the environment
131+
/// variables are set.
132+
///
133+
/// To forcibly capture a backtrace regardless of environment variables, use
134+
/// the `Backtrace::force_capture` function.
135+
#[inline(never)] // want to make sure there's a frame here to remove
136+
pub fn capture() -> Backtrace {
137+
if !Backtrace::enabled() {
138+
return Backtrace::disabled();
139+
}
140+
141+
Self::create(Backtrace::capture as usize)
142+
}
143+
144+
/// Forcibly captures a full backtrace, regardless of environment variable
145+
/// configuration.
146+
///
147+
/// This function behaves the same as `capture` except that it ignores the
148+
/// values of the `RUST_BACKTRACE` and `RUST_LIB_BACKTRACE` environment
149+
/// variables, always capturing a backtrace.
150+
///
151+
/// Note that capturing a backtrace can be an expensive operation on some
152+
/// platforms, so this should be used with caution in performance-sensitive
153+
/// parts of code.
154+
#[inline(never)] // want to make sure there's a frame here to remove
155+
pub fn force_capture() -> Backtrace {
156+
Self::create(Backtrace::force_capture as usize)
157+
}
158+
159+
/// Forcibly captures a disabled backtrace, regardless of environment
160+
/// variable configuration.
161+
pub const fn disabled() -> Backtrace {
162+
DisabledBacktrace::create()
163+
}
164+
165+
/// Returns the status of this backtrace, indicating whether this backtrace
166+
/// request was unsupported, disabled, or a stack trace was actually
167+
/// captured.
168+
pub fn status(&self) -> BacktraceStatus {
169+
unsafe { backtrace_status(self.inner) }
170+
}
17171
}
18172

19-
#[unstable(feature = "core_backtrace", issue = "74465")]
173+
#[unstable(feature = "backtrace", issue = "74465")]
20174
unsafe impl Send for Backtrace {}
21175

22-
#[unstable(feature = "core_backtrace", issue = "74465")]
176+
#[unstable(feature = "backtrace", issue = "74465")]
23177
unsafe impl Sync for Backtrace {}
24178

25-
#[unstable(feature = "core_backtrace", issue = "74465")]
179+
#[unstable(feature = "backtrace", issue = "74465")]
26180
impl Drop for Backtrace {
27181
fn drop(&mut self) {
28-
unsafe { RawBacktraceImpl::drop_and_free(self.inner) }
182+
unsafe { RawBacktrace::drop_and_free(self.inner) }
29183
}
30184
}
31185

32-
#[unstable(feature = "core_backtrace", issue = "74465")]
186+
#[unstable(feature = "backtrace", issue = "74465")]
33187
impl fmt::Debug for Backtrace {
34188
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
35-
let imp: &dyn RawBacktraceImpl = unsafe { &*self.inner };
189+
let imp: &dyn RawBacktrace = unsafe { &*self.inner };
36190
fmt::Debug::fmt(imp, fmt)
37191
}
38192
}
39193

40-
#[unstable(feature = "core_backtrace", issue = "74465")]
194+
#[unstable(feature = "backtrace", issue = "74465")]
41195
impl fmt::Display for Backtrace {
42196
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
43-
let imp: &dyn RawBacktraceImpl = unsafe { &*self.inner };
197+
let imp: &dyn RawBacktrace = unsafe { &*self.inner };
44198
fmt::Display::fmt(imp, fmt)
45199
}
46200
}

‎library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
#![feature(fundamental)]
117117
#![feature(intrinsics)]
118118
#![feature(lang_items)]
119+
#![feature(linkage)]
119120
#![feature(link_llvm_intrinsics)]
120121
#![feature(llvm_asm)]
121122
#![feature(negative_impls)]

‎library/std/src/backtrace.rs

Lines changed: 92 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -105,38 +105,102 @@ use crate::sys_common::backtrace::{lock, output_filename};
105105
use crate::vec::Vec;
106106

107107
pub use core::backtrace::Backtrace;
108+
pub use core::backtrace::BacktraceStatus;
109+
use core::backtrace::RawBacktrace;
110+
111+
/// Returns whether backtrace captures are enabled through environment
112+
/// variables.
113+
#[export_name = "__rust_backtrace_enabled"]
114+
pub fn enabled() -> bool {
115+
// Cache the result of reading the environment variables to make
116+
// backtrace captures speedy, because otherwise reading environment
117+
// variables every time can be somewhat slow.
118+
static ENABLED: AtomicUsize = AtomicUsize::new(0);
119+
match ENABLED.load(SeqCst) {
120+
0 => {}
121+
1 => return false,
122+
_ => return true,
123+
}
124+
let enabled = match env::var("RUST_LIB_BACKTRACE") {
125+
Ok(s) => s != "0",
126+
Err(_) => match env::var("RUST_BACKTRACE") {
127+
Ok(s) => s != "0",
128+
Err(_) => false,
129+
},
130+
};
131+
ENABLED.store(enabled as usize + 1, SeqCst);
132+
enabled
133+
}
134+
135+
// Capture a backtrace which start just before the function addressed by
136+
// `ip`
137+
#[export_name = "__rust_backtrace_create"]
138+
///
139+
pub fn create(ip: usize) -> *mut dyn RawBacktrace {
140+
// SAFETY: We don't attempt to lock this reentrantly.
141+
let _lock = unsafe { lock() };
142+
let mut frames = Vec::new();
143+
let mut actual_start = None;
144+
unsafe {
145+
backtrace_rs::trace_unsynchronized(|frame| {
146+
frames.push(BacktraceFrame {
147+
frame: RawFrame::Actual(frame.clone()),
148+
symbols: Vec::new(),
149+
});
150+
if frame.symbol_address() as usize == ip && actual_start.is_none() {
151+
actual_start = Some(frames.len());
152+
}
153+
true
154+
});
155+
}
156+
157+
// If no frames came out assume that this is an unsupported platform
158+
// since `backtrace` doesn't provide a way of learning this right now,
159+
// and this should be a good enough approximation.
160+
let inner = if frames.is_empty() {
161+
Inner::Unsupported
162+
} else {
163+
Inner::Captured(LazilyResolvedCapture::new(Capture {
164+
actual_start: actual_start.unwrap_or(0),
165+
frames,
166+
resolved: false,
167+
}))
168+
};
169+
170+
let bt: Box<dyn RawBacktrace> = Box::new(StdBacktrace { inner });
171+
Box::into_raw(bt)
172+
}
173+
174+
/// Returns the status of this backtrace, indicating whether this backtrace
175+
/// request was unsupported, disabled, or a stack trace was actually
176+
/// captured.
177+
#[export_name = "__rust_backtrace_status"]
178+
pub fn status(_backtrace: *mut dyn RawBacktrace) -> BacktraceStatus {
179+
todo!()
180+
// match backtrace.inner {
181+
// Inner::Unsupported => BacktraceStatus::Unsupported,
182+
// Inner::Captured(_) => BacktraceStatus::Captured,
183+
// }
184+
}
108185

109186
/// A captured OS thread stack backtrace.
110187
///
111188
/// This type represents a stack backtrace for an OS thread captured at a
112189
/// previous point in time. In some instances the `Backtrace` type may
113190
/// internally be empty due to configuration. For more information see
114191
/// `Backtrace::capture`.
115-
struct BacktraceImpl {
192+
struct StdBacktrace {
116193
inner: Inner,
117194
}
118195

119-
impl core::backtrace::RawBacktraceImpl for BacktraceImpl {}
120-
121-
/// The current status of a backtrace, indicating whether it was captured or
122-
/// whether it is empty for some other reason.
123-
#[non_exhaustive]
124-
#[derive(Debug, PartialEq, Eq)]
125-
pub enum BacktraceStatus {
126-
/// Capturing a backtrace is not supported, likely because it's not
127-
/// implemented for the current platform.
128-
Unsupported,
129-
/// Capturing a backtrace has been disabled through either the
130-
/// `RUST_LIB_BACKTRACE` or `RUST_BACKTRACE` environment variables.
131-
Disabled,
132-
/// A backtrace has been captured and the `Backtrace` should print
133-
/// reasonable information when rendered.
134-
Captured,
196+
impl RawBacktrace for StdBacktrace {
197+
unsafe fn drop_and_free(self: *mut Self) {
198+
todo!()
199+
}
135200
}
136201

137202
enum Inner {
138203
Unsupported,
139-
Disabled,
140204
Captured(LazilyResolvedCapture),
141205
}
142206

@@ -148,7 +212,7 @@ struct Capture {
148212

149213
fn _assert_send_sync() {
150214
fn _assert<T: Send + Sync>() {}
151-
_assert::<Backtrace>();
215+
_assert::<StdBacktrace>();
152216
}
153217

154218
/// A single frame of a backtrace.
@@ -177,11 +241,10 @@ enum BytesOrWide {
177241
Wide(Vec<u16>),
178242
}
179243

180-
impl fmt::Debug for BacktraceImpl {
244+
impl fmt::Debug for StdBacktrace {
181245
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
182246
let capture = match &self.inner {
183247
Inner::Unsupported => return fmt.write_str("<unsupported>"),
184-
Inner::Disabled => return fmt.write_str("<disabled>"),
185248
Inner::Captured(c) => c.force(),
186249
};
187250

@@ -251,136 +314,18 @@ impl fmt::Debug for BytesOrWide {
251314
}
252315
}
253316

254-
impl Backtrace {
255-
/// Returns whether backtrace captures are enabled through environment
256-
/// variables.
257-
fn enabled() -> bool {
258-
// Cache the result of reading the environment variables to make
259-
// backtrace captures speedy, because otherwise reading environment
260-
// variables every time can be somewhat slow.
261-
static ENABLED: AtomicUsize = AtomicUsize::new(0);
262-
match ENABLED.load(SeqCst) {
263-
0 => {}
264-
1 => return false,
265-
_ => return true,
266-
}
267-
let enabled = match env::var("RUST_LIB_BACKTRACE") {
268-
Ok(s) => s != "0",
269-
Err(_) => match env::var("RUST_BACKTRACE") {
270-
Ok(s) => s != "0",
271-
Err(_) => false,
272-
},
273-
};
274-
ENABLED.store(enabled as usize + 1, SeqCst);
275-
enabled
276-
}
277-
278-
/// Capture a stack backtrace of the current thread.
279-
///
280-
/// This function will capture a stack backtrace of the current OS thread of
281-
/// execution, returning a `Backtrace` type which can be later used to print
282-
/// the entire stack trace or render it to a string.
283-
///
284-
/// This function will be a noop if the `RUST_BACKTRACE` or
285-
/// `RUST_LIB_BACKTRACE` backtrace variables are both not set. If either
286-
/// environment variable is set and enabled then this function will actually
287-
/// capture a backtrace. Capturing a backtrace can be both memory intensive
288-
/// and slow, so these environment variables allow liberally using
289-
/// `Backtrace::capture` and only incurring a slowdown when the environment
290-
/// variables are set.
291-
///
292-
/// To forcibly capture a backtrace regardless of environment variables, use
293-
/// the `Backtrace::force_capture` function.
294-
#[inline(never)] // want to make sure there's a frame here to remove
295-
pub fn capture() -> Backtrace {
296-
if !Backtrace::enabled() {
297-
return Backtrace { inner: Inner::Disabled };
298-
}
299-
Backtrace::create(Backtrace::capture as usize)
300-
}
301-
302-
/// Forcibly captures a full backtrace, regardless of environment variable
303-
/// configuration.
304-
///
305-
/// This function behaves the same as `capture` except that it ignores the
306-
/// values of the `RUST_BACKTRACE` and `RUST_LIB_BACKTRACE` environment
307-
/// variables, always capturing a backtrace.
308-
///
309-
/// Note that capturing a backtrace can be an expensive operation on some
310-
/// platforms, so this should be used with caution in performance-sensitive
311-
/// parts of code.
312-
#[inline(never)] // want to make sure there's a frame here to remove
313-
pub fn force_capture() -> Backtrace {
314-
Backtrace::create(Backtrace::force_capture as usize)
315-
}
316-
317-
/// Forcibly captures a disabled backtrace, regardless of environment
318-
/// variable configuration.
319-
pub const fn disabled() -> Backtrace {
320-
Backtrace { inner: Inner::Disabled }
321-
}
322-
323-
// Capture a backtrace which start just before the function addressed by
324-
// `ip`
325-
fn create(ip: usize) -> Backtrace {
326-
// SAFETY: We don't attempt to lock this reentrantly.
327-
let _lock = unsafe { lock() };
328-
let mut frames = Vec::new();
329-
let mut actual_start = None;
330-
unsafe {
331-
backtrace_rs::trace_unsynchronized(|frame| {
332-
frames.push(BacktraceFrame {
333-
frame: RawFrame::Actual(frame.clone()),
334-
symbols: Vec::new(),
335-
});
336-
if frame.symbol_address() as usize == ip && actual_start.is_none() {
337-
actual_start = Some(frames.len());
338-
}
339-
true
340-
});
341-
}
342-
343-
// If no frames came out assume that this is an unsupported platform
344-
// since `backtrace` doesn't provide a way of learning this right now,
345-
// and this should be a good enough approximation.
346-
let inner = if frames.is_empty() {
347-
Inner::Unsupported
348-
} else {
349-
Inner::Captured(LazilyResolvedCapture::new(Capture {
350-
actual_start: actual_start.unwrap_or(0),
351-
frames,
352-
resolved: false,
353-
}))
354-
};
355-
356-
Backtrace { inner }
357-
}
358-
359-
/// Returns the status of this backtrace, indicating whether this backtrace
360-
/// request was unsupported, disabled, or a stack trace was actually
361-
/// captured.
362-
pub fn status(&self) -> BacktraceStatus {
363-
match self.inner {
364-
Inner::Unsupported => BacktraceStatus::Unsupported,
365-
Inner::Disabled => BacktraceStatus::Disabled,
366-
Inner::Captured(_) => BacktraceStatus::Captured,
367-
}
368-
}
369-
}
370-
371-
impl<'a> Backtrace {
372-
/// Returns an iterator over the backtrace frames.
373-
#[unstable(feature = "backtrace_frames", issue = "79676")]
374-
pub fn frames(&'a self) -> &'a [BacktraceFrame] {
375-
if let Inner::Captured(c) = &self.inner { &c.force().frames } else { &[] }
376-
}
377-
}
317+
// impl<'a> StdBacktrace {
318+
// /// Returns an iterator over the backtrace frames.
319+
// #[unstable(feature = "backtrace_frames", issue = "79676")]
320+
// pub fn frames(&'a self) -> &'a [BacktraceFrame] {
321+
// if let Inner::Captured(c) = &self.inner { &c.force().frames } else { &[] }
322+
// }
323+
// }
378324

379-
impl fmt::Display for BacktraceImpl {
325+
impl fmt::Display for StdBacktrace {
380326
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
381327
let capture = match &self.inner {
382328
Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
383-
Inner::Disabled => return fmt.write_str("disabled backtrace"),
384329
Inner::Captured(c) => c.force(),
385330
};
386331

‎library/std/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@
230230
#![feature(asm)]
231231
#![feature(associated_type_bounds)]
232232
#![feature(atomic_mut_ptr)]
233+
#![feature(backtrace)]
233234
#![feature(box_syntax)]
234235
#![feature(c_variadic)]
235236
#![feature(cfg_accessible)]
@@ -249,7 +250,6 @@
249250
#![feature(const_raw_ptr_deref)]
250251
#![feature(const_ipv4)]
251252
#![feature(container_error_extra)]
252-
#![feature(core_backtrace)]
253253
#![feature(core_intrinsics)]
254254
#![feature(custom_test_frameworks)]
255255
#![feature(decl_macro)]

0 commit comments

Comments
 (0)
Please sign in to comment.