Skip to content

Commit 051aca3

Browse files
committed
Added PTRACE_SYSEMU and PTRACE_SYSEMU_SINGLESTEP support
1 parent 2c24405 commit 051aca3

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

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", any(target_arch = "x86",
113+
target_arch = "x86_64")))]
114+
PTRACE_SYSEMU,
115+
#[cfg(all(target_os = "linux", any(target_arch = "x86",
116+
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", 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", any(target_arch = "x86", target_arch = "x86_64")))]
435+
pub fn step_or_sysemu<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)