mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-04 23:05:47 +02:00
[258284] This patch allows the user to enable reverse debugging from the launch. I got it all to work except for one case: if the user turns off StopOnMain, but actually has a real breakpoint on main,
then that breakpoint will be ignored when having Reverse on in the launch.
This commit is contained in:
parent
51cf30f09d
commit
ea1399cf07
5 changed files with 239 additions and 70 deletions
|
@ -46,8 +46,10 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
|
||||||
protected Text fGDBCommandText;
|
protected Text fGDBCommandText;
|
||||||
protected Text fGDBInitText;
|
protected Text fGDBInitText;
|
||||||
protected Button fNonStopCheckBox;
|
protected Button fNonStopCheckBox;
|
||||||
|
protected Button fReverseCheckBox;
|
||||||
protected Button fVerboseModeButton;
|
protected Button fVerboseModeButton;
|
||||||
|
|
||||||
|
|
||||||
private IMILaunchConfigurationComponent fSolibBlock;
|
private IMILaunchConfigurationComponent fSolibBlock;
|
||||||
private boolean fIsInitializing = false;
|
private boolean fIsInitializing = false;
|
||||||
|
|
||||||
|
@ -69,6 +71,8 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
|
||||||
IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT);
|
IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT);
|
||||||
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
|
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
|
||||||
IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
|
IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
|
||||||
|
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE,
|
||||||
|
IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT);
|
||||||
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_VERBOSE_MODE,
|
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_VERBOSE_MODE,
|
||||||
IGDBLaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT);
|
IGDBLaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT);
|
||||||
|
|
||||||
|
@ -95,6 +99,8 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
|
||||||
String gdbCommand = IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT;
|
String gdbCommand = IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT;
|
||||||
String gdbInit = IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT;
|
String gdbInit = IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT;
|
||||||
boolean nonStopMode = IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT;
|
boolean nonStopMode = IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT;
|
||||||
|
boolean reverseEnabled = IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT;
|
||||||
|
|
||||||
boolean verboseMode = IGDBLaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT;
|
boolean verboseMode = IGDBLaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -116,6 +122,14 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
|
||||||
}
|
}
|
||||||
catch(CoreException e) {
|
catch(CoreException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
reverseEnabled = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE,
|
||||||
|
IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT);
|
||||||
|
}
|
||||||
|
catch(CoreException e) {
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
verboseMode = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_VERBOSE_MODE,
|
verboseMode = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_VERBOSE_MODE,
|
||||||
IGDBLaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT );
|
IGDBLaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT );
|
||||||
|
@ -128,6 +142,7 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
|
||||||
fGDBCommandText.setText(gdbCommand);
|
fGDBCommandText.setText(gdbCommand);
|
||||||
fGDBInitText.setText(gdbInit);
|
fGDBInitText.setText(gdbInit);
|
||||||
fNonStopCheckBox.setSelection(nonStopMode);
|
fNonStopCheckBox.setSelection(nonStopMode);
|
||||||
|
fReverseCheckBox.setSelection(reverseEnabled);
|
||||||
fVerboseModeButton.setSelection(verboseMode);
|
fVerboseModeButton.setSelection(verboseMode);
|
||||||
|
|
||||||
setInitializing(false);
|
setInitializing(false);
|
||||||
|
@ -140,6 +155,8 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
|
||||||
fGDBInitText.getText().trim());
|
fGDBInitText.getText().trim());
|
||||||
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
|
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
|
||||||
fNonStopCheckBox.getSelection());
|
fNonStopCheckBox.getSelection());
|
||||||
|
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE,
|
||||||
|
fReverseCheckBox.getSelection());
|
||||||
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_VERBOSE_MODE,
|
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_VERBOSE_MODE,
|
||||||
fVerboseModeButton.getSelection() );
|
fVerboseModeButton.getSelection() );
|
||||||
|
|
||||||
|
@ -291,6 +308,16 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: Ideally, this field should be disabled if the back-end doesn't support reverse debugging
|
||||||
|
// TODO: Find a way to determine if reverse is supported (i.e. find the GDB version) then grey out the check box if necessary
|
||||||
|
fReverseCheckBox = ControlFactory.createCheckBox(subComp, LaunchUIMessages.getString("GDBDebuggerPage.14")); //$NON-NLS-1$
|
||||||
|
fReverseCheckBox.addSelectionListener( new SelectionAdapter() {
|
||||||
|
@Override
|
||||||
|
public void widgetSelected(SelectionEvent e) {
|
||||||
|
updateLaunchConfigurationDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
fVerboseModeButton = ControlFactory.createCheckBox( subComp, LaunchUIMessages.getString( "StandardGDBDebuggerPage.13" ) ); //$NON-NLS-1$
|
fVerboseModeButton = ControlFactory.createCheckBox( subComp, LaunchUIMessages.getString( "StandardGDBDebuggerPage.13" ) ); //$NON-NLS-1$
|
||||||
fVerboseModeButton.addSelectionListener(new SelectionAdapter() {
|
fVerboseModeButton.addSelectionListener(new SelectionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -312,8 +339,10 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
|
||||||
fNonStopCheckBox.setLayoutData(gd);
|
fNonStopCheckBox.setLayoutData(gd);
|
||||||
gd = new GridData();
|
gd = new GridData();
|
||||||
gd.horizontalSpan = 3;
|
gd.horizontalSpan = 3;
|
||||||
|
fReverseCheckBox.setLayoutData(gd);
|
||||||
|
gd = new GridData();
|
||||||
|
gd.horizontalSpan = 3;
|
||||||
fVerboseModeButton.setLayoutData(gd);
|
fVerboseModeButton.setLayoutData(gd);
|
||||||
|
|
||||||
// Grayed out until bug 249227 is resolved
|
// Grayed out until bug 249227 is resolved
|
||||||
//
|
//
|
||||||
fVerboseModeButton.setVisible(false);
|
fVerboseModeButton.setVisible(false);
|
||||||
|
|
|
@ -25,6 +25,7 @@ GDBDebuggerPage.10=Shared Libraries
|
||||||
GDBDebuggerPage.11=Protocol:
|
GDBDebuggerPage.11=Protocol:
|
||||||
GDBDebuggerPage.12=Default
|
GDBDebuggerPage.12=Default
|
||||||
GDBDebuggerPage.13=Non-stop mode (Note: Requires non-stop GDB)
|
GDBDebuggerPage.13=Non-stop mode (Note: Requires non-stop GDB)
|
||||||
|
GDBDebuggerPage.14=Enable Reverse Debugging at startup (Note: Requires Reverse GDB)
|
||||||
StandardGDBDebuggerPage.0=Debugger executable must be specified.
|
StandardGDBDebuggerPage.0=Debugger executable must be specified.
|
||||||
StandardGDBDebuggerPage.1=GDB Debugger Options
|
StandardGDBDebuggerPage.1=GDB Debugger Options
|
||||||
StandardGDBDebuggerPage.2=Main
|
StandardGDBDebuggerPage.2=Main
|
||||||
|
|
|
@ -82,6 +82,12 @@ public class IGDBLaunchConfigurationConstants {
|
||||||
*/
|
*/
|
||||||
public static final String ATTR_DEBUGGER_VERBOSE_MODE = GdbPlugin.PLUGIN_ID + ".verboseMode"; //$NON-NLS-1$
|
public static final String ATTR_DEBUGGER_VERBOSE_MODE = GdbPlugin.PLUGIN_ID + ".verboseMode"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch configuration attribute key. Boolean value to enable reverse debugging at launch time.
|
||||||
|
* @since 2.0
|
||||||
|
*/
|
||||||
|
public static final String ATTR_DEBUGGER_REVERSE = GdbPlugin.PLUGIN_ID + ".REVERSE"; //$NON-NLS-1$
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch configuration attribute value. The key is ATTR_DEBUG_NAME.
|
* Launch configuration attribute value. The key is ATTR_DEBUG_NAME.
|
||||||
*/
|
*/
|
||||||
|
@ -114,4 +120,10 @@ public class IGDBLaunchConfigurationConstants {
|
||||||
* @since 1.1
|
* @since 1.1
|
||||||
*/
|
*/
|
||||||
public static final boolean DEBUGGER_VERBOSE_MODE_DEFAULT = false;
|
public static final boolean DEBUGGER_VERBOSE_MODE_DEFAULT = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch configuration attribute value. The key is ATTR_DEBUGGER_REVERSE.
|
||||||
|
* @since 2.0
|
||||||
|
*/
|
||||||
|
public static final boolean DEBUGGER_REVERSE_DEFAULT = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,7 +184,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
||||||
public void handleSuccess() {
|
public void handleSuccess() {
|
||||||
getConnection().queueCommand(finalcmd, new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
getConnection().queueCommand(finalcmd, new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
||||||
@Override
|
@Override
|
||||||
public void handleSuccess() {
|
public void handleCompleted() {
|
||||||
getConnection().queueCommand(
|
getConnection().queueCommand(
|
||||||
new RawCommand(finaldmc, "set exec-direction forward"),
|
new RawCommand(finaldmc, "set exec-direction forward"),
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||||
|
@ -266,7 +266,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
||||||
public void handleSuccess() {
|
public void handleSuccess() {
|
||||||
getConnection().queueCommand(finalcmd, new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
getConnection().queueCommand(finalcmd, new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
||||||
@Override
|
@Override
|
||||||
public void handleSuccess() {
|
public void handleCompleted() {
|
||||||
getConnection().queueCommand(
|
getConnection().queueCommand(
|
||||||
new RawCommand(finaldmc, "set exec-direction forward"),
|
new RawCommand(finaldmc, "set exec-direction forward"),
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||||
|
|
|
@ -28,10 +28,12 @@ import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.GDBRunControl_7_0;
|
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.IGDBBackend;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.service.IReverseRunControl;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||||
|
@ -51,9 +53,9 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecRun;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBExit;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBExit;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInferiorTTYSet;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInferiorTTYSet;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
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.MIInfo;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
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.dsf.service.DsfSession;
|
||||||
import org.eclipse.cdt.utils.pty.PTY;
|
import org.eclipse.cdt.utils.pty.PTY;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
@ -277,77 +279,202 @@ public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
|
||||||
/**
|
/**
|
||||||
* Insert breakpoint at entry if set, and start or restart the program.
|
* Insert breakpoint at entry if set, and start or restart the program.
|
||||||
* Note that restart does not apply to remote or attach sessions.
|
* 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, boolean restart, final RequestMonitor requestMonitor) {
|
protected void startOrRestart(final GdbLaunch launch, 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()) {
|
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
|
// 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.
|
// 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();
|
requestMonitor.done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DsfServicesTracker servicesTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), getSession().getId());
|
// When it is not an attach session, it gets a little more complicated
|
||||||
IMIProcesses procService = servicesTracker.getService(IMIProcesses.class);
|
// so let's use a sequence.
|
||||||
servicesTracker.dispose();
|
getExecutor().execute(new Sequence(getExecutor(), requestMonitor) {
|
||||||
|
IContainerDMContext fContainerDmc;
|
||||||
|
MICommand<MIInfo> fExecCommand;
|
||||||
|
String fUserStopSymbol = null;
|
||||||
|
|
||||||
|
MIBreakpoint fUserBreakpoint = null;
|
||||||
|
boolean fUserBreakpointIsOnMain = false;
|
||||||
|
|
||||||
|
Step[] fSteps = new Step[] {
|
||||||
|
/*
|
||||||
|
* Figure out if we should use 'exec-continue' or '-exec-run'.
|
||||||
|
*/
|
||||||
|
new Step() {
|
||||||
|
@Override
|
||||||
|
public void execute(RequestMonitor rm) {
|
||||||
|
IMIProcesses procService = getServicesTracker().getService(IMIProcesses.class);
|
||||||
IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, MIProcesses.UNIQUE_GROUP_ID);
|
IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, MIProcesses.UNIQUE_GROUP_ID);
|
||||||
final IContainerDMContext containerDmc = procService.createContainerContext(procDmc, MIProcesses.UNIQUE_GROUP_ID);
|
fContainerDmc = procService.createContainerContext(procDmc, MIProcesses.UNIQUE_GROUP_ID);
|
||||||
|
|
||||||
final MICommand<MIInfo> execCommand;
|
|
||||||
if (fMIBackend.getSessionType() == SessionType.REMOTE) {
|
if (fMIBackend.getSessionType() == SessionType.REMOTE) {
|
||||||
|
// Restart does not apply to remote sessions
|
||||||
|
//
|
||||||
// When doing remote debugging, we use -exec-continue instead of -exec-run
|
// When doing remote debugging, we use -exec-continue instead of -exec-run
|
||||||
execCommand = new MIExecContinue(containerDmc);
|
fExecCommand = new MIExecContinue(fContainerDmc);
|
||||||
} else {
|
} else {
|
||||||
execCommand = new MIExecRun(containerDmc, new String[0]);
|
fExecCommand = new MIExecRun(fContainerDmc, new String[0]);
|
||||||
}
|
}
|
||||||
|
rm.done();
|
||||||
boolean stopInMain = false;
|
}},
|
||||||
|
/*
|
||||||
|
* 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 {
|
try {
|
||||||
stopInMain = launch.getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false );
|
userRequestedStop = launch.getLaunchConfiguration().getAttribute(
|
||||||
|
ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN,
|
||||||
|
false);
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve stop at entry point boolean", e)); //$NON-NLS-1$
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve stop at entry point boolean", e)); //$NON-NLS-1$
|
||||||
requestMonitor.done();
|
rm.done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final DataRequestMonitor<MIInfo> execMonitor = new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
|
if (userRequestedStop) {
|
||||||
|
try {
|
||||||
|
fUserStopSymbol = 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(new MIBreakInsert(fControlDmc, true, false, null, 0, fUserStopSymbol, 0),
|
||||||
|
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), rm) {
|
||||||
@Override
|
@Override
|
||||||
public void handleSuccess() {
|
public void handleSuccess() {
|
||||||
DsfServicesTracker servicesTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), getSession().getId());
|
if (getData() != null) {
|
||||||
GDBRunControl_7_0 reverseService = servicesTracker.getService(GDBRunControl_7_0.class);
|
MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
|
||||||
servicesTracker.dispose();
|
if (breakpoints.length > 0) {
|
||||||
|
fUserBreakpoint = breakpoints[0];
|
||||||
if (reverseService != null) {
|
|
||||||
// When starting or restarting a program, reverse mode is automatically disabled
|
|
||||||
reverseService.setReverseModeEnabled(false);
|
|
||||||
}
|
}
|
||||||
requestMonitor.done();
|
|
||||||
}
|
}
|
||||||
};
|
rm.done();
|
||||||
|
|
||||||
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(
|
|
||||||
new MIBreakInsert(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);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} 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(new MIBreakInsert(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.
|
||||||
|
*/
|
||||||
|
new Step() {
|
||||||
|
@Override
|
||||||
|
public void execute(RequestMonitor rm) {
|
||||||
|
queueCommand(fExecCommand, 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(new MIExecContinue(fContainerDmc),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||||
|
} else {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Step[] getSteps() {
|
||||||
|
return fSteps;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue