From f61e9c283bfbcca31062ae924778f577249a303f Mon Sep 17 00:00:00 2001 From: Stefan Huber Date: Mon, 2 Jun 2008 11:51:20 +0200 Subject: [PATCH] initial commit with a little terminal code to gdb --- DbgTerminal.py | 205 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100755 DbgTerminal.py diff --git a/DbgTerminal.py b/DbgTerminal.py new file mode 100755 index 0000000..cef0d27 --- /dev/null +++ b/DbgTerminal.py @@ -0,0 +1,205 @@ +#!/usr/bin/python + + +import select +import sys +import thread +import threading +import time +import os +import pty + + +class DbgTerminal: + + def __init__ (self, binary, gdbReadCallback, childReadCallback): + + #Set some members + self.gdbReadCallback = gdbReadCallback + self.childReadCallback = childReadCallback + self.binary = binary + self.stopped = False + + #Connect to sub-process + self.__connect() + + def __connect( self ): + + + #Open pseudo-terminal where to-be-debugged process reads/writes to + self.ptymaster, self.ptyslave = pty.openpty() + self.childout = os.fdopen(self.ptymaster, "r", 0) + self.childin = os.fdopen(self.ptymaster, "w", 0) + + #Open the subprocess and get in- and out-streams + cmd = self.getCommand(self.binary) + self.gdbin, self.gdbout = os.popen4( cmd, bufsize=0) + + + #Set up a reading thread to gdb output + self.gdbReadThread = self.ReadThread(self.gdbout, self.gdbReadCallback) + self.gdbReadThread.start() + + #Set up a reading thread to gdb output + self.childReadThread = self.ReadThread(self.childout, self.childReadCallback) + self.childReadThread.start() + + #Set up tty gdb-childs process + time.sleep(0.1) + self.sendSetTTY(os.ttyname(self.ptyslave)) + time.sleep(0.1) + + + + def getCommand( self, binary ): + """Get the command to execute""" + raise NotImplementedError() + + + def iseof( self ): + """Check if terminal is closed already""" + + return self.gdbReadThread.eventFin.isSet() + + + def stop( self ): + + if not self.stopped: + + self.stopped = True + + #Finish the reading-thread + self.gdbReadThread.fin = True + self.childReadThread.fin = True + self.gdbReadThread.eventFin.wait(1) + self.childReadThread.eventFin.wait(1) + + + def sendBreak(self, file, lineno): + raise NotImplementedError() + + def sendContinue(self): + raise NotImplementedError() + + def sendRun(self): + raise NotImplementedError() + + def sendInspectVar(self, var): + raise NotImplementedError() + + def sendInspectExpr(self, expr): + raise NotImplementedError() + + def sendSetTTY(self, ttyname): + raise NotImplementedError() + + def sendQuit(self): + raise NotImplementedError() + + + class ReadThread (threading.Thread): + """Thread which reads from sub-process output""" + + def __init__( self, stream, callback, sleep=0.1): + self.stream = stream + self.fin = False + self.callback = callback + self.sleep = sleep + self.eventFin = threading.Event() + threading.Thread.__init__(self) + + def run(self): + + try: + while True: + #Wait until data is available + rlist, wlist, xlist = select.select([self.stream], [], [], self.sleep) + + #If we should finish, finish + if self.fin: + break + + #Got new data + if len(rlist) > 0: + fd = rlist[0] + str = fd.read(1) + #Call callbacks + self.callback(str) + except: + pass + + #Set the finished event + self.eventFin.set() + + + + +class GdbTerminal (DbgTerminal): + + def getCommand( self, binary ): + return "gdb --fullname %s" % (binary,) + + def sendBreak(self, file, lineno): + self.gdbin.write("break %s:%d\n" % (file, lineno)) + + def sendContinue(self): + self.gdbin.write("cont\n") + + def sendRun(self): + self.gdbin.write("run\n") + + def sendInspectVar(self, var): + self.sendInspectExpr(var) + + def sendInspectExpr(self, expr): + self.gdbin.write("print %s\n" % (expr,)) + + def sendSetTTY(self, ttyname): + self.gdbin.write("set inferior-tty %s\n" % (ttyname,)) + + def sendQuit(self): + self.gdbin.write("quit\n") + DbgTerminal.stop(self) + + + +if __name__ == "__main__": + + def tostdout(str): + sys.stdout.write(str) + sys.stdout.flush() + + try: + + term = GdbTerminal( "./main", tostdout, tostdout) + term.sendBreak("main.cpp", 13) + term.sendRun() + term.childin.write("1\n"); + term.childin.write("2\n"); + term.sendInspectVar("a+b") + term.sendContinue() + + + while not term.iseof(): + + cmd = sys.stdin.readline() + + if term.iseof(): + break + + if cmd == "quit\n": + term.sendQuit() + else: + term.gdbin.write(cmd) + + except Exception, e: + print e + except: + pass + + + print "stopping..." + term.stop() + + + -- 2.30.2