]> git.lizzy.rs Git - rust.git/commitdiff
Add an `fn_ptr` field to `MiriFrame`
authorAaron Hill <aa1ronham@gmail.com>
Sat, 10 Oct 2020 17:07:57 +0000 (13:07 -0400)
committerAaron Hill <aa1ronham@gmail.com>
Sat, 10 Oct 2020 17:07:57 +0000 (13:07 -0400)
The `backtrace-rs` crate can use this to implement
`Frame::symbol_address`, which is used to skip frames
above the call to `Backtrace::capture` on the stack.

The function pointer will not be useable for comparison purposes if the
function is generic, as CTFE creates a new function pointer for each
cast of a (monomorphized) generic function. However, this already
affects code running under Miri, and isn't a problem for `backtrace-rs`
(which only casts a non-generic function).

I've added logic to allow `MiriFrame` to have either 4 or 5 fields - if
a 5th field is present, we write the function pointer to it.

README.md
src/shims/backtrace.rs
tests/compile-fail/backtrace/bad-backtrace-decl.rs
tests/run-pass/backtrace-api.rs
tests/run-pass/backtrace-api.stderr
tests/run-pass/backtrace-api.stdout

index ceaf993924efde9cb8f07cedf6d42daec8780cd6..747afb9c4e93aa3e38cae47a5c974e853f9dd0d2 100644 (file)
--- a/README.md
+++ b/README.md
@@ -286,6 +286,10 @@ extern "Rust" {
     ///     lineno: u32,
     ///     // The column number currently being executed in `filename`, starting from '1'.
     ///     colno: u32,
+    ///     // The function pointer to the function currently being executed.
+    ///     // This can be compared against function pointers obtained by
+    ///     // casting a function (e.g. `my_fn as *mut ()`)
+    ///     fn_ptr: *mut ()
     /// }
     /// ```
     ///
index bd36587116a06f5822b2da1c30fff69b62b88177..9b396c718493fc2a54892ac7215d4a751563819a 100644 (file)
@@ -92,8 +92,18 @@ fn handle_miri_resolve_frame(
             throw_ub_format!("expected function pointer, found {:?}", ptr);
         };
 
-        if dest.layout.layout.fields.count() != 4 {
-            throw_ub_format!("bad declaration of miri_resolve_frame - should return a struct with 4 fields");
+        // Reconstruct the original function pointer,
+        // which we pass to user code.
+        let mut fn_ptr = ptr;
+        fn_ptr.offset = Size::from_bytes(0);
+        let fn_ptr = Scalar::Ptr(fn_ptr);
+
+        let num_fields = dest.layout.layout.fields.count();
+
+        if num_fields != 4 && num_fields != 5 {
+            // Always mention 5 fields, since the 4-field struct is only supported
+            // for backwards compatiblity. New code should declare 5 fields
+            throw_ub_format!("bad declaration of miri_resolve_frame - should return a struct with 5 fields");
         }
 
         let pos = BytePos(ptr.offset.bytes().try_into().unwrap());
@@ -122,6 +132,11 @@ fn handle_miri_resolve_frame(
         this.write_immediate(filename_alloc.to_ref(), this.mplace_field(dest, 1)?.into())?;
         this.write_scalar(lineno_alloc, this.mplace_field(dest, 2)?.into())?;
         this.write_scalar(colno_alloc, this.mplace_field(dest, 3)?.into())?;
+
+        if num_fields == 5 {
+            this.write_scalar(fn_ptr, this.mplace_field(dest, 4)?.into())?;
+        }
+
         Ok(())
     }
 }
index b9f1c779ae23277377acab99fc60946b989e6618..23379992d5ecb535b16c32833508deb20c79ec00 100644 (file)
@@ -7,7 +7,7 @@ fn main() {
     let frames = unsafe { miri_get_backtrace(0) };
     for frame in frames.into_iter() {
         unsafe {
-            miri_resolve_frame(*frame, 0); //~ ERROR Undefined Behavior: bad declaration of miri_resolve_frame - should return a struct with 4 fields
+            miri_resolve_frame(*frame, 0); //~ ERROR Undefined Behavior: bad declaration of miri_resolve_frame - should return a struct with 5 fields
         }
     }
 }
index eaf29abfd9f48d16d864367ea8b68e0cfc0f0d1e..19169060038e07d5aee763e8febdd61e9790def5 100644 (file)
@@ -2,20 +2,6 @@
 // normalize-stderr-test "RUSTLIB/(.*):\d+:\d+ "-> "RUSTLIB/$1:LL:COL "
 // normalize-stderr-test "::<.*>" -> ""
 
-extern "Rust" {
-    fn miri_get_backtrace(flags: u64) -> Box<[*mut ()]>;
-    fn miri_resolve_frame(ptr: *mut (), flags: u64) -> MiriFrame;
-}
-
-#[derive(Debug)]
-#[repr(C)]
-struct MiriFrame {
-    name: Box<[u8]>,
-    filename: Box<[u8]>,
-    lineno: u32,
-    colno: u32
-}
-
 #[inline(never)] fn func_a() -> Box<[*mut ()]> { func_b::<u8>() }
 #[inline(never)] fn func_b<T>() -> Box<[*mut ()]> { func_c() }
 
@@ -34,6 +20,10 @@ fn main() {
         let name = String::from_utf8(miri_frame.name.into()).unwrap();
         let filename = String::from_utf8(miri_frame.filename.into()).unwrap();
 
+        if name == "func_a" {
+            assert_eq!(func_a as *mut (), miri_frame.fn_ptr);
+        }
+
         // Print every frame to stderr.
         let out = format!("{}:{}:{} ({})", filename, miri_frame.lineno, miri_frame.colno, name);
         eprintln!("{}", out);
@@ -45,3 +35,22 @@ fn main() {
         }
     }
 }
