summaryrefslogtreecommitdiffstats
path: root/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/Packet.java
diff options
context:
space:
mode:
Diffstat (limited to 'zpu/sw/simulator/com/zylin/zpu/simulator/gdb/Packet.java')
-rw-r--r--zpu/sw/simulator/com/zylin/zpu/simulator/gdb/Packet.java472
1 files changed, 472 insertions, 0 deletions
diff --git a/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/Packet.java b/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/Packet.java
new file mode 100644
index 0000000..ad68947
--- /dev/null
+++ b/zpu/sw/simulator/com/zylin/zpu/simulator/gdb/Packet.java
@@ -0,0 +1,472 @@
+/*
+ * Created on Nov 16, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package com.zylin.zpu.simulator.gdb;
+
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+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.NoAckException;
+import com.zylin.zpu.simulator.exceptions.UnknownPacketException;
+
+
+/** all packet related operations */
+class Packet
+{
+ private final GDBServer server;
+
+ Packet(GDBServer server)
+ {
+ this.server = server;
+ reply=new StringBuffer();
+ }
+
+ void receive() throws IOException, GDBServerException, EndSessionException
+ {
+ int t;
+ /* we spool until we see a $ */
+ this.server.expect('$');
+
+ StringBuffer packet=new StringBuffer();
+
+ int cc=0;
+ for (;;)
+ {
+ int t1;
+ t1=this.server.read();
+ t = t1;
+ if (t==0x7d)
+ {
+ int t2;
+ t2=this.server.read();
+ /* the next char is escaped after a GDB specific scheme. See
+ * gdb/gdb/remote.c */
+ t = t2;
+ t^=0x20;
+ } else
+ {
+ if (t=='#')
+ {
+ break;
+ }
+ }
+
+ cc+=t;
+
+ packet.append((char)t);
+ }
+ cc&=0xff;
+
+ String checkSum;
+ checkSum=""+(char)this.server.read()+(char)this.server.read();
+ int readCheckSum;
+ readCheckSum=Integer.parseInt(checkSum, 16);
+ if (readCheckSum!=cc)
+ {
+ // error
+ dumpHex(packet.toString());
+
+ this.server.write("-".getBytes());
+ throw new BadPacketException();
+ } else
+ {
+ // ack
+ this.server.write("+".getBytes());
+ }
+
+ cmd=packet.toString();
+ this.server.print(GDBServer.PACKET, "Got " + number + ": #$" + cmd + "#" + checkSum);
+ origCmd=cmd;
+ }
+
+ void parseAndExecute() throws IOException, EndSessionException
+ {
+ boolean silent=false;
+ try
+ {
+ if (checkPrefix("g"))
+ {
+ readRegisters();
+ } else if (checkPrefix("?"))
+ {
+ querySignal();
+ } else if (checkPrefix("s"))
+ {
+ doStep();
+ } else if (checkPrefix("m"))
+ {
+ try
+ {
+ readMemory();
+ } catch (CPUException e)
+ {
+ silent=true; // happens all the time while hovering over variables in the GUI
+ throw e;
+ }
+ } else if (checkPrefix("c"))
+ {
+ continueExecution();
+ } else if (checkPrefix("M"))
+ {
+ writeMemory();
+ } else if (checkPrefix("z4"))
+ {
+ disableAccessWatchPoint();
+ } else if (checkPrefix("Z4"))
+ {
+ enableAccessWatchPoint();
+ } else if (checkPrefix("k"))
+ {
+ /* we must send a reply, but not wait for ack before we shut down
+ the connection.
+ */
+ server.alive=false;
+ reply("OK");
+ } else
+ {
+ throw new UnknownPacketException();
+ }
+ } catch (UnknownPacketException e)
+ {
+ this.server.print(GDBServer.UNKNOWN, "Unknown packet: " + origCmd);
+ // empty reply to unknown packets
+ } catch (CPUException e)
+ {
+ if (!silent)
+ {
+ this.server.print(GDBServer.CPUEXCEPTION, "Exception handling GDB request");
+ if (GDBServer.CPUEXCEPTION)
+ {
+ e.printStackTrace();
+ }
+ }
+ reply("E01");
+ } catch (GDBServerException e)
+ {
+ e.printStackTrace();
+ reply("E01");
+ } catch (RuntimeException e)
+ {
+ e.printStackTrace();
+ reply("E01");
+ }
+
+ sendReply();
+ }
+
+ private void checkEmpty() throws GDBServerException
+ {
+ if (cmd.length()>0)
+ {
+ throw new GDBServerException();
+ }
+ }
+ private void dumpHex(String arrayList2)
+ {
+ for (int i=0; i<arrayList2.length(); i++)
+ {
+ System.out.println(this.server.formatHex(arrayList2.charAt(i), "00"));
+ }
+ }
+ /**
+ * @param packetString
+ * @param string
+ * @return
+ */
+ private boolean checkPrefix(String string)
+ {
+ if (cmd.length() < string.length())
+ {
+ return false;
+ } else
+ {
+ return cmd.substring(0, string.length()).equals(string);
+ }
+ }
+ /**
+ * @throws GDBServerException
+ * @throws IOException
+ * @throws MemoryAccessException
+ *
+ */
+ private void continueExecution() throws GDBServerException
+ {
+ extractString("c");
+ try
+ {
+ if (!isEmpty())
+ {
+ int pc=extractInteger();
+ this.server.simulator.setPc(pc);
+ }
+ checkEmpty();
+ this.server.simulator.cont();
+ } catch (MemoryAccessException e)
+ {
+ if (GDBServer.IGNOREDEXCEPTIONS)
+ {
+ e.printStackTrace();
+ }
+ }
+ reply("S05");
+ }
+ private void doStep()
+ {
+ this.server.simulator.step();
+ reply("S05");
+ }
+ protected int extractInteger() throws GDBServerException
+ {
+ String number;
+ Pattern p=Pattern.compile("(\\-?[0-9a-fA-F]+)");
+ Matcher m = p.matcher(cmd);
+ if (!m.find())
+ {
+ throw new GDBServerException();
+ }
+ number=m.group();
+ extractString(number);
+
+ try
+ {
+ return (int)Long.parseLong(number, 16);
+ } catch (NumberFormatException e)
+ {
+ throw new GDBServerException(e);
+ }
+ }
+ /**
+ * @param string
+ * @throws GDBServerException
+ */
+ private void extractString(String string) throws GDBServerException
+ {
+ if (!checkPrefix(string))
+ {
+ throw new GDBServerException();
+ }
+ stripStart(string.length());
+ }
+ /**
+ * @throws GDBServerException
+ *
+ */
+ private void readMemory() throws CPUException, GDBServerException
+ {
+ extractString("m");
+ int address=extractInteger();
+ extractString(",");
+ int length=extractInteger();
+ checkEmpty();
+
+ for (int i=0; i<length; i++)
+ {
+ reply(this.server.formatHex(this.server.simulator.readByte(address+i), "00"));
+ }
+ }
+ /**
+ *
+ */
+ private void readRegisters() throws CPUException
+ {
+ for (int i=0; i<this.server.simulator.getREGNUM(); i++)
+ {
+ reply(this.server.printHex(this.server.simulator.getReg(i)));
+ }
+ }
+ private void writeMemory() throws GDBServerException, MemoryAccessException
+ {
+ extractString("M");
+ int address=extractInteger();
+ extractString(",");
+ int length=extractInteger();
+ extractString(":");
+
+ for (int i=0; i<length; i++)
+ {
+ String t;
+ t=cmd.substring(i*2, i*2+2);
+ int val;
+ val=Integer.parseInt(t, 16);
+ this.server.simulator.writeByte(address+i, val);
+ }
+ reply("OK");
+
+ }
+
+ private void enableAccessWatchPoint() throws GDBServerException, CPUException
+ {
+ extractString("Z4");
+ extractString(",");
+ int address=extractInteger();
+ extractString(",");
+ int length=extractInteger();
+ checkEmpty();
+ server.simulator.enableAccessWatchPoint(address, length);
+
+ reply("OK");
+ }
+
+ private void disableAccessWatchPoint() throws GDBServerException, CPUException
+ {
+ extractString("z4");
+ extractString(",");
+ int address=extractInteger();
+ extractString(",");
+ int length=extractInteger();
+ checkEmpty();
+ server.simulator.disableAccessWatchPoint(address, length);
+
+ reply("OK");
+ }
+
+
+ private void stripStart(int length)
+ {
+ cmd=cmd.substring(length);
+ }
+ private boolean isEmpty()
+ {
+ return cmd.length()==0;
+ }
+ /**
+ * @param string
+ */
+ protected void reply(String string)
+ {
+ reply.append(string);
+ }
+ void sendReply()
+ {
+ // a bit easier to debug if we can see the entire string.
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("$");
+ number++;
+ String replyString = reply.toString();
+ buffer.append(replyString);
+ byte[] data = replyString.toString().getBytes();
+ int csum = 0;
+ for (int i = 0; i < data.length; i++)
+ {
+ csum += data[i];
+ }
+ csum &= 0xff;
+ buffer.append("#");
+ String t = Integer.toHexString(csum);
+ if (t.length() == 1)
+ {
+ t = "0" + t;
+ }
+ buffer.append(t);
+ this.server.print(GDBServer.REPLY, "Reply " + number + " : " + buffer.toString());
+ try
+ {
+ this.server.write(buffer.toString().getBytes());
+ } catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ if (server.alive)
+ {
+ /* check for ack. */
+ int ack;
+ try
+ {
+ ack = (char)this.server.read();
+ } catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ if (ack == '+')
+ {
+ return;
+ }
+ this.server.print(GDBServer.MINIMAL, "Retry");
+
+ throw new NoAckException();
+ }
+ reply=new StringBuffer();
+ }
+
+ private void querySignal()
+ {
+ // SIGINT
+ // reply("S02");
+ reply("S05");
+ }
+ protected String cmd;
+ private int number;
+ private StringBuffer reply;
+ private String origCmd;
+ int syscallErrno;
+ int syscallRetval;
+
+
+
+ void invokeSyscall(String string, int argNum, String types) throws IOException, NoAckException, GDBServerException, EndSessionException, CPUException
+ {
+ string="F"+string;
+
+ int j=0;
+ for (int i=0; i<argNum; i++)
+ {
+ string+=",";
+ string+=Integer.toHexString(server.getSyscallArg(j));
+ j++;
+ if (types.charAt(i)=='s')
+ {
+ string+="/" + Integer.toHexString(server.getSyscallArg(j));
+ j++;
+ }
+ }
+
+ reply(string);
+ sendReply();
+ for (;;)
+ {
+ Packet packet=new Packet(server);
+ packet.receive();
+ if (packet.checkPrefix("F"))
+ {
+ /* this is the reply we are waiting for */
+ packet.extractString("F");
+ syscallRetval=packet.extractInteger();
+ syscallErrno=0;
+ if (packet.checkPrefix(","))
+ {
+ /* errno is optional */
+ packet.extractString(",");
+ syscallErrno = packet.extractInteger();
+ }
+ break;
+ } else
+ {
+ /* something else... */
+ try
+ {
+ packet.parseAndExecute();
+ packet.sendReply();
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ } catch (EndSessionException e)
+ {
+ e.printStackTrace();
+ } catch (RuntimeException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+} \ No newline at end of file
OpenPOWER on IntegriCloud