@@ -197,15 +197,36 @@ fn test_ptrace_syscall() {
197
197
#[ cfg( target_arch = "x86" ) ]
198
198
let get_syscall_id = || ptrace:: getregs ( child) . unwrap ( ) . orig_eax as libc:: c_long ;
199
199
200
+ // this duplicates `get_syscall_id` for the purpose of testing `ptrace::read_user`.
201
+ #[ cfg( target_arch = "x86_64" ) ]
202
+ let get_rax_offset = |user_struct_ptr : * const libc:: user | {
203
+ unsafe { & ( * user_struct_ptr) . regs . orig_rax as * const _ }
204
+ } ;
205
+ #[ cfg( target_arch = "x86" ) ]
206
+ let get_rax_offset = |user_struct_ptr : * const libc:: user | {
207
+ unsafe { & ( * user_struct_ptr) . regs . orig_eax as * const _ }
208
+ } ;
209
+
210
+ let get_syscall_from_user_area = || {
211
+ // Find the offset of `user.regs.rax` (or `eax` for x86)
212
+ let user_struct = std:: mem:: MaybeUninit :: < libc:: user > :: uninit ( ) ;
213
+ let user_struct_ptr = user_struct. as_ptr ( ) ;
214
+ let rax_offset = get_rax_offset ( user_struct_ptr) as usize - user_struct_ptr as usize ;
215
+
216
+ ptrace:: read_user ( child, rax_offset as _ ) . unwrap ( ) as libc:: c_long
217
+ } ;
218
+
200
219
// kill entry
201
220
ptrace:: syscall ( child, None ) . unwrap ( ) ;
202
221
assert_eq ! ( waitpid( child, None ) , Ok ( WaitStatus :: PtraceSyscall ( child) ) ) ;
203
222
assert_eq ! ( get_syscall_id( ) , :: libc:: SYS_kill ) ;
223
+ assert_eq ! ( get_syscall_from_user_area( ) , :: libc:: SYS_kill ) ;
204
224
205
225
// kill exit
206
226
ptrace:: syscall ( child, None ) . unwrap ( ) ;
207
227
assert_eq ! ( waitpid( child, None ) , Ok ( WaitStatus :: PtraceSyscall ( child) ) ) ;
208
228
assert_eq ! ( get_syscall_id( ) , :: libc:: SYS_kill ) ;
229
+ assert_eq ! ( get_syscall_from_user_area( ) , :: libc:: SYS_kill ) ;
209
230
210
231
// receive signal
211
232
ptrace:: syscall ( child, None ) . unwrap ( ) ;
0 commit comments