initial commit with a little terminal code to gdb
authorStefan Huber <shuber2@gmail.com>
Mon, 2 Jun 2008 09:51:20 +0000 (11:51 +0200)
committerStefan Huber <shuber2@gmail.com>
Mon, 2 Jun 2008 09:51:20 +0000 (11:51 +0200)
DbgTerminal.py [new file with mode: 0755]

diff --git a/DbgTerminal.py b/DbgTerminal.py
new file mode 100755 (executable)
index 0000000..cef0d27
--- /dev/null
@@ -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()
+
+               
+