*
*/
public class PHPDBGInterface {
- public boolean sessionEnded = false;
- public int sessType = -1;
- public int BPUnderHit = 0;
- public String sessID = new String();
-
- private int[] LastBPRead = new int[10];
- private Vector DBGBPList = new Vector();
- private Vector DBGVarList = new Vector();
+ public boolean sessionEnded = false;
+ public int sessType = -1;
+ public int BPUnderHit = 0;
+ public String sessID = new String();
+
+ private int[] LastBPRead = new int[10];
+ private Vector DBGBPList = new Vector();
+ private Vector DBGVarList = new Vector();
private PHPStackFrame[] DBGStackList = new PHPStackFrame[0];
- private Vector DBGMods = new Vector(); // The module names and their numbers
- private Vector stackListOld = new Vector();
- private BufferedReader in;
- private OutputStream os; // The stream which goes to DBG
- private boolean shouldStop = false;
- private String evalRet = new String("");
- private int rawCounter = 1000; // An rawData frame ID counter
- private PHPDBGProxy proxy = null;
- //private int lastCmd = -1;
- private int sid = 0;
- private boolean stopOnError = false;
- private char[] lastCommand = new char[4];
+ private Vector DBGMods = new Vector(); // The module names and their numbers
+ private Vector stackListOld = new Vector();
+ private BufferedReader dbgInput;
+ private OutputStream dbgOutput; // The stream which goes to DBG
+ private boolean shouldStop = false;
+ private String evalRet = new String("");
+ private int rawCounter = 1000; // An rawData frame ID counter
+ private PHPDBGProxy proxy = null;
+// private int lastCmd = -1;
+ private int sid = 0;
+ private boolean stopOnError = false; // If we the debugger should be relaunched after script termination
+ private boolean bRelaunch = true;
+ private char[] lastCommand = new char[4];
+ private boolean bBusy = false;
+ private boolean bDebug = true; // Prints text to console for debugging purposes
private static final String GlobalVariablesTitle = PHPDebugCorePlugin
.getResourceString("VariablesView.GlobalVariables.title");
/**
- * @param in The input stream (communication from DBG).
- * @param os The output stream (communication to DBG).
- * @param proxy The proxy to which this interface belongs.
+ * @param in The input stream (communication from DBG).
+ * @param os The output stream (communication to DBG).
+ * @param proxy The proxy to which this interface belongs.
+ * @param bRelaunch The debugger should be relaunched after PHP script termination
*/
- public PHPDBGInterface (BufferedReader in, OutputStream os, PHPDBGProxy proxy) {
+ public PHPDBGInterface (BufferedReader in, OutputStream os, PHPDBGProxy proxy, boolean bRelaunch) {
DBGBPList.clear ();
- this.in = in;
- this.os = os;
- this.proxy = proxy;
+ this.dbgInput = in;
+ this.dbgOutput = os;
+ this.proxy = proxy;
+ this.bRelaunch = bRelaunch;
}
/**
PHPDBGPacket DBGPacket; // A DBG message packet
PHPDBGFrame DBGFrame; // A frame within a DBG packet
+ while (bBusy) {
+ }
+
+ bBusy = true;
+
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: getSourceTree");
+ }
+
DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST); // A request for DBG
DBGFrame = new PHPDBGFrame (PHPDBGBase.FRAME_SRC_TREE); // We want a source tree from DBG
DBGPacket.addFrame (DBGFrame); // Add the 'what we want' to the DBG packet
if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
+ bBusy = false;
return; // No
}
- DBGPacket.sendPacket (os); // Send the request to DBG
+ DBGPacket.sendPacket (dbgOutput); // Send the request to DBG
waitResponse (1000); // Wait for the DBG response (1 second)
flushAllPackets (); // Read and process the response from DBG
PHPDBGFrame DBGFrame3;
int modNo;
+ while (bBusy) {
+ }
+
+ bBusy = true;
+
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: setBreakpoint");
+ }
+
DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_REQUEST);
DBGFrame1 = new PHPDBGFrame (PHPDBGBase.FRAME_BPS);
DBGFrame2 = new PHPDBGFrame (PHPDBGBase.FRAME_RAWDATA);
DBGPacket.addFrame (DBGFrame1); // Second add command data
if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
+ bBusy = false;
return 0; // No
}
- DBGPacket.sendPacket (os); // Send the request to DBG
+ DBGPacket.sendPacket (dbgOutput); // Send the request to DBG
clearLastBP ();
public void continueExecution () throws IOException {
PHPDBGPacket DBGPacket;
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: continueExecution");
+ }
+
BPUnderHit = 0;
DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_CONTINUE);
if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
return; // No
}
- DBGPacket.sendPacket (os); // Send the request to DBG
+ DBGPacket.sendPacket (dbgOutput); // Send the request to DBG
lastCommand = PHPDBGBase.DBGA_CONTINUE; // Store the info about the command we sent
}
public void pauseExecution () throws IOException {
PHPDBGPacket DBGPacket;
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: pauseExecution");
+ }
+
DBGPacket = new PHPDBGPacket (PHPDBGBase.IntToChar4 (PHPDBGBase.DBGC_PAUSE));
if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
return; // No
}
- DBGPacket.sendPacket (os); // Send the request to DBG
+ DBGPacket.sendPacket (dbgOutput); // Send the request to DBG
}
/**
/**
*
*/
- public void stepInto () throws IOException {
+ public boolean stepInto () throws IOException {
PHPDBGPacket DBGPacket;
+ if (bBusy) {
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: stepOver vetoed");
+ }
+ }
+
+ while (bBusy) {
+ }
+
+ bBusy = true;
+
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: stepInto");
+ }
+
BPUnderHit = 0;
DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPINTO);
if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
- return; // No
+ return false; // No
}
- DBGPacket.sendPacket (os); // Send the request to DBG
+ DBGPacket.sendPacket (dbgOutput); // Send the request to DBG
lastCommand = PHPDBGBase.DBGA_STEPINTO; // Store the info about the command we sent
+
+ return true;
}
/**
*
*/
- public void stepOver () throws IOException {
+ public boolean stepOver () throws IOException {
PHPDBGPacket DBGPacket;
+ if (bBusy) {
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: stepOver vetoed");
+ }
+ }
+
+ while (bBusy) {
+ }
+
+ bBusy = true;
+
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: stepOver");
+ }
+
BPUnderHit = 0;
DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOVER);
if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
- return; // No
+ return false; // No
}
- DBGPacket.sendPacket (os); // Send the request to DBG
+ DBGPacket.sendPacket (dbgOutput); // Send the request to DBG
lastCommand = PHPDBGBase.DBGA_STEPOVER; // Store the info about the command we sent
+
+ return true;
}
/**
*
*/
- public void stepOut () throws IOException {
+ public boolean stepOut () throws IOException {
PHPDBGPacket DBGPacket;
+ if (bBusy) {
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: stepOver vetoed");
+ }
+ }
+
+ while (bBusy) {
+ }
+
+ bBusy = true;
+
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: stepOut");
+ }
+
BPUnderHit = 0;
DBGPacket = new PHPDBGPacket (PHPDBGBase.DBGA_STEPOUT);
if (proxy.getSocket ().isClosed ()) { // Can we communiate with DBG?
- return; // No
+ return false; // No
}
- DBGPacket.sendPacket (os); // Send the request to DBG
+ DBGPacket.sendPacket (dbgOutput); // Send the request to DBG
lastCommand = PHPDBGBase.DBGA_STEPOUT; // Store the info about the command we sent
+
+ return true;
}
/**
public synchronized Vector getVariables(PHPStackFrame stack) throws IOException, DebugException {
if (DBGStackList.length == 0) {
DBGVarList.clear();
+
return DBGVarList;
}
// Also note that 2.13.1 doesn't return $this in class context.
// (You can inspect $this in Expressions View. And once it is shown, 2.13.1 comes to return $this.)
Vector globalList = getVariables(DBGStackList[DBGStackList.length - 1], global_scope_id);
+
if (!globalList.isEmpty()) {
// remove unresolved '$this=?' variable
removeUnresolvedThisVar(globalList);
}
int scopeID = stack.getScopeID();
- if (!globalList.isEmpty()
- && ((DBGStackList.length == 1)
- || (scopeID == PHPDBGBase.CURLOC_SCOPE_ID + 1))) {
+
+ if (!globalList.isEmpty () &&
+ ((DBGStackList.length == 1) || (scopeID == PHPDBGBase.CURLOC_SCOPE_ID + 1))) {
// 'main()' stackframe
PHPVariable var = (PHPVariable) globalList.get(0);
- PHPValue val = (PHPValue) var.getValue();
- DBGVarList = val.getChildVariables();
- return DBGVarList;
+ PHPValue val = (PHPValue) var.getValue();
+
+ DBGVarList = val.getChildVariables();
- } else if (scopeID == PHPDBGBase.CURLOC_SCOPE_ID) {
+ return DBGVarList;
+ }
+ else if (scopeID == PHPDBGBase.CURLOC_SCOPE_ID) {
// current stackframe
DBGVarList = getVariables(stack, PHPDBGBase.CURLOC_SCOPE_ID);
-
- } else {
+ }
+ else {
// back-trace stackframe
//DBGVarList = getVariables(stack, scopeID);
//removeUnresolvedThisVar(DBGVarList);
}
/**
- *
+ *
*/
private Vector getVariables(PHPStackFrame stack, int scope_id) throws IOException {
PHPDBGPacket DBGPacket = new PHPDBGPacket(PHPDBGBase.DBGA_REQUEST);
PHPDBGFrame DBGFrame1 = new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
+ if (bBusy) {
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: getVariables vetoed");
+ }
+ }
+
+ while (bBusy) {
+ }
+
+ bBusy = true;
+
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: getVariables");
+ }
+
DBGFrame1.addInt(0);
DBGFrame1.addInt(scope_id);
evalRet = "";
if (proxy.getSocket().isClosed()) {
+ bBusy = false;
return new Vector();
}
- DBGPacket.sendPacket(os);
+
+ DBGPacket.sendPacket(dbgOutput);
waitResponse(1000);
flushAllPackets();
+ bBusy = false; // Already done in flushAllPackets ()
+
PHPDBGEvalString evalStr = new PHPDBGEvalString(stack, evalRet);
return evalStr.getVariables();
}
/**
* Remove unresolved $this variable
- *
+ *
* DBG returns $this=? in function's or intermediate stackframes.
* (In current method's stackframe, DBG returns $this=classname)
- *
+ *
* @param varList
*/
private void removeUnresolvedThisVar(Vector varList) {
if (varList.size() > 0) {
- PHPVariable var = (PHPVariable) varList.get(0);
- PHPValue val = (PHPValue) var.getValue();
- Vector workList = val.getChildVariables();
+ PHPVariable var = (PHPVariable) varList.get(0);
+ PHPValue val = (PHPValue) var.getValue();
+ Vector workList = val.getChildVariables ();
+
for (int i = 0; i < workList.size(); i++) {
PHPVariable workvar = (PHPVariable) workList.get(i);
- if (workvar.getName().equals("$this")) {
- String workval = ((PHPValue) workvar.getValue()).getValueString();
- if (workval.equals("?") || workval.equals("NULL")) {
- workList.remove(i);
+
+ if (workvar.getName().equals ("$this")) {
+ String workval = ((PHPValue) workvar.getValue ()).getValueString ();
+
+ if (workval.equals ("?") ||
+ workval.equals ("NULL")) {
+ workList.remove (i);
}
break;
}
PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_LOG);
PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
+ while (bBusy) {
+ }
+
+ bBusy = true;
+
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: log");
+ }
+
rawCounter++;
DBGFrame1.addInt(rawCounter); // ilog
DBGFrame1.addInt(1); // type
DBGPacket.addFrame(DBGFrame1);
if (proxy.getSocket ().isClosed ()) { // Do we have a socket for DBG communication?
+ bBusy = false;
return; // No, then leave here
}
- DBGPacket.sendPacket(os);
+ DBGPacket.sendPacket(dbgOutput);
waitResponse(1000);
flushAllPackets();
PHPDBGFrame DBGFrame1= new PHPDBGFrame(PHPDBGBase.FRAME_EVAL);
PHPDBGFrame DBGFrame2= new PHPDBGFrame(PHPDBGBase.FRAME_RAWDATA);
+ while (bBusy) {
+ }
+
+ bBusy = true;
+
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: evalBlock");
+ }
+
rawCounter++;
DBGFrame1.addInt(rawCounter); // istr = raw data ID
//DBGFrame1.addInt(1); // scope_id = -1 means current location, 0 never used, +1 first depth
DBGPacket.addFrame(DBGFrame1);
if (proxy.getSocket().isClosed()) { // Do we have a socket for DBG communication?
+ bBusy = false;
return null; // No, then leave here
}
- DBGPacket.sendPacket(os);
+
+ DBGPacket.sendPacket(dbgOutput);
waitResponse(1000);
flushAllPackets();
stackFrameOld.setAvailable (true); // We found the new stackframe in the list of old stack frames
stackFrameOld.setIndex (stackFrameNew.getIndex ());
stackFrameOld.setScopeID(stackFrameNew.getScopeID());
+
return true; // The stackframe was found in the list
}
}
if (isStackFrameInList (stackFrameNew, oldList)) { // Is this stackframe in the list
stackFrameNew.setAvailable (true); //
//
- break;
+// break;
}
}
}
PHPStackFrame stackFrameOld;
PHPStackFrame[] newStackList;
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: updateStackFrameList Start");
+ }
+
markIdenticalStackFrames (stackListOld, stackList); // Check whether the newly send stack frames can be found in the list
// of old stack frames
newStackList = new PHPStackFrame[stackListOld.size ()];
newStackList = (PHPStackFrame[]) stackListOld.toArray (newStackList);
DBGStackList = newStackList;
+
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: updateStackFrameList End");
+ }
}
/**
Vector rawList = new Vector();
Vector stackList = new Vector(); // Intermediate stacklist which is build up in FRAME_STACK frame
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: readResponse start");
+ }
+
rawList.clear ();
stackList.clear ();
dbg_header_struct[3] = PHPDBGBase.Char4ToInt (dbg_header_struct_read, 12); // Bytes within this block
if (dbg_header_struct[0] != 0x5953) { // Check DBG sync bytes
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: readResponse. Wrong sync");
+ }
+
+ bBusy = false;
return 0; // Wrong header
}
if (bytesToRead > 0) { // If there is something within the frame
if (readInput (entirePack, bytesToRead) < bytesToRead) { // Read the frame into the buffer
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: readResponse. Did not read enough");
+ }
+
+ bBusy = false;
return 0; // We did not read enough bytes, error
}
}
-
+
nextFrame = 0; // Start with the first frame
while (nextFrame < bytesToRead) { // As long as we have something within this block
nextFrame += 8; // The next read position
if (dbg_frame[1] == 0) { // Something within the frame?
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: readResponse. Nothing within the frame");
+ }
+
+ bBusy = false;
return 0; // Nothing to read, error
}
break;
case PHPDBGBase.DBGC_END:
- sessionEnded = true;
- this.proxy.setTerminated();
+ if (bRelaunch) {
+ continueExecution (); // Inform dbg that we want to continue execution
+ proxy.updateView (); // Sent a change event and create thread event to eclipse core
+ updateStackFrameList (stackList); // ??? Just a try
+ }
+ else {
+ sessionEnded = true;
+ proxy.setTerminated ();
+ }
break;
case PHPDBGBase.DBGC_BREAKPOINT:
}
}
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: readResponse finish, received: " + cmdReceived);
+ }
+
+ bBusy = false;
+
return cmdReceived; // Return the command we received with this block
}
*/
private int readInput (char[] buffer, int bytes) throws IOException {
int bytesRead = 0; // Reset the bytes read counter
+ int nRetry = 0; // Retry counter
+
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: readInput " + bytes);
+ }
- for (int i = 0; i < bytes; i++) { // For the number of bytes we should read
- if (in.ready ()) { // If input stream is ready for reading
- buffer[i] = (char) (in.read () & 0x00FF); // Read a char and store only the least significant 8-bits
+ for (int i = 0; i < bytes;) { // For the number of bytes we should read
+ if (dbgInput.ready ()) { // If input stream is ready for reading
+ nRetry = 0; // Reset the retry counter
+ buffer[i] = (char) (dbgInput.read () & 0x00FF); // Read a char and store only the least significant 8-bits
bytesRead++; // Increment the bytes read counter
+ i++;
}
else { // Input stream is not ready
- break; // Break the loop
+ nRetry++; // Increment the retry counter
+
+ if (nRetry > 10) { // If nothing received within 100 retries
+ if (i > 0) {
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: Too many retries without receiving something");
+ }
+ }
+ break; // we break the loop
+ }
+
+ synchronized (dbgInput) {
+ if (i > 0) {
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: retry: " + nRetry + " Wait for something to receive, received: " + i + " need " + bytes);
+ }
+ }
+ try {
+ dbgInput.wait (10); // wait 5 ms maximum for something to receive
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+
+ if (bytesRead > 0) {
+ if (bytes != bytesRead) {
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: readInput: Possible error: not enough bytes in buffer should read: " + bytes +
+ " actually read: " + bytesRead);
+ }
}
}
* @return - true if something was received from DBG
* - false if nothing was send from DBG within the given time
*
+ * This method has been a busy wait loop. It was changed to use
+ * a non busy wait to avoid a heavy load after automatic relaunch
+ * after script termination
+ *
*/
public boolean waitResponse (long milliseconds) throws IOException {
long timeout;
+ if (bDebug) {
+ System.out.println ("PHPDBGInterface: waitResponse " + milliseconds);
+ }
+
timeout = System.currentTimeMillis () + milliseconds; // Calculate the system time till we wait.
while (System.currentTimeMillis () < timeout) { // Is waiting time running out?
- if (in.ready () || shouldStop) { // No, so did we get something or should we stop now
- break; // Yes, break the waiting
+ synchronized (dbgInput) {
+ try {
+ dbgInput.wait (5); // wait 5 ms maximum for something to receive
+ } catch (InterruptedException e) {
+ }
+ }
+
+ if (dbgInput.ready () || shouldStop) { // If something is received of if we should stop now
+ break; // break the waiting loop
}
}
- return in.ready (); // true if we got something from DBG
+ return dbgInput.ready (); // true if we got something from DBG
}
}