@@ -168,8 +168,6 @@ unsafe fn ptrace_other(request: Request, pid: Pid, addr: *mut c_void, data: *mut
168
168
169
169
/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`.
170
170
pub fn setoptions ( pid : Pid , options : Options ) -> Result < ( ) > {
171
- use std:: ptr;
172
-
173
171
let res = unsafe {
174
172
libc:: ptrace ( Request :: PTRACE_SETOPTIONS as RequestType ,
175
173
libc:: pid_t:: from ( pid) ,
@@ -238,12 +236,7 @@ pub fn syscall(pid: Pid) -> Result<()> {
238
236
/// Attaches to the process specified in pid, making it a tracee of the calling process.
239
237
pub fn attach ( pid : Pid ) -> Result < ( ) > {
240
238
unsafe {
241
- ptrace_other (
242
- Request :: PTRACE_ATTACH ,
243
- pid,
244
- ptr:: null_mut ( ) ,
245
- ptr:: null_mut ( ) ,
246
- ) . map ( |_| ( ) ) // ignore the useless return value
239
+ ptrace_other ( Request :: PTRACE_ATTACH , pid, ptr:: null_mut ( ) , ptr:: null_mut ( ) ) . map ( |_| ( ) ) // ignore the useless return value
247
240
}
248
241
}
249
242
@@ -275,3 +268,207 @@ pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
275
268
}
276
269
}
277
270
271
+ #[ cfg( target_arch = "x86_64" ) ]
272
+ #[ allow( non_camel_case_types) ]
273
+ #[ derive( Debug , PartialEq ) ]
274
+ /// Represents all possible ptrace-accessible registers on x86_64
275
+ pub enum Register {
276
+ R15 = 8 * :: libc:: R15 as isize ,
277
+ R14 = 8 * :: libc:: R14 as isize ,
278
+ R13 = 8 * :: libc:: R13 as isize ,
279
+ R12 = 8 * :: libc:: R12 as isize ,
280
+ RBP = 8 * :: libc:: RBP as isize ,
281
+ RBX = 8 * :: libc:: RBX as isize ,
282
+ R11 = 8 * :: libc:: R11 as isize ,
283
+ R10 = 8 * :: libc:: R10 as isize ,
284
+ R9 = 8 * :: libc:: R9 as isize ,
285
+ R8 = 8 * :: libc:: R8 as isize ,
286
+ RAX = 8 * :: libc:: RAX as isize ,
287
+ RCX = 8 * :: libc:: RCX as isize ,
288
+ RDX = 8 * :: libc:: RDX as isize ,
289
+ RSI = 8 * :: libc:: RSI as isize ,
290
+ RDI = 8 * :: libc:: RDI as isize ,
291
+ ORIG_RAX = 8 * :: libc:: ORIG_RAX as isize ,
292
+ RIP = 8 * :: libc:: RIP as isize ,
293
+ CS = 8 * :: libc:: CS as isize ,
294
+ EFLAGS = 8 * :: libc:: EFLAGS as isize ,
295
+ RSP = 8 * :: libc:: RSP as isize ,
296
+ SS = 8 * :: libc:: SS as isize ,
297
+ FS_BASE = 8 * :: libc:: FS_BASE as isize ,
298
+ GS_BASE = 8 * :: libc:: GS_BASE as isize ,
299
+ DS = 8 * :: libc:: DS as isize ,
300
+ ES = 8 * :: libc:: ES as isize ,
301
+ FS = 8 * :: libc:: FS as isize ,
302
+ GS = 8 * :: libc:: GS as isize ,
303
+ }
304
+
305
+ #[ cfg( target_arch = "x86" ) ]
306
+ #[ allow( non_camel_case_types) ]
307
+ #[ derive( Debug , PartialEq ) ]
308
+ /// Represents all possible ptrace-accessible registers on x86
309
+ pub enum Register {
310
+ EBX = 4 * :: libc:: EBX as isize ,
311
+ ECX = 4 * :: libc:: ECX as isize ,
312
+ EDX = 4 * :: libc:: EDX as isize ,
313
+ ESI = 4 * :: libc:: ESI as isize ,
314
+ EDI = 4 * :: libc:: EDI as isize ,
315
+ EBP = 4 * :: libc:: EBP as isize ,
316
+ EAX = 4 * :: libc:: EAX as isize ,
317
+ DS = 4 * :: libc:: DS as isize ,
318
+ ES = 4 * :: libc:: ES as isize ,
319
+ FS = 4 * :: libc:: FS as isize ,
320
+ GS = 4 * :: libc:: GS as isize ,
321
+ ORIG_EAX = 4 * :: libc:: ORIG_EAX as isize ,
322
+ EIP = 4 * :: libc:: EIP as isize ,
323
+ CS = 4 * :: libc:: CS as isize ,
324
+ EFL = 4 * :: libc:: EFL as isize ,
325
+ UESP = 4 * :: libc:: UESP as isize ,
326
+ SS = 4 * :: libc:: SS as isize ,
327
+ }
328
+
329
+ /// Returns the register containing nth register argument.
330
+ ///
331
+ /// 0th argument is considered to be the syscall number.
332
+ /// Please note that these mappings are only valid for 64-bit programs.
333
+ /// Use syscall_arg32 for tracing 32-bit programs instead.
334
+ ///
335
+ /// # Examples
336
+ ///
337
+ /// ```
338
+ /// # #[macro_use] extern crate nix;
339
+ /// # fn main() {
340
+ /// assert_eq!(syscall_arg!(1), nix::sys::ptrace::Register::RDI);
341
+ /// # }
342
+ #[ cfg( target_arch = "x86_64" ) ]
343
+ #[ macro_export]
344
+ macro_rules! syscall_arg {
345
+ ( 0 ) => ( $crate:: sys:: ptrace:: Register :: ORIG_RAX ) ;
346
+ ( 1 ) => ( $crate:: sys:: ptrace:: Register :: RDI ) ;
347
+ ( 2 ) => ( $crate:: sys:: ptrace:: Register :: RSI ) ;
348
+ ( 3 ) => ( $crate:: sys:: ptrace:: Register :: RDX ) ;
349
+ ( 4 ) => ( $crate:: sys:: ptrace:: Register :: R10 ) ;
350
+ ( 5 ) => ( $crate:: sys:: ptrace:: Register :: R8 ) ;
351
+ ( 6 ) => ( $crate:: sys:: ptrace:: Register :: R9 ) ;
352
+ }
353
+
354
+ /// Returns the register containing nth register argument for 32-bit programs
355
+ ///
356
+ /// 0th argument is considered to be the syscall number.
357
+ /// Please note that these mappings are only valid for 32-bit programs.
358
+ /// Use syscall_arg for tracing 64-bit programs instead.
359
+ ///
360
+ /// # Examples
361
+ ///
362
+ /// ```
363
+ /// # #[macro_use] extern crate nix;
364
+ /// # fn main() {
365
+ /// assert_eq!(syscall_arg32!(1), nix::sys::ptrace::Register::RBX);
366
+ /// # }
367
+ #[ cfg( target_arch = "x86_64" ) ]
368
+ #[ macro_export]
369
+ macro_rules! syscall_arg32 {
370
+ ( 0 ) => ( $crate:: sys:: ptrace:: Register :: ORIG_RAX ) ;
371
+ ( 1 ) => ( $crate:: sys:: ptrace:: Register :: RBX ) ;
372
+ ( 2 ) => ( $crate:: sys:: ptrace:: Register :: RCX ) ;
373
+ ( 3 ) => ( $crate:: sys:: ptrace:: Register :: RDX ) ;
374
+ ( 4 ) => ( $crate:: sys:: ptrace:: Register :: RSI ) ;
375
+ ( 5 ) => ( $crate:: sys:: ptrace:: Register :: RDI ) ;
376
+ ( 6 ) => ( $crate:: sys:: ptrace:: Register :: RBP ) ;
377
+ }
378
+
379
+ /// Returns the register containing nth register argument.
380
+ ///
381
+ /// 0th argument is considered to be the syscall number.
382
+ ///
383
+ /// # Examples
384
+ ///
385
+ /// ```
386
+ /// # #[macro_use] extern crate nix;
387
+ /// # fn main() {
388
+ /// assert_eq!(syscall_arg!(1), nix::sys::ptrace::Register::RDI);
389
+ /// # }
390
+ #[ cfg( target_arch = "x86" ) ]
391
+ #[ macro_export]
392
+ macro_rules! syscall_arg {
393
+ ( 0 ) => ( $crate:: sys:: ptrace:: Register :: ORIG_EAX ) ;
394
+ ( 1 ) => ( $crate:: sys:: ptrace:: Register :: EBX ) ;
395
+ ( 2 ) => ( $crate:: sys:: ptrace:: Register :: ECX ) ;
396
+ ( 3 ) => ( $crate:: sys:: ptrace:: Register :: EDX ) ;
397
+ ( 4 ) => ( $crate:: sys:: ptrace:: Register :: ESI ) ;
398
+ ( 5 ) => ( $crate:: sys:: ptrace:: Register :: EDI ) ;
399
+ ( 6 ) => ( $crate:: sys:: ptrace:: Register :: EBP ) ;
400
+ }
401
+
402
+ /// An integer type, whose size equals a machine word
403
+ ///
404
+ /// `ptrace` always returns a machine word. This type provides an abstraction
405
+ /// of the fact that on *nix systems, `c_long` is always a machine word,
406
+ /// so as to prevent the library from leaking C implementation-dependent types.
407
+ type Word = usize ;
408
+
409
+ /// Peeks a user-accessible register, as with `ptrace(PTRACE_PEEKUSER, ...)`
410
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
411
+ pub fn peekuser ( pid : Pid , reg : Register ) -> Result < Word > {
412
+ let reg_arg = ( reg as i32 ) as * mut c_void ;
413
+ unsafe {
414
+ ptrace_peek ( Request :: PTRACE_PEEKUSER , pid, reg_arg, ptr:: null_mut ( ) ) . map ( |r| r as Word )
415
+ }
416
+ }
417
+
418
+ /// Sets the value of a user-accessible register, as with `ptrace(PTRACE_POKEUSER, ...)`
419
+ ///
420
+ /// # Safety
421
+ /// When incorrectly used, may change the registers to bad values,
422
+ /// causing e.g. memory being corrupted by a syscall, thus is marked unsafe
423
+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
424
+ pub unsafe fn pokeuser ( pid : Pid , reg : Register , val : Word ) -> Result < ( ) > {
425
+ let reg_arg = ( reg as u64 ) as * mut c_void ;
426
+ ptrace_other ( Request :: PTRACE_POKEUSER , pid, reg_arg, val as * mut c_void ) . map ( |_| ( ) ) // ignore the useless return value
427
+ }
428
+
429
+ /// Peeks the memory of a process, as with `ptrace(PTRACE_PEEKDATA, ...)`
430
+ ///
431
+ /// A memory chunk of a size of a machine word is returned.
432
+ /// # Safety
433
+ /// This function allows for accessing arbitrary data in the traced process
434
+ /// and may crash the inferior if used incorrectly and is thus marked `unsafe`.
435
+ pub unsafe fn peekdata ( pid : Pid , addr : usize ) -> Result < Word > {
436
+ ptrace_peek (
437
+ Request :: PTRACE_PEEKDATA ,
438
+ pid,
439
+ addr as * mut c_void ,
440
+ ptr:: null_mut ( ) ,
441
+ ) . map ( |r| r as Word )
442
+ }
443
+
444
+ /// Modifies the memory of a process, as with `ptrace(PTRACE_POKEUSER, ...)`
445
+ ///
446
+ /// A memory chunk of a size of a machine word is overwriten in the requested
447
+ /// place in the memory of a process.
448
+ ///
449
+ /// # Safety
450
+ /// This function allows for accessing arbitrary data in the traced process
451
+ /// and may crash the inferior or introduce race conditions if used
452
+ /// incorrectly and is thus marked `unsafe`.
453
+ pub unsafe fn pokedata ( pid : Pid , addr : usize , val : Word ) -> Result < ( ) > {
454
+ ptrace_other (
455
+ Request :: PTRACE_POKEDATA ,
456
+ pid,
457
+ addr as * mut c_void ,
458
+ val as * mut c_void ,
459
+ ) . map ( |_| ( ) ) // ignore the useless return value
460
+ }
461
+
462
+ #[ cfg( test) ]
463
+ mod tests {
464
+ use super :: Word ;
465
+ use std:: mem:: size_of;
466
+ use libc:: c_long;
467
+
468
+ #[ test]
469
+ fn test_types ( ) {
470
+ // c_long is implementation defined, so make sure
471
+ // its width matches
472
+ assert_eq ! ( size_of:: <Word >( ) , size_of:: <c_long>( ) ) ;
473
+ }
474
+ }
0 commit comments