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], _) = ecx.check_varargs(
29                shim_varargs![*libc::c_char],
30                varargs,
31                "prctl(PR_SET_NAME, ...)",
32            )?;
33
34            let name = ecx.read_scalar(name)?;
35            let thread = ecx.pthread_self()?;
36            // The Linux kernel silently truncates long names.
37            // https://www.man7.org/linux/man-pages/man2/PR_SET_NAME.2const.html
38            let res =
39                ecx.pthread_setname_np(thread, name, TASK_COMM_LEN, /* truncate */ true)?;
40            assert_eq!(res, ThreadNameResult::Ok);
41            Scalar::from_u32(0)
42        }
43        op if op == pr_get_name => {
44            let ([name], _) = ecx.check_varargs(
45                shim_varargs![*libc::c_char],
46                varargs,
47                "prctl(PR_GET_NAME, ...)",
48            )?;
49
50            let name = ecx.read_scalar(name)?;
51            let thread = ecx.pthread_self()?;
52            let len = Scalar::from_target_usize(TASK_COMM_LEN, ecx);
53            ecx.check_ptr_access(
54                name.to_pointer(ecx),
55                Size::from_bytes(TASK_COMM_LEN),
56                CheckInAllocMsg::MemoryAccess,
57            )?;
58            let res = ecx.pthread_getname_np(thread, name, len, /* truncate*/ false)?;
59            assert_eq!(res, ThreadNameResult::Ok);
60            Scalar::from_u32(0)
61        }
62        op => throw_unsup_format!("Miri does not support `prctl` syscall with op={}", op),
63    };
64    ecx.write_scalar(res, dest)?;
65    interp_ok(())
66}