Skip to main content

miri/shims/unix/linux_like/
thread.rs

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