diff options
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.java | 364 |
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 + + } +} |