//! Tracee-side syscall contract for installing host shadows.
//!
//! The fd model decides *what* must appear at a guest fd, and the shadow module
//! owns the host handles. This module defines the minimal syscall sequence a
//! Linux x86_64 tracee executor must perform to make that plan real.

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
use super::fd::ModelThreadId;
use super::fd::{FdError, FdNumber, FdOperation, KboxlikeFdSystem, ProcessId, ShadowInstallPlan};
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
use super::memory::read_proc_maps_for_pid;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
use super::snapshot::{
    KboxlikeMaterializedMemoryRestore, KboxlikeMaterializedMemoryRestoreAction,
    KboxlikeSharedMappingKind, KboxlikeSharedMemoryDump, KboxlikeThreadKernelStateSnapshot,
    KboxlikeThreadSnapshot,
};
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
use std::collections::{BTreeMap, BTreeSet};
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
use std::ffi::{c_void, CString};
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
use std::os::unix::ffi::OsStrExt;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
use std::path::{Path, PathBuf};

const LINUX_X86_64_SYS_CLOSE: i64 = 3;
const LINUX_X86_64_SYS_DUP2: i64 = 33;
const LINUX_X86_64_SYS_FCNTL: i64 = 72;
const LINUX_X86_64_SYS_MMAP: i64 = 9;
const LINUX_X86_64_SYS_MPROTECT: i64 = 10;
const LINUX_X86_64_SYS_MUNMAP: i64 = 11;
const LINUX_X86_64_SYS_RECVMSG: i64 = 47;
const LINUX_X86_64_SYS_SOCKETPAIR: i64 = 53;
const LINUX_X86_64_SYS_PRCTL: i64 = 157;
const LINUX_X86_64_SYS_OPENAT: i64 = 257;
const LINUX_X86_64_SYS_SETGROUPS: i64 = 116;
const LINUX_X86_64_SYS_SETRESUID: i64 = 117;
const LINUX_X86_64_SYS_SETRESGID: i64 = 119;
const LINUX_X86_64_SYS_SET_TID_ADDRESS: i64 = 218;
const LINUX_X86_64_SYS_SET_ROBUST_LIST: i64 = 273;
const LINUX_AT_FDCWD: u64 = (-100i64) as u64;
const LINUX_AF_UNIX: u64 = 1;
const LINUX_SOCK_STREAM: u64 = 1;
const LINUX_O_RDWR: u64 = 0o2;
const LINUX_O_CLOEXEC: u64 = 0o2000000;
const LINUX_PROT_READ: u64 = 0x1;
const LINUX_PROT_WRITE: u64 = 0x2;
const LINUX_PROT_EXEC: u64 = 0x4;
const LINUX_MAP_SHARED: u64 = 0x01;
const LINUX_MAP_PRIVATE: u64 = 0x02;
const LINUX_MAP_FIXED: u64 = 0x10;
const LINUX_MAP_ANONYMOUS: u64 = 0x20;
const LINUX_MAP_FIXED_NOREPLACE: u64 = 0x100000;
const LINUX_F_DUPFD_CLOEXEC: u64 = 1030;
const LINUX_F_SETFD: u64 = 2;
const LINUX_FD_CLOEXEC: u64 = 1;
const LINUX_PR_SET_MM: u64 = 35;
const LINUX_PR_SET_MM_EXE_FILE: u64 = 13;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const LINUX_CLONE_VM: i32 = 0x0000_0100;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const LINUX_CLONE_FS: i32 = 0x0000_0200;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const LINUX_CLONE_FILES: i32 = 0x0000_0400;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const LINUX_CLONE_SIGHAND: i32 = 0x0000_0800;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const LINUX_CLONE_THREAD: i32 = 0x0001_0000;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const LINUX_CLONE_SYSVSEM: i32 = 0x0004_0000;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const KBOXLIKE_REPLACEMENT_SYSCALL_PAGE_ENV: &str =
    "SUPERMACHINE_KBOXLIKE_REPLACEMENT_SYSCALL_PAGE";
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const LINUX_PTRACE_O_TRACESYSGOOD: u64 = 0x0000_0001;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const LINUX_PTRACE_O_TRACECLONE: u64 = 0x0000_0008;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const LINUX_PTRACE_EVENT_CLONE: i32 = 3;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const LINUX_PTRACE_EVENT_SHIFT: i32 = 16;
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
const REPLACEMENT_FOLLOWER_STACK_LEN: usize = 1024 * 1024;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct TraceeInstallPlan {
    pub(crate) source_fd: i32,
    pub(crate) target_fd: i32,
    pub(crate) cloexec: bool,
    pub(crate) close_source_after_install: bool,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct TraceeSyscall {
    pub(crate) nr: i64,
    pub(crate) args: [u64; 6],
}

impl TraceeSyscall {
    pub(crate) fn new3(nr: i64, arg0: u64, arg1: u64, arg2: u64) -> Self {
        Self {
            nr,
            args: [arg0, arg1, arg2, 0, 0, 0],
        }
    }

    pub(crate) fn new6(nr: i64, args: [u64; 6]) -> Self {
        Self { nr, args }
    }
}

pub(crate) trait TraceeSyscallExecutor {
    fn syscall(&mut self, syscall: TraceeSyscall) -> Result<i64, FdError>;

    fn tracee_pid(&self) -> Option<i32> {
        None
    }

    fn kernel_synthetic_ranges(&self) -> Result<Vec<(u64, u64)>, FdError> {
        Ok(Vec::new())
    }
}

pub(crate) trait TraceeMemoryWriter {
    fn write_bytes(&mut self, addr: u64, bytes: &[u8]) -> Result<(), FdError>;
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) trait TraceeRegisterWriter {
    fn write_regs(&mut self, regs: &libc::user_regs_struct) -> Result<(), FdError>;
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeMemoryRestoreSummary {
    pub(crate) byte_backed_applied: usize,
    pub(crate) clean_file_remapped: usize,
    pub(crate) shared_object_remapped: usize,
    pub(crate) skipped_no_mapping: usize,
    pub(crate) deferred_unsupported: usize,
    pub(crate) other_tracee: usize,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeRegisterRestoreSummary {
    pub(crate) registers_restored: usize,
    pub(crate) other_tracee: usize,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeKernelStateRestoreSummary {
    pub(crate) clear_child_tid_applied: usize,
    pub(crate) robust_list_applied: usize,
    pub(crate) other_tracee: usize,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeRestoreSummary {
    pub(crate) memory: TraceeMemoryRestoreSummary,
    pub(crate) registers: TraceeRegisterRestoreSummary,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeRestoreSetSummary {
    pub(crate) tracees_restored: usize,
    pub(crate) shared_objects: TraceeSharedObjectRegistryBuildSummary,
    pub(crate) memory: TraceeMemoryRestoreSummary,
    pub(crate) registers: TraceeRegisterRestoreSummary,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeFullRestoreSetSummary {
    pub(crate) tracees_restored: usize,
    pub(crate) shared_objects: TraceeSharedObjectRegistryBuildSummary,
    pub(crate) memory: TraceeMemoryRestoreSummary,
    pub(crate) kernel_state: TraceeKernelStateRestoreSummary,
    pub(crate) registers: TraceeRegisterRestoreSummary,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeResumeSetSummary {
    pub(crate) tracees_resumed: usize,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeRestoreAndResumeSetSummary {
    pub(crate) restore: TraceeRestoreSetSummary,
    pub(crate) resume: TraceeResumeSetSummary,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeFullRestoreAndResumeSetSummary {
    pub(crate) restore: TraceeFullRestoreSetSummary,
    pub(crate) resume: TraceeResumeSetSummary,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeReplacementPidRemapSummary {
    pub(crate) threads_remapped: usize,
    pub(crate) memory_actions_remapped: usize,
    pub(crate) shared_dumps_remapped: usize,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Debug)]
pub(crate) struct TraceeRemappedRestoreSet {
    pub(crate) restore: KboxlikeMaterializedMemoryRestore,
    pub(crate) threads: Vec<KboxlikeThreadSnapshot>,
    pub(crate) shared_dumps: Vec<KboxlikeSharedMemoryDump>,
    pub(crate) summary: TraceeReplacementPidRemapSummary,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeThreadGroupMemoryNormalizeSummary {
    pub(crate) process_groups: usize,
    pub(crate) memory_actions_retained: usize,
    pub(crate) memory_actions_reassigned_to_owner: usize,
    pub(crate) duplicate_memory_actions_removed: usize,
    pub(crate) shared_dumps_retained: usize,
    pub(crate) shared_dumps_reassigned_to_owner: usize,
    pub(crate) duplicate_shared_dumps_removed: usize,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Debug)]
pub(crate) struct TraceeThreadGroupMemoryNormalizedRestoreSet {
    pub(crate) restore: KboxlikeMaterializedMemoryRestore,
    pub(crate) shared_dumps: Vec<KboxlikeSharedMemoryDump>,
    pub(crate) memory_owner_host_pids: BTreeMap<ProcessId, i32>,
    pub(crate) summary: TraceeThreadGroupMemoryNormalizeSummary,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeReplacementThreadGroupCreateSummary {
    pub(crate) process_groups: usize,
    pub(crate) tracees_requested: usize,
    pub(crate) tracees_created: usize,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct TraceeReplacementThreadGroupCreateSet {
    pub(crate) replacement_host_pids: BTreeMap<ModelThreadId, i32>,
    pub(crate) summary: TraceeReplacementThreadGroupCreateSummary,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) trait StoppedTraceeReplacementFactory {
    fn prepare_syscall_page(&mut self, _syscall_page: u64) -> Result<(), FdError> {
        Ok(())
    }

    fn create_stopped_replacement_group(
        &mut self,
        model_pid: ProcessId,
        threads: &[KboxlikeThreadSnapshot],
    ) -> Result<BTreeMap<ModelThreadId, i32>, FdError>;
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeMemoryRestoreSummary {
    fn add_assign(&mut self, other: Self) {
        self.byte_backed_applied += other.byte_backed_applied;
        self.clean_file_remapped += other.clean_file_remapped;
        self.shared_object_remapped += other.shared_object_remapped;
        self.skipped_no_mapping += other.skipped_no_mapping;
        self.deferred_unsupported += other.deferred_unsupported;
        self.other_tracee += other.other_tracee;
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeRegisterRestoreSummary {
    fn add_assign(&mut self, other: Self) {
        self.registers_restored += other.registers_restored;
        self.other_tracee += other.other_tracee;
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeKernelStateRestoreSummary {
    fn add_assign(&mut self, other: Self) {
        self.clear_child_tid_applied += other.clear_child_tid_applied;
        self.robust_list_applied += other.robust_list_applied;
        self.other_tracee += other.other_tracee;
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) struct TraceeRestoreAccess<W, E, R> {
    pub(crate) writer: W,
    pub(crate) executor: E,
    pub(crate) register_writer: R,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) trait TraceeRestoreAccessFactory {
    type Writer: TraceeMemoryWriter;
    type Executor: TraceeSyscallExecutor;
    type RegisterWriter: TraceeRegisterWriter;

    fn access_for_restore(
        &mut self,
        host_pid: i32,
    ) -> Result<TraceeRestoreAccess<Self::Writer, Self::Executor, Self::RegisterWriter>, FdError>;
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) trait RestoredTraceeResumer {
    fn resume_restored_tracee(&mut self, host_pid: i32) -> Result<(), FdError>;
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct TraceeByteBackedMapping {
    pub(crate) addr: u64,
    pub(crate) prot: i32,
    pub(crate) bytes: Vec<u8>,
}

impl TraceeByteBackedMapping {
    pub(crate) fn new(addr: u64, prot: i32, bytes: Vec<u8>) -> Result<Self, FdError> {
        if addr == 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee mapping address is null",
            ));
        }
        if bytes.is_empty() {
            return Err(FdError::TraceeInstallFailed(
                "tracee mapping bytes are empty",
            ));
        }
        let valid_prot_bits = (LINUX_PROT_READ | LINUX_PROT_WRITE | LINUX_PROT_EXEC) as i32;
        if prot < 0 || prot & !valid_prot_bits != 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee mapping protection is invalid",
            ));
        }
        Ok(Self { addr, prot, bytes })
    }

    pub(crate) fn apply(
        &self,
        writer: &mut impl TraceeMemoryWriter,
        executor: &mut impl TraceeSyscallExecutor,
    ) -> Result<(), FdError> {
        let blocked = executor.kernel_synthetic_ranges()?;
        let blocked = unmap_mappable_synthetic_collisions(
            self.addr,
            self.bytes.len() as u64,
            &blocked,
            executor,
        )?;
        let segments =
            split_range_around_blocked_ranges(self.addr, self.bytes.len() as u64, &blocked)?;
        if segments.is_empty() {
            return Ok(());
        }
        let restored_len = segments.iter().map(|(_, len)| *len).sum::<u64>();
        if (segments.len() > 1 || restored_len != self.bytes.len() as u64)
            && std::env::var_os("SUPERMACHINE_KBOXLIKE_TRACE_MEMORY_RESTORE").is_some()
        {
            eprintln!(
                "KBOXLIVE_BYTE_MMAP_SPLIT start=0x{:x} len={} restored_len={} segments={} blocked={:?}",
                self.addr,
                self.bytes.len(),
                restored_len,
                segments.len(),
                blocked,
            );
        }
        for (addr, len) in segments {
            self.apply_range(addr, len, writer, executor)?;
        }
        Ok(())
    }

    pub(crate) fn mmap_syscall(&self) -> TraceeSyscall {
        self.mmap_range_syscall(self.addr, self.bytes.len() as u64)
    }

    pub(crate) fn mmap_range_syscall(&self, addr: u64, len: u64) -> TraceeSyscall {
        TraceeSyscall::new6(
            LINUX_X86_64_SYS_MMAP,
            [
                addr,
                len,
                LINUX_PROT_READ | LINUX_PROT_WRITE,
                LINUX_MAP_PRIVATE | LINUX_MAP_FIXED | LINUX_MAP_ANONYMOUS,
                (-1i64) as u64,
                0,
            ],
        )
    }

    pub(crate) fn mprotect_syscall(&self) -> TraceeSyscall {
        self.mprotect_range_syscall(self.addr, self.bytes.len() as u64)
    }

    pub(crate) fn mprotect_range_syscall(&self, addr: u64, len: u64) -> TraceeSyscall {
        TraceeSyscall::new3(LINUX_X86_64_SYS_MPROTECT, addr, len, self.prot as u64)
    }

    fn apply_range(
        &self,
        addr: u64,
        len: u64,
        writer: &mut impl TraceeMemoryWriter,
        executor: &mut impl TraceeSyscallExecutor,
    ) -> Result<(), FdError> {
        let mapped = executor.syscall(self.mmap_range_syscall(addr, len))?;
        if mapped < 0 {
            return Err(FdError::TraceeInstallFailed("tracee fixed mmap failed"));
        }
        if mapped as u64 != addr {
            return Err(FdError::TraceeInstallFailed(
                "tracee fixed mmap returned wrong address",
            ));
        }

        let offset = usize::try_from(addr - self.addr)
            .map_err(|_| FdError::TraceeInstallFailed("tracee mapping byte offset overflowed"))?;
        let len_usize = usize::try_from(len)
            .map_err(|_| FdError::TraceeInstallFailed("tracee mapping byte len overflowed"))?;
        let end = offset
            .checked_add(len_usize)
            .ok_or(FdError::TraceeInstallFailed(
                "tracee mapping byte slice overflowed",
            ))?;
        writer.write_bytes(addr, &self.bytes[offset..end])?;

        if self.needs_final_mprotect() {
            let protected = executor.syscall(self.mprotect_range_syscall(addr, len))?;
            if protected < 0 {
                return Err(FdError::TraceeInstallFailed("tracee mprotect failed"));
            }
        }

        Ok(())
    }

    fn needs_final_mprotect(&self) -> bool {
        self.prot as u64 != (LINUX_PROT_READ | LINUX_PROT_WRITE)
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct TraceeReservedMapping {
    pub(crate) addr: u64,
    pub(crate) len: u64,
    pub(crate) prot: i32,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeReservedMapping {
    pub(crate) fn new(addr: u64, len: u64, prot: i32) -> Result<Self, FdError> {
        if addr == 0 || len == 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee reserved mapping requires non-empty address range",
            ));
        }
        Ok(Self { addr, len, prot })
    }

    pub(crate) fn apply(&self, executor: &mut impl TraceeSyscallExecutor) -> Result<(), FdError> {
        let blocked = executor.kernel_synthetic_ranges()?;
        let blocked = unmap_mappable_synthetic_collisions(self.addr, self.len, &blocked, executor)?;
        let segments = split_range_around_blocked_ranges(self.addr, self.len, &blocked)?;
        for (addr, len) in segments {
            let mapped = executor.syscall(self.mmap_range_syscall(addr, len))?;
            if mapped < 0 {
                return Err(FdError::TraceeInstallFailed(
                    "tracee fixed reserved mmap failed",
                ));
            }
            if mapped as u64 != addr {
                return Err(FdError::TraceeInstallFailed(
                    "tracee fixed reserved mmap returned wrong address",
                ));
            }
        }
        Ok(())
    }

    pub(crate) fn mmap_syscall(&self) -> TraceeSyscall {
        self.mmap_range_syscall(self.addr, self.len)
    }

    pub(crate) fn mmap_range_syscall(&self, addr: u64, len: u64) -> TraceeSyscall {
        TraceeSyscall::new6(
            LINUX_X86_64_SYS_MMAP,
            [
                addr,
                len,
                self.prot as u64,
                LINUX_MAP_PRIVATE | LINUX_MAP_FIXED | LINUX_MAP_ANONYMOUS,
                (-1i64) as u64,
                0,
            ],
        )
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct TraceeCleanFileMapping {
    pub(crate) addr: u64,
    pub(crate) len: u64,
    pub(crate) prot: i32,
    pub(crate) path_bytes: Vec<u8>,
    pub(crate) file_offset: u64,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeCleanFileMapping {
    pub(crate) fn new(
        addr: u64,
        len: u64,
        prot: i32,
        path: &Path,
        file_offset: u64,
    ) -> Result<Self, FdError> {
        if addr == 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee file mapping address is null",
            ));
        }
        if len == 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee file mapping length is zero",
            ));
        }
        let valid_prot_bits = (LINUX_PROT_READ | LINUX_PROT_WRITE | LINUX_PROT_EXEC) as i32;
        if prot < 0 || prot & !valid_prot_bits != 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee file mapping protection is invalid",
            ));
        }

        let raw_path = path.as_os_str().as_bytes();
        if raw_path.is_empty() {
            return Err(FdError::TraceeInstallFailed(
                "tracee file mapping path is empty",
            ));
        }
        if raw_path.contains(&0) {
            return Err(FdError::TraceeInstallFailed(
                "tracee file mapping path contains nul",
            ));
        }

        let mut path_bytes = raw_path.to_vec();
        path_bytes.push(0);
        Ok(Self {
            addr,
            len,
            prot,
            path_bytes,
            file_offset,
        })
    }

    pub(crate) fn apply_with_scratch(
        &self,
        writer: &mut impl TraceeMemoryWriter,
        executor: &mut impl TraceeSyscallExecutor,
    ) -> Result<(), FdError> {
        let scratch = TraceeScratchMapping::map(self.path_bytes.len(), executor)?;
        let result = self.apply_at_path_addr(scratch.addr, writer, executor);
        let unmap_result = scratch.unmap(executor);

        match (result, unmap_result) {
            (Err(err), _) => Err(err),
            (Ok(()), Err(err)) => Err(err),
            (Ok(()), Ok(())) => Ok(()),
        }
    }

    pub(crate) fn apply_at_path_addr(
        &self,
        tracee_path_addr: u64,
        writer: &mut impl TraceeMemoryWriter,
        executor: &mut impl TraceeSyscallExecutor,
    ) -> Result<(), FdError> {
        if tracee_path_addr == 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee file mapping path address is null",
            ));
        }

        writer.write_bytes(tracee_path_addr, &self.path_bytes)?;
        let file_fd = self.open(executor, tracee_path_addr)?;
        let mmap_result = self.mmap_file(executor, file_fd);
        let close_result = self.close_file(executor, file_fd);

        match (mmap_result, close_result) {
            (Err(err), _) => Err(err),
            (Ok(()), Err(err)) => Err(err),
            (Ok(()), Ok(())) => Ok(()),
        }
    }

    pub(crate) fn open_syscall(&self, tracee_path_addr: u64) -> TraceeSyscall {
        TraceeSyscall::new3(
            LINUX_X86_64_SYS_OPENAT,
            LINUX_AT_FDCWD,
            tracee_path_addr,
            LINUX_O_CLOEXEC,
        )
    }

    pub(crate) fn mmap_syscall(&self, file_fd: i32) -> TraceeSyscall {
        self.mmap_range_syscall(self.addr, self.len, self.file_offset, file_fd)
    }

    pub(crate) fn mmap_range_syscall(
        &self,
        addr: u64,
        len: u64,
        file_offset: u64,
        file_fd: i32,
    ) -> TraceeSyscall {
        TraceeSyscall::new6(
            LINUX_X86_64_SYS_MMAP,
            [
                addr,
                len,
                self.prot as u64,
                LINUX_MAP_PRIVATE | LINUX_MAP_FIXED,
                file_fd as u64,
                file_offset,
            ],
        )
    }

    fn open(
        &self,
        executor: &mut impl TraceeSyscallExecutor,
        tracee_path_addr: u64,
    ) -> Result<i32, FdError> {
        let ret = executor.syscall(self.open_syscall(tracee_path_addr))?;
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee open clean file failed",
            ));
        }
        i32::try_from(ret)
            .map_err(|_| FdError::TraceeInstallFailed("tracee open clean file fd overflowed"))
    }

    fn mmap_file(
        &self,
        executor: &mut impl TraceeSyscallExecutor,
        file_fd: i32,
    ) -> Result<(), FdError> {
        let blocked = executor.kernel_synthetic_ranges()?;
        let blocked = unmap_mappable_synthetic_collisions(self.addr, self.len, &blocked, executor)?;
        let segments = split_range_around_blocked_ranges(self.addr, self.len, &blocked)?;
        if segments.is_empty() {
            return Ok(());
        }
        let restored_len = segments.iter().map(|(_, len)| *len).sum::<u64>();
        if (segments.len() > 1 || restored_len != self.len)
            && std::env::var_os("SUPERMACHINE_KBOXLIKE_TRACE_MEMORY_RESTORE").is_some()
        {
            eprintln!(
                "KBOXLIVE_CLEAN_MMAP_SPLIT start=0x{:x} len={} restored_len={} segments={} blocked={:?} path={}",
                self.addr,
                self.len,
                restored_len,
                segments.len(),
                blocked,
                String::from_utf8_lossy(&self.path_bytes[..self.path_bytes.len() - 1]),
            );
        }
        for (addr, len) in segments {
            let file_offset = self.file_offset.checked_add(addr - self.addr).ok_or(
                FdError::TraceeInstallFailed("tracee fixed file mmap offset overflowed"),
            )?;
            self.mmap_file_range(executor, file_fd, addr, len, file_offset)?;
        }
        Ok(())
    }

    fn mmap_file_range(
        &self,
        executor: &mut impl TraceeSyscallExecutor,
        file_fd: i32,
        addr: u64,
        len: u64,
        file_offset: u64,
    ) -> Result<(), FdError> {
        let mapped = executor.syscall(self.mmap_range_syscall(addr, len, file_offset, file_fd))?;
        if mapped < 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee fixed file mmap failed",
            ));
        }
        if mapped as u64 != addr {
            return Err(FdError::TraceeInstallFailed(
                "tracee fixed file mmap returned wrong address",
            ));
        }
        Ok(())
    }

    fn close_file(
        &self,
        executor: &mut impl TraceeSyscallExecutor,
        file_fd: i32,
    ) -> Result<(), FdError> {
        let ret = executor.syscall(TraceeSyscall::new3(
            LINUX_X86_64_SYS_CLOSE,
            file_fd as u64,
            0,
            0,
        ))?;
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee close clean file failed",
            ));
        }
        Ok(())
    }
}

fn split_range_around_blocked_ranges(
    start: u64,
    len: u64,
    blocked: &[(u64, u64)],
) -> Result<Vec<(u64, u64)>, FdError> {
    let end = start.checked_add(len).ok_or(FdError::TraceeInstallFailed(
        "tracee mapping range overflowed",
    ))?;
    let mut segments = vec![(start, end)];
    for &(block_start, block_end) in blocked {
        if block_start >= block_end {
            continue;
        }
        let mut next = Vec::new();
        for (seg_start, seg_end) in segments {
            if block_end <= seg_start || block_start >= seg_end {
                next.push((seg_start, seg_end));
                continue;
            }
            if block_start > seg_start {
                next.push((seg_start, block_start));
            }
            if block_end < seg_end {
                next.push((block_end, seg_end));
            }
        }
        segments = next;
        if segments.is_empty() {
            break;
        }
    }
    Ok(segments
        .into_iter()
        .filter_map(|(seg_start, seg_end)| {
            (seg_end > seg_start).then_some((seg_start, seg_end - seg_start))
        })
        .collect())
}

fn unmap_mappable_synthetic_collisions(
    start: u64,
    len: u64,
    blocked: &[(u64, u64)],
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<Vec<(u64, u64)>, FdError> {
    let end = start.checked_add(len).ok_or(FdError::TraceeInstallFailed(
        "tracee mapping range overflowed",
    ))?;
    let mut still_blocked = Vec::new();
    for &(block_start, block_end) in blocked {
        if block_start >= block_end {
            continue;
        }
        if block_end <= start || block_start >= end {
            still_blocked.push((block_start, block_end));
            continue;
        }
        if is_fixed_vsyscall_range(block_start, block_end) {
            still_blocked.push((block_start, block_end));
            continue;
        }
        let block_len = block_end - block_start;
        let ret = executor.syscall(TraceeSyscall::new6(
            LINUX_X86_64_SYS_MUNMAP,
            [block_start, block_len, 0, 0, 0, 0],
        ))?;
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee synthetic munmap failed",
            ));
        }
        if std::env::var_os("SUPERMACHINE_KBOXLIKE_TRACE_MEMORY_RESTORE").is_some() {
            eprintln!(
                "KBOXLIVE_SYNTHETIC_MUNMAP start=0x{:x} len={} mapping_start=0x{:x} mapping_len={}",
                block_start, block_len, start, len,
            );
        }
    }
    Ok(still_blocked)
}

