mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
Bug 303808: Run all-stop mode with target async on GDB 7.12
The previous all-stop implementation use Ctrl-C (variants) to suspend the target program. This option is not supported when using the new GDB full CLI console provided in GDB 7.12. So the alternative is to send the mi command -exec-interrupt to suspend the target, however this option requires the use of target async-on mode (already in use for non stop mode). This update makes all-stop mode use target async mode when using versions higher or equal to GDB 7.12. This update also removes the non-stop mode restriction initially implemented for the use of the new GDB Full CLI console. Change-Id: Iabef20bdee814d413fc338f9ec8c2d99d6311c20
This commit is contained in:
parent
36fd126919
commit
31f0cc6476
15 changed files with 751 additions and 18 deletions
|
@ -0,0 +1,146 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2016 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
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.dsf.gdb.launching;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress;
|
||||||
|
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.command.CommandFactory;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclass for GDB >= 7.12.
|
||||||
|
*
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
public class FinalLaunchSequence_7_12 extends FinalLaunchSequence_7_7 {
|
||||||
|
private IGDBControl fCommandControl;
|
||||||
|
private CommandFactory fCommandFactory;
|
||||||
|
private Map<String, Object> fAttributes;
|
||||||
|
|
||||||
|
public FinalLaunchSequence_7_12(DsfSession session, Map<String, Object> attributes,
|
||||||
|
RequestMonitorWithProgress rm) {
|
||||||
|
super(session, attributes, rm);
|
||||||
|
fAttributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getExecutionOrder(String group) {
|
||||||
|
if (GROUP_TOP_LEVEL.equals(group)) {
|
||||||
|
// Initialize the list with the base class' steps
|
||||||
|
// We need to create a list that we can modify, which is why we create our own ArrayList.
|
||||||
|
List<String> orderList = new ArrayList<String>(
|
||||||
|
Arrays.asList(super.getExecutionOrder(GROUP_TOP_LEVEL)));
|
||||||
|
|
||||||
|
// Now insert our steps right after the initialization of the base class.
|
||||||
|
orderList.add(orderList.indexOf("stepInitializeFinalLaunchSequence_7_7") + 1, //$NON-NLS-1$
|
||||||
|
"stepInitializeFinalLaunchSequence_7_12"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
orderList.add(orderList.indexOf("stepSourceGDBInitFile") + 1, //$NON-NLS-1$
|
||||||
|
"stepSetTargetAsync"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
orderList.add(orderList.indexOf("stepSetTargetAsync") + 1, //$NON-NLS-1$
|
||||||
|
"stepSetRecordFullStopAtLimit"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
return orderList.toArray(new String[orderList.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the members of the FinalLaunchSequence_7_12 class. This step is mandatory for the rest of
|
||||||
|
* the sequence to complete.
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepInitializeFinalLaunchSequence_7_12(RequestMonitor rm) {
|
||||||
|
DsfServicesTracker tracker = new DsfServicesTracker(GdbPlugin.getBundleContext(),
|
||||||
|
getSession().getId());
|
||||||
|
fCommandControl = tracker.getService(IGDBControl.class);
|
||||||
|
tracker.dispose();
|
||||||
|
|
||||||
|
if (fCommandControl == null) {
|
||||||
|
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
|
||||||
|
"Cannot obtain service", null)); //$NON-NLS-1$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fCommandFactory = fCommandControl.getCommandFactory();
|
||||||
|
|
||||||
|
rm.done();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Execute
|
||||||
|
public void stepSetTargetAsync(RequestMonitor requestMonitor) {
|
||||||
|
// Use target async when interfacing with GDB 7.12 or higher
|
||||||
|
// this will allow us to use the new enhanced GDB Full CLI console
|
||||||
|
fCommandControl.queueCommand(
|
||||||
|
fCommandFactory.createMIGDBSetTargetAsync(fCommandControl.getContext(), true),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
|
||||||
|
@Override
|
||||||
|
protected void handleError() {
|
||||||
|
// We should only be calling this for GDB >= 7.12,
|
||||||
|
// but just in case, accept errors for older GDBs
|
||||||
|
requestMonitor.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set reverse debugging record full stop-at-limit to off, so GDB does not halt waiting for user input
|
||||||
|
* when the recording buffer gets full
|
||||||
|
* @param requestMonitor
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepSetRecordFullStopAtLimit(RequestMonitor requestMonitor) {
|
||||||
|
fCommandControl.queueCommand(
|
||||||
|
fCommandFactory.createMIGDBSetRecordFullStopAtLimit(fCommandControl.getContext(), false),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
|
||||||
|
@Override
|
||||||
|
protected void handleError() {
|
||||||
|
// Accept errors since this is not essential
|
||||||
|
requestMonitor.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Execute
|
||||||
|
public void stepSetNonStop(final RequestMonitor requestMonitor) {
|
||||||
|
boolean isNonStop = CDebugUtils.getAttribute(fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
|
||||||
|
LaunchUtils.getIsNonStopModeDefault());
|
||||||
|
|
||||||
|
if (isNonStop) {
|
||||||
|
// GDBs that don't support non-stop don't allow you to set it to false.
|
||||||
|
// We really should set it to false when GDB supports it though.
|
||||||
|
// Something to fix later.
|
||||||
|
// Note that disabling pagination is taken care of elsewhere
|
||||||
|
fCommandControl.queueCommand(
|
||||||
|
fCommandFactory.createMIGDBSetNonStop(fCommandControl.getContext(), true),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
||||||
|
} else {
|
||||||
|
requestMonitor.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,6 @@ import java.io.OutputStream;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.parser.util.StringUtil;
|
import org.eclipse.cdt.core.parser.util.StringUtil;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
|
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.cdt.utils.pty.PTY;
|
import org.eclipse.cdt.utils.pty.PTY;
|
||||||
import org.eclipse.cdt.utils.pty.PTY.Mode;
|
import org.eclipse.cdt.utils.pty.PTY.Mode;
|
||||||
|
@ -48,20 +47,16 @@ public class GDBBackend_7_12 extends GDBBackend {
|
||||||
/** Indicate that we failed to create a PTY. */
|
/** Indicate that we failed to create a PTY. */
|
||||||
private boolean fPtyFailure;
|
private boolean fPtyFailure;
|
||||||
|
|
||||||
private boolean fIsAllStop;
|
|
||||||
|
|
||||||
private InputStream fDummyErrorStream;
|
private InputStream fDummyErrorStream;
|
||||||
|
|
||||||
public GDBBackend_7_12(DsfSession session, ILaunchConfiguration lc) {
|
public GDBBackend_7_12(DsfSession session, ILaunchConfiguration lc) {
|
||||||
super(session, lc);
|
super(session, lc);
|
||||||
fIsAllStop = !LaunchUtils.getIsNonStopMode(lc);
|
|
||||||
createPty();
|
createPty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFullGdbConsoleSupported() {
|
public boolean isFullGdbConsoleSupported() {
|
||||||
return !Platform.getOS().equals(Platform.OS_WIN32)
|
return !Platform.getOS().equals(Platform.OS_WIN32)
|
||||||
&& !fIsAllStop
|
|
||||||
&& !fPtyFailure;
|
&& !fPtyFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,6 +154,12 @@ public class GDBBackend_7_12 extends GDBBackend {
|
||||||
// Now trigger the new console towards our PTY.
|
// Now trigger the new console towards our PTY.
|
||||||
"-ex", "new-ui mi " + fMIPty.getSlaveName(), //$NON-NLS-1$ //$NON-NLS-2$
|
"-ex", "new-ui mi " + fMIPty.getSlaveName(), //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
// With GDB.7.12, pagination can lock up the whole debug session
|
||||||
|
// when using the full GDB console, so we turn it off.
|
||||||
|
// We must turn it off before calling 'show version' as even
|
||||||
|
// that command could cause pagination to trigger
|
||||||
|
"-ex", "set pagination off", //$NON-NLS-1$//$NON-NLS-2$
|
||||||
|
|
||||||
// Now print the version so the user gets that familiar output
|
// Now print the version so the user gets that familiar output
|
||||||
"-ex", "show version" //$NON-NLS-1$ //$NON-NLS-2$
|
"-ex", "show version" //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,11 +7,17 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.dsf.gdb.service;
|
package org.eclipse.cdt.dsf.gdb.service;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
|
||||||
|
@ -29,6 +35,13 @@ public class GDBProcesses_7_12 extends GDBProcesses_7_10 {
|
||||||
super(session);
|
super(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Sequence getStartOrRestartProcessSequence(DsfExecutor executor,
|
||||||
|
IContainerDMContext containerDmc, Map<String, Object> attributes, boolean restart,
|
||||||
|
DataRequestMonitor<IContainerDMContext> rm) {
|
||||||
|
return new StartOrRestartProcessSequence_7_12(executor, containerDmc, attributes, restart, rm);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void terminate(IThreadDMContext thread, RequestMonitor rm) {
|
public void terminate(IThreadDMContext thread, RequestMonitor rm) {
|
||||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
||||||
|
|
|
@ -74,6 +74,17 @@ public class GDBRunControl_7_10 extends GDBRunControl_7_6 implements IReverseRun
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReverseModeEnabled(boolean enabled) {
|
||||||
|
super.setReverseModeEnabled(enabled);
|
||||||
|
if (!enabled) {
|
||||||
|
// Keep the disabled state in sync with the trace method
|
||||||
|
// This is needed e.g. to restart reverse mode during
|
||||||
|
// a process restart
|
||||||
|
fReverseTraceMethod = ReverseDebugMethod.OFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @since 5.1 */
|
/** @since 5.1 */
|
||||||
protected void setReverseTraceMethod(ReverseDebugMethod traceMethod) {
|
protected void setReverseTraceMethod(ReverseDebugMethod traceMethod) {
|
||||||
if (fReverseTraceMethod != traceMethod) {
|
if (fReverseTraceMethod != traceMethod) {
|
||||||
|
|
|
@ -0,0 +1,356 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2016 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
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.dsf.gdb.service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.debug.core.model.IChangeReverseMethodHandler.ReverseDebugMethod;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
|
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.IMICommandControl;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIFrame;
|
||||||
|
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.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
public class GDBRunControl_7_12 extends GDBRunControl_7_10 {
|
||||||
|
private IMICommandControl fCommandControl;
|
||||||
|
private CommandFactory fCommandFactory;
|
||||||
|
private Map<String, EnableReverseAtLocOperation> fBpIdToReverseOpMap = new HashMap<>();
|
||||||
|
|
||||||
|
public GDBRunControl_7_12(DsfSession session) {
|
||||||
|
super(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(final RequestMonitor rm) {
|
||||||
|
super.initialize(new ImmediateRequestMonitor(rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
doInitialize(rm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doInitialize(final RequestMonitor rm) {
|
||||||
|
fCommandControl = getServicesTracker().getService(IMICommandControl.class);
|
||||||
|
fCommandFactory = fCommandControl.getCommandFactory();
|
||||||
|
|
||||||
|
register(new String[]{ GDBRunControl_7_12.class.getName() },
|
||||||
|
new Hashtable<String,String>());
|
||||||
|
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void suspend(IExecutionDMContext context, final RequestMonitor rm){
|
||||||
|
canSuspend(
|
||||||
|
context,
|
||||||
|
new DataRequestMonitor<Boolean>(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
if (getData()) {
|
||||||
|
// Thread or Process
|
||||||
|
doSuspend(context, rm);
|
||||||
|
} else {
|
||||||
|
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context cannot be suspended.", null)); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doSuspend(IExecutionDMContext context, final RequestMonitor rm) {
|
||||||
|
// Start the job before sending the interrupt command
|
||||||
|
// to make sure we don't miss the *stopped event
|
||||||
|
final MonitorSuspendJob monitorJob = new MonitorSuspendJob(0, rm);
|
||||||
|
fCommandControl.queueCommand(fCommandFactory.createMIExecInterrupt(context),
|
||||||
|
new ImmediateDataRequestMonitor<MIInfo>() {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
// Nothing to do in the case of success, the monitoring job
|
||||||
|
// will take care of completing the RM once it gets the
|
||||||
|
// *stopped event.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleFailure() {
|
||||||
|
// In case of failure, we must cancel the monitoring job
|
||||||
|
// and indicate the failure in the rm.
|
||||||
|
monitorJob.cleanAndCancel();
|
||||||
|
rm.done(getStatus());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTargetAcceptingCommands() {
|
||||||
|
// Async mode is on when running with GDB 7.12 or higher
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
@DsfServiceEventHandler
|
||||||
|
public void eventDispatched(ISuspendedDMEvent event) {
|
||||||
|
assert event instanceof IMIDMEvent;
|
||||||
|
|
||||||
|
if (event instanceof IMIDMEvent) {
|
||||||
|
Object evt = ((IMIDMEvent)event).getMIEvent();
|
||||||
|
|
||||||
|
if (evt instanceof MIBreakpointHitEvent) {
|
||||||
|
MIBreakpointHitEvent miEvt = (MIBreakpointHitEvent)evt;
|
||||||
|
|
||||||
|
for (EnableReverseAtLocOperation enableReverse : fBpIdToReverseOpMap.values()) {
|
||||||
|
if (breakpointHitMatchesLocation(miEvt, enableReverse)) {
|
||||||
|
// We are now stopped at the right place to initiate the recording for reverse mode
|
||||||
|
// Remove the operation from our internal map and process it
|
||||||
|
fBpIdToReverseOpMap.remove(enableReverse.fBpId);
|
||||||
|
IContainerDMContext containerContext = enableReverse.getContainerContext();
|
||||||
|
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(containerContext, ICommandControlDMContext.class);
|
||||||
|
ReverseDebugMethod reverseMethod = enableReverse.getReverseDebugMethod();
|
||||||
|
if (controlDmc != null && reverseMethod != null) {
|
||||||
|
enableReverseMode(controlDmc, reverseMethod, new RequestMonitor(getExecutor(), null) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
if (enableReverse.shouldTriggerContinue()) {
|
||||||
|
fCommandControl.queueCommand(fCommandFactory.createMIExecContinue(containerContext),
|
||||||
|
new ImmediateDataRequestMonitor<MIInfo>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not expecting more than one operation for the same location
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class EnableReverseAtLocOperation {
|
||||||
|
private final IContainerDMContext fContainerContext;
|
||||||
|
private final ReverseDebugMethod fTraceMethod;
|
||||||
|
private final String fBpId;
|
||||||
|
private final String fFileLocation;
|
||||||
|
private final String fAddrLocation;
|
||||||
|
private final boolean fTriggerContinue;
|
||||||
|
|
||||||
|
public EnableReverseAtLocOperation(IContainerDMContext containerContext, ReverseDebugMethod traceMethod,
|
||||||
|
String bpId, String fileLoc, String addr, boolean tiggerContinue) {
|
||||||
|
fContainerContext = containerContext;
|
||||||
|
fTraceMethod = traceMethod;
|
||||||
|
fBpId = bpId;
|
||||||
|
fFileLocation = fileLoc;
|
||||||
|
fAddrLocation = addr;
|
||||||
|
fTriggerContinue = tiggerContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IContainerDMContext getContainerContext() {
|
||||||
|
return fContainerContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReverseDebugMethod getReverseDebugMethod() {
|
||||||
|
return fTraceMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBreakointId() {
|
||||||
|
return fBpId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileLocation() {
|
||||||
|
return fFileLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddrLocation() {
|
||||||
|
return fAddrLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldTriggerContinue() {
|
||||||
|
return fTriggerContinue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return fBpId.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (other instanceof EnableReverseAtLocOperation) {
|
||||||
|
if (fContainerContext != null
|
||||||
|
&& fContainerContext.equals(((EnableReverseAtLocOperation) other).fContainerContext)
|
||||||
|
&& fTraceMethod != null
|
||||||
|
&& fTraceMethod.equals(((EnableReverseAtLocOperation) other).fTraceMethod)
|
||||||
|
&& fBpId != null
|
||||||
|
&& fBpId.equals(((EnableReverseAtLocOperation) other).fBpId)
|
||||||
|
&& fFileLocation != null
|
||||||
|
&& fFileLocation.equals(((EnableReverseAtLocOperation) other).fFileLocation)
|
||||||
|
&& fAddrLocation != null
|
||||||
|
&& fAddrLocation.equals(((EnableReverseAtLocOperation) other).fAddrLocation)
|
||||||
|
&& fTriggerContinue == ((EnableReverseAtLocOperation) other).fTriggerContinue) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the reverse debugging method as soon as the program is suspended at the specified breakpoint location
|
||||||
|
*
|
||||||
|
* It is recommended to use this request before the program runs or restarts in order to prevent timing issues and
|
||||||
|
* miss a suspend event
|
||||||
|
*
|
||||||
|
* Note, using the break point id to determine the stop location would be sufficient although in the case where
|
||||||
|
* multiple break points are inserted in the same location, GDB will only report one of them (e.g. GDB 7.12)
|
||||||
|
*
|
||||||
|
* Having the MIBreakpoint will give us access to the address, file and line number as well which can be used as
|
||||||
|
* alternatives to determine a matched location.
|
||||||
|
*
|
||||||
|
* This method is specially useful when using async mode with i.e. with GDB 7.12.
|
||||||
|
* Activating reverse debugging when the target is running may trigger an unresponsive GDB, this triggered the
|
||||||
|
* creation of this method
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void enableReverseModeAtBpLocation(final IContainerDMContext containerContext, final ReverseDebugMethod traceMethod,
|
||||||
|
MIBreakpoint bp, boolean triggerContinue) {
|
||||||
|
|
||||||
|
// Using an internal convention for file location i.e. file:lineNumber
|
||||||
|
String fileLoc = bp.getFile() + ":" + bp.getLine(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
fBpIdToReverseOpMap.put(bp.getNumber(), new EnableReverseAtLocOperation(containerContext, traceMethod,
|
||||||
|
bp.getNumber(), fileLoc, bp.getAddress(), triggerContinue));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean breakpointHitMatchesLocation(MIBreakpointHitEvent e, EnableReverseAtLocOperation enableReverse) {
|
||||||
|
if (enableReverse != null) {
|
||||||
|
String bpId = e.getNumber();
|
||||||
|
|
||||||
|
// Here we check three different things to see if we are stopped at the right place
|
||||||
|
// 1- The actual location in the file. But this does not work for breakpoints that
|
||||||
|
// were set on non-executable lines
|
||||||
|
// 2- The address where the breakpoint was set. But this does not work for breakpoints
|
||||||
|
// that have multiple addresses (GDB returns <MULTIPLE>.) I think that is for multi-process
|
||||||
|
// 3- The breakpoint id that was hit. But this does not work if another breakpoint
|
||||||
|
// was also set on the same line because GDB may return that breakpoint as being hit.
|
||||||
|
//
|
||||||
|
// So this works for the large majority of cases. The case that won't work is when the user
|
||||||
|
// does a runToLine to a line that is non-executable AND has another breakpoint AND
|
||||||
|
// has multiple addresses for the breakpoint. I'm mean, come on!
|
||||||
|
boolean equalFileLocation = false;
|
||||||
|
boolean equalAddrLocation = false;
|
||||||
|
boolean equalBpId = bpId.equals(enableReverse.getBreakointId());
|
||||||
|
MIFrame frame = e.getFrame();
|
||||||
|
if(frame != null) {
|
||||||
|
String fileLocation = frame.getFile() + ":" + frame.getLine(); //$NON-NLS-1$
|
||||||
|
String addrLocation = frame.getAddress();
|
||||||
|
equalFileLocation = fileLocation.equals(enableReverse.getFileLocation());
|
||||||
|
equalAddrLocation = addrLocation.equals(enableReverse.getAddrLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (equalFileLocation || equalAddrLocation || equalBpId) {
|
||||||
|
// We stopped at the right place
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class MonitorSuspendJob extends Job {
|
||||||
|
// Bug 310274. Until we have a preference to configure timeouts,
|
||||||
|
// we need a large enough default timeout to accommodate slow
|
||||||
|
// remote sessions.
|
||||||
|
private final static int TIMEOUT_DEFAULT_VALUE = 5000;
|
||||||
|
|
||||||
|
private final RequestMonitor fRequestMonitor;
|
||||||
|
|
||||||
|
public MonitorSuspendJob(int timeout, RequestMonitor rm) {
|
||||||
|
super("Suspend monitor job."); //$NON-NLS-1$
|
||||||
|
setSystem(true);
|
||||||
|
fRequestMonitor = rm;
|
||||||
|
|
||||||
|
if (timeout <= 0) {
|
||||||
|
timeout = TIMEOUT_DEFAULT_VALUE; // default of 5 seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register to listen for the stopped event
|
||||||
|
getSession().addServiceEventListener(this, null);
|
||||||
|
|
||||||
|
schedule(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup job and cancel it.
|
||||||
|
* This method is required because super.canceling() is only called
|
||||||
|
* if the job is actually running.
|
||||||
|
*/
|
||||||
|
public boolean cleanAndCancel() {
|
||||||
|
if (getExecutor().isInExecutorThread()) {
|
||||||
|
getSession().removeServiceEventListener(this);
|
||||||
|
} else {
|
||||||
|
getExecutor().submit(
|
||||||
|
new DsfRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
getSession().removeServiceEventListener(MonitorSuspendJob.this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@DsfServiceEventHandler
|
||||||
|
public void eventDispatched(MIStoppedEvent e) {
|
||||||
|
if (e.getDMContext() != null && e.getDMContext() instanceof IMIExecutionDMContext ) {
|
||||||
|
// For all-stop, this means all threads have stopped
|
||||||
|
if (cleanAndCancel()) {
|
||||||
|
fRequestMonitor.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
|
// This will be called when the timeout is hit and no *stopped event was received
|
||||||
|
getExecutor().submit(
|
||||||
|
new DsfRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
getSession().removeServiceEventListener(MonitorSuspendJob.this);
|
||||||
|
fRequestMonitor.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Suspend operation timeout.", null)); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,6 +45,7 @@ import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.CommandFactory_6_8;
|
import org.eclipse.cdt.dsf.gdb.service.command.CommandFactory_6_8;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl;
|
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_0;
|
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_0;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_12;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_2;
|
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_2;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_4;
|
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_4;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_7;
|
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_7;
|
||||||
|
@ -212,6 +213,9 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ICommandControl createCommandControl(DsfSession session, ILaunchConfiguration config) {
|
protected ICommandControl createCommandControl(DsfSession session, ILaunchConfiguration config) {
|
||||||
|
if (compareVersionWith(GDB_7_12_VERSION) >= 0) {
|
||||||
|
return new GDBControl_7_12(session, config, new CommandFactory_6_8());
|
||||||
|
}
|
||||||
if (compareVersionWith(GDB_7_7_VERSION) >= 0) {
|
if (compareVersionWith(GDB_7_7_VERSION) >= 0) {
|
||||||
return new GDBControl_7_7(session, config, new CommandFactory_6_8());
|
return new GDBControl_7_7(session, config, new CommandFactory_6_8());
|
||||||
}
|
}
|
||||||
|
@ -318,6 +322,9 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Else, handle all-stop mode
|
// Else, handle all-stop mode
|
||||||
|
if (compareVersionWith(GDB_7_12_VERSION) >= 0) {
|
||||||
|
return new GDBRunControl_7_12(session);
|
||||||
|
}
|
||||||
if (compareVersionWith(GDB_7_10_VERSION) >= 0) {
|
if (compareVersionWith(GDB_7_10_VERSION) >= 0) {
|
||||||
return new GDBRunControl_7_10(session);
|
return new GDBRunControl_7_10(session);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,6 +80,7 @@ public class StartOrRestartProcessSequence_7_0 extends ReflectionSequence {
|
||||||
// on the main() method.
|
// on the main() method.
|
||||||
private boolean fUserBreakpointIsOnMain;
|
private boolean fUserBreakpointIsOnMain;
|
||||||
|
|
||||||
|
private MIBreakpoint fBreakPointForReverse;
|
||||||
private boolean fReverseEnabled;
|
private boolean fReverseEnabled;
|
||||||
private final Map<String, Object> fAttributes;
|
private final Map<String, Object> fAttributes;
|
||||||
|
|
||||||
|
@ -100,11 +101,18 @@ public class StartOrRestartProcessSequence_7_0 extends ReflectionSequence {
|
||||||
protected MIBreakpoint getUserBreakpoint() {
|
protected MIBreakpoint getUserBreakpoint() {
|
||||||
return fUserBreakpoint;
|
return fUserBreakpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
protected MIBreakpoint getBreakPointForReverse() {
|
||||||
|
return fBreakPointForReverse;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean getUserBreakpointIsOnMain() {
|
protected boolean getUserBreakpointIsOnMain() {
|
||||||
return fUserBreakpointIsOnMain;
|
return fUserBreakpointIsOnMain;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 5.0 */
|
/** @since 5.0 */
|
||||||
protected boolean getReverseEnabled() {
|
protected boolean getReverseEnabled() {
|
||||||
return fReverseEnabled;
|
return fReverseEnabled;
|
||||||
|
@ -243,8 +251,11 @@ public class StartOrRestartProcessSequence_7_0 extends ReflectionSequence {
|
||||||
public void handleSuccess() {
|
public void handleSuccess() {
|
||||||
if (getData() != null) {
|
if (getData() != null) {
|
||||||
MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
|
MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
|
||||||
if (breakpoints.length > 0 && fUserBreakpoint != null) {
|
if (breakpoints.length > 0) {
|
||||||
fUserBreakpointIsOnMain = breakpoints[0].getAddress().equals(fUserBreakpoint.getAddress());
|
fBreakPointForReverse = breakpoints[0];
|
||||||
|
if (fUserBreakpoint != null) {
|
||||||
|
fUserBreakpointIsOnMain = fBreakPointForReverse.getAddress().equals(fUserBreakpoint.getAddress());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rm.done();
|
rm.done();
|
||||||
|
|
|
@ -111,7 +111,13 @@ public class StartOrRestartProcessSequence_7_10 extends StartOrRestartProcessSeq
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
protected ReverseDebugMethod getReverseMode() {
|
||||||
|
return fReverseMode;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Here we set the reverse debug mode
|
* Here we set the reverse debug mode
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2016 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
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.dsf.gdb.service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
public class StartOrRestartProcessSequence_7_12 extends StartOrRestartProcessSequence_7_10 {
|
||||||
|
private GDBRunControl_7_12 fReverseService;
|
||||||
|
|
||||||
|
public StartOrRestartProcessSequence_7_12(DsfExecutor executor, IContainerDMContext containerDmc,
|
||||||
|
Map<String, Object> attributes, boolean restart, DataRequestMonitor<IContainerDMContext> rm) {
|
||||||
|
super(executor, containerDmc, attributes, restart, rm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the members of the StartOrRestartProcessSequence_7_12 class.
|
||||||
|
* This step is mandatory for the rest of the sequence to complete.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Execute
|
||||||
|
public void stepInitializeBaseSequence(final RequestMonitor rm) {
|
||||||
|
super.stepInitializeBaseSequence(new ImmediateRequestMonitor(rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
DsfServicesTracker tracker = new DsfServicesTracker(GdbPlugin.getBundleContext(),
|
||||||
|
getContainerContext().getSessionId());
|
||||||
|
fReverseService = tracker.getService(GDBRunControl_7_12.class);
|
||||||
|
tracker.dispose();
|
||||||
|
rm.done();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getExecutionOrder(String group) {
|
||||||
|
if (GROUP_TOP_LEVEL.equals(group)) {
|
||||||
|
// Initialize the list with the base class' steps
|
||||||
|
// We need to create a list that we can modify, which is why we create our own ArrayList.
|
||||||
|
List<String> orderList = new ArrayList<String>(Arrays.asList(super.getExecutionOrder(GROUP_TOP_LEVEL)));
|
||||||
|
|
||||||
|
// Need to insert reverse mode off before ordering the reverse start at a specified location
|
||||||
|
orderList.add(orderList.indexOf("stepCreateConsole") + 1, "stepSetReverseOff2"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
// Order the activation of reverse debugging before starting the program, it will be executed once the
|
||||||
|
// program stops at the specified location.
|
||||||
|
orderList.add(orderList.indexOf("stepSetReverseOff2") + 1, "stepSetReverseModeAtLocation"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
return orderList.toArray(new String[orderList.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Execute
|
||||||
|
public void stepSetReverseOff2(RequestMonitor rm) {
|
||||||
|
super.stepSetReverseOff(rm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request the enabling of reverse debugging, it will be applied once the program
|
||||||
|
* stops at the breakpoint inserted for reverse debugging
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepSetReverseModeAtLocation(final RequestMonitor rm) {
|
||||||
|
MIBreakpoint bp = getBreakPointForReverse();
|
||||||
|
if (getReverseEnabled() && fReverseService != null && bp != null) {
|
||||||
|
// Order to continue execution if there is no user break point inserted at main
|
||||||
|
fReverseService.enableReverseModeAtBpLocation(getContainerContext(), getReverseMode(), bp,
|
||||||
|
!getUserBreakpointIsOnMain());
|
||||||
|
}
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have scheduled the start of reverse debug, so we shall skip this method from super class
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Execute
|
||||||
|
public void stepSetReverseMode(RequestMonitor rm) {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have scheduled the start of reverse debug, so we shall skip this method from super class
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Execute
|
||||||
|
public void stepEnableReverse(RequestMonitor rm) {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The order to continue or not has been included with the order to start reverse debugging at a specific location
|
||||||
|
* so we shall skip this method from super class
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Execute
|
||||||
|
public void stepContinue(RequestMonitor rm) {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2016 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
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.dsf.gdb.service.command;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence_7_12;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Need a new FinalLaunchSequence for GDB 7.12
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
public class GDBControl_7_12 extends GDBControl_7_7 {
|
||||||
|
public GDBControl_7_12(DsfSession session, ILaunchConfiguration config, CommandFactory factory) {
|
||||||
|
super(session, config, factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Sequence getCompleteInitializationSequence(Map<String, Object> attributes, RequestMonitorWithProgress rm) {
|
||||||
|
return new FinalLaunchSequence_7_12(getSession(), attributes, rm);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ package org.eclipse.cdt.dsf.gdb.service.extensions;
|
||||||
|
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory;
|
import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_7;
|
import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_12;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
@ -38,14 +38,14 @@ import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
*
|
*
|
||||||
* @since 4.8
|
* @since 4.8
|
||||||
*/
|
*/
|
||||||
public class GDBControl_HEAD extends GDBControl_7_7 {
|
public class GDBControl_HEAD extends GDBControl_7_12 {
|
||||||
public GDBControl_HEAD(DsfSession session, ILaunchConfiguration lc, CommandFactory factory) {
|
public GDBControl_HEAD(DsfSession session, ILaunchConfiguration lc, CommandFactory factory) {
|
||||||
super(session, lc, factory);
|
super(session, lc, factory);
|
||||||
|
|
||||||
validateGdbVersion(session);
|
validateGdbVersion(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getMinGDBVersionSupported() { return GdbDebugServicesFactory.GDB_7_7_VERSION; }
|
protected String getMinGDBVersionSupported() { return GdbDebugServicesFactory.GDB_7_12_VERSION; }
|
||||||
|
|
||||||
protected void validateGdbVersion(DsfSession session) {
|
protected void validateGdbVersion(DsfSession session) {
|
||||||
GdbDebugServicesFactory.validateGdbVersion(session, getMinGDBVersionSupported(), this);
|
GdbDebugServicesFactory.validateGdbVersion(session, getMinGDBVersionSupported(), this);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
package org.eclipse.cdt.dsf.gdb.service.extensions;
|
package org.eclipse.cdt.dsf.gdb.service.extensions;
|
||||||
|
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.GDBRunControl_7_10;
|
import org.eclipse.cdt.dsf.gdb.service.GDBRunControl_7_12;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory;
|
import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
|
|
||||||
|
@ -37,14 +37,14 @@ import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
*
|
*
|
||||||
* @since 4.8
|
* @since 4.8
|
||||||
*/
|
*/
|
||||||
public class GDBRunControl_HEAD extends GDBRunControl_7_10 {
|
public class GDBRunControl_HEAD extends GDBRunControl_7_12 {
|
||||||
public GDBRunControl_HEAD(DsfSession session) {
|
public GDBRunControl_HEAD(DsfSession session) {
|
||||||
super(session);
|
super(session);
|
||||||
|
|
||||||
validateGdbVersion(session);
|
validateGdbVersion(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getMinGDBVersionSupported() { return GdbDebugServicesFactory.GDB_7_10_VERSION; }
|
protected String getMinGDBVersionSupported() { return GdbDebugServicesFactory.GDB_7_12_VERSION; }
|
||||||
|
|
||||||
protected void validateGdbVersion(DsfSession session) {
|
protected void validateGdbVersion(DsfSession session) {
|
||||||
GdbDebugServicesFactory.validateGdbVersion(session, getMinGDBVersionSupported(), this);
|
GdbDebugServicesFactory.validateGdbVersion(session, getMinGDBVersionSupported(), this);
|
||||||
|
|
|
@ -135,6 +135,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetPagination;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetPrintObject;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetPrintObject;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetPrintSevenbitStrings;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetPrintSevenbitStrings;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetPythonPrintStack;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetPythonPrintStack;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetRecordFullStopAtLimit;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetSchedulerLocking;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetSchedulerLocking;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetSolibAbsolutePrefix;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetSolibAbsolutePrefix;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetSolibSearchPath;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetSolibSearchPath;
|
||||||
|
@ -821,6 +822,11 @@ public class CommandFactory {
|
||||||
return new MIGDBSetPythonPrintStack(ctx, option);
|
return new MIGDBSetPythonPrintStack(ctx, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 5.2 */
|
||||||
|
public ICommand<MIInfo> createMIGDBSetRecordFullStopAtLimit(ICommandControlDMContext ctx, boolean isSet) {
|
||||||
|
return new MIGDBSetRecordFullStopAtLimit(ctx, isSet);
|
||||||
|
}
|
||||||
|
|
||||||
/** @since 4.1 */
|
/** @since 4.1 */
|
||||||
public ICommand<MIInfo> createMIGDBSetSchedulerLocking(ICommandControlDMContext ctx, String mode) {
|
public ICommand<MIInfo> createMIGDBSetSchedulerLocking(ICommandControlDMContext ctx, String mode) {
|
||||||
return new MIGDBSetSchedulerLocking(ctx, mode);
|
return new MIGDBSetSchedulerLocking(ctx, mode);
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2016 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
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.dsf.mi.service.command.commands;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* -gdb-set record full stop-at-limit [on | off]
|
||||||
|
* @since 5.2
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MIGDBSetRecordFullStopAtLimit extends MIGDBSet
|
||||||
|
{
|
||||||
|
public MIGDBSetRecordFullStopAtLimit(ICommandControlDMContext ctx, boolean isSet) {
|
||||||
|
super(ctx, new String[] {"record", "full", "stop-at-limit", isSet ? "on" : "off"});//$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress;
|
||||||
import org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence_7_7;
|
import org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence_7_12;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
|
@ -29,7 +29,7 @@ import org.eclipse.cdt.examples.dsf.gdb.service.IGDBExtendedFunctions;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
|
|
||||||
public class GdbExtendedFinalLaunchSequence extends FinalLaunchSequence_7_7 {
|
public class GdbExtendedFinalLaunchSequence extends FinalLaunchSequence_7_12 {
|
||||||
|
|
||||||
private IGDBControl fControl;
|
private IGDBControl fControl;
|
||||||
private DsfServicesTracker fTracker;
|
private DsfServicesTracker fTracker;
|
||||||
|
|
Loading…
Add table
Reference in a new issue