1
0
Fork 0
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:
Alvaro Sanchez-Leon 2016-11-02 17:31:44 -04:00
parent 36fd126919
commit 31f0cc6476
15 changed files with 751 additions and 18 deletions

View file

@ -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();
}
}
}

View file

@ -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$
}; };

View file

@ -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);

View file

@ -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) {

View file

@ -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;
}
}
}

View file

@ -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);
} }

View file

@ -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();

View file

@ -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

View file

@ -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();
}
}

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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$
}
}

View file

@ -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;