diff options
author | Pawel Piech | 2009-01-16 23:44:55 +0000 |
---|---|---|
committer | Pawel Piech | 2009-01-16 23:44:55 +0000 |
commit | 710d2b7f0e09ad78957386e02787908caea8a72f (patch) | |
tree | b91ec78ff174dc0714704347467062213c191f38 /org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda | |
parent | 9cb32841fe223aeb0c43404f71bbb8eabfaa7d52 (diff) | |
download | eclipse.platform.debug-710d2b7f0e09ad78957386e02787908caea8a72f.tar.gz eclipse.platform.debug-710d2b7f0e09ad78957386e02787908caea8a72f.tar.xz eclipse.platform.debug-710d2b7f0e09ad78957386e02787908caea8a72f.zip |
Bug 261400 - Port the PDA example debugger's virtual machine from Perl to Java
Diffstat (limited to 'org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda')
12 files changed, 631 insertions, 378 deletions
diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java index 24062b0b5..894d7432c 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDALineBreakpoint.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.breakpoints; @@ -16,14 +17,18 @@ import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IBreakpoint; -import org.eclipse.debug.core.model.IThread; import org.eclipse.debug.core.model.LineBreakpoint; import org.eclipse.debug.examples.core.pda.DebugCorePlugin; import org.eclipse.debug.examples.core.pda.model.IPDAEventListener; import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; import org.eclipse.debug.examples.core.pda.model.PDAThread; +import org.eclipse.debug.examples.core.protocol.PDAClearBreakpointCommand; +import org.eclipse.debug.examples.core.protocol.PDAEvent; +import org.eclipse.debug.examples.core.protocol.PDARunControlEvent; +import org.eclipse.debug.examples.core.protocol.PDASetBreakpointCommand; +import org.eclipse.debug.examples.core.protocol.PDASuspendedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMSuspendedEvent; /** @@ -108,7 +113,7 @@ public class PDALineBreakpoint extends LineBreakpoint implements IPDAEventListen //#ifdef ex3 //# // TODO: Exercise 3 - create breakpoint request in interpreter //#else - target.sendRequest("set " + (getLineNumber() - 1)); + target.sendCommand(new PDASetBreakpointCommand((getLineNumber() - 1), false)); //#endif } @@ -123,7 +128,7 @@ public class PDALineBreakpoint extends LineBreakpoint implements IPDAEventListen //#ifdef ex3 //# // TODO: Exercise 3 - clear breakpoint request in interpreter //#else - target.sendRequest("clear " + (getLineNumber() - 1)); + target.sendCommand(new PDAClearBreakpointCommand((getLineNumber() - 1))); //#endif } @@ -154,16 +159,12 @@ public class PDALineBreakpoint extends LineBreakpoint implements IPDAEventListen /** * Notify's the PDA interprettor that this breakpoint has been hit. */ - protected void notifyThread() { + protected void notifyThread(int threadId) { if (fTarget != null) { - try { - IThread[] threads = fTarget.getThreads(); - if (threads.length == 1) { - PDAThread thread = (PDAThread)threads[0]; - thread.suspendedBy(this); - } - } catch (DebugException e) { - } + PDAThread thread = fTarget.getThread(threadId); + if (thread != null) { + thread.suspendedBy(this); + } } } @@ -173,9 +174,12 @@ public class PDALineBreakpoint extends LineBreakpoint implements IPDAEventListen * * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String) */ - public void handleEvent(String event) { - if (event.startsWith("suspended breakpoint")) { - handleHit(event); + public void handleEvent(PDAEvent event) { + if (event instanceof PDASuspendedEvent || event instanceof PDAVMSuspendedEvent) { + PDARunControlEvent rcEvent = (PDARunControlEvent)event; + if (rcEvent.fReason.equals("breakpoint")) { + handleHit(rcEvent); + } } } @@ -184,16 +188,16 @@ public class PDALineBreakpoint extends LineBreakpoint implements IPDAEventListen * * @param event breakpoint event */ - private void handleHit(String event) { - int lastSpace = event.lastIndexOf(' '); + private void handleHit(PDARunControlEvent event) { + int lastSpace = event.fMessage.lastIndexOf(' '); if (lastSpace > 0) { - String line = event.substring(lastSpace + 1); + String line = event.fMessage.substring(lastSpace + 1); int lineNumber = Integer.parseInt(line); // breakpoints event line numbers are 0 based, model objects are 1 based lineNumber++; try { if (getLineNumber() == lineNumber) { - notifyThread(); + notifyThread(event.fThreadId); } } catch (CoreException e) { } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java index ab819d0b5..651532909 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/breakpoints/PDAWatchpoint.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.breakpoints; @@ -19,6 +20,11 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IWatchpoint; import org.eclipse.debug.examples.core.pda.model.PDADebugTarget; +import org.eclipse.debug.examples.core.protocol.PDAEvent; +import org.eclipse.debug.examples.core.protocol.PDARunControlEvent; +import org.eclipse.debug.examples.core.protocol.PDASuspendedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMSuspendedEvent; +import org.eclipse.debug.examples.core.protocol.PDAWatchCommand; /** @@ -177,23 +183,26 @@ public class PDAWatchpoint extends PDALineBreakpoint implements IWatchpoint { if (isModification()) { flag = flag | 2; } - target.sendRequest("watch " + getFunctionName() + "::" + getVariableName() + " " + flag); + target.sendCommand(new PDAWatchCommand(getFunctionName(), getVariableName(), flag)); } /* (non-Javadoc) * @see org.eclipse.debug.examples.core.pda.breakpoints.PDALineBreakpoint#clearRequest(org.eclipse.debug.examples.core.pda.model.PDADebugTarget) */ protected void clearRequest(PDADebugTarget target) throws CoreException { - target.sendRequest("watch " + getFunctionName() + "::" + getVariableName() + " " + 0); + target.sendCommand(new PDAWatchCommand(getFunctionName(), getVariableName(), 0)); } /* (non-Javadoc) * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String) */ - public void handleEvent(String event) { - if (event.startsWith("suspended watch")) { - handleHit(event); - } + public void handleEvent(PDAEvent event) { + if (event instanceof PDASuspendedEvent || event instanceof PDAVMSuspendedEvent) { + PDARunControlEvent rcEvent = (PDARunControlEvent)event; + if (rcEvent.fReason.equals("watch")) { + handleHit(rcEvent); + } + } } /** @@ -201,8 +210,8 @@ public class PDAWatchpoint extends PDALineBreakpoint implements IWatchpoint { * * @param event breakpoint event */ - private void handleHit(String event) { - String[] strings = event.split(" "); + private void handleHit(PDARunControlEvent event) { + String[] strings = event.fMessage.split(" "); if (strings.length == 4) { String fv = strings[3]; int j = fv.indexOf("::"); @@ -212,7 +221,7 @@ public class PDAWatchpoint extends PDALineBreakpoint implements IWatchpoint { try { if (getVariableName().equals(var) && getFunctionName().equals(fcn)) { setSuspendType(strings[2]); - notifyThread(); + notifyThread(event.fThreadId); } } catch (CoreException e) { } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java index b5fd026dd..be7db91dd 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/launcher/PDALaunchDelegate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.launcher; @@ -55,28 +56,23 @@ public class PDALaunchDelegate extends LaunchConfigurationDelegate { List commandList = new ArrayList(); - // Perl executable - IValueVariable perl = VariablesPlugin.getDefault().getStringVariableManager().getValueVariable(DebugCorePlugin.VARIALBE_PERL_EXECUTABLE); - if (perl == null) { - abort("Perl executable location undefined. Check value of ${perlExecutable}.", null); - } - String path = perl.getValue(); - if (path == null) { - abort("Perl executable location unspecified. Check value of ${perlExecutable}.", null); - } - File exe = new File(path); - if (!exe.exists()) { - abort(MessageFormat.format("Specified Perl executable {0} does not exist. Check value of $perlExecutable.", new String[]{path}), null); - } - commandList.add(path); - - // Add PDA VM - File vm = DebugCorePlugin.getFileInPlugin(new Path("pdavm/pda.pl")); - if (vm == null) { - abort("Missing PDA VM", null); - } - commandList.add(vm.getAbsolutePath()); - + // Get Java VM path + String javaVMHome = System.getProperty("java.home"); + String javaVMExec = javaVMHome + File.separatorChar + "bin" + File.separatorChar + "java"; + if (File.separatorChar == '\\') { + javaVMExec += ".exe"; + } + File exe = new File(javaVMExec); + if (!exe.exists()) { + abort(MessageFormat.format("Specified java VM executable {0} does not exist.", new Object[]{javaVMExec}), null); + } + commandList.add(javaVMExec); + + commandList.add("-cp"); + commandList.add(File.pathSeparator + DebugCorePlugin.getFileInPlugin(new Path("bin"))); + + commandList.add("org.eclipse.debug.examples.pdavm.PDAVirtualMachine"); + // program name String program = configuration.getAttribute(DebugCorePlugin.ATTR_PDA_PROGRAM, (String)null); if (program == null) { @@ -106,7 +102,7 @@ public class PDALaunchDelegate extends LaunchConfigurationDelegate { String[] commandLine = (String[]) commandList.toArray(new String[commandList.size()]); Process process = DebugPlugin.exec(commandLine, null); - IProcess p = DebugPlugin.newProcess(launch, process, path); + IProcess p = DebugPlugin.newProcess(launch, process, javaVMExec); // if in debug mode, create a debug target if (mode.equals(ILaunchManager.DEBUG_MODE)) { IDebugTarget target = new PDADebugTarget(launch, p, requestPort, eventPort); diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java index 6935ad32b..b681dc880 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/IPDAEventListener.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,46 +8,28 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; +import org.eclipse.debug.examples.core.protocol.PDAEvent; + /** * Listeners are notified of events occurring in a PDA program * being interpreted. - * <p> - * The events generated by the interpreter are: - * <ul> - * <li><code>started</code> - the interpreter has started (guaranteed to be the - * first event sent)</li> - * <li><code>terminated</code> - the interpreter has terminated (guaranteed to be - * the last event sent)</li> - * <li><code>suspended X</code> - the interpreter has suspended and entered debug mode; - * <code>X</code> is the cause of the suspension: - * <ul> - * <li><code>breakpoint N</code> - a breakpoint at line <code>N</code> was hit</li> - * <li><code>client</code> - a client request to suspend has completed</li> - * <li><code>drop</code> - a client request to drop a frame has completed</li> - * <li><code>event E</code> - an error was encountered, where <code>E</code> is one - * of <code>unimpinstr</code> or <code>nosuchlabel</code></li> - * <li><code>step</code> - a step request has completed</li> - * <li><code>watch A F::V</code> - a watchpoint was hit for reason <code>A</code> - * (<code>read</code> or <code>write</code>), on variable <code>V</code> in - * function <code>F</code></li> - * </ul> - * </li> - * <li><code>resumed X</code> - the interpreter has resumed execution in run mode; - * <code>X</code> is the cause of the resume: - * <ul> - * <li><code>step</code> - a step request has been initiated</li> - * <li><code>client</code> - a client request to resume has been initiated</li> - * </ul> - * </li> - * <li><code>unimplemented instruction X</code> - an unimplemented instruction <code>X</code> - * was encountered</li> - * <li><code>no such label X</code> - a branch or call to an unknown label <code>X</code> - * was encountered</li> - * </ul> - * </p> + * + * @see org.eclipse.debug.examples.core.protocol.PDAVMStarted + * @see org.eclipse.debug.examples.core.protocol.PDAVMTerminated + * @see org.eclipse.debug.examples.core.protocol.PDAVMSuspneded + * @see org.eclipse.debug.examples.core.protocol.PDAVMResumed + * @see org.eclipse.debug.examples.core.protocol.PDAStarted + * @see org.eclipse.debug.examples.core.protocol.PDAExited + * @see org.eclipse.debug.examples.core.protocol.PDASuspended + * @see org.eclipse.debug.examples.core.protocol.PDAResumed + * @see org.eclipse.debug.examples.core.protocol.PDAUnimplementedInstructionEvent + * @see org.eclipse.debug.examples.core.protocol.PDARegisterData + * @see org.eclipse.debug.examples.core.protocol.PDANoSuchLabelEvent + * @see org.eclipse.debug.examples.core.protocol.PDAEvalResultEvent */ public interface IPDAEventListener { @@ -57,6 +39,6 @@ public interface IPDAEventListener { * * @param event the event */ - public void handleEvent(String event); + public void handleEvent(PDAEvent event); } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java index e27e1bad1..bcc07ba35 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAArray.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; @@ -23,7 +24,7 @@ public class PDAArray extends PDAValue { * @throws DebugException */ public PDAArray(PDAValue value) throws DebugException { - super(value.getPDADebugTarget(), value.getValueString()); + super(value.getVariable(), value.getValueString()); } /* (non-Javadoc) @@ -42,7 +43,7 @@ public class PDAArray extends PDAValue { IVariable[] variables = new IVariable[words.length]; for (int i = 0; i < words.length; i++) { String word = words[i]; - variables[i] = new PDAArrayEntry(getPDADebugTarget(), i, new PDAValue(getPDADebugTarget(), word)); + variables[i] = new PDAArrayEntry(getPDADebugTarget(), i, new PDAValue(getVariable(), word)); } return variables; } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java index e64f22050..6bf39f31d 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; @@ -17,6 +18,8 @@ import org.eclipse.debug.core.IBreakpointManager; import org.eclipse.debug.core.model.DebugElement; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.examples.core.pda.DebugCorePlugin; +import org.eclipse.debug.examples.core.protocol.PDACommand; +import org.eclipse.debug.examples.core.protocol.PDACommandResult; /** @@ -41,61 +44,50 @@ public class PDADebugElement extends DebugElement { } /** - * Sends a request to the PDA interpreter, waits for and returns the reply. - * <p> - * Interpreter commands and replies are as follows: - * <ul> - * <li><code>clear N</code> - clear the breakpoint on line <code>N</code>; - * reply is <code>ok</code></li> - * <li><code>data</code> - return the contents of the data stack; reply is the data - * from oldest to newest as a single string <code>"value|value|value|...|value|"</code></li> - * <li><code>drop</code> - pops the top stack frame off the call stack setting the - * instruction pointer to the calling statement in the calling frame</li> - * <li><code>eventstop E B</code> - optionally stop the interpreter when an error event - * <code>E</code> is encountered; <code>B</code> specifies stop (<code>1</code>) or - * continue (<code>0</code>). The possible events are <code>unimpinstr</code> and - * <code>nosuchlabel</code>. Reply is <code>ok</code>. When an event is encountered, - * the interpreter sends the error event (for example <code>unimlpemented instruction foo</code>) - * and corresponding suspend event (for example <code>suspended event unimpinstr</code>).</li> - * <li><code>exit</code> - end the interpreter; reply is <code>ok</code></li> - * <li><code>popdata</code> - pop the top value off the data stack; reply is the value</li> - * <li><code>pushdata V</code> - push the value <code>V</code> onto the data stack; reply is - * <code>ok</code></li> - * <li><code>resume</code> - resume execution of the program; reply is <code>ok</code></li> - * <li><code>set N</code> - set a line breakpoint on line <code>N</code> (lines are indexed - * from 0); reply is <code>ok</code></li> - * <li><code>setdata N V</code> - set the contents of data stack element <code>N</code> to - * value <code>V</code> (the data stack is indexed from 0, 0 being the oldest); reply - * is <code>ok</code></li> - * <li><code>setvar N M V</code> - set the contents of variable <code>M</code> from the control - * stack <code>N</code> to value <code>V</code> (the control stack is indexed from 0, - * 0 being the oldest); reply is <code>ok</code></li> - * <li><code>stack</code> - return the contents of the control stack (program counters, function and - * variable names); reply is control stack from oldest to newest as a single string - * <code>frame#frame#frame...#frame</code> where each frame is a string - * <code>"filename|pc|function name|variable name|variable name|...|variable name"</code></li> - * <li><code>step</code> - single step forward; reply is <code>ok</code></li> - * <li><code>stepreturn</code> - single step forward until the next <code>return</code> op code; - * stop before executing the <code>return</code> ; reply is <code>ok</code></li> - * <li><code>suspend</code> - suspend execution of the program and listen for debug commands; - * reply is <code>ok</code></li> - * <li><code>watch F::V M</code> - set a watchpoint on variable <code>V</code> in function - * <code>F</code> to magic value <code>M</code>; the magic value is a bit flag corresponding - * to read access (1), write access (2), or both (3); the magic value 0 clears the watchpoint; - * reply is <code>ok</code></li> - * <li><code>var N M</code> - return the contents of variable <code>M</code> in the control - * stack frame <code>N</code> (stack frames are indexed from 0, 0 being the oldest); - * reply is variable value</li> - * </ul> - * </p> - * - * @param request command - * @return reply - * @throws DebugException if the request fails - */ - public String sendRequest(String request) throws DebugException { - return getPDADebugTarget().sendRequest(request); - } + * Sends a request to the PDA interpreter, waits for and returns the reply. + * + * @param request command + * @return reply + * @throws DebugException if the request fails + * + * @see org.eclipse.debug.examples.core.protocol.PDATerminateCommand + * @see org.eclipse.debug.examples.core.protocol.PDAVMSuspendCommand + * @see org.eclipse.debug.examples.core.protocol.PDAVMResumeCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDASuspendCommand + * @see org.eclipse.debug.examples.core.protocol.PDAResumeCommand + * @see org.eclipse.debug.examples.core.protocol.PDAStepCommand + * @see org.eclipse.debug.examples.core.protocol.PDADropFrameCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDASetBreakpointCommand + * @see org.eclipse.debug.examples.core.protocol.PDAClearBreakpointCommand + * @see org.eclipse.debug.examples.core.protocol.PDAWatchCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDADataCommand + * @see org.eclipse.debug.examples.core.protocol.PDASetDataCommand + * @see org.eclipse.debug.examples.core.protocol.PDAPopDataCommand + * @see org.eclipse.debug.examples.core.protocol.PDAPushDataCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDAEvalCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDAEventStopCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDAStackCommand + * @see org.eclipse.debug.examples.core.protocol.PDAStackDepthCommand + * @see org.eclipse.debug.examples.core.protocol.PDAFrameCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDASetVarCommand + * @see org.eclipse.debug.examples.core.protocol.PDAVarCommand + * @see org.eclipse.debug.examples.core.protocol.PDAChildrenCommand + * + * @see org.eclipse.debug.examples.core.protocol.PDAGroupsCommand + * @see org.eclipse.debug.examples.core.protocol.PDARegistersCommand + * + * @since 3.5 + */ + public PDACommandResult sendCommand(PDACommand command) throws DebugException { + return getPDADebugTarget().sendCommand(command); + } /** * Returns the debug target as a PDA target. diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java index 6df9fad76..44437af5d 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDADebugTarget.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; @@ -17,7 +18,11 @@ import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.net.UnknownHostException; -import java.util.Vector; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IMarkerDelta; @@ -29,6 +34,7 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.IBreakpointManager; import org.eclipse.debug.core.IBreakpointManagerListener; @@ -38,10 +44,22 @@ import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.IThread; -import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.examples.core.pda.DebugCorePlugin; import org.eclipse.debug.examples.core.pda.breakpoints.PDALineBreakpoint; import org.eclipse.debug.examples.core.pda.breakpoints.PDARunToLineBreakpoint; +import org.eclipse.debug.examples.core.protocol.PDACommand; +import org.eclipse.debug.examples.core.protocol.PDACommandResult; +import org.eclipse.debug.examples.core.protocol.PDAEvent; +import org.eclipse.debug.examples.core.protocol.PDAEventStopCommand; +import org.eclipse.debug.examples.core.protocol.PDAExitedEvent; +import org.eclipse.debug.examples.core.protocol.PDAStartedEvent; +import org.eclipse.debug.examples.core.protocol.PDATerminateCommand; +import org.eclipse.debug.examples.core.protocol.PDAVMResumeCommand; +import org.eclipse.debug.examples.core.protocol.PDAVMResumedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMStartedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMSuspendCommand; +import org.eclipse.debug.examples.core.protocol.PDAVMSuspendedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMTerminatedEvent; /** @@ -62,17 +80,20 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr private Socket fEventSocket; private BufferedReader fEventReader; + // suspended state + private boolean fVMSuspended = false; + // terminated state private boolean fTerminated = false; // threads - private IThread[] fThreads; - private PDAThread fThread; + private Map fThreads = Collections.synchronizedMap(new LinkedHashMap()); // event dispatch job private EventDispatchJob fEventDispatch; + // event listeners - private Vector fEventListeners = new Vector(); + private List fEventListeners = Collections.synchronizedList(new ArrayList()); /** * Listens to events from the PDA VM and fires corresponding @@ -89,18 +110,28 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) */ protected IStatus run(IProgressMonitor monitor) { - String event = ""; - while (!isTerminated() && event != null) { + String message = ""; + while (!isTerminated() && message != null) { try { - event = fEventReader.readLine(); - if (event != null) { + message = fEventReader.readLine(); + System.out.println(message); + if (message != null) { + PDAEvent event = null; + try { + event = PDAEvent.parseEvent(message); + } + catch (IllegalArgumentException e) { + DebugCorePlugin.getDefault().getLog().log( + new Status (IStatus.ERROR, "org.eclipse.debug.examples.core", "Error parsing PDA event", e)); + continue; + } Object[] listeners = fEventListeners.toArray(); for (int i = 0; i < listeners.length; i++) { ((IPDAEventListener)listeners[i]).handleEvent(event); } } } catch (IOException e) { - terminated(); + vmTerminated(); } } return Status.OK_STATUS; @@ -116,9 +147,11 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr * @param listener event listener */ public void addEventListener(IPDAEventListener listener) { - if (!fEventListeners.contains(listener)) { - fEventListeners.add(listener); - } + synchronized(fEventListeners) { + if (!fEventListeners.contains(listener)) { + fEventListeners.add(listener); + } + } } /** @@ -167,8 +200,6 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr } catch (IOException e) { requestFailed("Unable to connect to PDA VM", e); } - fThread = new PDAThread(this); - fThreads = new IThread[] {fThread}; fEventDispatch = new EventDispatchJob(); fEventDispatch.schedule(); IBreakpointManager breakpointManager = getBreakpointManager(); @@ -176,8 +207,8 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr breakpointManager.addBreakpointManagerListener(this); // initialize error hanlding to suspend on 'unimplemented instructions' // and 'no such label' errors - sendRequest("eventstop unimpinstr 1"); - sendRequest("eventstop nosuchlabel 1"); + sendCommand(new PDAEventStopCommand(PDAEventStopCommand.UNIMPINSTR, true)); + sendCommand(new PDAEventStopCommand(PDAEventStopCommand.NOSUCHLABEL, true)); } /* (non-Javadoc) @@ -190,13 +221,15 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr * @see org.eclipse.debug.core.model.IDebugTarget#getThreads() */ public IThread[] getThreads() throws DebugException { - return fThreads; + synchronized (fThreads) { + return (IThread[])fThreads.values().toArray(new IThread[fThreads.size()]); + } } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IDebugTarget#hasThreads() */ public boolean hasThreads() throws DebugException { - return true; + return fThreads.size() > 0; } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IDebugTarget#getName() @@ -253,14 +286,18 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr /* (non-Javadoc) * @see org.eclipse.debug.core.model.ITerminate#isTerminated() */ - public boolean isTerminated() { + public synchronized boolean isTerminated() { return fTerminated || getProcess().isTerminated(); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.ITerminate#terminate() */ public void terminate() throws DebugException { - getThread().terminate(); +//#ifdef ex2 +//# // TODO: Exercise 2 - send termination request to interpreter +//#else + sendCommand(new PDATerminateCommand()); +//#endif } /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#canResume() @@ -277,22 +314,24 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended() */ - public boolean isSuspended() { - return !isTerminated() && getThread().isSuspended(); + public synchronized boolean isSuspended() { + return !isTerminated() && fVMSuspended; } + /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#resume() */ public void resume() throws DebugException { - getThread().resume(); + sendCommand(new PDAVMResumeCommand()); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#suspend() */ public void suspend() throws DebugException { - getThread().suspend(); + sendCommand(new PDAVMSuspendCommand()); } + /* (non-Javadoc) * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint) */ @@ -368,7 +407,7 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr * Notification we have connected to the VM and it has started. * Resume the VM. */ - private void started() { + private void vmStarted(PDAVMStartedEvent event) { fireCreationEvent(); installDeferredBreakpoints(); try { @@ -391,10 +430,9 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr /** * Called when this debug target terminates. */ - private synchronized void terminated() { - fTerminated = true; - fThread = null; - fThreads = new IThread[0]; + private void vmTerminated() { + setTerminated(true); + fThreads.clear(); IBreakpointManager breakpointManager = getBreakpointManager(); breakpointManager.removeBreakpointListener(this); breakpointManager.removeBreakpointManagerListener(this); @@ -402,29 +440,58 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr removeEventListener(this); } - /** - * Returns the values on the data stack (top down) - * - * @return the values on the data stack (top down) - */ - public IValue[] getDataStack() throws DebugException { - String dataStack = sendRequest("data"); - if (dataStack != null && dataStack.length() > 0) { - String[] values = dataStack.split("\\|"); - IValue[] theValues = new IValue[values.length]; - for (int i = 0; i < values.length; i++) { - String value = values[values.length - i - 1]; - theValues[i] = new PDAStackValue(this, value, i); - } - return theValues; - } - return new IValue[0]; + private void vmResumed(PDAVMResumedEvent event) { + setVMSuspended(false); + fireResumeEvent(calcDetail(event.fReason)); + } + + private void vmSuspended(PDAVMSuspendedEvent event) { + setVMSuspended(true); + int detail = DebugEvent.UNSPECIFIED; + fireSuspendEvent(calcDetail(event.fReason)); + } + + private int calcDetail(String reason) { + if (reason.equals("breakpoint") || reason.equals("watch")) { + return DebugEvent.BREAKPOINT; + } else if (reason.equals("step")) { + return DebugEvent.STEP_OVER; + } else if (reason.equals("drop")) { + return DebugEvent.STEP_RETURN; + } else if (reason.equals("client")) { + return DebugEvent.CLIENT_REQUEST; + } else if (reason.equals("event")) { + return DebugEvent.BREAKPOINT; + } else { + return DebugEvent.UNSPECIFIED; + } + } + + private void started(PDAStartedEvent event) { + PDAThread newThread = new PDAThread(this, event.fThreadId); + fThreads.put(new Integer(event.fThreadId), newThread); + newThread.start(); + } + + private void exited(PDAExitedEvent event) { + PDAThread thread = (PDAThread)fThreads.remove(new Integer(event.fThreadId)); + if (thread != null) { + thread.exit(); + } + } + + private synchronized void setVMSuspended(boolean suspended) { + fVMSuspended = suspended; } + private synchronized void setTerminated(boolean terminated) { + fTerminated = terminated; + } + /* (non-Javadoc) * @see org.eclipse.debug.examples.core.pda.model.PDADebugElement#sendRequest(java.lang.String) */ - public String sendRequest(String request) throws DebugException { + private String sendRequest(String request) throws DebugException { synchronized (fRequestSocket) { fRequestWriter.println(request); fRequestWriter.flush(); @@ -438,6 +505,11 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr return null; } + public PDACommandResult sendCommand(PDACommand command) throws DebugException { + String response = sendRequest(command.getRequest()); + return command.createResult(response); + } + /** * When the breakpoint manager disables, remove all registered breakpoints * requests from the VM. When it enables, reinstall them. @@ -452,74 +524,45 @@ public class PDADebugTarget extends PDADebugElement implements IDebugTarget, IBr } } } - - /** - * Returns whether popping the data stack is currently permitted - * - * @return whether popping the data stack is currently permitted - */ - public boolean canPop() { - try { - return !isTerminated() && isSuspended() && getDataStack().length > 0; - } catch (DebugException e) { - } - return false; - } - - /** - * Pops and returns the top of the data stack - * - * @return the top value on the stack - * @throws DebugException if the stack is empty or the request fails - */ - public IValue pop() throws DebugException { - IValue[] dataStack = getDataStack(); - if (dataStack.length > 0) { - sendRequest("popdata"); - return dataStack[0]; - } - requestFailed("Empty stack", null); - return null; - } - - /** - * Returns whether pushing a value is currently supported. - * - * @return whether pushing a value is currently supported - */ - public boolean canPush() { - return !isTerminated() && isSuspended(); - } - - /** - * Pushes a value onto the stack. - * - * @param value value to push - * @throws DebugException on failure - */ - public void push(String value) throws DebugException { - sendRequest("pushdata " + value); - } /* (non-Javadoc) * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String) */ - public void handleEvent(String event) { - if (event.equals("started")) { - started(); - } else if (event.equals("terminated")) { - terminated(); - } + public void handleEvent(PDAEvent event) { + if (event instanceof PDAStartedEvent) { + started((PDAStartedEvent)event); + } else if (event instanceof PDAExitedEvent) { + exited((PDAExitedEvent)event); + } else if (event instanceof PDAVMStartedEvent) { + vmStarted((PDAVMStartedEvent)event); + } else if (event instanceof PDAVMTerminatedEvent) { + vmTerminated(); + } else if (event instanceof PDAVMSuspendedEvent) { + vmSuspended((PDAVMSuspendedEvent)event); + } else if (event instanceof PDAVMResumedEvent) { + vmResumed((PDAVMResumedEvent)event); + } } /** * Returns this debug target's single thread, or <code>null</code> * if terminated. * + * @param threadId ID of the thread to return, or <code>0</code> + * to return the first available thread * @return this debug target's single thread, or <code>null</code> * if terminated */ - public synchronized PDAThread getThread() { - return fThread; + public PDAThread getThread(int threadId) { + if (threadId > 0) { + return (PDAThread)fThreads.get(new Integer(threadId)); + } else { + synchronized(fThreads) { + if (fThreads.size() > 0) { + return (PDAThread)fThreads.values().iterator().next(); + } + } + } + return null; } } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java index a3cbe43c8..fbd1c7bb8 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackFrame.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; @@ -17,6 +18,7 @@ import org.eclipse.debug.core.model.IRegisterGroup; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IThread; import org.eclipse.debug.core.model.IVariable; +import org.eclipse.debug.examples.core.protocol.PDAFrameData; /** * PDA stack frame. @@ -37,7 +39,7 @@ public class PDAStackFrame extends PDADebugElement implements IStackFrame { * @param data frame data * @param id stack frame id (0 is the bottom of the stack) */ - public PDAStackFrame(PDAThread thread, String data, int id) { + public PDAStackFrame(PDAThread thread, PDAFrameData data, int id) { super(thread.getPDADebugTarget()); fId = id; fThread = thread; @@ -49,17 +51,13 @@ public class PDAStackFrame extends PDADebugElement implements IStackFrame { * * @param data */ - private void init(String data) { - String[] strings = data.split("\\|"); - String fileName = strings[0]; - fFileName = (new Path(fileName)).lastSegment(); - String pc = strings[1]; - fPC = Integer.parseInt(pc) + 1; - fName = strings[2]; - int numVars = strings.length - 3; - IVariable[] vars = new IVariable[numVars]; - for (int i = 0; i < numVars; i++) { - vars[i] = new PDAVariable(this, strings[i + 3]); + private void init(PDAFrameData data) { + fFileName = data.fFilePath.lastSegment(); + fPC = data.fPC + 1; + fName = data.fFunction; + IVariable[] vars = new IVariable[data.fVariables.length]; + for (int i = 0; i < data.fVariables.length; i++) { + vars[i] = new PDAVariable(this, data.fVariables[i]); } fThread.setVariables(this, vars); } @@ -247,5 +245,15 @@ public class PDAStackFrame extends PDADebugElement implements IStackFrame { return fId; } + /** + * Returns the stack frame's thread's unique identifier + * + * @return this stack frame's thread's unique identifier + * + * @since 3.5 + */ + protected int getThreadIdentifier() { + return fThread.getIdentifier(); + } } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java index 2f13211f4..a7909d485 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAStackValue.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,15 +8,22 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IValue; +import org.eclipse.debug.core.model.IVariable; + /** * A value on the data stack */ -public class PDAStackValue extends PDAValue { - - private int fIndex; +public class PDAStackValue extends PDADebugElement implements IValue { + + final private PDAThread fThread; + final private String fValue; + final private int fIndex; /** * Constructs a value that appears on the data stack @@ -25,17 +32,55 @@ public class PDAStackValue extends PDAValue { * @param value value on the stack * @param index index on the stack */ - public PDAStackValue(PDADebugTarget target, String value, int index) { - super(target, value); + public PDAStackValue(PDAThread thread, String value, int index) { + super(thread.getDebugTarget()); + fThread = thread; + fValue = value; fIndex = index; } + public PDAThread getThread() { + return fThread; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IValue#getValueString() + */ + public String getValueString() throws DebugException { + return fValue; + } + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IValue#isAllocated() + */ + public boolean isAllocated() throws DebugException { + return true; + } + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IValue#getVariables() + */ + public IVariable[] getVariables() throws DebugException { + return new IVariable[0]; + } + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IValue#hasVariables() + */ + public boolean hasVariables() throws DebugException { + return false; + } + /* (non-Javadoc) + * @see org.eclipse.debug.core.model.IValue#getReferenceTypeName() + */ + public String getReferenceTypeName() throws DebugException { + return null; + } /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object obj) { - return super.equals(obj) && ((PDAStackValue)obj).fIndex == fIndex; + return obj instanceof PDAStackValue && + ((PDAStackValue)obj).fValue.equals(fValue) && + ((PDAStackValue)obj).fIndex == fIndex; } /* * (non-Javadoc) diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java index 6a4102ac3..e9dfd9bea 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAThread.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,9 +8,11 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -19,13 +21,37 @@ import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IThread; +import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; +import org.eclipse.debug.examples.core.protocol.PDADataCommand; +import org.eclipse.debug.examples.core.protocol.PDADropFrameCommand; +import org.eclipse.debug.examples.core.protocol.PDAEvent; +import org.eclipse.debug.examples.core.protocol.PDAListResult; +import org.eclipse.debug.examples.core.protocol.PDANoSuchLabelEvent; +import org.eclipse.debug.examples.core.protocol.PDAPopDataCommand; +import org.eclipse.debug.examples.core.protocol.PDAPushDataCommand; +import org.eclipse.debug.examples.core.protocol.PDAResumeCommand; +import org.eclipse.debug.examples.core.protocol.PDAResumedEvent; +import org.eclipse.debug.examples.core.protocol.PDARunControlEvent; +import org.eclipse.debug.examples.core.protocol.PDAStackCommand; +import org.eclipse.debug.examples.core.protocol.PDAStackCommandResult; +import org.eclipse.debug.examples.core.protocol.PDAStepCommand; +import org.eclipse.debug.examples.core.protocol.PDASuspendCommand; +import org.eclipse.debug.examples.core.protocol.PDASuspendedEvent; +import org.eclipse.debug.examples.core.protocol.PDAUnimplementedInstructionEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMResumedEvent; +import org.eclipse.debug.examples.core.protocol.PDAVMSuspendedEvent; /** * A PDA thread. A PDA VM is single threaded. */ public class PDAThread extends PDADebugElement implements IThread, IPDAEventListener { + /** + * ID of this thread as reported by PDA. + */ + private final int fThreadId; + /** * Breakpoint this thread is suspended at or <code>null</code> * if none. @@ -38,7 +64,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList private boolean fStepping = false; /** - * Wether this thread is suspended + * Whether this thread is suspended */ private boolean fSuspended = false; @@ -50,16 +76,36 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList /** * Table mapping stack frames to current variables */ - private Map fVariables = new HashMap(); + private Map fVariables = Collections.synchronizedMap(new HashMap()); /** * Constructs a new thread for the given target * * @param target VM */ - public PDAThread(PDADebugTarget target) { + public PDAThread(PDADebugTarget target, int threadId) { super(target); - getPDADebugTarget().addEventListener(this); + fThreadId = threadId; + } + + /** + * Called by the debug target after the thread is created. + * + * @since 3.5 + */ + void start() { + fireCreationEvent(); + getPDADebugTarget().addEventListener(this); + } + + /** + * Called by the debug target before the thread is removed. + * + * @since 3.5 + */ + void exit() { + getPDADebugTarget().removeEventListener(this); + fireTerminateEvent(); } /* (non-Javadoc) @@ -67,16 +113,12 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList */ public IStackFrame[] getStackFrames() throws DebugException { if (isSuspended()) { - String framesData = sendRequest("stack"); - if (framesData != null) { - String[] frames = framesData.split("#"); - IStackFrame[] theFrames = new IStackFrame[frames.length]; - for (int i = 0; i < frames.length; i++) { - String data = frames[i]; - theFrames[frames.length - i - 1] = new PDAStackFrame(this, data, i); - } - return theFrames; + PDAStackCommandResult result = (PDAStackCommandResult)sendCommand(new PDAStackCommand(fThreadId)); + IStackFrame[] frames = new IStackFrame[result.fFrames.length]; + for (int i = 0; i < result.fFrames.length; i++) { + frames[frames.length - i - 1] = new PDAStackFrame(this, result.fFrames[i], i); } + return frames; } return new IStackFrame[0]; } @@ -109,10 +151,11 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList public String getName() { return "Main thread"; } + /* (non-Javadoc) * @see org.eclipse.debug.core.model.IThread#getBreakpoints() */ - public IBreakpoint[] getBreakpoints() { + public synchronized IBreakpoint[] getBreakpoints() { if (fBreakpoint == null) { return new IBreakpoint[0]; } @@ -124,7 +167,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * * @param breakpoint breakpoint */ - public void suspendedBy(IBreakpoint breakpoint) { + public synchronized void suspendedBy(IBreakpoint breakpoint) { fBreakpoint = breakpoint; suspended(DebugEvent.BREAKPOINT); } @@ -133,7 +176,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * @see org.eclipse.debug.core.model.ISuspendResume#canResume() */ public boolean canResume() { - return isSuspended(); + return isSuspended() && !getDebugTarget().isSuspended(); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend() @@ -145,7 +188,15 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended() */ public boolean isSuspended() { - return fSuspended && !isTerminated(); + if (getDebugTarget().isTerminated()) { + return false; + } + if (getDebugTarget().isSuspended()) { + return true; + } + synchronized (this) { + return fSuspended; + } } /* (non-Javadoc) * @see org.eclipse.debug.core.model.ISuspendResume#resume() @@ -154,7 +205,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList //#ifdef ex2 //# // TODO: Exercise 2 - send resume request to interpreter //#else - sendRequest("resume"); + sendCommand(new PDAResumeCommand(fThreadId)); //#endif } /* (non-Javadoc) @@ -164,7 +215,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList //#ifdef ex2 //# // TODO: Exercise 2 - send suspend request to interpreter //#else - sendRequest("suspend"); + sendCommand(new PDASuspendCommand(fThreadId)); //#endif } /* (non-Javadoc) @@ -200,7 +251,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * @see org.eclipse.debug.core.model.IStep#stepOver() */ public void stepOver() throws DebugException { - sendRequest("step"); + sendCommand(new PDAStepCommand(fThreadId)); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IStep#stepReturn() @@ -223,11 +274,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * @see org.eclipse.debug.core.model.ITerminate#terminate() */ public void terminate() throws DebugException { - //#ifdef ex2 -//# // TODO: Exercise 2 - send termination request to interpreter - //#else - sendRequest("exit"); - //#endif + getDebugTarget().terminate(); } /** @@ -235,7 +282,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * * @param stepping whether stepping */ - private void setStepping(boolean stepping) { + private synchronized void setStepping(boolean stepping) { fStepping = stepping; } @@ -244,7 +291,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * * @param suspended whether suspended */ - private void setSuspended(boolean suspended) { + private synchronized void setSuspended(boolean suspended) { fSuspended = suspended; } @@ -254,15 +301,15 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * * @param event one of 'unimpinstr' or 'nosuchlabel' or <code>null</code> */ - private void setError(String event) { + private synchronized void setError(String event) { fErrorEvent = event; } /** - * Returns the most revent error event encountered since the last + * Returns the most recent error event encountered since the last * suspend, or <code>null</code> if none. * - * @return the most revent error event encountered since the last + * @return the most recent error event encountered since the last * suspend, or <code>null</code> if none */ public Object getError() { @@ -272,63 +319,65 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList /* (non-Javadoc) * @see org.eclipse.debug.examples.core.pda.model.IPDAEventListener#handleEvent(java.lang.String) */ - public void handleEvent(String event) { - // clear previous state - fBreakpoint = null; - setStepping(false); - - // handle events - if (event.startsWith("resumed")) { - setSuspended(false); - if (event.endsWith("step")) { - setStepping(true); - resumed(DebugEvent.STEP_OVER); - //#ifdef ex2 -//# } -//# // TODO: Exercise 2 - handle/fire "client" resume event - //#else - } else if (event.endsWith("client")) { - resumed(DebugEvent.CLIENT_REQUEST); - } - //#endif - //#ifdef ex5 -//# // TODO: Exercise 5 - handle start of drop event - //#else - else if (event.endsWith("drop")) { - resumed(DebugEvent.STEP_RETURN); - } - //#endif - } else if (event.startsWith("suspended")) { - setSuspended(true); - //#ifdef ex2 -//# // TODO: Exercise 2 - handle/fire "client" suspend event -//# if (event.endsWith("step")) { -//# suspended(DebugEvent.STEP_END); -//# } else if (event.startsWith("suspended event") && getError() != null) { -//# exceptionHit(); -//# } - //#else - if (event.endsWith("client")) { - suspended(DebugEvent.CLIENT_REQUEST); - } else if (event.endsWith("step")) { - suspended(DebugEvent.STEP_END); - } else if (event.startsWith("suspended event") && getError() != null) { - exceptionHit(); - } - //#endif - //#ifdef ex5 -//# // TODO: Exercise 5 - handle end of drop event - //#else - else if (event.endsWith("drop")) { - suspended(DebugEvent.STEP_END); - } - //#endif - } else if (event.equals("started")) { - fireCreationEvent(); - } else { - setError(event); - } - + public void handleEvent(PDAEvent _event) { + if (_event instanceof PDARunControlEvent && fThreadId == ((PDARunControlEvent)_event).fThreadId) { + PDARunControlEvent event = (PDARunControlEvent)_event; + // clear previous state + fBreakpoint = null; + setStepping(false); + + // handle events + if (event instanceof PDAResumedEvent || event instanceof PDAVMResumedEvent) { + setSuspended(false); + if ("step".equals(event.fReason)) { + setStepping(true); + resumed(DebugEvent.STEP_OVER); + //#ifdef ex2 + //# } + //# // TODO: Exercise 2 - handle/fire "client" resume event + //#else + } else if ("client".equals(event.fReason)) { + resumed(DebugEvent.CLIENT_REQUEST); + } + //#endif + //#ifdef ex5 + //# // TODO: Exercise 5 - handle start of drop event + //#else + else if ("drop".equals(event.fReason)) { + resumed(DebugEvent.STEP_RETURN); + } + //#endif + } else if (event instanceof PDASuspendedEvent || event instanceof PDAVMSuspendedEvent) { + setSuspended(true); + //#ifdef ex2 + //# // TODO: Exercise 2 - handle/fire "client" suspend event + //# if (event.endsWith("step")) { + //# suspended(DebugEvent.STEP_END); + //# } else if (event.startsWith("suspended event") && getError() != null) { + //# exceptionHit(); + //# } + //#else + if ("client".equals(event.fReason)) { + suspended(DebugEvent.CLIENT_REQUEST); + } else if ("step".equals(event.fReason)) { + suspended(DebugEvent.STEP_END); + } else if ("event".equals(event.fReason) && getError() != null) { + exceptionHit(); + } + //#endif + //#ifdef ex5 + //# // TODO: Exercise 5 - handle end of drop event + //#else + else if ("drop".equals(event.fReason)) { + suspended(DebugEvent.STEP_END); + } + //#endif + } else if (_event instanceof PDANoSuchLabelEvent || + _event instanceof PDAUnimplementedInstructionEvent) + { + setError(event.fMessage); + } + } } /** @@ -341,9 +390,7 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList */ private void resumed(int detail) { setError(null); - synchronized (fVariables) { - fVariables.clear(); - } + fVariables.clear(); fireResumeEvent(detail); } @@ -398,12 +445,14 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * Pops the top frame off the callstack. * * @throws DebugException + * + * @since 3.5 */ - public void pop() throws DebugException { + public void popFrame() throws DebugException { //#ifdef ex5 //# // TODO: Exercise 5 - send drop request //#else - sendRequest("drop"); + sendCommand(new PDADropFrameCommand(fThreadId)); //#endif } @@ -411,8 +460,10 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList * Returns whether this thread can pop the top stack frame. * * @return whether this thread can pop the top stack frame + * + * @since 3.5 */ - public boolean canPop() { + public boolean canPopFrame() { //#ifdef ex5 //# // TODO: Exercise 5 - allow pop if there is more than 1 frame on the stack //#else @@ -423,4 +474,90 @@ public class PDAThread extends PDADebugElement implements IThread, IPDAEventList //#endif return false; } + + /** + * Returns the values on the data stack (top down) + * + * @return the values on the data stack (top down) + * + * @since 3.5 + */ + public IValue[] getDataStack() throws DebugException { + PDAListResult result = (PDAListResult)sendCommand(new PDADataCommand(fThreadId)); + if (result.fValues.length > 0) { + IValue[] values = new IValue[result.fValues.length]; + for (int i = 0; i < result.fValues.length; i++) { + values[values.length - i - 1] = new PDAStackValue(this, result.fValues[i], i); + } + return values; + } + return new IValue[0]; + } + + /** + * Returns whether popping the data stack is currently permitted + * + * @return whether popping the data stack is currently permitted + * + * @since 3.5 + */ + public boolean canPopData() { + try { + return !isTerminated() && isSuspended() && getDataStack().length > 0; + } catch (DebugException e) { + } + return false; + } + + /** + * Pops and returns the top of the data stack + * + * @return the top value on the stack + * @throws DebugException if the stack is empty or the request fails + * + * @since 3.5 + */ + public IValue popData() throws DebugException { + IValue[] dataStack = getDataStack(); + if (dataStack.length > 0) { + sendCommand(new PDAPopDataCommand(fThreadId)); + return dataStack[0]; + } + requestFailed("Empty stack", null); + return null; + } + + /** + * Returns whether pushing a value is currently supported. + * + * @return whether pushing a value is currently supported + * + * @since 3.5 + */ + public boolean canPushData() { + return !isTerminated() && isSuspended(); + } + + /** + * Pushes a value onto the stack. + * + * @param value value to push + * @throws DebugException on failure + * + * @since 3.5 + */ + public void pushData(String value) throws DebugException { + sendCommand(new PDAPushDataCommand(fThreadId, value)); + } + + /** + * Returns this thread's unique identifier + * + * @return this thread's unique identifier + * + * @since 3.5 + */ + public int getIdentifier() { + return fThreadId; + } } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java index e871004af..e3f371588 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAValue.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,22 +8,27 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; +import org.eclipse.debug.examples.core.protocol.PDAChildrenCommand; +import org.eclipse.debug.examples.core.protocol.PDAListResult; /** * Value of a PDA variable. */ public class PDAValue extends PDADebugElement implements IValue { - private String fValue; + final private PDAVariable fVariable; + final private String fValue; - public PDAValue(PDADebugTarget target, String value) { - super(target); + public PDAValue(PDAVariable variable, String value) { + super(variable.getStackFrame().getPDADebugTarget()); + fVariable = variable; fValue = value; } @@ -54,12 +59,26 @@ public class PDAValue extends PDADebugElement implements IValue { * @see org.eclipse.debug.core.model.IValue#getVariables() */ public IVariable[] getVariables() throws DebugException { - return new IVariable[0]; + PDAStackFrame frame = fVariable.getStackFrame(); + PDAListResult result = (PDAListResult) sendCommand( + new PDAChildrenCommand(frame.getThreadIdentifier(), frame.getIdentifier(), fVariable.getName()) ); + + IVariable[] children = new IVariable[result.fValues.length]; + for(int i = 0; i < result.fValues.length; i++) { + children[i] = new PDAVariable(frame, result.fValues[i]); + } + return children; } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IValue#hasVariables() */ public boolean hasVariables() throws DebugException { + if (getVariables().length != 0) { + return true; + } + // Value with multiple words can be show as an array using logical + // structures. If the value has multiple words, it needs to indicate + // that it has children even if logical structures are not turned on. return fValue.split("\\W+").length > 1; } /* @@ -76,4 +95,15 @@ public class PDAValue extends PDADebugElement implements IValue { public int hashCode() { return fValue.hashCode(); } + + /** + * Returns the variable that this value was created for. + * + * @return The variable that this value was created for. + * + * @since 3.5 + */ + public PDAVariable getVariable() { + return fVariable; + } } diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java index b0ddd6433..135a173c7 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -9,6 +9,7 @@ * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation * Wind River Systems - added support for IToggleBreakpointsTargetFactory + * Pawel Piech (Wind River) - ported PDA Virtual Machine to Java (Bug 261400) *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; @@ -16,6 +17,9 @@ import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; +import org.eclipse.debug.examples.core.protocol.PDACommandResult; +import org.eclipse.debug.examples.core.protocol.PDASetVarCommand; +import org.eclipse.debug.examples.core.protocol.PDAVarCommand; /** * A variable in a PDA stack frame @@ -43,8 +47,9 @@ public class PDAVariable extends PDADebugElement implements IVariable { * @see org.eclipse.debug.core.model.IVariable#getValue() */ public IValue getValue() throws DebugException { - String value = sendRequest("var " + getStackFrame().getIdentifier() + " " + getName()); - return new PDAValue(this.getPDADebugTarget(), value); + PDACommandResult result = sendCommand(new PDAVarCommand( + fFrame.getThreadIdentifier(), getStackFrame().getIdentifier(), getName())); + return new PDAValue(this, result.fResponseText); } /* (non-Javadoc) @@ -69,7 +74,8 @@ public class PDAVariable extends PDADebugElement implements IVariable { * @see org.eclipse.debug.core.model.IValueModification#setValue(java.lang.String) */ public void setValue(String expression) throws DebugException { - sendRequest("setvar " + getStackFrame().getIdentifier() + " " + getName() + " " + expression); + sendCommand(new PDASetVarCommand( + fFrame.getThreadIdentifier(), getStackFrame().getIdentifier(), getName(), expression)); fireChangeEvent(DebugEvent.CONTENT); } /* (non-Javadoc) |