fn is_fixed_vsyscall_range(start: u64, end: u64) -> bool {
    start >= 0xffff_ffff_ff00_0000 || end > 0xffff_ffff_ff00_0000
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) struct TraceeSharedObjectKey {
    pub(crate) kind: super::snapshot::KboxlikeSharedMappingKind,
    pub(crate) path: Option<String>,
    pub(crate) dev: String,
    pub(crate) inode: u64,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeSharedObjectKey {
    pub(crate) fn from_action(action: &KboxlikeMaterializedMemoryRestoreAction) -> Option<Self> {
        let KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
            kind,
            path,
            dev,
            inode,
            ..
        } = action
        else {
            return None;
        };

        Some(Self {
            kind: *kind,
            path: path.clone(),
            dev: dev.clone(),
            inode: *inode,
        })
    }

    pub(crate) fn from_shared_dump(dump: &KboxlikeSharedMemoryDump) -> Self {
        Self {
            kind: dump.kind,
            path: dump.path.clone(),
            dev: dump.dev.clone(),
            inode: dump.inode,
        }
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Debug, Default)]
pub(crate) struct TraceeSharedObjectRegistry {
    supervisor_fds: BTreeMap<TraceeSharedObjectKey, i32>,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeSharedObjectRegistry {
    pub(crate) fn new() -> Self {
        Self::default()
    }

    pub(crate) fn register(
        &mut self,
        key: TraceeSharedObjectKey,
        supervisor_fd: i32,
    ) -> Result<(), FdError> {
        if supervisor_fd < 0 {
            return Err(FdError::InvalidFd(supervisor_fd));
        }
        if self.supervisor_fds.insert(key, supervisor_fd).is_some() {
            return Err(FdError::TraceeInstallFailed(
                "shared object already registered",
            ));
        }
        Ok(())
    }

    pub(crate) fn supervisor_fd(&self, key: &TraceeSharedObjectKey) -> Option<i32> {
        self.supervisor_fds.get(key).copied()
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub(crate) struct TraceeSharedObjectRegistryBuildSummary {
    pub(crate) created_objects: usize,
    pub(crate) initialized_extents: usize,
    pub(crate) skipped_unsupported_objects: usize,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Debug)]
pub(crate) struct TraceeOwnedSharedObjectRegistry {
    registry: TraceeSharedObjectRegistry,
    owned_fds: Vec<i32>,
    close_on_drop: bool,
    summary: TraceeSharedObjectRegistryBuildSummary,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeOwnedSharedObjectRegistry {
    pub(crate) fn registry(&self) -> &TraceeSharedObjectRegistry {
        &self.registry
    }

    pub(crate) fn summary(&self) -> TraceeSharedObjectRegistryBuildSummary {
        self.summary
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl Drop for TraceeOwnedSharedObjectRegistry {
    fn drop(&mut self) {
        if self.close_on_drop {
            for fd in self.owned_fds.drain(..) {
                unsafe {
                    libc::close(fd);
                }
            }
        }
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) trait TraceeSharedObjectBackingFactory {
    fn create_memfd(&mut self, name: &str) -> Result<i32, FdError>;
    fn set_len(&mut self, fd: i32, len: u64) -> Result<(), FdError>;
    fn write_all_at(&mut self, fd: i32, offset: u64, bytes: &[u8]) -> Result<(), FdError>;

    fn close_fds_on_drop(&self) -> bool {
        true
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Debug, Default)]
pub(crate) struct LinuxTraceeSharedObjectBackingFactory;

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeSharedObjectBackingFactory for LinuxTraceeSharedObjectBackingFactory {
    fn create_memfd(&mut self, name: &str) -> Result<i32, FdError> {
        let name = CString::new(name)
            .map_err(|_| FdError::TraceeInstallFailed("shared object name contains nul"))?;
        let fd = unsafe { libc::memfd_create(name.as_ptr(), libc::MFD_CLOEXEC) };
        if fd < 0 {
            return Err(FdError::TraceeInstallFailed("memfd_create failed"));
        }
        Ok(fd)
    }

    fn set_len(&mut self, fd: i32, len: u64) -> Result<(), FdError> {
        let len = libc::off_t::try_from(len)
            .map_err(|_| FdError::TraceeInstallFailed("shared object length overflows off_t"))?;
        let ret = unsafe { libc::ftruncate(fd, len) };
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed(
                "shared object ftruncate failed",
            ));
        }
        Ok(())
    }

    fn write_all_at(&mut self, fd: i32, offset: u64, bytes: &[u8]) -> Result<(), FdError> {
        let mut written = 0usize;
        while written < bytes.len() {
            let remote_offset =
                offset
                    .checked_add(written as u64)
                    .ok_or(FdError::TraceeInstallFailed(
                        "shared object write offset overflows",
                    ))?;
            let remote_offset = libc::off_t::try_from(remote_offset).map_err(|_| {
                FdError::TraceeInstallFailed("shared object write offset overflows off_t")
            })?;
            let ret = unsafe {
                libc::pwrite(
                    fd,
                    bytes[written..].as_ptr() as *const libc::c_void,
                    bytes.len() - written,
                    remote_offset,
                )
            };
            if ret < 0 {
                return Err(FdError::TraceeInstallFailed("shared object pwrite failed"));
            }
            if ret == 0 {
                return Err(FdError::TraceeInstallFailed(
                    "shared object pwrite returned zero",
                ));
            }
            written += ret as usize;
        }
        Ok(())
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn build_owned_shared_object_registry(
    restore: &KboxlikeMaterializedMemoryRestore,
    shared_dumps: &[KboxlikeSharedMemoryDump],
) -> Result<TraceeOwnedSharedObjectRegistry, FdError> {
    let mut factory = LinuxTraceeSharedObjectBackingFactory;
    build_owned_shared_object_registry_with(restore, shared_dumps, &mut factory)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn build_owned_shared_object_registry_with(
    restore: &KboxlikeMaterializedMemoryRestore,
    shared_dumps: &[KboxlikeSharedMemoryDump],
    factory: &mut impl TraceeSharedObjectBackingFactory,
) -> Result<TraceeOwnedSharedObjectRegistry, FdError> {
    let mut required_extents = BTreeSet::new();
    let mut sizes = BTreeMap::<TraceeSharedObjectKey, u64>::new();
    let mut unsupported_keys = BTreeSet::new();

    for action in &restore.actions {
        let KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
            len, file_offset, ..
        } = action
        else {
            continue;
        };
        let Some(key) = TraceeSharedObjectKey::from_action(action) else {
            unreachable!("matched RecreateSharedObject action");
        };
        if !is_synthetic_shared_object_supported(key.kind) {
            unsupported_keys.insert(key);
            continue;
        }
        let end = file_offset
            .checked_add(*len)
            .ok_or(FdError::TraceeInstallFailed("shared object size overflows"))?;
        sizes
            .entry(key.clone())
            .and_modify(|size| *size = (*size).max(end))
            .or_insert(end);
        required_extents.insert((key, *file_offset, *len));
    }

    let mut dumps_by_extent = BTreeMap::new();
    for dump in shared_dumps {
        let key = TraceeSharedObjectKey::from_shared_dump(dump);
        if !sizes.contains_key(&key) {
            continue;
        }
        let len = dump.bytes.len() as u64;
        if dumps_by_extent
            .insert((key, dump.file_offset, len), dump)
            .is_some()
        {
            return Err(FdError::TraceeInstallFailed(
                "duplicate shared memory dump extent",
            ));
        }
    }

    for extent in &required_extents {
        if !dumps_by_extent.contains_key(extent) {
            return Err(FdError::TraceeInstallFailed(
                "missing shared memory dump extent",
            ));
        }
    }

    let mut registry = TraceeSharedObjectRegistry::new();
    let mut owned_fds = Vec::with_capacity(sizes.len());
    let mut summary = TraceeSharedObjectRegistryBuildSummary {
        skipped_unsupported_objects: unsupported_keys.len(),
        ..TraceeSharedObjectRegistryBuildSummary::default()
    };

    for (key, len) in sizes {
        let fd = factory.create_memfd(&shared_object_memfd_name(&key))?;
        owned_fds.push(fd);
        factory.set_len(fd, len)?;
        registry.register(key.clone(), fd)?;
        summary.created_objects += 1;

        for ((extent_key, offset, _len), dump) in &dumps_by_extent {
            if extent_key == &key {
                factory.write_all_at(fd, *offset, &dump.bytes)?;
                summary.initialized_extents += 1;
            }
        }
    }

    Ok(TraceeOwnedSharedObjectRegistry {
        registry,
        owned_fds,
        close_on_drop: factory.close_fds_on_drop(),
        summary,
    })
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn is_synthetic_shared_object_supported(kind: KboxlikeSharedMappingKind) -> bool {
    matches!(
        kind,
        KboxlikeSharedMappingKind::Memfd
            | KboxlikeSharedMappingKind::Anonymous
            | KboxlikeSharedMappingKind::Device
            | KboxlikeSharedMappingKind::File
    )
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn shared_object_memfd_name(key: &TraceeSharedObjectKey) -> String {
    let raw = key
        .path
        .as_deref()
        .unwrap_or("kboxlike-anonymous-shared")
        .trim_start_matches('/')
        .trim_start_matches("memfd:")
        .trim_end_matches(" (deleted)");
    let name = raw
        .chars()
        .map(|ch| {
            if ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_' | '.') {
                ch
            } else {
                '_'
            }
        })
        .take(240)
        .collect::<String>();
    if name.is_empty() {
        "kboxlike-shared".to_string()
    } else {
        name
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct TraceeSharedFdMapping {
    pub(crate) addr: u64,
    pub(crate) len: u64,
    pub(crate) prot: i32,
    pub(crate) file_offset: u64,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeSharedFdMapping {
    pub(crate) fn new(addr: u64, len: u64, prot: i32, file_offset: u64) -> Result<Self, FdError> {
        if addr == 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee shared mapping address is null",
            ));
        }
        if len == 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee shared mapping length is zero",
            ));
        }
        let valid_prot_bits = (LINUX_PROT_READ | LINUX_PROT_WRITE | LINUX_PROT_EXEC) as i32;
        if prot < 0 || prot & !valid_prot_bits != 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee shared mapping protection is invalid",
            ));
        }
        Ok(Self {
            addr,
            len,
            prot,
            file_offset,
        })
    }

    pub(crate) fn apply_from_supervisor_fd_with_scratch(
        &self,
        supervisor_pid: i32,
        supervisor_fd: i32,
        writer: &mut impl TraceeMemoryWriter,
        executor: &mut impl TraceeSyscallExecutor,
    ) -> Result<(), FdError> {
        let path_probe = TraceeProcFdSourcePlan::new(supervisor_pid, supervisor_fd, 1)?;
        let scratch = TraceeScratchMapping::map(path_probe.path_bytes().len(), executor)?;
        let source = TraceeProcFdSourcePlan::new(supervisor_pid, supervisor_fd, scratch.addr)?;

        let result = self.apply_from_proc_fd_source(&source, writer, executor);
        let unmap_result = scratch.unmap(executor);

        match (result, unmap_result) {
            (Err(err), _) => Err(err),
            (Ok(()), Err(err)) => Err(err),
            (Ok(()), Ok(())) => Ok(()),
        }
    }

    pub(crate) fn apply_from_proc_fd_source(
        &self,
        source: &TraceeProcFdSourcePlan,
        writer: &mut impl TraceeMemoryWriter,
        executor: &mut impl TraceeSyscallExecutor,
    ) -> Result<(), FdError> {
        source.write_path(writer)?;
        let tracee_fd = source.open_with_flags(executor, self.open_flags())?;
        let mmap_result = self.mmap_shared(executor, tracee_fd);
        let close_result = self.close_source(executor, tracee_fd);

        match (mmap_result, close_result) {
            (Err(err), _) => Err(err),
            (Ok(()), Err(err)) => Err(err),
            (Ok(()), Ok(())) => Ok(()),
        }
    }

    pub(crate) fn open_flags(&self) -> u64 {
        if self.prot & libc::PROT_WRITE != 0 {
            LINUX_O_CLOEXEC | LINUX_O_RDWR
        } else {
            LINUX_O_CLOEXEC
        }
    }

    pub(crate) fn mmap_syscall(&self, tracee_fd: i32) -> TraceeSyscall {
        TraceeSyscall::new6(
            LINUX_X86_64_SYS_MMAP,
            [
                self.addr,
                self.len,
                self.prot as u64,
                LINUX_MAP_SHARED | LINUX_MAP_FIXED,
                tracee_fd as u64,
                self.file_offset,
            ],
        )
    }

    fn mmap_shared(
        &self,
        executor: &mut impl TraceeSyscallExecutor,
        tracee_fd: i32,
    ) -> Result<(), FdError> {
        let mapped = executor.syscall(self.mmap_syscall(tracee_fd))?;
        if mapped < 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee fixed shared mmap failed",
            ));
        }
        if mapped as u64 != self.addr {
            return Err(FdError::TraceeInstallFailed(
                "tracee fixed shared mmap returned wrong address",
            ));
        }
        Ok(())
    }

    fn close_source(
        &self,
        executor: &mut impl TraceeSyscallExecutor,
        tracee_fd: i32,
    ) -> Result<(), FdError> {
        let ret = executor.syscall(TraceeSyscall::new3(
            LINUX_X86_64_SYS_CLOSE,
            tracee_fd as u64,
            0,
            0,
        ))?;
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee close shared fd failed",
            ));
        }
        Ok(())
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_materialized_memory_restore_for_tracee(
    restore: &KboxlikeMaterializedMemoryRestore,
    tracee_pid: i32,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<TraceeMemoryRestoreSummary, FdError> {
    let shared = TraceeSharedObjectRegistry::new();
    apply_materialized_memory_restore_for_tracee_with_shared_objects(
        restore, tracee_pid, 0, &shared, writer, executor,
    )
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_materialized_memory_restore_for_tracee_with_shared_objects(
    restore: &KboxlikeMaterializedMemoryRestore,
    tracee_pid: i32,
    supervisor_pid: i32,
    shared_objects: &TraceeSharedObjectRegistry,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<TraceeMemoryRestoreSummary, FdError> {
    if tracee_pid <= 0 {
        return Err(FdError::TraceeInstallFailed("invalid tracee pid"));
    }

    let mut summary = TraceeMemoryRestoreSummary::default();
    let trace_memory_restore =
        std::env::var_os("SUPERMACHINE_KBOXLIKE_TRACE_MEMORY_RESTORE").is_some();
    for (action_index, action) in restore.actions.iter().enumerate() {
        if materialized_action_host_pid(action) != tracee_pid {
            summary.other_tracee += 1;
            continue;
        }

        match action {
            KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                start, prot, bytes, ..
            } => {
                if trace_memory_restore {
                    eprintln!(
                        "KBOXLIVE_MEMORY_ACTION pid={} index={} kind=byte start=0x{:x} len={} prot=0x{:x}",
                        tracee_pid,
                        action_index,
                        start,
                        bytes.len(),
                        prot,
                    );
                }
                TraceeByteBackedMapping::new(*start, *prot, bytes.clone())?
                    .apply(writer, executor)?;
                summary.byte_backed_applied += 1;
            }
            KboxlikeMaterializedMemoryRestoreAction::RemapCleanFile {
                start,
                len,
                prot,
                path,
                file_offset,
                ..
            } => {
                if trace_memory_restore {
                    eprintln!(
                        "KBOXLIVE_MEMORY_ACTION pid={} index={} kind=clean start=0x{:x} len={} prot=0x{:x} offset={} path={}",
                        tracee_pid,
                        action_index,
                        start,
                        len,
                        prot,
                        file_offset,
                        path.display(),
                    );
                }
                TraceeCleanFileMapping::new(*start, *len, *prot, path, *file_offset)?
                    .apply_with_scratch(writer, executor)?;
                summary.clean_file_remapped += 1;
            }
            KboxlikeMaterializedMemoryRestoreAction::SkipKernelSynthetic { .. } => {
                summary.skipped_no_mapping += 1;
            }
            KboxlikeMaterializedMemoryRestoreAction::SkipInaccessible {
                start, len, prot, ..
            } => {
                if trace_memory_restore {
                    eprintln!(
                        "KBOXLIVE_MEMORY_ACTION pid={} index={} kind=reserve start=0x{:x} len={} prot=0x{:x}",
                        tracee_pid, action_index, start, len, prot,
                    );
                }
                TraceeReservedMapping::new(*start, *len, *prot)?.apply(executor)?;
                summary.skipped_no_mapping += 1;
            }
            action @ KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                start,
                len,
                prot,
                file_offset,
                ..
            } => {
                if trace_memory_restore {
                    eprintln!(
                        "KBOXLIVE_MEMORY_ACTION pid={} index={} kind=shared start=0x{:x} len={} prot=0x{:x} offset={}",
                        tracee_pid,
                        action_index,
                        start,
                        len,
                        prot,
                        file_offset,
                    );
                }
                let Some(key) = TraceeSharedObjectKey::from_action(action) else {
                    unreachable!("matched RecreateSharedObject action");
                };
                let Some(supervisor_fd) = shared_objects.supervisor_fd(&key) else {
                    summary.deferred_unsupported += 1;
                    continue;
                };
                TraceeSharedFdMapping::new(*start, *len, *prot, *file_offset)?
                    .apply_from_supervisor_fd_with_scratch(
                        supervisor_pid,
                        supervisor_fd,
                        writer,
                        executor,
                    )?;
                summary.shared_object_remapped += 1;
            }
        }
    }

    Ok(summary)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_thread_register_restore_for_tracee(
    threads: &[KboxlikeThreadSnapshot],
    tracee_pid: i32,
    writer: &mut impl TraceeRegisterWriter,
) -> Result<TraceeRegisterRestoreSummary, FdError> {
    if tracee_pid <= 0 {
        return Err(FdError::TraceeInstallFailed("invalid tracee pid"));
    }

    let mut summary = TraceeRegisterRestoreSummary::default();
    let mut matching_regs = None;

    for thread in threads {
        if thread.host_pid == tracee_pid {
            if matching_regs.replace(thread.regs).is_some() {
                return Err(FdError::TraceeInstallFailed(
                    "duplicate tracee register snapshot",
                ));
            }
        } else {
            summary.other_tracee += 1;
        }
    }

    let Some(regs) = matching_regs else {
        return Err(FdError::TraceeInstallFailed(
            "missing tracee register snapshot",
        ));
    };
    let regs = sanitize_restored_user_regs(regs);

    writer.write_regs(&regs)?;
    summary.registers_restored = 1;
    Ok(summary)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn sanitize_restored_user_regs(mut regs: libc::user_regs_struct) -> libc::user_regs_struct {
    if is_linux_internal_restart_result(regs.rax) {
        regs.rax = (-(libc::EINTR as i64)) as u64;
    }
    regs
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn is_linux_internal_restart_result(rax: u64) -> bool {
    matches!(
        rax as i64,
        -512 // ERESTARTSYS
            | -513 // ERESTARTNOINTR
            | -514 // ERESTARTNOHAND
            | -516 // ERESTART_RESTARTBLOCK
    )
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_thread_kernel_state_restore_for_tracee(
    states: &[KboxlikeThreadKernelStateSnapshot],
    tracee_pid: i32,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<TraceeKernelStateRestoreSummary, FdError> {
    if tracee_pid <= 0 {
        return Err(FdError::TraceeInstallFailed("invalid tracee pid"));
    }

    let mut summary = TraceeKernelStateRestoreSummary::default();
    let mut matching_state = None;

    for state in states {
        if state.host_pid == tracee_pid {
            if matching_state.replace(*state).is_some() {
                return Err(FdError::TraceeInstallFailed(
                    "duplicate tracee kernel state snapshot",
                ));
            }
        } else {
            summary.other_tracee += 1;
        }
    }

    let Some(state) = matching_state else {
        return Err(FdError::TraceeInstallFailed(
            "missing tracee kernel state snapshot",
        ));
    };

    if let Some(clear_child_tid) = state.clear_child_tid {
        let ret = executor.syscall(TraceeSyscall::new3(
            LINUX_X86_64_SYS_SET_TID_ADDRESS,
            clear_child_tid,
            0,
            0,
        ))?;
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee set_tid_address failed",
            ));
        }
        summary.clear_child_tid_applied = 1;
    }

    if let Some(robust_list_head) = state.robust_list_head {
        let ret = executor.syscall(TraceeSyscall::new3(
            LINUX_X86_64_SYS_SET_ROBUST_LIST,
            robust_list_head,
            state.robust_list_len,
            0,
        ))?;
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee set_robust_list failed",
            ));
        }
        summary.robust_list_applied = 1;
    }

    Ok(summary)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_stopped_tracee_restore(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    tracee_pid: i32,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
    register_writer: &mut impl TraceeRegisterWriter,
) -> Result<TraceeRestoreSummary, FdError> {
    let shared = TraceeSharedObjectRegistry::new();
    apply_stopped_tracee_restore_with_shared_objects(
        restore,
        threads,
        tracee_pid,
        0,
        &shared,
        writer,
        executor,
        register_writer,
    )
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_stopped_tracee_restore_with_shared_objects(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    tracee_pid: i32,
    supervisor_pid: i32,
    shared_objects: &TraceeSharedObjectRegistry,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
    register_writer: &mut impl TraceeRegisterWriter,
) -> Result<TraceeRestoreSummary, FdError> {
    let memory = apply_materialized_memory_restore_for_tracee_with_shared_objects(
        restore,
        tracee_pid,
        supervisor_pid,
        shared_objects,
        writer,
        executor,
    )?;
    let registers = apply_thread_register_restore_for_tracee(threads, tracee_pid, register_writer)?;

    Ok(TraceeRestoreSummary { memory, registers })
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_stopped_tracee_restore_set(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    shared_dumps: &[KboxlikeSharedMemoryDump],
    supervisor_pid: i32,
    access_factory: &mut impl TraceeRestoreAccessFactory,
) -> Result<TraceeRestoreSetSummary, FdError> {
    let normalized = normalize_thread_group_memory_restore(restore, threads, shared_dumps)?;
    let tracee_pids = validated_restore_tracee_pids(&normalized.restore, threads)?;

    apply_stopped_tracee_restore_set_for_pids(
        &normalized.restore,
        threads,
        &normalized.shared_dumps,
        supervisor_pid,
        tracee_pids,
        access_factory,
    )
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_and_resume_stopped_tracee_restore_set(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    shared_dumps: &[KboxlikeSharedMemoryDump],
    supervisor_pid: i32,
    access_factory: &mut impl TraceeRestoreAccessFactory,
    resumer: &mut impl RestoredTraceeResumer,
) -> Result<TraceeRestoreAndResumeSetSummary, FdError> {
    let normalized = normalize_thread_group_memory_restore(restore, threads, shared_dumps)?;
    let tracee_pids = validated_restore_tracee_pids(&normalized.restore, threads)?;
    let restore_summary = apply_stopped_tracee_restore_set_for_pids(
        &normalized.restore,
        threads,
        &normalized.shared_dumps,
        supervisor_pid,
        tracee_pids.clone(),
        access_factory,
    )?;

    let mut resume_summary = TraceeResumeSetSummary::default();
    for tracee_pid in tracee_pids {
        resumer.resume_restored_tracee(tracee_pid)?;
        resume_summary.tracees_resumed += 1;
    }

    Ok(TraceeRestoreAndResumeSetSummary {
        restore: restore_summary,
        resume: resume_summary,
    })
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_and_resume_stopped_tracee_restore_set_with_replacement_pids(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    shared_dumps: &[KboxlikeSharedMemoryDump],
    replacement_host_pids: &BTreeMap<ModelThreadId, i32>,
    supervisor_pid: i32,
    access_factory: &mut impl TraceeRestoreAccessFactory,
    resumer: &mut impl RestoredTraceeResumer,
) -> Result<TraceeRestoreAndResumeSetSummary, FdError> {
    let remapped = remap_stopped_tracee_restore_set_to_replacement_pids(
        restore,
        threads,
        shared_dumps,
        replacement_host_pids,
    )?;
    apply_and_resume_stopped_tracee_restore_set(
        &remapped.restore,
        &remapped.threads,
        &remapped.shared_dumps,
        supervisor_pid,
        access_factory,
        resumer,
    )
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_stopped_tracee_full_restore_set(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    kernel_states: &[KboxlikeThreadKernelStateSnapshot],
    shared_dumps: &[KboxlikeSharedMemoryDump],
    supervisor_pid: i32,
    access_factory: &mut impl TraceeRestoreAccessFactory,
) -> Result<TraceeFullRestoreSetSummary, FdError> {
    let normalized = normalize_thread_group_memory_restore(restore, threads, shared_dumps)?;
    let tracee_pids = validated_restore_tracee_pids(&normalized.restore, threads)?;

    apply_stopped_tracee_full_restore_set_for_pids(
        &normalized.restore,
        threads,
        kernel_states,
        &normalized.shared_dumps,
        supervisor_pid,
        tracee_pids,
        access_factory,
    )
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_stopped_tracee_full_restore_set_with_replacement_pids(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    kernel_states: &[KboxlikeThreadKernelStateSnapshot],
    shared_dumps: &[KboxlikeSharedMemoryDump],
    replacement_host_pids: &BTreeMap<ModelThreadId, i32>,
    supervisor_pid: i32,
    access_factory: &mut impl TraceeRestoreAccessFactory,
) -> Result<TraceeFullRestoreSetSummary, FdError> {
    let remapped = remap_stopped_tracee_restore_set_to_replacement_pids(
        restore,
        threads,
        shared_dumps,
        replacement_host_pids,
    )?;
    let remapped_kernel_states =
        remap_thread_kernel_states_to_replacement_pids(kernel_states, replacement_host_pids)?;
    let tracee_pids = validated_restore_tracee_pids(&remapped.restore, &remapped.threads)?;
    apply_stopped_tracee_full_restore_set_for_pids(
        &remapped.restore,
        &remapped.threads,
        &remapped_kernel_states,
        &remapped.shared_dumps,
        supervisor_pid,
        tracee_pids,
        access_factory,
    )
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_tracee_credentials_restore_with_replacement_pids(
    threads: &[KboxlikeThreadSnapshot],
    replacement_host_pids: &BTreeMap<ModelThreadId, i32>,
    access_factory: &mut impl TraceeRestoreAccessFactory,
) -> Result<(), FdError> {
    let credentials_by_replacement =
        source_credentials_by_replacement_pid(threads, replacement_host_pids)?;
    for replacement_pid in credentials_by_replacement.keys().copied() {
        let mut access = access_factory.access_for_restore(replacement_pid)?;
        apply_tracee_credentials_restore_for_tracee(
            &credentials_by_replacement,
            replacement_pid,
            &mut access.executor,
        )?;
    }
    Ok(())
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_and_resume_stopped_tracee_full_restore_set(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    kernel_states: &[KboxlikeThreadKernelStateSnapshot],
    shared_dumps: &[KboxlikeSharedMemoryDump],
    supervisor_pid: i32,
    access_factory: &mut impl TraceeRestoreAccessFactory,
    resumer: &mut impl RestoredTraceeResumer,
) -> Result<TraceeFullRestoreAndResumeSetSummary, FdError> {
    let normalized = normalize_thread_group_memory_restore(restore, threads, shared_dumps)?;
    let tracee_pids = validated_restore_tracee_pids(&normalized.restore, threads)?;
    let restore_summary = apply_stopped_tracee_full_restore_set_for_pids(
        &normalized.restore,
        threads,
        kernel_states,
        &normalized.shared_dumps,
        supervisor_pid,
        tracee_pids.clone(),
        access_factory,
    )?;
    let resume = resume_restored_tracee_set(tracee_pids, resumer)?;

    Ok(TraceeFullRestoreAndResumeSetSummary {
        restore: restore_summary,
        resume,
    })
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_and_resume_stopped_tracee_full_restore_set_with_replacement_pids(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    kernel_states: &[KboxlikeThreadKernelStateSnapshot],
    shared_dumps: &[KboxlikeSharedMemoryDump],
    replacement_host_pids: &BTreeMap<ModelThreadId, i32>,
    supervisor_pid: i32,
    access_factory: &mut impl TraceeRestoreAccessFactory,
    resumer: &mut impl RestoredTraceeResumer,
) -> Result<TraceeFullRestoreAndResumeSetSummary, FdError> {
    let remapped = remap_stopped_tracee_restore_set_to_replacement_pids(
        restore,
        threads,
        shared_dumps,
        replacement_host_pids,
    )?;
    let remapped_kernel_states =
        remap_thread_kernel_states_to_replacement_pids(kernel_states, replacement_host_pids)?;
    apply_and_resume_stopped_tracee_full_restore_set(
        &remapped.restore,
        &remapped.threads,
        &remapped_kernel_states,
        &remapped.shared_dumps,
        supervisor_pid,
        access_factory,
        resumer,
    )
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn remap_stopped_tracee_restore_set_to_replacement_pids(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    shared_dumps: &[KboxlikeSharedMemoryDump],
    replacement_host_pids: &BTreeMap<ModelThreadId, i32>,
) -> Result<TraceeRemappedRestoreSet, FdError> {
    let mut used_replacement_host_pids = BTreeSet::new();
    for replacement_host_pid in replacement_host_pids.values().copied() {
        if replacement_host_pid <= 0 {
            return Err(FdError::TraceeInstallFailed(
                "invalid replacement tracee pid",
            ));
        }
        if !used_replacement_host_pids.insert(replacement_host_pid) {
            return Err(FdError::TraceeInstallFailed(
                "duplicate replacement tracee pid",
            ));
        }
    }

    let source_vdso_ranges = source_vdso_ranges_by_host_pid(restore);
    let trace_memory_restore =
        std::env::var_os("SUPERMACHINE_KBOXLIKE_TRACE_MEMORY_RESTORE").is_some();
    let mut captured_host_to_model_thread = BTreeMap::new();
    let mut seen_thread_model_ids = BTreeSet::new();
    let mut remapped_threads = Vec::with_capacity(threads.len());
    for thread in threads {
        if !seen_thread_model_ids.insert(thread.model_thread_id) {
            return Err(FdError::TraceeInstallFailed(
                "duplicate tracee model thread id",
            ));
        }
        if captured_host_to_model_thread
            .insert(thread.host_pid, thread.model_thread_id)
            .is_some()
        {
            return Err(FdError::TraceeInstallFailed(
                "duplicate captured tracee pid",
            ));
        }
        let replacement_host_pid =
            replacement_host_pid_for_thread(replacement_host_pids, thread.model_thread_id)?;
        let regs = remap_source_vdso_rip_to_replacement_vdso(
            thread,
            replacement_host_pid,
            &source_vdso_ranges,
            trace_memory_restore,
        )?;
        remapped_threads.push(KboxlikeThreadSnapshot {
            host_pid: replacement_host_pid,
            model_pid: thread.model_pid,
            model_thread_id: thread.model_thread_id,
            regs,
        });
    }

    let mut remapped_actions = Vec::with_capacity(restore.actions.len());
    for action in &restore.actions {
        let model_thread_id = captured_host_to_model_thread_id(
            &captured_host_to_model_thread,
            materialized_action_host_pid(action),
        )?;
        let replacement_host_pid =
            replacement_host_pid_for_thread(replacement_host_pids, model_thread_id)?;
        remapped_actions.push(remap_materialized_action_host_pid(
            action,
            replacement_host_pid,
        ));
    }

    let mut remapped_shared_dumps = Vec::with_capacity(shared_dumps.len());
    for dump in shared_dumps {
        let model_thread_id =
            captured_host_to_model_thread_id(&captured_host_to_model_thread, dump.host_pid)?;
        let replacement_host_pid =
            replacement_host_pid_for_thread(replacement_host_pids, model_thread_id)?;
        let mut remapped_dump = dump.clone();
        remapped_dump.host_pid = replacement_host_pid;
        remapped_shared_dumps.push(remapped_dump);
    }

    let summary = TraceeReplacementPidRemapSummary {
        threads_remapped: remapped_threads.len(),
        memory_actions_remapped: remapped_actions.len(),
        shared_dumps_remapped: remapped_shared_dumps.len(),
    };

    Ok(TraceeRemappedRestoreSet {
        restore: KboxlikeMaterializedMemoryRestore {
            actions: remapped_actions,
        },
        threads: remapped_threads,
        shared_dumps: remapped_shared_dumps,
        summary,
    })
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn source_vdso_ranges_by_host_pid(
    restore: &KboxlikeMaterializedMemoryRestore,
) -> BTreeMap<i32, (u64, u64)> {
    let mut ranges = BTreeMap::new();
    for action in &restore.actions {
        if let KboxlikeMaterializedMemoryRestoreAction::SkipKernelSynthetic {
            host_pid,
            start,
            len,
            label,
            ..
        } = action
        {
            if label == "[vdso]" {
                ranges.insert(*host_pid, (*start, (*start).saturating_add(*len)));
            }
        }
    }
    ranges
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn remap_source_vdso_rip_to_replacement_vdso(
    thread: &KboxlikeThreadSnapshot,
    replacement_host_pid: i32,
    source_vdso_ranges: &BTreeMap<i32, (u64, u64)>,
    trace_memory_restore: bool,
) -> Result<libc::user_regs_struct, FdError> {
    let mut regs = thread.regs;
    let Some((source_start, source_end)) = source_vdso_ranges.get(&thread.host_pid).copied() else {
        return Ok(regs);
    };
    if regs.rip < source_start || regs.rip >= source_end {
        return Ok(regs);
    }
    let offset = regs.rip - source_start;
    let (replacement_start, replacement_end) = replacement_vdso_range(replacement_host_pid)?
        .ok_or(FdError::TraceeInstallFailed("replacement vdso missing"))?;
    if replacement_start.saturating_add(offset) >= replacement_end {
        return Err(FdError::TraceeInstallFailed(
            "replacement vdso shorter than source rip offset",
        ));
    }
    let old_rip = regs.rip;
    regs.rip = replacement_start + offset;
    if trace_memory_restore {
        eprintln!(
            "KBOXLIVE_VDSO_RIP_REMAP captured_pid={} replacement_pid={} old_rip=0x{:x} new_rip=0x{:x} offset=0x{:x}",
            thread.host_pid, replacement_host_pid, old_rip, regs.rip, offset,
        );
    }
    Ok(regs)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn replacement_vdso_range(host_pid: i32) -> Result<Option<(u64, u64)>, FdError> {
    Ok(read_proc_maps_for_pid(host_pid)?
        .into_iter()
        .find(|entry| entry.path.as_deref() == Some("[vdso]"))
        .map(|entry| (entry.start, entry.end)))
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn remap_thread_kernel_states_to_replacement_pids(
    states: &[KboxlikeThreadKernelStateSnapshot],
    replacement_host_pids: &BTreeMap<ModelThreadId, i32>,
) -> Result<Vec<KboxlikeThreadKernelStateSnapshot>, FdError> {
    let mut seen_model_thread_ids = BTreeSet::new();
    let mut remapped = Vec::with_capacity(states.len());

    for state in states {
        if !seen_model_thread_ids.insert(state.model_thread_id) {
            return Err(FdError::TraceeInstallFailed(
                "duplicate kernel state model thread id",
            ));
        }
        let replacement_host_pid =
            replacement_host_pid_for_thread(replacement_host_pids, state.model_thread_id)?;
        remapped.push(KboxlikeThreadKernelStateSnapshot {
            host_pid: replacement_host_pid,
            model_pid: state.model_pid,
            model_thread_id: state.model_thread_id,
            clear_child_tid: state.clear_child_tid,
            robust_list_head: state.robust_list_head,
            robust_list_len: state.robust_list_len,
        });
    }

    Ok(remapped)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn create_stopped_replacement_tracee_set(
    threads: &[KboxlikeThreadSnapshot],
    replacement_factory: &mut impl StoppedTraceeReplacementFactory,
) -> Result<TraceeReplacementThreadGroupCreateSet, FdError> {
    if threads.is_empty() {
        return Err(FdError::TraceeInstallFailed("no tracee register snapshots"));
    }

    let mut groups: BTreeMap<ProcessId, Vec<KboxlikeThreadSnapshot>> = BTreeMap::new();
    let mut seen_model_thread_ids = BTreeSet::new();
    for thread in threads {
        if thread.host_pid <= 0 {
            return Err(FdError::TraceeInstallFailed(
                "invalid tracee register snapshot pid",
            ));
        }
        if !seen_model_thread_ids.insert(thread.model_thread_id) {
            return Err(FdError::TraceeInstallFailed(
                "duplicate tracee model thread id",
            ));
        }
        groups
            .entry(thread.model_pid)
            .or_default()
            .push(thread.clone());
    }

    let mut replacement_host_pids = BTreeMap::new();
    let mut used_replacement_host_pids = BTreeSet::new();
    for (model_pid, group_threads) in groups.iter_mut() {
        group_threads.sort_by_key(|thread| thread.model_thread_id);
        let created = replacement_factory
            .create_stopped_replacement_group(*model_pid, group_threads.as_slice())?;
        validate_created_replacement_group(
            group_threads,
            &created,
            &mut used_replacement_host_pids,
            &mut replacement_host_pids,
        )?;
    }

    Ok(TraceeReplacementThreadGroupCreateSet {
        replacement_host_pids,
        summary: TraceeReplacementThreadGroupCreateSummary {
            process_groups: groups.len(),
            tracees_requested: threads.len(),
            tracees_created: threads.len(),
        },
    })
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn normalize_thread_group_memory_restore(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    shared_dumps: &[KboxlikeSharedMemoryDump],
) -> Result<TraceeThreadGroupMemoryNormalizedRestoreSet, FdError> {
    if threads.is_empty() {
        return Err(FdError::TraceeInstallFailed("no tracee register snapshots"));
    }

    let mut thread_by_host = BTreeMap::new();
    let mut seen_model_thread_ids = BTreeSet::new();
    let mut memory_owner_by_model = BTreeMap::new();

    for thread in threads {
        if thread.host_pid <= 0 {
            return Err(FdError::TraceeInstallFailed(
                "invalid tracee register snapshot pid",
            ));
        }
        if !seen_model_thread_ids.insert(thread.model_thread_id) {
            return Err(FdError::TraceeInstallFailed(
                "duplicate tracee model thread id",
            ));
        }
        if thread_by_host.insert(thread.host_pid, thread).is_some() {
            return Err(FdError::TraceeInstallFailed(
                "duplicate tracee register snapshot",
            ));
        }

        memory_owner_by_model
            .entry(thread.model_pid)
            .and_modify(|owner: &mut (ModelThreadId, i32)| {
                if thread.model_thread_id < owner.0 {
                    *owner = (thread.model_thread_id, thread.host_pid);
                }
            })
            .or_insert((thread.model_thread_id, thread.host_pid));
    }

    let mut summary = TraceeThreadGroupMemoryNormalizeSummary {
        process_groups: memory_owner_by_model.len(),
        ..TraceeThreadGroupMemoryNormalizeSummary::default()
    };

    let mut seen_actions = BTreeSet::new();
    let mut normalized_actions = Vec::with_capacity(restore.actions.len());
    for action in &restore.actions {
        let captured_host_pid = materialized_action_host_pid(action);
        let captured_thread =
            thread_by_host
                .get(&captured_host_pid)
                .ok_or(FdError::TraceeInstallFailed(
                    "memory restore action without tracee register snapshot",
                ))?;
        let action_model_pid = materialized_action_model_pid(action);
        if action_model_pid != captured_thread.model_pid {
            return Err(FdError::TraceeInstallFailed(
                "memory restore action model pid mismatch",
            ));
        }

        let owner_host_pid = memory_owner_host_pid(&memory_owner_by_model, action_model_pid)?;
        let normalized_action = remap_materialized_action_host_pid(action, owner_host_pid);
        if captured_host_pid != owner_host_pid {
            summary.memory_actions_reassigned_to_owner += 1;
        }
        if seen_actions.insert(normalized_action.clone()) {
            normalized_actions.push(normalized_action);
            summary.memory_actions_retained += 1;
        } else {
            summary.duplicate_memory_actions_removed += 1;
        }
    }

    let mut seen_shared_dumps = BTreeSet::new();
    let mut normalized_shared_dumps = Vec::with_capacity(shared_dumps.len());
    for dump in shared_dumps {
        let captured_thread =
            thread_by_host
                .get(&dump.host_pid)
                .ok_or(FdError::TraceeInstallFailed(
                    "shared memory dump without tracee register snapshot",
                ))?;
        if dump.model_pid != captured_thread.model_pid {
            return Err(FdError::TraceeInstallFailed(
                "shared memory dump model pid mismatch",
            ));
        }

        let owner_host_pid = memory_owner_host_pid(&memory_owner_by_model, dump.model_pid)?;
        let mut normalized_dump = dump.clone();
        normalized_dump.host_pid = owner_host_pid;
        if dump.host_pid != owner_host_pid {
            summary.shared_dumps_reassigned_to_owner += 1;
        }
        if seen_shared_dumps.insert(normalized_dump.clone()) {
            normalized_shared_dumps.push(normalized_dump);
            summary.shared_dumps_retained += 1;
        } else {
            summary.duplicate_shared_dumps_removed += 1;
        }
    }

    Ok(TraceeThreadGroupMemoryNormalizedRestoreSet {
        restore: KboxlikeMaterializedMemoryRestore {
            actions: normalized_actions,
        },
        shared_dumps: normalized_shared_dumps,
        memory_owner_host_pids: memory_owner_by_model
            .into_iter()
            .map(|(model_pid, (_model_thread_id, host_pid))| (model_pid, host_pid))
            .collect(),
        summary,
    })
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn validate_created_replacement_group(
    threads: &[KboxlikeThreadSnapshot],
    created: &BTreeMap<ModelThreadId, i32>,
    used_replacement_host_pids: &mut BTreeSet<i32>,
    replacement_host_pids: &mut BTreeMap<ModelThreadId, i32>,
) -> Result<(), FdError> {
    for model_thread_id in created.keys().copied() {
        if !threads
            .iter()
            .any(|thread| thread.model_thread_id == model_thread_id)
        {
            return Err(FdError::TraceeInstallFailed(
                "replacement group returned unknown model thread id",
            ));
        }
    }

    for thread in threads {
        let replacement_host_pid =
            created
                .get(&thread.model_thread_id)
                .copied()
                .ok_or(FdError::TraceeInstallFailed(
                    "replacement group missing model thread id",
                ))?;
        if replacement_host_pid <= 0 {
            return Err(FdError::TraceeInstallFailed(
                "invalid replacement tracee pid",
            ));
        }
        if !used_replacement_host_pids.insert(replacement_host_pid) {
            return Err(FdError::TraceeInstallFailed(
                "duplicate replacement tracee pid",
            ));
        }
        replacement_host_pids.insert(thread.model_thread_id, replacement_host_pid);
    }

    Ok(())
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn validated_restore_tracee_pids(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
) -> Result<BTreeSet<i32>, FdError> {
    if threads.is_empty() {
        return Err(FdError::TraceeInstallFailed("no tracee register snapshots"));
    }

    let mut tracee_pids = BTreeSet::new();
    for thread in threads {
        if thread.host_pid <= 0 {
            return Err(FdError::TraceeInstallFailed(
                "invalid tracee register snapshot pid",
            ));
        }
        tracee_pids.insert(thread.host_pid);
    }

    for action in &restore.actions {
        if !tracee_pids.contains(&materialized_action_host_pid(action)) {
            return Err(FdError::TraceeInstallFailed(
                "memory restore action without tracee register snapshot",
            ));
        }
    }

    Ok(tracee_pids)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn resume_restored_tracee_set(
    tracee_pids: BTreeSet<i32>,
    resumer: &mut impl RestoredTraceeResumer,
) -> Result<TraceeResumeSetSummary, FdError> {
    let mut summary = TraceeResumeSetSummary::default();
    for tracee_pid in tracee_pids {
        resumer.resume_restored_tracee(tracee_pid)?;
        summary.tracees_resumed += 1;
    }
    Ok(summary)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn memory_owner_host_pid(
    memory_owner_by_model: &BTreeMap<ProcessId, (ModelThreadId, i32)>,
    model_pid: ProcessId,
) -> Result<i32, FdError> {
    memory_owner_by_model
        .get(&model_pid)
        .map(|(_model_thread_id, host_pid)| *host_pid)
        .ok_or(FdError::TraceeInstallFailed(
            "memory restore action without tracee register snapshot",
        ))
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn apply_stopped_tracee_restore_set_for_pids(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    shared_dumps: &[KboxlikeSharedMemoryDump],
    supervisor_pid: i32,
    tracee_pids: BTreeSet<i32>,
    access_factory: &mut impl TraceeRestoreAccessFactory,
) -> Result<TraceeRestoreSetSummary, FdError> {
    let owned_shared_objects = build_owned_shared_object_registry(restore, shared_dumps)?;
    let mut summary = TraceeRestoreSetSummary {
        shared_objects: owned_shared_objects.summary(),
        ..TraceeRestoreSetSummary::default()
    };

    for tracee_pid in tracee_pids {
        let mut access = access_factory.access_for_restore(tracee_pid)?;
        let tracee_summary = apply_stopped_tracee_restore_with_shared_objects(
            restore,
            threads,
            tracee_pid,
            supervisor_pid,
            owned_shared_objects.registry(),
            &mut access.writer,
            &mut access.executor,
            &mut access.register_writer,
        )?;
        summary.tracees_restored += 1;
        summary.memory.add_assign(tracee_summary.memory);
        summary.registers.add_assign(tracee_summary.registers);
    }

    Ok(summary)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn apply_stopped_tracee_full_restore_set_for_pids(
    restore: &KboxlikeMaterializedMemoryRestore,
    threads: &[KboxlikeThreadSnapshot],
    kernel_states: &[KboxlikeThreadKernelStateSnapshot],
    shared_dumps: &[KboxlikeSharedMemoryDump],
    supervisor_pid: i32,
    tracee_pids: BTreeSet<i32>,
    access_factory: &mut impl TraceeRestoreAccessFactory,
) -> Result<TraceeFullRestoreSetSummary, FdError> {
    let owned_shared_objects = build_owned_shared_object_registry(restore, shared_dumps)?;
    let mut summary = TraceeFullRestoreSetSummary {
        shared_objects: owned_shared_objects.summary(),
        ..TraceeFullRestoreSetSummary::default()
    };

    for tracee_pid in tracee_pids {
        let mut access = access_factory.access_for_restore(tracee_pid)?;
        let memory = apply_materialized_memory_restore_for_tracee_with_shared_objects(
            restore,
            tracee_pid,
            supervisor_pid,
            owned_shared_objects.registry(),
            &mut access.writer,
            &mut access.executor,
        )?;
        let kernel_state = apply_thread_kernel_state_restore_for_tracee(
            kernel_states,
            tracee_pid,
            &mut access.executor,
        )?;
        let registers = apply_thread_register_restore_for_tracee(
            threads,
            tracee_pid,
            &mut access.register_writer,
        )?;
        summary.tracees_restored += 1;
        summary.memory.add_assign(memory);
        summary.kernel_state.add_assign(kernel_state);
        summary.registers.add_assign(registers);
    }

    Ok(summary)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn source_credentials_by_replacement_pid(
    threads: &[KboxlikeThreadSnapshot],
    replacement_host_pids: &BTreeMap<ModelThreadId, i32>,
) -> Result<BTreeMap<i32, (u32, u32)>, FdError> {
    let mut credentials = BTreeMap::new();
    for thread in threads {
        let Some(replacement_pid) = replacement_host_pids.get(&thread.model_thread_id).copied()
        else {
            continue;
        };
        let (uid, gid) = read_proc_status_uid_gid(thread.host_pid)?;
        if uid == 0 && gid == 0 {
            continue;
        }
        credentials.insert(replacement_pid, (uid, gid));
    }
    Ok(credentials)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn read_proc_status_uid_gid(host_pid: i32) -> Result<(u32, u32), FdError> {
    let status = std::fs::read_to_string(format!("/proc/{host_pid}/status"))
        .map_err(|_| FdError::TraceeInstallFailed("read proc status credentials failed"))?;
    let mut uid = None;
    let mut gid = None;
    for line in status.lines() {
        if let Some(rest) = line.strip_prefix("Uid:") {
            uid = rest
                .split_whitespace()
                .next()
                .and_then(|raw| raw.parse::<u32>().ok());
        } else if let Some(rest) = line.strip_prefix("Gid:") {
            gid = rest
                .split_whitespace()
                .next()
                .and_then(|raw| raw.parse::<u32>().ok());
        }
    }
    match (uid, gid) {
        (Some(uid), Some(gid)) => Ok((uid, gid)),
        _ => Err(FdError::TraceeInstallFailed(
            "proc status credentials missing uid/gid",
        )),
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn apply_tracee_credentials_restore_for_tracee(
    credentials_by_pid: &BTreeMap<i32, (u32, u32)>,
    tracee_pid: i32,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<(), FdError> {
    let Some((uid, gid)) = credentials_by_pid.get(&tracee_pid).copied() else {
        return Ok(());
    };
    let setgroups = executor.syscall(TraceeSyscall::new3(LINUX_X86_64_SYS_SETGROUPS, 0, 0, 0))?;
    if setgroups < 0 {
        return Err(FdError::TraceeInstallFailed(
            "restore credentials setgroups failed",
        ));
    }
    let setresgid = executor.syscall(TraceeSyscall::new3(
        LINUX_X86_64_SYS_SETRESGID,
        gid as u64,
        gid as u64,
        gid as u64,
    ))?;
    if setresgid < 0 {
        return Err(FdError::TraceeInstallFailed(
            "restore credentials setresgid failed",
        ));
    }
    let setresuid = executor.syscall(TraceeSyscall::new3(
        LINUX_X86_64_SYS_SETRESUID,
        uid as u64,
        uid as u64,
        uid as u64,
    ))?;
    if setresuid < 0 {
        return Err(FdError::TraceeInstallFailed(
            "restore credentials setresuid failed",
        ));
    }
    Ok(())
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn materialized_action_host_pid(action: &KboxlikeMaterializedMemoryRestoreAction) -> i32 {
    match action {
        KboxlikeMaterializedMemoryRestoreAction::ByteBacked { host_pid, .. }
        | KboxlikeMaterializedMemoryRestoreAction::RemapCleanFile { host_pid, .. }
        | KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject { host_pid, .. }
        | KboxlikeMaterializedMemoryRestoreAction::SkipKernelSynthetic { host_pid, .. }
        | KboxlikeMaterializedMemoryRestoreAction::SkipInaccessible { host_pid, .. } => *host_pid,
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn materialized_action_model_pid(action: &KboxlikeMaterializedMemoryRestoreAction) -> ProcessId {
    match action {
        KboxlikeMaterializedMemoryRestoreAction::ByteBacked { model_pid, .. }
        | KboxlikeMaterializedMemoryRestoreAction::RemapCleanFile { model_pid, .. }
        | KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject { model_pid, .. }
        | KboxlikeMaterializedMemoryRestoreAction::SkipKernelSynthetic { model_pid, .. }
        | KboxlikeMaterializedMemoryRestoreAction::SkipInaccessible { model_pid, .. } => *model_pid,
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn replacement_host_pid_for_thread(
    replacement_host_pids: &BTreeMap<ModelThreadId, i32>,
    model_thread_id: ModelThreadId,
) -> Result<i32, FdError> {
    replacement_host_pids
        .get(&model_thread_id)
        .copied()
        .ok_or(FdError::TraceeInstallFailed(
            "missing replacement tracee pid",
        ))
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn captured_host_to_model_thread_id(
    captured_host_to_model_thread: &BTreeMap<i32, ModelThreadId>,
    captured_host_pid: i32,
) -> Result<ModelThreadId, FdError> {
    captured_host_to_model_thread
        .get(&captured_host_pid)
        .copied()
        .ok_or(FdError::TraceeInstallFailed(
            "restore action without captured tracee thread",
        ))
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn remap_materialized_action_host_pid(
    action: &KboxlikeMaterializedMemoryRestoreAction,
    replacement_host_pid: i32,
) -> KboxlikeMaterializedMemoryRestoreAction {
    match action {
        KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
            model_pid,
            start,
            prot,
            bytes,
            source,
            ..
        } => KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
            host_pid: replacement_host_pid,
            model_pid: *model_pid,
            start: *start,
            prot: *prot,
            bytes: bytes.clone(),
            source: source.clone(),
        },
        KboxlikeMaterializedMemoryRestoreAction::RemapCleanFile {
            model_pid,
            start,
            len,
            prot,
            path,
            file_offset,
            dev,
            inode,
            ..
        } => KboxlikeMaterializedMemoryRestoreAction::RemapCleanFile {
            host_pid: replacement_host_pid,
            model_pid: *model_pid,
            start: *start,
            len: *len,
            prot: *prot,
            path: path.clone(),
            file_offset: *file_offset,
            dev: dev.clone(),
            inode: *inode,
        },
        KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
            model_pid,
            start,
            len,
            prot,
            kind,
            path,
            file_offset,
            dev,
            inode,
            ..
        } => KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
            host_pid: replacement_host_pid,
            model_pid: *model_pid,
            start: *start,
            len: *len,
            prot: *prot,
            kind: *kind,
            path: path.clone(),
            file_offset: *file_offset,
            dev: dev.clone(),
            inode: *inode,
        },
        KboxlikeMaterializedMemoryRestoreAction::SkipKernelSynthetic {
            model_pid,
            start,
            len,
            label,
            ..
        } => KboxlikeMaterializedMemoryRestoreAction::SkipKernelSynthetic {
            host_pid: replacement_host_pid,
            model_pid: *model_pid,
            start: *start,
            len: *len,
            label: label.clone(),
        },
        KboxlikeMaterializedMemoryRestoreAction::SkipInaccessible {
            model_pid,
            start,
            len,
            prot,
            ..
        } => KboxlikeMaterializedMemoryRestoreAction::SkipInaccessible {
            host_pid: replacement_host_pid,
            model_pid: *model_pid,
            start: *start,
            len: *len,
            prot: *prot,
        },
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct TraceeOperationInstallRequest {
    pub(crate) model_pid: ProcessId,
    pub(crate) tracee_pid: i32,
    pub(crate) fd: FdNumber,
    pub(crate) operation: FdOperation,
}

impl TraceeOperationInstallRequest {
    pub(crate) fn new(
        model_pid: ProcessId,
        tracee_pid: i32,
        fd: FdNumber,
        operation: FdOperation,
    ) -> Result<Self, FdError> {
        if tracee_pid <= 0 {
            return Err(FdError::TraceeInstallFailed("invalid tracee pid"));
        }
        Ok(Self {
            model_pid,
            tracee_pid,
            fd,
            operation,
        })
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct TraceeScratchMapping {
    pub(crate) addr: u64,
    pub(crate) len: usize,
}

impl TraceeScratchMapping {
    pub(crate) fn map(
        len: usize,
        executor: &mut impl TraceeSyscallExecutor,
    ) -> Result<Self, FdError> {
        if len == 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee scratch length is zero",
            ));
        }

        let addr = executor.syscall(Self::mmap_syscall(len))?;
        if addr < 0 {
            return Err(FdError::TraceeInstallFailed("tracee mmap failed"));
        }
        if addr == 0 {
            return Err(FdError::TraceeInstallFailed("tracee mmap returned null"));
        }

        Ok(Self {
            addr: addr as u64,
            len,
        })
    }

    pub(crate) fn unmap(self, executor: &mut impl TraceeSyscallExecutor) -> Result<(), FdError> {
        let ret = executor.syscall(self.munmap_syscall())?;
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed("tracee munmap failed"));
        }
        Ok(())
    }

    pub(crate) fn mmap_syscall(len: usize) -> TraceeSyscall {
        TraceeSyscall::new6(
            LINUX_X86_64_SYS_MMAP,
            [
                0,
                len as u64,
                LINUX_PROT_READ | LINUX_PROT_WRITE,
                LINUX_MAP_PRIVATE | LINUX_MAP_ANONYMOUS,
                (-1i64) as u64,
                0,
            ],
        )
    }

    pub(crate) fn munmap_syscall(&self) -> TraceeSyscall {
        TraceeSyscall::new6(
            LINUX_X86_64_SYS_MUNMAP,
            [self.addr, self.len as u64, 0, 0, 0, 0],
        )
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct ProcessVmMemoryWriter {
    pid: i32,
}

impl ProcessVmMemoryWriter {
    pub(crate) fn new(pid: i32) -> Result<Self, FdError> {
        if pid <= 0 {
            return Err(FdError::TraceeInstallFailed("invalid tracee pid"));
        }
        Ok(Self { pid })
    }

    pub(crate) fn pid(&self) -> i32 {
        self.pid
    }
}

#[cfg(target_os = "linux")]
impl TraceeMemoryWriter for ProcessVmMemoryWriter {
    fn write_bytes(&mut self, addr: u64, bytes: &[u8]) -> Result<(), FdError> {
        if addr == 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee memory address is null",
            ));
        }
        if bytes.is_empty() {
            return Ok(());
        }

        let local = libc::iovec {
            iov_base: bytes.as_ptr() as *mut libc::c_void,
            iov_len: bytes.len(),
        };
        let remote = libc::iovec {
            iov_base: addr as *mut libc::c_void,
            iov_len: bytes.len(),
        };
        let written = unsafe { libc::process_vm_writev(self.pid, &local, 1, &remote, 1, 0) };
        if written < 0 {
            return Err(FdError::TraceeInstallFailed("process_vm_writev failed"));
        }
        if written as usize != bytes.len() {
            return Err(FdError::TraceeInstallFailed(
                "process_vm_writev partial write",
            ));
        }
        Ok(())
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct PtraceSyscallExecutor {
    pid: i32,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl PtraceSyscallExecutor {
    pub(crate) fn new(pid: i32) -> Result<Self, FdError> {
        if pid <= 0 {
            return Err(FdError::TraceeInstallFailed("invalid tracee pid"));
        }
        Ok(Self { pid })
    }

    pub(crate) fn pid(&self) -> i32 {
        self.pid
    }

    fn getregs(&self) -> Result<libc::user_regs_struct, FdError> {
        let mut regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let ret = unsafe {
            libc::ptrace(
                libc::PTRACE_GETREGS,
                self.pid,
                std::ptr::null_mut::<c_void>(),
                &mut regs as *mut _ as *mut c_void,
            )
        };
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed("ptrace getregs failed"));
        }
        Ok(regs)
    }

    fn setregs(&self, regs: &libc::user_regs_struct) -> Result<(), FdError> {
        let ret = unsafe {
            libc::ptrace(
                libc::PTRACE_SETREGS,
                self.pid,
                std::ptr::null_mut::<c_void>(),
                regs as *const _ as *mut c_void,
            )
        };
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed("ptrace setregs failed"));
        }
        Ok(())
    }

    fn peek_word(&self, addr: u64) -> Result<u64, FdError> {
        unsafe {
            *libc::__errno_location() = 0;
        }
        let word = unsafe {
            libc::ptrace(
                libc::PTRACE_PEEKTEXT,
                self.pid,
                addr as *mut c_void,
                std::ptr::null_mut::<c_void>(),
            )
        };
        let errno = unsafe { *libc::__errno_location() };
        if word == -1 && errno != 0 {
            return Err(FdError::TraceeInstallFailed("ptrace peektext failed"));
        }
        Ok(word as u64)
    }

    fn poke_word(&self, addr: u64, word: u64) -> Result<(), FdError> {
        let ret = unsafe {
            libc::ptrace(
                libc::PTRACE_POKETEXT,
                self.pid,
                addr as *mut c_void,
                word as usize as *mut c_void,
            )
        };
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed("ptrace poketext failed"));
        }
        Ok(())
    }

    fn continue_tracee(&self) -> Result<(), FdError> {
        let ret = unsafe {
            libc::ptrace(
                libc::PTRACE_CONT,
                self.pid,
                std::ptr::null_mut::<c_void>(),
                std::ptr::null_mut::<c_void>(),
            )
        };
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed("ptrace cont failed"));
        }
        Ok(())
    }

    fn resume_to_syscall_stop(&self) -> Result<(), FdError> {
        let ret = unsafe {
            libc::ptrace(
                libc::PTRACE_SYSCALL,
                self.pid,
                std::ptr::null_mut::<c_void>(),
                std::ptr::null_mut::<c_void>(),
            )
        };
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed("ptrace syscall resume failed"));
        }
        Ok(())
    }

    fn wait_for_ptrace_syscall_stop(&self) -> Result<(), FdError> {
        let mut status = 0;
        loop {
            let waited = unsafe { libc::waitpid(self.pid, &mut status, 0) };
            if waited < 0 {
                return Err(FdError::TraceeInstallFailed("waitpid failed"));
            }
            if waited == self.pid && libc::WIFSTOPPED(status) {
                let signal = libc::WSTOPSIG(status);
                if signal == (libc::SIGTRAP | 0x80) || signal == libc::SIGTRAP {
                    return Ok(());
                }
                if signal == libc::SIGURG {
                    self.resume_to_syscall_stop()?;
                    continue;
                }
                let reason = match signal {
                    libc::SIGSEGV => "tracee stopped with SIGSEGV during remote syscall",
                    libc::SIGBUS => "tracee stopped with SIGBUS during remote syscall",
                    libc::SIGILL => "tracee stopped with SIGILL during remote syscall",
                    libc::SIGABRT => "tracee stopped with SIGABRT during remote syscall",
                    libc::SIGSYS => "tracee stopped with SIGSYS during remote syscall",
                    _ => "tracee stopped with unexpected signal during remote syscall",
                };
                self.log_signal_info("ptrace-syscall", signal);
                return Err(FdError::TraceeInstallFailed(reason));
            }
            if waited == self.pid {
                return Err(FdError::TraceeInstallFailed(
                    "tracee exited during remote syscall",
                ));
            }
        }
    }

    fn wait_for_syscall_trap(&self) -> Result<(), FdError> {
        let mut status = 0;
        loop {
            let waited = unsafe { libc::waitpid(self.pid, &mut status, 0) };
            if waited < 0 {
                return Err(FdError::TraceeInstallFailed("waitpid failed"));
            }
            if waited == self.pid && libc::WIFSTOPPED(status) {
                let signal = libc::WSTOPSIG(status);
                if signal == libc::SIGTRAP {
                    return Ok(());
                }
                if signal == libc::SIGURG {
                    self.continue_tracee()?;
                    continue;
                }
                let reason = match signal {
                    libc::SIGSEGV => "tracee stopped with SIGSEGV during remote syscall",
                    libc::SIGBUS => "tracee stopped with SIGBUS during remote syscall",
                    libc::SIGILL => "tracee stopped with SIGILL during remote syscall",
                    libc::SIGABRT => "tracee stopped with SIGABRT during remote syscall",
                    libc::SIGSYS => "tracee stopped with SIGSYS during remote syscall",
                    _ => "tracee stopped with unexpected signal during remote syscall",
                };
                self.log_signal_info("int3-syscall", signal);
                return Err(FdError::TraceeInstallFailed(reason));
            }
            if waited == self.pid {
                return Err(FdError::TraceeInstallFailed(
                    "tracee exited during remote syscall",
                ));
            }
        }
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeSyscallExecutor for PtraceSyscallExecutor {
    fn syscall(&mut self, syscall: TraceeSyscall) -> Result<i64, FdError> {
        self.syscall_from_current_rip(syscall)
    }

    fn tracee_pid(&self) -> Option<i32> {
        Some(self.pid())
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl PtraceSyscallExecutor {
    fn syscall_from_current_rip(&self, syscall: TraceeSyscall) -> Result<i64, FdError> {
        let saved_regs = self.getregs()?;
        let rip = saved_regs.rip;
        let saved_word = self.peek_word(rip)?;
        let injected_word = (saved_word & !0x00ff_ffff) | 0x00cc_050f;

        self.poke_word(rip, injected_word)?;

        let mut syscall_regs = saved_regs;
        syscall_regs.rax = syscall.nr as u64;
        syscall_regs.rdi = syscall.args[0];
        syscall_regs.rsi = syscall.args[1];
        syscall_regs.rdx = syscall.args[2];
        syscall_regs.r10 = syscall.args[3];
        syscall_regs.r8 = syscall.args[4];
        syscall_regs.r9 = syscall.args[5];

        let syscall_result = (|| {
            self.setregs(&syscall_regs)?;
            self.continue_tracee()?;
            self.wait_for_syscall_trap()?;
            let result_regs = self.getregs()?;
            Ok(result_regs.rax as i64)
        })();

        let restore_word_result = self.poke_word(rip, saved_word);
        let restore_regs_result = self.setregs(&saved_regs);

        match (syscall_result, restore_word_result, restore_regs_result) {
            (Err(err), _, _) => Err(err),
            (Ok(_), Err(err), _) => Err(err),
            (Ok(_), Ok(()), Err(err)) => Err(err),
            (Ok(ret), Ok(()), Ok(())) => Ok(ret),
        }
    }

    fn syscall_from_addr(&self, syscall_addr: u64, syscall: TraceeSyscall) -> Result<i64, FdError> {
        self.syscall_from_addr_with_stack(syscall_addr, None, syscall)
    }

    fn syscall_from_addr_with_stack(
        &self,
        syscall_addr: u64,
        stack_top: Option<u64>,
        syscall: TraceeSyscall,
    ) -> Result<i64, FdError> {
        if syscall_addr == 0 {
            return Err(FdError::TraceeInstallFailed("syscall page address is null"));
        }

        let saved_regs = self.getregs()?;
        let mut syscall_regs = saved_regs;
        syscall_regs.rip = syscall_addr;
        syscall_regs.rax = syscall.nr as u64;
        syscall_regs.rdi = syscall.args[0];
        syscall_regs.rsi = syscall.args[1];
        syscall_regs.rdx = syscall.args[2];
        syscall_regs.r10 = syscall.args[3];
        syscall_regs.r8 = syscall.args[4];
        syscall_regs.r9 = syscall.args[5];
        if let Some(stack_top) = stack_top {
            syscall_regs.rsp = stack_top;
        }

        let syscall_result = (|| {
            self.setregs(&syscall_regs)?;
            self.continue_tracee()?;
            self.wait_for_syscall_trap()?;
            let result_regs = self.getregs()?;
            Ok(result_regs.rax as i64)
        })();

        let restore_regs_result = self.setregs(&saved_regs);
        match (syscall_result, restore_regs_result) {
            (Err(err), _) => Err(err),
            (Ok(_), Err(err)) => Err(err),
            (Ok(ret), Ok(())) => Ok(ret),
        }
    }

    fn syscall_from_addr_stopping_at_exit(
        &self,
        syscall_addr: u64,
        stack_top: Option<u64>,
        syscall: TraceeSyscall,
    ) -> Result<i64, FdError> {
        if syscall_addr == 0 {
            return Err(FdError::TraceeInstallFailed("syscall page address is null"));
        }

        let saved_regs = self.getregs()?;
        let mut syscall_regs = saved_regs;
        syscall_regs.rip = syscall_addr;
        syscall_regs.rax = syscall.nr as u64;
        syscall_regs.rdi = syscall.args[0];
        syscall_regs.rsi = syscall.args[1];
        syscall_regs.rdx = syscall.args[2];
        syscall_regs.r10 = syscall.args[3];
        syscall_regs.r8 = syscall.args[4];
        syscall_regs.r9 = syscall.args[5];
        if let Some(stack_top) = stack_top {
            syscall_regs.rsp = stack_top;
        }

        let syscall_result = (|| {
            self.setregs(&syscall_regs)?;
            self.resume_to_syscall_stop()?;
            self.wait_for_ptrace_syscall_stop()?;
            self.resume_to_syscall_stop()?;
            self.wait_for_ptrace_syscall_stop()?;
            let result_regs = self.getregs()?;
            Ok(result_regs.rax as i64)
        })();

        let restore_regs_result = self.setregs(&saved_regs);
        match (syscall_result, restore_regs_result) {
            (Err(err), _) => Err(err),
            (Ok(_), Err(err)) => Err(err),
            (Ok(ret), Ok(())) => Ok(ret),
        }
    }

    fn log_signal_info(&self, context: &str, signal: i32) {
        if std::env::var_os("SUPERMACHINE_KBOXLIKE_TRACE_REMOTE_SYSCALLS").is_none() {
            return;
        }
        let mut siginfo: libc::siginfo_t = unsafe { std::mem::zeroed() };
        let ret = unsafe {
            libc::ptrace(
                libc::PTRACE_GETSIGINFO,
                self.pid,
                std::ptr::null_mut::<c_void>(),
                &mut siginfo as *mut _ as *mut c_void,
            )
        };
        if ret < 0 {
            eprintln!(
                "KBOXLIVE_REMOTE_SIGNAL pid={} context={context} signal={} siginfo=unavailable",
                self.pid, signal,
            );
            return;
        }
        let addr = unsafe { siginfo.si_addr() as usize };
        eprintln!(
            "KBOXLIVE_REMOTE_SIGNAL pid={} context={context} signal={} signo={} code={} addr=0x{:x}",
            self.pid, signal, siginfo.si_signo, siginfo.si_code, addr,
        );
        log_remote_proc_maps(self.pid);
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn log_remote_proc_maps(pid: i32) {
    if let Ok(maps) = std::fs::read_to_string(format!("/proc/{pid}/maps")) {
        eprintln!("KBOXLIVE_REMOTE_MAPS_BEGIN pid={pid}");
        for line in maps.lines() {
            eprintln!("KBOXLIVE_REMOTE_MAP pid={pid} {line}");
        }
        eprintln!("KBOXLIVE_REMOTE_MAPS_END pid={pid}");
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct PtraceScratchSyscallExecutor {
    inner: PtraceSyscallExecutor,
    syscall_addr: u64,
    stack_top: u64,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl PtraceScratchSyscallExecutor {
    pub(crate) fn new(pid: i32, syscall_addr: u64) -> Result<Self, FdError> {
        if syscall_addr == 0 {
            return Err(FdError::TraceeInstallFailed("syscall page address is null"));
        }
        if syscall_addr % 4096 != 0 {
            return Err(FdError::TraceeInstallFailed(
                "syscall page address is not page aligned",
            ));
        }

        let inner = PtraceSyscallExecutor::new(pid)?;
        let mapped = inner.syscall_from_current_rip(TraceeSyscall::new6(
            LINUX_X86_64_SYS_MMAP,
            [
                syscall_addr,
                8192,
                LINUX_PROT_READ | LINUX_PROT_WRITE | LINUX_PROT_EXEC,
                LINUX_MAP_PRIVATE | LINUX_MAP_ANONYMOUS | LINUX_MAP_FIXED_NOREPLACE,
                (-1i64) as u64,
                0,
            ],
        ))?;
        if mapped < 0 && mapped != -(libc::EEXIST as i64) {
            return Err(FdError::TraceeInstallFailed(
                "tracee syscall scratch mmap failed",
            ));
        }
        if mapped == -(libc::EEXIST as i64)
            && !tracee_mapping_has_execute(inner.pid(), syscall_addr, 8192)
        {
            let protected = inner.syscall_from_current_rip(TraceeSyscall::new3(
                LINUX_X86_64_SYS_MPROTECT,
                syscall_addr,
                8192,
                LINUX_PROT_READ | LINUX_PROT_WRITE | LINUX_PROT_EXEC,
            ))?;
            if protected < 0 {
                return Err(FdError::TraceeInstallFailed(
                    "tracee syscall scratch mprotect failed",
                ));
            }
        }
        if mapped >= 0 && mapped as u64 != syscall_addr {
            return Err(FdError::TraceeInstallFailed(
                "tracee syscall scratch mmap returned wrong address",
            ));
        }

        inner.poke_word(syscall_addr, 0x00cc_050f)?;
        set_ptrace_tracesysgood(pid)?;
        Ok(Self {
            inner,
            syscall_addr,
            stack_top: syscall_addr + 8192 - 16,
        })
    }

    pub(crate) fn pid(&self) -> i32 {
        self.inner.pid()
    }

    pub(crate) fn unmap_existing_mappings_except_scratch(&mut self) -> Result<usize, FdError> {
        const HIGH_ASLR_REGION_START: u64 = 0x7000_0000_0000;
        let maps = std::fs::read_to_string(format!("/proc/{}/maps", self.inner.pid()))
            .map_err(|_| FdError::TraceeInstallFailed("failed to read tracee maps"))?;
        let scratch_start = self.syscall_addr;
        let scratch_len = 8192;
        let mut unmapped = 0usize;

        for line in maps.lines() {
            if line.contains("[vvar]") || line.contains("[vdso]") || line.contains("[vsyscall]") {
                continue;
            }
            let Some((start, end)) = parse_proc_maps_range(line) else {
                continue;
            };
            if start >= end || ranges_overlap_u64(start, end - start, scratch_start, scratch_len) {
                continue;
            }
            // On some nested/new-kernel hosts, remotely munmapping the high ASLR
            // region that contains the replacement's libc/loader/stack can raise
            // a kernel-generated SIGSEGV even when the syscall runs from the
            // scratch page with a scratch stack. Source restore mappings are
            // applied with MAP_FIXED later, so real collisions in this region are
            // still replaced without needing an eager sweep.
            if start >= HIGH_ASLR_REGION_START {
                continue;
            }

            let ret = self.syscall(TraceeSyscall::new3(
                LINUX_X86_64_SYS_MUNMAP,
                start,
                end - start,
                0,
            ))?;
            if ret < 0 {
                return Err(FdError::TraceeInstallFailed(
                    "tracee inherited mapping munmap failed",
                ));
            }
            unmapped += 1;
        }

        Ok(unmapped)
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeSyscallExecutor for PtraceScratchSyscallExecutor {
    fn syscall(&mut self, syscall: TraceeSyscall) -> Result<i64, FdError> {
        let result = self.inner.syscall_from_addr_with_stack(
            self.syscall_addr,
            Some(self.stack_top),
            syscall,
        );
        if let Some(trace_mode) = std::env::var_os("SUPERMACHINE_KBOXLIKE_TRACE_REMOTE_SYSCALLS") {
            let trace_all = trace_mode == "all";
            match &result {
                Ok(ret) if *ret < 0 => {
                    eprintln!(
                        "KBOXLIVE_REMOTE_SYSCALL_NEGATIVE pid={} scratch=0x{:x} nr={} args={:?} ret={ret}",
                        self.inner.pid(),
                        self.syscall_addr,
                        syscall.nr,
                        syscall.args,
                    );
                    log_remote_proc_maps(self.inner.pid());
                }
                Ok(ret) if trace_all => {
                    eprintln!(
                        "KBOXLIVE_REMOTE_SYSCALL pid={} scratch=0x{:x} nr={} args={:?} ret={ret}",
                        self.inner.pid(),
                        self.syscall_addr,
                        syscall.nr,
                        syscall.args,
                    );
                }
                Err(err) => {
                    eprintln!(
                        "KBOXLIVE_REMOTE_SYSCALL_FAILURE pid={} scratch=0x{:x} nr={} args={:?} err={err:?}",
                        self.inner.pid(),
                        self.syscall_addr,
                        syscall.nr,
                        syscall.args,
                    );
                }
                _ => {}
            }
        }
        result
    }

    fn tracee_pid(&self) -> Option<i32> {
        Some(self.pid())
    }

    fn kernel_synthetic_ranges(&self) -> Result<Vec<(u64, u64)>, FdError> {
        let maps = std::fs::read_to_string(format!("/proc/{}/maps", self.inner.pid()))
            .map_err(|_| FdError::TraceeInstallFailed("failed to read tracee maps"))?;
        let mut ranges = Vec::new();
        for line in maps.lines() {
            if !(line.contains("[vvar]")
                || line.contains("[vvar_vclock]")
                || line.contains("[vdso]")
                || line.contains("[vsyscall]"))
            {
                continue;
            }
            let Some((start, end)) = parse_proc_maps_range(line) else {
                continue;
            };
            ranges.push((start, end));
        }
        Ok(ranges)
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct PtraceRegisterWriter {
    pid: i32,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl PtraceRegisterWriter {
    pub(crate) fn new(pid: i32) -> Result<Self, FdError> {
        if pid <= 0 {
            return Err(FdError::TraceeInstallFailed("invalid tracee pid"));
        }
        Ok(Self { pid })
    }

    pub(crate) fn pid(&self) -> i32 {
        self.pid
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeRegisterWriter for PtraceRegisterWriter {
    fn write_regs(&mut self, regs: &libc::user_regs_struct) -> Result<(), FdError> {
        let ret = unsafe {
            libc::ptrace(
                libc::PTRACE_SETREGS,
                self.pid,
                std::ptr::null_mut::<c_void>(),
                regs as *const _ as *mut c_void,
            )
        };
        if ret < 0 {
            return Err(FdError::TraceeInstallFailed("ptrace setregs failed"));
        }
        Ok(())
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Debug, Default)]
pub(crate) struct LinuxTraceeRestoreAccessFactory;

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl TraceeRestoreAccessFactory for LinuxTraceeRestoreAccessFactory {
    type Writer = ProcessVmMemoryWriter;
    type Executor = PtraceSyscallExecutor;
    type RegisterWriter = PtraceRegisterWriter;

    fn access_for_restore(
        &mut self,
        host_pid: i32,
    ) -> Result<TraceeRestoreAccess<Self::Writer, Self::Executor, Self::RegisterWriter>, FdError>
    {
        Ok(TraceeRestoreAccess {
            writer: ProcessVmMemoryWriter::new(host_pid)?,
            executor: PtraceSyscallExecutor::new(host_pid)?,
            register_writer: PtraceRegisterWriter::new(host_pid)?,
        })
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Debug, Default)]
pub(crate) struct PtraceDetachRestoredTraceeResumer;

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl RestoredTraceeResumer for PtraceDetachRestoredTraceeResumer {
    fn resume_restored_tracee(&mut self, host_pid: i32) -> Result<(), FdError> {
        if host_pid <= 0 {
            return Err(FdError::TraceeInstallFailed("invalid tracee pid"));
        }

        let detach_ret = unsafe {
            libc::ptrace(
                libc::PTRACE_DETACH,
                host_pid,
                std::ptr::null_mut::<c_void>(),
                std::ptr::null_mut::<c_void>(),
            )
        };
        if detach_ret < 0 {
            return Err(FdError::TraceeInstallFailed("ptrace detach failed"));
        }
        Ok(())
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
#[derive(Debug, Default)]
pub(crate) struct LinuxStoppedTraceeReplacementFactory {
    created_host_pids: Vec<i32>,
    static_replacement_path: Option<PathBuf>,
    syscall_page: Option<u64>,
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl LinuxStoppedTraceeReplacementFactory {
    pub(crate) fn with_static_replacement_path(path: impl Into<PathBuf>) -> Self {
        Self {
            created_host_pids: Vec::new(),
            static_replacement_path: Some(path.into()),
            syscall_page: None,
        }
    }

    pub(crate) fn created_host_pids(&self) -> &[i32] {
        &self.created_host_pids
    }

    pub(crate) fn kill_created_tracees(&mut self) {
        let mut pending: BTreeSet<i32> = self.created_host_pids.drain(..).collect();
        for host_pid in pending.iter().copied() {
            unsafe {
                libc::kill(host_pid, libc::SIGKILL);
            }
        }

        let deadline = std::time::Instant::now() + std::time::Duration::from_secs(2);
        while !pending.is_empty() && std::time::Instant::now() <= deadline {
            let mut status = 0;
            let waited = unsafe { libc::waitpid(-1, &mut status, libc::__WALL | libc::WNOHANG) };
            if waited > 0 {
                pending.remove(&waited);
            } else if waited == 0 {
                std::thread::sleep(std::time::Duration::from_millis(1));
            } else {
                break;
            }
        }
    }

    fn fork_stopped_replacement_leader(&mut self, thread_count: usize) -> Result<i32, FdError> {
        if let Some(path) = self.static_replacement_path.clone() {
            if std::env::var_os("SUPERMACHINE_KBOXLIKE_TRACE_MEMORY_RESTORE").is_some() {
                eprintln!(
                    "KBOXLIVE_STATIC_REPLACEMENT path={} threads={thread_count}",
                    path.display(),
                );
            }
            if thread_count != 1 {
                return Err(FdError::TraceeInstallFailed(
                    "static replacement helper does not create follower threads",
                ));
            }
            return self.fork_stopped_static_replacement_leader(&path);
        }

        let previous_syscall_page_env = std::env::var_os(KBOXLIKE_REPLACEMENT_SYSCALL_PAGE_ENV);
        if let Some(syscall_page) = self.syscall_page {
            std::env::set_var(
                KBOXLIKE_REPLACEMENT_SYSCALL_PAGE_ENV,
                format!("0x{syscall_page:x}"),
            );
        } else {
            std::env::remove_var(KBOXLIKE_REPLACEMENT_SYSCALL_PAGE_ENV);
        }

        let child = unsafe { libc::fork() };
        match previous_syscall_page_env {
            Some(value) => std::env::set_var(KBOXLIKE_REPLACEMENT_SYSCALL_PAGE_ENV, value),
            None => std::env::remove_var(KBOXLIKE_REPLACEMENT_SYSCALL_PAGE_ENV),
        }
        if child < 0 {
            return Err(FdError::TraceeInstallFailed(
                "fork replacement tracee failed",
            ));
        }

        if child == 0 {
            replacement_group_child_main(thread_count);
        }

        let mut status = 0;
        let waited = unsafe { libc::waitpid(child, &mut status, 0) };
        if waited != child {
            unsafe {
                libc::kill(child, libc::SIGKILL);
                libc::waitpid(child, &mut status, 0);
            }
            return Err(FdError::TraceeInstallFailed(
                "replacement tracee wait failed",
            ));
        }
        if !libc::WIFSTOPPED(status) || libc::WSTOPSIG(status) != libc::SIGSTOP {
            unsafe {
                libc::kill(child, libc::SIGKILL);
                libc::waitpid(child, &mut status, 0);
            }
            return Err(FdError::TraceeInstallFailed(
                "replacement tracee did not stop at initial SIGSTOP",
            ));
        }

        self.created_host_pids.push(child);
        Ok(child)
    }

    fn fork_stopped_static_replacement_leader(&mut self, path: &Path) -> Result<i32, FdError> {
        let child = unsafe { libc::fork() };
        if child < 0 {
            return Err(FdError::TraceeInstallFailed(
                "fork static replacement tracee failed",
            ));
        }

        if child == 0 {
            static_replacement_child_main(path);
        }

        let mut status = 0;
        let waited = unsafe { libc::waitpid(child, &mut status, 0) };
        if waited != child {
            unsafe {
                libc::kill(child, libc::SIGKILL);
                libc::waitpid(child, &mut status, 0);
            }
            return Err(FdError::TraceeInstallFailed(
                "static replacement tracee wait failed",
            ));
        }
        if !libc::WIFSTOPPED(status)
            || !matches!(libc::WSTOPSIG(status), libc::SIGTRAP | libc::SIGSTOP)
        {
            unsafe {
                libc::kill(child, libc::SIGKILL);
                libc::waitpid(child, &mut status, 0);
            }
            return Err(FdError::TraceeInstallFailed(
                "static replacement tracee did not stop after exec",
            ));
        }

        self.created_host_pids.push(child);
        Ok(child)
    }

    fn create_stopped_replacement_followers(
        &mut self,
        leader_pid: i32,
        thread_count: usize,
    ) -> Result<Vec<i32>, FdError> {
        if thread_count <= 1 {
            return Ok(Vec::new());
        }

        set_ptrace_traceclone(leader_pid)?;
        ptrace_cont(leader_pid)?;

        let mut follower_tids = Vec::new();
        let mut stopped_follower_tids = BTreeSet::new();
        let mut leader_final_stop = false;
        let deadline = std::time::Instant::now() + std::time::Duration::from_secs(5);
        while !leader_final_stop || stopped_follower_tids.len() < thread_count - 1 {
            if std::time::Instant::now() > deadline {
                return Err(FdError::TraceeInstallFailed(
                    "replacement thread bootstrap timed out",
                ));
            }

            let mut status = 0;
            let waited = unsafe { libc::waitpid(-1, &mut status, libc::__WALL | libc::WNOHANG) };
            if waited < 0 {
                return Err(FdError::TraceeInstallFailed(
                    "replacement tracee wait failed",
                ));
            }
            if waited == 0 {
                std::thread::sleep(std::time::Duration::from_millis(1));
                continue;
            }
            if !libc::WIFSTOPPED(status) {
                return Err(FdError::TraceeInstallFailed(
                    "replacement tracee exited during thread bootstrap",
                ));
            }

            let event = status >> LINUX_PTRACE_EVENT_SHIFT;
            if waited == leader_pid && event == LINUX_PTRACE_EVENT_CLONE {
                let follower_tid = ptrace_geteventmsg_pid(leader_pid)?;
                if follower_tid <= 0 {
                    return Err(FdError::TraceeInstallFailed(
                        "replacement clone event returned invalid tid",
                    ));
                }
                if follower_tids.len() >= thread_count - 1 {
                    return Err(FdError::TraceeInstallFailed(
                        "replacement clone event returned too many tids",
                    ));
                }
                follower_tids.push(follower_tid);
                self.created_host_pids.push(follower_tid);
                signal_thread(leader_pid, follower_tid, libc::SIGURG)?;
                ptrace_cont(leader_pid)?;
                continue;
            }

            if waited == leader_pid && libc::WSTOPSIG(status) == libc::SIGTRAP {
                leader_final_stop = true;
                continue;
            }

            if follower_tids.contains(&waited) {
                stopped_follower_tids.insert(waited);
                continue;
            }

            return Err(FdError::TraceeInstallFailed(
                "unexpected replacement tracee bootstrap stop",
            ));
        }

        Ok(follower_tids)
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
impl StoppedTraceeReplacementFactory for LinuxStoppedTraceeReplacementFactory {
    fn prepare_syscall_page(&mut self, syscall_page: u64) -> Result<(), FdError> {
        if syscall_page == 0 || syscall_page % 4096 != 0 {
            return Err(FdError::TraceeInstallFailed(
                "syscall page address is not page aligned",
            ));
        }
        self.syscall_page = Some(syscall_page);
        Ok(())
    }

    fn create_stopped_replacement_group(
        &mut self,
        _model_pid: ProcessId,
        threads: &[KboxlikeThreadSnapshot],
    ) -> Result<BTreeMap<ModelThreadId, i32>, FdError> {
        if threads.is_empty() {
            return Err(FdError::TraceeInstallFailed(
                "replacement group has no threads",
            ));
        }

        let leader_pid = self.fork_stopped_replacement_leader(threads.len())?;
        let follower_tids = self.create_stopped_replacement_followers(leader_pid, threads.len())?;
        if follower_tids.len() + 1 != threads.len() {
            return Err(FdError::TraceeInstallFailed(
                "replacement group created wrong thread count",
            ));
        }

        let mut host_pids = Vec::with_capacity(threads.len());
        host_pids.push(leader_pid);
        host_pids.extend(follower_tids);
        Ok(threads
            .iter()
            .zip(host_pids)
            .map(|(thread, host_pid)| (thread.model_thread_id, host_pid))
            .collect())
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
extern "C" fn replacement_follower_main(_arg: *mut c_void) -> i32 {
    unsafe {
        loop {
            libc::pause();
        }
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn replacement_group_child_main(thread_count: usize) -> ! {
    unsafe {
        if let Some(syscall_page) = replacement_syscall_page_from_env() {
            let mapped = libc::mmap(
                syscall_page as *mut c_void,
                8192,
                libc::PROT_READ | libc::PROT_WRITE | libc::PROT_EXEC,
                libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_FIXED_NOREPLACE,
                -1,
                0,
            );
            if mapped == libc::MAP_FAILED || mapped as u64 != syscall_page {
                libc::_exit(114);
            }
            let code = mapped as *mut u8;
            *code.add(0) = 0x0f;
            *code.add(1) = 0x05;
            *code.add(2) = 0xcc;
        }

        let ret = libc::ptrace(
            libc::PTRACE_TRACEME,
            0,
            std::ptr::null_mut::<c_void>(),
            std::ptr::null_mut::<c_void>(),
        );
        if ret < 0 {
            libc::_exit(111);
        }
        libc::raise(libc::SIGSTOP);

        for _ in 1..thread_count {
            let stack = libc::mmap(
                std::ptr::null_mut(),
                REPLACEMENT_FOLLOWER_STACK_LEN,
                libc::PROT_READ | libc::PROT_WRITE,
                libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
                -1,
                0,
            );
            if stack == libc::MAP_FAILED {
                libc::_exit(112);
            }
            let stack_top = (stack as *mut u8).add(REPLACEMENT_FOLLOWER_STACK_LEN) as *mut c_void;
            let flags = LINUX_CLONE_VM
                | LINUX_CLONE_FS
                | LINUX_CLONE_FILES
                | LINUX_CLONE_SIGHAND
                | LINUX_CLONE_THREAD
                | LINUX_CLONE_SYSVSEM;
            let tid = libc::clone(
                replacement_follower_main,
                stack_top,
                flags,
                std::ptr::null_mut::<c_void>(),
            );
            if tid < 0 {
                libc::_exit(113);
            }
        }

        libc::raise(libc::SIGTRAP);
        loop {
            libc::pause();
        }
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn replacement_syscall_page_from_env() -> Option<u64> {
    let raw = std::env::var(KBOXLIKE_REPLACEMENT_SYSCALL_PAGE_ENV).ok()?;
    let trimmed = raw.trim();
    let parsed = if let Some(hex) = trimmed.strip_prefix("0x") {
        u64::from_str_radix(hex, 16).ok()?
    } else {
        trimmed.parse::<u64>().ok()?
    };
    (parsed != 0 && parsed % 4096 == 0).then_some(parsed)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn static_replacement_child_main(path: &Path) -> ! {
    unsafe {
        let ret = libc::ptrace(
            libc::PTRACE_TRACEME,
            0,
            std::ptr::null_mut::<c_void>(),
            std::ptr::null_mut::<c_void>(),
        );
        if ret < 0 {
            libc::_exit(121);
        }

        let path_c = match CString::new(path.as_os_str().as_bytes()) {
            Ok(path) => path,
            Err(_) => libc::_exit(122),
        };
        let argv0 = c"busybox";
        let applet = c"sleep";
        let seconds = c"1000000";
        let argv = [
            argv0.as_ptr(),
            applet.as_ptr(),
            seconds.as_ptr(),
            std::ptr::null(),
        ];
        let envp = [std::ptr::null()];
        libc::execve(path_c.as_ptr(), argv.as_ptr(), envp.as_ptr());
        libc::_exit(123);
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn set_ptrace_tracesysgood(pid: i32) -> Result<(), FdError> {
    let ret = unsafe {
        libc::ptrace(
            libc::PTRACE_SETOPTIONS,
            pid,
            std::ptr::null_mut::<c_void>(),
            LINUX_PTRACE_O_TRACESYSGOOD as usize as *mut c_void,
        )
    };
    if ret < 0 {
        return Err(FdError::TraceeInstallFailed("ptrace setoptions failed"));
    }
    Ok(())
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn parse_proc_maps_range(line: &str) -> Option<(u64, u64)> {
    let range = line.split_whitespace().next()?;
    let (start, end) = range.split_once('-')?;
    Some((
        u64::from_str_radix(start, 16).ok()?,
        u64::from_str_radix(end, 16).ok()?,
    ))
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn tracee_mapping_has_execute(pid: i32, addr: u64, len: u64) -> bool {
    let Ok(maps) = std::fs::read_to_string(format!("/proc/{pid}/maps")) else {
        return false;
    };
    maps.lines().any(|line| {
        let mut fields = line.split_whitespace();
        let Some(range) = fields.next() else {
            return false;
        };
        let Some(perms) = fields.next() else {
            return false;
        };
        let Some((start, end)) = range.split_once('-') else {
            return false;
        };
        let Ok(start) = u64::from_str_radix(start, 16) else {
            return false;
        };
        let Ok(end) = u64::from_str_radix(end, 16) else {
            return false;
        };
        start <= addr && addr.saturating_add(len) <= end && perms.as_bytes().get(2) == Some(&b'x')
    })
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn ranges_overlap_u64(start_a: u64, len_a: u64, start_b: u64, len_b: u64) -> bool {
    let end_a = start_a.saturating_add(len_a);
    let end_b = start_b.saturating_add(len_b);
    start_a < end_b && start_b < end_a
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn set_ptrace_traceclone(pid: i32) -> Result<(), FdError> {
    let ret = unsafe {
        libc::ptrace(
            libc::PTRACE_SETOPTIONS,
            pid,
            std::ptr::null_mut::<c_void>(),
            LINUX_PTRACE_O_TRACECLONE as usize as *mut c_void,
        )
    };
    if ret < 0 {
        return Err(FdError::TraceeInstallFailed("ptrace setoptions failed"));
    }
    Ok(())
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn ptrace_cont(pid: i32) -> Result<(), FdError> {
    let ret = unsafe {
        libc::ptrace(
            libc::PTRACE_CONT,
            pid,
            std::ptr::null_mut::<c_void>(),
            std::ptr::null_mut::<c_void>(),
        )
    };
    if ret < 0 {
        return Err(FdError::TraceeInstallFailed("ptrace cont failed"));
    }
    Ok(())
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn ptrace_geteventmsg_pid(pid: i32) -> Result<i32, FdError> {
    let mut event_msg = 0u64;
    let ret = unsafe {
        libc::ptrace(
            libc::PTRACE_GETEVENTMSG,
            pid,
            std::ptr::null_mut::<c_void>(),
            &mut event_msg as *mut _ as *mut c_void,
        )
    };
    if ret < 0 {
        return Err(FdError::TraceeInstallFailed("ptrace geteventmsg failed"));
    }
    if event_msg > i32::MAX as u64 {
        return Err(FdError::TraceeInstallFailed(
            "ptrace geteventmsg pid overflowed",
        ));
    }
    Ok(event_msg as i32)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn signal_thread(tgid: i32, tid: i32, signal: i32) -> Result<(), FdError> {
    let ret = unsafe { libc::syscall(libc::SYS_tgkill, tgid, tid, signal) };
    if ret < 0 {
        return Err(FdError::TraceeInstallFailed("tgkill tracee signal failed"));
    }
    Ok(())
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) struct TraceeProcFdSourcePlan {
    pub(crate) supervisor_pid: i32,
    pub(crate) supervisor_fd: i32,
    pub(crate) tracee_path_addr: u64,
}

impl TraceeProcFdSourcePlan {
    pub(crate) fn new(
        supervisor_pid: i32,
        supervisor_fd: i32,
        tracee_path_addr: u64,
    ) -> Result<Self, FdError> {
        if supervisor_pid <= 0 {
            return Err(FdError::TraceeInstallFailed("invalid supervisor pid"));
        }
        if supervisor_fd < 0 {
            return Err(FdError::InvalidFd(supervisor_fd));
        }
        if tracee_path_addr == 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee source path address is null",
            ));
        }
        Ok(Self {
            supervisor_pid,
            supervisor_fd,
            tracee_path_addr,
        })
    }

    pub(crate) fn proc_fd_path(&self) -> String {
        format!("/proc/{}/fd/{}", self.supervisor_pid, self.supervisor_fd)
    }

    pub(crate) fn path_bytes(&self) -> Vec<u8> {
        let mut bytes = self.proc_fd_path().into_bytes();
        bytes.push(0);
        bytes
    }

    pub(crate) fn open_syscall(&self) -> TraceeSyscall {
        self.open_syscall_with_flags(LINUX_O_CLOEXEC)
    }

    pub(crate) fn open_syscall_with_flags(&self, flags: u64) -> TraceeSyscall {
        TraceeSyscall::new3(
            LINUX_X86_64_SYS_OPENAT,
            LINUX_AT_FDCWD,
            self.tracee_path_addr,
            flags,
        )
    }

    pub(crate) fn write_path(&self, writer: &mut impl TraceeMemoryWriter) -> Result<(), FdError> {
        writer.write_bytes(self.tracee_path_addr, &self.path_bytes())
    }

    pub(crate) fn open(&self, executor: &mut impl TraceeSyscallExecutor) -> Result<i32, FdError> {
        self.open_with_flags(executor, LINUX_O_CLOEXEC)
    }

    pub(crate) fn open_with_flags(
        &self,
        executor: &mut impl TraceeSyscallExecutor,
        flags: u64,
    ) -> Result<i32, FdError> {
        let fd = executor.syscall(self.open_syscall_with_flags(flags))?;
        if fd < 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee open supervisor fd failed",
            ));
        }
        if fd > i32::MAX as i64 {
            return Err(FdError::TraceeInstallFailed(
                "tracee open supervisor fd overflowed",
            ));
        }
        Ok(fd as i32)
    }
}

impl TraceeInstallPlan {
    pub(crate) fn from_shadow_install(
        plan: ShadowInstallPlan,
        tracee_source_fd: i32,
        close_source_after_install: bool,
    ) -> Result<Self, FdError> {
        Self::new(
            tracee_source_fd,
            plan.target_fd,
            plan.cloexec,
            close_source_after_install,
        )
    }

    pub(crate) fn new(
        source_fd: i32,
        target_fd: i32,
        cloexec: bool,
        close_source_after_install: bool,
    ) -> Result<Self, FdError> {
        if source_fd < 0 {
            return Err(FdError::InvalidFd(source_fd));
        }
        if target_fd < 0 {
            return Err(FdError::InvalidFd(target_fd));
        }
        if source_fd == target_fd {
            return Err(FdError::TraceeInstallFailed(
                "tracee source fd aliases target fd",
            ));
        }
        Ok(Self {
            source_fd,
            target_fd,
            cloexec,
            close_source_after_install,
        })
    }

    pub(crate) fn syscalls(&self) -> Vec<TraceeSyscall> {
        let mut calls = vec![
            TraceeSyscall::new3(
                LINUX_X86_64_SYS_DUP2,
                self.source_fd as u64,
                self.target_fd as u64,
                0,
            ),
            TraceeSyscall::new3(
                LINUX_X86_64_SYS_FCNTL,
                self.target_fd as u64,
                LINUX_F_SETFD,
                if self.cloexec { LINUX_FD_CLOEXEC } else { 0 },
            ),
        ];
        if self.close_source_after_install {
            calls.push(TraceeSyscall::new3(
                LINUX_X86_64_SYS_CLOSE,
                self.source_fd as u64,
                0,
                0,
            ));
        }
        calls
    }

    pub(crate) fn apply(&self, executor: &mut impl TraceeSyscallExecutor) -> Result<(), FdError> {
        let dup_ret = executor.syscall(TraceeSyscall::new3(
            LINUX_X86_64_SYS_DUP2,
            self.source_fd as u64,
            self.target_fd as u64,
            0,
        ))?;
        if dup_ret < 0 {
            return Err(FdError::TraceeInstallFailed("tracee dup2 failed"));
        }
        if dup_ret != self.target_fd as i64 {
            return Err(FdError::TraceeInstallFailed(
                "tracee dup2 returned wrong fd",
            ));
        }

        let fcntl_ret = executor.syscall(TraceeSyscall::new3(
            LINUX_X86_64_SYS_FCNTL,
            self.target_fd as u64,
            LINUX_F_SETFD,
            if self.cloexec { LINUX_FD_CLOEXEC } else { 0 },
        ))?;
        if fcntl_ret < 0 {
            return Err(FdError::TraceeInstallFailed("tracee fcntl failed"));
        }

        if self.close_source_after_install {
            let close_ret = executor.syscall(TraceeSyscall::new3(
                LINUX_X86_64_SYS_CLOSE,
                self.source_fd as u64,
                0,
                0,
            ))?;
            if close_ret < 0 {
                return Err(FdError::TraceeInstallFailed("tracee close failed"));
            }
        }

        Ok(())
    }
}

pub(crate) fn apply_proc_fd_shadow_install(
    source: &TraceeProcFdSourcePlan,
    shadow_install: ShadowInstallPlan,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<(), FdError> {
    source.write_path(writer)?;
    let source_fd = source.open(executor)?;
    if source_fd == shadow_install.target_fd {
        let fcntl_ret = executor.syscall(TraceeSyscall::new3(
            LINUX_X86_64_SYS_FCNTL,
            shadow_install.target_fd as u64,
            LINUX_F_SETFD,
            if shadow_install.cloexec {
                LINUX_FD_CLOEXEC
            } else {
                0
            },
        ))?;
        if fcntl_ret < 0 {
            return Err(FdError::TraceeInstallFailed("tracee fcntl failed"));
        }
        return Ok(());
    }
    let plan = TraceeInstallPlan::from_shadow_install(shadow_install, source_fd, true)?;
    plan.apply(executor)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_tracee_mm_exe_file_with_scratch(
    exe_path: &Path,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<(), FdError> {
    let path_bytes = nul_terminated_path_bytes(exe_path)?;
    let scratch = TraceeScratchMapping::map(path_bytes.len(), executor)?;
    let install_result = (|| {
        writer.write_bytes(scratch.addr, &path_bytes)?;
        let exe_fd = executor.syscall(TraceeSyscall::new3(
            LINUX_X86_64_SYS_OPENAT,
            LINUX_AT_FDCWD,
            scratch.addr,
            LINUX_O_CLOEXEC,
        ))?;
        if exe_fd < 0 {
            return Err(FdError::TraceeInstallFailed("tracee open exe file failed"));
        }
        let prctl_result = executor.syscall(TraceeSyscall::new6(
            LINUX_X86_64_SYS_PRCTL,
            [
                LINUX_PR_SET_MM,
                LINUX_PR_SET_MM_EXE_FILE,
                exe_fd as u64,
                0,
                0,
                0,
            ],
        ));
        let close_result = executor.syscall(TraceeSyscall::new3(
            LINUX_X86_64_SYS_CLOSE,
            exe_fd as u64,
            0,
            0,
        ));
        if prctl_result? < 0 {
            return Err(FdError::TraceeInstallFailed(
                "tracee prctl set mm exe file failed",
            ));
        }
        if close_result? < 0 {
            return Err(FdError::TraceeInstallFailed("tracee close exe file failed"));
        }
        Ok(())
    })();
    let unmap_result = scratch.unmap(executor);

    match (install_result, unmap_result) {
        (Err(err), _) => Err(err),
        (Ok(()), Err(err)) => Err(err),
        (Ok(()), Ok(())) => Ok(()),
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn nul_terminated_path_bytes(path: &Path) -> Result<Vec<u8>, FdError> {
    let bytes = path.as_os_str().as_bytes();
    if bytes.is_empty() || bytes.contains(&0) {
        return Err(FdError::TraceeInstallFailed("invalid tracee path bytes"));
    }
    let mut out = bytes.to_vec();
    out.push(0);
    Ok(out)
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct TraceeEndpointInstall {
    source_fd: i32,
    target_fd: i32,
    cloexec: bool,
}

pub(crate) fn apply_tracee_socketpair_install_with_scratch(
    first: ShadowInstallPlan,
    second: ShadowInstallPlan,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<(), FdError> {
    let scratch = TraceeScratchMapping::map(std::mem::size_of::<[i32; 2]>(), executor)?;
    let install_result = (|| {
        let socketpair_ret = executor.syscall(TraceeSyscall::new6(
            LINUX_X86_64_SYS_SOCKETPAIR,
            [LINUX_AF_UNIX, LINUX_SOCK_STREAM, 0, scratch.addr, 0, 0],
        ))?;
        if socketpair_ret < 0 {
            return Err(FdError::TraceeInstallFailed("tracee socketpair failed"));
        }

        let pid = executor
            .tracee_pid()
            .ok_or(FdError::TraceeInstallFailed("missing tracee pid"))?;
        let [first_source_fd, second_source_fd] = read_tracee_i32_pair(pid, scratch.addr)?;
        apply_tracee_socketpair_endpoint_installs(
            TraceeEndpointInstall {
                source_fd: first_source_fd,
                target_fd: first.target_fd,
                cloexec: first.cloexec,
            },
            TraceeEndpointInstall {
                source_fd: second_source_fd,
                target_fd: second.target_fd,
                cloexec: second.cloexec,
            },
            executor,
        )
    })();
    let unmap_result = scratch.unmap(executor);

    match (install_result, unmap_result) {
        (Err(err), _) => Err(err),
        (Ok(()), Err(err)) => Err(err),
        (Ok(()), Ok(())) => Ok(()),
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn apply_supervisor_fd_scm_rights_install_with_scratch(
    supervisor_fd: i32,
    shadow_install: ShadowInstallPlan,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<(), FdError> {
    if supervisor_fd < 0 {
        return Err(FdError::InvalidFd(supervisor_fd));
    }

    let scratch = TraceeScratchMapping::map(512, executor)?;
    let install_result = (|| {
        let socketpair_ret = executor.syscall(TraceeSyscall::new6(
            LINUX_X86_64_SYS_SOCKETPAIR,
            [LINUX_AF_UNIX, LINUX_SOCK_STREAM, 0, scratch.addr, 0, 0],
        ))?;
        if socketpair_ret < 0 {
            return Err(FdError::TraceeInstallFailed("tracee scm socketpair failed"));
        }

        let pid = executor
            .tracee_pid()
            .ok_or(FdError::TraceeInstallFailed("missing tracee pid"))?;
        let [tracee_send_fd, tracee_recv_fd] = read_tracee_i32_pair(pid, scratch.addr)?;
        let supervisor_control_fd = duplicate_tracee_fd_to_supervisor(pid, tracee_send_fd)?;
        let send_result = send_fd_over_unix_socket(supervisor_control_fd, supervisor_fd);
        let close_control_result = close_host_fd(supervisor_control_fd);
        send_result?;
        close_control_result?;

        let recv_fd = recv_supervisor_fd_in_tracee(tracee_recv_fd, scratch.addr, writer, executor)?;
        let close_send_result = close_tracee_fd(tracee_send_fd, executor);
        let install_result = apply_tracee_fd_install(
            recv_fd,
            shadow_install.target_fd,
            shadow_install.cloexec,
            true,
            executor,
        );
        let close_recv_result = if tracee_recv_fd == shadow_install.target_fd {
            Ok(())
        } else {
            close_tracee_fd(tracee_recv_fd, executor)
        };

        close_send_result?;
        install_result?;
        close_recv_result
    })();
    let unmap_result = scratch.unmap(executor);

    match (install_result, unmap_result) {
        (Err(err), _) => Err(err),
        (Ok(()), Err(err)) => Err(err),
        (Ok(()), Ok(())) => Ok(()),
    }
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn recv_supervisor_fd_in_tracee(
    tracee_recv_fd: i32,
    scratch_addr: u64,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<i32, FdError> {
    let data_addr = scratch_addr + 64;
    let iov_addr = scratch_addr + 80;
    let control_addr = scratch_addr + 128;
    let msghdr_addr = scratch_addr + 256;

    let data = [0u8; 1];
    writer.write_bytes(data_addr, &data)?;

    let iov = libc::iovec {
        iov_base: data_addr as *mut c_void,
        iov_len: data.len(),
    };
    writer.write_bytes(iov_addr, plain_old_bytes(&iov))?;

    let control = [0u8; 64];
    writer.write_bytes(control_addr, &control)?;

    let mut msg: libc::msghdr = unsafe { std::mem::zeroed() };
    msg.msg_iov = iov_addr as *mut libc::iovec;
    msg.msg_iovlen = 1;
    msg.msg_control = control_addr as *mut c_void;
    msg.msg_controllen = control.len();
    writer.write_bytes(msghdr_addr, plain_old_bytes(&msg))?;

    let recv_ret = executor.syscall(TraceeSyscall::new3(
        LINUX_X86_64_SYS_RECVMSG,
        tracee_recv_fd as u64,
        msghdr_addr,
        0,
    ))?;
    if recv_ret < 0 {
        return Err(FdError::TraceeInstallFailed("tracee recvmsg failed"));
    }

    let pid = executor
        .tracee_pid()
        .ok_or(FdError::TraceeInstallFailed("missing tracee pid"))?;
    read_tracee_i32(
        pid,
        control_addr + std::mem::size_of::<libc::cmsghdr>() as u64,
    )
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn duplicate_tracee_fd_to_supervisor(pid: i32, tracee_fd: i32) -> Result<i32, FdError> {
    const SYS_PIDFD_OPEN: libc::c_long = 434;
    const SYS_PIDFD_GETFD: libc::c_long = 438;

    let pidfd = unsafe { libc::syscall(SYS_PIDFD_OPEN, pid, 0) };
    if pidfd < 0 || pidfd > i32::MAX as libc::c_long {
        return Err(FdError::TraceeInstallFailed("pidfd_open failed"));
    }
    let dup_fd = unsafe { libc::syscall(SYS_PIDFD_GETFD, pidfd as i32, tracee_fd, 0) };
    let close_result = close_host_fd(pidfd as i32);
    if dup_fd < 0 || dup_fd > i32::MAX as libc::c_long {
        close_result?;
        return Err(FdError::TraceeInstallFailed("pidfd_getfd failed"));
    }
    close_result?;
    Ok(dup_fd as i32)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn send_fd_over_unix_socket(socket_fd: i32, fd_to_send: i32) -> Result<(), FdError> {
    let mut data = [0u8; 1];
    let mut iov = libc::iovec {
        iov_base: data.as_mut_ptr() as *mut c_void,
        iov_len: data.len(),
    };
    let mut control = [0u8; 64];
    let control_len = cmsg_space_for_i32();
    let cmsg = control.as_mut_ptr() as *mut libc::cmsghdr;
    unsafe {
        (*cmsg).cmsg_len = (std::mem::size_of::<libc::cmsghdr>() + std::mem::size_of::<i32>()) as _;
        (*cmsg).cmsg_level = libc::SOL_SOCKET;
        (*cmsg).cmsg_type = libc::SCM_RIGHTS;
        let data_ptr = control
            .as_mut_ptr()
            .add(std::mem::size_of::<libc::cmsghdr>()) as *mut i32;
        *data_ptr = fd_to_send;
    }

    let mut msg: libc::msghdr = unsafe { std::mem::zeroed() };
    msg.msg_iov = &mut iov;
    msg.msg_iovlen = 1;
    msg.msg_control = control.as_mut_ptr() as *mut c_void;
    msg.msg_controllen = control_len;

    let sent = unsafe { libc::sendmsg(socket_fd, &msg, 0) };
    if sent != 1 {
        let errno = std::io::Error::last_os_error()
            .raw_os_error()
            .unwrap_or_default();
        eprintln!(
            "KBOXLIVE_SCM_SENDMSG_FAILED socket_fd={socket_fd} fd_to_send={fd_to_send} sent={sent} errno={errno}"
        );
        return Err(FdError::TraceeInstallFailed("sendmsg scm_rights failed"));
    }
    Ok(())
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn cmsg_space_for_i32() -> usize {
    align_to_usize(std::mem::size_of::<libc::cmsghdr>())
        + align_to_usize(std::mem::size_of::<i32>())
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn align_to_usize(value: usize) -> usize {
    let align = std::mem::size_of::<usize>();
    (value + align - 1) & !(align - 1)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn close_host_fd(fd: i32) -> Result<(), FdError> {
    let ret = unsafe { libc::close(fd) };
    if ret < 0 {
        return Err(FdError::TraceeInstallFailed("host close failed"));
    }
    Ok(())
}

fn apply_tracee_socketpair_endpoint_installs(
    first: TraceeEndpointInstall,
    second: TraceeEndpointInstall,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<(), FdError> {
    if first.source_fd == second.target_fd && second.source_fd == first.target_fd {
        let temp_fd = executor.syscall(TraceeSyscall::new3(
            LINUX_X86_64_SYS_FCNTL,
            first.source_fd as u64,
            LINUX_F_DUPFD_CLOEXEC,
            0,
        ))?;
        if temp_fd < 0 || temp_fd > i32::MAX as i64 {
            return Err(FdError::TraceeInstallFailed("tracee temp dup failed"));
        }
        apply_tracee_fd_install(
            second.source_fd,
            second.target_fd,
            second.cloexec,
            false,
            executor,
        )?;
        apply_tracee_fd_install(
            temp_fd as i32,
            first.target_fd,
            first.cloexec,
            true,
            executor,
        )?;
        return Ok(());
    }

    if second.source_fd == first.target_fd {
        apply_tracee_fd_install(
            second.source_fd,
            second.target_fd,
            second.cloexec,
            true,
            executor,
        )?;
        apply_tracee_fd_install(
            first.source_fd,
            first.target_fd,
            first.cloexec,
            true,
            executor,
        )?;
        return Ok(());
    }

    if first.source_fd == second.target_fd {
        apply_tracee_fd_install(
            first.source_fd,
            first.target_fd,
            first.cloexec,
            true,
            executor,
        )?;
        apply_tracee_fd_install(
            second.source_fd,
            second.target_fd,
            second.cloexec,
            true,
            executor,
        )?;
        return Ok(());
    }

    apply_tracee_fd_install(
        first.source_fd,
        first.target_fd,
        first.cloexec,
        true,
        executor,
    )?;
    apply_tracee_fd_install(
        second.source_fd,
        second.target_fd,
        second.cloexec,
        true,
        executor,
    )
}

fn close_tracee_fd(fd: i32, executor: &mut impl TraceeSyscallExecutor) -> Result<(), FdError> {
    let ret = executor.syscall(TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, fd as u64, 0, 0))?;
    if ret < 0 {
        return Err(FdError::TraceeInstallFailed("tracee close failed"));
    }
    Ok(())
}

fn apply_tracee_fd_install(
    source_fd: i32,
    target_fd: i32,
    cloexec: bool,
    close_source_after_install: bool,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<(), FdError> {
    if source_fd == target_fd {
        let fcntl_ret = executor.syscall(TraceeSyscall::new3(
            LINUX_X86_64_SYS_FCNTL,
            target_fd as u64,
            LINUX_F_SETFD,
            if cloexec { LINUX_FD_CLOEXEC } else { 0 },
        ))?;
        if fcntl_ret < 0 {
            return Err(FdError::TraceeInstallFailed("tracee fcntl failed"));
        }
        return Ok(());
    }

    TraceeInstallPlan::new(source_fd, target_fd, cloexec, close_source_after_install)?
        .apply(executor)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn read_tracee_i32_pair(pid: i32, addr: u64) -> Result<[i32; 2], FdError> {
    let mut values = [0i32; 2];
    let local = libc::iovec {
        iov_base: values.as_mut_ptr() as *mut c_void,
        iov_len: std::mem::size_of_val(&values),
    };
    let remote = libc::iovec {
        iov_base: addr as *mut c_void,
        iov_len: std::mem::size_of_val(&values),
    };
    let read = unsafe { libc::process_vm_readv(pid, &local, 1, &remote, 1, 0) };
    if read != std::mem::size_of_val(&values) as isize {
        return Err(FdError::TraceeInstallFailed(
            "process_vm_readv socketpair fds failed",
        ));
    }
    Ok(values)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn read_tracee_i32(pid: i32, addr: u64) -> Result<i32, FdError> {
    let mut value = 0i32;
    let local = libc::iovec {
        iov_base: &mut value as *mut _ as *mut c_void,
        iov_len: std::mem::size_of::<i32>(),
    };
    let remote = libc::iovec {
        iov_base: addr as *mut c_void,
        iov_len: std::mem::size_of::<i32>(),
    };
    let read = unsafe { libc::process_vm_readv(pid, &local, 1, &remote, 1, 0) };
    if read != std::mem::size_of::<i32>() as isize {
        return Err(FdError::TraceeInstallFailed(
            "process_vm_readv received fd failed",
        ));
    }
    Ok(value)
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn plain_old_bytes<T>(value: &T) -> &[u8] {
    unsafe { std::slice::from_raw_parts(value as *const T as *const u8, std::mem::size_of::<T>()) }
}

#[cfg(not(all(target_os = "linux", target_arch = "x86_64")))]
fn read_tracee_i32_pair(_pid: i32, _addr: u64) -> Result<[i32; 2], FdError> {
    Err(FdError::TraceeInstallFailed(
        "tracee socketpair fd read unsupported on this host",
    ))
}

pub(crate) fn apply_proc_fd_shadow_install_with_scratch(
    supervisor_pid: i32,
    supervisor_fd: i32,
    shadow_install: ShadowInstallPlan,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<(), FdError> {
    let path_probe = TraceeProcFdSourcePlan::new(supervisor_pid, supervisor_fd, 1)?;
    let scratch = TraceeScratchMapping::map(path_probe.path_bytes().len(), executor)?;
    let source = TraceeProcFdSourcePlan::new(supervisor_pid, supervisor_fd, scratch.addr)?;

    let install_result = apply_proc_fd_shadow_install(&source, shadow_install, writer, executor);
    let unmap_result = scratch.unmap(executor);

    match (install_result, unmap_result) {
        (Err(err), _) => Err(err),
        (Ok(()), Err(err)) => Err(err),
        (Ok(()), Ok(())) => Ok(()),
    }
}

pub(crate) fn apply_shadow_install_plan_with_scratch(
    supervisor_pid: i32,
    shadow_install: ShadowInstallPlan,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<(), FdError> {
    apply_proc_fd_shadow_install_with_scratch(
        supervisor_pid,
        shadow_install.shadow.supervisor_fd,
        shadow_install,
        writer,
        executor,
    )
}

pub(crate) fn install_operation_shadow_if_needed(
    fd_system: &KboxlikeFdSystem,
    pid: ProcessId,
    fd: FdNumber,
    operation: FdOperation,
    supervisor_pid: i32,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<bool, FdError> {
    let Some(plan) = fd_system.plan_operation_shadow_install(pid, fd, operation)? else {
        return Ok(false);
    };
    apply_shadow_install_plan_with_scratch(supervisor_pid, plan, writer, executor)?;
    Ok(true)
}

pub(crate) fn install_requested_operation_shadow_if_needed(
    fd_system: &KboxlikeFdSystem,
    request: TraceeOperationInstallRequest,
    supervisor_pid: i32,
    writer: &mut impl TraceeMemoryWriter,
    executor: &mut impl TraceeSyscallExecutor,
) -> Result<bool, FdError> {
    install_operation_shadow_if_needed(
        fd_system,
        request.model_pid,
        request.fd,
        request.operation,
        supervisor_pid,
        writer,
        executor,
    )
}

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
pub(crate) fn install_requested_operation_shadow_in_stopped_tracee(
    fd_system: &KboxlikeFdSystem,
    request: TraceeOperationInstallRequest,
    supervisor_pid: i32,
) -> Result<bool, FdError> {
    let mut writer = ProcessVmMemoryWriter::new(request.tracee_pid)?;
    let mut executor = PtraceSyscallExecutor::new(request.tracee_pid)?;
    install_requested_operation_shadow_if_needed(
        fd_system,
        request,
        supervisor_pid,
        &mut writer,
        &mut executor,
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::kboxlike::fd::{ShadowInstallPlan, ShadowKind, ShadowObject};
    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    use crate::kboxlike::snapshot::{
        KboxlikeByteBackedRestoreSource, KboxlikeMaterializedMemoryRestore,
        KboxlikeMaterializedMemoryRestoreAction, KboxlikeSharedMappingKind,
        KboxlikeSharedMemoryDump, KboxlikeThreadKernelStateSnapshot, KboxlikeThreadSnapshot,
    };
    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    use std::collections::BTreeMap;
    use std::collections::VecDeque;
    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    use std::path::PathBuf;

    #[derive(Default)]
    struct FakeTracee {
        calls: Vec<TraceeSyscall>,
        returns: VecDeque<i64>,
        synthetic_ranges: Vec<(u64, u64)>,
    }

    #[derive(Default)]
    struct FakeMemory {
        writes: Vec<(u64, Vec<u8>)>,
        fail: bool,
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[derive(Default)]
    struct FakeRegisterWriter {
        writes: Vec<libc::user_regs_struct>,
        fail: bool,
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[derive(Default)]
    struct FakeSharedObjectBackingFactory {
        next_fd: i32,
        created: Vec<String>,
        truncated: Vec<(i32, u64)>,
        writes: Vec<(i32, u64, Vec<u8>)>,
        fail_create: bool,
        fail_set_len: bool,
        fail_write: bool,
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[derive(Default)]
    struct FakeRestoreAccessFactory {
        returns_by_pid: BTreeMap<i32, Vec<i64>>,
        requested: Vec<i32>,
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[derive(Default)]
    struct FakeRestoredTraceeResumer {
        resumed: Vec<i32>,
        fail_pid: Option<i32>,
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[derive(Default)]
    struct FakeStoppedTraceeReplacementFactory {
        calls: Vec<(ProcessId, Vec<ModelThreadId>)>,
        returns: VecDeque<Result<BTreeMap<ModelThreadId, i32>, FdError>>,
    }

    impl FakeTracee {
        fn with_returns(returns: impl IntoIterator<Item = i64>) -> Self {
            Self {
                calls: Vec::new(),
                returns: returns.into_iter().collect(),
                synthetic_ranges: Vec::new(),
            }
        }

        fn with_returns_and_synthetic_ranges(
            returns: impl IntoIterator<Item = i64>,
            synthetic_ranges: Vec<(u64, u64)>,
        ) -> Self {
            Self {
                calls: Vec::new(),
                returns: returns.into_iter().collect(),
                synthetic_ranges,
            }
        }
    }

    impl TraceeSyscallExecutor for FakeTracee {
        fn syscall(&mut self, syscall: TraceeSyscall) -> Result<i64, FdError> {
            self.calls.push(syscall);
            Ok(self.returns.pop_front().unwrap_or(0))
        }

        fn kernel_synthetic_ranges(&self) -> Result<Vec<(u64, u64)>, FdError> {
            Ok(self.synthetic_ranges.clone())
        }
    }

    impl TraceeMemoryWriter for FakeMemory {
        fn write_bytes(&mut self, addr: u64, bytes: &[u8]) -> Result<(), FdError> {
            if self.fail {
                return Err(FdError::TraceeInstallFailed(
                    "tracee source path write failed",
                ));
            }
            self.writes.push((addr, bytes.to_vec()));
            Ok(())
        }
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    impl TraceeRegisterWriter for FakeRegisterWriter {
        fn write_regs(&mut self, regs: &libc::user_regs_struct) -> Result<(), FdError> {
            if self.fail {
                return Err(FdError::TraceeInstallFailed("ptrace setregs failed"));
            }
            self.writes.push(*regs);
            Ok(())
        }
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    impl TraceeSharedObjectBackingFactory for FakeSharedObjectBackingFactory {
        fn create_memfd(&mut self, name: &str) -> Result<i32, FdError> {
            if self.fail_create {
                return Err(FdError::TraceeInstallFailed("memfd_create failed"));
            }
            let fd = self.next_fd;
            self.next_fd += 1;
            self.created.push(name.to_string());
            Ok(fd)
        }

        fn set_len(&mut self, fd: i32, len: u64) -> Result<(), FdError> {
            if self.fail_set_len {
                return Err(FdError::TraceeInstallFailed(
                    "shared object ftruncate failed",
                ));
            }
            self.truncated.push((fd, len));
            Ok(())
        }

        fn write_all_at(&mut self, fd: i32, offset: u64, bytes: &[u8]) -> Result<(), FdError> {
            if self.fail_write {
                return Err(FdError::TraceeInstallFailed("shared object pwrite failed"));
            }
            self.writes.push((fd, offset, bytes.to_vec()));
            Ok(())
        }

        fn close_fds_on_drop(&self) -> bool {
            false
        }
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    impl TraceeRestoreAccessFactory for FakeRestoreAccessFactory {
        type Writer = FakeMemory;
        type Executor = FakeTracee;
        type RegisterWriter = FakeRegisterWriter;

        fn access_for_restore(
            &mut self,
            host_pid: i32,
        ) -> Result<TraceeRestoreAccess<Self::Writer, Self::Executor, Self::RegisterWriter>, FdError>
        {
            self.requested.push(host_pid);
            let returns = self
                .returns_by_pid
                .remove(&host_pid)
                .ok_or(FdError::TraceeInstallFailed("missing fake tracee returns"))?;
            Ok(TraceeRestoreAccess {
                writer: FakeMemory::default(),
                executor: FakeTracee::with_returns(returns),
                register_writer: FakeRegisterWriter::default(),
            })
        }
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    impl RestoredTraceeResumer for FakeRestoredTraceeResumer {
        fn resume_restored_tracee(&mut self, host_pid: i32) -> Result<(), FdError> {
            if self.fail_pid == Some(host_pid) {
                return Err(FdError::TraceeInstallFailed("resume failed"));
            }
            self.resumed.push(host_pid);
            Ok(())
        }
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    impl StoppedTraceeReplacementFactory for FakeStoppedTraceeReplacementFactory {
        fn create_stopped_replacement_group(
            &mut self,
            model_pid: ProcessId,
            threads: &[KboxlikeThreadSnapshot],
        ) -> Result<BTreeMap<ModelThreadId, i32>, FdError> {
            self.calls.push((
                model_pid,
                threads
                    .iter()
                    .map(|thread| thread.model_thread_id)
                    .collect(),
            ));
            self.returns
                .pop_front()
                .unwrap_or_else(|| Err(FdError::TraceeInstallFailed("missing fake replacement")))
        }
    }

    fn shadow_install(target_fd: i32, cloexec: bool) -> ShadowInstallPlan {
        ShadowInstallPlan {
            source_fd: 33033,
            target_fd,
            shadow: ShadowObject {
                kind: ShadowKind::LocalOnly,
                supervisor_fd: 700,
            },
            cloexec,
        }
    }

    #[test]
    fn tracee_plan_from_shadow_install_emits_dup2_and_fcntl() {
        let plan =
            TraceeInstallPlan::from_shadow_install(shadow_install(104, true), 900, false).unwrap();

        assert_eq!(
            plan.syscalls(),
            vec![
                TraceeSyscall::new3(LINUX_X86_64_SYS_DUP2, 900, 104, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_FCNTL, 104, LINUX_F_SETFD, LINUX_FD_CLOEXEC),
            ]
        );
    }

    #[test]
    fn tracee_plan_can_clear_cloexec_and_close_source() {
        let plan = TraceeInstallPlan::new(901, 6, false, true).unwrap();

        assert_eq!(
            plan.syscalls(),
            vec![
                TraceeSyscall::new3(LINUX_X86_64_SYS_DUP2, 901, 6, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_FCNTL, 6, LINUX_F_SETFD, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 901, 0, 0),
            ]
        );
    }

    #[test]
    fn socketpair_endpoint_install_preserves_overlapping_second_source() {
        let mut tracee = FakeTracee::with_returns([5, 0, 0, 4, 0, 0]);

        apply_tracee_socketpair_endpoint_installs(
            TraceeEndpointInstall {
                source_fd: 3,
                target_fd: 4,
                cloexec: false,
            },
            TraceeEndpointInstall {
                source_fd: 4,
                target_fd: 5,
                cloexec: false,
            },
            &mut tracee,
        )
        .unwrap();

        assert_eq!(
            tracee.calls,
            vec![
                TraceeSyscall::new3(LINUX_X86_64_SYS_DUP2, 4, 5, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_FCNTL, 5, LINUX_F_SETFD, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 4, 0, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_DUP2, 3, 4, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_FCNTL, 4, LINUX_F_SETFD, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 3, 0, 0),
            ]
        );
    }

    #[test]
    fn tracee_syscall_can_encode_six_linux_args() {
        assert_eq!(
            TraceeSyscall::new6(9, [1, 2, 3, 4, 5, 6]),
            TraceeSyscall {
                nr: 9,
                args: [1, 2, 3, 4, 5, 6],
            }
        );
    }

    #[test]
    fn tracee_scratch_mapping_uses_remote_mmap_and_munmap() {
        let mut tracee = FakeTracee::with_returns([0x7f00_1000, 0]);

        let mapping = TraceeScratchMapping::map(4096, &mut tracee).unwrap();
        mapping.unmap(&mut tracee).unwrap();

        assert_eq!(
            mapping,
            TraceeScratchMapping {
                addr: 0x7f00_1000,
                len: 4096,
            }
        );
        assert_eq!(
            tracee.calls,
            vec![
                TraceeSyscall::new6(
                    LINUX_X86_64_SYS_MMAP,
                    [
                        0,
                        4096,
                        LINUX_PROT_READ | LINUX_PROT_WRITE,
                        LINUX_MAP_PRIVATE | LINUX_MAP_ANONYMOUS,
                        (-1i64) as u64,
                        0,
                    ],
                ),
                TraceeSyscall::new6(LINUX_X86_64_SYS_MUNMAP, [0x7f00_1000, 4096, 0, 0, 0, 0]),
            ]
        );
    }

    #[test]
    fn tracee_scratch_mapping_rejects_zero_length_before_syscall() {
        let mut tracee = FakeTracee::with_returns([0x7f00_1000]);

        assert_eq!(
            TraceeScratchMapping::map(0, &mut tracee).unwrap_err(),
            FdError::TraceeInstallFailed("tracee scratch length is zero")
        );
        assert!(tracee.calls.is_empty());
    }

    #[test]
    fn tracee_scratch_mapping_rejects_failed_mmap_and_munmap() {
        let mut mmap_fail = FakeTracee::with_returns([-12]);
        assert_eq!(
            TraceeScratchMapping::map(4096, &mut mmap_fail).unwrap_err(),
            FdError::TraceeInstallFailed("tracee mmap failed")
        );

        let mut null_mmap = FakeTracee::with_returns([0]);
        assert_eq!(
            TraceeScratchMapping::map(4096, &mut null_mmap).unwrap_err(),
            FdError::TraceeInstallFailed("tracee mmap returned null")
        );

        let mapping = TraceeScratchMapping {
            addr: 0x7f00_1000,
            len: 4096,
        };
        let mut munmap_fail = FakeTracee::with_returns([-22]);
        assert_eq!(
            mapping.unmap(&mut munmap_fail).unwrap_err(),
            FdError::TraceeInstallFailed("tracee munmap failed")
        );
    }

    #[test]
    fn byte_backed_mapping_maps_writes_and_applies_final_protection() {
        let mapping = TraceeByteBackedMapping::new(
            0x7f00_0000,
            libc::PROT_READ | libc::PROT_EXEC,
            b"abcd".to_vec(),
        )
        .unwrap();
        let mut tracee = FakeTracee::with_returns([0x7f00_0000, 0]);
        let mut memory = FakeMemory::default();

        mapping.apply(&mut memory, &mut tracee).unwrap();

        assert_eq!(
            tracee.calls,
            vec![
                TraceeSyscall::new6(
                    LINUX_X86_64_SYS_MMAP,
                    [
                        0x7f00_0000,
                        4,
                        LINUX_PROT_READ | LINUX_PROT_WRITE,
                        LINUX_MAP_PRIVATE | LINUX_MAP_FIXED | LINUX_MAP_ANONYMOUS,
                        (-1i64) as u64,
                        0,
                    ],
                ),
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_MPROTECT,
                    0x7f00_0000,
                    4,
                    (libc::PROT_READ | libc::PROT_EXEC) as u64,
                ),
            ]
        );
        assert_eq!(memory.writes, vec![(0x7f00_0000, b"abcd".to_vec())]);
    }

    #[test]
    fn byte_backed_mapping_skips_mprotect_when_final_mapping_stays_writable() {
        let mapping = TraceeByteBackedMapping::new(
            0x7f00_1000,
            libc::PROT_READ | libc::PROT_WRITE,
            b"xy".to_vec(),
        )
        .unwrap();
        let mut tracee = FakeTracee::with_returns([0x7f00_1000]);
        let mut memory = FakeMemory::default();

        mapping.apply(&mut memory, &mut tracee).unwrap();

        assert_eq!(tracee.calls, vec![mapping.mmap_syscall()]);
        assert_eq!(memory.writes, vec![(0x7f00_1000, b"xy".to_vec())]);
    }

    #[test]
    fn byte_backed_mapping_unmaps_mappable_kernel_synthetic_collisions() {
        let mapping = TraceeByteBackedMapping::new(
            0x7f00_0000,
            libc::PROT_READ | libc::PROT_EXEC,
            b"abcdefghijkl".to_vec(),
        )
        .unwrap();
        let mut tracee = FakeTracee::with_returns_and_synthetic_ranges(
            [0, 0x7f00_0000, 0],
            vec![(0x7f00_0004, 0x7f00_0008)],
        );
        let mut memory = FakeMemory::default();

        mapping.apply(&mut memory, &mut tracee).unwrap();

        assert_eq!(
            tracee.calls,
            vec![
                TraceeSyscall::new6(LINUX_X86_64_SYS_MUNMAP, [0x7f00_0004, 4, 0, 0, 0, 0],),
                mapping.mmap_syscall(),
                mapping.mprotect_syscall(),
            ]
        );
        assert_eq!(memory.writes, vec![(0x7f00_0000, b"abcdefghijkl".to_vec())]);
    }

    #[test]
    fn byte_backed_mapping_rejects_invalid_inputs_before_syscalls() {
        assert_eq!(
            TraceeByteBackedMapping::new(0, libc::PROT_READ, b"x".to_vec()).unwrap_err(),
            FdError::TraceeInstallFailed("tracee mapping address is null")
        );
        assert_eq!(
            TraceeByteBackedMapping::new(0x1000, libc::PROT_READ, Vec::new()).unwrap_err(),
            FdError::TraceeInstallFailed("tracee mapping bytes are empty")
        );
        assert_eq!(
            TraceeByteBackedMapping::new(0x1000, -1, b"x".to_vec()).unwrap_err(),
            FdError::TraceeInstallFailed("tracee mapping protection is invalid")
        );
    }

    #[test]
    fn byte_backed_mapping_rejects_failed_syscalls_and_writes() {
        let mapping =
            TraceeByteBackedMapping::new(0x7f00_0000, libc::PROT_READ, b"abcd".to_vec()).unwrap();

        let mut mmap_fail = FakeTracee::with_returns([-12]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            mapping.apply(&mut memory, &mut mmap_fail).unwrap_err(),
            FdError::TraceeInstallFailed("tracee fixed mmap failed")
        );
        assert!(memory.writes.is_empty());

        let mut wrong_addr = FakeTracee::with_returns([0x7f00_1000]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            mapping.apply(&mut memory, &mut wrong_addr).unwrap_err(),
            FdError::TraceeInstallFailed("tracee fixed mmap returned wrong address")
        );
        assert!(memory.writes.is_empty());

        let mut write_fail = FakeTracee::with_returns([0x7f00_0000]);
        let mut memory = FakeMemory {
            writes: Vec::new(),
            fail: true,
        };
        assert_eq!(
            mapping.apply(&mut memory, &mut write_fail).unwrap_err(),
            FdError::TraceeInstallFailed("tracee source path write failed")
        );

        let mut mprotect_fail = FakeTracee::with_returns([0x7f00_0000, -22]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            mapping.apply(&mut memory, &mut mprotect_fail).unwrap_err(),
            FdError::TraceeInstallFailed("tracee mprotect failed")
        );
        assert_eq!(memory.writes, vec![(0x7f00_0000, b"abcd".to_vec())]);
    }

    #[test]
    fn synthetic_collision_helper_keeps_fixed_vsyscall_blocked() {
        let mut tracee = FakeTracee::default();
        let blocked = unmap_mappable_synthetic_collisions(
            0xffff_ffff_ff5f_f000,
            8192,
            &[(0xffff_ffff_ff60_0000, 0xffff_ffff_ff60_1000)],
            &mut tracee,
        )
        .unwrap();

        assert_eq!(
            blocked,
            vec![(0xffff_ffff_ff60_0000, 0xffff_ffff_ff60_1000)]
        );
        assert!(tracee.calls.is_empty());
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn clean_file_mapping_stages_path_maps_file_and_cleans_up() {
        let mapping = TraceeCleanFileMapping::new(
            0x7f00_2000,
            4096,
            libc::PROT_READ | libc::PROT_EXEC,
            Path::new("/lib/libc.so.6"),
            0x1000,
        )
        .unwrap();
        let mut tracee = FakeTracee::with_returns([0x9000, 901, 0x7f00_2000, 0, 0]);
        let mut memory = FakeMemory::default();

        mapping
            .apply_with_scratch(&mut memory, &mut tracee)
            .unwrap();

        assert_eq!(memory.writes, vec![(0x9000, b"/lib/libc.so.6\0".to_vec())]);
        assert_eq!(
            tracee.calls,
            vec![
                TraceeScratchMapping::mmap_syscall(15),
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_OPENAT,
                    LINUX_AT_FDCWD,
                    0x9000,
                    LINUX_O_CLOEXEC,
                ),
                TraceeSyscall::new6(
                    LINUX_X86_64_SYS_MMAP,
                    [
                        0x7f00_2000,
                        4096,
                        (libc::PROT_READ | libc::PROT_EXEC) as u64,
                        LINUX_MAP_PRIVATE | LINUX_MAP_FIXED,
                        901,
                        0x1000,
                    ],
                ),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 901, 0, 0),
                TraceeSyscall::new6(LINUX_X86_64_SYS_MUNMAP, [0x9000, 15, 0, 0, 0, 0]),
            ]
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn clean_file_mapping_rejects_invalid_inputs_and_failed_syscalls() {
        assert_eq!(
            TraceeCleanFileMapping::new(0, 1, libc::PROT_READ, Path::new("/x"), 0).unwrap_err(),
            FdError::TraceeInstallFailed("tracee file mapping address is null")
        );
        assert_eq!(
            TraceeCleanFileMapping::new(0x1000, 0, libc::PROT_READ, Path::new("/x"), 0)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee file mapping length is zero")
        );
        assert_eq!(
            TraceeCleanFileMapping::new(0x1000, 1, -1, Path::new("/x"), 0).unwrap_err(),
            FdError::TraceeInstallFailed("tracee file mapping protection is invalid")
        );
        assert_eq!(
            TraceeCleanFileMapping::new(0x1000, 1, libc::PROT_READ, Path::new(""), 0).unwrap_err(),
            FdError::TraceeInstallFailed("tracee file mapping path is empty")
        );

        let mapping =
            TraceeCleanFileMapping::new(0x7f00_2000, 4096, libc::PROT_READ, Path::new("/x"), 0)
                .unwrap();

        let mut open_fail = FakeTracee::with_returns([0x9000, -2, 0]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            mapping
                .apply_with_scratch(&mut memory, &mut open_fail)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee open clean file failed")
        );

        let mut mmap_fail = FakeTracee::with_returns([0x9000, 901, -12, 0, 0]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            mapping
                .apply_with_scratch(&mut memory, &mut mmap_fail)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee fixed file mmap failed")
        );

        let mut wrong_addr = FakeTracee::with_returns([0x9000, 901, 0x7f00_3000, 0, 0]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            mapping
                .apply_with_scratch(&mut memory, &mut wrong_addr)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee fixed file mmap returned wrong address")
        );

        let mut close_fail = FakeTracee::with_returns([0x9000, 901, 0x7f00_2000, -9, 0]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            mapping
                .apply_with_scratch(&mut memory, &mut close_fail)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee close clean file failed")
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn owned_shared_object_registry_builds_memfds_and_initializes_extents() {
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![
                KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                    host_pid: 4321,
                    model_pid: 7,
                    start: 0x7f00_3000,
                    len: 4,
                    prot: libc::PROT_READ | libc::PROT_WRITE,
                    kind: KboxlikeSharedMappingKind::Memfd,
                    path: Some("/memfd:chrome shared (deleted)".to_string()),
                    file_offset: 0,
                    dev: "00:01".to_string(),
                    inode: 2,
                },
                KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                    host_pid: 5000,
                    model_pid: 8,
                    start: 0x7f00_9000,
                    len: 4,
                    prot: libc::PROT_READ | libc::PROT_WRITE,
                    kind: KboxlikeSharedMappingKind::Memfd,
                    path: Some("/memfd:chrome shared (deleted)".to_string()),
                    file_offset: 0,
                    dev: "00:01".to_string(),
                    inode: 2,
                },
                KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                    host_pid: 4321,
                    model_pid: 7,
                    start: 0x7f00_4000,
                    len: 2,
                    prot: libc::PROT_READ,
                    kind: KboxlikeSharedMappingKind::Memfd,
                    path: Some("/memfd:chrome shared (deleted)".to_string()),
                    file_offset: 4,
                    dev: "00:01".to_string(),
                    inode: 2,
                },
                KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                    host_pid: 4321,
                    model_pid: 7,
                    start: 0x7f00_5000,
                    len: 4096,
                    prot: libc::PROT_READ,
                    kind: KboxlikeSharedMappingKind::Device,
                    path: Some("/dev/shm/chrome".to_string()),
                    file_offset: 0,
                    dev: "00:05".to_string(),
                    inode: 10,
                },
            ],
        };
        let dumps = vec![
            KboxlikeSharedMemoryDump {
                host_pid: 4321,
                model_pid: 7,
                start: 0x7f00_3000,
                kind: KboxlikeSharedMappingKind::Memfd,
                path: Some("/memfd:chrome shared (deleted)".to_string()),
                file_offset: 0,
                dev: "00:01".to_string(),
                inode: 2,
                bytes: b"abcd".to_vec(),
            },
            KboxlikeSharedMemoryDump {
                host_pid: 4321,
                model_pid: 7,
                start: 0x7f00_4000,
                kind: KboxlikeSharedMappingKind::Memfd,
                path: Some("/memfd:chrome shared (deleted)".to_string()),
                file_offset: 4,
                dev: "00:01".to_string(),
                inode: 2,
                bytes: b"ef".to_vec(),
            },
            KboxlikeSharedMemoryDump {
                host_pid: 4321,
                model_pid: 7,
                start: 0x7f00_5000,
                kind: KboxlikeSharedMappingKind::Device,
                path: Some("/dev/shm/chrome".to_string()),
                file_offset: 0,
                dev: "00:05".to_string(),
                inode: 10,
                bytes: vec![0xaa; 4096],
            },
        ];
        let mut factory = FakeSharedObjectBackingFactory {
            next_fd: 700,
            ..FakeSharedObjectBackingFactory::default()
        };

        let owned =
            build_owned_shared_object_registry_with(&restore, &dumps, &mut factory).unwrap();

        assert_eq!(
            owned.summary(),
            TraceeSharedObjectRegistryBuildSummary {
                created_objects: 2,
                initialized_extents: 3,
                skipped_unsupported_objects: 0,
            }
        );
        let key = TraceeSharedObjectKey {
            kind: KboxlikeSharedMappingKind::Memfd,
            path: Some("/memfd:chrome shared (deleted)".to_string()),
            dev: "00:01".to_string(),
            inode: 2,
        };
        assert_eq!(owned.registry().supervisor_fd(&key), Some(700));
        let device_key = TraceeSharedObjectKey {
            kind: KboxlikeSharedMappingKind::Device,
            path: Some("/dev/shm/chrome".to_string()),
            dev: "00:05".to_string(),
            inode: 10,
        };
        assert_eq!(owned.registry().supervisor_fd(&device_key), Some(701));
        assert_eq!(
            factory.created,
            vec!["chrome_shared".to_string(), "dev_shm_chrome".to_string()]
        );
        assert_eq!(factory.truncated, vec![(700, 6), (701, 4096)]);
        assert_eq!(
            factory.writes,
            vec![
                (700, 0, b"abcd".to_vec()),
                (700, 4, b"ef".to_vec()),
                (701, 0, vec![0xaa; 4096])
            ]
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn owned_shared_object_registry_rejects_missing_or_duplicate_extents() {
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![
                KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                    host_pid: 4321,
                    model_pid: 7,
                    start: 0x7f00_3000,
                    len: 4,
                    prot: libc::PROT_READ | libc::PROT_WRITE,
                    kind: KboxlikeSharedMappingKind::Memfd,
                    path: Some("/memfd:shared".to_string()),
                    file_offset: 0,
                    dev: "00:01".to_string(),
                    inode: 2,
                },
            ],
        };
        let mut factory = FakeSharedObjectBackingFactory {
            next_fd: 700,
            ..FakeSharedObjectBackingFactory::default()
        };

        assert_eq!(
            build_owned_shared_object_registry_with(&restore, &[], &mut factory).unwrap_err(),
            FdError::TraceeInstallFailed("missing shared memory dump extent")
        );

        let dump = KboxlikeSharedMemoryDump {
            host_pid: 4321,
            model_pid: 7,
            start: 0x7f00_3000,
            kind: KboxlikeSharedMappingKind::Memfd,
            path: Some("/memfd:shared".to_string()),
            file_offset: 0,
            dev: "00:01".to_string(),
            inode: 2,
            bytes: b"abcd".to_vec(),
        };
        let mut factory = FakeSharedObjectBackingFactory {
            next_fd: 700,
            ..FakeSharedObjectBackingFactory::default()
        };

        assert_eq!(
            build_owned_shared_object_registry_with(&restore, &[dump.clone(), dump], &mut factory)
                .unwrap_err(),
            FdError::TraceeInstallFailed("duplicate shared memory dump extent")
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn shared_fd_mapping_opens_supervisor_fd_maps_shared_and_cleans_up() {
        let mapping = TraceeSharedFdMapping::new(
            0x7f00_3000,
            4096,
            libc::PROT_READ | libc::PROT_WRITE,
            0x2000,
        )
        .unwrap();
        let mut tracee = FakeTracee::with_returns([0x9000, 901, 0x7f00_3000, 0, 0]);
        let mut memory = FakeMemory::default();

        mapping
            .apply_from_supervisor_fd_with_scratch(1234, 700, &mut memory, &mut tracee)
            .unwrap();

        assert_eq!(
            memory.writes,
            vec![(0x9000, b"/proc/1234/fd/700\0".to_vec())]
        );
        assert_eq!(
            tracee.calls,
            vec![
                TraceeScratchMapping::mmap_syscall(18),
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_OPENAT,
                    LINUX_AT_FDCWD,
                    0x9000,
                    LINUX_O_CLOEXEC | LINUX_O_RDWR,
                ),
                TraceeSyscall::new6(
                    LINUX_X86_64_SYS_MMAP,
                    [
                        0x7f00_3000,
                        4096,
                        (libc::PROT_READ | libc::PROT_WRITE) as u64,
                        LINUX_MAP_SHARED | LINUX_MAP_FIXED,
                        901,
                        0x2000,
                    ],
                ),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 901, 0, 0),
                TraceeSyscall::new6(LINUX_X86_64_SYS_MUNMAP, [0x9000, 18, 0, 0, 0, 0]),
            ]
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn shared_fd_mapping_rejects_invalid_inputs_and_failed_syscalls() {
        assert_eq!(
            TraceeSharedFdMapping::new(0, 1, libc::PROT_READ, 0).unwrap_err(),
            FdError::TraceeInstallFailed("tracee shared mapping address is null")
        );
        assert_eq!(
            TraceeSharedFdMapping::new(0x1000, 0, libc::PROT_READ, 0).unwrap_err(),
            FdError::TraceeInstallFailed("tracee shared mapping length is zero")
        );
        assert_eq!(
            TraceeSharedFdMapping::new(0x1000, 1, -1, 0).unwrap_err(),
            FdError::TraceeInstallFailed("tracee shared mapping protection is invalid")
        );

        let mapping = TraceeSharedFdMapping::new(0x7f00_3000, 4096, libc::PROT_READ, 0).unwrap();

        let mut open_fail = FakeTracee::with_returns([0x9000, -2, 0]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            mapping
                .apply_from_supervisor_fd_with_scratch(1234, 700, &mut memory, &mut open_fail)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee open supervisor fd failed")
        );

        let mut mmap_fail = FakeTracee::with_returns([0x9000, 901, -12, 0, 0]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            mapping
                .apply_from_supervisor_fd_with_scratch(1234, 700, &mut memory, &mut mmap_fail)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee fixed shared mmap failed")
        );

        let mut wrong_addr = FakeTracee::with_returns([0x9000, 901, 0x7f00_4000, 0, 0]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            mapping
                .apply_from_supervisor_fd_with_scratch(1234, 700, &mut memory, &mut wrong_addr)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee fixed shared mmap returned wrong address")
        );

        let mut close_fail = FakeTracee::with_returns([0x9000, 901, 0x7f00_3000, -9, 0]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            mapping
                .apply_from_supervisor_fd_with_scratch(1234, 700, &mut memory, &mut close_fail)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee close shared fd failed")
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn materialized_memory_restore_remaps_registered_shared_objects() {
        let shared_action = KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
            host_pid: 4321,
            model_pid: 7,
            start: 0x7f00_3000,
            len: 4096,
            prot: libc::PROT_READ | libc::PROT_WRITE,
            kind: KboxlikeSharedMappingKind::Memfd,
            path: Some("/memfd:shared".to_string()),
            file_offset: 0x2000,
            dev: "00:00".to_string(),
            inode: 2,
        };
        let key = TraceeSharedObjectKey::from_action(&shared_action).unwrap();
        let mut shared = TraceeSharedObjectRegistry::new();
        shared.register(key, 700).unwrap();
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![shared_action],
        };
        let mut tracee = FakeTracee::with_returns([0x9000, 901, 0x7f00_3000, 0, 0]);
        let mut memory = FakeMemory::default();

        let summary = apply_materialized_memory_restore_for_tracee_with_shared_objects(
            &restore,
            4321,
            1234,
            &shared,
            &mut memory,
            &mut tracee,
        )
        .unwrap();

        assert_eq!(
            summary,
            TraceeMemoryRestoreSummary {
                byte_backed_applied: 0,
                clean_file_remapped: 0,
                shared_object_remapped: 1,
                skipped_no_mapping: 0,
                deferred_unsupported: 0,
                other_tracee: 0,
            }
        );
        assert_eq!(
            memory.writes,
            vec![(0x9000, b"/proc/1234/fd/700\0".to_vec())]
        );
        assert_eq!(
            tracee.calls,
            vec![
                TraceeScratchMapping::mmap_syscall(18),
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_OPENAT,
                    LINUX_AT_FDCWD,
                    0x9000,
                    LINUX_O_CLOEXEC | LINUX_O_RDWR,
                ),
                TraceeSyscall::new6(
                    LINUX_X86_64_SYS_MMAP,
                    [
                        0x7f00_3000,
                        4096,
                        (libc::PROT_READ | libc::PROT_WRITE) as u64,
                        LINUX_MAP_SHARED | LINUX_MAP_FIXED,
                        901,
                        0x2000,
                    ],
                ),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 901, 0, 0),
                TraceeSyscall::new6(LINUX_X86_64_SYS_MUNMAP, [0x9000, 18, 0, 0, 0, 0]),
            ]
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn materialized_memory_restore_applies_byte_backed_actions_for_one_tracee() {
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![
                KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                    host_pid: 4321,
                    model_pid: 7,
                    start: 0x7f00_0000,
                    prot: libc::PROT_READ,
                    bytes: b"abcd".to_vec(),
                    source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
                },
                KboxlikeMaterializedMemoryRestoreAction::SkipInaccessible {
                    host_pid: 4321,
                    model_pid: 7,
                    start: 0x7f00_1000,
                    len: 4096,
                    prot: libc::PROT_NONE,
                },
                KboxlikeMaterializedMemoryRestoreAction::RemapCleanFile {
                    host_pid: 4321,
                    model_pid: 7,
                    start: 0x7f00_2000,
                    len: 4096,
                    prot: libc::PROT_READ,
                    path: PathBuf::from("/lib/libc.so.6"),
                    file_offset: 0,
                    dev: "00:00".to_string(),
                    inode: 1,
                },
                KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                    host_pid: 4321,
                    model_pid: 7,
                    start: 0x7f00_3000,
                    len: 4096,
                    prot: libc::PROT_READ | libc::PROT_WRITE,
                    kind: KboxlikeSharedMappingKind::Memfd,
                    path: Some("/memfd:shared".to_string()),
                    file_offset: 0,
                    dev: "00:00".to_string(),
                    inode: 2,
                },
                KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                    host_pid: 5000,
                    model_pid: 9,
                    start: 0x7f00_4000,
                    prot: libc::PROT_READ,
                    bytes: b"other".to_vec(),
                    source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
                },
            ],
        };
        let mut tracee =
            FakeTracee::with_returns([0x7f00_0000, 0, 0x7f00_1000, 0x9000, 901, 0x7f00_2000, 0, 0]);
        let mut memory = FakeMemory::default();

        let summary =
            apply_materialized_memory_restore_for_tracee(&restore, 4321, &mut memory, &mut tracee)
                .unwrap();

        assert_eq!(
            summary,
            TraceeMemoryRestoreSummary {
                byte_backed_applied: 1,
                clean_file_remapped: 1,
                shared_object_remapped: 0,
                skipped_no_mapping: 1,
                deferred_unsupported: 1,
                other_tracee: 1,
            }
        );
        assert_eq!(
            memory.writes,
            vec![
                (0x7f00_0000, b"abcd".to_vec()),
                (0x9000, b"/lib/libc.so.6\0".to_vec()),
            ]
        );
        assert_eq!(
            tracee.calls,
            vec![
                TraceeSyscall::new6(
                    LINUX_X86_64_SYS_MMAP,
                    [
                        0x7f00_0000,
                        4,
                        LINUX_PROT_READ | LINUX_PROT_WRITE,
                        LINUX_MAP_PRIVATE | LINUX_MAP_FIXED | LINUX_MAP_ANONYMOUS,
                        (-1i64) as u64,
                        0,
                    ],
                ),
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_MPROTECT,
                    0x7f00_0000,
                    4,
                    libc::PROT_READ as u64
                ),
                TraceeSyscall::new6(
                    LINUX_X86_64_SYS_MMAP,
                    [
                        0x7f00_1000,
                        4096,
                        libc::PROT_NONE as u64,
                        LINUX_MAP_PRIVATE | LINUX_MAP_FIXED | LINUX_MAP_ANONYMOUS,
                        (-1i64) as u64,
                        0,
                    ],
                ),
                TraceeScratchMapping::mmap_syscall(15),
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_OPENAT,
                    LINUX_AT_FDCWD,
                    0x9000,
                    LINUX_O_CLOEXEC,
                ),
                TraceeSyscall::new6(
                    LINUX_X86_64_SYS_MMAP,
                    [
                        0x7f00_2000,
                        4096,
                        libc::PROT_READ as u64,
                        LINUX_MAP_PRIVATE | LINUX_MAP_FIXED,
                        901,
                        0,
                    ],
                ),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 901, 0, 0),
                TraceeSyscall::new6(LINUX_X86_64_SYS_MUNMAP, [0x9000, 15, 0, 0, 0, 0]),
            ]
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn materialized_memory_restore_rejects_invalid_tracee_and_replay_failures() {
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                host_pid: 4321,
                model_pid: 7,
                start: 0x7f00_0000,
                prot: libc::PROT_READ,
                bytes: b"abcd".to_vec(),
                source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
            }],
        };
        let mut tracee = FakeTracee::default();
        let mut memory = FakeMemory::default();

        assert_eq!(
            apply_materialized_memory_restore_for_tracee(&restore, 0, &mut memory, &mut tracee)
                .unwrap_err(),
            FdError::TraceeInstallFailed("invalid tracee pid")
        );

        let mut tracee = FakeTracee::with_returns([-12]);
        let mut memory = FakeMemory::default();
        assert_eq!(
            apply_materialized_memory_restore_for_tracee(&restore, 4321, &mut memory, &mut tracee)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee fixed mmap failed")
        );
        assert!(memory.writes.is_empty());
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn thread_register_restore_writes_matching_tracee_regs() {
        let mut target_regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        target_regs.rip = 0x7f00_3000;
        target_regs.rsp = 0x7fff_0000;
        let mut other_regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        other_regs.rip = 0x1234;
        let threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 1111,
                model_pid: 1,
                model_thread_id: 1,
                regs: other_regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 4321,
                model_pid: 7,
                model_thread_id: 7,
                regs: target_regs,
            },
        ];
        let mut writer = FakeRegisterWriter::default();

        let summary =
            apply_thread_register_restore_for_tracee(&threads, 4321, &mut writer).unwrap();

        assert_eq!(
            summary,
            TraceeRegisterRestoreSummary {
                registers_restored: 1,
                other_tracee: 1,
            }
        );
        assert_eq!(writer.writes.len(), 1);
        assert_eq!(writer.writes[0].rip, 0x7f00_3000);
        assert_eq!(writer.writes[0].rsp, 0x7fff_0000);
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn thread_register_restore_converts_kernel_restart_result_to_eintr() {
        let mut regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        regs.rip = 0x7f00_3000;
        regs.rax = (-512i64) as u64;
        let threads = vec![KboxlikeThreadSnapshot {
            host_pid: 4321,
            model_pid: 7,
            model_thread_id: 7,
            regs,
        }];
        let mut writer = FakeRegisterWriter::default();

        apply_thread_register_restore_for_tracee(&threads, 4321, &mut writer).unwrap();

        assert_eq!(writer.writes.len(), 1);
        assert_eq!(writer.writes[0].rip, 0x7f00_3000);
        assert_eq!(writer.writes[0].rax, (-(libc::EINTR as i64)) as u64);
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn thread_register_restore_rejects_missing_duplicate_and_writer_failure() {
        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let threads = vec![KboxlikeThreadSnapshot {
            host_pid: 4321,
            model_pid: 7,
            model_thread_id: 1,
            regs,
        }];

        let mut writer = FakeRegisterWriter::default();
        assert_eq!(
            apply_thread_register_restore_for_tracee(&threads, 0, &mut writer).unwrap_err(),
            FdError::TraceeInstallFailed("invalid tracee pid")
        );
        assert_eq!(
            apply_thread_register_restore_for_tracee(&threads, 5000, &mut writer).unwrap_err(),
            FdError::TraceeInstallFailed("missing tracee register snapshot")
        );

        let duplicate_threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 4321,
                model_pid: 7,
                model_thread_id: 1,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 4321,
                model_pid: 7,
                model_thread_id: 2,
                regs,
            },
        ];
        assert_eq!(
            apply_thread_register_restore_for_tracee(&duplicate_threads, 4321, &mut writer)
                .unwrap_err(),
            FdError::TraceeInstallFailed("duplicate tracee register snapshot")
        );

        let mut failing_writer = FakeRegisterWriter {
            fail: true,
            ..FakeRegisterWriter::default()
        };
        assert_eq!(
            apply_thread_register_restore_for_tracee(&threads, 4321, &mut failing_writer)
                .unwrap_err(),
            FdError::TraceeInstallFailed("ptrace setregs failed")
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn thread_kernel_state_restore_applies_matching_tracee_state() {
        let states = vec![
            KboxlikeThreadKernelStateSnapshot {
                host_pid: 1111,
                model_pid: 7,
                model_thread_id: 1,
                clear_child_tid: None,
                robust_list_head: Some(0x7100),
                robust_list_len: 24,
            },
            KboxlikeThreadKernelStateSnapshot {
                host_pid: 4321,
                model_pid: 7,
                model_thread_id: 2,
                clear_child_tid: Some(0x7000),
                robust_list_head: Some(0x8000),
                robust_list_len: 24,
            },
        ];
        let mut tracee = FakeTracee::default();

        let summary =
            apply_thread_kernel_state_restore_for_tracee(&states, 4321, &mut tracee).unwrap();

        assert_eq!(
            summary,
            TraceeKernelStateRestoreSummary {
                clear_child_tid_applied: 1,
                robust_list_applied: 1,
                other_tracee: 1,
            }
        );
        assert_eq!(
            tracee.calls,
            vec![
                TraceeSyscall::new3(LINUX_X86_64_SYS_SET_TID_ADDRESS, 0x7000, 0, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_SET_ROBUST_LIST, 0x8000, 24, 0),
            ]
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn thread_kernel_state_restore_rejects_missing_duplicate_and_failed_syscall() {
        let states = vec![KboxlikeThreadKernelStateSnapshot {
            host_pid: 4321,
            model_pid: 7,
            model_thread_id: 1,
            clear_child_tid: Some(0x7000),
            robust_list_head: Some(0x8000),
            robust_list_len: 24,
        }];

        let mut tracee = FakeTracee::default();
        assert_eq!(
            apply_thread_kernel_state_restore_for_tracee(&states, 0, &mut tracee).unwrap_err(),
            FdError::TraceeInstallFailed("invalid tracee pid")
        );
        assert_eq!(
            apply_thread_kernel_state_restore_for_tracee(&states, 5000, &mut tracee).unwrap_err(),
            FdError::TraceeInstallFailed("missing tracee kernel state snapshot")
        );

        let duplicate_states = vec![
            KboxlikeThreadKernelStateSnapshot {
                host_pid: 4321,
                model_pid: 7,
                model_thread_id: 1,
                clear_child_tid: Some(0x7000),
                robust_list_head: None,
                robust_list_len: 0,
            },
            KboxlikeThreadKernelStateSnapshot {
                host_pid: 4321,
                model_pid: 7,
                model_thread_id: 2,
                clear_child_tid: None,
                robust_list_head: Some(0x8000),
                robust_list_len: 24,
            },
        ];
        assert_eq!(
            apply_thread_kernel_state_restore_for_tracee(&duplicate_states, 4321, &mut tracee)
                .unwrap_err(),
            FdError::TraceeInstallFailed("duplicate tracee kernel state snapshot")
        );

        let mut clear_tid_fails = FakeTracee::with_returns([-22]);
        assert_eq!(
            apply_thread_kernel_state_restore_for_tracee(&states, 4321, &mut clear_tid_fails)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee set_tid_address failed")
        );

        let mut robust_fails = FakeTracee::with_returns([4321, -22]);
        assert_eq!(
            apply_thread_kernel_state_restore_for_tracee(&states, 4321, &mut robust_fails)
                .unwrap_err(),
            FdError::TraceeInstallFailed("tracee set_robust_list failed")
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn stopped_tracee_restore_applies_memory_before_registers() {
        let mut regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        regs.rip = 0x7f00_3000;
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                host_pid: 4321,
                model_pid: 7,
                start: 0x7f00_3000,
                prot: libc::PROT_READ,
                bytes: b"code".to_vec(),
                source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
            }],
        };
        let threads = vec![KboxlikeThreadSnapshot {
            host_pid: 4321,
            model_pid: 7,
            model_thread_id: 1,
            regs,
        }];
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([0x7f00_3000, 0]);
        let mut register_writer = FakeRegisterWriter::default();

        let summary = apply_stopped_tracee_restore(
            &restore,
            &threads,
            4321,
            &mut memory,
            &mut tracee,
            &mut register_writer,
        )
        .unwrap();

        assert_eq!(
            summary,
            TraceeRestoreSummary {
                memory: TraceeMemoryRestoreSummary {
                    byte_backed_applied: 1,
                    clean_file_remapped: 0,
                    shared_object_remapped: 0,
                    skipped_no_mapping: 0,
                    deferred_unsupported: 0,
                    other_tracee: 0,
                },
                registers: TraceeRegisterRestoreSummary {
                    registers_restored: 1,
                    other_tracee: 0,
                },
            }
        );
        assert_eq!(memory.writes, vec![(0x7f00_3000, b"code".to_vec())]);
        assert_eq!(register_writer.writes.len(), 1);
        assert_eq!(register_writer.writes[0].rip, 0x7f00_3000);
        assert_eq!(
            tracee.calls,
            vec![
                TraceeByteBackedMapping::new(0x7f00_3000, libc::PROT_READ, b"code".to_vec())
                    .unwrap()
                    .mmap_syscall(),
                TraceeByteBackedMapping::new(0x7f00_3000, libc::PROT_READ, b"code".to_vec())
                    .unwrap()
                    .mprotect_syscall(),
            ]
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn stopped_tracee_restore_does_not_write_registers_after_memory_failure() {
        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                host_pid: 4321,
                model_pid: 7,
                start: 0x7f00_3000,
                prot: libc::PROT_READ,
                bytes: b"code".to_vec(),
                source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
            }],
        };
        let threads = vec![KboxlikeThreadSnapshot {
            host_pid: 4321,
            model_pid: 7,
            model_thread_id: 1,
            regs,
        }];
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([-12]);
        let mut register_writer = FakeRegisterWriter::default();

        assert_eq!(
            apply_stopped_tracee_restore(
                &restore,
                &threads,
                4321,
                &mut memory,
                &mut tracee,
                &mut register_writer,
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("tracee fixed mmap failed")
        );
        assert!(memory.writes.is_empty());
        assert!(register_writer.writes.is_empty());
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn stopped_tracee_restore_set_builds_shared_objects_once_and_restores_in_pid_order() {
        let mut regs_a: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        regs_a.rip = 0x7f00_3000;
        let mut regs_b: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        regs_b.rip = 0x7f00_3000;
        let shared_action_for =
            |host_pid| KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                host_pid,
                model_pid: host_pid as u64,
                start: 0x7f00_3000,
                len: 4,
                prot: libc::PROT_READ,
                kind: KboxlikeSharedMappingKind::Memfd,
                path: Some("/memfd:kboxlike-set-shared".to_string()),
                file_offset: 0,
                dev: "00:00".to_string(),
                inode: 99,
            };
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![shared_action_for(2002), shared_action_for(2001)],
        };
        let threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 2002,
                model_pid: 2002,
                model_thread_id: 2002,
                regs: regs_b,
            },
            KboxlikeThreadSnapshot {
                host_pid: 2001,
                model_pid: 2001,
                model_thread_id: 2001,
                regs: regs_a,
            },
        ];
        let dumps = vec![KboxlikeSharedMemoryDump {
            host_pid: 2001,
            model_pid: 2001,
            start: 0x7f00_3000,
            kind: KboxlikeSharedMappingKind::Memfd,
            path: Some("/memfd:kboxlike-set-shared".to_string()),
            file_offset: 0,
            dev: "00:00".to_string(),
            inode: 99,
            bytes: b"code".to_vec(),
        }];
        let mut factory = FakeRestoreAccessFactory::default();
        factory
            .returns_by_pid
            .insert(2001, vec![0x9000, 901, 0x7f00_3000, 0, 0]);
        factory
            .returns_by_pid
            .insert(2002, vec![0x9000, 902, 0x7f00_3000, 0, 0]);

        let summary =
            apply_stopped_tracee_restore_set(&restore, &threads, &dumps, 1234, &mut factory)
                .unwrap();

        assert_eq!(factory.requested, vec![2001, 2002]);
        assert_eq!(
            summary,
            TraceeRestoreSetSummary {
                tracees_restored: 2,
                shared_objects: TraceeSharedObjectRegistryBuildSummary {
                    created_objects: 1,
                    initialized_extents: 1,
                    skipped_unsupported_objects: 0,
                },
                memory: TraceeMemoryRestoreSummary {
                    byte_backed_applied: 0,
                    clean_file_remapped: 0,
                    shared_object_remapped: 2,
                    skipped_no_mapping: 0,
                    deferred_unsupported: 0,
                    other_tracee: 2,
                },
                registers: TraceeRegisterRestoreSummary {
                    registers_restored: 2,
                    other_tracee: 2,
                },
            }
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn replacement_tracee_set_creation_groups_threads_by_model_process() {
        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 2222,
                model_pid: 7,
                model_thread_id: 2,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 3333,
                model_pid: 8,
                model_thread_id: 3,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 1111,
                model_pid: 7,
                model_thread_id: 1,
                regs,
            },
        ];
        let mut factory = FakeStoppedTraceeReplacementFactory {
            returns: VecDeque::from([
                Ok(BTreeMap::from([(1, 7001), (2, 7002)])),
                Ok(BTreeMap::from([(3, 8001)])),
            ]),
            ..FakeStoppedTraceeReplacementFactory::default()
        };

        let created = create_stopped_replacement_tracee_set(&threads, &mut factory).unwrap();

        assert_eq!(factory.calls, vec![(7, vec![1, 2]), (8, vec![3])]);
        assert_eq!(
            created,
            TraceeReplacementThreadGroupCreateSet {
                replacement_host_pids: BTreeMap::from([(1, 7001), (2, 7002), (3, 8001)]),
                summary: TraceeReplacementThreadGroupCreateSummary {
                    process_groups: 2,
                    tracees_requested: 3,
                    tracees_created: 3,
                },
            }
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn replacement_tracee_set_creation_rejects_incomplete_or_ambiguous_groups() {
        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 1111,
                model_pid: 7,
                model_thread_id: 1,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 2222,
                model_pid: 7,
                model_thread_id: 2,
                regs,
            },
        ];

        let mut missing = FakeStoppedTraceeReplacementFactory {
            returns: VecDeque::from([Ok(BTreeMap::from([(1, 7001)]))]),
            ..FakeStoppedTraceeReplacementFactory::default()
        };
        assert_eq!(
            create_stopped_replacement_tracee_set(&threads, &mut missing).unwrap_err(),
            FdError::TraceeInstallFailed("replacement group missing model thread id")
        );

        let mut unknown = FakeStoppedTraceeReplacementFactory {
            returns: VecDeque::from([Ok(BTreeMap::from([(1, 7001), (2, 7002), (9, 9001)]))]),
            ..FakeStoppedTraceeReplacementFactory::default()
        };
        assert_eq!(
            create_stopped_replacement_tracee_set(&threads, &mut unknown).unwrap_err(),
            FdError::TraceeInstallFailed("replacement group returned unknown model thread id")
        );

        let mut invalid_pid = FakeStoppedTraceeReplacementFactory {
            returns: VecDeque::from([Ok(BTreeMap::from([(1, 7001), (2, 0)]))]),
            ..FakeStoppedTraceeReplacementFactory::default()
        };
        assert_eq!(
            create_stopped_replacement_tracee_set(&threads, &mut invalid_pid).unwrap_err(),
            FdError::TraceeInstallFailed("invalid replacement tracee pid")
        );

        let mut duplicate_pid = FakeStoppedTraceeReplacementFactory {
            returns: VecDeque::from([Ok(BTreeMap::from([(1, 7001), (2, 7001)]))]),
            ..FakeStoppedTraceeReplacementFactory::default()
        };
        assert_eq!(
            create_stopped_replacement_tracee_set(&threads, &mut duplicate_pid).unwrap_err(),
            FdError::TraceeInstallFailed("duplicate replacement tracee pid")
        );

        let duplicate_threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 1111,
                model_pid: 7,
                model_thread_id: 1,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 2222,
                model_pid: 8,
                model_thread_id: 1,
                regs,
            },
        ];
        let mut factory = FakeStoppedTraceeReplacementFactory::default();
        assert_eq!(
            create_stopped_replacement_tracee_set(&duplicate_threads, &mut factory).unwrap_err(),
            FdError::TraceeInstallFailed("duplicate tracee model thread id")
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn linux_replacement_factory_rejects_empty_groups_before_forking() {
        let mut factory = LinuxStoppedTraceeReplacementFactory::default();

        assert_eq!(
            factory
                .create_stopped_replacement_group(7, &[])
                .unwrap_err(),
            FdError::TraceeInstallFailed("replacement group has no threads")
        );
        assert!(factory.created_host_pids().is_empty());
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn thread_group_memory_normalize_assigns_one_memory_owner_per_model_process() {
        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 2222,
                model_pid: 7,
                model_thread_id: 2,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 1111,
                model_pid: 7,
                model_thread_id: 1,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 3333,
                model_pid: 8,
                model_thread_id: 3,
                regs,
            },
        ];
        let duplicate_thread_group_action =
            |host_pid| KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                host_pid,
                model_pid: 7,
                start: 0x7f00_3000,
                prot: libc::PROT_READ,
                bytes: b"code".to_vec(),
                source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
            };
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![
                duplicate_thread_group_action(2222),
                duplicate_thread_group_action(1111),
                KboxlikeMaterializedMemoryRestoreAction::RemapCleanFile {
                    host_pid: 3333,
                    model_pid: 8,
                    start: 0x7f00_4000,
                    len: 0x1000,
                    prot: libc::PROT_READ,
                    path: PathBuf::from("/usr/bin/node"),
                    file_offset: 0,
                    dev: "08:01".to_string(),
                    inode: 55,
                },
            ],
        };
        let duplicate_thread_group_dump = |host_pid| KboxlikeSharedMemoryDump {
            host_pid,
            model_pid: 7,
            start: 0x7f00_5000,
            kind: KboxlikeSharedMappingKind::Memfd,
            path: Some("/memfd:thread-group".to_string()),
            file_offset: 0,
            dev: "00:01".to_string(),
            inode: 77,
            bytes: b"shared".to_vec(),
        };
        let dumps = vec![
            duplicate_thread_group_dump(2222),
            duplicate_thread_group_dump(1111),
            KboxlikeSharedMemoryDump {
                host_pid: 3333,
                model_pid: 8,
                start: 0x7f00_6000,
                kind: KboxlikeSharedMappingKind::Memfd,
                path: Some("/memfd:other-process".to_string()),
                file_offset: 0,
                dev: "00:01".to_string(),
                inode: 88,
                bytes: b"other".to_vec(),
            },
        ];

        let normalized = normalize_thread_group_memory_restore(&restore, &threads, &dumps).unwrap();

        assert_eq!(
            normalized.memory_owner_host_pids,
            BTreeMap::from([(7, 1111), (8, 3333)])
        );
        assert_eq!(
            normalized.summary,
            TraceeThreadGroupMemoryNormalizeSummary {
                process_groups: 2,
                memory_actions_retained: 2,
                memory_actions_reassigned_to_owner: 1,
                duplicate_memory_actions_removed: 1,
                shared_dumps_retained: 2,
                shared_dumps_reassigned_to_owner: 1,
                duplicate_shared_dumps_removed: 1,
            }
        );
        assert_eq!(normalized.restore.actions.len(), 2);
        assert_eq!(
            normalized
                .restore
                .actions
                .iter()
                .map(materialized_action_host_pid)
                .collect::<Vec<_>>(),
            vec![1111, 3333]
        );
        assert_eq!(
            normalized
                .shared_dumps
                .iter()
                .map(|dump| dump.host_pid)
                .collect::<Vec<_>>(),
            vec![1111, 3333]
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn thread_group_memory_normalize_rejects_inconsistent_restore_metadata() {
        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let threads = vec![KboxlikeThreadSnapshot {
            host_pid: 1111,
            model_pid: 7,
            model_thread_id: 1,
            regs,
        }];

        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                host_pid: 1111,
                model_pid: 8,
                start: 0x7f00_3000,
                prot: libc::PROT_READ,
                bytes: b"code".to_vec(),
                source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
            }],
        };
        assert_eq!(
            normalize_thread_group_memory_restore(&restore, &threads, &[]).unwrap_err(),
            FdError::TraceeInstallFailed("memory restore action model pid mismatch")
        );

        let duplicate_threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 1111,
                model_pid: 7,
                model_thread_id: 1,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 2222,
                model_pid: 7,
                model_thread_id: 1,
                regs,
            },
        ];
        assert_eq!(
            normalize_thread_group_memory_restore(
                &KboxlikeMaterializedMemoryRestore { actions: vec![] },
                &duplicate_threads,
                &[],
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("duplicate tracee model thread id")
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn replacement_pid_remap_rewrites_restore_inputs_by_model_thread_id() {
        let mut regs_a: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        regs_a.rip = 0x7f00_3000;
        let mut regs_b: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        regs_b.rip = 0x7f00_4000;
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![
                KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                    host_pid: 1111,
                    model_pid: 7,
                    start: 0x7f00_3000,
                    prot: libc::PROT_READ,
                    bytes: b"code-a".to_vec(),
                    source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
                },
                KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                    host_pid: 2222,
                    model_pid: 7,
                    start: 0x7f00_4000,
                    len: 6,
                    prot: libc::PROT_READ,
                    kind: KboxlikeSharedMappingKind::Memfd,
                    path: Some("/memfd:kboxlike-remap".to_string()),
                    file_offset: 0,
                    dev: "00:00".to_string(),
                    inode: 44,
                },
            ],
        };
        let threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 1111,
                model_pid: 7,
                model_thread_id: 1,
                regs: regs_a,
            },
            KboxlikeThreadSnapshot {
                host_pid: 2222,
                model_pid: 7,
                model_thread_id: 2,
                regs: regs_b,
            },
        ];
        let dumps = vec![KboxlikeSharedMemoryDump {
            host_pid: 2222,
            model_pid: 7,
            start: 0x7f00_4000,
            kind: KboxlikeSharedMappingKind::Memfd,
            path: Some("/memfd:kboxlike-remap".to_string()),
            file_offset: 0,
            dev: "00:00".to_string(),
            inode: 44,
            bytes: b"code-b".to_vec(),
        }];
        let replacement_host_pids = BTreeMap::from([(1, 7001), (2, 8001)]);

        let remapped = remap_stopped_tracee_restore_set_to_replacement_pids(
            &restore,
            &threads,
            &dumps,
            &replacement_host_pids,
        )
        .unwrap();

        assert_eq!(
            remapped.summary,
            TraceeReplacementPidRemapSummary {
                threads_remapped: 2,
                memory_actions_remapped: 2,
                shared_dumps_remapped: 1,
            }
        );
        assert_eq!(
            remapped
                .threads
                .iter()
                .map(|thread| {
                    (
                        thread.model_pid,
                        thread.model_thread_id,
                        thread.host_pid,
                        thread.regs.rip,
                    )
                })
                .collect::<Vec<_>>(),
            vec![(7, 1, 7001, 0x7f00_3000), (7, 2, 8001, 0x7f00_4000)]
        );
        assert_eq!(
            materialized_action_host_pid(&remapped.restore.actions[0]),
            7001
        );
        assert_eq!(
            materialized_action_model_pid(&remapped.restore.actions[0]),
            7
        );
        assert_eq!(
            materialized_action_host_pid(&remapped.restore.actions[1]),
            8001
        );
        assert_eq!(
            materialized_action_model_pid(&remapped.restore.actions[1]),
            7
        );
        assert_eq!(remapped.shared_dumps[0].host_pid, 8001);
        assert_eq!(remapped.shared_dumps[0].model_pid, 7);
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn replacement_pid_remap_rewrites_kernel_state_by_model_thread_id() {
        let states = vec![
            KboxlikeThreadKernelStateSnapshot {
                host_pid: 1111,
                model_pid: 7,
                model_thread_id: 1,
                clear_child_tid: Some(0x7000),
                robust_list_head: Some(0x7100),
                robust_list_len: 24,
            },
            KboxlikeThreadKernelStateSnapshot {
                host_pid: 2222,
                model_pid: 7,
                model_thread_id: 2,
                clear_child_tid: None,
                robust_list_head: Some(0x8100),
                robust_list_len: 24,
            },
        ];
        let replacement_host_pids = BTreeMap::from([(1, 7001), (2, 8001)]);

        let remapped =
            remap_thread_kernel_states_to_replacement_pids(&states, &replacement_host_pids)
                .unwrap();

        assert_eq!(
            remapped
                .iter()
                .map(|state| {
                    (
                        state.host_pid,
                        state.model_pid,
                        state.model_thread_id,
                        state.clear_child_tid,
                        state.robust_list_head,
                        state.robust_list_len,
                    )
                })
                .collect::<Vec<_>>(),
            vec![
                (7001, 7, 1, Some(0x7000), Some(0x7100), 24),
                (8001, 7, 2, None, Some(0x8100), 24),
            ]
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn replacement_pid_remap_rejects_ambiguous_or_missing_replacements() {
        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                host_pid: 1111,
                model_pid: 7,
                start: 0x7f00_3000,
                prot: libc::PROT_READ,
                bytes: b"code".to_vec(),
                source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
            }],
        };
        let threads = vec![KboxlikeThreadSnapshot {
            host_pid: 1111,
            model_pid: 7,
            model_thread_id: 1,
            regs,
        }];

        assert_eq!(
            remap_stopped_tracee_restore_set_to_replacement_pids(
                &restore,
                &threads,
                &[],
                &BTreeMap::new(),
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("missing replacement tracee pid")
        );

        assert_eq!(
            remap_stopped_tracee_restore_set_to_replacement_pids(
                &restore,
                &threads,
                &[],
                &BTreeMap::from([(1, 0)]),
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("invalid replacement tracee pid")
        );

        assert_eq!(
            remap_stopped_tracee_restore_set_to_replacement_pids(
                &restore,
                &threads,
                &[],
                &BTreeMap::from([(1, 7001), (2, 7001)]),
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("duplicate replacement tracee pid")
        );

        let duplicate_threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 1111,
                model_pid: 7,
                model_thread_id: 1,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 1112,
                model_pid: 7,
                model_thread_id: 1,
                regs,
            },
        ];
        assert_eq!(
            remap_stopped_tracee_restore_set_to_replacement_pids(
                &restore,
                &duplicate_threads,
                &[],
                &BTreeMap::from([(1, 7001)]),
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("duplicate tracee model thread id")
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn stopped_tracee_restore_and_resume_set_restores_all_before_resuming_in_pid_order() {
        let mut regs_a: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        regs_a.rip = 0x7f00_3000;
        let mut regs_b: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        regs_b.rip = 0x7f00_3000;
        let shared_action_for =
            |host_pid| KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                host_pid,
                model_pid: host_pid as u64,
                start: 0x7f00_3000,
                len: 4,
                prot: libc::PROT_READ,
                kind: KboxlikeSharedMappingKind::Memfd,
                path: Some("/memfd:kboxlike-set-shared".to_string()),
                file_offset: 0,
                dev: "00:00".to_string(),
                inode: 99,
            };
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![shared_action_for(2002), shared_action_for(2001)],
        };
        let threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 2002,
                model_pid: 2002,
                model_thread_id: 2002,
                regs: regs_b,
            },
            KboxlikeThreadSnapshot {
                host_pid: 2001,
                model_pid: 2001,
                model_thread_id: 2001,
                regs: regs_a,
            },
        ];
        let dumps = vec![KboxlikeSharedMemoryDump {
            host_pid: 2001,
            model_pid: 2001,
            start: 0x7f00_3000,
            kind: KboxlikeSharedMappingKind::Memfd,
            path: Some("/memfd:kboxlike-set-shared".to_string()),
            file_offset: 0,
            dev: "00:00".to_string(),
            inode: 99,
            bytes: b"code".to_vec(),
        }];
        let mut factory = FakeRestoreAccessFactory::default();
        factory
            .returns_by_pid
            .insert(2001, vec![0x9000, 901, 0x7f00_3000, 0, 0]);
        factory
            .returns_by_pid
            .insert(2002, vec![0x9000, 902, 0x7f00_3000, 0, 0]);
        let mut resumer = FakeRestoredTraceeResumer::default();

        let summary = apply_and_resume_stopped_tracee_restore_set(
            &restore,
            &threads,
            &dumps,
            1234,
            &mut factory,
            &mut resumer,
        )
        .unwrap();

        assert_eq!(factory.requested, vec![2001, 2002]);
        assert_eq!(resumer.resumed, vec![2001, 2002]);
        assert_eq!(
            summary,
            TraceeRestoreAndResumeSetSummary {
                restore: TraceeRestoreSetSummary {
                    tracees_restored: 2,
                    shared_objects: TraceeSharedObjectRegistryBuildSummary {
                        created_objects: 1,
                        initialized_extents: 1,
                        skipped_unsupported_objects: 0,
                    },
                    memory: TraceeMemoryRestoreSummary {
                        byte_backed_applied: 0,
                        clean_file_remapped: 0,
                        shared_object_remapped: 2,
                        skipped_no_mapping: 0,
                        deferred_unsupported: 0,
                        other_tracee: 2,
                    },
                    registers: TraceeRegisterRestoreSummary {
                        registers_restored: 2,
                        other_tracee: 2,
                    },
                },
                resume: TraceeResumeSetSummary { tracees_resumed: 2 },
            }
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn stopped_tracee_restore_and_resume_set_does_not_resume_after_restore_failure() {
        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                host_pid: 4321,
                model_pid: 7,
                start: 0x7f00_3000,
                prot: libc::PROT_READ,
                bytes: b"code".to_vec(),
                source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
            }],
        };
        let threads = vec![KboxlikeThreadSnapshot {
            host_pid: 4321,
            model_pid: 7,
            model_thread_id: 1,
            regs,
        }];
        let mut factory = FakeRestoreAccessFactory::default();
        let mut resumer = FakeRestoredTraceeResumer::default();

        assert_eq!(
            apply_and_resume_stopped_tracee_restore_set(
                &restore,
                &threads,
                &[],
                1234,
                &mut factory,
                &mut resumer,
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("missing fake tracee returns")
        );
        assert!(resumer.resumed.is_empty());
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn full_replacement_restore_applies_memory_kernel_registers_then_resume() {
        let mut regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        regs.rip = 0x7f00_3000;
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                host_pid: 4321,
                model_pid: 7,
                start: 0x7f00_3000,
                prot: libc::PROT_READ | libc::PROT_WRITE,
                bytes: b"code".to_vec(),
                source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
            }],
        };
        let threads = vec![KboxlikeThreadSnapshot {
            host_pid: 4321,
            model_pid: 7,
            model_thread_id: 1,
            regs,
        }];
        let kernel_states = vec![KboxlikeThreadKernelStateSnapshot {
            host_pid: 4321,
            model_pid: 7,
            model_thread_id: 1,
            clear_child_tid: Some(0x7f00_4000),
            robust_list_head: Some(0x7f00_5000),
            robust_list_len: 24,
        }];
        let replacement_host_pids = BTreeMap::from([(1, 9001)]);
        let mut factory = FakeRestoreAccessFactory::default();
        factory
            .returns_by_pid
            .insert(9001, vec![0x7f00_3000, 9001, 0]);
        let mut resumer = FakeRestoredTraceeResumer::default();

        let summary = apply_and_resume_stopped_tracee_full_restore_set_with_replacement_pids(
            &restore,
            &threads,
            &kernel_states,
            &[],
            &replacement_host_pids,
            1234,
            &mut factory,
            &mut resumer,
        )
        .unwrap();

        assert_eq!(factory.requested, vec![9001]);
        assert_eq!(resumer.resumed, vec![9001]);
        assert_eq!(
            summary,
            TraceeFullRestoreAndResumeSetSummary {
                restore: TraceeFullRestoreSetSummary {
                    tracees_restored: 1,
                    shared_objects: TraceeSharedObjectRegistryBuildSummary::default(),
                    memory: TraceeMemoryRestoreSummary {
                        byte_backed_applied: 1,
                        clean_file_remapped: 0,
                        shared_object_remapped: 0,
                        skipped_no_mapping: 0,
                        deferred_unsupported: 0,
                        other_tracee: 0,
                    },
                    kernel_state: TraceeKernelStateRestoreSummary {
                        clear_child_tid_applied: 1,
                        robust_list_applied: 1,
                        other_tracee: 0,
                    },
                    registers: TraceeRegisterRestoreSummary {
                        registers_restored: 1,
                        other_tracee: 0,
                    },
                },
                resume: TraceeResumeSetSummary { tracees_resumed: 1 },
            }
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn stopped_tracee_restore_set_rejects_unmatched_or_invalid_tracees() {
        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let restore = KboxlikeMaterializedMemoryRestore {
            actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                host_pid: 4321,
                model_pid: 7,
                start: 0x7f00_3000,
                prot: libc::PROT_READ,
                bytes: b"code".to_vec(),
                source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
            }],
        };
        let mut factory = FakeRestoreAccessFactory::default();

        assert_eq!(
            apply_stopped_tracee_restore_set(&restore, &[], &[], 1234, &mut factory).unwrap_err(),
            FdError::TraceeInstallFailed("no tracee register snapshots")
        );

        let invalid_threads = vec![KboxlikeThreadSnapshot {
            host_pid: 0,
            model_pid: 7,
            model_thread_id: 1,
            regs,
        }];
        assert_eq!(
            apply_stopped_tracee_restore_set(&restore, &invalid_threads, &[], 1234, &mut factory)
                .unwrap_err(),
            FdError::TraceeInstallFailed("invalid tracee register snapshot pid")
        );

        let unmatched_threads = vec![KboxlikeThreadSnapshot {
            host_pid: 5000,
            model_pid: 7,
            model_thread_id: 1,
            regs,
        }];
        assert_eq!(
            apply_stopped_tracee_restore_set(&restore, &unmatched_threads, &[], 1234, &mut factory)
                .unwrap_err(),
            FdError::TraceeInstallFailed("memory restore action without tracee register snapshot")
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and a Linux x86_64 tracee"]
    fn live_materialized_memory_restore_replays_bytes_into_stopped_child() {
        const ADDR: u64 = 0x7000_0000_0000;
        const BYTES: &[u8] = b"kboxlike-byte-replay";

        let child = unsafe { libc::fork() };
        assert!(child >= 0, "fork failed");

        if child == 0 {
            unsafe {
                let ret = libc::ptrace(
                    libc::PTRACE_TRACEME,
                    0,
                    std::ptr::null_mut::<libc::c_void>(),
                    std::ptr::null_mut::<libc::c_void>(),
                );
                if ret < 0 {
                    libc::_exit(111);
                }
                libc::raise(libc::SIGSTOP);

                let restored = std::slice::from_raw_parts(ADDR as *const u8, BYTES.len());
                if restored == BYTES {
                    libc::_exit(0);
                }
                libc::_exit(113);
            }
        }

        let result: Result<(), FdError> = (|| {
            let mut status = 0;
            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("initial tracee wait failed"));
            }
            if !libc::WIFSTOPPED(status) || libc::WSTOPSIG(status) != libc::SIGSTOP {
                return Err(FdError::TraceeInstallFailed(
                    "tracee did not stop at initial SIGSTOP",
                ));
            }

            let restore = KboxlikeMaterializedMemoryRestore {
                actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                    host_pid: child,
                    model_pid: 1,
                    start: ADDR,
                    prot: libc::PROT_READ,
                    bytes: BYTES.to_vec(),
                    source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
                }],
            };
            let mut writer = ProcessVmMemoryWriter::new(child)?;
            let mut executor = PtraceSyscallExecutor::new(child)?;

            let summary = apply_materialized_memory_restore_for_tracee(
                &restore,
                child,
                &mut writer,
                &mut executor,
            )?;
            assert_eq!(
                summary,
                TraceeMemoryRestoreSummary {
                    byte_backed_applied: 1,
                    clean_file_remapped: 0,
                    shared_object_remapped: 0,
                    skipped_no_mapping: 0,
                    deferred_unsupported: 0,
                    other_tracee: 0,
                }
            );

            let detach_ret = unsafe {
                libc::ptrace(
                    libc::PTRACE_DETACH,
                    child,
                    std::ptr::null_mut::<libc::c_void>(),
                    std::ptr::null_mut::<libc::c_void>(),
                )
            };
            if detach_ret < 0 {
                return Err(FdError::TraceeInstallFailed("ptrace detach failed"));
            }

            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("final tracee wait failed"));
            }
            if libc::WIFEXITED(status) && libc::WEXITSTATUS(status) == 0 {
                return Ok(());
            }
            Err(FdError::TraceeInstallFailed(
                "tracee did not observe restored bytes",
            ))
        })();

        if result.is_err() {
            unsafe {
                libc::kill(child, libc::SIGKILL);
                let mut status = 0;
                libc::waitpid(child, &mut status, 0);
            }
        }

        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and a Linux x86_64 tracee"]
    fn live_thread_register_restore_redirects_stopped_child_to_restored_rip() {
        const ADDR: u64 = 0x7400_0000_0000;
        const EXIT_CODE: i32 = 42;
        const EXIT_42_STUB: &[u8] = &[
            0xb8, 0x3c, 0x00, 0x00, 0x00, // mov eax, SYS_exit
            0xbf, 0x2a, 0x00, 0x00, 0x00, // mov edi, 42
            0x0f, 0x05, // syscall
        ];

        let child = unsafe { libc::fork() };
        assert!(child >= 0, "fork failed");

        if child == 0 {
            unsafe {
                let ret = libc::ptrace(
                    libc::PTRACE_TRACEME,
                    0,
                    std::ptr::null_mut::<libc::c_void>(),
                    std::ptr::null_mut::<libc::c_void>(),
                );
                if ret < 0 {
                    libc::_exit(111);
                }
                libc::raise(libc::SIGSTOP);
                libc::_exit(113);
            }
        }

        let result: Result<(), FdError> = (|| {
            let mut status = 0;
            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("initial tracee wait failed"));
            }
            if !libc::WIFSTOPPED(status) || libc::WSTOPSIG(status) != libc::SIGSTOP {
                return Err(FdError::TraceeInstallFailed(
                    "tracee did not stop at initial SIGSTOP",
                ));
            }

            let restore = KboxlikeMaterializedMemoryRestore {
                actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                    host_pid: child,
                    model_pid: 1,
                    start: ADDR,
                    prot: libc::PROT_READ | libc::PROT_EXEC,
                    bytes: EXIT_42_STUB.to_vec(),
                    source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
                }],
            };
            let mut writer = ProcessVmMemoryWriter::new(child)?;
            let mut executor = PtraceSyscallExecutor::new(child)?;
            apply_materialized_memory_restore_for_tracee(
                &restore,
                child,
                &mut writer,
                &mut executor,
            )?;

            let mut restored_regs = executor.getregs()?;
            restored_regs.rip = ADDR;
            let threads = vec![KboxlikeThreadSnapshot {
                host_pid: child,
                model_pid: 1,
                model_thread_id: 1,
                regs: restored_regs,
            }];
            let mut register_writer = PtraceRegisterWriter::new(child)?;
            let summary =
                apply_thread_register_restore_for_tracee(&threads, child, &mut register_writer)?;
            assert_eq!(
                summary,
                TraceeRegisterRestoreSummary {
                    registers_restored: 1,
                    other_tracee: 0,
                }
            );

            let detach_ret = unsafe {
                libc::ptrace(
                    libc::PTRACE_DETACH,
                    child,
                    std::ptr::null_mut::<libc::c_void>(),
                    std::ptr::null_mut::<libc::c_void>(),
                )
            };
            if detach_ret < 0 {
                return Err(FdError::TraceeInstallFailed("ptrace detach failed"));
            }

            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("final tracee wait failed"));
            }
            if libc::WIFEXITED(status) && libc::WEXITSTATUS(status) == EXIT_CODE {
                return Ok(());
            }
            Err(FdError::TraceeInstallFailed(
                "tracee did not execute restored instruction pointer",
            ))
        })();

        if result.is_err() {
            unsafe {
                libc::kill(child, libc::SIGKILL);
                let mut status = 0;
                libc::waitpid(child, &mut status, 0);
            }
        }

        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and a Linux x86_64 tracee"]
    fn live_stopped_tracee_restore_replays_memory_then_registers() {
        const ADDR: u64 = 0x7500_0000_0000;
        const EXIT_CODE: i32 = 43;
        const EXIT_43_STUB: &[u8] = &[
            0xb8, 0x3c, 0x00, 0x00, 0x00, // mov eax, SYS_exit
            0xbf, 0x2b, 0x00, 0x00, 0x00, // mov edi, 43
            0x0f, 0x05, // syscall
        ];

        let child = unsafe { libc::fork() };
        assert!(child >= 0, "fork failed");

        if child == 0 {
            unsafe {
                let ret = libc::ptrace(
                    libc::PTRACE_TRACEME,
                    0,
                    std::ptr::null_mut::<libc::c_void>(),
                    std::ptr::null_mut::<libc::c_void>(),
                );
                if ret < 0 {
                    libc::_exit(111);
                }
                libc::raise(libc::SIGSTOP);
                libc::_exit(113);
            }
        }

        let result = (|| {
            let mut status = 0;
            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("initial tracee wait failed"));
            }
            if !libc::WIFSTOPPED(status) || libc::WSTOPSIG(status) != libc::SIGSTOP {
                return Err(FdError::TraceeInstallFailed(
                    "tracee did not stop at initial SIGSTOP",
                ));
            }

            let restore = KboxlikeMaterializedMemoryRestore {
                actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                    host_pid: child,
                    model_pid: 1,
                    start: ADDR,
                    prot: libc::PROT_READ | libc::PROT_EXEC,
                    bytes: EXIT_43_STUB.to_vec(),
                    source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
                }],
            };
            let mut writer = ProcessVmMemoryWriter::new(child)?;
            let mut executor = PtraceSyscallExecutor::new(child)?;
            let mut restored_regs = executor.getregs()?;
            restored_regs.rip = ADDR;
            let threads = vec![KboxlikeThreadSnapshot {
                host_pid: child,
                model_pid: 1,
                model_thread_id: 1,
                regs: restored_regs,
            }];
            let mut register_writer = PtraceRegisterWriter::new(child)?;

            let summary = apply_stopped_tracee_restore(
                &restore,
                &threads,
                child,
                &mut writer,
                &mut executor,
                &mut register_writer,
            )?;
            assert_eq!(
                summary,
                TraceeRestoreSummary {
                    memory: TraceeMemoryRestoreSummary {
                        byte_backed_applied: 1,
                        clean_file_remapped: 0,
                        shared_object_remapped: 0,
                        skipped_no_mapping: 0,
                        deferred_unsupported: 0,
                        other_tracee: 2,
                    },
                    registers: TraceeRegisterRestoreSummary {
                        registers_restored: 1,
                        other_tracee: 0,
                    },
                }
            );

            let detach_ret = unsafe {
                libc::ptrace(
                    libc::PTRACE_DETACH,
                    child,
                    std::ptr::null_mut::<libc::c_void>(),
                    std::ptr::null_mut::<libc::c_void>(),
                )
            };
            if detach_ret < 0 {
                return Err(FdError::TraceeInstallFailed("ptrace detach failed"));
            }

            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("final tracee wait failed"));
            }
            if libc::WIFEXITED(status) && libc::WEXITSTATUS(status) == EXIT_CODE {
                return Ok(());
            }
            Err(FdError::TraceeInstallFailed(
                "tracee did not execute orchestrated restore",
            ))
        })();

        if result.is_err() {
            unsafe {
                libc::kill(child, libc::SIGKILL);
                let mut status = 0;
                libc::waitpid(child, &mut status, 0);
            }
        }

        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and two Linux x86_64 tracees"]
    fn live_stopped_tracee_restore_set_materializes_shared_code_once() {
        const ADDR: u64 = 0x7600_0000_0000;
        const EXIT_CODE: i32 = 44;
        const EXIT_44_STUB: &[u8] = &[
            0xb8, 0x3c, 0x00, 0x00, 0x00, // mov eax, SYS_exit
            0xbf, 0x2c, 0x00, 0x00, 0x00, // mov edi, 44
            0x0f, 0x05, // syscall
        ];

        fn fork_stopped_child() -> libc::pid_t {
            let child = unsafe { libc::fork() };
            assert!(child >= 0, "fork failed");
            if child == 0 {
                unsafe {
                    let ret = libc::ptrace(
                        libc::PTRACE_TRACEME,
                        0,
                        std::ptr::null_mut::<libc::c_void>(),
                        std::ptr::null_mut::<libc::c_void>(),
                    );
                    if ret < 0 {
                        libc::_exit(111);
                    }
                    libc::raise(libc::SIGSTOP);
                    libc::_exit(113);
                }
            }
            child
        }

        fn wait_initial_stop(child: libc::pid_t) -> Result<(), FdError> {
            let mut status = 0;
            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("initial tracee wait failed"));
            }
            if !libc::WIFSTOPPED(status) || libc::WSTOPSIG(status) != libc::SIGSTOP {
                return Err(FdError::TraceeInstallFailed(
                    "tracee did not stop at initial SIGSTOP",
                ));
            }
            Ok(())
        }

        fn wait_exit(child: libc::pid_t, code: i32) -> Result<(), FdError> {
            let mut status = 0;
            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("final tracee wait failed"));
            }
            if libc::WIFEXITED(status) && libc::WEXITSTATUS(status) == code {
                return Ok(());
            }
            Err(FdError::TraceeInstallFailed(
                "tracee did not execute restored shared code",
            ))
        }

        let child_a = fork_stopped_child();
        let child_b = fork_stopped_child();

        let result: Result<(), FdError> = (|| {
            wait_initial_stop(child_a)?;
            wait_initial_stop(child_b)?;

            let shared_action_for =
                |host_pid| KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                    host_pid,
                    model_pid: host_pid as u64,
                    start: ADDR,
                    len: EXIT_44_STUB.len() as u64,
                    prot: libc::PROT_READ | libc::PROT_EXEC,
                    kind: KboxlikeSharedMappingKind::Memfd,
                    path: Some("/memfd:kboxlike-restore-set-code".to_string()),
                    file_offset: 0,
                    dev: "00:00".to_string(),
                    inode: 144,
                };
            let restore = KboxlikeMaterializedMemoryRestore {
                actions: vec![shared_action_for(child_a), shared_action_for(child_b)],
            };
            let dumps = vec![KboxlikeSharedMemoryDump {
                host_pid: child_a,
                model_pid: child_a as u64,
                start: ADDR,
                kind: KboxlikeSharedMappingKind::Memfd,
                path: Some("/memfd:kboxlike-restore-set-code".to_string()),
                file_offset: 0,
                dev: "00:00".to_string(),
                inode: 144,
                bytes: EXIT_44_STUB.to_vec(),
            }];

            let mut regs_a = PtraceSyscallExecutor::new(child_a)?.getregs()?;
            regs_a.rip = ADDR;
            let mut regs_b = PtraceSyscallExecutor::new(child_b)?.getregs()?;
            regs_b.rip = ADDR;
            let threads = vec![
                KboxlikeThreadSnapshot {
                    host_pid: child_a,
                    model_pid: child_a as u64,
                    model_thread_id: child_a as u64,
                    regs: regs_a,
                },
                KboxlikeThreadSnapshot {
                    host_pid: child_b,
                    model_pid: child_b as u64,
                    model_thread_id: child_b as u64,
                    regs: regs_b,
                },
            ];
            let mut access_factory = LinuxTraceeRestoreAccessFactory;
            let mut resumer = PtraceDetachRestoredTraceeResumer;

            let summary = apply_and_resume_stopped_tracee_restore_set(
                &restore,
                &threads,
                &dumps,
                std::process::id() as i32,
                &mut access_factory,
                &mut resumer,
            )?;
            assert_eq!(
                summary,
                TraceeRestoreAndResumeSetSummary {
                    restore: TraceeRestoreSetSummary {
                        tracees_restored: 2,
                        shared_objects: TraceeSharedObjectRegistryBuildSummary {
                            created_objects: 1,
                            initialized_extents: 1,
                            skipped_unsupported_objects: 0,
                        },
                        memory: TraceeMemoryRestoreSummary {
                            byte_backed_applied: 0,
                            clean_file_remapped: 0,
                            shared_object_remapped: 2,
                            skipped_no_mapping: 0,
                            deferred_unsupported: 0,
                            other_tracee: 2,
                        },
                        registers: TraceeRegisterRestoreSummary {
                            registers_restored: 2,
                            other_tracee: 2,
                        },
                    },
                    resume: TraceeResumeSetSummary { tracees_resumed: 2 },
                },
            );

            wait_exit(child_a, EXIT_CODE)?;
            wait_exit(child_b, EXIT_CODE)?;
            Ok(())
        })();

        if result.is_err() {
            unsafe {
                libc::kill(child_a, libc::SIGKILL);
                libc::kill(child_b, libc::SIGKILL);
                let mut status = 0;
                libc::waitpid(child_a, &mut status, 0);
                libc::waitpid(child_b, &mut status, 0);
            }
        }

        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and a Linux x86_64 replacement tracee"]
    fn live_replacement_pid_restore_maps_model_pid_to_new_stopped_child() {
        const ADDR: u64 = 0x7700_0000_0000;
        const CAPTURED_HOST_PID: i32 = 1111;
        const MODEL_PID: ProcessId = 7;
        const MODEL_THREAD_ID: ModelThreadId = 1;
        const EXIT_CODE: i32 = 45;
        const EXIT_45_STUB: &[u8] = &[
            0xb8, 0x3c, 0x00, 0x00, 0x00, // mov eax, SYS_exit
            0xbf, 0x2d, 0x00, 0x00, 0x00, // mov edi, 45
            0x0f, 0x05, // syscall
        ];

        let source_threads = vec![KboxlikeThreadSnapshot {
            host_pid: CAPTURED_HOST_PID,
            model_pid: MODEL_PID,
            model_thread_id: MODEL_THREAD_ID,
            regs: unsafe { std::mem::zeroed() },
        }];
        let mut replacement_factory = LinuxStoppedTraceeReplacementFactory::default();

        let result: Result<(), FdError> = (|| {
            let created =
                create_stopped_replacement_tracee_set(&source_threads, &mut replacement_factory)?;
            assert_eq!(
                created.summary,
                TraceeReplacementThreadGroupCreateSummary {
                    process_groups: 1,
                    tracees_requested: 1,
                    tracees_created: 1,
                }
            );
            assert_eq!(replacement_factory.created_host_pids().len(), 1);
            let child = *created.replacement_host_pids.get(&MODEL_THREAD_ID).ok_or(
                FdError::TraceeInstallFailed("replacement model thread id was not created"),
            )?;

            let restore = KboxlikeMaterializedMemoryRestore {
                actions: vec![KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                    host_pid: CAPTURED_HOST_PID,
                    model_pid: MODEL_PID,
                    start: ADDR,
                    prot: libc::PROT_READ | libc::PROT_EXEC,
                    bytes: EXIT_45_STUB.to_vec(),
                    source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
                }],
            };
            let mut regs = PtraceSyscallExecutor::new(child)?.getregs()?;
            regs.rip = ADDR;
            let threads = vec![KboxlikeThreadSnapshot {
                host_pid: CAPTURED_HOST_PID,
                model_pid: MODEL_PID,
                model_thread_id: MODEL_THREAD_ID,
                regs,
            }];
            let mut access_factory = LinuxTraceeRestoreAccessFactory;
            let mut resumer = PtraceDetachRestoredTraceeResumer;

            let summary = apply_and_resume_stopped_tracee_restore_set_with_replacement_pids(
                &restore,
                &threads,
                &[],
                &created.replacement_host_pids,
                std::process::id() as i32,
                &mut access_factory,
                &mut resumer,
            )?;
            assert_eq!(
                summary,
                TraceeRestoreAndResumeSetSummary {
                    restore: TraceeRestoreSetSummary {
                        tracees_restored: 1,
                        shared_objects: TraceeSharedObjectRegistryBuildSummary {
                            created_objects: 0,
                            initialized_extents: 0,
                            skipped_unsupported_objects: 0,
                        },
                        memory: TraceeMemoryRestoreSummary {
                            byte_backed_applied: 1,
                            clean_file_remapped: 0,
                            shared_object_remapped: 0,
                            skipped_no_mapping: 0,
                            deferred_unsupported: 0,
                            other_tracee: 0,
                        },
                        registers: TraceeRegisterRestoreSummary {
                            registers_restored: 1,
                            other_tracee: 0,
                        },
                    },
                    resume: TraceeResumeSetSummary { tracees_resumed: 1 },
                },
            );

            let mut status = 0;
            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("final tracee wait failed"));
            }
            if libc::WIFEXITED(status) && libc::WEXITSTATUS(status) == EXIT_CODE {
                return Ok(());
            }
            Err(FdError::TraceeInstallFailed(
                "replacement tracee did not execute restored code",
            ))
        })();

        if result.is_err() {
            replacement_factory.kill_created_tracees();
        }

        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and Linux x86_64 clone tracing"]
    fn live_replacement_factory_creates_two_stopped_threads_in_one_thread_group() {
        const MODEL_PID: ProcessId = 7;
        const MODEL_THREAD_A: ModelThreadId = 1;
        const MODEL_THREAD_B: ModelThreadId = 2;

        fn proc_status_tgid(tid: i32) -> Result<i32, FdError> {
            let status = std::fs::read_to_string(format!("/proc/{tid}/status"))
                .map_err(|_| FdError::TraceeInstallFailed("read proc status failed"))?;
            for line in status.lines() {
                if let Some(rest) = line.strip_prefix("Tgid:") {
                    return rest
                        .trim()
                        .parse::<i32>()
                        .map_err(|_| FdError::TraceeInstallFailed("parse proc tgid failed"));
                }
            }
            Err(FdError::TraceeInstallFailed("proc status missing tgid"))
        }

        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let source_threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 1111,
                model_pid: MODEL_PID,
                model_thread_id: MODEL_THREAD_A,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 2222,
                model_pid: MODEL_PID,
                model_thread_id: MODEL_THREAD_B,
                regs,
            },
        ];
        let mut factory = LinuxStoppedTraceeReplacementFactory::default();

        let result: Result<(), FdError> = (|| {
            let created = create_stopped_replacement_tracee_set(&source_threads, &mut factory)?;
            assert_eq!(
                created.summary,
                TraceeReplacementThreadGroupCreateSummary {
                    process_groups: 1,
                    tracees_requested: 2,
                    tracees_created: 2,
                }
            );

            let leader = *created
                .replacement_host_pids
                .get(&MODEL_THREAD_A)
                .ok_or(FdError::TraceeInstallFailed("missing replacement leader"))?;
            let follower = *created
                .replacement_host_pids
                .get(&MODEL_THREAD_B)
                .ok_or(FdError::TraceeInstallFailed("missing replacement follower"))?;
            assert_ne!(leader, follower);
            assert_eq!(proc_status_tgid(leader)?, proc_status_tgid(follower)?);

            PtraceSyscallExecutor::new(leader)?.getregs()?;
            PtraceSyscallExecutor::new(follower)?.getregs()?;
            Ok(())
        })();

        factory.kill_created_tracees();
        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and Linux x86_64 clone tracing"]
    fn live_replacement_restore_resumes_two_threads_in_shared_vm() {
        const ADDR: u64 = 0x7800_0000_0000;
        const MSG_A_OFFSET: usize = 0x40;
        const MSG_B_OFFSET: usize = 0x41;
        const CAPTURED_HOST_A: i32 = 1111;
        const CAPTURED_HOST_B: i32 = 2222;
        const MODEL_PID: ProcessId = 7;
        const MODEL_THREAD_A: ModelThreadId = 1;
        const MODEL_THREAD_B: ModelThreadId = 2;
        const WRITE_AND_PAUSE_STUB: &[u8] = &[
            0xb8, 0x01, 0x00, 0x00, 0x00, // mov eax, SYS_write
            0xba, 0x01, 0x00, 0x00, 0x00, // mov edx, 1
            0x0f, 0x05, // syscall
            0xb8, 0x22, 0x00, 0x00, 0x00, // mov eax, SYS_pause
            0x0f, 0x05, // syscall
            0xeb, 0xf7, // jmp back to pause
        ];

        fn set_nonblocking(fd: i32) -> Result<(), FdError> {
            let flags = unsafe { libc::fcntl(fd, libc::F_GETFL) };
            if flags < 0 {
                return Err(FdError::TraceeInstallFailed("fcntl getfl failed"));
            }
            let ret = unsafe { libc::fcntl(fd, libc::F_SETFL, flags | libc::O_NONBLOCK) };
            if ret < 0 {
                return Err(FdError::TraceeInstallFailed("fcntl setfl failed"));
            }
            Ok(())
        }

        fn proc_status_state(tid: i32) -> String {
            std::fs::read_to_string(format!("/proc/{tid}/status"))
                .ok()
                .and_then(|status| {
                    status
                        .lines()
                        .find(|line| line.starts_with("State:"))
                        .map(str::to_string)
                })
                .unwrap_or_else(|| "State: <missing>".to_string())
        }

        fn read_two_pipe_bytes(fd: i32, leader: i32, follower: i32) -> Result<Vec<u8>, FdError> {
            let deadline = std::time::Instant::now() + std::time::Duration::from_secs(5);
            let mut bytes = Vec::new();
            while bytes.len() < 2 && std::time::Instant::now() <= deadline {
                let mut byte = 0u8;
                let read_ret = unsafe { libc::read(fd, &mut byte as *mut _ as *mut c_void, 1) };
                if read_ret == 1 {
                    bytes.push(byte);
                    continue;
                }
                if read_ret < 0 {
                    let errno = unsafe { *libc::__errno_location() };
                    if errno != libc::EAGAIN && errno != libc::EWOULDBLOCK {
                        return Err(FdError::TraceeInstallFailed("pipe read failed"));
                    }
                }
                std::thread::sleep(std::time::Duration::from_millis(1));
            }
            if bytes.len() != 2 {
                eprintln!(
                    "two-thread restore pipe timeout bytes={bytes:?} leader={} follower={} leader_state={} follower_state={}",
                    leader,
                    follower,
                    proc_status_state(leader),
                    proc_status_state(follower)
                );
                return Err(FdError::TraceeInstallFailed(
                    "restored threads did not write pipe bytes",
                ));
            }
            bytes.sort_unstable();
            Ok(bytes)
        }

        let mut pipe_fds = [0; 2];
        let pipe_ret = unsafe { libc::pipe(pipe_fds.as_mut_ptr()) };
        assert_eq!(pipe_ret, 0, "pipe failed");
        set_nonblocking(pipe_fds[0]).unwrap();

        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let source_threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: CAPTURED_HOST_A,
                model_pid: MODEL_PID,
                model_thread_id: MODEL_THREAD_A,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: CAPTURED_HOST_B,
                model_pid: MODEL_PID,
                model_thread_id: MODEL_THREAD_B,
                regs,
            },
        ];
        let mut replacement_factory = LinuxStoppedTraceeReplacementFactory::default();

        let result: Result<(), FdError> = (|| {
            let created =
                create_stopped_replacement_tracee_set(&source_threads, &mut replacement_factory)?;
            let leader = *created
                .replacement_host_pids
                .get(&MODEL_THREAD_A)
                .ok_or(FdError::TraceeInstallFailed("missing replacement leader"))?;
            let follower = *created
                .replacement_host_pids
                .get(&MODEL_THREAD_B)
                .ok_or(FdError::TraceeInstallFailed("missing replacement follower"))?;

            let mut page = vec![0xcc; 0x100];
            page[..WRITE_AND_PAUSE_STUB.len()].copy_from_slice(WRITE_AND_PAUSE_STUB);
            page[MSG_A_OFFSET] = b'A';
            page[MSG_B_OFFSET] = b'B';
            let action_for = |host_pid| KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                host_pid,
                model_pid: MODEL_PID,
                start: ADDR,
                prot: libc::PROT_READ | libc::PROT_EXEC,
                bytes: page.clone(),
                source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
            };
            let restore = KboxlikeMaterializedMemoryRestore {
                actions: vec![action_for(CAPTURED_HOST_A), action_for(CAPTURED_HOST_B)],
            };

            let mut regs_a = PtraceSyscallExecutor::new(leader)?.getregs()?;
            regs_a.rip = ADDR;
            regs_a.rdi = pipe_fds[1] as u64;
            regs_a.rsi = ADDR + MSG_A_OFFSET as u64;
            let mut regs_b = PtraceSyscallExecutor::new(follower)?.getregs()?;
            regs_b.rip = ADDR;
            regs_b.rdi = pipe_fds[1] as u64;
            regs_b.rsi = ADDR + MSG_B_OFFSET as u64;
            let threads = vec![
                KboxlikeThreadSnapshot {
                    host_pid: CAPTURED_HOST_A,
                    model_pid: MODEL_PID,
                    model_thread_id: MODEL_THREAD_A,
                    regs: regs_a,
                },
                KboxlikeThreadSnapshot {
                    host_pid: CAPTURED_HOST_B,
                    model_pid: MODEL_PID,
                    model_thread_id: MODEL_THREAD_B,
                    regs: regs_b,
                },
            ];
            let mut access_factory = LinuxTraceeRestoreAccessFactory;
            let mut resumer = PtraceDetachRestoredTraceeResumer;

            let summary = apply_and_resume_stopped_tracee_restore_set_with_replacement_pids(
                &restore,
                &threads,
                &[],
                &created.replacement_host_pids,
                std::process::id() as i32,
                &mut access_factory,
                &mut resumer,
            )?;
            assert_eq!(
                summary,
                TraceeRestoreAndResumeSetSummary {
                    restore: TraceeRestoreSetSummary {
                        tracees_restored: 2,
                        shared_objects: TraceeSharedObjectRegistryBuildSummary {
                            created_objects: 0,
                            initialized_extents: 0,
                            skipped_unsupported_objects: 0,
                        },
                        memory: TraceeMemoryRestoreSummary {
                            byte_backed_applied: 1,
                            clean_file_remapped: 0,
                            shared_object_remapped: 0,
                            skipped_no_mapping: 0,
                            deferred_unsupported: 0,
                            other_tracee: 1,
                        },
                        registers: TraceeRegisterRestoreSummary {
                            registers_restored: 2,
                            other_tracee: 2,
                        },
                    },
                    resume: TraceeResumeSetSummary { tracees_resumed: 2 },
                },
            );

            let bytes = read_two_pipe_bytes(pipe_fds[0], leader, follower)?;
            if bytes != b"AB" {
                return Err(FdError::TraceeInstallFailed(
                    "restored threads wrote unexpected pipe bytes",
                ));
            }

            Ok(())
        })();

        replacement_factory.kill_created_tracees();
        unsafe {
            libc::close(pipe_fds[0]);
            libc::close(pipe_fds[1]);
        }
        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and Linux x86_64 clone tracing"]
    fn live_captured_two_thread_registers_restore_into_replacement_group() {
        const ADDR: u64 = 0x7900_0000_0000;
        const MSG_A_OFFSET: usize = 0x40;
        const MSG_B_OFFSET: usize = 0x41;
        const SOURCE_MODEL_PID: ProcessId = 21;
        const MODEL_PID: ProcessId = 7;
        const MODEL_THREAD_A: ModelThreadId = 1;
        const MODEL_THREAD_B: ModelThreadId = 2;
        const WRITE_AND_PAUSE_STUB: &[u8] = &[
            0xb8, 0x01, 0x00, 0x00, 0x00, // mov eax, SYS_write
            0xba, 0x01, 0x00, 0x00, 0x00, // mov edx, 1
            0x0f, 0x05, // syscall
            0xb8, 0x22, 0x00, 0x00, 0x00, // mov eax, SYS_pause
            0x0f, 0x05, // syscall
            0xeb, 0xf7, // jmp back to pause
        ];

        fn set_nonblocking(fd: i32) -> Result<(), FdError> {
            let flags = unsafe { libc::fcntl(fd, libc::F_GETFL) };
            if flags < 0 {
                return Err(FdError::TraceeInstallFailed("fcntl getfl failed"));
            }
            let ret = unsafe { libc::fcntl(fd, libc::F_SETFL, flags | libc::O_NONBLOCK) };
            if ret < 0 {
                return Err(FdError::TraceeInstallFailed("fcntl setfl failed"));
            }
            Ok(())
        }

        fn proc_status_state(tid: i32) -> String {
            std::fs::read_to_string(format!("/proc/{tid}/status"))
                .ok()
                .and_then(|status| {
                    status
                        .lines()
                        .find(|line| line.starts_with("State:"))
                        .map(str::to_string)
                })
                .unwrap_or_else(|| "State: <missing>".to_string())
        }

        fn read_two_pipe_bytes(fd: i32, leader: i32, follower: i32) -> Result<Vec<u8>, FdError> {
            let deadline = std::time::Instant::now() + std::time::Duration::from_secs(5);
            let mut bytes = Vec::new();
            while bytes.len() < 2 && std::time::Instant::now() <= deadline {
                let mut byte = 0u8;
                let read_ret = unsafe { libc::read(fd, &mut byte as *mut _ as *mut c_void, 1) };
                if read_ret == 1 {
                    bytes.push(byte);
                    continue;
                }
                if read_ret < 0 {
                    let errno = unsafe { *libc::__errno_location() };
                    if errno != libc::EAGAIN && errno != libc::EWOULDBLOCK {
                        return Err(FdError::TraceeInstallFailed("pipe read failed"));
                    }
                }
                std::thread::sleep(std::time::Duration::from_millis(1));
            }
            if bytes.len() != 2 {
                eprintln!(
                    "captured two-thread restore pipe timeout bytes={bytes:?} leader={} follower={} leader_state={} follower_state={}",
                    leader,
                    follower,
                    proc_status_state(leader),
                    proc_status_state(follower)
                );
                return Err(FdError::TraceeInstallFailed(
                    "restored captured threads did not write pipe bytes",
                ));
            }
            bytes.sort_unstable();
            Ok(bytes)
        }

        let mut pipe_fds = [0; 2];
        let pipe_ret = unsafe { libc::pipe(pipe_fds.as_mut_ptr()) };
        assert_eq!(pipe_ret, 0, "pipe failed");
        set_nonblocking(pipe_fds[0]).unwrap();

        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let source_seed_threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 3111,
                model_pid: SOURCE_MODEL_PID,
                model_thread_id: MODEL_THREAD_A,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 3222,
                model_pid: SOURCE_MODEL_PID,
                model_thread_id: MODEL_THREAD_B,
                regs,
            },
        ];
        let mut source_factory = LinuxStoppedTraceeReplacementFactory::default();
        let mut replacement_factory = LinuxStoppedTraceeReplacementFactory::default();

        let result: Result<(), FdError> = (|| {
            let source_created =
                create_stopped_replacement_tracee_set(&source_seed_threads, &mut source_factory)?;
            let source_leader = *source_created
                .replacement_host_pids
                .get(&MODEL_THREAD_A)
                .ok_or(FdError::TraceeInstallFailed("missing source leader"))?;
            let source_follower = *source_created
                .replacement_host_pids
                .get(&MODEL_THREAD_B)
                .ok_or(FdError::TraceeInstallFailed("missing source follower"))?;

            let mut regs_a = PtraceSyscallExecutor::new(source_leader)?.getregs()?;
            regs_a.rip = ADDR;
            regs_a.rdi = pipe_fds[1] as u64;
            regs_a.rsi = ADDR + MSG_A_OFFSET as u64;
            PtraceRegisterWriter::new(source_leader)?.write_regs(&regs_a)?;
            let captured_regs_a = PtraceSyscallExecutor::new(source_leader)?.getregs()?;

            let mut regs_b = PtraceSyscallExecutor::new(source_follower)?.getregs()?;
            regs_b.rip = ADDR;
            regs_b.rdi = pipe_fds[1] as u64;
            regs_b.rsi = ADDR + MSG_B_OFFSET as u64;
            PtraceRegisterWriter::new(source_follower)?.write_regs(&regs_b)?;
            let captured_regs_b = PtraceSyscallExecutor::new(source_follower)?.getregs()?;

            let captured_threads = vec![
                KboxlikeThreadSnapshot {
                    host_pid: source_leader,
                    model_pid: MODEL_PID,
                    model_thread_id: MODEL_THREAD_A,
                    regs: captured_regs_a,
                },
                KboxlikeThreadSnapshot {
                    host_pid: source_follower,
                    model_pid: MODEL_PID,
                    model_thread_id: MODEL_THREAD_B,
                    regs: captured_regs_b,
                },
            ];
            let replacement_created =
                create_stopped_replacement_tracee_set(&captured_threads, &mut replacement_factory)?;
            let replacement_leader = *replacement_created
                .replacement_host_pids
                .get(&MODEL_THREAD_A)
                .ok_or(FdError::TraceeInstallFailed(
                    "missing captured replacement leader",
                ))?;
            let replacement_follower = *replacement_created
                .replacement_host_pids
                .get(&MODEL_THREAD_B)
                .ok_or(FdError::TraceeInstallFailed(
                    "missing captured replacement follower",
                ))?;

            let mut page = vec![0xcc; 0x100];
            page[..WRITE_AND_PAUSE_STUB.len()].copy_from_slice(WRITE_AND_PAUSE_STUB);
            page[MSG_A_OFFSET] = b'A';
            page[MSG_B_OFFSET] = b'B';
            let action_for = |host_pid| KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                host_pid,
                model_pid: MODEL_PID,
                start: ADDR,
                prot: libc::PROT_READ | libc::PROT_EXEC,
                bytes: page.clone(),
                source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
            };
            let restore = KboxlikeMaterializedMemoryRestore {
                actions: vec![action_for(source_leader), action_for(source_follower)],
            };
            let mut access_factory = LinuxTraceeRestoreAccessFactory;
            let mut resumer = PtraceDetachRestoredTraceeResumer;

            let summary = apply_and_resume_stopped_tracee_restore_set_with_replacement_pids(
                &restore,
                &captured_threads,
                &[],
                &replacement_created.replacement_host_pids,
                std::process::id() as i32,
                &mut access_factory,
                &mut resumer,
            )?;
            assert_eq!(
                summary,
                TraceeRestoreAndResumeSetSummary {
                    restore: TraceeRestoreSetSummary {
                        tracees_restored: 2,
                        shared_objects: TraceeSharedObjectRegistryBuildSummary {
                            created_objects: 0,
                            initialized_extents: 0,
                            skipped_unsupported_objects: 0,
                        },
                        memory: TraceeMemoryRestoreSummary {
                            byte_backed_applied: 1,
                            clean_file_remapped: 0,
                            shared_object_remapped: 0,
                            skipped_no_mapping: 0,
                            deferred_unsupported: 0,
                            other_tracee: 1,
                        },
                        registers: TraceeRegisterRestoreSummary {
                            registers_restored: 2,
                            other_tracee: 2,
                        },
                    },
                    resume: TraceeResumeSetSummary { tracees_resumed: 2 },
                },
            );

            let bytes = read_two_pipe_bytes(pipe_fds[0], replacement_leader, replacement_follower)?;
            if bytes != b"AB" {
                return Err(FdError::TraceeInstallFailed(
                    "restored captured threads wrote unexpected pipe bytes",
                ));
            }

            Ok(())
        })();

        replacement_factory.kill_created_tracees();
        source_factory.kill_created_tracees();
        unsafe {
            libc::close(pipe_fds[0]);
            libc::close(pipe_fds[1]);
        }
        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and Linux x86_64 clone tracing"]
    fn live_captured_two_thread_fs_base_restores_tls_addressing() {
        const CODE_ADDR: u64 = 0x7a00_0000_0000;
        const SCRATCH_ADDR: u64 = 0x7a00_0000_1000;
        const TLS_A_ADDR: u64 = 0x7a00_0000_2000;
        const TLS_B_ADDR: u64 = 0x7a00_0000_3000;
        const SCRATCH_A_OFFSET: usize = 0x40;
        const SCRATCH_B_OFFSET: usize = 0x41;
        const SOURCE_MODEL_PID: ProcessId = 31;
        const MODEL_PID: ProcessId = 7;
        const MODEL_THREAD_A: ModelThreadId = 1;
        const MODEL_THREAD_B: ModelThreadId = 2;
        const READ_FS_WRITE_AND_PAUSE_STUB: &[u8] = &[
            0x64, 0x8a, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov al, byte ptr fs:[0]
            0x88, 0x06, // mov byte ptr [rsi], al
            0xb8, 0x01, 0x00, 0x00, 0x00, // mov eax, SYS_write
            0xba, 0x01, 0x00, 0x00, 0x00, // mov edx, 1
            0x0f, 0x05, // syscall
            0xb8, 0x22, 0x00, 0x00, 0x00, // mov eax, SYS_pause
            0x0f, 0x05, // syscall
            0xeb, 0xf7, // jmp back to pause
        ];

        fn set_nonblocking(fd: i32) -> Result<(), FdError> {
            let flags = unsafe { libc::fcntl(fd, libc::F_GETFL) };
            if flags < 0 {
                return Err(FdError::TraceeInstallFailed("fcntl getfl failed"));
            }
            let ret = unsafe { libc::fcntl(fd, libc::F_SETFL, flags | libc::O_NONBLOCK) };
            if ret < 0 {
                return Err(FdError::TraceeInstallFailed("fcntl setfl failed"));
            }
            Ok(())
        }

        fn proc_status_state(tid: i32) -> String {
            std::fs::read_to_string(format!("/proc/{tid}/status"))
                .ok()
                .and_then(|status| {
                    status
                        .lines()
                        .find(|line| line.starts_with("State:"))
                        .map(str::to_string)
                })
                .unwrap_or_else(|| "State: <missing>".to_string())
        }

        fn read_two_pipe_bytes(fd: i32, leader: i32, follower: i32) -> Result<Vec<u8>, FdError> {
            let deadline = std::time::Instant::now() + std::time::Duration::from_secs(5);
            let mut bytes = Vec::new();
            while bytes.len() < 2 && std::time::Instant::now() <= deadline {
                let mut byte = 0u8;
                let read_ret = unsafe { libc::read(fd, &mut byte as *mut _ as *mut c_void, 1) };
                if read_ret == 1 {
                    bytes.push(byte);
                    continue;
                }
                if read_ret < 0 {
                    let errno = unsafe { *libc::__errno_location() };
                    if errno != libc::EAGAIN && errno != libc::EWOULDBLOCK {
                        return Err(FdError::TraceeInstallFailed("pipe read failed"));
                    }
                }
                std::thread::sleep(std::time::Duration::from_millis(1));
            }
            if bytes.len() != 2 {
                eprintln!(
                    "captured FS-base restore pipe timeout bytes={bytes:?} leader={} follower={} leader_state={} follower_state={}",
                    leader,
                    follower,
                    proc_status_state(leader),
                    proc_status_state(follower)
                );
                return Err(FdError::TraceeInstallFailed(
                    "restored captured FS-base threads did not write pipe bytes",
                ));
            }
            bytes.sort_unstable();
            Ok(bytes)
        }

        let mut pipe_fds = [0; 2];
        let pipe_ret = unsafe { libc::pipe(pipe_fds.as_mut_ptr()) };
        assert_eq!(pipe_ret, 0, "pipe failed");
        set_nonblocking(pipe_fds[0]).unwrap();

        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let source_seed_threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: 4111,
                model_pid: SOURCE_MODEL_PID,
                model_thread_id: MODEL_THREAD_A,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: 4222,
                model_pid: SOURCE_MODEL_PID,
                model_thread_id: MODEL_THREAD_B,
                regs,
            },
        ];
        let mut source_factory = LinuxStoppedTraceeReplacementFactory::default();
        let mut replacement_factory = LinuxStoppedTraceeReplacementFactory::default();

        let result: Result<(), FdError> = (|| {
            let source_created =
                create_stopped_replacement_tracee_set(&source_seed_threads, &mut source_factory)?;
            let source_leader = *source_created
                .replacement_host_pids
                .get(&MODEL_THREAD_A)
                .ok_or(FdError::TraceeInstallFailed("missing source leader"))?;
            let source_follower = *source_created
                .replacement_host_pids
                .get(&MODEL_THREAD_B)
                .ok_or(FdError::TraceeInstallFailed("missing source follower"))?;

            let mut regs_a = PtraceSyscallExecutor::new(source_leader)?.getregs()?;
            regs_a.rip = CODE_ADDR;
            regs_a.rdi = pipe_fds[1] as u64;
            regs_a.rsi = SCRATCH_ADDR + SCRATCH_A_OFFSET as u64;
            regs_a.fs_base = TLS_A_ADDR;
            PtraceRegisterWriter::new(source_leader)?.write_regs(&regs_a)?;
            let captured_regs_a = PtraceSyscallExecutor::new(source_leader)?.getregs()?;
            if captured_regs_a.fs_base != TLS_A_ADDR {
                return Err(FdError::TraceeInstallFailed(
                    "source leader FS base did not capture",
                ));
            }

            let mut regs_b = PtraceSyscallExecutor::new(source_follower)?.getregs()?;
            regs_b.rip = CODE_ADDR;
            regs_b.rdi = pipe_fds[1] as u64;
            regs_b.rsi = SCRATCH_ADDR + SCRATCH_B_OFFSET as u64;
            regs_b.fs_base = TLS_B_ADDR;
            PtraceRegisterWriter::new(source_follower)?.write_regs(&regs_b)?;
            let captured_regs_b = PtraceSyscallExecutor::new(source_follower)?.getregs()?;
            if captured_regs_b.fs_base != TLS_B_ADDR {
                return Err(FdError::TraceeInstallFailed(
                    "source follower FS base did not capture",
                ));
            }

            let captured_threads = vec![
                KboxlikeThreadSnapshot {
                    host_pid: source_leader,
                    model_pid: MODEL_PID,
                    model_thread_id: MODEL_THREAD_A,
                    regs: captured_regs_a,
                },
                KboxlikeThreadSnapshot {
                    host_pid: source_follower,
                    model_pid: MODEL_PID,
                    model_thread_id: MODEL_THREAD_B,
                    regs: captured_regs_b,
                },
            ];
            let replacement_created =
                create_stopped_replacement_tracee_set(&captured_threads, &mut replacement_factory)?;
            let replacement_leader = *replacement_created
                .replacement_host_pids
                .get(&MODEL_THREAD_A)
                .ok_or(FdError::TraceeInstallFailed(
                    "missing FS replacement leader",
                ))?;
            let replacement_follower = *replacement_created
                .replacement_host_pids
                .get(&MODEL_THREAD_B)
                .ok_or(FdError::TraceeInstallFailed(
                    "missing FS replacement follower",
                ))?;

            let mut code_page = vec![0xcc; 0x100];
            code_page[..READ_FS_WRITE_AND_PAUSE_STUB.len()]
                .copy_from_slice(READ_FS_WRITE_AND_PAUSE_STUB);
            let scratch_page = vec![0u8; 0x100];
            let mut tls_a_page = vec![0u8; 0x100];
            let mut tls_b_page = vec![0u8; 0x100];
            tls_a_page[0] = b'A';
            tls_b_page[0] = b'B';
            let action_for =
                |start, prot, bytes| KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                    host_pid: source_leader,
                    model_pid: MODEL_PID,
                    start,
                    prot,
                    bytes,
                    source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
                };
            let restore = KboxlikeMaterializedMemoryRestore {
                actions: vec![
                    action_for(CODE_ADDR, libc::PROT_READ | libc::PROT_EXEC, code_page),
                    action_for(
                        SCRATCH_ADDR,
                        libc::PROT_READ | libc::PROT_WRITE,
                        scratch_page,
                    ),
                    action_for(TLS_A_ADDR, libc::PROT_READ, tls_a_page),
                    action_for(TLS_B_ADDR, libc::PROT_READ, tls_b_page),
                ],
            };
            let mut access_factory = LinuxTraceeRestoreAccessFactory;
            let mut resumer = PtraceDetachRestoredTraceeResumer;

            let summary = apply_and_resume_stopped_tracee_restore_set_with_replacement_pids(
                &restore,
                &captured_threads,
                &[],
                &replacement_created.replacement_host_pids,
                std::process::id() as i32,
                &mut access_factory,
                &mut resumer,
            )?;
            assert_eq!(
                summary,
                TraceeRestoreAndResumeSetSummary {
                    restore: TraceeRestoreSetSummary {
                        tracees_restored: 2,
                        shared_objects: TraceeSharedObjectRegistryBuildSummary {
                            created_objects: 0,
                            initialized_extents: 0,
                            skipped_unsupported_objects: 0,
                        },
                        memory: TraceeMemoryRestoreSummary {
                            byte_backed_applied: 4,
                            clean_file_remapped: 0,
                            shared_object_remapped: 0,
                            skipped_no_mapping: 0,
                            deferred_unsupported: 0,
                            other_tracee: 4,
                        },
                        registers: TraceeRegisterRestoreSummary {
                            registers_restored: 2,
                            other_tracee: 2,
                        },
                    },
                    resume: TraceeResumeSetSummary { tracees_resumed: 2 },
                },
            );

            let bytes = read_two_pipe_bytes(pipe_fds[0], replacement_leader, replacement_follower)?;
            if bytes != b"AB" {
                return Err(FdError::TraceeInstallFailed(
                    "restored FS-base threads wrote unexpected pipe bytes",
                ));
            }

            Ok(())
        })();

        replacement_factory.kill_created_tracees();
        source_factory.kill_created_tracees();
        unsafe {
            libc::close(pipe_fds[0]);
            libc::close(pipe_fds[1]);
        }
        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and Linux x86_64 clone tracing"]
    fn live_restored_thread_kernel_state_clears_child_tid_on_exit() {
        const CODE_ADDR: u64 = 0x7b00_0000_0000;
        const STATE_ADDR: u64 = 0x7b00_0000_1000;
        const EXIT_STUB_OFFSET: u64 = 0x40;
        const CLEAR_TID_ADDR: u64 = STATE_ADDR + 0x20;
        const ROBUST_LEADER_ADDR: u64 = STATE_ADDR + 0x40;
        const ROBUST_FOLLOWER_ADDR: u64 = STATE_ADDR + 0x80;
        const CAPTURED_HOST_A: i32 = 5111;
        const CAPTURED_HOST_B: i32 = 5222;
        const MODEL_PID: ProcessId = 7;
        const MODEL_THREAD_A: ModelThreadId = 1;
        const MODEL_THREAD_B: ModelThreadId = 2;
        const ROBUST_LIST_HEAD_LEN: u64 = 24;
        const PAUSE_STUB: &[u8] = &[
            0xb8, 0x22, 0x00, 0x00, 0x00, // mov eax, SYS_pause
            0x0f, 0x05, // syscall
            0xeb, 0xf7, // jmp back to pause
        ];
        const EXIT_THREAD_STUB: &[u8] = &[
            0xb8, 0x3c, 0x00, 0x00, 0x00, // mov eax, SYS_exit
            0x31, 0xff, // xor edi, edi
            0x0f, 0x05, // syscall
        ];

        fn robust_list_for_tid(tid: i32) -> Result<(u64, u64), FdError> {
            let mut head: *mut c_void = std::ptr::null_mut();
            let mut len: libc::size_t = 0;
            let ret = unsafe {
                libc::syscall(
                    libc::SYS_get_robust_list,
                    tid,
                    &mut head as *mut _,
                    &mut len as *mut _,
                )
            };
            if ret < 0 {
                return Err(FdError::TraceeInstallFailed("get_robust_list failed"));
            }
            Ok((head as u64, len as u64))
        }

        fn read_i32_from_tracee(pid: i32, addr: u64) -> Result<i32, FdError> {
            let mut value = 0i32;
            let local = libc::iovec {
                iov_base: &mut value as *mut _ as *mut c_void,
                iov_len: std::mem::size_of::<i32>(),
            };
            let remote = libc::iovec {
                iov_base: addr as *mut c_void,
                iov_len: std::mem::size_of::<i32>(),
            };
            let read = unsafe { libc::process_vm_readv(pid, &local, 1, &remote, 1, 0) };
            if read != std::mem::size_of::<i32>() as isize {
                return Err(FdError::TraceeInstallFailed("process_vm_readv i32 failed"));
            }
            Ok(value)
        }

        fn wait_for_clear_child_tid_zero(pid: i32, addr: u64) -> Result<(), FdError> {
            let deadline = std::time::Instant::now() + std::time::Duration::from_secs(5);
            while std::time::Instant::now() <= deadline {
                if read_i32_from_tracee(pid, addr)? == 0 {
                    return Ok(());
                }
                std::thread::sleep(std::time::Duration::from_millis(1));
            }
            Err(FdError::TraceeInstallFailed(
                "clear_child_tid was not cleared after thread exit",
            ))
        }

        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let seed_threads = vec![
            KboxlikeThreadSnapshot {
                host_pid: CAPTURED_HOST_A,
                model_pid: MODEL_PID,
                model_thread_id: MODEL_THREAD_A,
                regs,
            },
            KboxlikeThreadSnapshot {
                host_pid: CAPTURED_HOST_B,
                model_pid: MODEL_PID,
                model_thread_id: MODEL_THREAD_B,
                regs,
            },
        ];
        let mut replacement_factory = LinuxStoppedTraceeReplacementFactory::default();

        let result: Result<(), FdError> = (|| {
            let created =
                create_stopped_replacement_tracee_set(&seed_threads, &mut replacement_factory)?;
            let leader = *created.replacement_host_pids.get(&MODEL_THREAD_A).ok_or(
                FdError::TraceeInstallFailed("missing kernel-state replacement leader"),
            )?;
            let follower = *created.replacement_host_pids.get(&MODEL_THREAD_B).ok_or(
                FdError::TraceeInstallFailed("missing kernel-state replacement follower"),
            )?;

            let mut leader_regs = PtraceSyscallExecutor::new(leader)?.getregs()?;
            leader_regs.rip = CODE_ADDR;
            let mut follower_regs = PtraceSyscallExecutor::new(follower)?.getregs()?;
            follower_regs.rip = CODE_ADDR + EXIT_STUB_OFFSET;
            let captured_threads = vec![
                KboxlikeThreadSnapshot {
                    host_pid: CAPTURED_HOST_A,
                    model_pid: MODEL_PID,
                    model_thread_id: MODEL_THREAD_A,
                    regs: leader_regs,
                },
                KboxlikeThreadSnapshot {
                    host_pid: CAPTURED_HOST_B,
                    model_pid: MODEL_PID,
                    model_thread_id: MODEL_THREAD_B,
                    regs: follower_regs,
                },
            ];

            let mut code_page = vec![0xcc; 0x100];
            code_page[..PAUSE_STUB.len()].copy_from_slice(PAUSE_STUB);
            let exit_offset = EXIT_STUB_OFFSET as usize;
            code_page[exit_offset..exit_offset + EXIT_THREAD_STUB.len()]
                .copy_from_slice(EXIT_THREAD_STUB);
            let mut state_page = vec![0u8; 0x100];
            state_page[0x20..0x24].copy_from_slice(&0x5151_5151i32.to_ne_bytes());

            let action_for =
                |start, prot, bytes| KboxlikeMaterializedMemoryRestoreAction::ByteBacked {
                    host_pid: CAPTURED_HOST_A,
                    model_pid: MODEL_PID,
                    start,
                    prot,
                    bytes,
                    source: KboxlikeByteBackedRestoreSource::AnonymousPrivate { label: None },
                };
            let restore = KboxlikeMaterializedMemoryRestore {
                actions: vec![
                    action_for(CODE_ADDR, libc::PROT_READ | libc::PROT_EXEC, code_page),
                    action_for(STATE_ADDR, libc::PROT_READ | libc::PROT_WRITE, state_page),
                ],
            };
            let kernel_states = vec![
                KboxlikeThreadKernelStateSnapshot {
                    host_pid: CAPTURED_HOST_A,
                    model_pid: MODEL_PID,
                    model_thread_id: MODEL_THREAD_A,
                    clear_child_tid: None,
                    robust_list_head: Some(ROBUST_LEADER_ADDR),
                    robust_list_len: ROBUST_LIST_HEAD_LEN,
                },
                KboxlikeThreadKernelStateSnapshot {
                    host_pid: CAPTURED_HOST_B,
                    model_pid: MODEL_PID,
                    model_thread_id: MODEL_THREAD_B,
                    clear_child_tid: Some(CLEAR_TID_ADDR),
                    robust_list_head: Some(ROBUST_FOLLOWER_ADDR),
                    robust_list_len: ROBUST_LIST_HEAD_LEN,
                },
            ];
            let mut access_factory = LinuxTraceeRestoreAccessFactory;
            let full_restore_summary = apply_stopped_tracee_full_restore_set_with_replacement_pids(
                &restore,
                &captured_threads,
                &kernel_states,
                &[],
                &created.replacement_host_pids,
                std::process::id() as i32,
                &mut access_factory,
            )?;
            assert_eq!(
                full_restore_summary,
                TraceeFullRestoreSetSummary {
                    tracees_restored: 2,
                    shared_objects: TraceeSharedObjectRegistryBuildSummary::default(),
                    memory: TraceeMemoryRestoreSummary {
                        byte_backed_applied: 2,
                        clean_file_remapped: 0,
                        shared_object_remapped: 0,
                        skipped_no_mapping: 0,
                        deferred_unsupported: 0,
                        other_tracee: 2,
                    },
                    kernel_state: TraceeKernelStateRestoreSummary {
                        clear_child_tid_applied: 1,
                        robust_list_applied: 2,
                        other_tracee: 2,
                    },
                    registers: TraceeRegisterRestoreSummary {
                        registers_restored: 2,
                        other_tracee: 2,
                    },
                }
            );
            assert_eq!(
                full_restore_summary.kernel_state,
                TraceeKernelStateRestoreSummary {
                    clear_child_tid_applied: 1,
                    robust_list_applied: 2,
                    other_tracee: 2,
                }
            );

            assert_eq!(
                robust_list_for_tid(leader)?,
                (ROBUST_LEADER_ADDR, ROBUST_LIST_HEAD_LEN)
            );
            assert_eq!(
                robust_list_for_tid(follower)?,
                (ROBUST_FOLLOWER_ADDR, ROBUST_LIST_HEAD_LEN)
            );
            if read_i32_from_tracee(leader, CLEAR_TID_ADDR)? == 0 {
                return Err(FdError::TraceeInstallFailed(
                    "clear_child_tid was zero before follower exit",
                ));
            }

            let mut resumer = PtraceDetachRestoredTraceeResumer;
            resumer.resume_restored_tracee(leader)?;
            resumer.resume_restored_tracee(follower)?;
            wait_for_clear_child_tid_zero(leader, CLEAR_TID_ADDR)?;
            Ok(())
        })();

        replacement_factory.kill_created_tracees();
        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and a Linux x86_64 tracee"]
    fn live_materialized_memory_restore_remaps_clean_file_into_stopped_child() {
        const ADDR: u64 = 0x7100_0000_0000;
        const BYTES: &[u8] = b"kboxlike-clean-file-remap";

        let path =
            std::env::temp_dir().join(format!("kboxlike-clean-remap-{}", std::process::id()));
        std::fs::write(&path, BYTES).unwrap();

        let child = unsafe { libc::fork() };
        assert!(child >= 0, "fork failed");

        if child == 0 {
            unsafe {
                let ret = libc::ptrace(
                    libc::PTRACE_TRACEME,
                    0,
                    std::ptr::null_mut::<libc::c_void>(),
                    std::ptr::null_mut::<libc::c_void>(),
                );
                if ret < 0 {
                    libc::_exit(111);
                }
                libc::raise(libc::SIGSTOP);

                let restored = std::slice::from_raw_parts(ADDR as *const u8, BYTES.len());
                if restored == BYTES {
                    libc::_exit(0);
                }
                libc::_exit(113);
            }
        }

        let result = (|| {
            let mut status = 0;
            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("initial tracee wait failed"));
            }
            if !libc::WIFSTOPPED(status) || libc::WSTOPSIG(status) != libc::SIGSTOP {
                return Err(FdError::TraceeInstallFailed(
                    "tracee did not stop at initial SIGSTOP",
                ));
            }

            let restore = KboxlikeMaterializedMemoryRestore {
                actions: vec![KboxlikeMaterializedMemoryRestoreAction::RemapCleanFile {
                    host_pid: child,
                    model_pid: 1,
                    start: ADDR,
                    len: BYTES.len() as u64,
                    prot: libc::PROT_READ,
                    path: path.clone(),
                    file_offset: 0,
                    dev: "00:00".to_string(),
                    inode: 1,
                }],
            };
            let mut writer = ProcessVmMemoryWriter::new(child)?;
            let mut executor = PtraceSyscallExecutor::new(child)?;

            let summary = apply_materialized_memory_restore_for_tracee(
                &restore,
                child,
                &mut writer,
                &mut executor,
            )?;
            assert_eq!(
                summary,
                TraceeMemoryRestoreSummary {
                    byte_backed_applied: 0,
                    clean_file_remapped: 1,
                    shared_object_remapped: 0,
                    skipped_no_mapping: 0,
                    deferred_unsupported: 0,
                    other_tracee: 0,
                }
            );

            let detach_ret = unsafe {
                libc::ptrace(
                    libc::PTRACE_DETACH,
                    child,
                    std::ptr::null_mut::<libc::c_void>(),
                    std::ptr::null_mut::<libc::c_void>(),
                )
            };
            if detach_ret < 0 {
                return Err(FdError::TraceeInstallFailed("ptrace detach failed"));
            }

            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("final tracee wait failed"));
            }
            if libc::WIFEXITED(status) && libc::WEXITSTATUS(status) == 0 {
                return Ok(());
            }
            Err(FdError::TraceeInstallFailed(
                "tracee did not observe remapped file bytes",
            ))
        })();

        if result.is_err() {
            unsafe {
                libc::kill(child, libc::SIGKILL);
                let mut status = 0;
                libc::waitpid(child, &mut status, 0);
            }
        }
        let _ = std::fs::remove_file(path);

        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and two Linux x86_64 tracees"]
    fn live_materialized_memory_restore_preserves_shared_mapping_visibility() {
        const ADDR: u64 = 0x7200_0000_0000;
        const BYTES: &[u8] = b"kboxlike-shared-remap";

        fn fork_shared_reader(addr: u64, bytes: &'static [u8]) -> libc::pid_t {
            let child = unsafe { libc::fork() };
            assert!(child >= 0, "fork failed");
            if child == 0 {
                unsafe {
                    let ret = libc::ptrace(
                        libc::PTRACE_TRACEME,
                        0,
                        std::ptr::null_mut::<libc::c_void>(),
                        std::ptr::null_mut::<libc::c_void>(),
                    );
                    if ret < 0 {
                        libc::_exit(111);
                    }
                    libc::raise(libc::SIGSTOP);

                    let restored = std::slice::from_raw_parts(addr as *const u8, bytes.len());
                    if restored == bytes {
                        libc::_exit(0);
                    }
                    libc::_exit(113);
                }
            }
            child
        }

        fn wait_initial_stop(child: libc::pid_t) -> Result<(), FdError> {
            let mut status = 0;
            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("initial tracee wait failed"));
            }
            if !libc::WIFSTOPPED(status) || libc::WSTOPSIG(status) != libc::SIGSTOP {
                return Err(FdError::TraceeInstallFailed(
                    "tracee did not stop at initial SIGSTOP",
                ));
            }
            Ok(())
        }

        fn detach_and_wait_clean(child: libc::pid_t) -> Result<(), FdError> {
            let detach_ret = unsafe {
                libc::ptrace(
                    libc::PTRACE_DETACH,
                    child,
                    std::ptr::null_mut::<libc::c_void>(),
                    std::ptr::null_mut::<libc::c_void>(),
                )
            };
            if detach_ret < 0 {
                return Err(FdError::TraceeInstallFailed("ptrace detach failed"));
            }

            let mut status = 0;
            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("final tracee wait failed"));
            }
            if libc::WIFEXITED(status) && libc::WEXITSTATUS(status) == 0 {
                return Ok(());
            }
            Err(FdError::TraceeInstallFailed(
                "tracee did not observe shared bytes",
            ))
        }

        let name = std::ffi::CString::new("kboxlike-shared").unwrap();
        let memfd = unsafe { libc::memfd_create(name.as_ptr(), libc::MFD_CLOEXEC) };
        assert!(memfd >= 0, "memfd_create failed");
        let truncate_ret = unsafe { libc::ftruncate(memfd, 4096) };
        assert_eq!(truncate_ret, 0, "ftruncate failed");

        let child_a = fork_shared_reader(ADDR, BYTES);
        let child_b = fork_shared_reader(ADDR, BYTES);

        let result: Result<(), FdError> = (|| {
            wait_initial_stop(child_a)?;
            wait_initial_stop(child_b)?;

            let shared_action_for =
                |host_pid| KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                    host_pid,
                    model_pid: host_pid as u64,
                    start: ADDR,
                    len: 4096,
                    prot: libc::PROT_READ | libc::PROT_WRITE,
                    kind: KboxlikeSharedMappingKind::Memfd,
                    path: Some("/memfd:kboxlike-shared".to_string()),
                    file_offset: 0,
                    dev: "00:00".to_string(),
                    inode: 77,
                };
            let key = TraceeSharedObjectKey::from_action(&shared_action_for(child_a)).unwrap();
            let mut shared = TraceeSharedObjectRegistry::new();
            shared.register(key, memfd)?;

            for child in [child_a, child_b] {
                let restore = KboxlikeMaterializedMemoryRestore {
                    actions: vec![shared_action_for(child)],
                };
                let mut writer = ProcessVmMemoryWriter::new(child)?;
                let mut executor = PtraceSyscallExecutor::new(child)?;
                let summary = apply_materialized_memory_restore_for_tracee_with_shared_objects(
                    &restore,
                    child,
                    std::process::id() as i32,
                    &shared,
                    &mut writer,
                    &mut executor,
                )?;
                assert_eq!(
                    summary,
                    TraceeMemoryRestoreSummary {
                        byte_backed_applied: 0,
                        clean_file_remapped: 0,
                        shared_object_remapped: 1,
                        skipped_no_mapping: 0,
                        deferred_unsupported: 0,
                        other_tracee: 0,
                    }
                );
            }

            let mut writer = ProcessVmMemoryWriter::new(child_a)?;
            writer.write_bytes(ADDR, BYTES)?;

            detach_and_wait_clean(child_a)?;
            detach_and_wait_clean(child_b)?;
            Ok(())
        })();

        if result.is_err() {
            unsafe {
                libc::kill(child_a, libc::SIGKILL);
                libc::kill(child_b, libc::SIGKILL);
                let mut status = 0;
                libc::waitpid(child_a, &mut status, 0);
                libc::waitpid(child_b, &mut status, 0);
            }
        }
        unsafe {
            libc::close(memfd);
        }

        result.unwrap();
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and two Linux x86_64 tracees"]
    fn live_owned_shared_object_registry_initializes_and_remaps_shared_memory() {
        const ADDR: u64 = 0x7300_0000_0000;
        const BYTES: &[u8] = b"kboxlike-owned-shared";

        fn fork_shared_reader(addr: u64, bytes: &'static [u8]) -> libc::pid_t {
            let child = unsafe { libc::fork() };
            assert!(child >= 0, "fork failed");
            if child == 0 {
                unsafe {
                    let ret = libc::ptrace(
                        libc::PTRACE_TRACEME,
                        0,
                        std::ptr::null_mut::<libc::c_void>(),
                        std::ptr::null_mut::<libc::c_void>(),
                    );
                    if ret < 0 {
                        libc::_exit(111);
                    }
                    libc::raise(libc::SIGSTOP);

                    let restored = std::slice::from_raw_parts(addr as *const u8, bytes.len());
                    if restored == bytes {
                        libc::_exit(0);
                    }
                    libc::_exit(113);
                }
            }
            child
        }

        fn wait_initial_stop(child: libc::pid_t) -> Result<(), FdError> {
            let mut status = 0;
            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("initial tracee wait failed"));
            }
            if !libc::WIFSTOPPED(status) || libc::WSTOPSIG(status) != libc::SIGSTOP {
                return Err(FdError::TraceeInstallFailed(
                    "tracee did not stop at initial SIGSTOP",
                ));
            }
            Ok(())
        }

        fn detach_and_wait_clean(child: libc::pid_t) -> Result<(), FdError> {
            let detach_ret = unsafe {
                libc::ptrace(
                    libc::PTRACE_DETACH,
                    child,
                    std::ptr::null_mut::<libc::c_void>(),
                    std::ptr::null_mut::<libc::c_void>(),
                )
            };
            if detach_ret < 0 {
                return Err(FdError::TraceeInstallFailed("ptrace detach failed"));
            }

            let mut status = 0;
            let waited = unsafe { libc::waitpid(child, &mut status, 0) };
            if waited != child {
                return Err(FdError::TraceeInstallFailed("final tracee wait failed"));
            }
            if libc::WIFEXITED(status) && libc::WEXITSTATUS(status) == 0 {
                return Ok(());
            }
            Err(FdError::TraceeInstallFailed(
                "tracee did not observe initialized shared bytes",
            ))
        }

        let child_a = fork_shared_reader(ADDR, BYTES);
        let child_b = fork_shared_reader(ADDR, BYTES);

        let result: Result<(), FdError> = (|| {
            wait_initial_stop(child_a)?;
            wait_initial_stop(child_b)?;

            let shared_action_for =
                |host_pid| KboxlikeMaterializedMemoryRestoreAction::RecreateSharedObject {
                    host_pid,
                    model_pid: host_pid as u64,
                    start: ADDR,
                    len: BYTES.len() as u64,
                    prot: libc::PROT_READ,
                    kind: KboxlikeSharedMappingKind::Memfd,
                    path: Some("/memfd:kboxlike-owned-shared".to_string()),
                    file_offset: 0,
                    dev: "00:00".to_string(),
                    inode: 88,
                };
            let restore = KboxlikeMaterializedMemoryRestore {
                actions: vec![shared_action_for(child_a), shared_action_for(child_b)],
            };
            let dumps = vec![KboxlikeSharedMemoryDump {
                host_pid: child_a,
                model_pid: child_a as u64,
                start: ADDR,
                kind: KboxlikeSharedMappingKind::Memfd,
                path: Some("/memfd:kboxlike-owned-shared".to_string()),
                file_offset: 0,
                dev: "00:00".to_string(),
                inode: 88,
                bytes: BYTES.to_vec(),
            }];
            let owned = build_owned_shared_object_registry(&restore, &dumps)?;
            assert_eq!(
                owned.summary(),
                TraceeSharedObjectRegistryBuildSummary {
                    created_objects: 1,
                    initialized_extents: 1,
                    skipped_unsupported_objects: 0,
                }
            );

            for child in [child_a, child_b] {
                let mut writer = ProcessVmMemoryWriter::new(child)?;
                let mut executor = PtraceSyscallExecutor::new(child)?;
                let summary = apply_materialized_memory_restore_for_tracee_with_shared_objects(
                    &restore,
                    child,
                    std::process::id() as i32,
                    owned.registry(),
                    &mut writer,
                    &mut executor,
                )?;
                assert_eq!(
                    summary,
                    TraceeMemoryRestoreSummary {
                        byte_backed_applied: 0,
                        clean_file_remapped: 0,
                        shared_object_remapped: 1,
                        skipped_no_mapping: 0,
                        deferred_unsupported: 0,
                        other_tracee: 1,
                    }
                );
            }

            detach_and_wait_clean(child_a)?;
            detach_and_wait_clean(child_b)?;
            Ok(())
        })();

        if result.is_err() {
            unsafe {
                libc::kill(child_a, libc::SIGKILL);
                libc::kill(child_b, libc::SIGKILL);
                let mut status = 0;
                libc::waitpid(child_a, &mut status, 0);
                libc::waitpid(child_b, &mut status, 0);
            }
        }

        result.unwrap();
    }

    #[test]
    fn tracee_plan_rejects_bad_fds_and_source_target_alias() {
        assert_eq!(
            TraceeInstallPlan::new(-1, 6, false, false).unwrap_err(),
            FdError::InvalidFd(-1)
        );
        assert_eq!(
            TraceeInstallPlan::new(7, -2, false, false).unwrap_err(),
            FdError::InvalidFd(-2)
        );
        assert_eq!(
            TraceeInstallPlan::new(7, 7, false, false).unwrap_err(),
            FdError::TraceeInstallFailed("tracee source fd aliases target fd")
        );
    }

    #[test]
    fn proc_fd_source_plan_encodes_supervisor_fd_path_and_openat() {
        let source = TraceeProcFdSourcePlan::new(1234, 77, 0x7000).unwrap();

        assert_eq!(source.proc_fd_path(), "/proc/1234/fd/77");
        assert_eq!(source.path_bytes(), b"/proc/1234/fd/77\0");
        assert_eq!(
            source.open_syscall(),
            TraceeSyscall::new3(
                LINUX_X86_64_SYS_OPENAT,
                LINUX_AT_FDCWD,
                0x7000,
                LINUX_O_CLOEXEC,
            )
        );
    }

    #[test]
    fn proc_fd_source_plan_rejects_invalid_inputs() {
        assert_eq!(
            TraceeProcFdSourcePlan::new(0, 7, 0x7000).unwrap_err(),
            FdError::TraceeInstallFailed("invalid supervisor pid")
        );
        assert_eq!(
            TraceeProcFdSourcePlan::new(12, -1, 0x7000).unwrap_err(),
            FdError::InvalidFd(-1)
        );
        assert_eq!(
            TraceeProcFdSourcePlan::new(12, 7, 0).unwrap_err(),
            FdError::TraceeInstallFailed("tracee source path address is null")
        );
    }

    #[test]
    fn process_vm_memory_writer_rejects_invalid_pid() {
        assert_eq!(
            ProcessVmMemoryWriter::new(0).unwrap_err(),
            FdError::TraceeInstallFailed("invalid tracee pid")
        );
        assert_eq!(
            ProcessVmMemoryWriter::new(-1).unwrap_err(),
            FdError::TraceeInstallFailed("invalid tracee pid")
        );
        assert_eq!(ProcessVmMemoryWriter::new(1234).unwrap().pid(), 1234);
    }

    #[test]
    fn tracee_operation_install_request_rejects_invalid_tracee_pid() {
        assert_eq!(
            TraceeOperationInstallRequest::new(1, 0, 104, FdOperation::Mmap).unwrap_err(),
            FdError::TraceeInstallFailed("invalid tracee pid")
        );
        assert_eq!(
            TraceeOperationInstallRequest::new(1, -1, 104, FdOperation::Mmap).unwrap_err(),
            FdError::TraceeInstallFailed("invalid tracee pid")
        );
        assert_eq!(
            TraceeOperationInstallRequest::new(1, 4321, 104, FdOperation::Mmap).unwrap(),
            TraceeOperationInstallRequest {
                model_pid: 1,
                tracee_pid: 4321,
                fd: 104,
                operation: FdOperation::Mmap,
            }
        );
    }

    #[cfg(target_os = "linux")]
    #[test]
    fn process_vm_memory_writer_writes_current_process_memory() {
        let mut target = [0u8; 5];
        let addr = target.as_mut_ptr() as u64;
        let mut writer = ProcessVmMemoryWriter::new(std::process::id() as i32).unwrap();

        writer.write_bytes(addr, b"trace").unwrap();

        assert_eq!(&target, b"trace");
    }

    #[cfg(target_os = "linux")]
    #[test]
    fn process_vm_memory_writer_rejects_null_address() {
        let mut writer = ProcessVmMemoryWriter::new(std::process::id() as i32).unwrap();

        assert_eq!(
            writer.write_bytes(0, b"trace").unwrap_err(),
            FdError::TraceeInstallFailed("tracee memory address is null")
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn ptrace_syscall_executor_rejects_invalid_pid() {
        assert_eq!(
            PtraceSyscallExecutor::new(0).unwrap_err(),
            FdError::TraceeInstallFailed("invalid tracee pid")
        );
        assert_eq!(
            PtraceSyscallExecutor::new(-1).unwrap_err(),
            FdError::TraceeInstallFailed("invalid tracee pid")
        );
        assert_eq!(PtraceSyscallExecutor::new(1234).unwrap().pid(), 1234);
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and an unconfined parent/child test process"]
    fn ptrace_syscall_executor_runs_getpid_in_stopped_child() {
        unsafe {
            let child = libc::fork();
            assert!(child >= 0);
            if child == 0 {
                libc::ptrace(
                    libc::PTRACE_TRACEME,
                    0,
                    std::ptr::null_mut::<c_void>(),
                    std::ptr::null_mut::<c_void>(),
                );
                libc::raise(libc::SIGSTOP);
                libc::_exit(0);
            }

            let mut status = 0;
            assert_eq!(libc::waitpid(child, &mut status, 0), child);
            assert!(libc::WIFSTOPPED(status));

            let mut executor = PtraceSyscallExecutor::new(child).unwrap();
            let ret = executor.syscall(TraceeSyscall::new3(39, 0, 0, 0)).unwrap();
            assert_eq!(ret, child as i64);

            libc::kill(child, libc::SIGKILL);
            libc::waitpid(child, &mut status, 0);
        }
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    #[ignore = "requires ptrace permission and an unconfined parent/child test process"]
    fn ptrace_scratch_executor_survives_inherited_mapping_sweep() {
        const MODEL_PID: ProcessId = 7;
        const MODEL_THREAD: ModelThreadId = 1;
        const SYSCALL_PAGE: u64 = 0x7000_0000_0000;

        let regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
        let source_threads = [KboxlikeThreadSnapshot {
            host_pid: 1111,
            model_pid: MODEL_PID,
            model_thread_id: MODEL_THREAD,
            regs,
        }];
        let mut factory = LinuxStoppedTraceeReplacementFactory::default();

        let result: Result<(), FdError> = (|| {
            factory.prepare_syscall_page(SYSCALL_PAGE)?;
            let created = create_stopped_replacement_tracee_set(&source_threads, &mut factory)?;
            let replacement_pid = *created.replacement_host_pids.get(&MODEL_THREAD).ok_or(
                FdError::TraceeInstallFailed("missing replacement tracee pid"),
            )?;

            let mut executor = PtraceScratchSyscallExecutor::new(replacement_pid, SYSCALL_PAGE)?;
            let unmapped = executor.unmap_existing_mappings_except_scratch()?;
            assert!(unmapped > 0, "expected inherited mappings to be swept");
            let ret = executor.syscall(TraceeSyscall::new3(libc::SYS_getpid, 0, 0, 0))?;
            assert_eq!(ret, replacement_pid as i64);
            Ok(())
        })();

        factory.kill_created_tracees();
        result.unwrap();
    }

    #[test]
    fn apply_runs_tracee_syscalls_in_order() {
        let plan = TraceeInstallPlan::new(901, 104, true, true).unwrap();
        let mut tracee = FakeTracee::with_returns([104, 0, 0]);

        plan.apply(&mut tracee).unwrap();

        assert_eq!(tracee.calls, plan.syscalls());
    }

    #[test]
    fn apply_rejects_wrong_dup2_return() {
        let plan = TraceeInstallPlan::new(901, 104, true, false).unwrap();
        let mut tracee = FakeTracee::with_returns([105]);

        assert_eq!(
            plan.apply(&mut tracee).unwrap_err(),
            FdError::TraceeInstallFailed("tracee dup2 returned wrong fd")
        );
    }

    #[test]
    fn apply_rejects_negative_syscall_returns() {
        let plan = TraceeInstallPlan::new(901, 104, true, true).unwrap();
        let mut dup_fail = FakeTracee::with_returns([-1]);
        assert_eq!(
            plan.apply(&mut dup_fail).unwrap_err(),
            FdError::TraceeInstallFailed("tracee dup2 failed")
        );

        let mut fcntl_fail = FakeTracee::with_returns([104, -1]);
        assert_eq!(
            plan.apply(&mut fcntl_fail).unwrap_err(),
            FdError::TraceeInstallFailed("tracee fcntl failed")
        );

        let mut close_fail = FakeTracee::with_returns([104, 0, -1]);
        assert_eq!(
            plan.apply(&mut close_fail).unwrap_err(),
            FdError::TraceeInstallFailed("tracee close failed")
        );
    }

    #[test]
    fn proc_fd_shadow_install_opens_source_then_installs_and_closes_it() {
        let source = TraceeProcFdSourcePlan::new(1234, 77, 0x7000).unwrap();
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([901, 104, 0, 0]);

        apply_proc_fd_shadow_install(&source, shadow_install(104, true), &mut memory, &mut tracee)
            .unwrap();

        assert_eq!(
            memory.writes,
            vec![(0x7000, b"/proc/1234/fd/77\0".to_vec())]
        );
        assert_eq!(
            tracee.calls,
            vec![
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_OPENAT,
                    LINUX_AT_FDCWD,
                    0x7000,
                    LINUX_O_CLOEXEC,
                ),
                TraceeSyscall::new3(LINUX_X86_64_SYS_DUP2, 901, 104, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_FCNTL, 104, LINUX_F_SETFD, LINUX_FD_CLOEXEC),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 901, 0, 0),
            ]
        );
    }

    #[test]
    fn proc_fd_shadow_install_fails_if_source_open_fails() {
        let source = TraceeProcFdSourcePlan::new(1234, 77, 0x7000).unwrap();
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([-1]);

        assert_eq!(
            apply_proc_fd_shadow_install(
                &source,
                shadow_install(104, true),
                &mut memory,
                &mut tracee,
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("tracee open supervisor fd failed")
        );
        assert_eq!(
            memory.writes,
            vec![(0x7000, b"/proc/1234/fd/77\0".to_vec())]
        );
        assert_eq!(tracee.calls, vec![source.open_syscall()]);
    }

    #[test]
    fn proc_fd_shadow_install_fails_before_syscalls_if_path_write_fails() {
        let source = TraceeProcFdSourcePlan::new(1234, 77, 0x7000).unwrap();
        let mut memory = FakeMemory {
            writes: Vec::new(),
            fail: true,
        };
        let mut tracee = FakeTracee::with_returns([901, 104, 0, 0]);

        assert_eq!(
            apply_proc_fd_shadow_install(
                &source,
                shadow_install(104, true),
                &mut memory,
                &mut tracee,
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("tracee source path write failed")
        );
        assert!(memory.writes.is_empty());
        assert!(tracee.calls.is_empty());
    }

    #[test]
    fn proc_fd_shadow_install_with_scratch_maps_writes_installs_and_unmaps() {
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([0x7000, 901, 104, 0, 0, 0]);

        apply_proc_fd_shadow_install_with_scratch(
            1234,
            77,
            shadow_install(104, true),
            &mut memory,
            &mut tracee,
        )
        .unwrap();

        assert_eq!(
            memory.writes,
            vec![(0x7000, b"/proc/1234/fd/77\0".to_vec())]
        );
        assert_eq!(
            tracee.calls,
            vec![
                TraceeScratchMapping::mmap_syscall(17),
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_OPENAT,
                    LINUX_AT_FDCWD,
                    0x7000,
                    LINUX_O_CLOEXEC,
                ),
                TraceeSyscall::new3(LINUX_X86_64_SYS_DUP2, 901, 104, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_FCNTL, 104, LINUX_F_SETFD, LINUX_FD_CLOEXEC),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 901, 0, 0),
                TraceeSyscall::new6(LINUX_X86_64_SYS_MUNMAP, [0x7000, 17, 0, 0, 0, 0]),
            ]
        );
    }

    #[test]
    fn proc_fd_shadow_install_with_scratch_unmaps_after_install_failure() {
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([0x7000, -1, 0]);

        assert_eq!(
            apply_proc_fd_shadow_install_with_scratch(
                1234,
                77,
                shadow_install(104, true),
                &mut memory,
                &mut tracee,
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("tracee open supervisor fd failed")
        );
        assert_eq!(
            memory.writes,
            vec![(0x7000, b"/proc/1234/fd/77\0".to_vec())]
        );
        assert_eq!(
            tracee.calls,
            vec![
                TraceeScratchMapping::mmap_syscall(17),
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_OPENAT,
                    LINUX_AT_FDCWD,
                    0x7000,
                    LINUX_O_CLOEXEC,
                ),
                TraceeSyscall::new6(LINUX_X86_64_SYS_MUNMAP, [0x7000, 17, 0, 0, 0, 0]),
            ]
        );
    }

    #[test]
    fn proc_fd_shadow_install_with_scratch_returns_unmap_failure_after_successful_install() {
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([0x7000, 901, 104, 0, 0, -1]);

        assert_eq!(
            apply_proc_fd_shadow_install_with_scratch(
                1234,
                77,
                shadow_install(104, true),
                &mut memory,
                &mut tracee,
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("tracee munmap failed")
        );
    }

    #[test]
    fn proc_fd_shadow_install_with_scratch_aborts_before_write_if_mmap_fails() {
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([-12]);

        assert_eq!(
            apply_proc_fd_shadow_install_with_scratch(
                1234,
                77,
                shadow_install(104, true),
                &mut memory,
                &mut tracee,
            )
            .unwrap_err(),
            FdError::TraceeInstallFailed("tracee mmap failed")
        );
        assert!(memory.writes.is_empty());
        assert_eq!(tracee.calls, vec![TraceeScratchMapping::mmap_syscall(17)]);
    }

    #[test]
    fn shadow_install_plan_with_scratch_uses_plan_shadow_supervisor_fd() {
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([0x8000, 901, 104, 0, 0, 0]);

        apply_shadow_install_plan_with_scratch(
            1234,
            shadow_install(104, true),
            &mut memory,
            &mut tracee,
        )
        .unwrap();

        assert_eq!(
            memory.writes,
            vec![(0x8000, b"/proc/1234/fd/700\0".to_vec())]
        );
        assert_eq!(
            tracee.calls,
            vec![
                TraceeScratchMapping::mmap_syscall(18),
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_OPENAT,
                    LINUX_AT_FDCWD,
                    0x8000,
                    LINUX_O_CLOEXEC,
                ),
                TraceeSyscall::new3(LINUX_X86_64_SYS_DUP2, 901, 104, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_FCNTL, 104, LINUX_F_SETFD, LINUX_FD_CLOEXEC),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 901, 0, 0),
                TraceeSyscall::new6(LINUX_X86_64_SYS_MUNMAP, [0x8000, 18, 0, 0, 0, 0]),
            ]
        );
    }

    #[test]
    fn operation_shadow_installer_skips_plain_lkl_fd() {
        let mut fds = KboxlikeFdSystem::new();
        let pid = fds.spawn_init();
        fds.insert_plain_fd(pid, 4, Some(44), false).unwrap();
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([0x8000]);

        let installed = install_operation_shadow_if_needed(
            &fds,
            pid,
            4,
            FdOperation::Mmap,
            1234,
            &mut memory,
            &mut tracee,
        )
        .unwrap();

        assert!(!installed);
        assert!(memory.writes.is_empty());
        assert!(tracee.calls.is_empty());
    }

    #[test]
    fn operation_shadow_installer_installs_shadow_for_mmap() {
        let mut fds = KboxlikeFdSystem::new();
        let pid = fds.spawn_init();
        fds.insert_shadow_fd(
            pid,
            104,
            Some(204),
            ShadowObject {
                kind: ShadowKind::LocalOnly,
                supervisor_fd: 700,
            },
            true,
        )
        .unwrap();
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([0x8000, 901, 104, 0, 0, 0]);

        let installed = install_operation_shadow_if_needed(
            &fds,
            pid,
            104,
            FdOperation::Mmap,
            1234,
            &mut memory,
            &mut tracee,
        )
        .unwrap();

        assert!(installed);
        assert_eq!(
            memory.writes,
            vec![(0x8000, b"/proc/1234/fd/700\0".to_vec())]
        );
        assert_eq!(
            tracee.calls,
            vec![
                TraceeScratchMapping::mmap_syscall(18),
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_OPENAT,
                    LINUX_AT_FDCWD,
                    0x8000,
                    LINUX_O_CLOEXEC,
                ),
                TraceeSyscall::new3(LINUX_X86_64_SYS_DUP2, 901, 104, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_FCNTL, 104, LINUX_F_SETFD, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 901, 0, 0),
                TraceeSyscall::new6(LINUX_X86_64_SYS_MUNMAP, [0x8000, 18, 0, 0, 0, 0]),
            ]
        );
    }

    #[test]
    fn requested_operation_shadow_installer_uses_request_identity_and_operation() {
        let mut fds = KboxlikeFdSystem::new();
        let pid = fds.spawn_init();
        fds.insert_shadow_fd(
            pid,
            104,
            Some(204),
            ShadowObject {
                kind: ShadowKind::LocalOnly,
                supervisor_fd: 700,
            },
            false,
        )
        .unwrap();
        let request =
            TraceeOperationInstallRequest::new(pid, 4321, 104, FdOperation::Mmap).unwrap();
        let mut memory = FakeMemory::default();
        let mut tracee = FakeTracee::with_returns([0x8000, 901, 104, 0, 0, 0]);

        let installed = install_requested_operation_shadow_if_needed(
            &fds,
            request,
            1234,
            &mut memory,
            &mut tracee,
        )
        .unwrap();

        assert!(installed);
        assert_eq!(
            memory.writes,
            vec![(0x8000, b"/proc/1234/fd/700\0".to_vec())]
        );
        assert_eq!(
            tracee.calls,
            vec![
                TraceeScratchMapping::mmap_syscall(18),
                TraceeSyscall::new3(
                    LINUX_X86_64_SYS_OPENAT,
                    LINUX_AT_FDCWD,
                    0x8000,
                    LINUX_O_CLOEXEC,
                ),
                TraceeSyscall::new3(LINUX_X86_64_SYS_DUP2, 901, 104, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_FCNTL, 104, LINUX_F_SETFD, 0),
                TraceeSyscall::new3(LINUX_X86_64_SYS_CLOSE, 901, 0, 0),
                TraceeSyscall::new6(LINUX_X86_64_SYS_MUNMAP, [0x8000, 18, 0, 0, 0, 0]),
            ]
        );
    }

    #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
    #[test]
    fn stopped_tracee_installer_rejects_invalid_tracee_before_planning() {
        let fds = KboxlikeFdSystem::new();
        let request = TraceeOperationInstallRequest {
            model_pid: 1,
            tracee_pid: -1,
            fd: 104,
            operation: FdOperation::Mmap,
        };

        assert_eq!(
            install_requested_operation_shadow_in_stopped_tracee(&fds, request, 1234).unwrap_err(),
            FdError::TraceeInstallFailed("invalid tracee pid")
        );
    }
}
