Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@ repository = "https://github.com/JohnTitor/mach2"
readme = "README.md"
keywords = ["kernel", "macos", "darwin"]
categories = ["api-bindings", "external-ffi-bindings", "no-std", "os"]
edition = "2015"
edition = "2024"
include = ["src/**/*", "LICENSE-*", "README.md"]

[badges]
maintenance = { status = "passively-maintained" }

[target.'cfg(target_vendor = "apple")'.dependencies]
libc = { version = "0.2", default-features = false }

Expand Down
10 changes: 5 additions & 5 deletions examples/dump_process_registers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ use mach2::thread_act::thread_get_state;
use mach2::traps::{mach_task_self, task_for_pid};
use mach2::vm::mach_vm_deallocate;

#[cfg(target_arch = "x86_64")]
use mach2::thread_status::x86_THREAD_STATE64 as THREAD_STATE64;
#[cfg(target_arch = "aarch64")]
use mach2::thread_status::ARM_THREAD_STATE64 as THREAD_STATE64;
#[cfg(target_arch = "x86_64")]
use mach2::thread_status::x86_THREAD_STATE64 as THREAD_STATE64;

#[cfg(target_arch = "aarch64")]
use mach2::structs::arm_thread_state64_t as thread_state64_t;
Expand All @@ -29,16 +29,16 @@ use mach2::structs::x86_thread_state64_t as thread_state64_t;

use std::io::prelude::*;

