BHM: Support aarch64 for Mac sampler (#31298)

Replaced unmaintained `mach` crate with `mach2`, and added support for getting arm registers.
This commit is contained in:
Rajesh Malviya 2024-02-09 19:25:28 +05:30 committed by GitHub
parent f6b81a97f3
commit 9d42602fe7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 52 additions and 24 deletions

11
Cargo.lock generated
View file

@ -283,7 +283,7 @@ dependencies = [
"lazy_static", "lazy_static",
"libc", "libc",
"log", "log",
"mach", "mach2",
"msg", "msg",
"nix 0.25.1", "nix 0.25.1",
"serde_json", "serde_json",
@ -3428,6 +3428,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "mach2"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "malloc_buf" name = "malloc_buf"
version = "0.0.6" version = "0.0.6"

View file

@ -25,7 +25,7 @@ serde_json = { workspace = true }
lazy_static = { workspace = true } lazy_static = { workspace = true }
[target.'cfg(target_os = "macos")'.dependencies] [target.'cfg(target_os = "macos")'.dependencies]
mach = "0.3" mach2 = "0.4"
[target.'cfg(all(target_os = "linux", not(any(target_arch = "arm", target_arch = "aarch64"))))'.dependencies] [target.'cfg(all(target_os = "linux", not(any(target_arch = "arm", target_arch = "aarch64"))))'.dependencies]
nix = "0.25" nix = "0.25"

View file

@ -4,11 +4,11 @@
use std::{panic, process}; use std::{panic, process};
use {libc, mach}; use {libc, mach2};
use crate::sampler::{Address, NativeStack, Registers, Sampler}; use crate::sampler::{Address, NativeStack, Registers, Sampler};
type MonitoredThreadId = mach::mach_types::thread_act_t; type MonitoredThreadId = mach2::mach_types::thread_act_t;
pub struct MacOsSampler { pub struct MacOsSampler {
thread_id: MonitoredThreadId, thread_id: MonitoredThreadId,
@ -17,7 +17,7 @@ pub struct MacOsSampler {
impl MacOsSampler { impl MacOsSampler {
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub fn new() -> Box<dyn Sampler> { pub fn new() -> Box<dyn Sampler> {
let thread_id = unsafe { mach::mach_init::mach_thread_self() }; let thread_id = unsafe { mach2::mach_init::mach_thread_self() };
Box::new(MacOsSampler { thread_id }) Box::new(MacOsSampler { thread_id })
} }
} }
@ -55,8 +55,8 @@ impl Sampler for MacOsSampler {
} }
} }
fn check_kern_return(kret: mach::kern_return::kern_return_t) -> Result<(), ()> { fn check_kern_return(kret: mach2::kern_return::kern_return_t) -> Result<(), ()> {
if kret != mach::kern_return::KERN_SUCCESS { if kret != mach2::kern_return::KERN_SUCCESS {
return Err(()); return Err(());
} }
Ok(()) Ok(())
@ -64,16 +64,18 @@ fn check_kern_return(kret: mach::kern_return::kern_return_t) -> Result<(), ()> {
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn suspend_thread(thread_id: MonitoredThreadId) -> Result<(), ()> { unsafe fn suspend_thread(thread_id: MonitoredThreadId) -> Result<(), ()> {
check_kern_return(mach::thread_act::thread_suspend(thread_id)) check_kern_return(mach2::thread_act::thread_suspend(thread_id))
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn get_registers(thread_id: MonitoredThreadId) -> Result<Registers, ()> { unsafe fn get_registers(thread_id: MonitoredThreadId) -> Result<Registers, ()> {
let mut state = mach::structs::x86_thread_state64_t::new(); #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
let mut state_count = mach::structs::x86_thread_state64_t::count(); {
let kret = mach::thread_act::thread_get_state( let mut state = mach2::structs::x86_thread_state64_t::new();
let mut state_count = mach2::structs::x86_thread_state64_t::count();
let kret = mach2::thread_act::thread_get_state(
thread_id, thread_id,
mach::thread_status::x86_THREAD_STATE64, mach2::thread_status::x86_THREAD_STATE64,
(&mut state) as *mut _ as *mut _, (&mut state) as *mut _ as *mut _,
&mut state_count, &mut state_count,
); );
@ -84,10 +86,27 @@ unsafe fn get_registers(thread_id: MonitoredThreadId) -> Result<Registers, ()> {
frame_ptr: state.__rbp as Address, frame_ptr: state.__rbp as Address,
}) })
} }
#[cfg(target_arch = "aarch64")]
{
let mut state = mach2::structs::arm_thread_state64_t::new();
let mut state_count = mach2::structs::arm_thread_state64_t::count();
let kret = mach2::thread_act::thread_get_state(
thread_id,
mach2::thread_status::ARM_THREAD_STATE64,
(&mut state) as *mut _ as *mut _,
&mut state_count,
);
check_kern_return(kret)?;
Ok(Registers {
instruction_ptr: state.__pc as Address,
stack_ptr: state.__sp as Address,
frame_ptr: state.__fp as Address,
})
}
}
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn resume_thread(thread_id: MonitoredThreadId) -> Result<(), ()> { unsafe fn resume_thread(thread_id: MonitoredThreadId) -> Result<(), ()> {
check_kern_return(mach::thread_act::thread_resume(thread_id)) check_kern_return(mach2::thread_act::thread_resume(thread_id))
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]