Skip to content

Commit 5da8fa6

Browse files
tekknolagiclaude
andcommitted
ZJIT: Fix jitdump file creation for macOS samply integration
Use C open() syscall directly so samply's DYLD_INSERT_LIBRARIES preload can hook the call and discover the jitdump file. Fix file permissions (mode argument) and use PROT_READ only mmap on macOS (PROT_EXEC requires code signing). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e569d34 commit 5da8fa6

1 file changed

Lines changed: 22 additions & 8 deletions

File tree

zjit/src/jitdump.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,27 @@
77
88
use std::fs;
99
use std::io::{self, Write, BufWriter};
10+
use std::os::unix::io::{AsRawFd, FromRawFd};
1011
use std::sync::Mutex;
1112
use std::time::Instant;
1213

1314
// Raw libc bindings for mmap (no libc crate dependency)
1415
mod ffi {
15-
use std::os::raw::{c_void, c_int, c_long};
16+
use std::os::raw::{c_void, c_int, c_long, c_char};
1617
pub const PROT_READ: c_int = 1;
1718
pub const PROT_EXEC: c_int = 4;
1819
pub const MAP_PRIVATE: c_int = 0x0002;
1920
pub const MAP_FAILED: *mut c_void = !0 as *mut c_void;
21+
pub const O_RDWR: c_int = 2;
22+
pub const O_CREAT: c_int = 0x200;
23+
pub const O_TRUNC: c_int = 0x400;
2024
#[cfg(target_os = "linux")]
2125
pub const _SC_PAGESIZE: c_int = 30;
2226
#[cfg(target_os = "macos")]
2327
pub const _SC_PAGESIZE: c_int = 29;
2428
unsafe extern "C" {
29+
pub fn open(path: *const c_char, flags: c_int, ...) -> c_int;
30+
pub fn close(fd: c_int) -> c_int;
2531
pub fn mmap(addr: *mut c_void, len: usize, prot: c_int, flags: c_int, fd: c_int, offset: i64) -> *mut c_void;
2632
pub fn munmap(addr: *mut c_void, len: usize) -> c_int;
2733
pub fn sysconf(name: c_int) -> c_long;
@@ -73,12 +79,14 @@ impl JitdumpWriter {
7379
let pid = std::process::id();
7480
let path = format!("/tmp/jit-{pid}.dump");
7581

76-
let file = fs::OpenOptions::new()
77-
.create(true)
78-
.write(true)
79-
.truncate(true)
80-
.read(true)
81-
.open(&path)?;
82+
// Use C open() so samply can hook it on macOS to discover the jitdump file.
83+
// samply interposes open()/fopen() to detect jitdump paths.
84+
let c_path = std::ffi::CString::new(path.as_bytes()).unwrap();
85+
let fd = unsafe { ffi::open(c_path.as_ptr(), ffi::O_RDWR | ffi::O_CREAT | ffi::O_TRUNC, 0o644 as std::os::raw::c_int) };
86+
if fd < 0 {
87+
return Err(io::Error::last_os_error());
88+
}
89+
let file = unsafe { fs::File::from_raw_fd(fd) };
8290

8391
let epoch = Instant::now();
8492

@@ -98,11 +106,17 @@ impl JitdumpWriter {
98106
use std::os::unix::io::AsRawFd;
99107
let fd = writer.get_ref().as_raw_fd();
100108
let page_size = unsafe { ffi::sysconf(ffi::_SC_PAGESIZE) as usize };
109+
// mmap with PROT_READ|PROT_EXEC so Linux perf can discover the file.
110+
// On macOS, PROT_EXEC requires code signing, so use PROT_READ only.
111+
#[cfg(target_os = "linux")]
112+
let prot = ffi::PROT_READ | ffi::PROT_EXEC;
113+
#[cfg(not(target_os = "linux"))]
114+
let prot = ffi::PROT_READ;
101115
let mmap_ptr = unsafe {
102116
ffi::mmap(
103117
std::ptr::null_mut(),
104118
page_size,
105-
ffi::PROT_READ | ffi::PROT_EXEC,
119+
prot,
106120
ffi::MAP_PRIVATE,
107121
fd,
108122
0,

0 commit comments

Comments
 (0)