Skip to content

Commit b889ce3

Browse files
committed
Add PTRACE_SYSEMU and PTRACE_SYSEMU_SINGLESTEP support
1 parent fe0aa23 commit b889ce3

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1010
- Added `clock_gettime`, `clock_settime`, `clock_getres`,
1111
`clock_getcpuclockid` functions and `ClockId` struct.
1212
(#[1281](https://github.com/nix-rust/nix/pull/1281))
13+
- Added wrapper functions for `PTRACE_SYSEMU` and `PTRACE_SYSEMU_SINGLESTEP`.
14+
(#[1300](https://github.com/nix-rust/nix/pull/1300))
1315
### Changed
1416
- Expose `SeekData` and `SeekHole` on all Linux targets
1517
(#[1284](https://github.com/nix-rust/nix/pull/1284))

src/sys/ptrace/linux.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ libc_enum!{
109109
#[cfg(all(target_os = "linux", not(any(target_arch = "mips",
110110
target_arch = "mips64"))))]
111111
PTRACE_PEEKSIGINFO,
112+
#[cfg(all(target_os = "linux", target_env = "gnu",
113+
any(target_arch = "x86", target_arch = "x86_64")))]
114+
PTRACE_SYSEMU,
115+
#[cfg(all(target_os = "linux", target_env = "gnu",
116+
any(target_arch = "x86", target_arch = "x86_64")))]
117+
PTRACE_SYSEMU_SINGLESTEP,
112118
}
113119
}
114120

@@ -278,7 +284,7 @@ pub fn traceme() -> Result<()> {
278284
}
279285
}
280286

281-
/// Ask for next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
287+
/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
282288
///
283289
/// Arranges for the tracee to be stopped at the next entry to or exit from a system call,
284290
/// optionally delivering a signal specified by `sig`.
@@ -297,6 +303,23 @@ pub fn syscall<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
297303
}
298304
}
299305

306+
/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSEMU, ...)`
307+
///
308+
/// In contrast to the `syscall` function, the syscall stopped at will not be executed.
309+
/// Thus the the tracee will only be stopped once per syscall,
310+
/// optionally delivering a signal specified by `sig`.
311+
#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))]
312+
pub fn sysemu<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
313+
let data = match sig.into() {
314+
Some(s) => s as i32 as *mut c_void,
315+
None => ptr::null_mut(),
316+
};
317+
unsafe {
318+
ptrace_other(Request::PTRACE_SYSEMU, pid, ptr::null_mut(), data).map(drop)
319+
// ignore the useless return value
320+
}
321+
}
322+
300323
/// Attach to a running process, as with `ptrace(PTRACE_ATTACH, ...)`
301324
///
302325
/// Attaches to the process specified by `pid`, making it a tracee of the calling process.
@@ -402,6 +425,28 @@ pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
402425
}
403426
}
404427

428+
/// Move the stopped tracee process forward by a single step or stop at the next syscall
429+
/// as with `ptrace(PTRACE_SYSEMU_SINGLESTEP, ...)`
430+
///
431+
/// Advances the execution by a single step or until the next syscall.
432+
/// In case the tracee is stopped at a syscall, the syscall will not be executed.
433+
/// Optionally, the signal specified by `sig` is delivered to the tracee upon continuation.
434+
#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))]
435+
pub fn sysemu_step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
436+
let data = match sig.into() {
437+
Some(s) => s as i32 as *mut c_void,
438+
None => ptr::null_mut(),
439+
};
440+
unsafe {
441+
ptrace_other(
442+
Request::PTRACE_SYSEMU_SINGLESTEP,
443+
pid,
444+
ptr::null_mut(),
445+
data,
446+
)
447+
.map(drop) // ignore the useless return value
448+
}
449+
}
405450

406451
/// Reads a word from a processes memory at the given address
407452
pub fn read(pid: Pid, addr: AddressType) -> Result<c_long> {

0 commit comments

Comments
 (0)