def _debug_event_iteration(self): # (pid, status) = waitpid(self.pid, 0) (pid, status) = waitpid(0, 0) self.pid = pid signum = 0 logger.debug('status:' + hex(status) + ' pid:' + str(pid)) # Process exited? if WIFEXITED(status): self._event_handle_process_exit(status, pid) # Process killed by a signal? elif WIFSIGNALED(status): self._event_handle_process_kill(status, pid) # Invalid process status? elif not WIFSTOPPED(status): self._event_handle_process_unknown_status(status, pid) # Ptrace event? elif self.WPTRACEEVENT(status): self._event_handle_process_ptrace_event(status, pid) else: signum = self._event_handle_process_signal(status, pid) # continue if signum is None: signum = 0 if self.single_step_flag | (self._restore_breakpoint is not None): self._ptrace(PTRACE_SINGLESTEP, pid, 0, signum) elif self.trace_sys_call_flag: self._ptrace(PTRACE_SYSCALL, pid, 0, signum) else: self._ptrace(PTRACE_CONT, pid, 0, signum)
def pass_on_signals(pid): from os import waitpid, WIFSTOPPED, WSTOPSIG from sys import stderr while True: retpid, status = waitpid(pid, 0) assert WIFSTOPPED(status) signum = WSTOPSIG(status) print >>stderr, "Passing signal to tracee:", signum ptrace_cont(pid, signum)
def execute(self, *args): process = Popen4([self.facility.path] + self.facility.args + list(args)) timers = [ Timer(time, self.kill, [process.pid, signal]) for time, signal in self.facility.wait.iteritems() ] for timer in timers: timer.start() status = process.wait() for timer in timers: # No penalty, btw, for cancelling a dead timer if timer.isAlive(): timer.cancel() process.tochild.close() if __debug__: while True: line = process.fromchild.readline() if line: syslog(line) else: break process.fromchild.close() command = basename(self.facility.path) if WIFEXITED(status): exit_status = WEXITSTATUS(status) if exit_status != EX_OK: raise ExecutionError( EX_SOFTWARE, '`%(command)s\' exited with \ error-code %(exit_status)d' % { 'command': command, 'exit_status': exit_status }) elif WIFSIGNALED(status): raise ExecutionError( EX_SOFTWARE, '`%(command)s\' terminated \ with signal %(signal)d' % { 'command': command, 'signal': WTERMSIG(status) }) elif WIFSTOPPED(status): raise ExecutionError( EX_SOFTWARE, '`%(command)s\' stopped with \ signal %(signal)d' % { 'command': command, 'signal': WSTOPSIG(status) }) else: # Failsafe: timers should have killed the process by this point, or # it should have ended naturally. kill(process.pid, SIGKILL) raise ExecutionError( EX_SOFTWARE, 'Failed timer on `%(command)s\'; \ terminating the process extraordinarily.' % {'command': command})
def wait_for_tracee_stop(pid): from os import waitpid, WIFSTOPPED, WSTOPSIG from signal import SIGSTOP from sys import stderr while True: retpid, status = waitpid(pid, 0) assert retpid == pid assert WIFSTOPPED(status) signum = WSTOPSIG(status) if signum == SIGSTOP: break else: print >>stderr, "Passing signal to tracee:", signum ptrace_cont(pid, signum)
def debugger(pid): # Liczba wykonanych instrukcji icounter = 0 # Oczekuj az potomek wykona pierwsza instrukcje status = wait() # Oczekuj na sygnaly od potomka do # momentu jego zatrzymania while (WIFSTOPPED(status[1])): icounter += 1 # Nakaz potomkowi wykonac kolejna instrukcje ptrace(PTRACE_SINGLESTEP, pid, 0, 0) status = wait() print(f"Potomek wykonal {icounter} instrukcji")
def formatProcessStatus(status, title="Process"): if WIFSTOPPED(status): signum = WSTOPSIG(status) return "%s stopped by signal %s" % (title, signalName(signum)) if WIFSIGNALED(status): signum = WTERMSIG(status) return "%s killed by signal %s" % (title, signalName(signum)) if not WIFEXITED(status): raise ValueError("Invalid status: %r" % status) exitcode = WEXITSTATUS(status) if exitcode: return "%s exited with code %s" % (title, exitcode) else: return "%s exited normally" % title
def __debugger_handover(self): # restore permanent breakpoints if self.__restore: self.add_breakpoint(self.__restore) self.__restore = None # wait for the child to finish, refresh regs and check for # breakpoint _, s = waitpid(self.__child_pid, 0) if WIFSTOPPED(s): self.__regs = self.__get_regs() restore = self.__ignore_ptrace_errors self.__ignore_ptrace_errors = True if self.__regs.rip - 1 in self.breakpoints: self.__breakpoint_hook() self.__ignore_ptrace_errors = restore else: self.__child_alive = False
def _waitpid(pid): """Convenience wrapper around the original waitpid invocation.""" # 0 and -1 trigger a different behavior in waitpid. We disallow those # values. assert pid > 0 while True: pid_, status = waitpid_(pid, 0) assert pid_ == pid if WIFEXITED(status): return WEXITSTATUS(status) elif WIFSIGNALED(status): # Signals are usually represented as the negated signal number. return -WTERMSIG(status) elif WIFSTOPPED(status) or WIFCONTINUED(status): # In our current usage scenarios we can simply ignore SIGSTOP and # SIGCONT by restarting the wait. continue else: assert False return 1
def formatProcessStatus(status, title="Process"): """ Format a process status (integer) as a string. """ if WIFSTOPPED(status): signum = WSTOPSIG(status) text = "%s stopped by signal %s" % (title, signalName(signum)) elif WIFSIGNALED(status): signum = WTERMSIG(status) text = "%s killed by signal %s" % (title, signalName(signum)) else: if not WIFEXITED(status): raise ValueError("Invalid status: %r" % status) exitcode = WEXITSTATUS(status) if exitcode: text = "%s exited with code %s" % (title, exitcode) else: text = "%s exited normally" % title if WCOREDUMP(status): text += " (core dumped)" return text
def processStatus(self, status): # Process exited? if WIFEXITED(status): code = WEXITSTATUS(status) event = self.processExited(code) # Process killed by a signal? elif WIFSIGNALED(status): signum = WTERMSIG(status) event = self.processKilled(signum) # Invalid process status? elif not WIFSTOPPED(status): raise ProcessError(self, "Unknown process status: %r" % status) # Ptrace event? elif HAS_PTRACE_EVENTS and WPTRACEEVENT(status): event = WPTRACEEVENT(status) event = self.ptraceEvent(event) else: signum = WSTOPSIG(status) event = self.processSignal(signum) return event