+
+// This goes at the bottom of the file so that we can change it
+// without disturbing line numbers of the functions in the backtrace.
+
+extern "Rust" {
+    fn miri_get_backtrace(flags: u64) -> Box<[*mut ()]>;
+    fn miri_resolve_frame(ptr: *mut (), flags: u64) -> MiriFrame;
+}
+
+#[derive(Debug)]
+#[repr(C)]
+struct MiriFrame {
+    name: Box<[u8]>,
+    filename: Box<[u8]>,
+    lineno: u32,
+    colno: u32,
+    fn_ptr: *mut (),
+}
+
index 02e7a7e1eaf9c88635b6c5d449b0b702ceb60840..a5208221da4053631d61a37648c1affbec88687f 100644 (file)
@@ -1,8 +1,8 @@
-$DIR/backtrace-api.rs:27:59 (func_d)
-$DIR/backtrace-api.rs:26:50 (func_c)
-$DIR/backtrace-api.rs:20:53 (func_b)
-$DIR/backtrace-api.rs:19:50 (func_a)
-$DIR/backtrace-api.rs:31:18 (main)
+$DIR/backtrace-api.rs:13:59 (func_d)
+$DIR/backtrace-api.rs:12:50 (func_c)
+$DIR/backtrace-api.rs:6:53 (func_b)
+$DIR/backtrace-api.rs:5:50 (func_a)
+$DIR/backtrace-api.rs:17:18 (main)
 RUSTLIB/core/src/ops/function.rs:LL:COL (<fn() as std::ops::FnOnce<()>>::call_once - shim(fn()))
 RUSTLIB/std/src/sys_common/backtrace.rs:LL:COL (std::sys_common::backtrace::__rust_begin_short_backtrace)
 RUSTLIB/std/src/rt.rs:LL:COL (std::rt::lang_start::{closure#0})
index 90ab4bb96e625c5e2ac20904f8e273e56bd8ed27..175ff3b82946194c62ffdf20cf9de0ece53aaa8c 100644 (file)
@@ -1,5 +1,5 @@
-$DIR/backtrace-api.rs:27:59 (func_d)
-$DIR/backtrace-api.rs:26:50 (func_c)
-$DIR/backtrace-api.rs:20:53 (func_b::<u8>)
-$DIR/backtrace-api.rs:19:50 (func_a)
-$DIR/backtrace-api.rs:31:18 (main)
+$DIR/backtrace-api.rs:13:59 (func_d)
+$DIR/backtrace-api.rs:12:50 (func_c)
+$DIR/backtrace-api.rs:6:53 (func_b::<u8>)
+$DIR/backtrace-api.rs:5:50 (func_a)
+$DIR/backtrace-api.rs:17:18 (main)