Skip to main content

miri/shims/unix/linux_like/
thread.rs

1use rustc_abi::Size;
2use rustc_middle::ty::Ty;
3use rustc_span::Symbol;
4use rustc_target::callconv::FnAbi;
5
6use crate::shims::unix::thread::{EvalContextExt as _, ThreadNameResult};
7use crate::*;
8
9const TASK_COMM_LEN: u64 = 16;
10
11pub fn prctl<'tcx>(
12    ecx: &mut MiriInterpCx<'tcx>,
13    link_name: Symbol,
14    abi: &FnAbi<'tcx, Ty<'tcx>>,
15    args: &[OpTy<'tcx>],
16    dest: &MPlaceTy<'tcx>,
17) -> InterpResult<'tcx> {
18    let ([op], varargs) = ecx.check_shim_sig_variadic(
19        shim_sig!(extern "C" fn(i32, ...) -> i32),
20        (link_name, abi, args),
21    )?;
22
23    let pr_set_name = ecx.eval_libc_i32("PR_SET_NAME");
24    let pr_get_name = ecx.eval_libc_i32("PR_GET_NAME");
25
26    let res = match ecx.read_scalar(op)?.to_i32()? {
27        op if op == pr_set_name => {
28            let ([name], _) =
29                ecx.check_varargs(shim_varargs![*_], varargs, "prctl(PR_SET_NAME, ...)")?;
30
31            let name = ecx.read_scalar(name)?;
32            let thread = ecx.pthread_self()?;
33            // The Linux kernel silently truncates long names.
34            // https://www.man7.org/linux/man-pages/man2/PR_SET_NAME.2const.html
35            let res =
36                ecx.pthread_setname_np(thread, name, TASK_COMM_LEN, /* truncate */ true)?;
37            assert_eq!(res, ThreadNameResult::Ok);
38            Scalar::from_u32(0)
39        }
40        op if op == pr_get_name => {
41            let ([name], _) =
42                ecx.check_varargs(shim_varargs![*_], varargs, "prctl(PR_GET_NAME, ...)")?;
43
44            let name = ecx.read_scalar(name)?;
45            let thread = ecx.pthread_self()?;
46            let len = Scalar::from_target_usize(TASK_COMM_LEN, ecx);
47            ecx.check_ptr_access(
48                name.to_pointer(ecx),
49                Size::from_bytes(TASK_COMM_LEN),
50                CheckInAllocMsg::MemoryAccess,
51            )?;
52            let res = ecx.pthread_getname_np(thread, name, len, /* truncate*/ false)?;
53            assert_eq!(res, ThreadNameResult::Ok);
54            Scalar::from_u32(0)
55        }
56        op => throw_unsup_format!("Miri does not support `prctl` syscall with op={}", op),
57    };
58    ecx.write_scalar(res, dest)?;
59    interp_ok(())
60}