mach-sys 0.5.4

forked from original mach, and merge from mach2/machx. A Rust interface to the user-space API of the Mach 3.0 kernel that underlies OSX.
Documentation
//! This module roughly corresponds to `mach/mach_vm.defs`.

use crate::ffi::{c_int, policy_t};

use crate::boolean::boolean_t;
use crate::kern_return::kern_return_t;
use crate::mach_types::{
    mem_entry_name_port_t,
    vm_task_entry_t
};
use crate::memory_object_types::{
    memory_object_offset_t,
    memory_object_size_t
};
use crate::message::mach_msg_type_number_t;
use crate::port::mach_port_t;
use crate::vm_attributes::{
    vm_machine_attribute_t,
    vm_machine_attribute_val_t
};
use crate::vm_behavior::vm_behavior_t;
use crate::vm_inherit::vm_inherit_t;
use crate::vm_prot::vm_prot_t;
use crate::vm_purgable::vm_purgable_t;
use crate::vm_region::{
    mach_vm_read_entry_t,
    vm_page_info_flavor_t,
    vm_page_info_t,
    vm_region_flavor_t,
    vm_region_info_t,
    vm_region_recurse_info_t,
};
use crate::vm_sync::vm_sync_t;
use crate::clock_types::time_value_t;
use crate::vm_types::{
    integer_t,
    mach_vm_address_t,
    mach_vm_offset_t,
    mach_vm_size_t,
    natural_t,
    vm_map_t,
    vm_offset_t,
    vm_size_t,
};

extern "C" {
    pub fn mach_vm_allocate(
        target:  vm_task_entry_t,
        address: *mut mach_vm_address_t,
        size:    mach_vm_size_t,
        flags:   c_int,
    ) -> kern_return_t;

    pub fn mach_vm_deallocate(
        target:  vm_task_entry_t,
        address: mach_vm_address_t,
        size:    mach_vm_size_t,
    ) -> kern_return_t;

    pub fn mach_vm_protect(
        target_task:    vm_task_entry_t,
        address:        mach_vm_address_t,
        size:           mach_vm_size_t,
        set_maximum:    boolean_t,
        new_protection: vm_prot_t,
    ) -> kern_return_t;

    pub fn mach_vm_inherit(
        target_task:     vm_task_entry_t,
        address:         mach_vm_address_t,
        size:            mach_vm_size_t,
        new_inheritance: vm_inherit_t,
    ) -> kern_return_t;

    pub fn mach_vm_read(
        target_task: vm_task_entry_t,
        address:     mach_vm_address_t,
        size:        mach_vm_size_t,
        data:        *mut vm_offset_t,
        dataCnt:     *mut mach_msg_type_number_t,
    ) -> kern_return_t;

    #[allow(improper_ctypes)]
    pub fn mach_vm_read_list(
        target_task: vm_task_entry_t,
        data_list:   mach_vm_read_entry_t,
        count:       natural_t,
    ) -> kern_return_t;

    pub fn mach_vm_write(
        target_task: vm_map_t,
        address:     mach_vm_address_t,
        data:        vm_offset_t,
        dataCnt:     mach_msg_type_number_t,
    ) -> kern_return_t;

    pub fn mach_vm_copy(
        target_task:    vm_task_entry_t,
        source_address: mach_vm_address_t,
        size:           mach_vm_size_t,
        dest_address:   mach_vm_address_t,
    ) -> kern_return_t;

    pub fn mach_vm_read_overwrite(
        target_task: vm_task_entry_t,
        address:     mach_vm_address_t,
        size:        mach_vm_size_t,
        data:        mach_vm_address_t,
        outsize:     *mut mach_vm_size_t,
    ) -> kern_return_t;

    pub fn mach_vm_msync(
        target_task: vm_task_entry_t,
        address:     mach_vm_address_t,
        size:        mach_vm_size_t,
        sync_flags:  vm_sync_t,
    ) -> kern_return_t;

    pub fn mach_vm_behavior_set(
        target_task:  vm_task_entry_t,
        address:      mach_vm_address_t,
        size:         mach_vm_size_t,
        new_behavior: vm_behavior_t,
    ) -> kern_return_t;

    pub fn mach_vm_map(
        target_task:    vm_task_entry_t,
        inout:          *mut mach_vm_address_t,
        size:           mach_vm_size_t,
        mask:           mach_vm_offset_t,
        flags:          c_int,
        object:         mem_entry_name_port_t,
        offset:         memory_object_offset_t,
        copy:           boolean_t,
        cur_protection: vm_prot_t,
        max_protection: vm_prot_t,
        inheritance:    vm_inherit_t,
    ) -> kern_return_t;

    pub fn mach_vm_machine_attribute(
        target_task: vm_task_entry_t,
        address:     mach_vm_address_t,
        size:        mach_vm_size_t,
        attribute:   vm_machine_attribute_t,
        value:       *mut vm_machine_attribute_val_t,
    ) -> kern_return_t;

    pub fn mach_vm_remap(
        target_task:    vm_task_entry_t,
        target_address: *mut mach_vm_address_t,
        size:           mach_vm_size_t,
        mask:           mach_vm_offset_t,
        flags:          c_int,
        src_task:       vm_task_entry_t,
        src_address:    mach_vm_address_t,
        copy:           boolean_t,
        cur_protection: *mut vm_prot_t,
        out:            *mut vm_prot_t,
        inheritance:    vm_inherit_t,
    ) -> kern_return_t;

    pub fn mach_vm_page_query(
        target_map:  vm_map_t,
        offset:      mach_vm_offset_t,
        disposition: *mut integer_t,
        ref_count:   *mut integer_t,
    ) -> kern_return_t;

    pub fn mach_vm_region_recurse(
        target_task:   vm_task_entry_t,
        address:       *mut mach_vm_address_t,
        size:          *mut mach_vm_size_t,
        nesting_depth: *mut natural_t,
        info:          vm_region_recurse_info_t,
        infoCnt:       *mut mach_msg_type_number_t,
    ) -> kern_return_t;

    pub fn mach_vm_region(
        target_task: vm_task_entry_t,
        address:     *mut mach_vm_address_t,
        size:        *mut mach_vm_size_t,
        flavor:      vm_region_flavor_t,
        info:        vm_region_info_t,
        infoCnt:     *mut mach_msg_type_number_t,
        object_name: *mut mach_port_t,
    ) -> kern_return_t;

    pub fn mach_make_memory_entry(
        target_task:   vm_map_t,
        size:          *mut vm_size_t,
        offset:        vm_offset_t,
        permission:    vm_prot_t,
        object_handle: *mut mem_entry_name_port_t,
        parent_handle: mem_entry_name_port_t,
    ) -> kern_return_t;

    pub fn mach_make_memory_entry_64(
        target_task:   vm_map_t,
        size:          *mut memory_object_size_t,
        offset:        memory_object_offset_t,
        permission:    vm_prot_t,
        object_handle: *mut mach_port_t,
        parent_entry:  mem_entry_name_port_t,
    ) -> kern_return_t;

    pub fn mach_vm_purgable_control(
        target_task: vm_task_entry_t,
        address:     mach_vm_address_t,
        control:     vm_purgable_t,
        state:       *mut c_int,
    ) -> kern_return_t;

    pub fn mach_vm_page_info(
        target_task: vm_task_entry_t,
        address:     mach_vm_address_t,
        flavor:      vm_page_info_flavor_t,
        info:        vm_page_info_t,
        infoCnt:     *mut mach_msg_type_number_t,
    ) -> kern_return_t;
}

