Skip to content

Commit

Permalink
Merge pull request #139 from nbaksalyar/update-deps
Browse files Browse the repository at this point in the history
Fix race condition in the writemem test
  • Loading branch information
nbaksalyar authored Apr 5, 2022
2 parents d3416b4 + 3d4facf commit c735f86
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 22 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ readme = "README.md"
[dependencies]
lazy_static = "1.4.0"
object = "0.20"
gimli = "0.22.0"
gimli = "0.26.1"
capstone = "0.7.0"
addr2line = "0.13.0"
addr2line = "0.17.0"
syntect = {version = "4.4.0", optional = true}

# Dependencies specific to macOS & Linux
Expand Down
12 changes: 2 additions & 10 deletions src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,7 @@ pub type Reader<'a> = gimli::EndianReader<gimli::RunTimeEndian, RcCow<'a, [u8]>>
pub struct ParsedDwarf<'a> {
object: object::File<'a>,
addr2line: addr2line::Context<Reader<'a>>,
vars: BTreeMap<
String,
(
gimli::CompilationUnitHeader<Reader<'a>>,
gimli::Expression<Reader<'a>>,
),
>,
vars: BTreeMap<String, (gimli::UnitHeader<Reader<'a>>, gimli::Expression<Reader<'a>>)>,
symbols: Vec<Symbol<'a>>,
symbol_names: HashMap<String, usize>,
}
Expand Down Expand Up @@ -110,11 +104,9 @@ impl<'a> ParsedDwarf<'a> {
None => Ok(gimli::EndianReader::new(RcCow::Borrowed(&[][..]), endian)),
}
};
// we don't support supplementary object files for now
let sup_loader = |_| Ok(gimli::EndianReader::new(RcCow::Borrowed(&[][..]), endian));

// Create `EndianSlice`s for all of the sections.
let dwarf = gimli::Dwarf::load(loader, sup_loader)?;
let dwarf = gimli::Dwarf::load(loader)?;

let addr2line = addr2line::Context::from_dwarf(dwarf)?;
let dwarf = addr2line.dwarf();
Expand Down
14 changes: 9 additions & 5 deletions src/target/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,11 @@ impl LinuxTarget {
Ok(status)
}

fn new(pid: Pid) -> Self {
/// Creates a new debug target.
/// This method should only be used if you know that `pid` is expecting to be traced
/// (e.g., when it called `PTRACE_TRACEME`). Otherwise, you should use `LinuxTarget::attach`
/// or `LinuxTarget::launch`.
pub fn from_debuggee_pid(pid: Pid) -> Self {
Self {
pid,
hardware_breakpoints: Default::default(),
Expand All @@ -196,15 +200,15 @@ impl LinuxTarget {
/// Launches a new debuggee process
pub fn launch(cmd: Command) -> CrabResult<(LinuxTarget, nix::sys::wait::WaitStatus)> {
let (pid, status) = unix::launch(cmd)?;
let target = LinuxTarget::new(pid);
let target = LinuxTarget::from_debuggee_pid(pid);
target.kill_on_exit()?;
Ok((target, status))
}

/// Attaches process as a debuggee.
pub fn attach(pid: Pid, options: AttachOptions) -> CrabResult<(LinuxTarget, WaitStatus)> {
let status = unix::attach(pid)?;
let target = LinuxTarget::new(pid);
let target = LinuxTarget::from_debuggee_pid(pid);

if options.kill_on_exit {
target.kill_on_exit()?;
Expand All @@ -215,7 +219,7 @@ impl LinuxTarget {

/// Uses this process as a debuggee.
pub fn me() -> LinuxTarget {
LinuxTarget::new(getpid())
LinuxTarget::from_debuggee_pid(getpid())
}

/// Reads memory from a debuggee process.
Expand Down Expand Up @@ -610,7 +614,7 @@ mod tests {
let mut read_var2_op: u8 = 0;

unsafe {
let target = LinuxTarget::new(getpid());
let target = LinuxTarget::me();
ReadMemory::new(&target)
.read(&mut read_var_op, &var as *const _ as usize)
.read(&mut read_var2_op, &var2 as *const _ as usize)
Expand Down
2 changes: 1 addition & 1 deletion src/target/linux/software_breakpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl Breakpoint {
pub(crate) fn new(addr: usize, pid: Pid) -> Result<Self, BreakpointError> {
let mut shadow = 0_i64;
unsafe {
ReadMemory::new(&LinuxTarget::new(pid))
ReadMemory::new(&LinuxTarget::from_debuggee_pid(pid))
.read(&mut shadow, addr)
.apply()
}
Expand Down
48 changes: 44 additions & 4 deletions src/target/linux/writemem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,9 @@ mod tests {
use nix::{
sys::{
mman::{mprotect, ProtFlags},
ptrace, wait,
ptrace,
signal::{self, Signal},
wait,
},
unistd::{fork, ForkResult},
};
Expand Down Expand Up @@ -274,6 +276,14 @@ mod tests {
Ok(ForkResult::Child) => {
ptrace::traceme().unwrap();

unsafe {
assert_eq!(ptr::read_volatile(&write_var_op), 0);
assert_eq!(ptr::read_volatile(&write_var2_op), 0);
}

// Wait for the parent process to signal to continue.
signal::raise(Signal::SIGSTOP).unwrap();

// Catch the panic so that we can report back to the original process.
let test_res = std::panic::catch_unwind(|| unsafe {
assert_eq!(ptr::read_volatile(&write_var_op), var);
Expand All @@ -285,9 +295,20 @@ mod tests {
std::process::exit(if test_res.is_ok() { 0 } else { 100 });
}
Ok(ForkResult::Parent { child, .. }) => {
let (target, _wait_stat) = LinuxTarget::attach(child, Default::default()).unwrap();
// Wait for child.
let wait_status = wait::waitpid(child, None).unwrap();

match wait_status {
wait::WaitStatus::Stopped(_pid, _sig) => {}
status => {
signal::kill(child, Signal::SIGKILL).unwrap();
panic!("Unexpected child status: {:?}", status);
}
}

let target = LinuxTarget::from_debuggee_pid(child);

// Write memory to parent's process
// Write memory to the child's process
let write_mem = target
.write()
.write(&var, &write_var_op as *const _ as usize)
Expand Down Expand Up @@ -336,6 +357,14 @@ mod tests {
Ok(ForkResult::Child) => {
ptrace::traceme().unwrap();

unsafe {
assert_eq!(ptr::read_volatile(write_protected_ptr), 0);
assert_eq!(ptr::read_volatile(write_protected_ptr), 0);
}

// Wait for the parent process to signal to continue.
signal::raise(Signal::SIGSTOP).unwrap();

// Catch the panic so that we can report back to the original process.
let test_res = std::panic::catch_unwind(|| unsafe {
assert_eq!(ptr::read_volatile(write_protected_ptr), var);
Expand All @@ -346,7 +375,18 @@ mod tests {
std::process::exit(if test_res.is_ok() { 0 } else { 100 });
}
Ok(ForkResult::Parent { child, .. }) => unsafe {
let (target, _wait_stat) = LinuxTarget::attach(child, Default::default()).unwrap();
// Wait for child.
let wait_status = wait::waitpid(child, None).unwrap();

match wait_status {
wait::WaitStatus::Stopped(_pid, _sig) => {}
status => {
signal::kill(child, Signal::SIGKILL).unwrap();
panic!("Unexpected child status: {:?}", status);
}
}

let target = LinuxTarget::from_debuggee_pid(child);

// Write memory to the child's process.
target
Expand Down

0 comments on commit c735f86

Please sign in to comment.