summaryrefslogtreecommitdiffstats
path: root/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/GDBServer.java
diff options
context:
space:
mode:
Diffstat (limited to 'zpu/sw/simulator/com/zylin/zpu/simulator/gdb/GDBServer.java')
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/gdb/GDBServer.java364
1 files changed, 364 insertions, 0 deletions
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/GDBServer.java b/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/GDBServer.java
new file mode 100644
index 0000000..182e426
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/GDBServer.java
@@ -0,0 +1,364 @@
+/**
+ * Handles TCP/IP communication between simulator and GDB
+ */
+
+package com.zylin.zpu.simulator.gdb;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.util.Iterator;
+
+import com.zylin.zpu.simulator.Host;
+import com.zylin.zpu.simulator.Sim;
+import com.zylin.zpu.simulator.SimApp;
+import com.zylin.zpu.simulator.exceptions.BadPacketException;
+import com.zylin.zpu.simulator.exceptions.CPUException;
+import com.zylin.zpu.simulator.exceptions.EndSessionException;
+import com.zylin.zpu.simulator.exceptions.GDBServerException;
+import com.zylin.zpu.simulator.exceptions.MemoryAccessException;
+import com.zylin.zpu.simulator.exceptions.UnsupportedSyscallException;
+
+public class GDBServer implements Host
+{
+ /* logging filter */
+ static final boolean UNKNOWN=false;
+ static final boolean ALL=false;
+ static final boolean CPUEXCEPTION = false;
+ static protected boolean MINIMAL=true;
+ static boolean PACKET=true;
+ static boolean REPLY=true;
+ static protected boolean IGNOREDEXCEPTIONS=false;
+
+
+
+ protected Throwable packetException;
+ protected Object packetReady=new Object();
+ private Packet packet;
+ boolean done;
+ private Socket sc;
+ public boolean alive;
+ static private int sessionNr;
+ private SimApp app;
+ Sim simulator;
+
+ public GDBServer(Sim simulator, SimApp app)
+ {
+ this.simulator=simulator;
+ this.app=app;
+ }
+
+ void print(boolean filter, String str)
+ {
+ if (filter)
+ {
+ System.out.println(str);
+ }
+ }
+
+ /** infinite loop that waits for debug sessions to be initiated via TCP/IP */
+ public void gdbServer() throws MemoryAccessException, IOException, GDBServerException, EndSessionException
+ {
+ sc=app.serverSocket.accept();
+ try
+ {
+ debugSession();
+ } catch (IOException e)
+ {
+ // the session failed...
+ if (IGNOREDEXCEPTIONS)
+ {
+ e.printStackTrace();
+ }
+ } catch (GDBServerException e)
+ {
+ // connect failed...
+ if (IGNOREDEXCEPTIONS)
+ {
+ e.printStackTrace();
+ }
+ } catch (EndSessionException e)
+ {
+ } catch (Throwable e)
+ {
+ // some terrible unforseen failure.
+ e.printStackTrace();
+ } finally
+ {
+ sc.close();
+ }
+ }
+
+
+
+ protected void sleepABit()
+ {
+ try
+ {
+ // just to avoid locking up the machine in a busy loop when
+ // debugging the Simulator
+ Thread.sleep(2000);
+ } catch (InterruptedException e1)
+ {
+ e1.printStackTrace();
+ }
+ }
+
+ private void debugSession() throws IOException, GDBServerException, EndSessionException, MemoryAccessException
+ {
+ print(MINIMAL, "GDB server waiting for connection " + sessionNr++ + "...");
+
+ try
+ {
+ sessionStarted();
+
+ expect('+'); // connection ack.
+
+ sessionLoop();
+ } finally
+ {
+ print(MINIMAL, "Session ended");
+ }
+
+ }
+
+ private void sessionStarted()
+ {
+ simulator.sessionStarted();
+ print(MINIMAL, "Session started");
+ }
+
+
+ private void sessionLoop() throws IOException, EndSessionException
+ {
+ alive=true;
+ while (alive)
+ {
+ try
+ {
+ /* wait for new packet to arrive and notify the packet execution thread... */
+ packet=new Packet(this);
+ packet.receive();
+
+ // During execution we can receive an abort/suspend command...
+ packet.parseAndExecute();
+
+ if (!alive)
+ throw new EndSessionException();
+ } catch (BadPacketException e)
+ {
+ // do nothing.
+ if (IGNOREDEXCEPTIONS)
+ {
+ e.printStackTrace();
+ }
+ sleepABit();
+ } catch (GDBServerException e)
+ {
+ if (IGNOREDEXCEPTIONS)
+ {
+ e.printStackTrace();
+ }
+ // continue processing packets
+ sleepABit();
+ }
+ }
+ }
+
+
+
+
+ void expect(char nextChar) throws IOException, GDBServerException
+ {
+ int t = read();
+ if (t!=nextChar)
+ {
+ throw new BadPacketException();
+ }
+ }
+
+ int read() throws IOException
+ {
+ flush();
+ int t=sc.getInputStream().read();
+ if (t==-1)
+ throw new IOException();
+ return t;
+ }
+
+ /**
+ * @param value
+ * @return
+ */
+ protected String printHex(int value)
+ {
+ return formatHex(value, "00000000");
+ }
+
+ /**
+ * @param value
+ * @param pad TODO
+ * @return
+ */
+ protected String formatHex(int value, String pad)
+ {
+ String t=Integer.toHexString(value);
+ if (t.length()>pad.length())
+ {
+ t=t.substring(0, pad.length());
+ }
+ return pad.substring(0, pad.length()-t.length())+t;
+ }
+
+ public void write(byte[] bytes) throws IOException
+ {
+ sc.getOutputStream().write(bytes);
+ }
+
+ void flush() throws IOException
+ {
+ sc.getOutputStream().flush();
+ }
+
+
+ private boolean enterSyscall;
+
+
+
+ /* handle all sorts of IO calls, etc. by sending them to the
+ */
+ public void syscall(Sim s) throws CPUException
+ {
+ simulator.suspend();
+ enterSyscall=true;
+ }
+
+
+ protected void performSyscall()
+ {
+ enterSyscall=false;
+ try
+ {
+ int id;
+ id=simulator.getArg(1);
+ Packet syscall;
+ syscall=new Packet(this);
+ switch (id)
+ {
+ case Host.SYS_write:
+ syscall.invokeSyscall("write", 3, "iii");
+ break;
+ case Host.SYS_read:
+ syscall.invokeSyscall("read", 3, "iii");
+ break;
+ case Host.SYS_lseek:
+ syscall.invokeSyscall("lseek", 3, "iii");
+ break;
+ case Host.SYS_open:
+ syscall.invokeSyscall("open", 3, "sii");
+ break;
+ case Host.SYS_close:
+ syscall.invokeSyscall("close", 1, "i");
+ break;
+ case Host.SYS_fstat:
+ syscall.invokeSyscall("fstat", 2, "ii");
+ break;
+ case Host.SYS_stat:
+ syscall.invokeSyscall("stat", 2, "si");
+ break;
+ case Host.SYS_isatty:
+ syscall.invokeSyscall("isatty", 1, "i");
+ break;
+ case Host.SYS_unlink:
+ syscall.invokeSyscall("unlink", 1, "s");
+ break;
+ default:
+ simulator.suspend();
+ throw new UnsupportedSyscallException();
+ }
+ simulator.cpuWriteLong(simulator.getArg(0), syscall.syscallErrno);
+ simulator.cpuWriteLong(0, syscall.syscallRetval);
+ } catch (CPUException e)
+ {
+ e.printStackTrace();
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ } catch (GDBServerException e)
+ {
+ e.printStackTrace();
+ } catch (EndSessionException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public boolean doneContinue()
+ {
+ if (!enterSyscall)
+ return true;
+ performSyscall();
+ return false;
+ }
+
+ public int getSyscallArg(int i) throws CPUException
+ {
+ return simulator.getArg(i+2);
+ }
+
+ public void writeUART(int val)
+ {
+ System.out.print((char)val);
+ System.out.flush();
+
+
+ Packet p=new Packet(this);
+ p.reply("O" + formatHex(val, "00"));
+ p.sendReply();
+
+
+ }
+ public int readUART() throws CPUException
+ {
+ try
+ {
+ if (System.in.available()<=0)
+ {
+ throw new MemoryAccessException();
+ }
+
+ return System.in.read();
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ public int readFIFO()
+ {
+ try
+ {
+ return System.in.available()>0?0:1;
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ return 1;
+ }
+
+ public void halted()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void running()
+ {
+ // TODO Auto-generated method stub
+
+ }
+}
OpenPOWER on IntegriCloud