fn read_int() -> Result<::libc::c_int, ()> {
fn read_int() -> Result<libc::c_int, ()> {
let stdin = io::stdin();
let mut line = String::new();

stdin.read_line(&mut line).ok().unwrap();
let mut value: ::libc::c_int = 0;
let mut value: libc::c_int = 0;

for c in line.chars().take_while(|&c| c != '\n') {
if let Some(d) = c.to_digit(10) {
value = value * 10 + (d as ::libc::c_int);
value = value * 10 + (d as libc::c_int);
} else {
return Err(());
}
Expand Down
5 changes: 3 additions & 2 deletions mach-test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
[package]
name = "mach-test"
version = "0.1.0"
authors = ["gnzlbg <gonzalobg88@gmail.com>"]
authors = ["Yuki Okushi <huyuumi.dev@gmail.com>"]
build = "build.rs"
edition = "2021"

[dependencies]
mach2 = { path = ".." }
libc = "0.2"

[build-dependencies]
ctest = "0.4"
ctest = "=0.5.0-beta.1"

[[test]]
name = "main"
Expand Down
111 changes: 94 additions & 17 deletions mach-test/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
extern crate ctest;

use std::env;
use std::fs;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf};

#[derive(Eq, Ord, PartialEq, PartialOrd, Copy, Clone, Debug)]
struct Xcode(pub u32, pub u32);

Expand Down Expand Up @@ -38,6 +44,8 @@ impl Xcode {
}

fn main() {
inject_libc_extern();

let xcode = Xcode::version();
// kept on purpose for debugging:
// println!("cargo:warning=\"Xcode version: {:?}\"", xcode);
Expand Down Expand Up @@ -136,7 +144,7 @@ fn main() {
}

cfg.skip_struct(move |s| {
match s {
match s.ident() {
// TODO: this type is a bitfield and must be verified by hand
"mach_msg_type_descriptor_t" |

Expand All @@ -161,8 +169,8 @@ fn main() {
}
});

cfg.skip_type(move |s| {
match s {
cfg.skip_alias(move |s| {
match s.ident() {
// FIXME: this type is not exposed in /usr/include/mach
// but seems to be exposed in
// SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/mach
Expand All @@ -180,10 +188,10 @@ fn main() {

cfg.skip_fn(move |s| {
// FIXME: The return type of these functions are different in Xcode 13 or higher.
if s.starts_with("semaphore") {
if s.ident().starts_with("semaphore") {
return true;
}
match s {
match s.ident() {
// mac_task_self and current_tasl are not functions, but macro that map to the
// mask_task_self_ static variable:
"mach_task_self" | "current_task" => true,
Expand All @@ -192,7 +200,7 @@ fn main() {
}
});

cfg.skip_const(move |s| match s {
cfg.skip_const(move |s| match s.ident() {
"MACH_RCV_NOTIFY" | "MACH_RCV_OVERWRITE" if xcode <= Xcode(11, 0) => true,

// FIXME: Somehow it fails, like:
Expand All @@ -205,10 +213,6 @@ fn main() {
_ => false,
});

cfg.fn_cname(|rust, _link_name| match rust {
v => v.to_string(),
});

cfg.skip_signededness(|c| {
// signededness test does not make sense for these:
match c {
Expand Down Expand Up @@ -287,12 +291,10 @@ fn main() {
}
});

cfg.type_name(move |ty, is_struct, is_union| match ty {
t if is_union => format!("union {}", t),
t if t.ends_with("_t") => t.to_string(),
t @ "gpu_energy_data" => t.to_string(),
t if is_struct => format!("struct {}", t),
t => t.to_string(),
cfg.rename_struct_ty(move |ty| match ty {
t if t.ends_with("_t") => Some(t.to_string()),
t @ "gpu_energy_data" => Some(t.to_string()),
t => Some(format!("struct {}", t)),
});

cfg.skip_roundtrip(move |s| match s {
Expand All @@ -306,5 +308,80 @@ fn main() {

// Generate the tests, passing the path to the `*-sys` library as well as
// the module to generate.
cfg.generate("../src/lib.rs", "all.rs");
ctest::generate_test(&mut cfg, "../src/lib.rs", "all.rs").unwrap();
}

fn inject_libc_extern() {
if env::var_os("CTEST_LIBC_WRAPPER_INSTALLED").is_some() {
return;
}

let rustc = env::var("RUSTC").unwrap_or_else(|_| String::from("rustc"));

let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR must be set"));
let profile_dir = out_dir
.ancestors()
.nth(3)
.expect("failed to locate Cargo profile directory");
let deps_dir = profile_dir.join("deps");

let libc_artifact = find_libc_artifact(&deps_dir)
.unwrap_or_else(|| panic!("failed to locate libc artifact in {}", deps_dir.display()));

let wrapper_path = create_rustc_wrapper(&out_dir);

unsafe {
env::set_var("CTEST_REAL_RUSTC", &rustc);
env::set_var("CTEST_LIBC_ARTIFACT", &libc_artifact);
env::set_var("RUSTC", &wrapper_path);
env::set_var("CTEST_LIBC_WRAPPER_INSTALLED", "1");
}
}

fn find_libc_artifact(dir: &Path) -> Option<PathBuf> {
let mut fallback = None;
let entries = fs::read_dir(dir).ok()?;
for entry in entries.flatten() {
let path = entry.path();
let file_name = path.file_name()?.to_string_lossy();
if !file_name.starts_with("liblibc-") {
continue;
}
match path.extension().and_then(|ext| ext.to_str()) {
Some("rlib") => return Some(path),
Some("rmeta") | Some("a") | Some("lib") if fallback.is_none() => {
fallback = Some(path);
}
_ => {}
}
}
fallback
}

fn create_rustc_wrapper(out_dir: &Path) -> PathBuf {
#[cfg(unix)]
{
let wrapper_path = out_dir.join("rustc-with-libc.sh");
let script = r#"#!/bin/sh
exec "$CTEST_REAL_RUSTC" --extern "libc=$CTEST_LIBC_ARTIFACT" "$@"
"#;
fs::write(&wrapper_path, script).expect("failed to write rustc wrapper script");
let mut perms = fs::metadata(&wrapper_path)
.and_then(|meta| Ok(meta.permissions()))
.expect("failed to read wrapper permissions");
perms.set_mode(0o755);
fs::set_permissions(&wrapper_path, perms)
.expect("failed to set executable bit on rustc wrapper script");
wrapper_path
}
#[cfg(not(unix))]
{
let wrapper_path = out_dir.join("rustc-with-libc.cmd");
let script = r#"@echo off
setlocal
"%CTEST_REAL_RUSTC%" --extern libc="%CTEST_LIBC_ARTIFACT%" %*
"#;
fs::write(&wrapper_path, script).expect("failed to write rustc wrapper script");
wrapper_path
}
}
5 changes: 1 addition & 4 deletions mach-test/test/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#![allow(bad_style)]

extern crate libc;
extern crate mach2;

use mach2::boolean::*;
use mach2::bootstrap::*;
use mach2::clock::*;
Expand Down Expand Up @@ -51,7 +48,7 @@ use mach2::vm_types::*;
use libc::{c_int, c_uchar, c_uint, c_ulonglong, clock_t};

// Imported by mach, but kept private:
extern "C" {
unsafe extern "C" {
static mach_task_self_: mach_port_t;
}

Expand Down
4 changes: 2 additions & 2 deletions src/boolean.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! This module corresponds to `mach/i386/boolean.h`.

#[cfg(target_arch = "x86_64")]
pub type boolean_t = ::libc::c_uint;
pub type boolean_t = libc::c_uint;

#[cfg(not(target_arch = "x86_64"))]
pub type boolean_t = ::libc::c_int;
pub type boolean_t = libc::c_int;
60 changes: 30 additions & 30 deletions src/bootstrap.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
//! This module corresponds to `bootstrap.h`

use boolean::boolean_t;
use kern_return::kern_return_t;
use port::mach_port_t;
use crate::boolean::boolean_t;
use crate::kern_return::kern_return_t;
use crate::port::mach_port_t;

pub const BOOTSTRAP_MAX_NAME_LEN: ::libc::c_uint = 128;
pub const BOOTSTRAP_MAX_CMD_LEN: ::libc::c_uint = 512;
pub const BOOTSTRAP_MAX_NAME_LEN: libc::c_uint = 128;
pub const BOOTSTRAP_MAX_CMD_LEN: libc::c_uint = 512;

pub const BOOTSTRAP_MAX_LOOKUP_COUNT: ::libc::c_uint = 20;
pub const BOOTSTRAP_MAX_LOOKUP_COUNT: libc::c_uint = 20;

pub const BOOTSTRAP_SUCCESS: ::libc::c_uint = 0;
pub const BOOTSTRAP_NOT_PRIVILEGED: ::libc::c_uint = 1100;
pub const BOOTSTRAP_NAME_IN_USE: ::libc::c_uint = 1101;
pub const BOOTSTRAP_UNKNOWN_SERVICE: ::libc::c_uint = 1102;
pub const BOOTSTRAP_SERVICE_ACTIVE: ::libc::c_uint = 1103;
pub const BOOTSTRAP_BAD_COUNT: ::libc::c_uint = 1104;
pub const BOOTSTRAP_NO_MEMORY: ::libc::c_uint = 1105;
pub const BOOTSTRAP_NO_CHILDREN: ::libc::c_uint = 1106;
pub const BOOTSTRAP_SUCCESS: libc::c_uint = 0;
pub const BOOTSTRAP_NOT_PRIVILEGED: libc::c_uint = 1100;
pub const BOOTSTRAP_NAME_IN_USE: libc::c_uint = 1101;
pub const BOOTSTRAP_UNKNOWN_SERVICE: libc::c_uint = 1102;
pub const BOOTSTRAP_SERVICE_ACTIVE: libc::c_uint = 1103;
pub const BOOTSTRAP_BAD_COUNT: libc::c_uint = 1104;
pub const BOOTSTRAP_NO_MEMORY: libc::c_uint = 1105;
pub const BOOTSTRAP_NO_CHILDREN: libc::c_uint = 1106;

pub const BOOTSTRAP_STATUS_INACTIVE: ::libc::c_uint = 0;
pub const BOOTSTRAP_STATUS_ACTIVE: ::libc::c_uint = 1;
pub const BOOTSTRAP_STATUS_ON_DEMAND: ::libc::c_uint = 2;
pub const BOOTSTRAP_STATUS_INACTIVE: libc::c_uint = 0;
pub const BOOTSTRAP_STATUS_ACTIVE: libc::c_uint = 1;
pub const BOOTSTRAP_STATUS_ON_DEMAND: libc::c_uint = 2;

pub type name_t = [::libc::c_char; 128];
pub type cmd_t = [::libc::c_char; 512];
pub type name_t = [libc::c_char; 128];
pub type cmd_t = [libc::c_char; 512];
pub type name_array_t = *mut name_t;
pub type bootstrap_status_t = ::libc::c_int;
pub type bootstrap_status_t = libc::c_int;
pub type bootstrap_status_array_t = *mut bootstrap_status_t;
pub type bootstrap_property_t = ::libc::c_uint;
pub type bootstrap_property_t = libc::c_uint;
pub type bootstrap_property_array_t = *mut bootstrap_property_t;
pub type bool_array_t = *mut boolean_t;

extern "C" {
unsafe extern "C" {
pub static bootstrap_port: mach_port_t;
pub fn bootstrap_create_server(
bp: mach_port_t,
server_cmd: *mut ::libc::c_char,
server_uid: ::libc::uid_t,
server_cmd: *mut libc::c_char,
server_uid: libc::uid_t,
on_demand: boolean_t,
server_port: *mut mach_port_t,
) -> kern_return_t;
Expand All @@ -49,28 +49,28 @@ extern "C" {
pub fn bootstrap_parent(bp: mach_port_t, parent_port: *mut mach_port_t) -> kern_return_t;
pub fn bootstrap_register(
bp: mach_port_t,
service_name: *mut ::libc::c_char,
service_name: *mut libc::c_char,
sp: mach_port_t,
) -> kern_return_t;
pub fn bootstrap_create_service(
bp: mach_port_t,
service_name: *mut ::libc::c_char,
service_name: *mut libc::c_char,
sp: *mut mach_port_t,
) -> kern_return_t;
pub fn bootstrap_check_in(
bp: mach_port_t,
service_name: *const ::libc::c_char,
service_name: *const libc::c_char,
sp: *mut mach_port_t,
) -> kern_return_t;
pub fn bootstrap_look_up(
bp: mach_port_t,
service_name: *const ::libc::c_char,
service_name: *const libc::c_char,
sp: *mut mach_port_t,
) -> kern_return_t;
pub fn bootstrap_status(
bp: mach_port_t,
service_name: *mut ::libc::c_char,
service_name: *mut libc::c_char,
service_active: *mut bootstrap_status_t,
) -> kern_return_t;
pub fn bootstrap_strerror(r: kern_return_t) -> *const ::libc::c_char;
pub fn bootstrap_strerror(r: kern_return_t) -> *const libc::c_char;
}
12 changes: 6 additions & 6 deletions src/clock.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//! This module roughly corresponds to `mach/clock.h`.

pub const clock_MSG_COUNT: ::libc::c_uint = 3;
pub const clock_MSG_COUNT: libc::c_uint = 3;

use clock_types::{alarm_type_t, clock_attr_t, clock_flavor_t, mach_timespec_t};
use kern_return::kern_return_t;
use mach_types::{clock_reply_t, clock_serv_t};
use message::mach_msg_type_number_t;
use crate::clock_types::{alarm_type_t, clock_attr_t, clock_flavor_t, mach_timespec_t};
use crate::kern_return::kern_return_t;
use crate::mach_types::{clock_reply_t, clock_serv_t};
use crate::message::mach_msg_type_number_t;

extern "C" {
unsafe extern "C" {
pub fn clock_get_time(
clock_serv: clock_serv_t,
cur_time: *mut mach_timespec_t,
Expand Down
Loading