mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 335528: [multi-process] Move startOrRestart to the Processes service
This commit is contained in:
parent
6a815d839a
commit
4881bba10c
11 changed files with 666 additions and 435 deletions
|
@ -19,6 +19,7 @@ import java.nio.charset.CharsetDecoder;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
|
@ -673,4 +674,26 @@ public class CDebugUtils {
|
|||
private static void throwCoreException(String msg, Exception innerException, int code) throws CoreException {
|
||||
throw new CoreException(new Status(IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), code, msg, innerException));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method to fetch an attribute from a Map that has keys of type String. The defaultValue
|
||||
* parameter will be returned if the map does not contain the key, or if the matching value is not
|
||||
* of the correct type.
|
||||
*
|
||||
* @param <V> The type of the value we are looking for. Specified by the type of defaultValue.
|
||||
* @param attributes The map with keys of type String, and values of any type. Cannot be null.
|
||||
* @param key They key for which we want the value.
|
||||
* @param defaultValue The default value to return if the key is not found in the map, or if the value found
|
||||
* is not of the same type as defaultValue. Cannot be null.
|
||||
* @return The value, if found and of the same type as defaultValue. Else, returns defaultValue.
|
||||
* @since 7.1
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <V> V getAttribute(Map<String, ?> attributes, String key, V defaultValue) {
|
||||
Object value = attributes.get(key);
|
||||
if (defaultValue.getClass().isInstance(value)) {
|
||||
return (V)value;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2010 Wind River Systems and others.
|
||||
* Copyright (c) 2006, 2011 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
|
||||
|
@ -11,12 +11,19 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.gdb.internal.ui.actions;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.ui.actions.DsfCommandRunnable;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.GDBProcess;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
|
@ -51,19 +58,29 @@ public class GdbRestartCommand implements IRestartHandler {
|
|||
request.done();
|
||||
return;
|
||||
}
|
||||
|
||||
fExecutor.submit(new DsfRunnable() {
|
||||
public void run() {
|
||||
IGDBControl gdbControl = fTracker.getService(IGDBControl.class);
|
||||
if (gdbControl != null) {
|
||||
request.setEnabled(gdbControl.canRestart());
|
||||
} else {
|
||||
request.setEnabled(false);
|
||||
}
|
||||
request.done();
|
||||
|
||||
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
|
||||
@Override public void doExecute() {
|
||||
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(getContext(), IContainerDMContext.class);
|
||||
IGDBProcesses procService = fTracker.getService(IGDBProcesses.class);
|
||||
|
||||
if (procService != null) {
|
||||
procService.canRestart(
|
||||
containerDmc,
|
||||
new DataRequestMonitor<Boolean>(fExecutor, null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
request.setEnabled(isSuccess() && getData());
|
||||
request.done();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
request.setEnabled(false);
|
||||
request.done();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class UpdateLaunchJob extends Job {
|
||||
IDebugCommandRequest fRequest;
|
||||
|
@ -106,20 +123,29 @@ public class GdbRestartCommand implements IRestartHandler {
|
|||
|
||||
// Now that we have added the new inferior to the launch,
|
||||
// which creates its console, we can perform the restart safely.
|
||||
fExecutor.submit(new DsfRunnable() {
|
||||
public void run() {
|
||||
final IGDBControl gdbControl = fTracker.getService(IGDBControl.class);
|
||||
if (gdbControl != null) {
|
||||
gdbControl.restart(fLaunch, new RequestMonitor(fExecutor, null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
fRequest.done();
|
||||
};
|
||||
});
|
||||
} else {
|
||||
fRequest.done();
|
||||
}
|
||||
}
|
||||
fExecutor.submit(new DsfCommandRunnable(fTracker, fRequest.getElements()[0], fRequest) {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override public void doExecute() {
|
||||
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(getContext(), IContainerDMContext.class);
|
||||
IGDBProcesses procService = fTracker.getService(IGDBProcesses.class);
|
||||
|
||||
if (procService != null) {
|
||||
Map<String, Object> attributes = null;
|
||||
try {
|
||||
attributes = fLaunch.getLaunchConfiguration().getAttributes();
|
||||
} catch (CoreException e) {}
|
||||
|
||||
procService.restart(containerDmc, attributes,
|
||||
new RequestMonitor(fExecutor, null) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
fRequest.done();
|
||||
};
|
||||
});
|
||||
} else {
|
||||
fRequest.done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Status.OK_STATUS;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
package org.eclipse.cdt.dsf.gdb.launching;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||
|
@ -26,12 +27,14 @@ import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
|||
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.actions.IConnect;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||
|
@ -39,6 +42,7 @@ import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
|||
import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
|
@ -682,10 +686,21 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
* Start executing the program.
|
||||
* @since 4.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Execute
|
||||
public void stepStartExecution(final RequestMonitor requestMonitor) {
|
||||
if (fSessionType != SessionType.CORE) {
|
||||
fCommandControl.start(fLaunch, requestMonitor);
|
||||
Map<String, Object> attributes = null;
|
||||
try {
|
||||
attributes = fLaunch.getLaunchConfiguration().getAttributes();
|
||||
} catch (CoreException e) {}
|
||||
|
||||
IGDBProcesses procService = fTracker.getService(IGDBProcesses.class);
|
||||
IContainerDMContext containerDmc = procService.createContainerContextFromGroupId(fCommandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID);
|
||||
|
||||
// For now, call restart since it does the same as start
|
||||
// but this is just temporary until procService.debugNewProcess is ready
|
||||
procService.restart(containerDmc, attributes, requestMonitor);
|
||||
} else {
|
||||
requestMonitor.done();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008, 2010 Ericsson and others.
|
||||
* Copyright (c) 2008, 2011 Ericsson 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
|
||||
|
@ -17,23 +17,32 @@ import java.util.Map;
|
|||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.IProcessInfo;
|
||||
import org.eclipse.cdt.core.IProcessList;
|
||||
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
|
@ -42,7 +51,7 @@ import org.eclipse.core.runtime.Status;
|
|||
import org.osgi.framework.BundleContext;
|
||||
|
||||
|
||||
public class GDBProcesses extends MIProcesses {
|
||||
public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
||||
|
||||
private class GDBContainerDMC extends MIContainerDMC
|
||||
implements IMemoryDMContext
|
||||
|
@ -53,6 +62,8 @@ public class GDBProcesses extends MIProcesses {
|
|||
}
|
||||
|
||||
private IGDBControl fGdb;
|
||||
private IGDBBackend fBackend;
|
||||
private CommandFactory fCommandFactory;
|
||||
|
||||
// A map of pid to names. It is filled when we get all the
|
||||
// processes that are running
|
||||
|
@ -83,10 +94,13 @@ public class GDBProcesses extends MIProcesses {
|
|||
private void doInitialize(RequestMonitor requestMonitor) {
|
||||
|
||||
fGdb = getServicesTracker().getService(IGDBControl.class);
|
||||
|
||||
fBackend = getServicesTracker().getService(IGDBBackend.class);
|
||||
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
|
||||
|
||||
// Register this service.
|
||||
register(new String[] { IProcesses.class.getName(),
|
||||
IMIProcesses.class.getName(),
|
||||
IGDBProcesses.class.getName(),
|
||||
MIProcesses.class.getName(),
|
||||
GDBProcesses.class.getName() },
|
||||
new Hashtable<String, String>());
|
||||
|
@ -148,8 +162,7 @@ public class GDBProcesses extends MIProcesses {
|
|||
if (inferior != null) {
|
||||
String inferiorPidStr = inferior.getPid();
|
||||
if (inferiorPidStr != null && Integer.parseInt(inferiorPidStr) == pid) {
|
||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
||||
name = backend.getProgramPath().lastSegment();
|
||||
name = fBackend.getProgramPath().lastSegment();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -160,8 +173,7 @@ public class GDBProcesses extends MIProcesses {
|
|||
// Until bug 305385 is fixed, the above code will not work, so we assume we
|
||||
// are looking for our own process
|
||||
// assert false : "Don't have entry for process ID: " + pid; //$NON-NLS-1$
|
||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
||||
name = backend.getProgramPath().lastSegment();
|
||||
name = fBackend.getProgramPath().lastSegment();
|
||||
|
||||
}
|
||||
|
||||
|
@ -248,8 +260,7 @@ public class GDBProcesses extends MIProcesses {
|
|||
@Override
|
||||
public void getRunningProcesses(IDMContext dmc, final DataRequestMonitor<IProcessDMContext[]> rm) {
|
||||
final ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
|
||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
||||
if (backend.getSessionType() == SessionType.LOCAL) {
|
||||
if (fBackend.getSessionType() == SessionType.LOCAL) {
|
||||
IProcessList list = null;
|
||||
try {
|
||||
list = CCorePlugin.getDefault().getProcessList();
|
||||
|
@ -296,6 +307,113 @@ public class GDBProcesses extends MIProcesses {
|
|||
}
|
||||
}
|
||||
|
||||
/** @since 4.0 */
|
||||
public IMIExecutionDMContext[] getExecutionContexts(IMIContainerDMContext containerDmc) {
|
||||
assert false; // This is not being used before GDB 7.0
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @since 4.0 */
|
||||
public void canRestart(IContainerDMContext containerDmc, DataRequestMonitor<Boolean> rm) {
|
||||
if (fBackend.getIsAttachSession() || fBackend.getSessionType() == SessionType.CORE) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Before GDB6.8, the Linux gdbserver would restart a new
|
||||
// process when getting a -exec-run but the communication
|
||||
// with GDB had a bug and everything hung.
|
||||
// with GDB6.8 the program restarts properly one time,
|
||||
// but on a second attempt, gdbserver crashes.
|
||||
// So, lets just turn off the Restart for Remote debugging
|
||||
if (fBackend.getSessionType() == SessionType.REMOTE) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
rm.setData(true);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/** @since 4.0 */
|
||||
public void restart(IContainerDMContext containerDmc, Map<String, Object> attributes, RequestMonitor rm) {
|
||||
startOrRestart(containerDmc, attributes, true, rm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert breakpoint at entry if set, and start or restart the program.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
protected void startOrRestart(final IContainerDMContext containerDmc, Map<String, Object> attributes,
|
||||
boolean restart, final RequestMonitor requestMonitor) {
|
||||
if (fBackend.getIsAttachSession()) {
|
||||
// When attaching to a running process, we do not need to set a breakpoint or
|
||||
// start the program; it is left up to the user.
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
final DataRequestMonitor<MIInfo> execMonitor = new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
if (fBackend.getSessionType() != SessionType.REMOTE) {
|
||||
// Don't send the ContainerStarted event for a remote session because
|
||||
// it has already been done by MIRunControlEventProcessor when receiving
|
||||
// the ^connect
|
||||
getSession().dispatchEvent(new ContainerStartedDMEvent(containerDmc), getProperties());
|
||||
}
|
||||
super.handleSuccess();
|
||||
}
|
||||
};
|
||||
|
||||
final ICommand<MIInfo> execCommand;
|
||||
if (useContinueCommand()) {
|
||||
execCommand = fCommandFactory.createMIExecContinue(containerDmc);
|
||||
} else {
|
||||
execCommand = fCommandFactory.createMIExecRun(containerDmc);
|
||||
}
|
||||
|
||||
boolean stopInMain = CDebugUtils.getAttribute(attributes,
|
||||
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN,
|
||||
false);
|
||||
|
||||
if (!stopInMain) {
|
||||
// Just start the program.
|
||||
fGdb.queueCommand(execCommand, execMonitor);
|
||||
} else {
|
||||
String stopSymbol = CDebugUtils.getAttribute(attributes,
|
||||
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL,
|
||||
ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT);
|
||||
|
||||
// Insert a breakpoint at the requested stop symbol.
|
||||
IBreakpointsTargetDMContext bpTarget = DMContexts.getAncestorOfType(containerDmc, IBreakpointsTargetDMContext.class);
|
||||
fGdb.queueCommand(
|
||||
fCommandFactory.createMIBreakInsert(bpTarget, true, false, null, 0, stopSymbol, 0),
|
||||
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// After the break-insert is done, execute the -exec-run or -exec-continue command.
|
||||
fGdb.queueCommand(execCommand, execMonitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates if we should use the -exec-continue command
|
||||
* instead of the -exec-run command.
|
||||
* This method can be overridden to allow for customization.
|
||||
* @since 4.0
|
||||
*/
|
||||
protected boolean useContinueCommand() {
|
||||
// When doing remote debugging, we use -exec-continue instead of -exec-run
|
||||
// Restart does not apply to remote sessions
|
||||
return fBackend.getSessionType() == SessionType.REMOTE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.0
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008, 2010 Ericsson and others.
|
||||
* Copyright (c) 2008, 2011 Ericsson 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
|
||||
|
@ -24,6 +24,7 @@ import org.eclipse.cdt.core.CCorePlugin;
|
|||
import org.eclipse.cdt.core.IProcessInfo;
|
||||
import org.eclipse.cdt.core.IProcessList;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Immutable;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
|
||||
|
@ -981,6 +982,38 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
fCommandControl.terminate(rm);
|
||||
}
|
||||
|
||||
/** @since 4.0 */
|
||||
public void canRestart(IContainerDMContext containerDmc, DataRequestMonitor<Boolean> rm) {
|
||||
if (fBackend.getIsAttachSession() || fBackend.getSessionType() == SessionType.CORE) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Before GDB6.8, the Linux gdbserver would restart a new
|
||||
// process when getting a -exec-run but the communication
|
||||
// with GDB had a bug and everything hung.
|
||||
// with GDB6.8 the program restarts properly one time,
|
||||
// but on a second attempt, gdbserver crashes.
|
||||
// So, lets just turn off the Restart for Remote debugging
|
||||
if (fBackend.getSessionType() == SessionType.REMOTE) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
rm.setData(true);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/** @since 4.0 */
|
||||
public void restart(IContainerDMContext containerDmc, Map<String, Object> attributes, RequestMonitor rm) {
|
||||
ImmediateExecutor.getInstance().execute(
|
||||
new StartOrRestartProcessSequence_7_0(
|
||||
getExecutor(), containerDmc, attributes, true,
|
||||
new DataRequestMonitor<IContainerDMContext>(ImmediateExecutor.getInstance(), rm)));
|
||||
}
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(final MIThreadGroupCreatedEvent e) {
|
||||
IProcessDMContext procDmc = e.getDMContext();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008, 2010 Ericsson and others.
|
||||
* Copyright (c) 2008, 2011 Ericsson 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
|
||||
|
@ -11,6 +11,11 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.gdb.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||
|
@ -50,5 +55,26 @@ public interface IGDBProcesses extends IMIProcesses {
|
|||
* @param containerDmc The container for which we want to get the execution contexts
|
||||
*/
|
||||
IMIExecutionDMContext[] getExecutionContexts(IMIContainerDMContext containerDmc);
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the specified process can be restarted.
|
||||
*
|
||||
* @param containerDmc The process that should be restarted
|
||||
* @param rm The requestMonitor that returns if a restart is allowed on the specified process.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
void canRestart(IContainerDMContext containerDmc, DataRequestMonitor<Boolean> rm);
|
||||
|
||||
/**
|
||||
* Request that the specified process be restarted.
|
||||
*
|
||||
* @param containerDmc The process that should be restarted
|
||||
* @param attributes Different attributes that affect the restart operation. This is
|
||||
* usually the launch configuration attributes
|
||||
* @param rm The requetMonitor that indicates that the restart request has been completed.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
void restart(IContainerDMContext containerDmc, Map<String, Object> attributes, RequestMonitor rm);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,354 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Ericsson 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:
|
||||
* Ericsson - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.gdb.service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.ReflectionSequence;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
||||
/**
|
||||
* This class causes a process to start (run for the first time), or to
|
||||
* be restarted. The complexity is due to the handling of reverse debugging,
|
||||
* which this class transparently enables if necessary.
|
||||
*
|
||||
* This sequence is used for GDB >= 7.0 which supports reverse debugging.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public class StartOrRestartProcessSequence_7_0 extends ReflectionSequence {
|
||||
|
||||
private IGDBControl fCommandControl;
|
||||
private CommandFactory fCommandFactory;
|
||||
private IGDBProcesses fProcService;
|
||||
private IReverseRunControl fReverseService;
|
||||
|
||||
private DsfServicesTracker fTracker;
|
||||
|
||||
// This variable will be used to store the original container context,
|
||||
// but once the new process is start (restarted), it will contain the new
|
||||
// container context. This new container context has for parent the process
|
||||
// context, which holds the new pid.
|
||||
private IContainerDMContext fContainerDmc;
|
||||
|
||||
// If the user requested a stop_on_main, this variable will hold the breakpoint
|
||||
private MIBreakpoint fUserBreakpoint;
|
||||
// Since the stop_on_main option allows the user to set the breakpoint on any
|
||||
// symbol, we use this variable to know if the stop_on_main breakpoint was really
|
||||
// on the main() method.
|
||||
private boolean fUserBreakpointIsOnMain;
|
||||
|
||||
private boolean fReverseEnabled;
|
||||
private final Map<String, Object> fAttributes;
|
||||
|
||||
// Indicates if the sequence is being used for a restart or a start
|
||||
private final boolean fRestart;
|
||||
|
||||
// Store the dataRM so that we can fill it with the new container context, which we must return
|
||||
// Although we can access this through Sequence.getRequestMonitor(), we would loose the type-checking.
|
||||
// Therefore, doing it like this is more future-proof.
|
||||
private final DataRequestMonitor<IContainerDMContext> fDataRequestMonitor;
|
||||
|
||||
|
||||
protected IContainerDMContext getContainerContext() {
|
||||
return fContainerDmc;
|
||||
}
|
||||
|
||||
protected MIBreakpoint getUserBreakpoint() {
|
||||
return fUserBreakpoint;
|
||||
}
|
||||
|
||||
protected boolean getUserBreakpointIsOnMain() {
|
||||
return fUserBreakpointIsOnMain;
|
||||
}
|
||||
|
||||
|
||||
public StartOrRestartProcessSequence_7_0(DsfExecutor executor, IContainerDMContext containerDmc, Map<String, Object> attributes,
|
||||
boolean restart, DataRequestMonitor<IContainerDMContext> rm) {
|
||||
super(executor, rm);
|
||||
|
||||
assert executor != null;
|
||||
assert containerDmc != null;
|
||||
if (attributes == null) {
|
||||
// If no attributes are specified, simply use an empty map.
|
||||
attributes = new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
fContainerDmc = containerDmc;
|
||||
fAttributes = attributes;
|
||||
fRestart = restart;
|
||||
fDataRequestMonitor = rm;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getExecutionOrder(String group) {
|
||||
if (GROUP_TOP_LEVEL.equals(group)) {
|
||||
|
||||
DsfServicesTracker tracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fContainerDmc.getSessionId());
|
||||
IGDBBackend backend = tracker.getService(IGDBBackend.class);
|
||||
tracker.dispose();
|
||||
|
||||
if (backend.getIsAttachSession()) {
|
||||
// Restart does not apply to attach sessions, so we are only dealing with the
|
||||
// Start case.
|
||||
//
|
||||
// When attaching to a running process, we do not need to set a breakpoint or
|
||||
// start the program; it is left up to the user.
|
||||
// We only need to turn on Reverse Debugging if requested.
|
||||
|
||||
return new String[] {
|
||||
"stepInitializeBaseSequence", //$NON-NLS-1$
|
||||
"stepEnableReverse", //$NON-NLS-1$
|
||||
"stepCleanupBaseSequence", //$NON-NLS-1$
|
||||
};
|
||||
} else {
|
||||
return new String[] {
|
||||
"stepInitializeBaseSequence", //$NON-NLS-1$
|
||||
"stepInsertStopOnMainBreakpoint", //$NON-NLS-1$
|
||||
"stepSetBreakpointForReverse", //$NON-NLS-1$
|
||||
"stepRunProgram", //$NON-NLS-1$
|
||||
"stepSetReverseOff", //$NON-NLS-1$
|
||||
"stepEnableReverse", //$NON-NLS-1$
|
||||
"stepContinue", //$NON-NLS-1$
|
||||
"stepCleanupBaseSequence", //$NON-NLS-1$
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the members of the {@link StartOrRestartProcessSequence_7_0} class.
|
||||
* This step is mandatory for the rest of the sequence to complete.
|
||||
*/
|
||||
@Execute
|
||||
public void stepInitializeBaseSequence(RequestMonitor rm) {
|
||||
fTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fContainerDmc.getSessionId());
|
||||
fCommandControl = fTracker.getService(IGDBControl.class);
|
||||
fCommandFactory = fTracker.getService(IMICommandControl.class).getCommandFactory();
|
||||
fProcService = fTracker.getService(IGDBProcesses.class);
|
||||
|
||||
if (fCommandControl == null || fCommandFactory == null || fProcService == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Cannot obtain service", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
fReverseService = fTracker.getService(IReverseRunControl.class);
|
||||
if (fReverseService != null) {
|
||||
// Although the option to use reverse debugging could be on, we only check
|
||||
// it if we actually have a reverse debugging service. There is no point
|
||||
// in trying to handle reverse debugging if it is not available.
|
||||
fReverseEnabled = CDebugUtils.getAttribute(fAttributes,
|
||||
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT);
|
||||
}
|
||||
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback method for {@link #stepInitializeBaseSequence()}
|
||||
*/
|
||||
@RollBack("stepInitializeBaseSequence")
|
||||
public void rollBackInitializeBaseSequence(RequestMonitor rm) {
|
||||
if (fTracker != null) fTracker.dispose();
|
||||
fTracker = null;
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user requested a 'stopOnMain', let's set the temporary breakpoint
|
||||
* where the user specified.
|
||||
*/
|
||||
@Execute
|
||||
public void stepInsertStopOnMainBreakpoint(final RequestMonitor rm) {
|
||||
boolean userRequestedStop = CDebugUtils.getAttribute(fAttributes,
|
||||
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN,
|
||||
false);
|
||||
|
||||
if (userRequestedStop) {
|
||||
String userStopSymbol = CDebugUtils.getAttribute(fAttributes,
|
||||
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL,
|
||||
ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT);
|
||||
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMIBreakInsert((IBreakpointsTargetDMContext)fCommandControl.getContext(),
|
||||
true, false, null, 0, userStopSymbol, 0),
|
||||
new DataRequestMonitor<MIBreakInsertInfo>(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
public void handleSuccess() {
|
||||
if (getData() != null) {
|
||||
MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
|
||||
if (breakpoints.length > 0) {
|
||||
fUserBreakpoint = breakpoints[0];
|
||||
}
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If reverse debugging, set a breakpoint on main to be able to enable reverse
|
||||
* as early as possible.
|
||||
* If the user has requested a stop at the same point, we could skip this breakpoint
|
||||
* however, we have to first set it to find out! So, we just leave it.
|
||||
*/
|
||||
@Execute
|
||||
public void stepSetBreakpointForReverse(final RequestMonitor rm) {
|
||||
if (fReverseEnabled) {
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMIBreakInsert((IBreakpointsTargetDMContext)fCommandControl.getContext(),
|
||||
true, false, null, 0, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT, 0),
|
||||
new DataRequestMonitor<MIBreakInsertInfo>(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
public void handleSuccess() {
|
||||
if (getData() != null) {
|
||||
MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
|
||||
if (breakpoints.length > 0 && fUserBreakpoint != null) {
|
||||
fUserBreakpointIsOnMain = breakpoints[0].getAddress().equals(fUserBreakpoint.getAddress());
|
||||
}
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Now, run the program.
|
||||
*/
|
||||
@Execute
|
||||
public void stepRunProgram(final RequestMonitor rm) {
|
||||
ICommand<MIInfo> command;
|
||||
if (useContinueCommand()) {
|
||||
command = fCommandFactory.createMIExecContinue(fContainerDmc);
|
||||
} else {
|
||||
command = fCommandFactory.createMIExecRun(fContainerDmc);
|
||||
}
|
||||
fCommandControl.queueCommand(command, new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// Now that the process is started, the pid has been allocated
|
||||
// so we need to fetch the proper container context
|
||||
// We replace our current context which does not have the pid, with one that has the pid.
|
||||
|
||||
if (fContainerDmc instanceof IMIContainerDMContext) {
|
||||
fContainerDmc = fProcService.createContainerContextFromGroupId(fCommandControl.getContext(), ((IMIContainerDMContext)fContainerDmc).getGroupId());
|
||||
// This is the container context that this sequence is supposed to return: set the dataRm
|
||||
fDataRequestMonitor.setData(fContainerDmc);
|
||||
} else {
|
||||
assert false : "Container context was not an IMIContainerDMContext"; //$NON-NLS-1$
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of a restart, we must mark reverse debugging as disabled because
|
||||
* GDB has turned it off. We may have to turn it back on after.
|
||||
*/
|
||||
@Execute
|
||||
public void stepSetReverseOff(RequestMonitor rm) {
|
||||
if (fRestart) {
|
||||
GDBRunControl_7_0 reverseService = fTracker.getService(GDBRunControl_7_0.class);
|
||||
if (reverseService != null) {
|
||||
reverseService.setReverseModeEnabled(false);
|
||||
} else {
|
||||
assert false : "Missing reverse runControl service"; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* Since we have started the program, we can turn on reverse debugging if needed.
|
||||
* We know the program will stop since we set a breakpoint on main, to enable reverse.
|
||||
*/
|
||||
@Execute
|
||||
public void stepEnableReverse(RequestMonitor rm) {
|
||||
if (fReverseEnabled) {
|
||||
fReverseService.enableReverseMode(fCommandControl.getContext(), true, rm);
|
||||
} else {
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finally, if we are enabling reverse, and the userSymbolStop is not on main,
|
||||
* we should do a continue because we are currently stopped on main but that
|
||||
* is not what the user requested
|
||||
*/
|
||||
@Execute
|
||||
public void stepContinue(RequestMonitor rm) {
|
||||
if (fReverseEnabled && !fUserBreakpointIsOnMain) {
|
||||
fCommandControl.queueCommand(fCommandFactory.createMIExecContinue(fContainerDmc),
|
||||
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||
} else {
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup now that the sequence has been run.
|
||||
*/
|
||||
@Execute
|
||||
public void stepCleanupBaseSequence(final RequestMonitor rm) {
|
||||
fTracker.dispose();
|
||||
fTracker = null;
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates if we should use the -exec-continue command
|
||||
* instead of the -exec-run command.
|
||||
* This method can be overridden to allow for customization.
|
||||
*/
|
||||
protected boolean useContinueCommand() {
|
||||
// When doing remote debugging, we use -exec-continue instead of -exec-run
|
||||
// Restart does not apply to remote sessions
|
||||
IGDBBackend backend = fTracker.getService(IGDBBackend.class);
|
||||
if (backend == null) {
|
||||
return false;
|
||||
}
|
||||
return backend.getSessionType() == SessionType.REMOTE;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2010 Wind River Systems and others.
|
||||
* Copyright (c) 2006, 2011 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
|
||||
|
@ -24,7 +24,6 @@ import java.util.Properties;
|
|||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
|
@ -33,22 +32,16 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
|||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend.BackendStateChangedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses.ContainerExitedDMEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses.ContainerStartedDMEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.AbstractMIControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CLIEventProcessor;
|
||||
|
@ -57,18 +50,13 @@ import org.eclipse.cdt.dsf.mi.service.command.MIControlDMContext;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess.State;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIRunControlEventProcessor;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.utils.pty.PTY;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
|
@ -273,122 +261,6 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean canRestart() {
|
||||
if (fMIBackend.getIsAttachSession() || fMIBackend.getSessionType() == SessionType.CORE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Before GDB6.8, the Linux gdbserver would restart a new
|
||||
// process when getting a -exec-run but the communication
|
||||
// with GDB had a bug and everything hung.
|
||||
// with GDB6.8 the program restarts properly one time,
|
||||
// but on a second attempt, gdbserver crashes.
|
||||
// So, lets just turn off the Restart for Remote debugging
|
||||
if (fMIBackend.getSessionType() == SessionType.REMOTE) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the program.
|
||||
*/
|
||||
public void start(GdbLaunch launch, final RequestMonitor requestMonitor) {
|
||||
startOrRestart(launch, false, requestMonitor);
|
||||
}
|
||||
|
||||
/*
|
||||
* Before restarting the inferior, we must re-initialize its input/output streams
|
||||
* and create a new inferior process object. Then we can restart the inferior.
|
||||
*/
|
||||
public void restart(final GdbLaunch launch, final RequestMonitor requestMonitor) {
|
||||
startOrRestart(launch, true, requestMonitor);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert breakpoint at entry if set, and start or restart the program.
|
||||
*/
|
||||
protected void startOrRestart(final GdbLaunch launch, boolean restart, final RequestMonitor requestMonitor) {
|
||||
if (fMIBackend.getIsAttachSession()) {
|
||||
// When attaching to a running process, we do not need to set a breakpoint or
|
||||
// start the program; it is left up to the user.
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
DsfServicesTracker servicesTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), getSession().getId());
|
||||
IMIProcesses procService = servicesTracker.getService(IMIProcesses.class);
|
||||
servicesTracker.dispose();
|
||||
final IContainerDMContext containerDmc = procService.createContainerContextFromGroupId(fControlDmc, MIProcesses.UNIQUE_GROUP_ID);
|
||||
|
||||
final ICommand<MIInfo> execCommand;
|
||||
if (useContinueCommand(launch, restart)) {
|
||||
execCommand = getCommandFactory().createMIExecContinue(containerDmc);
|
||||
} else {
|
||||
execCommand = getCommandFactory().createMIExecRun(containerDmc);
|
||||
}
|
||||
|
||||
boolean stopInMain = false;
|
||||
try {
|
||||
stopInMain = launch.getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false );
|
||||
} catch (CoreException e) {
|
||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve stop at entry point boolean", e)); //$NON-NLS-1$
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
final DataRequestMonitor<MIInfo> execMonitor = new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
if (fMIBackend.getSessionType() != SessionType.REMOTE) {
|
||||
// Don't send the ContainerStarted event for a remote session because
|
||||
// it has already been done by MIRunControlEventProcessor when receiving
|
||||
// the ^connect
|
||||
getSession().dispatchEvent(new ContainerStartedDMEvent(containerDmc), getProperties());
|
||||
}
|
||||
super.handleSuccess();
|
||||
}
|
||||
};
|
||||
|
||||
if (!stopInMain) {
|
||||
// Just start the program.
|
||||
queueCommand(execCommand, execMonitor);
|
||||
} else {
|
||||
String stopSymbol = null;
|
||||
try {
|
||||
stopSymbol = launch.getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT );
|
||||
} catch (CoreException e) {
|
||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.CONFIGURATION_INVALID, "Cannot retrieve the entry point symbol", e)); //$NON-NLS-1$
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Insert a breakpoint at the requested stop symbol.
|
||||
queueCommand(
|
||||
getCommandFactory().createMIBreakInsert(fControlDmc, true, false, null, 0, stopSymbol, 0),
|
||||
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// After the break-insert is done, execute the -exec-run or -exec-continue command.
|
||||
queueCommand(execCommand, execMonitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates if we should use the -exec-continue method
|
||||
* instead of the -exec-run method.
|
||||
* This can be overridden to allow for customization.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
protected boolean useContinueCommand(ILaunch launch, boolean restart) {
|
||||
// When doing remote debugging, we use -exec-continue instead of -exec-run
|
||||
// Restart does not apply to remote sessions
|
||||
return fMIBackend.getSessionType() == SessionType.REMOTE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method creates a new inferior process object based on the current Pty or output stream.
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2010 Wind River Systems and others.
|
||||
* Copyright (c) 2006, 2011 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
|
||||
|
@ -24,7 +24,6 @@ import java.util.Properties;
|
|||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
|
@ -33,26 +32,18 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
|||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
||||
import org.eclipse.cdt.dsf.gdb.service.GDBProcesses_7_0.ContainerExitedDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.service.GDBProcesses_7_0.ContainerStartedDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.service.GDBRunControl_7_0;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IReverseRunControl;
|
||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend.BackendStateChangedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.AbstractMIControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CLIEventProcessor_7_0;
|
||||
|
@ -61,19 +52,14 @@ import org.eclipse.cdt.dsf.mi.service.command.MIControlDMContext;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess.State;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIRunControlEventProcessor_7_0;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIListFeaturesInfo;
|
||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.utils.pty.PTY;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
|
@ -292,240 +278,6 @@ public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean canRestart() {
|
||||
if (fMIBackend.getIsAttachSession()|| fMIBackend.getSessionType() == SessionType.CORE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Before GDB6.8, the Linux gdbserver would restart a new
|
||||
// process when getting a -exec-run but the communication
|
||||
// with GDB had a bug and everything hung.
|
||||
// with GDB6.8 the program restarts properly one time,
|
||||
// but on a second attempt, gdbserver crashes.
|
||||
// So, lets just turn off the Restart for Remote debugging
|
||||
if (fMIBackend.getSessionType() == SessionType.REMOTE) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the program.
|
||||
*/
|
||||
public void start(GdbLaunch launch, final RequestMonitor requestMonitor) {
|
||||
startOrRestart(launch, false, requestMonitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Before restarting the inferior, we must re-initialize its input/output streams
|
||||
* and create a new inferior process object. Then we can restart the inferior.
|
||||
*/
|
||||
public void restart(final GdbLaunch launch, final RequestMonitor requestMonitor) {
|
||||
startOrRestart(launch, true, requestMonitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert breakpoint at entry if set, and start or restart the program.
|
||||
* Note that restart does not apply to remote or attach sessions.
|
||||
*
|
||||
* If we want to enable Reverse debugging from the start of the program we do the following:
|
||||
* attachSession => enable reverse
|
||||
* else => set temp bp on main, run, enable reverse, continue if bp on main was not requested by user
|
||||
*/
|
||||
protected void startOrRestart(final GdbLaunch launch, final boolean restart, RequestMonitor requestMonitor) {
|
||||
boolean tmpReverseEnabled = IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT;
|
||||
try {
|
||||
tmpReverseEnabled = launch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT);
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
final boolean reverseEnabled = tmpReverseEnabled;
|
||||
|
||||
if (fMIBackend.getIsAttachSession()) {
|
||||
// Restart does not apply to attach sessions.
|
||||
//
|
||||
// When attaching to a running process, we do not need to set a breakpoint or
|
||||
// start the program; it is left up to the user.
|
||||
// We only need to turn on Reverse Debugging if requested.
|
||||
if (reverseEnabled) {
|
||||
IReverseRunControl reverseService = getServicesTracker().getService(IReverseRunControl.class);
|
||||
if (reverseService != null) {
|
||||
reverseService.enableReverseMode(fControlDmc, true, requestMonitor);
|
||||
return;
|
||||
}
|
||||
}
|
||||
requestMonitor.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// When it is not an attach session, it gets a little more complicated
|
||||
// so let's use a sequence.
|
||||
getExecutor().execute(new Sequence(getExecutor(), requestMonitor) {
|
||||
IContainerDMContext fContainerDmc;
|
||||
MIBreakpoint fUserBreakpoint = null;
|
||||
boolean fUserBreakpointIsOnMain = false;
|
||||
|
||||
Step[] fSteps = new Step[] {
|
||||
/*
|
||||
* If the user requested a 'stopOnMain', let's set the temporary breakpoint
|
||||
* where the user specified.
|
||||
*/
|
||||
new Step() {
|
||||
@Override
|
||||
public void execute(final RequestMonitor rm) {
|
||||
boolean userRequestedStop = false;
|
||||
try {
|
||||
userRequestedStop = launch.getLaunchConfiguration().getAttribute(
|
||||
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN,
|
||||
false);
|
||||
} catch (CoreException e) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve stop at entry point boolean", e)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (userRequestedStop) {
|
||||
String userStopSymbol = null;
|
||||
try {
|
||||
userStopSymbol = launch.getLaunchConfiguration().getAttribute(
|
||||
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL,
|
||||
ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT);
|
||||
} catch (CoreException e) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.CONFIGURATION_INVALID, "Cannot retrieve the entry point symbol", e)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
queueCommand(getCommandFactory().createMIBreakInsert(fControlDmc, true, false, null, 0, userStopSymbol, 0),
|
||||
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
public void handleSuccess() {
|
||||
if (getData() != null) {
|
||||
MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
|
||||
if (breakpoints.length > 0) {
|
||||
fUserBreakpoint = breakpoints[0];
|
||||
}
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rm.done();
|
||||
}
|
||||
}},
|
||||
/*
|
||||
* If reverse debugging, set a breakpoint on main to be able to enable reverse
|
||||
* as early as possible.
|
||||
* If the user has requested a stop at the same point, we could skip this breakpoint
|
||||
* however, we have to first set it to find out! So, we just leave it.
|
||||
*/
|
||||
new Step() {
|
||||
@Override
|
||||
public void execute(final RequestMonitor rm) {
|
||||
if (reverseEnabled) {
|
||||
queueCommand(getCommandFactory().createMIBreakInsert(fControlDmc, true, false, null, 0,
|
||||
ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT, 0),
|
||||
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
public void handleSuccess() {
|
||||
if (getData() != null) {
|
||||
MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
|
||||
if (breakpoints.length > 0 && fUserBreakpoint != null) {
|
||||
fUserBreakpointIsOnMain = breakpoints[0].getAddress().equals(fUserBreakpoint.getAddress());
|
||||
}
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rm.done();
|
||||
}
|
||||
}},
|
||||
/*
|
||||
* Now, run the program. Use either -exec-run or -exec-continue depending
|
||||
* on whether we have remote session or not.
|
||||
*/
|
||||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
IMIProcesses procService = getServicesTracker().getService(IMIProcesses.class);
|
||||
fContainerDmc = procService.createContainerContextFromGroupId(fControlDmc, MIProcesses.UNIQUE_GROUP_ID);
|
||||
ICommand<MIInfo> command;
|
||||
|
||||
if (useContinueCommand(launch, restart)) {
|
||||
command = getCommandFactory().createMIExecContinue(fContainerDmc);
|
||||
} else {
|
||||
command = getCommandFactory().createMIExecRun(fContainerDmc);
|
||||
}
|
||||
queueCommand(command, new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||
}},
|
||||
/*
|
||||
* In case of a restart, reverse debugging should be marked as off here because
|
||||
* GDB will have turned it off. We may turn it back on after.
|
||||
*/
|
||||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
// Although it only makes sense for a restart, it doesn't hurt
|
||||
// do to it all the time.
|
||||
GDBRunControl_7_0 reverseService = getServicesTracker().getService(GDBRunControl_7_0.class);
|
||||
if (reverseService != null) {
|
||||
reverseService.setReverseModeEnabled(false);
|
||||
}
|
||||
rm.done();
|
||||
}},
|
||||
/*
|
||||
* Since we have started the program, we can turn on reverse debugging if needed
|
||||
*/
|
||||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
if (reverseEnabled) {
|
||||
IReverseRunControl reverseService = getServicesTracker().getService(IReverseRunControl.class);
|
||||
if (reverseService != null) {
|
||||
reverseService.enableReverseMode(fControlDmc, true, rm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
rm.done();
|
||||
}},
|
||||
/*
|
||||
* Finally, if we are enabling reverse, and the userSymbolStop is not on main,
|
||||
* we should do a continue because we are currently stopped on main but that
|
||||
* is not what the user requested
|
||||
*/
|
||||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
if (reverseEnabled && !fUserBreakpointIsOnMain) {
|
||||
queueCommand(getCommandFactory().createMIExecContinue(fContainerDmc),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||
} else {
|
||||
rm.done();
|
||||
}
|
||||
}},
|
||||
};
|
||||
|
||||
@Override
|
||||
public Step[] getSteps() {
|
||||
return fSteps;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates if we should use the -exec-continue method
|
||||
* instead of the -exec-run method.
|
||||
* This can be overridden to allow for customization.
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
protected boolean useContinueCommand(ILaunch launch, boolean restart) {
|
||||
// When doing remote debugging, we use -exec-continue instead of -exec-run
|
||||
// Restart does not apply to remote sessions
|
||||
return fMIBackend.getSessionType() == SessionType.REMOTE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a new inferior process object based on the current Pty or output stream.
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008, 2010 Ericsson and others.
|
||||
* Copyright (c) 2008, 2011 Ericsson and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -17,7 +17,6 @@ import java.util.List;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
|
||||
|
@ -27,9 +26,6 @@ public interface IGDBControl extends IMICommandControl {
|
|||
void terminate(final RequestMonitor rm);
|
||||
void initInferiorInputOutput(final RequestMonitor requestMonitor);
|
||||
|
||||
boolean canRestart();
|
||||
void start(GdbLaunch launch, final RequestMonitor requestMonitor);
|
||||
void restart(final GdbLaunch launch, final RequestMonitor requestMonitor);
|
||||
void createInferiorProcess();
|
||||
|
||||
boolean isConnected();
|
||||
|
|
|
@ -41,10 +41,10 @@ import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
|||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIRunControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIStack;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
|
@ -76,7 +76,7 @@ public class SyncUtil {
|
|||
private static CommandFactory fCommandFactory;
|
||||
|
||||
private static IBreakpointsTargetDMContext fBreakpointsDmc;
|
||||
private static IMIProcesses fProcessesService;
|
||||
private static IGDBProcesses fProcessesService;
|
||||
|
||||
// Initialize some common things, once the session has been established
|
||||
public static void initialize(DsfSession session) throws Exception {
|
||||
|
@ -92,7 +92,7 @@ public class SyncUtil {
|
|||
fRunControl = tracker.getService(IMIRunControl.class);
|
||||
fStack = tracker.getService(MIStack.class);
|
||||
fExpressions = tracker.getService(IExpressions.class);
|
||||
fProcessesService = tracker.getService(IMIProcesses.class);
|
||||
fProcessesService = tracker.getService(IGDBProcesses.class);
|
||||
fCommandFactory = tracker.getService(IMICommandControl.class).getCommandFactory();
|
||||
|
||||
fBreakpointsDmc = (IBreakpointsTargetDMContext)fGdbControl.getContext();
|
||||
|
@ -606,12 +606,22 @@ public class SyncUtil {
|
|||
* Restart the program.
|
||||
*/
|
||||
public static void restart(final GdbLaunch launch) throws Throwable {
|
||||
// Check if restart is allowed
|
||||
final IContainerDMContext containerDmc = getContainerContext();
|
||||
|
||||
// Check if restart is allowed
|
||||
Query<Boolean> query = new Query<Boolean>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<Boolean> rm) {
|
||||
rm.setData(fGdbControl.canRestart());
|
||||
rm.done();
|
||||
protected void execute(final DataRequestMonitor<Boolean> rm) {
|
||||
fProcessesService.canRestart(
|
||||
containerDmc,
|
||||
new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
rm.setData(getData());
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -628,14 +638,20 @@ public class SyncUtil {
|
|||
MIStoppedEvent.class);
|
||||
|
||||
// Perform the restart
|
||||
Query<Boolean> query2 = new Query<Boolean>() {
|
||||
Query<Object> query2 = new Query<Object>() {
|
||||
@Override
|
||||
protected void execute(final DataRequestMonitor<Boolean> rm) {
|
||||
protected void execute(final DataRequestMonitor<Object> rm) {
|
||||
fGdbControl.initInferiorInputOutput(new RequestMonitor(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
fGdbControl.createInferiorProcess();
|
||||
fGdbControl.restart(launch, rm);
|
||||
Map<String, Object> attributes = null;
|
||||
try {
|
||||
attributes = launch.getLaunchConfiguration().getAttributes();
|
||||
} catch (CoreException e) {}
|
||||
|
||||
fProcessesService.restart(containerDmc, attributes, rm);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue