use super::*;
use crate::minidump_format::*;
fn os_version() -> (u32, u32, u32) {
let vers = mach::sysctl_string(b"kern.osproductversion\0");
let inner = || {
let mut it = vers.split('.');
let major: u32 = it.next()?.parse().ok()?;
let minor: u32 = it.next()?.parse().ok()?;
let patch: u32 = it.next().and_then(|p| p.parse().ok()).unwrap_or_default();
Some((major, minor, patch))
};
inner().unwrap_or_default()
}
#[inline]
fn build_version() -> String {
mach::sysctl_string(b"kern.osversion\0")
}
fn read_cpu_info(cpu: &mut format::CPU_INFORMATION) {
if !cfg!(target_arch = "x86_64") {
return;
}
let mut md_feats: u64 = 1 << 2 ;
let features: u64 = mach::sysctl_by_name(b"machdep.cpu.feature_bits\0");
macro_rules! map_feature {
($set:expr, $cpuid_bit:expr, $md_bit:expr) => {
if $set & (1 << $cpuid_bit) != 0 {
md_feats |= 1 << $md_bit;
}
};
}
map_feature!(
features, 4,
8
);
map_feature!(features, 6 , 9 );
map_feature!(
features, 23,
3
);
map_feature!(
features, 25,
6
);
map_feature!(
features, 26,
10
);
map_feature!(
features, 32,
13
);
map_feature!(
features, 45,
14
);
map_feature!(features, 58 , 17 );
map_feature!(
features, 62,
28
);
let ext_features: u64 = mach::sysctl_by_name(b"machdep.cpu.extfeature_bits\0");
map_feature!(
ext_features,
27,
32
);
map_feature!(
ext_features,
31,
7
);
let leaf_features: u32 = mach::sysctl_by_name(b"machdep.cpu.leaf7_feature_bits\0");
map_feature!(
leaf_features,
0,
22
);
md_feats |= 1 << 12 ;
md_feats |= 1 << 11 ;
cpu.data[..std::mem::size_of::<u64>()].copy_from_slice(&md_feats.to_ne_bytes());
}
impl MinidumpWriter {
pub(crate) fn write_system_info(
&mut self,
buffer: &mut DumpBuf,
_dumper: &TaskDumper,
) -> Result<MDRawDirectory, WriterError> {
let mut info_section = MemoryWriter::<MDRawSystemInfo>::alloc(buffer)?;
let dirent = MDRawDirectory {
stream_type: MDStreamType::SystemInfoStream as u32,
location: info_section.location(),
};
let number_of_processors: u8 = mach::int_sysctl_by_name(b"hw.ncpu\0");
let mut cpu: format::CPU_INFORMATION = unsafe { std::mem::zeroed() };
read_cpu_info(&mut cpu);
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
let processor_architecture = MDCPUArchitecture::PROCESSOR_ARCHITECTURE_AMD64;
let processor_level: u16 = mach::int_sysctl_by_name(b"machdep.cpu.family\0");
let model: u8 = mach::int_sysctl_by_name(b"machdep.cpu.model\0");
let stepping: u8 = mach::int_sysctl_by_name(b"machdep.cpu.stepping\0");
let processor_revision = ((model as u16) << 8) | stepping as u16;
} else if #[cfg(target_arch = "aarch64")] {
let processor_architecture = MDCPUArchitecture::PROCESSOR_ARCHITECTURE_ARM64_OLD;
let family: u32 = mach::sysctl_by_name(b"hw.cpufamily\0");
let processor_level = (family & 0xffff0000 >> 16) as u16;
let processor_revision = (family & 0x0000ffff) as u16;
} else {
compile_error!("unsupported target architecture");
}
}
let (major_version, minor_version, build_number) = os_version();
let os_version_loc = write_string_to_location(buffer, &build_version())?;
let info = MDRawSystemInfo {
processor_architecture: processor_architecture as u16,
processor_level,
processor_revision,
number_of_processors,
cpu,
platform_id: PlatformId::MacOs as u32,
product_type: 1, major_version,
minor_version,
build_number,
csd_version_rva: os_version_loc.rva,
suite_mask: 0,
reserved2: 0,
};
info_section.set_value(buffer, info)?;
Ok(dirent)
}
}