]> git.proxmox.com Git - rustc.git/blame - library/backtrace/src/backtrace/miri.rs
New upstream version 1.65.0+dfsg1
[rustc.git] / library / backtrace / src / backtrace / miri.rs
CommitLineData
29967ef6 1use alloc::boxed::Box;
923072b8 2use alloc::vec::Vec;
29967ef6
XL
3use core::ffi::c_void;
4
5extern "Rust" {
923072b8
FG
6 fn miri_backtrace_size(flags: u64) -> usize;
7 fn miri_get_backtrace(flags: u64, buf: *mut *mut ());
29967ef6 8 fn miri_resolve_frame(ptr: *mut (), flags: u64) -> MiriFrame;
923072b8 9 fn miri_resolve_frame_names(ptr: *mut (), flags: u64, name_buf: *mut u8, filename_buf: *mut u8);
29967ef6
XL
10}
11
29967ef6
XL
12#[repr(C)]
13pub struct MiriFrame {
923072b8
FG
14 pub name_len: usize,
15 pub filename_len: usize,
16 pub lineno: u32,
17 pub colno: u32,
18 pub fn_ptr: *mut c_void,
19}
20
21#[derive(Clone, Debug)]
22pub struct FullMiriFrame {
29967ef6
XL
23 pub name: Box<[u8]>,
24 pub filename: Box<[u8]>,
25 pub lineno: u32,
26 pub colno: u32,
27 pub fn_ptr: *mut c_void,
28}
29
30#[derive(Debug, Clone)]
31pub struct Frame {
32 pub addr: *mut c_void,
923072b8 33 pub inner: FullMiriFrame,
29967ef6
XL
34}
35
36// SAFETY: Miri guarantees that the returned pointer
37// can be used from any thread.
38unsafe impl Send for Frame {}
39unsafe impl Sync for Frame {}
40
41impl Frame {
42 pub fn ip(&self) -> *mut c_void {
43 self.addr
44 }
45
46 pub fn sp(&self) -> *mut c_void {
47 core::ptr::null_mut()
48 }
49
50 pub fn symbol_address(&self) -> *mut c_void {
51 self.inner.fn_ptr
52 }
53
54 pub fn module_base_address(&self) -> Option<*mut c_void> {
55 None
56 }
57}
58
59pub fn trace<F: FnMut(&super::Frame) -> bool>(cb: F) {
923072b8 60 // SAFETY: Miri guarantees that the backtrace API functions
29967ef6
XL
61 // can be called from any thread.
62 unsafe { trace_unsynchronized(cb) };
63}
64
65pub fn resolve_addr(ptr: *mut c_void) -> Frame {
66 // SAFETY: Miri will stop execution with an error if this pointer
67 // is invalid.
923072b8
FG
68 let frame = unsafe { miri_resolve_frame(ptr as *mut (), 1) };
69
70 let mut name = Vec::with_capacity(frame.name_len);
71 let mut filename = Vec::with_capacity(frame.filename_len);
72
73 // SAFETY: name and filename have been allocated with the amount
74 // of memory miri has asked for, and miri guarantees it will initialize it
75 unsafe {
76 miri_resolve_frame_names(ptr as *mut (), 0, name.as_mut_ptr(), filename.as_mut_ptr());
77
78 name.set_len(frame.name_len);
79 filename.set_len(frame.filename_len);
80 }
81
29967ef6
XL
82 Frame {
83 addr: ptr,
923072b8
FG
84 inner: FullMiriFrame {
85 name: name.into(),
86 filename: filename.into(),
87 lineno: frame.lineno,
88 colno: frame.colno,
89 fn_ptr: frame.fn_ptr,
90 },
29967ef6
XL
91 }
92}
93
f2b60f7d 94unsafe fn trace_unsynchronized<F: FnMut(&super::Frame) -> bool>(mut cb: F) {
923072b8
FG
95 let len = miri_backtrace_size(0);
96
97 let mut frames = Vec::with_capacity(len);
98
99 miri_get_backtrace(1, frames.as_mut_ptr());
100
101 frames.set_len(len);
102
29967ef6
XL
103 for ptr in frames.iter() {
104 let frame = resolve_addr(*ptr as *mut c_void);
f2b60f7d
FG
105 if !cb(&super::Frame { inner: frame }) {
106 return;
107 }
29967ef6
XL
108 }
109}