def cleanup(self): self.restore_original() self.question("kill", self.cleanup_timeout) self.proxy_child = None self.debuggee_pid = None self.question("shell rm -f " + sh_quote(self.debuggee_output_file()), self.cleanup_timeout) self.disabled_functions = {}
def debuggee_output(self, timeout=None): # If the program is still running, kill it self.question("kill") # Wait for the queue to terminate if self.proxy_child is not None: a = AlarmHandler.AlarmHandler(timeout) try: self.proxy_child.wait() except AlarmHandler.TimeOutError: pass # Close queue self.proxy_child = None return self.question("shell cat " + sh_quote(self.debuggee_output_file()))
def run_indirect(self, invocation, timeout): self.original_program = self.debuggee_original_file() self.output_file = self.debuggee_output_file() # Here's how this works. We replace the original program by a # proxy script. This proxy script forwards all its input to a # named pipe. This pipe is read by the debuggee within GDB. # The debuggee output is sent to another named pipe, which is # then read by the proxy script and forwarded to its output. # FIXME: Make the script exit with the same return tcas as the # original debuggee. # FIXME: calling this script with embedded quotes does not work, # eg. "replace '*' '%@&a' < file" leads to a finalized call at & proxy_script = \ """ #!/bin/sh in_pipe=/tmp/gdb_in$$ out_pipe=/tmp/gdb_out$$ err_pipe=/tmp/gdb_err$$ mkfifo $in_pipe $out_pipe $err_pipe echo "PiPeS" $in_pipe $out_pipe $err_pipe >&31 echo "ArGs" "$@" >&31 cat < $out_pipe & cat < $err_pipe >&2 & cat > $in_pipe & wait rm -f $in_pipe $out_pipe $err_pipe """ self.question("shell mv -f " + sh_quote(self.debuggee()) + " " + sh_quote(self.original_program)) for line in proxy_script.splitlines(): if line: self.question("shell echo " + sh_quote(line) + " >> " + sh_quote(self.debuggee())) self.question("shell chmod 770 " + sh_quote(self.debuggee())) self.question("shell touch -r " + sh_quote(self.original_program) + " " + sh_quote(self.debuggee())) invocation_cmd = ("(" + invocation + ") 30<&0 31>&1 32>&2" + " > " + self.output_file + " 2>&1") self.proxy_child = self.open_child(invocation_cmd) a = AlarmHandler.AlarmHandler(self.invocation_timeout) try: pipes = self.proxy_child.fromchild.readline().split() except AlarmHandler.TimeOutError: pipes = [] if len(pipes) == 0 or pipes[0] != "PiPeS": output = self.debuggee_output(self.invocation_timeout) self.cleanup() raise NotInvokedError, output in_pipe = pipes[1] out_pipe = pipes[2] err_pipe = pipes[3] try: args = self.proxy_child.fromchild.readline().split() except AlarmHandler.TimeOutError: args = [] if len(args) == 0 or args[0] != "ArGs": output = self.debuggee_output(self.invocation_timeout) self.cleanup() raise NotInvokedError, output del a args = string.join(args[1:], " ") self.load_debuggee(self.original_program) run_cmd = ("run " + args + " < " + in_pipe + " > " + out_pipe + " 2> " + err_pipe) return self.question(run_cmd, timeout)
def restore_original(self): if self.original_program is not None: self.question("shell mv -f " + sh_quote(self.original_program) + " " + sh_quote(self.debuggee())) self.load_debuggee(self.debuggee()) self.original_program = None
def run_indirect(self, invocation, timeout): self.original_program = self.debuggee_original_file() self.output_file = self.debuggee_output_file() # Here's how this works. We replace the original program by a # proxy script. This proxy script forwards all its input to a # named pipe. This pipe is read by the debuggee within GDB. # The debuggee output is sent to another named pipe, which is # then read by the proxy script and forwarded to its output. # FIXME: Make the script exit with the same return code as the # original debuggee. # FIXME: calling this script with embedded quotes does not work, # eg. "replace '*' '%@&a' < file" leads to a finalized call at & proxy_script = \ """ #!/bin/sh in_pipe=/tmp/gdb_in$$ out_pipe=/tmp/gdb_out$$ err_pipe=/tmp/gdb_err$$ mkfifo $in_pipe $out_pipe $err_pipe echo "PiPeS" $in_pipe $out_pipe $err_pipe >&31 echo "ArGs" "$@" >&31 cat < $out_pipe & cat < $err_pipe >&2 & cat > $in_pipe & wait rm -f $in_pipe $out_pipe $err_pipe """ self.question("shell mv -f " + sh_quote(self.debuggee()) + " " + sh_quote(self.original_program)) for line in proxy_script.splitlines(): if line: self.question("shell echo " + sh_quote(line) + " >> " + sh_quote(self.debuggee())) self.question("shell chmod 770 " + sh_quote(self.debuggee())) self.question("shell touch -r " + sh_quote(self.original_program) + " " + sh_quote(self.debuggee())) invocation_cmd = ("(" + invocation + ") 30<&0 31>&1 32>&2" + " > " + self.output_file + " 2>&1") self.proxy_child = self.open_child(invocation_cmd) a = AlarmHandler.AlarmHandler(self.invocation_timeout) try: pipes = self.proxy_child.fromchild.readline().split() except AlarmHandler.TimeOutError: pipes = [] if len(pipes) == 0 or pipes[0] != "PiPeS": output = self.debuggee_output(self.invocation_timeout) self.cleanup() raise NotInvokedError, output in_pipe = pipes[1] out_pipe = pipes[2] err_pipe = pipes[3] try: args = self.proxy_child.fromchild.readline().split() except AlarmHandler.TimeOutError: args = [] if len(args) == 0 or args[0] != "ArGs": output = self.debuggee_output(self.invocation_timeout) self.cleanup() raise NotInvokedError, output del a args = string.join(args[1:], " ") self.load_debuggee(self.original_program) run_cmd = ("run " + args + " < " + in_pipe + " > " + out_pipe + " 2> " + err_pipe) return self.question(run_cmd, timeout)