Skip to content

Commit 7ed2820

Browse files
bors[bot]voidc
andauthored
Merge #1300
1300: Add PTRACE_SYSEMU and PTRACE_SYSEMU_SINGLESTEP support r=asomers a=voidc Closes #1249. I think @jabedude was working on this, but as there was no progress since May I went ahead and implemented it myself. I'm not completely sure about the cfg gates. Could we enable the functions for more targets? I'm also open for suggestions of better names for the new functions. Co-authored-by: Dominik Stolz <[email protected]>
2 parents 8e3789d + b889ce3 commit 7ed2820

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)