Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor.java')
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor.java272
1 files changed, 272 insertions, 0 deletions
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor.java
new file mode 100644
index 00000000000..caa2f6fa7f5
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/MIRunControlEventProcessor.java
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Ericsson - Additional handling of events
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.mi.service.command;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.ICommand;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandListener;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandResult;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandToken;
+import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIProcesses;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecFinish;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecNext;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecNextInstruction;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReturn;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecStep;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecStepInstruction;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecUntil;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIFunctionFinishedEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIInferiorExitEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIInferiorSignalExitEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MILocationReachedEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIRunningEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MISignalEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MISteppingRangeEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointScopeEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointTriggerEvent;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIConst;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIExecAsyncOutput;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIOOBRecord;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIResult;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIResultRecord;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIValue;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+
+/**
+ * MI debugger output listener that listens for the parsed MI output, and
+ * generates corresponding MI events. The generated MI events are then
+ * received by other services and clients.
+ */
+public class MIRunControlEventProcessor
+ implements IEventListener, ICommandListener
+{
+ private static final String STOPPED_REASON = "stopped"; //$NON-NLS-1$
+
+ /**
+ * The connection service that this event processor is registered with.
+ */
+ private final AbstractMIControl fCommandControl;
+
+ /**
+ * Container context used as the context for the run control events generated
+ * by this processor.
+ */
+ private final ICommandControlDMContext fControlDmc;
+
+ private final DsfServicesTracker fServicesTracker;
+
+ /**
+ * Creates the event processor and registers it as listener with the debugger
+ * control.
+ * @param connection
+ * @param inferior
+ * @since 1.1
+ */
+ public MIRunControlEventProcessor(AbstractMIControl connection, ICommandControlDMContext controlDmc) {
+ fCommandControl = connection;
+ fControlDmc = controlDmc;
+ fServicesTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fCommandControl.getSession().getId());
+ connection.addEventListener(this);
+ connection.addCommandListener(this);
+ }
+
+ @Deprecated
+ public MIRunControlEventProcessor(AbstractMIControl connection, IContainerDMContext containerDmc) {
+ this(connection, DMContexts.getAncestorOfType(containerDmc, ICommandControlDMContext.class));
+
+ }
+
+ /**
+ * This processor must be disposed before the control service is un-registered.
+ */
+ public void dispose() {
+ fCommandControl.removeEventListener(this);
+ fCommandControl.removeCommandListener(this);
+ fServicesTracker.dispose();
+ }
+
+ public void eventReceived(Object output) {
+ for (MIOOBRecord oobr : ((MIOutput)output).getMIOOBRecords()) {
+ List<MIEvent<?>> events = new LinkedList<MIEvent<?>>();
+ if (oobr instanceof MIExecAsyncOutput) {
+ MIExecAsyncOutput exec = (MIExecAsyncOutput) oobr;
+ // Change of state.
+ String state = exec.getAsyncClass();
+ if ("stopped".equals(state)) { //$NON-NLS-1$
+ // Re-set the thread and stack level to -1 when stopped event is recvd.
+ // This is to synchronize the state between GDB back-end and AbstractMIControl.
+ fCommandControl.resetCurrentThreadLevel();
+ fCommandControl.resetCurrentStackLevel();
+
+ MIResult[] results = exec.getMIResults();
+ for (int i = 0; i < results.length; i++) {
+ String var = results[i].getVariable();
+ MIValue val = results[i].getMIValue();
+ if (var.equals("reason")) { //$NON-NLS-1$
+ if (val instanceof MIConst) {
+ String reason = ((MIConst) val).getString();
+ MIEvent<?> e = createEvent(reason, exec);
+ if (e != null) {
+ events.add(e);
+ continue;
+ }
+ }
+ }
+ }
+ // We were stopped for some unknown reason, for example
+ // GDB for temporary breakpoints will not send the
+ // "reason" ??? still fire a stopped event.
+ if (events.isEmpty()) {
+ MIEvent<?> e = createEvent(STOPPED_REASON, exec);
+ if (e != null) {
+ events.add(e);
+ }
+ }
+
+ for (MIEvent<?> event : events) {
+ fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
+ }
+ }
+ }
+ }
+ }
+
+ protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec) {
+ String threadId = null;
+
+ MIResult[] results = exec.getMIResults();
+ for (int i = 0; i < results.length; i++) {
+ String var = results[i].getVariable();
+ MIValue val = results[i].getMIValue();
+
+ if (var.equals("thread-id")) { //$NON-NLS-1$
+ if (val instanceof MIConst) {
+ threadId = ((MIConst)val).getString();
+ }
+ }
+ }
+
+ IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class);
+ if (procService == null) {
+ return null;
+ }
+
+ String groupId = MIProcesses.UNIQUE_GROUP_ID;
+
+ IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, groupId);
+ IContainerDMContext processContainerDmc = procService.createContainerContext(procDmc, groupId);
+
+ IExecutionDMContext execDmc = processContainerDmc;
+ if (threadId != null) {
+ IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId);
+ execDmc = procService.createExecutionContext(processContainerDmc, threadDmc, threadId);
+ }
+
+ MIEvent<?> event = null;
+ if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$
+ event = MIBreakpointHitEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
+ } else if (
+ "watchpoint-trigger".equals(reason) //$NON-NLS-1$
+ || "read-watchpoint-trigger".equals(reason) //$NON-NLS-1$
+ || "access-watchpoint-trigger".equals(reason)) { //$NON-NLS-1$
+ event = MIWatchpointTriggerEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
+ } else if ("watchpoint-scope".equals(reason)) { //$NON-NLS-1$
+ event = MIWatchpointScopeEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
+ } else if ("end-stepping-range".equals(reason)) { //$NON-NLS-1$
+ event = MISteppingRangeEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
+ } else if ("signal-received".equals(reason)) { //$NON-NLS-1$
+ event = MISignalEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
+ } else if ("location-reached".equals(reason)) { //$NON-NLS-1$
+ event = MILocationReachedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
+ } else if ("function-finished".equals(reason)) { //$NON-NLS-1$
+ event = MIFunctionFinishedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
+ } else if ("exited-normally".equals(reason) || "exited".equals(reason)) { //$NON-NLS-1$ //$NON-NLS-2$
+ event = MIInferiorExitEvent.parse(fCommandControl.getContext(), exec.getToken(), exec.getMIResults());
+ } else if ("exited-signalled".equals(reason)) { //$NON-NLS-1$
+ event = MIInferiorSignalExitEvent.parse(fCommandControl.getContext(), exec.getToken(), exec.getMIResults());
+ } else if (STOPPED_REASON.equals(reason)) {
+ event = MIStoppedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
+ }
+ return event;
+ }
+
+ public void commandQueued(ICommandToken token) {
+ // Do nothing.
+ }
+
+ public void commandSent(ICommandToken token) {
+ // Do nothing.
+ }
+
+ public void commandRemoved(ICommandToken token) {
+ // Do nothing.
+ }
+
+ public void commandDone(ICommandToken token, ICommandResult result) {
+ ICommand<?> cmd = token.getCommand();
+ MIInfo cmdResult = (MIInfo) result ;
+ MIOutput output = cmdResult.getMIOutput();
+ MIResultRecord rr = output.getMIResultRecord();
+ if (rr != null) {
+ int id = rr.getToken();
+ // Check if the state changed.
+ String state = rr.getResultClass();
+ if ("running".equals(state)) { //$NON-NLS-1$
+ int type = 0;
+ // Check the type of command
+ // if it was a step instruction set state stepping
+
+ if (cmd instanceof MIExecNext) { type = MIRunningEvent.NEXT; }
+ else if (cmd instanceof MIExecNextInstruction) { type = MIRunningEvent.NEXTI; }
+ else if (cmd instanceof MIExecStep) { type = MIRunningEvent.STEP; }
+ else if (cmd instanceof MIExecStepInstruction) { type = MIRunningEvent.STEPI; }
+ else if (cmd instanceof MIExecUntil) { type = MIRunningEvent.UNTIL; }
+ else if (cmd instanceof MIExecFinish) { type = MIRunningEvent.FINISH; }
+ else if (cmd instanceof MIExecReturn) { type = MIRunningEvent.RETURN; }
+ else if (cmd instanceof MIExecContinue) { type = MIRunningEvent.CONTINUE; }
+ else { type = MIRunningEvent.CONTINUE; }
+
+ IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class);
+ if (procService != null) {
+ String groupId = MIProcesses.UNIQUE_GROUP_ID;
+ IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, groupId);
+ IContainerDMContext processContainerDmc = procService.createContainerContext(procDmc, groupId);
+
+ fCommandControl.getSession().dispatchEvent(
+ new MIRunningEvent(processContainerDmc, id, type), fCommandControl.getProperties());
+ }
+ } else if ("exit".equals(state)) { //$NON-NLS-1$
+ // No need to do anything, terminate() will.
+ // Send exited?
+ } else if ("connected".equals(state)) { //$NON-NLS-1$
+ } else if ("error".equals(state)) { //$NON-NLS-1$
+ }
+ }
+ }
+}

Back to the top