77
88use std:: fs;
99use std:: io:: { self , Write , BufWriter } ;
10+ use std:: os:: unix:: io:: { AsRawFd , FromRawFd } ;
1011use std:: sync:: Mutex ;
1112use std:: time:: Instant ;
1213
1314// Raw libc bindings for mmap (no libc crate dependency)
1415mod 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