@@ -17,8 +17,10 @@ pub type AddressType = *mut ::libc::c_void;
17
17
target_arch = "x86_64" ,
18
18
any( target_env = "gnu" , target_env = "musl" )
19
19
) ,
20
- all( target_arch = "x86" , target_env = "gnu" )
21
- )
20
+ all( target_arch = "x86" , target_env = "gnu" ) ,
21
+ all( target_arch = "aarch64" , target_env = "gnu" ) ,
22
+ all( target_arch = "riscv64" , target_env = "gnu" ) ,
23
+ ) ,
22
24
) ) ]
23
25
use libc:: user_regs_struct;
24
26
@@ -170,6 +172,29 @@ libc_enum! {
170
172
}
171
173
}
172
174
175
+ libc_enum ! {
176
+ #[ cfg( all(
177
+ target_os = "linux" ,
178
+ target_env = "gnu" ,
179
+ any(
180
+ target_arch = "x86_64" ,
181
+ target_arch = "x86" ,
182
+ target_arch = "aarch64" ,
183
+ target_arch = "riscv64" ,
184
+ )
185
+ ) ) ]
186
+ #[ repr( i32 ) ]
187
+ /// Defining a specific register set, as used in [`getregset`] and [`setregset`].
188
+ #[ non_exhaustive]
189
+ pub enum RegisterSet {
190
+ NT_PRSTATUS ,
191
+ NT_PRFPREG ,
192
+ NT_PRPSINFO ,
193
+ NT_TASKSTRUCT ,
194
+ NT_AUXV ,
195
+ }
196
+ }
197
+
173
198
libc_bitflags ! {
174
199
/// Ptrace options used in conjunction with the PTRACE_SETOPTIONS request.
175
200
/// See `man ptrace` for more details.
@@ -217,6 +242,12 @@ fn ptrace_peek(
217
242
}
218
243
219
244
/// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
245
+ ///
246
+ /// Note that since `PTRACE_GETREGS` are not available on all platforms (as in [ptrace(2)]),
247
+ /// `ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, ...)` is used instead to achieve the same effect
248
+ /// on aarch64 and riscv64.
249
+ ///
250
+ /// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
220
251
#[ cfg( all(
221
252
target_os = "linux" ,
222
253
any(
@@ -231,7 +262,58 @@ pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
231
262
ptrace_get_data :: < user_regs_struct > ( Request :: PTRACE_GETREGS , pid)
232
263
}
233
264
265
+ /// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
266
+ ///
267
+ /// Note that since `PTRACE_GETREGS` are not available on all platforms (as in [ptrace(2)]),
268
+ /// `ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, ...)` is used instead to achieve the same effect
269
+ /// on aarch64 and riscv64.
270
+ ///
271
+ /// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
272
+ #[ cfg( all(
273
+ target_os = "linux" ,
274
+ target_env = "gnu" ,
275
+ any( target_arch = "aarch64" , target_arch = "riscv64" )
276
+ ) ) ]
277
+ pub fn getregs ( pid : Pid ) -> Result < user_regs_struct > {
278
+ getregset ( pid, RegisterSet :: NT_PRSTATUS )
279
+ }
280
+
281
+ /// Get a particular set of user registers, as with `ptrace(PTRACE_GETREGSET, ...)`
282
+ #[ cfg( all(
283
+ target_os = "linux" ,
284
+ target_env = "gnu" ,
285
+ any(
286
+ target_arch = "x86_64" ,
287
+ target_arch = "x86" ,
288
+ target_arch = "aarch64" ,
289
+ target_arch = "riscv64" ,
290
+ )
291
+ ) ) ]
292
+ pub fn getregset ( pid : Pid , set : RegisterSet ) -> Result < user_regs_struct > {
293
+ let request = Request :: PTRACE_GETREGSET ;
294
+ let mut data = mem:: MaybeUninit :: < user_regs_struct > :: uninit ( ) ;
295
+ let mut iov = libc:: iovec {
296
+ iov_base : data. as_mut_ptr ( ) . cast ( ) ,
297
+ iov_len : mem:: size_of :: < user_regs_struct > ( ) ,
298
+ } ;
299
+ unsafe {
300
+ ptrace_other (
301
+ request,
302
+ pid,
303
+ set as i32 as AddressType ,
304
+ ( & mut iov as * mut libc:: iovec ) . cast ( ) ,
305
+ ) ?;
306
+ } ;
307
+ Ok ( unsafe { data. assume_init ( ) } )
308
+ }
309
+
234
310
/// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)`
311
+ ///
312
+ /// Note that since `PTRACE_SETREGS` are not available on all platforms (as in [ptrace(2)]),
313
+ /// `ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, ...)` is used instead to achieve the same effect
314
+ /// on aarch64 and riscv64.
315
+ ///
316
+ /// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
235
317
#[ cfg( all(
236
318
target_os = "linux" ,
237
319
any(
@@ -248,12 +330,59 @@ pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
248
330
Request :: PTRACE_SETREGS as RequestType ,
249
331
libc:: pid_t:: from ( pid) ,
250
332
ptr:: null_mut :: < c_void > ( ) ,
251
- & regs as * const _ as * const c_void ,
333
+ & regs as * const user_regs_struct as * const c_void ,
252
334
)
253
335
} ;
254
336
Errno :: result ( res) . map ( drop)
255
337
}
256
338
339
+ /// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)`
340
+ ///
341
+ /// Note that since `PTRACE_SETREGS` are not available on all platforms (as in [ptrace(2)]),
342
+ /// `ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, ...)` is used instead to achieve the same effect
343
+ /// on aarch64 and riscv64.
344
+ ///
345
+ /// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
346
+ #[ cfg( all(
347
+ target_os = "linux" ,
348
+ target_env = "gnu" ,
349
+ any( target_arch = "aarch64" , target_arch = "riscv64" )
350
+ ) ) ]
351
+ pub fn setregs ( pid : Pid , regs : user_regs_struct ) -> Result < ( ) > {
352
+ setregset ( pid, RegisterSet :: NT_PRSTATUS , regs)
353
+ }
354
+
355
+ /// Set a particular set of user registers, as with `ptrace(PTRACE_SETREGSET, ...)`
356
+ #[ cfg( all(
357
+ target_os = "linux" ,
358
+ target_env = "gnu" ,
359
+ any(
360
+ target_arch = "x86_64" ,
361
+ target_arch = "x86" ,
362
+ target_arch = "aarch64" ,
363
+ target_arch = "riscv64" ,
364
+ )
365
+ ) ) ]
366
+ pub fn setregset (
367
+ pid : Pid ,
368
+ set : RegisterSet ,
369
+ mut regs : user_regs_struct ,
370
+ ) -> Result < ( ) > {
371
+ let mut iov = libc:: iovec {
372
+ iov_base : ( & mut regs as * mut user_regs_struct ) . cast ( ) ,
373
+ iov_len : mem:: size_of :: < user_regs_struct > ( ) ,
374
+ } ;
375
+ unsafe {
376
+ ptrace_other (
377
+ Request :: PTRACE_SETREGSET ,
378
+ pid,
379
+ set as i32 as AddressType ,
380
+ ( & mut iov as * mut libc:: iovec ) . cast ( ) ,
381
+ ) ?;
382
+ }
383
+ Ok ( ( ) )
384
+ }
385
+
257
386
/// Function for ptrace requests that return values from the data field.
258
387
/// Some ptrace get requests populate structs or larger elements than `c_long`
259
388
/// and therefore use the data field to return values. This function handles these
0 commit comments