pub type thread_basic_info_data = thread_basic_info_t;

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct thread_basic_info_t {
    pub user_time:     time_value_t,
    pub system_time:   time_value_t,
    pub cpu_usage:     integer_t,
    pub policy:        policy_t,
    pub run_state:     integer_t,
    pub flags:         integer_t,
    pub suspend_count: integer_t,
    pub sleep_time:    integer_t,
}

#[cfg(test)]
mod tests {
    use super::*;

    use crate::kern_return::KERN_SUCCESS;
    use crate::traps::mach_task_self;
    use crate::vm_statistics::VM_FLAGS_ANYWHERE;

    #[test]
    fn mach_vm_allocate_sanity() {
        unsafe {
            let size = 0x100;
            let task = mach_task_self();

            let mut address: mach_vm_address_t = 0;
            assert_eq!(mach_vm_allocate(task, &mut address, size, VM_FLAGS_ANYWHERE), KERN_SUCCESS);
            assert_eq!(mach_vm_deallocate(task, address, size), KERN_SUCCESS);
        }
    }

    #[test]
    fn mach_vm_region_sanity() {
        use core::mem;

        use crate::vm_prot::{VM_PROT_EXECUTE, VM_PROT_READ};
        use crate::vm_region::{vm_region_basic_info_64, VM_REGION_BASIC_INFO_64};

        unsafe {
            let mut size = 0x10;
            let mut object_name = 0;
            #[allow(clippy::fn_to_numeric_cast)]
            let mut address = mach_vm_region_sanity as mach_vm_address_t;
            let mut info: vm_region_basic_info_64 = mem::zeroed();
            let mut info_size = vm_region_basic_info_64::count();

            let result = mach_vm_region(
                mach_task_self(),
                &mut address,
                &mut size,
                VM_REGION_BASIC_INFO_64,
                (&mut info as *mut _) as vm_region_info_t,
                &mut info_size,
                &mut object_name,
            );
            assert_eq!(result, KERN_SUCCESS);
            assert_eq!(info.protection, VM_PROT_READ | VM_PROT_EXECUTE);
        }
    }
}