use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct VirtAddr(pub u64);
impl VirtAddr {
pub fn addr(self) -> u64 {
self.0
}
}
impl fmt::Display for VirtAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "0x{:x}", self.0)
}
}
impl fmt::LowerHex for VirtAddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::LowerHex::fmt(&self.0, f)
}
}
impl std::ops::Add<u64> for VirtAddr {
type Output = VirtAddr;
fn add(self, rhs: u64) -> Self::Output {
VirtAddr(self.0 + rhs)
}
}
impl std::ops::Sub<u64> for VirtAddr {
type Output = VirtAddr;
fn sub(self, rhs: u64) -> Self::Output {
VirtAddr(self.0 - rhs)
}
}
#[derive(Debug, Clone)]
pub enum StopReason {
BreakpointHit { addr: VirtAddr },
SingleStep,
Signal(nix::sys::signal::Signal),
WatchpointHit { slot: usize, addr: VirtAddr },
SyscallEntry { number: u64, args: [u64; 6] },
SyscallExit { number: u64, retval: i64 },
Exited(i32),
Terminated(nix::sys::signal::Signal),
ThreadCreated(nix::unistd::Pid),
ThreadExited(nix::unistd::Pid),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProcessState {
Stopped,
Running,
Exited,
Terminated,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn virt_addr_display() {
let addr = VirtAddr(0x400000);
assert_eq!(format!("{}", addr), "0x400000");
}
#[test]
fn virt_addr_arithmetic() {
let addr = VirtAddr(0x1000);
assert_eq!((addr + 0x10).addr(), 0x1010);
assert_eq!((addr - 0x10).addr(), 0x0FF0);
}
#[test]
fn virt_addr_ord() {
let a = VirtAddr(0x100);
let b = VirtAddr(0x200);
assert!(a < b);
assert_eq!(a, VirtAddr(0x100));
}
#[test]
fn virt_addr_hash() {
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert(VirtAddr(0x1000));
set.insert(VirtAddr(0x2000));
set.insert(VirtAddr(0x1000)); assert_eq!(set.len(), 2);
}
}