Skip to content

Commit

Permalink
Merge #1300
Browse files Browse the repository at this point in the history
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 <d.stolz@tum.de>
  • Loading branch information
bors[bot] and voidc committed Oct 3, 2020
2 parents 8e3789d + b889ce3 commit 7ed2820
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Added `clock_gettime`, `clock_settime`, `clock_getres`,
`clock_getcpuclockid` functions and `ClockId` struct.
(#[1281](https://github.com/nix-rust/nix/pull/1281))
- Added wrapper functions for `PTRACE_SYSEMU` and `PTRACE_SYSEMU_SINGLESTEP`.
(#[1300](https://github.com/nix-rust/nix/pull/1300))
### Changed
- Expose `SeekData` and `SeekHole` on all Linux targets
(#[1284](https://github.com/nix-rust/nix/pull/1284))
Expand Down
47 changes: 46 additions & 1 deletion src/sys/ptrace/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ libc_enum!{
#[cfg(all(target_os = "linux", not(any(target_arch = "mips",
target_arch = "mips64"))))]
PTRACE_PEEKSIGINFO,
#[cfg(all(target_os = "linux", target_env = "gnu",
any(target_arch = "x86", target_arch = "x86_64")))]
PTRACE_SYSEMU,
#[cfg(all(target_os = "linux", target_env = "gnu",
any(target_arch = "x86", target_arch = "x86_64")))]
PTRACE_SYSEMU_SINGLESTEP,
}
}

Expand Down Expand Up @@ -278,7 +284,7 @@ pub fn traceme() -> Result<()> {
}
}

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

/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSEMU, ...)`
///
/// In contrast to the `syscall` function, the syscall stopped at will not be executed.
/// Thus the the tracee will only be stopped once per syscall,
/// optionally delivering a signal specified by `sig`.
#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))]
pub fn sysemu<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
let data = match sig.into() {
Some(s) => s as i32 as *mut c_void,
None => ptr::null_mut(),
};
unsafe {
ptrace_other(Request::PTRACE_SYSEMU, pid, ptr::null_mut(), data).map(drop)
// ignore the useless return value
}
}

/// Attach to a running process, as with `ptrace(PTRACE_ATTACH, ...)`
///
/// Attaches to the process specified by `pid`, making it a tracee of the calling process.
Expand Down Expand Up @@ -402,6 +425,28 @@ pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
}
}

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

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

0 comments on commit 7ed2820

Please sign in to comment.