More cleanup...
This commit is contained in:
@@ -55,6 +55,20 @@ struct Session {
|
||||
tracee: Arc<WaitCondition>,
|
||||
tracer: Arc<WaitCondition>,
|
||||
}
|
||||
impl Session {
|
||||
fn send_event(&mut self, event: PtraceEvent) {
|
||||
self.events.push_back(event);
|
||||
|
||||
// Notify nonblocking tracers
|
||||
if self.events.len() == 1 {
|
||||
// If the list of events was previously empty, alert now
|
||||
proc_trigger_event(self.file_id, EVENT_READ);
|
||||
}
|
||||
|
||||
// Alert blocking tracers
|
||||
self.tracer.notify();
|
||||
}
|
||||
}
|
||||
|
||||
type SessionMap = BTreeMap<ContextId, Session>;
|
||||
|
||||
@@ -103,9 +117,6 @@ pub fn session_fevent_flags(pid: ContextId) -> Option<EventFlags> {
|
||||
if !session.events.is_empty() {
|
||||
flags |= EVENT_READ;
|
||||
}
|
||||
if session.breakpoint.as_ref().map(|b| b.reached).unwrap_or(true) {
|
||||
flags |= EVENT_WRITE;
|
||||
}
|
||||
Some(flags)
|
||||
}
|
||||
|
||||
@@ -139,16 +150,7 @@ pub fn send_event(event: PtraceEvent) -> Option<()> {
|
||||
return None;
|
||||
}
|
||||
|
||||
session.events.push_back(event);
|
||||
|
||||
// Notify nonblocking tracers
|
||||
if session.events.len() == 1 {
|
||||
// If the list of events was previously empty, alert now
|
||||
proc_trigger_event(session.file_id, EVENT_READ);
|
||||
}
|
||||
|
||||
// Alert blocking tracers
|
||||
session.tracer.notify();
|
||||
session.send_event(event);
|
||||
|
||||
Some(())
|
||||
}
|
||||
@@ -209,31 +211,22 @@ pub fn set_breakpoint(pid: ContextId, flags: PtraceFlags) {
|
||||
///
|
||||
/// Note: Don't call while holding any locks, this will switch
|
||||
/// contexts
|
||||
pub fn wait(pid: ContextId) -> Result<Option<PtraceEvent>> {
|
||||
pub fn wait(pid: ContextId) -> Result<()> {
|
||||
let tracer: Arc<WaitCondition> = {
|
||||
let sessions = sessions();
|
||||
match sessions.get(&pid) {
|
||||
Some(session) if session.breakpoint.as_ref().map(|b| !b.reached).unwrap_or(true) => {
|
||||
if !session.events.is_empty() {
|
||||
return Ok(None);
|
||||
return Ok(());
|
||||
}
|
||||
Arc::clone(&session.tracer)
|
||||
},
|
||||
_ => return Ok(None)
|
||||
_ => return Ok(())
|
||||
}
|
||||
};
|
||||
|
||||
while !tracer.wait() {}
|
||||
|
||||
{
|
||||
let sessions = sessions();
|
||||
if let Some(session) = sessions.get(&pid) {
|
||||
if let Some(event) = session.events.front() {
|
||||
return Ok(Some(event.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let contexts = context::contexts();
|
||||
let context = contexts.get(pid).ok_or(Error::new(ESRCH))?;
|
||||
let context = context.read();
|
||||
@@ -241,7 +234,7 @@ pub fn wait(pid: ContextId) -> Result<Option<PtraceEvent>> {
|
||||
return Err(Error::new(ESRCH));
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Notify the tracer and await green flag to continue.
|
||||
@@ -261,23 +254,16 @@ pub fn breakpoint_callback(match_flags: PtraceFlags, event: Option<PtraceEvent>)
|
||||
return None;
|
||||
}
|
||||
|
||||
session.events.push_back(event.unwrap_or(ptrace_event!(match_flags)));
|
||||
|
||||
// Notify nonblocking tracers
|
||||
if session.events.len() == 1 {
|
||||
// If the list of events was previously empty, alert now
|
||||
proc_trigger_event(session.file_id, EVENT_READ);
|
||||
}
|
||||
|
||||
// In case no tracer is waiting, make sure the next one gets
|
||||
// the memo
|
||||
breakpoint.reached = true;
|
||||
|
||||
session.tracer.notify();
|
||||
let flags = breakpoint.flags;
|
||||
session.send_event(event.unwrap_or(ptrace_event!(match_flags)));
|
||||
|
||||
(
|
||||
Arc::clone(&session.tracee),
|
||||
breakpoint.flags
|
||||
flags
|
||||
)
|
||||
};
|
||||
|
||||
@@ -306,8 +292,12 @@ pub fn close_tracee(pid: ContextId) -> Option<()> {
|
||||
let mut sessions = sessions_mut();
|
||||
let session = sessions.get_mut(&pid)?;
|
||||
|
||||
// Cause tracers to wake up. Any action will cause ESRCH which can
|
||||
// be used to detect exit.
|
||||
session.breakpoint = None;
|
||||
session.tracer.notify();
|
||||
proc_trigger_event(session.file_id, EVENT_READ);
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ impl Handle {
|
||||
let contexts = context::contexts();
|
||||
for pid in clones.drain(..) {
|
||||
if ptrace::is_traced(pid) {
|
||||
return None;
|
||||
continue;
|
||||
}
|
||||
if let Some(context) = contexts.get(pid) {
|
||||
let mut context = context.write();
|
||||
@@ -332,13 +332,20 @@ impl Scheme for ProcScheme {
|
||||
|
||||
Ok(len)
|
||||
},
|
||||
Operation::Trace { .. } => {
|
||||
let read = ptrace::recv_events(info.pid, unsafe {
|
||||
Operation::Trace { ref mut clones } => {
|
||||
let slice = unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
buf.as_mut_ptr() as *mut PtraceEvent,
|
||||
buf.len() / mem::size_of::<PtraceEvent>()
|
||||
)
|
||||
}).unwrap_or(0);
|
||||
};
|
||||
let read = ptrace::recv_events(info.pid, slice).unwrap_or(0);
|
||||
|
||||
for event in &slice[..read] {
|
||||
if event.cause == PTRACE_EVENT_CLONE {
|
||||
clones.push(ContextId::from(event.a));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(read * mem::size_of::<PtraceEvent>())
|
||||
}
|
||||
@@ -409,7 +416,7 @@ impl Scheme for ProcScheme {
|
||||
})
|
||||
}
|
||||
},
|
||||
Operation::Trace { ref mut clones } => {
|
||||
Operation::Trace { .. } => {
|
||||
if buf.len() < mem::size_of::<u64>() {
|
||||
return Ok(0);
|
||||
}
|
||||
@@ -454,11 +461,7 @@ impl Scheme for ProcScheme {
|
||||
}
|
||||
|
||||
if op.contains(PTRACE_FLAG_WAIT) || info.flags & O_NONBLOCK != O_NONBLOCK {
|
||||
if let Some(event) = ptrace::wait(info.pid)? {
|
||||
if event.cause == PTRACE_EVENT_CLONE {
|
||||
clones.push(ContextId::from(event.a));
|
||||
}
|
||||
}
|
||||
ptrace::wait(info.pid)?;
|
||||
}
|
||||
|
||||
Ok(mem::size_of::<u64>())
|
||||
|
||||
@@ -175,8 +175,8 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
validate_slice_mut(c as *mut TimeSpec, 1)
|
||||
),
|
||||
SYS_CLONE => format!(
|
||||
"clone({})",
|
||||
b
|
||||
"clone({:?})",
|
||||
CloneFlags::from_bits(b)
|
||||
),
|
||||
SYS_EXIT => format!(
|
||||
"exit({})",
|
||||
@@ -256,10 +256,10 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
validate_slice(b as *const [usize; 2], c)
|
||||
),
|
||||
SYS_MPROTECT => format!(
|
||||
"mprotect({:#X}, {}, {:#X})",
|
||||
"mprotect({:#X}, {}, {:?})",
|
||||
b,
|
||||
c,
|
||||
d
|
||||
ProtFlags::from_bits(d)
|
||||
),
|
||||
SYS_NANOSLEEP => format!(
|
||||
"nanosleep({:?}, ({}, {}))",
|
||||
@@ -277,10 +277,10 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
c
|
||||
),
|
||||
SYS_PHYSMAP => format!(
|
||||
"physmap({:#X}, {}, {:#X})",
|
||||
"physmap({:#X}, {}, {:?})",
|
||||
b,
|
||||
c,
|
||||
d
|
||||
PhysmapFlags::from_bits(d)
|
||||
),
|
||||
SYS_PHYSUNMAP => format!(
|
||||
"physunmap({:#X})",
|
||||
@@ -315,10 +315,10 @@ pub fn format_call(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -
|
||||
b
|
||||
),
|
||||
SYS_WAITPID => format!(
|
||||
"waitpid({}, {:#X}, {})",
|
||||
"waitpid({}, {:#X}, {:?})",
|
||||
b,
|
||||
c,
|
||||
d
|
||||
WaitFlags::from_bits(d)
|
||||
),
|
||||
SYS_YIELD => format!("yield()"),
|
||||
_ => format!(
|
||||
|
||||
Reference in New Issue
Block a user