Skip to content

miri_get_backtrace: stop supporting the v0 protocol #4172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1211,22 +1211,6 @@ where
throw_ub_format!("incorrect number of arguments: got {}, expected {}", args.len(), N)
}

/// Check that the number of args is at least the minimum what we expect.
/// FIXME: Remove this function, use varargs and `check_min_vararg_count` instead.
pub fn check_min_arg_count<'a, 'tcx, const N: usize>(
name: &'a str,
args: &'a [OpTy<'tcx>],
) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> {
if let Some((ops, _)) = args.split_first_chunk() {
return interp_ok(ops);
}
throw_ub_format!(
"incorrect number of arguments for `{name}`: got {}, expected at least {}",
args.len(),
N
)
}

/// Check that the number of varargs is at least the minimum what we expect.
/// Fixed args should not be included.
/// Use `check_vararg_fixed_arg_count` to extract the varargs slice from full function arguments.
Expand Down
40 changes: 8 additions & 32 deletions src/shims/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use rustc_middle::ty::{self, Instance, Ty};
use rustc_span::{BytePos, Loc, Symbol, hygiene};
use rustc_target::callconv::{Conv, FnAbi};

use crate::helpers::check_min_arg_count;
use crate::*;

impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
Expand Down Expand Up @@ -34,13 +33,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
abi: &FnAbi<'tcx, Ty<'tcx>>,
link_name: Symbol,
args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
let tcx = this.tcx;
let ptr_ty = this.machine.layouts.mut_raw_ptr.ty;
let ptr_layout = this.layout_of(ptr_ty)?;

let [flags, buf] = this.check_shim(abi, Conv::Rust, link_name, args)?;

let [flags] = check_min_arg_count("miri_get_backtrace", args)?;
let flags = this.read_scalar(flags)?.to_u64()?;
let buf_place = this.deref_pointer_as(buf, ptr_layout)?;

let mut data = Vec::new();
for frame in this.active_thread_stack().iter().rev() {
Expand All @@ -63,43 +64,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
})
.collect();

let len: u64 = ptrs.len().try_into().unwrap();

let ptr_ty = this.machine.layouts.mut_raw_ptr.ty;
let array_layout = this.layout_of(Ty::new_array(tcx.tcx, ptr_ty, len)).unwrap();

match flags {
// storage for pointers is allocated by miri
// deallocating the slice is undefined behavior with a custom global allocator
0 => {
let [_flags] = this.check_shim(abi, Conv::Rust, link_name, args)?;

let alloc = this.allocate(array_layout, MiriMemoryKind::Rust.into())?;

// Write pointers into array
for (i, ptr) in ptrs.into_iter().enumerate() {
let place = this.project_index(&alloc, i as u64)?;

this.write_pointer(ptr, &place)?;
}

this.write_immediate(Immediate::new_slice(alloc.ptr(), len, this), dest)?;
throw_unsup_format!("miri_get_backtrace: v0 is not supported any more");
}
// storage for pointers is allocated by the caller
1 => {
let [_flags, buf] = this.check_shim(abi, Conv::Rust, link_name, args)?;

let ptr_layout = this.layout_of(ptr_ty)?;
let buf_place = this.deref_pointer_as(buf, ptr_layout)?;

1 =>
for (i, ptr) in ptrs.into_iter().enumerate() {
let offset = ptr_layout.size.checked_mul(i.try_into().unwrap(), this).unwrap();

let op_place = buf_place.offset(offset, ptr_layout, this)?;

this.write_pointer(ptr, &op_place)?;
}
}
},
_ => throw_unsup_format!("unknown `miri_get_backtrace` flags {}", flags),
};

Expand Down
2 changes: 1 addition & 1 deletion src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Obtains a Miri backtrace. See the README for details.
"miri_get_backtrace" => {
// `check_shim` happens inside `handle_miri_get_backtrace`.
this.handle_miri_get_backtrace(abi, link_name, args, dest)?;
this.handle_miri_get_backtrace(abi, link_name, args)?;
}
// Resolves a Miri backtrace frame. See the README for details.
"miri_resolve_frame" => {
Expand Down
7 changes: 5 additions & 2 deletions tests/fail/shims/backtrace/bad-backtrace-decl.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
extern "Rust" {
fn miri_get_backtrace(flags: u64) -> Box<[*mut ()]>;
fn miri_backtrace_size(flags: u64) -> usize;
fn miri_get_backtrace(flags: u64, buf: *mut *mut ());
fn miri_resolve_frame(ptr: *mut (), flags: u64);
}

fn main() {
let frames = unsafe { miri_get_backtrace(0) };
let size = unsafe { miri_backtrace_size(0) };
let mut frames = vec![std::ptr::null_mut(); size];
unsafe { miri_get_backtrace(1, frames.as_mut_ptr()) };
for frame in frames.iter() {
unsafe {
miri_resolve_frame(*frame, 0); //~ ERROR: Undefined Behavior: bad declaration of miri_resolve_frame - should return a struct with 5 fields
Expand Down