@@ -51,14 +51,71 @@ const DRI3_OPCODE_PIXMAP_FROM_BUFFERS: u8 = 7;
5151const PRESENT_OPCODE_PRESENT_PIXMAP : u8 = 1 ;
5252pub const SHM_TEMPLATE : & str = "/dev/shm/krshm-XXXXXX" ;
5353pub const SHM_DIR : & str = "/dev/shm/" ;
54- const SYSCALL_INSTR : u32 = 0xd4000001 ;
5554static SYSCALL_OFFSET : OnceLock < usize > = OnceLock :: new ( ) ;
5655const CROSS_DOMAIN_CHANNEL_TYPE_X11 : u32 = 0x11 ;
5756const CROSS_DOMAIN_ID_TYPE_SHM : u32 = 5 ;
5857const CROSS_DOMAIN_CMD_FUTEX_NEW : u8 = 8 ;
5958const CROSS_DOMAIN_CMD_FUTEX_SIGNAL : u8 = 9 ;
6059const CROSS_DOMAIN_CMD_FUTEX_DESTROY : u8 = 10 ;
6160
61+ #[ cfg( target_arch = "aarch64" ) ]
62+ mod arch {
63+ use nix:: libc:: { c_long, c_ulonglong, user_regs_struct} ;
64+ pub type SyscallInstr = u32 ;
65+ pub const SYSCALL_INSTR : SyscallInstr = 0xd4000001 ;
66+
67+ pub fn set_syscall_addr ( regs : & mut user_regs_struct , syscall_addr : usize ) {
68+ regs. pc = syscall_addr as u64 ;
69+ }
70+
71+ pub fn fill_syscall_args (
72+ regs : & mut user_regs_struct ,
73+ syscall_no : c_long ,
74+ args : & [ c_ulonglong ; 6 ] ,
75+ ) {
76+ regs. regs [ ..6 ] . copy_from_slice ( args) ;
77+ regs. regs [ 8 ] = syscall_no as c_ulonglong ;
78+ }
79+
80+ pub fn get_syscall_result ( regs : & user_regs_struct ) -> c_ulonglong {
81+ regs. regs [ 0 ]
82+ }
83+ }
84+
85+ #[ cfg( target_arch = "x86_64" ) ]
86+ mod arch {
87+ use nix:: libc:: { c_long, c_ulonglong, user_regs_struct} ;
88+ pub type SyscallInstr = u16 ;
89+ pub const SYSCALL_INSTR : SyscallInstr = 0x05_0f ;
90+
91+ pub fn set_syscall_addr ( regs : & mut user_regs_struct , syscall_addr : usize ) {
92+ regs. rip = syscall_addr as u64 ;
93+ }
94+
95+ pub fn fill_syscall_args (
96+ regs : & mut user_regs_struct ,
97+ syscall_no : c_long ,
98+ args : & [ c_ulonglong ; 6 ] ,
99+ ) {
100+ regs. rdi = args[ 0 ] ;
101+ regs. rsi = args[ 1 ] ;
102+ regs. rdx = args[ 2 ] ;
103+ regs. r10 = args[ 3 ] ;
104+ regs. r8 = args[ 4 ] ;
105+ regs. r9 = args[ 5 ] ;
106+ regs. rax = syscall_no as c_ulonglong ;
107+ }
108+
109+ pub fn get_syscall_result ( regs : & user_regs_struct ) -> c_ulonglong {
110+ regs. rax
111+ }
112+ }
113+
114+ #[ cfg( not( any( target_arch = "aarch64" , target_arch = "x86_64" ) ) ) ]
115+ mod arch {
116+ pub const SYSCALL_INSTR : u32 = 0xffffffff ;
117+ }
118+
62119#[ repr( C ) ]
63120#[ derive( Debug , Default ) ]
64121struct ExportedHandle {
@@ -458,7 +515,7 @@ impl X11ProtocolHandler {
458515 // Allow everything in /dev/shm (including paths with trailing '(deleted)')
459516 let shmem_file = if filename. starts_with ( SHM_DIR ) {
460517 File :: from ( memfd)
461- } else if cfg ! ( not( target_arch = "aarch64" ) ) {
518+ } else if cfg ! ( not( any ( target_arch = "aarch64" , target_arch = "x86_64" ) ) ) {
462519 return Err ( Errno :: EOPNOTSUPP . into ( ) ) ;
463520 } else {
464521 let ( fd, shmem_path) = mkstemp ( SHM_TEMPLATE ) ?;
@@ -638,8 +695,7 @@ struct RemoteCaller {
638695}
639696
640697impl RemoteCaller {
641- // This is arch-specific, so gate it off of x86_64 builds done for CI purposes
642- #[ cfg( target_arch = "aarch64" ) ]
698+ #[ cfg( any( target_arch = "aarch64" , target_arch = "x86_64" ) ) ]
643699 fn with < R , F > ( pid : Pid , f : F ) -> Result < R >
644700 where
645701 F : FnOnce ( & RemoteCaller ) -> Result < R > ,
@@ -651,7 +707,7 @@ impl RemoteCaller {
651707 let syscall_addr = vdso_start + SYSCALL_OFFSET . get ( ) . unwrap ( ) ;
652708
653709 let mut regs = old_regs;
654- regs. pc = syscall_addr as u64 ;
710+ arch :: set_syscall_addr ( & mut regs, syscall_addr) ;
655711 ptrace:: setregs ( pid, regs) ?;
656712 let res = f ( & RemoteCaller { regs, pid } ) ?;
657713 ptrace:: setregs ( pid, old_regs) ?;
@@ -711,30 +767,29 @@ impl RemoteCaller {
711767 . map ( |x| x as i32 )
712768 }
713769
714- // This is arch-specific, so gate it off of x86_64 builds done for CI purposes
715- #[ cfg( target_arch = "aarch64" ) ]
770+ #[ cfg( any( target_arch = "aarch64" , target_arch = "x86_64" ) ) ]
716771 fn syscall ( & self , syscall_no : c_long , args : [ c_ulonglong ; 6 ] ) -> Result < c_ulonglong > {
717772 let mut regs = self . regs ;
718- regs. regs [ ..6 ] . copy_from_slice ( & args) ;
719- regs. regs [ 8 ] = syscall_no as c_ulonglong ;
773+ arch:: fill_syscall_args ( & mut regs, syscall_no, & args) ;
720774 ptrace:: setregs ( self . pid , regs) ?;
721775 ptrace:: step ( self . pid , None ) ?;
722776 let evt = waitpid ( self . pid , Some ( WaitPidFlag :: __WALL) ) ?;
723777 if !matches ! ( evt, WaitStatus :: Stopped ( _, _) ) {
724778 unimplemented ! ( ) ;
725779 }
726780 regs = ptrace:: getregs ( self . pid ) ?;
727- Ok ( regs. regs [ 0 ] )
781+ Ok ( arch :: get_syscall_result ( & regs) )
728782 }
729783
730- #[ cfg( not( target_arch = "aarch64" ) ) ]
784+ #[ cfg( not( any ( target_arch = "aarch64" , target_arch = "x86_64" ) ) ) ]
731785 fn with < R , F > ( _pid : Pid , _f : F ) -> Result < R >
732786 where
733787 F : FnOnce ( & RemoteCaller ) -> Result < R > ,
734788 {
735789 Err ( Errno :: EOPNOTSUPP . into ( ) )
736790 }
737- #[ cfg( not( target_arch = "aarch64" ) ) ]
791+
792+ #[ cfg( not( any( target_arch = "aarch64" , target_arch = "x86_64" ) ) ) ]
738793 fn syscall ( & self , _syscall_no : c_long , _args : [ c_ulonglong ; 6 ] ) -> Result < c_ulonglong > {
739794 Err ( Errno :: EOPNOTSUPP . into ( ) )
740795 }
@@ -799,10 +854,10 @@ pub fn start_x11bridge(display: u32) {
799854 // the same vDSO (which should be true if they are running under the same
800855 // kernel!)
801856 let ( vdso_start, vdso_end) = find_vdso ( None ) . unwrap ( ) ;
802- for off in ( 0 ..( vdso_end - vdso_start) ) . step_by ( 4 ) {
857+ for off in ( 0 ..( vdso_end - vdso_start) ) . step_by ( mem :: size_of :: < arch :: SyscallInstr > ( ) ) {
803858 let addr = vdso_start + off;
804- let val = unsafe { std:: ptr:: read ( addr as * const u32 ) } ;
805- if val == SYSCALL_INSTR {
859+ let val = unsafe { std:: ptr:: read ( addr as * const arch :: SyscallInstr ) } ;
860+ if val == arch :: SYSCALL_INSTR {
806861 SYSCALL_OFFSET . set ( off) . unwrap ( ) ;
807862 break ;
808863 }
0 commit comments