diff --git a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/GDBJtagDSFFinalLaunchSequence.java b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/GDBJtagDSFFinalLaunchSequence.java index fefbbb15019..3e2b4a02130 100644 --- a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/GDBJtagDSFFinalLaunchSequence.java +++ b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/GDBJtagDSFFinalLaunchSequence.java @@ -11,7 +11,8 @@ * Sage Electronic Engineering, LLC - bug 305943 * - API generalization to become transport-independent (allow * connections via serial ports and pipes). - * John Dallaway - Wrong groupId during initialization (Bug 349736) + * John Dallaway - Wrong groupId during initialization (Bug 349736) + * Marc Khouzam (Ericsson) - Updated to extend FinalLaunchSequence instead of copying it (bug 324101) *******************************************************************************/ package org.eclipse.cdt.debug.gdbjtag.core; @@ -23,28 +24,29 @@ package org.eclipse.cdt.debug.gdbjtag.core; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Properties; import org.eclipse.cdt.debug.core.CDebugUtils; +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.debug.gdbjtag.core.jtagdevice.GDBJtagDeviceContribution; import org.eclipse.cdt.debug.gdbjtag.core.jtagdevice.GDBJtagDeviceContributionFactory; import org.eclipse.cdt.debug.gdbjtag.core.jtagdevice.IGDBJtagDevice; import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; 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.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress; -import org.eclipse.cdt.dsf.concurrent.Sequence; import org.eclipse.cdt.dsf.datamodel.DMContexts; -import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent; import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; -import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; +import org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence; import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; -import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages; -import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils; import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; import org.eclipse.cdt.dsf.gdb.service.SessionType; import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; @@ -52,16 +54,16 @@ import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext; import org.eclipse.cdt.dsf.mi.service.IMIProcesses; import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager; import org.eclipse.cdt.dsf.mi.service.MIProcesses; -import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; import org.eclipse.cdt.dsf.mi.service.command.commands.CLICommand; 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.cdt.utils.CommandLineUtil; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.variables.VariablesPlugin; -import org.eclipse.debug.core.ILaunchConfiguration; /** * The final launch sequence for the Jtag hardware debugging using the @@ -75,711 +77,542 @@ import org.eclipse.debug.core.ILaunchConfiguration; *

* @since 7.0 */ -public class GDBJtagDSFFinalLaunchSequence extends Sequence { +public class GDBJtagDSFFinalLaunchSequence extends FinalLaunchSequence { /** utility method; cuts down on clutter */ private void queueCommands(List commands, RequestMonitor rm) { if (!commands.isEmpty()) { fCommandControl.queueCommand( - new CLICommand(fCommandControl.getContext(), composeCommand(commands)), - new DataRequestMonitor(getExecutor(), rm)); + new CLICommand(fCommandControl.getContext(), composeCommand(commands)), + new DataRequestMonitor(getExecutor(), rm)); } else { rm.done(); } } - private Step[] fSteps = new Step[] { - /* - * Create the service tracker for later use - */ - new Step() { - @Override - public void execute(RequestMonitor requestMonitor) { - fTracker = new DsfServicesTracker(Activator.getBundleContext(), fLaunch.getSession().getId()); - requestMonitor.done(); - } - @Override - public void rollBack(RequestMonitor requestMonitor) { - if (fTracker != null) fTracker.dispose(); - fTracker = null; - requestMonitor.done(); - }}, - /* - * Fetch the GDBBackend service for later use - */ - new Step() { - @Override - public void execute(RequestMonitor requestMonitor) { - fGDBBackend = fTracker.getService(IGDBBackend.class); - if (fGDBBackend == null) { - requestMonitor.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot obtain GDBBackend service", null)); //$NON-NLS-1$ - } + // The launchConfiguration attributes + private Map fAttributes; - requestMonitor.done(); - }}, - /* - * Fetch the control service for later use - */ - new Step() { - @Override - public void execute(RequestMonitor requestMonitor) { - fCommandControl = fTracker.getService(IGDBControl.class); - if (fCommandControl == null) { - requestMonitor.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot obtain control service", null)); //$NON-NLS-1$ - } - else { - fCommandFactory = fCommandControl.getCommandFactory(); - } - - requestMonitor.done(); - }}, - /* - * Fetch the process service for later use - */ - new Step() { - @Override - public void execute(RequestMonitor requestMonitor) { - fProcService = fTracker.getService(IMIProcesses.class); - if (fProcService == null) { - requestMonitor.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot obtain process service", null)); //$NON-NLS-1$ - } + private DsfSession fSession; - requestMonitor.done(); - }}, - /* - * Specify GDB's working directory - */ - new Step() { - @Override - public void execute(final RequestMonitor requestMonitor) { - IPath dir = null; - try { - dir = fGDBBackend.getGDBWorkingDirectory(); - } catch (CoreException e) { - requestMonitor.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot get working directory", e)); //$NON-NLS-1$ - requestMonitor.done(); - return; - } + private IGDBControl fCommandControl; + private IGDBBackend fGDBBackend; + private IMIProcesses fProcService; + private IGDBJtagDevice fGdbJtagDevice; - if (dir != null) { - fCommandControl.queueCommand( - fCommandFactory.createMIEnvironmentCD(fCommandControl.getContext(), dir.toPortableString()), - new DataRequestMonitor(getExecutor(), requestMonitor)); - } else { - requestMonitor.done(); - } - }}, - /* - * Source the gdbinit file specified in the launch - */ - new Step() { - @Override - public void execute(final RequestMonitor requestMonitor) { - try { - final String gdbinitFile = fGDBBackend.getGDBInitFile(); - - if (gdbinitFile != null && gdbinitFile.length() > 0) { - fCommandControl.queueCommand( - fCommandFactory.createCLISource(fCommandControl.getContext(), gdbinitFile), - new DataRequestMonitor(getExecutor(), requestMonitor) { - @Override - protected void handleCompleted() { - // If the gdbinitFile is the default, then it may not exist and we - // should not consider this an error. - // If it is not the default, then the user must have specified it and - // we want to warn the user if we can't find it. - if (!gdbinitFile.equals(IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT )) { - requestMonitor.setStatus(getStatus()); - } - requestMonitor.done(); - } - }); - } else { - requestMonitor.done(); - } - } catch (CoreException e) { - requestMonitor.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot get gdbinit option", e)); //$NON-NLS-1$ - requestMonitor.done(); - } - }}, - /* - * Specify the arguments to the executable file - */ - new Step() { - @Override - public void execute(final RequestMonitor requestMonitor) { - try { - String args = fGDBBackend.getProgramArguments(); - - if (args != null) { - String[] argArray = args.replaceAll("\n", " ").split(" "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - IMIContainerDMContext containerDmc = fProcService.createContainerContextFromGroupId(fCommandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID); - fCommandControl.queueCommand( - fCommandFactory.createMIGDBSetArgs(containerDmc, argArray), - new DataRequestMonitor(getExecutor(), requestMonitor)); - } else { - requestMonitor.done(); - } - } catch (CoreException e) { - requestMonitor.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot get inferior arguments", e)); //$NON-NLS-1$ - requestMonitor.done(); - } - }}, - /* - * Specify environment variables if needed - */ - new Step() { - @Override - public void execute(final RequestMonitor requestMonitor) { - boolean clear = false; - Properties properties = new Properties(); - try { - clear = fGDBBackend.getClearEnvironment(); - properties = fGDBBackend.getEnvironmentVariables(); - } catch (CoreException e) { - requestMonitor.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot get environment information", e)); //$NON-NLS-1$ - requestMonitor.done(); - return; - } - - if (clear == true || properties.size() > 0) { - fCommandControl.setEnvironment(properties, clear, requestMonitor); - } else { - requestMonitor.done(); - } - }}, - /* - * Enable non-stop mode if necessary - */ - new Step() { - @Override - public void execute(final RequestMonitor requestMonitor) { - boolean isNonStop = false; - try { - isNonStop = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP, - LaunchUtils.getIsNonStopModeDefault()); - } catch (CoreException e) { - } - - // 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. - if (isNonStop) { - // The raw commands should not be necessary in the official GDB release - fCommandControl.queueCommand( - fCommandFactory.createMIGDBSetTargetAsync(fCommandControl.getContext(), true), - new DataRequestMonitor(getExecutor(), requestMonitor) { - @Override - protected void handleSuccess() { - fCommandControl.queueCommand( - fCommandFactory.createMIGDBSetPagination(fCommandControl.getContext(), false), - new DataRequestMonitor(getExecutor(), requestMonitor) { - @Override - protected void handleSuccess() { - fCommandControl.queueCommand( - fCommandFactory.createMIGDBSetNonStop(fCommandControl.getContext(), true), - new DataRequestMonitor(getExecutor(), requestMonitor)); - } - }); - } - }); - } else { - requestMonitor.done(); - } - }}, - /* - * Tell GDB to automatically load or not the shared library symbols - */ - new Step() { - @Override - public void execute(RequestMonitor requestMonitor) { - try { - boolean autolib = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB, - IGDBLaunchConfigurationConstants.DEBUGGER_AUTO_SOLIB_DEFAULT); - fCommandControl.queueCommand( - fCommandFactory.createMIGDBSetAutoSolib(fCommandControl.getContext(), autolib), - new DataRequestMonitor(getExecutor(), requestMonitor)); - } catch (CoreException e) { - requestMonitor.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot set shared library option", e)); //$NON-NLS-1$ - requestMonitor.done(); - } - }}, - /* - * Set the shared library paths - */ - new Step() { - @Override - public void execute(final RequestMonitor requestMonitor) { - try { - List p = fGDBBackend.getSharedLibraryPaths(); - - if (p.size() > 0) { - String[] paths = p.toArray(new String[p.size()]); - fCommandControl.queueCommand( - fCommandFactory.createMIGDBSetSolibSearchPath(fCommandControl.getContext(), paths), - new DataRequestMonitor(getExecutor(), requestMonitor) { - @Override - protected void handleSuccess() { - // Sysroot is not available in GDB6.6 and will make the launch fail in that case. - // Let's remove it for now - requestMonitor.done(); -// // If we are able to set the solib-search-path, -// // we should disable the sysroot variable, as indicated -// // in the GDB documentation. This is to avoid the sysroot -// // variable finding libraries that were not meant to be found. -// fCommandControl.queueCommand( -// new MIGDBSetSysroot(fCommandControl.getContext()), -// new DataRequestMonitor(getExecutor(), requestMonitor)); - }; - }); - } else { - requestMonitor.done(); - } - } catch (CoreException e) { - requestMonitor.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot set share library paths", e)); //$NON-NLS-1$ - requestMonitor.done(); - } - }}, - -// -environment-directory with a lot of paths could -// make setting breakpoint incredibly slow, which makes -// the debug session un-workable. We simply stop -// using it because it's usefulness is unclear. -// Bug 225805 -// /* -// * Setup the source paths -// */ -// new Step() { -// @Override -// public void execute(RequestMonitor requestMonitor) { -// CSourceLookup sourceLookup = fTracker.getService(CSourceLookup.class); -// CSourceLookupDirector locator = (CSourceLookupDirector)fLaunch.getSourceLocator(); -// ISourceLookupDMContext sourceLookupDmc = (ISourceLookupDMContext)fCommandControl.getContext(); -// -// sourceLookup.setSourceLookupPath(sourceLookupDmc, locator.getSourceContainers(), requestMonitor); -// }}, - - // Below steps are specific to JTag hardware debugging - - /* - * Retrieve the IGDBJtagDevice instance - */ - new Step() { - @Override - public void execute(RequestMonitor rm) { - Exception exception = null; - try { - fGdbJtagDevice = getGDBJtagDevice(fLaunch.getLaunchConfiguration()); - } catch (NullPointerException e) { - exception = e; - } catch (CoreException e) { - exception = e; - } - if (fGdbJtagDevice == null) { - // Abort the launch - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot get Jtag device", exception)); //$NON-NLS-1$ - } - rm.done(); - }}, - /* - * Execute symbol loading - */ - new Step() { - @Override - public void execute(RequestMonitor rm) { - ILaunchConfiguration config = fLaunch.getLaunchConfiguration(); - try { - if (config.getAttribute(IGDBJtagConstants.ATTR_LOAD_SYMBOLS, IGDBJtagConstants.DEFAULT_LOAD_SYMBOLS)) { - String symbolsFileName = null; - - // New setting in Helios. Default is true. Check for existence - // in order to support older launch configs - if (config.hasAttribute(IGDBJtagConstants.ATTR_USE_PROJ_BINARY_FOR_SYMBOLS) && - config.getAttribute(IGDBJtagConstants.ATTR_USE_PROJ_BINARY_FOR_SYMBOLS, IGDBJtagConstants.DEFAULT_USE_PROJ_BINARY_FOR_SYMBOLS)) { - IPath programFile = CDebugUtils.verifyProgramPath(config); - if (programFile != null) { - symbolsFileName = programFile.toOSString(); - } - } - else { - symbolsFileName = config.getAttribute(IGDBJtagConstants.ATTR_SYMBOLS_FILE_NAME, IGDBJtagConstants.DEFAULT_SYMBOLS_FILE_NAME); - if (symbolsFileName.length() > 0) { - symbolsFileName = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(symbolsFileName); - } else { - symbolsFileName = null; - } - } - - if (symbolsFileName == null) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, Messages.getString("GDBJtagDebugger.err_no_img_file"), null)); //$NON-NLS-1$ - rm.done(); - return; - } - - // Escape windows path separator characters TWICE, once for Java and once for GDB. - symbolsFileName = symbolsFileName.replace("\\", "\\\\"); //$NON-NLS-1$ //$NON-NLS-2$ - - String symbolsOffset = config.getAttribute(IGDBJtagConstants.ATTR_SYMBOLS_OFFSET, IGDBJtagConstants.DEFAULT_SYMBOLS_OFFSET); - if (symbolsOffset.length() > 0) { - symbolsOffset = "0x" + symbolsOffset; - } - List commands = new ArrayList(); - fGdbJtagDevice.doLoadSymbol(symbolsFileName, symbolsOffset, commands); - queueCommands(commands, rm); - - } else { - rm.done(); - } - } catch (CoreException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot load symbol", e)); //$NON-NLS-1$ - rm.done(); - } - }}, - - /* - * Hook up to remote target - */ - new Step() { - @SuppressWarnings("deprecation") - @Override - public void execute(RequestMonitor rm) { - ILaunchConfiguration config = fLaunch.getLaunchConfiguration(); - try { - if (config.getAttribute(IGDBJtagConstants.ATTR_USE_REMOTE_TARGET, IGDBJtagConstants.DEFAULT_USE_REMOTE_TARGET)) { - List commands = new ArrayList(); - if (fGdbJtagDevice instanceof IGDBJtagConnection) { - URI uri = new URI(config.getAttribute(IGDBJtagConstants.ATTR_CONNECTION, IGDBJtagConstants.DEFAULT_CONNECTION)); - IGDBJtagConnection device = (IGDBJtagConnection)fGdbJtagDevice; - device.doRemote(uri.getSchemeSpecificPart(), commands); - } else { - // Handle legacy network device contributions that don't understand URIs - String ipAddress = config.getAttribute(IGDBJtagConstants.ATTR_IP_ADDRESS, IGDBJtagConstants.DEFAULT_IP_ADDRESS); - int portNumber = config.getAttribute(IGDBJtagConstants.ATTR_PORT_NUMBER, IGDBJtagConstants.DEFAULT_PORT_NUMBER); - fGdbJtagDevice.doRemote(ipAddress, portNumber, commands); - } - queueCommands(commands, rm); - } else { - rm.done(); - } - } catch (CoreException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot connect to remote target", e)); //$NON-NLS-1$ - rm.done(); - } catch (URISyntaxException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Invalid remote target connection syntax", e)); //$NON-NLS-1$ - rm.done(); - } - }}, - /* - * Run device-specific code to reset the board - */ - new Step() { - @Override - public void execute(RequestMonitor rm) { - ILaunchConfiguration config = fLaunch.getLaunchConfiguration(); - try { - if (config.getAttribute(IGDBJtagConstants.ATTR_DO_RESET, IGDBJtagConstants.DEFAULT_DO_RESET)) { - List commands = new ArrayList(); - fGdbJtagDevice.doReset(commands); - queueCommands(commands, rm); - } else { - rm.done(); - } - } catch (CoreException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot reset the remote target", e)); //$NON-NLS-1$ - rm.done(); - } - }}, - /* - * Run device-specific code to delay the startup - */ - new Step() { - @Override - public void execute(RequestMonitor rm) { - ILaunchConfiguration config = fLaunch.getLaunchConfiguration(); - int defaultDelay = fGdbJtagDevice.getDefaultDelay(); - try { - List commands = new ArrayList(); - fGdbJtagDevice.doDelay(config.getAttribute(IGDBJtagConstants.ATTR_DELAY, defaultDelay), commands); - queueCommands(commands, rm); - } catch (CoreException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot delay the remote target", e)); //$NON-NLS-1$ - rm.done(); - } - }}, - /* - * Run device-specific code to halt the board - */ - new Step() { - @Override - public void execute(RequestMonitor rm) { - ILaunchConfiguration config = fLaunch.getLaunchConfiguration(); - try { - if (config.getAttribute(IGDBJtagConstants.ATTR_DO_HALT, IGDBJtagConstants.DEFAULT_DO_HALT)) { - List commands = new ArrayList(); - fGdbJtagDevice.doHalt(commands); - queueCommands(commands, rm); - } else { - rm.done(); - } - } catch (CoreException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot halt the remote target", e)); //$NON-NLS-1$ - rm.done(); - } - }}, - /* - * Execute any user defined init commands - */ - new Step() { - @Override - public void execute(RequestMonitor rm) { - ILaunchConfiguration config = fLaunch.getLaunchConfiguration(); - try { - String userCmd = config.getAttribute(IGDBJtagConstants.ATTR_INIT_COMMANDS, IGDBJtagConstants.DEFAULT_INIT_COMMANDS); - userCmd = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(userCmd); - if (userCmd.length() > 0) { - String[] commands = userCmd.split("\\r?\\n"); //$NON-NLS-1$ - - CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm); - crm.setDoneCount(commands.length); - for (int i = 0; i < commands.length; ++i) { - fCommandControl.queueCommand( - new CLICommand(fCommandControl.getContext(), commands[i]), - new DataRequestMonitor(getExecutor(), crm)); - } - } - else { - rm.done(); - } - } catch (CoreException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot run user defined init commands", e)); //$NON-NLS-1$ - rm.done(); - } - }}, - /* - * Execute image loading - */ - new Step() { - @Override - public void execute(RequestMonitor rm) { - ILaunchConfiguration config = fLaunch.getLaunchConfiguration(); - try { - String imageFileName = null; - if (config.getAttribute(IGDBJtagConstants.ATTR_LOAD_IMAGE, IGDBJtagConstants.DEFAULT_LOAD_IMAGE)) { - // New setting in Helios. Default is true. Check for existence - // in order to support older launch configs - if (config.hasAttribute(IGDBJtagConstants.ATTR_USE_PROJ_BINARY_FOR_IMAGE) && - config.getAttribute(IGDBJtagConstants.ATTR_USE_PROJ_BINARY_FOR_IMAGE, IGDBJtagConstants.DEFAULT_USE_PROJ_BINARY_FOR_IMAGE)) { - IPath programFile = CDebugUtils.verifyProgramPath(config); - if (programFile != null) { - imageFileName = programFile.toOSString(); - } - } - else { - imageFileName = config.getAttribute(IGDBJtagConstants.ATTR_IMAGE_FILE_NAME, IGDBJtagConstants.DEFAULT_IMAGE_FILE_NAME); - if (imageFileName.length() > 0) { - imageFileName = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(imageFileName); - } else { - imageFileName = null; - } - } - - if (imageFileName == null) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, Messages.getString("GDBJtagDebugger.err_no_img_file"), null)); //$NON-NLS-1$ - rm.done(); - return; - } - - // Escape windows path separator characters TWICE, once for Java and once for GDB. - imageFileName = imageFileName.replace("\\", "\\\\"); //$NON-NLS-1$ //$NON-NLS-2$ - - String imageOffset = config.getAttribute(IGDBJtagConstants.ATTR_IMAGE_OFFSET, IGDBJtagConstants.DEFAULT_IMAGE_OFFSET); - if (imageOffset.length() > 0) { - imageOffset = (imageFileName.endsWith(".elf")) ? "" : "0x" + config.getAttribute(IGDBJtagConstants.ATTR_IMAGE_OFFSET, IGDBJtagConstants.DEFAULT_IMAGE_OFFSET); //$NON-NLS-2$ - } - List commands = new ArrayList(); - fGdbJtagDevice.doLoadImage(imageFileName, imageOffset, commands); - queueCommands(commands, rm); - } - else { - rm.done(); - } - } catch (CoreException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot load image", e)); //$NON-NLS-1$ - rm.done(); - } - }}, - /* - * Start tracking the breakpoints once we know we are connected to the target (necessary for remote debugging) - */ - new Step() { - @Override - public void execute(final RequestMonitor requestMonitor) { - if (fSessionType != SessionType.CORE) { - MIBreakpointsManager bpmService = fTracker.getService(MIBreakpointsManager.class); - IMIContainerDMContext containerDmc = fProcService.createContainerContextFromGroupId(fCommandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID); - IBreakpointsTargetDMContext bpTargetDmc = DMContexts.getAncestorOfType(containerDmc, IBreakpointsTargetDMContext.class); + private DsfServicesTracker fTracker; + private IMIContainerDMContext fContainerCtx; - bpmService.startTrackingBreakpoints(bpTargetDmc, requestMonitor); - } else { - requestMonitor.done(); - } - }}, - /* - * Set the program counter - */ - new Step() { - @Override - public void execute(RequestMonitor rm) { - ILaunchConfiguration config = fLaunch.getLaunchConfiguration(); - try { - if (config.getAttribute(IGDBJtagConstants.ATTR_SET_PC_REGISTER, IGDBJtagConstants.DEFAULT_SET_PC_REGISTER)) { - String pcRegister = config.getAttribute(IGDBJtagConstants.ATTR_PC_REGISTER, config.getAttribute(IGDBJtagConstants.ATTR_IMAGE_OFFSET, IGDBJtagConstants.DEFAULT_PC_REGISTER)); - List commands = new ArrayList(); - fGdbJtagDevice.doSetPC(pcRegister, commands); - queueCommands(commands, rm); - } else { - rm.done(); + /** + * @since 8.2 + */ + public GDBJtagDSFFinalLaunchSequence(DsfSession session, Map attributes, RequestMonitorWithProgress rm) { + super(session, attributes, rm); + fSession = session; + fAttributes = attributes; + } + + public GDBJtagDSFFinalLaunchSequence(DsfExecutor executor, GdbLaunch launch, SessionType sessionType, boolean attach, RequestMonitorWithProgress rm) { + this(launch.getSession(), getAttributes(launch), rm); + } + + @SuppressWarnings("unchecked") + private static Map getAttributes(GdbLaunch launch) { + try { + return launch.getLaunchConfiguration().getAttributes(); + } catch (CoreException e) { + } + return new HashMap(); + } + + /** @since 8.2 */ + protected IMIContainerDMContext getContainerContext() { + return fContainerCtx; + } + + /** @since 8.2 */ + protected void setContainerContext(IMIContainerDMContext ctx) { + fContainerCtx = ctx; + } + + /** @since 8.2 */ + protected static final String GROUP_JTAG = "GROUP_JTAG"; + + @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 orderList = new ArrayList(Arrays.asList(super.getExecutionOrder(GROUP_TOP_LEVEL))); + + // First, remove all steps of the base class that we don't want to use. + orderList.removeAll(Arrays.asList(new String[] { + "stepNewProcess", //$NON-NLS-1$ + })); + + // Now insert our steps before the data model initialized event is sent + orderList.add(orderList.indexOf("stepDataModelInitializationComplete"), GROUP_JTAG); + + return orderList.toArray(new String[orderList.size()]); + } + + // Finally, deal with our groups and their steps. + if (GROUP_JTAG.equals(group)) { + return new String[] { + "stepInitializeJTAGFinalLaunchSequence", + "stepRetrieveJTAGDevice", //$NON-NLS-1$ + "stepLoadSymbols", //$NON-NLS-1$ + "stepConnectToTarget", //$NON-NLS-1$ + "stepResetBoard", //$NON-NLS-1$ + "stepDelayStartup", //$NON-NLS-1$ + "stepHaltBoard", //$NON-NLS-1$ + "stepUserInitCommands", //$NON-NLS-1$ + "stepLoadImage", //$NON-NLS-1$ + + "stepUpdateContainer", //$NON-NLS-1$ + + "stepSetArguments", //$NON-NLS-1$ + "stepSetEnvironmentVariables", //$NON-NLS-1$ + "stepStartTrackingBreakpoints", //$NON-NLS-1$ + + "stepSetProgramCounter", //$NON-NLS-1$ + "stepStopScript", //$NON-NLS-1$ + "stepResumeScript", //$NON-NLS-1$ + "stepUserDebugCommands", //$NON-NLS-1$ + "stepJTAGCleanup", //$NON-NLS-1$ + }; + } + + // For any subgroups of the base class + return super.getExecutionOrder(group); + } + + /** + * Initialize the members of the class. + * This step is mandatory for the rest of the sequence to complete. + * @since 8.2 + */ + @Execute + public void stepInitializeJTAGFinalLaunchSequence(RequestMonitor rm) { + fTracker = new DsfServicesTracker(Activator.getBundleContext(), fSession.getId()); + fGDBBackend = fTracker.getService(IGDBBackend.class); + if (fGDBBackend == null) { + rm.done(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot obtain GDBBackend service", null)); //$NON-NLS-1$ + return; + } + + fCommandControl = fTracker.getService(IGDBControl.class); + if (fCommandControl == null) { + rm.done(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot obtain control service", null)); //$NON-NLS-1$ + return; + } + + fProcService = fTracker.getService(IMIProcesses.class); + if (fProcService == null) { + rm.done(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot obtain process service", null)); //$NON-NLS-1$ + return; + } + + // When we are starting to debug a new process, the container is the default process used by GDB. + // We don't have a pid yet, so we can simply create the container with the UNIQUE_GROUP_ID + setContainerContext(fProcService.createContainerContextFromGroupId(fCommandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID)); + + rm.done(); + } + + /** + * Rollback method for {@link #stepInitializeJTAGFinalLaunchSequence()} + * @since 4.0 + */ + @RollBack("stepInitializeJTAGFinalLaunchSequence") + public void rollBackInitializeFinalLaunchSequence(RequestMonitor rm) { + if (fTracker != null) fTracker.dispose(); + fTracker = null; + rm.done(); + } + + /* + * Retrieve the IGDBJtagDevice instance + */ + /** @since 8.2 */ + @Execute + public void stepRetrieveJTAGDevice(final RequestMonitor rm) { + Exception exception = null; + try { + fGdbJtagDevice = getGDBJtagDevice(); + } catch (NullPointerException e) { + exception = e; + } + if (fGdbJtagDevice == null) { + // Abort the launch + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot get Jtag device", exception)); //$NON-NLS-1$ + } + rm.done(); + } + + /* + * Execute symbol loading + */ + /** @since 8.2 */ + @Execute + public void stepLoadSymbols(final RequestMonitor rm) { + try { + if (CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_LOAD_SYMBOLS, IGDBJtagConstants.DEFAULT_LOAD_SYMBOLS)) { + String symbolsFileName = null; + + // New setting in Helios. Default is true. Check for existence + // in order to support older launch configs + if (fAttributes.containsKey(IGDBJtagConstants.ATTR_USE_PROJ_BINARY_FOR_SYMBOLS) && + CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_USE_PROJ_BINARY_FOR_SYMBOLS, IGDBJtagConstants.DEFAULT_USE_PROJ_BINARY_FOR_SYMBOLS)) { + IPath programFile = fGDBBackend.getProgramPath(); + if (programFile != null) { + symbolsFileName = programFile.toOSString(); } - } catch (CoreException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot set program counter", e)); //$NON-NLS-1$ - rm.done(); } - }}, - /* - * Execute the stop script - */ - new Step() { - @Override - public void execute(RequestMonitor rm) { - ILaunchConfiguration config = fLaunch.getLaunchConfiguration(); - try { - if (config.getAttribute(IGDBJtagConstants.ATTR_SET_STOP_AT, IGDBJtagConstants.DEFAULT_SET_STOP_AT)) { - String stopAt = config.getAttribute(IGDBJtagConstants.ATTR_STOP_AT, IGDBJtagConstants.DEFAULT_STOP_AT); - List commands = new ArrayList(); - fGdbJtagDevice.doStopAt(stopAt, commands); - queueCommands(commands, rm); + else { + symbolsFileName = CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_SYMBOLS_FILE_NAME, IGDBJtagConstants.DEFAULT_SYMBOLS_FILE_NAME); + if (symbolsFileName.length() > 0) { + symbolsFileName = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(symbolsFileName); } else { - rm.done(); + symbolsFileName = null; } - } catch (CoreException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot run the stop script", e)); //$NON-NLS-1$ - rm.done(); + } + + if (symbolsFileName == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, Messages.getString("GDBJtagDebugger.err_no_img_file"), null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // Escape windows path separator characters TWICE, once for Java and once for GDB. + symbolsFileName = symbolsFileName.replace("\\", "\\\\"); //$NON-NLS-1$ //$NON-NLS-2$ + + String symbolsOffset = CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_SYMBOLS_OFFSET, IGDBJtagConstants.DEFAULT_SYMBOLS_OFFSET); + if (symbolsOffset.length() > 0) { + symbolsOffset = "0x" + symbolsOffset; + } + List commands = new ArrayList(); + fGdbJtagDevice.doLoadSymbol(symbolsFileName, symbolsOffset, commands); + queueCommands(commands, rm); + + } else { + rm.done(); + } + } catch (CoreException e) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot load symbol", e)); //$NON-NLS-1$ + rm.done(); + } + } + + /* + * Hook up to remote target + */ + /** @since 8.2 */ + @SuppressWarnings("deprecation") + @Execute + public void stepConnectToTarget(final RequestMonitor rm) { + try { + if (CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_USE_REMOTE_TARGET, IGDBJtagConstants.DEFAULT_USE_REMOTE_TARGET)) { + List commands = new ArrayList(); + if (fGdbJtagDevice instanceof IGDBJtagConnection) { + URI uri = new URI(CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_CONNECTION, IGDBJtagConstants.DEFAULT_CONNECTION)); + IGDBJtagConnection device = (IGDBJtagConnection)fGdbJtagDevice; + device.doRemote(uri.getSchemeSpecificPart(), commands); + } else { + // Handle legacy network device contributions that don't understand URIs + String ipAddress = CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_IP_ADDRESS, IGDBJtagConstants.DEFAULT_IP_ADDRESS); + int portNumber = CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_PORT_NUMBER, IGDBJtagConstants.DEFAULT_PORT_NUMBER); + fGdbJtagDevice.doRemote(ipAddress, portNumber, commands); + } + queueCommands(commands, rm); + } else { + rm.done(); + } + } catch (URISyntaxException e) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Invalid remote target connection syntax", e)); //$NON-NLS-1$ + rm.done(); + } + } + + /* + * Run device-specific code to reset the board + */ + /** @since 8.2 */ + @Execute + public void stepResetBoard(final RequestMonitor rm) { + if (CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_DO_RESET, IGDBJtagConstants.DEFAULT_DO_RESET)) { + List commands = new ArrayList(); + fGdbJtagDevice.doReset(commands); + queueCommands(commands, rm); + } else { + rm.done(); + } + } + + /* + * Run device-specific code to delay the startup + */ + /** @since 8.2 */ + @Execute + public void stepDelayStartup(final RequestMonitor rm) { + int defaultDelay = fGdbJtagDevice.getDefaultDelay(); + List commands = new ArrayList(); + fGdbJtagDevice.doDelay(CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_DELAY, defaultDelay), commands); + queueCommands(commands, rm); + } + + /* + * Run device-specific code to halt the board + */ + /** @since 8.2 */ + @Execute + public void stepHaltBoard(final RequestMonitor rm) { + if (CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_DO_HALT, IGDBJtagConstants.DEFAULT_DO_HALT)) { + List commands = new ArrayList(); + fGdbJtagDevice.doHalt(commands); + queueCommands(commands, rm); + } else { + rm.done(); + } + } + + /* + * Execute any user defined init commands + */ + /** @since 8.2 */ + @Execute + public void stepUserInitCommands(final RequestMonitor rm) { + try { + String userCmd = CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_INIT_COMMANDS, IGDBJtagConstants.DEFAULT_INIT_COMMANDS); + userCmd = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(userCmd); + if (userCmd.length() > 0) { + String[] commands = userCmd.split("\\r?\\n"); //$NON-NLS-1$ + + CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm); + crm.setDoneCount(commands.length); + for (int i = 0; i < commands.length; ++i) { + fCommandControl.queueCommand( + new CLICommand(fCommandControl.getContext(), commands[i]), + new DataRequestMonitor(getExecutor(), crm)); } } - }, - /* - * Execute the resume script - */ - new Step() { - @Override - public void execute(RequestMonitor rm) { - ILaunchConfiguration config = fLaunch.getLaunchConfiguration(); - try { - if (config.getAttribute(IGDBJtagConstants.ATTR_SET_RESUME, IGDBJtagConstants.DEFAULT_SET_RESUME)) { - List commands = new ArrayList(); - fGdbJtagDevice.doContinue(commands); - queueCommands(commands, rm); - } else { - rm.done(); - } - } catch (CoreException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot resume the remote target", e)); //$NON-NLS-1$ - rm.done(); - } - }}, - /* - * Run any user defined commands to start debugging - */ - new Step() { - @Override - public void execute(RequestMonitor rm) { - ILaunchConfiguration config = fLaunch.getLaunchConfiguration(); - try { - String userCmd = config.getAttribute(IGDBJtagConstants.ATTR_RUN_COMMANDS, IGDBJtagConstants.DEFAULT_RUN_COMMANDS); - if (userCmd.length() > 0) { - userCmd = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(userCmd); - String[] commands = userCmd.split("\\r?\\n"); //$NON-NLS-1$ - - CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm); - crm.setDoneCount(commands.length); - for (int i = 0; i < commands.length; ++i) { - fCommandControl.queueCommand( - new CLICommand(fCommandControl.getContext(), commands[i]), - new DataRequestMonitor(getExecutor(), crm)); - } - } - else { - rm.done(); - } - } catch (CoreException e) { - rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot run user defined run commands", e)); //$NON-NLS-1$ - rm.done(); - } - }}, - - /* - * Indicate that the Data Model has been filled. This will trigger the Debug view to expand. - */ - new Step() { - @Override - public void execute(final RequestMonitor requestMonitor) { - fLaunch.getSession().dispatchEvent(new DataModelInitializedEvent(fCommandControl.getContext()), - fCommandControl.getProperties()); - requestMonitor.done(); - }}, - /* - * Cleanup - */ - new Step() { - @Override - public void execute(final RequestMonitor requestMonitor) { - fTracker.dispose(); - fTracker = null; - requestMonitor.done(); - }}, - }; - - GdbLaunch fLaunch; - SessionType fSessionType; - boolean fAttach; - - private IGDBControl fCommandControl; - private IGDBBackend fGDBBackend; - private IMIProcesses fProcService; - private CommandFactory fCommandFactory; - private IGDBJtagDevice fGdbJtagDevice; - - DsfServicesTracker fTracker; - - /** - * @since 8.0 - */ - public GDBJtagDSFFinalLaunchSequence(DsfExecutor executor, GdbLaunch launch, SessionType sessionType, boolean attach, RequestMonitorWithProgress rm) { - super(executor, rm, LaunchMessages.getString("FinalLaunchSequence.0"), LaunchMessages.getString("FinalLaunchSequence.1")); //$NON-NLS-1$ //$NON-NLS-2$ - fLaunch = launch; - fSessionType = sessionType; - fAttach = attach; - } + else { + rm.done(); + } + } catch (CoreException e) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot run user defined init commands", e)); //$NON-NLS-1$ + rm.done(); + } + } - /* (non-Javadoc) - * @see org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence#getSteps() + /* + * Execute image loading */ - @Override - public Step[] getSteps() { - return fSteps; + /** @since 8.2 */ + @Execute + public void stepLoadImage(final RequestMonitor rm) { + try { + String imageFileName = null; + if (CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_LOAD_IMAGE, IGDBJtagConstants.DEFAULT_LOAD_IMAGE)) { + // New setting in Helios. Default is true. Check for existence + // in order to support older launch configs + if (fAttributes.containsKey(IGDBJtagConstants.ATTR_USE_PROJ_BINARY_FOR_IMAGE) && + CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_USE_PROJ_BINARY_FOR_IMAGE, IGDBJtagConstants.DEFAULT_USE_PROJ_BINARY_FOR_IMAGE)) { + IPath programFile = fGDBBackend.getProgramPath(); + if (programFile != null) { + imageFileName = programFile.toOSString(); + } + } + else { + imageFileName = CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_IMAGE_FILE_NAME, IGDBJtagConstants.DEFAULT_IMAGE_FILE_NAME); + if (imageFileName.length() > 0) { + imageFileName = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(imageFileName); + } else { + imageFileName = null; + } + } + + if (imageFileName == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, Messages.getString("GDBJtagDebugger.err_no_img_file"), null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // Escape windows path separator characters TWICE, once for Java and once for GDB. + imageFileName = imageFileName.replace("\\", "\\\\"); //$NON-NLS-1$ //$NON-NLS-2$ + + String imageOffset = CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_IMAGE_OFFSET, IGDBJtagConstants.DEFAULT_IMAGE_OFFSET); + if (imageOffset.length() > 0) { + imageOffset = (imageFileName.endsWith(".elf")) ? "" : "0x" + CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_IMAGE_OFFSET, IGDBJtagConstants.DEFAULT_IMAGE_OFFSET); //$NON-NLS-2$ + } + List commands = new ArrayList(); + fGdbJtagDevice.doLoadImage(imageFileName, imageOffset, commands); + queueCommands(commands, rm); + } + else { + rm.done(); + } + } catch (CoreException e) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot load image", e)); //$NON-NLS-1$ + rm.done(); + } } /** - * @param config - * @return IGDBJtagDevice the selected Jtag device - * @throws CoreException - * @throws NullPointerException + * Now that we are connected to the target, we should update + * our container to properly fill in its pid. + * @since 8.2 */ - private IGDBJtagDevice getGDBJtagDevice (ILaunchConfiguration config) - throws CoreException, NullPointerException { + @Execute + public void stepUpdateContainer(RequestMonitor rm) { + String groupId = getContainerContext().getGroupId(); + setContainerContext(fProcService.createContainerContextFromGroupId(fCommandControl.getContext(), groupId)); + rm.done(); + } + + /** + * Specify the arguments to the program that will be run. + * @since 8.2 + */ + @Execute + public void stepSetArguments(RequestMonitor rm) { + try { + String args = CDebugUtils.getAttribute( + fAttributes, + ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, + ""); //$NON-NLS-1$ + + if (args.length() != 0) { + args = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(args); + String[] argArray = CommandLineUtil.argumentsToArray(args); + fCommandControl.queueCommand( + fCommandControl.getCommandFactory().createMIGDBSetArgs(getContainerContext(), argArray), + new ImmediateDataRequestMonitor(rm)); + } else { + rm.done(); + } + } catch (CoreException e) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot get inferior arguments", e)); //$NON-NLS-1$ + rm.done(); + } + } + + /** + * Specify environment variables if needed + * @since 8.2 + */ + @Execute + public void stepSetEnvironmentVariables(RequestMonitor rm) { + boolean clear = false; + Properties properties = new Properties(); + try { + // here we need to pass the proper container context + clear = fGDBBackend.getClearEnvironment(); + properties = fGDBBackend.getEnvironmentVariables(); + } catch (CoreException e) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot get environment information", e)); //$NON-NLS-1$ + rm.done(); + return; + } + + if (clear == true || properties.size() > 0) { + fCommandControl.setEnvironment(properties, clear, rm); + } else { + rm.done(); + } + } + + /* + * Start tracking the breakpoints once we know we are connected to the target (necessary for remote debugging) + */ + /** @since 8.2 */ + @Execute + public void stepStartTrackingBreakpoints(final RequestMonitor rm) { + MIBreakpointsManager bpmService = fTracker.getService(MIBreakpointsManager.class); + IBreakpointsTargetDMContext bpTargetDmc = DMContexts.getAncestorOfType(getContainerContext(), IBreakpointsTargetDMContext.class); + bpmService.startTrackingBreakpoints(bpTargetDmc, rm); + } + + /* + * Set the program counter + */ + /** @since 8.2 */ + @Execute + public void stepSetProgramCounter(final RequestMonitor rm) { + if (CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_SET_PC_REGISTER, IGDBJtagConstants.DEFAULT_SET_PC_REGISTER)) { + String pcRegister = CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_PC_REGISTER, CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_IMAGE_OFFSET, IGDBJtagConstants.DEFAULT_PC_REGISTER)); + List commands = new ArrayList(); + fGdbJtagDevice.doSetPC(pcRegister, commands); + queueCommands(commands, rm); + } else { + rm.done(); + } + } + + /* + * Execute the stop script + */ + /** @since 8.2 */ + @Execute + public void stepStopScript(final RequestMonitor rm) { + if (CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_SET_STOP_AT, IGDBJtagConstants.DEFAULT_SET_STOP_AT)) { + String stopAt = CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_STOP_AT, IGDBJtagConstants.DEFAULT_STOP_AT); + List commands = new ArrayList(); + fGdbJtagDevice.doStopAt(stopAt, commands); + queueCommands(commands, rm); + } else { + rm.done(); + } + } + + /* + * Execute the resume script + */ + /** @since 8.2 */ + @Execute + public void stepResumeScript(final RequestMonitor rm) { + if (CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_SET_RESUME, IGDBJtagConstants.DEFAULT_SET_RESUME)) { + List commands = new ArrayList(); + fGdbJtagDevice.doContinue(commands); + queueCommands(commands, rm); + } else { + rm.done(); + } + } + + /* + * Run any user defined commands to start debugging + */ + /** @since 8.2 */ + @Execute + public void stepUserDebugCommands(final RequestMonitor rm) { + try { + String userCmd = CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_RUN_COMMANDS, IGDBJtagConstants.DEFAULT_RUN_COMMANDS); + if (userCmd.length() > 0) { + userCmd = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(userCmd); + String[] commands = userCmd.split("\\r?\\n"); //$NON-NLS-1$ + + CountingRequestMonitor crm = new CountingRequestMonitor(getExecutor(), rm); + crm.setDoneCount(commands.length); + for (int i = 0; i < commands.length; ++i) { + fCommandControl.queueCommand( + new CLICommand(fCommandControl.getContext(), commands[i]), + new DataRequestMonitor(getExecutor(), crm)); + } + } + else { + rm.done(); + } + } catch (CoreException e) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot run user defined run commands", e)); //$NON-NLS-1$ + rm.done(); + } + } + + private IGDBJtagDevice getGDBJtagDevice () { IGDBJtagDevice gdbJtagDevice = null; - String jtagDeviceName = config.getAttribute(IGDBJtagConstants.ATTR_JTAG_DEVICE, IGDBJtagConstants.DEFAULT_JTAG_DEVICE); + String jtagDeviceName = CDebugUtils.getAttribute(fAttributes, IGDBJtagConstants.ATTR_JTAG_DEVICE, IGDBJtagConstants.DEFAULT_JTAG_DEVICE); GDBJtagDeviceContribution[] availableDevices = GDBJtagDeviceContributionFactory.getInstance().getGDBJtagDeviceContribution(); for (GDBJtagDeviceContribution availableDevice : availableDevices) { if (jtagDeviceName.equals(availableDevice.getDeviceName())) { @@ -789,7 +622,7 @@ public class GDBJtagDSFFinalLaunchSequence extends Sequence { } return gdbJtagDevice; } - + /** * @param commands * @return String commands in String format @@ -804,4 +637,15 @@ public class GDBJtagDSFFinalLaunchSequence extends Sequence { } return sb.toString(); } + + /** + * Cleanup now that the sequence has been run. + * @since 8.2 + */ + @Execute + public void stepJTAGCleanup(final RequestMonitor requestMonitor) { + fTracker.dispose(); + fTracker = null; + requestMonitor.done(); + } } diff --git a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/GDBJtagDSFFinalLaunchSequence_7_2.java b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/GDBJtagDSFFinalLaunchSequence_7_2.java new file mode 100644 index 00000000000..1c74ad75df6 --- /dev/null +++ b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/GDBJtagDSFFinalLaunchSequence_7_2.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Khouzam (Ericsson) - initial API and implementation this class is based on + \******************************************************************************/ +package org.eclipse.cdt.debug.gdbjtag.core; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress; +import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses; +import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +/** + * Version for GDB 7.2 and higher. + * @since 8.2 + */ +public class GDBJtagDSFFinalLaunchSequence_7_2 extends GDBJtagDSFFinalLaunchSequence { + + private DsfSession fSession; + + public GDBJtagDSFFinalLaunchSequence_7_2(DsfSession session, Map attributes, RequestMonitorWithProgress rm) { + super(session, attributes, rm); + fSession = session; + } + + @Override + protected String[] getExecutionOrder(String group) { + if (GROUP_JTAG.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 orderList = new ArrayList(Arrays.asList(super.getExecutionOrder(GROUP_JTAG))); + + // Now insert our steps right after the initialization of the base class. + orderList.add(orderList.indexOf("stepInitializeJTAGFinalLaunchSequence") + 1, "stepInitializeJTAGSequence_7_2"); //$NON-NLS-1$ //$NON-NLS-2$ + + return orderList.toArray(new String[orderList.size()]); + } + + return super.getExecutionOrder(group); + } + + /** + * Initialize the members of the DebugNewProcessSequence_7_2 class. + * This step is mandatory for the rest of the sequence to complete. + */ + @Execute + public void stepInitializeJTAGSequence_7_2(RequestMonitor rm) { + DsfServicesTracker tracker = new DsfServicesTracker(Activator.getBundleContext(), fSession.getId()); + IGDBControl gdbControl = tracker.getService(IGDBControl.class); + IGDBProcesses procService = tracker.getService(IGDBProcesses.class); + tracker.dispose(); + + if (gdbControl == null || procService == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot obtain service", null)); //$NON-NLS-1$ + rm.done(); + return; + } + setContainerContext(procService.createContainerContextFromGroupId(gdbControl.getContext(), "i1")); //$NON-NLS-1$ + rm.done(); + } +} diff --git a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl.java b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl.java index e5d24f2f06f..ccb36f2daa8 100644 --- a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl.java +++ b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl.java @@ -15,12 +15,9 @@ import java.util.Map; import org.eclipse.cdt.debug.gdbjtag.core.GDBJtagDSFFinalLaunchSequence; import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress; import org.eclipse.cdt.dsf.concurrent.Sequence; -import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; -import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; import org.eclipse.cdt.dsf.gdb.service.command.GDBControl; import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; import org.eclipse.cdt.dsf.service.DsfSession; -import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; @@ -36,8 +33,6 @@ public class GDBJtagControl extends GDBControl { @Override protected Sequence getCompleteInitializationSequence(Map attributes, RequestMonitorWithProgress rm) { - GdbLaunch launch = (GdbLaunch)getSession().getModelAdapter(ILaunch.class); - IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class); - return new GDBJtagDSFFinalLaunchSequence(getExecutor(), launch, backend.getSessionType(), backend.getIsAttachSession(), rm); + return new GDBJtagDSFFinalLaunchSequence(getSession(), attributes, rm); } } \ No newline at end of file diff --git a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl_7_0.java b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl_7_0.java index b94ea194155..e52a77c7555 100644 --- a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl_7_0.java +++ b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl_7_0.java @@ -15,12 +15,9 @@ import java.util.Map; import org.eclipse.cdt.debug.gdbjtag.core.GDBJtagDSFFinalLaunchSequence; import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress; import org.eclipse.cdt.dsf.concurrent.Sequence; -import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; -import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_0; import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; import org.eclipse.cdt.dsf.service.DsfSession; -import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; @@ -36,8 +33,6 @@ public class GDBJtagControl_7_0 extends GDBControl_7_0 { @Override protected Sequence getCompleteInitializationSequence(Map attributes, RequestMonitorWithProgress rm) { - GdbLaunch launch = (GdbLaunch)getSession().getModelAdapter(ILaunch.class); - IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class); - return new GDBJtagDSFFinalLaunchSequence(getExecutor(), launch, backend.getSessionType(), backend.getIsAttachSession(), rm); + return new GDBJtagDSFFinalLaunchSequence(getSession(), attributes, rm); } } \ No newline at end of file diff --git a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl_7_2.java b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl_7_2.java index 6bf25811c09..4676b77c47f 100644 --- a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl_7_2.java +++ b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl_7_2.java @@ -12,15 +12,12 @@ package org.eclipse.cdt.debug.gdbjtag.core.dsf.gdb.service; import java.util.Map; -import org.eclipse.cdt.debug.gdbjtag.core.GDBJtagDSFFinalLaunchSequence; +import org.eclipse.cdt.debug.gdbjtag.core.GDBJtagDSFFinalLaunchSequence_7_2; import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress; import org.eclipse.cdt.dsf.concurrent.Sequence; -import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; -import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_2; import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; import org.eclipse.cdt.dsf.service.DsfSession; -import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; @@ -36,8 +33,6 @@ public class GDBJtagControl_7_2 extends GDBControl_7_2 { @Override protected Sequence getCompleteInitializationSequence(Map attributes, RequestMonitorWithProgress rm) { - GdbLaunch launch = (GdbLaunch)getSession().getModelAdapter(ILaunch.class); - IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class); - return new GDBJtagDSFFinalLaunchSequence(getExecutor(), launch, backend.getSessionType(), backend.getIsAttachSession(), rm); + return new GDBJtagDSFFinalLaunchSequence_7_2(getSession(), attributes, rm); } } \ No newline at end of file diff --git a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl_7_4.java b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl_7_4.java new file mode 100644 index 00000000000..3e8a85b6096 --- /dev/null +++ b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GDBJtagControl_7_4.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Khouzam (Ericsson) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.gdbjtag.core.dsf.gdb.service; + +import java.util.Map; + +import org.eclipse.cdt.debug.gdbjtag.core.GDBJtagDSFFinalLaunchSequence_7_2; +import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress; +import org.eclipse.cdt.dsf.concurrent.Sequence; +import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_4; +import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.debug.core.ILaunchConfiguration; + + +/** + * Jtag control service which selects the Jtag CompleteInitializationSequence. + * Use for GDB >= 7.2 + */ +public class GDBJtagControl_7_4 extends GDBControl_7_4 { + + public GDBJtagControl_7_4(DsfSession session, ILaunchConfiguration config, CommandFactory factory) { + super(session, config, factory); + } + + @Override + protected Sequence getCompleteInitializationSequence(Map attributes, RequestMonitorWithProgress rm) { + return new GDBJtagDSFFinalLaunchSequence_7_2(getSession(), attributes, rm); + } +} \ No newline at end of file diff --git a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GdbJtagDebugServicesFactory.java b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GdbJtagDebugServicesFactory.java index f4e335e2e1b..33ae2ff8714 100644 --- a/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GdbJtagDebugServicesFactory.java +++ b/jtag/org.eclipse.cdt.debug.gdbjtag.core/src/org/eclipse/cdt/debug/gdbjtag/core/dsf/gdb/service/GdbJtagDebugServicesFactory.java @@ -7,6 +7,7 @@ * * Contributors: * Ericsson - initial API and implementation + * Marc Khouzam (Ericsson) - Added support for the different GDBControl versions (Bug 324101) *******************************************************************************/ package org.eclipse.cdt.debug.gdbjtag.core.dsf.gdb.service; @@ -29,6 +30,9 @@ public class GdbJtagDebugServicesFactory extends GdbDebugServicesFactory { @Override protected ICommandControl createCommandControl(DsfSession session, ILaunchConfiguration config) { + if (GDB_7_4_VERSION.compareTo(getVersion()) <= 0) { + return new GDBJtagControl_7_4(session, config, new CommandFactory_6_8()); + } if (GDB_7_2_VERSION.compareTo(getVersion()) <= 0) { return new GDBJtagControl_7_2(session, config, new CommandFactory_6_8()); }