| /******************************************************************************* |
| * Copyright (c) 2007 - 2010 QNX Software Systems and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Ericsson - initial API and implementation this class is based on |
| * QNX Software Systems - Initial implementation for Jtag debugging |
| * Sage Electronic Engineering, LLC - bug 305943 |
| * - API generalization to become transport-independent (allow |
| * connections via serial ports and pipes). |
| *******************************************************************************/ |
| package org.eclipse.cdt.debug.gdbjtag.core; |
| |
| /** |
| * @author Andy Jin |
| * |
| */ |
| |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Properties; |
| |
| import org.eclipse.cdt.debug.core.CDebugUtils; |
| 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.debug.internal.core.sourcelookup.CSourceLookupDirector; |
| 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.RequestMonitor; |
| import org.eclipse.cdt.dsf.concurrent.Sequence; |
| import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent; |
| import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; |
| import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext; |
| import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; |
| import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; |
| import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages; |
| 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; |
| import org.eclipse.cdt.dsf.mi.service.CSourceLookup; |
| import org.eclipse.cdt.dsf.mi.service.IMIProcesses; |
| import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager; |
| import org.eclipse.cdt.dsf.mi.service.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.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| 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 |
| * DSF/GDB debugger framework. |
| * <p> |
| * This class is based on the implementation of the standard DSF/GDB debugging |
| * <code>org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence</code> |
| * <p> |
| * It adds Jtag hardware debugging specific steps to initialize remote target |
| * and start the remote Jtag debugging. |
| * <p> |
| * @since 7.0 |
| */ |
| public class GDBJtagDSFFinalLaunchSequence extends Sequence { |
| |
| /** utility method; cuts down on clutter */ |
| private void queueCommands(List<String> commands, RequestMonitor rm) { |
| if (!commands.isEmpty()) { |
| fCommandControl.queueCommand( |
| new CLICommand<MIInfo>(fCommandControl.getContext(), composeCommand(commands)), |
| new DataRequestMonitor<MIInfo>(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$ |
| } |
| |
| 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$ |
| } |
| |
| 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$ |
| } |
| |
| 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; |
| } |
| |
| if (dir != null) { |
| fCommandControl.queueCommand( |
| fCommandFactory.createMIEnvironmentCD(fCommandControl.getContext(), dir.toPortableString()), |
| new DataRequestMonitor<MIInfo>(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<MIInfo>(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) { |
| fCommandControl.queueCommand( |
| fCommandFactory.createMIGDBSetArgs(fCommandControl.getContext(), args), |
| new DataRequestMonitor<MIInfo>(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, |
| IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT); |
| } 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<MIInfo>(getExecutor(), requestMonitor) { |
| @Override |
| protected void handleSuccess() { |
| fCommandControl.queueCommand( |
| fCommandFactory.createMIGDBSetPagination(fCommandControl.getContext(), false), |
| new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) { |
| @Override |
| protected void handleSuccess() { |
| fCommandControl.queueCommand( |
| fCommandFactory.createMIGDBSetNonStop(fCommandControl.getContext(), true), |
| new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor)); |
| } |
| }); |
| } |
| }); |
| } else { |
| requestMonitor.done(); |
| } |
| }}, |
| /* |
| * Tell GDB to automatically load or not the shared library symbols |
| */ |
| new Step() { |
| 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<MIInfo>(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<String> p = fGDBBackend.getSharedLibraryPaths(); |
| |
| if (p.size() > 0) { |
| String[] paths = p.toArray(new String[p.size()]); |
| fCommandControl.queueCommand( |
| fCommandFactory.createMIGDBSetSolibSearchPath(fCommandControl.getContext(), paths), |
| new DataRequestMonitor<MIInfo>(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<MIInfo>(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<String> commands = new ArrayList<String>(); |
| 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<String> commands = new ArrayList<String>(); |
| 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<String> commands = new ArrayList<String>(); |
| 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<String> commands = new ArrayList<String>(); |
| 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<String> commands = new ArrayList<String>(); |
| 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<MIInfo>(fCommandControl.getContext(), commands[i]), |
| new DataRequestMonitor<MIInfo>(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); //$NON-NLS-1$ |
| 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$ //$NON-NLS-4$ |
| } |
| List<String> commands = new ArrayList<String>(); |
| 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); |
| IBreakpointsTargetDMContext breakpointDmc = (IBreakpointsTargetDMContext)fCommandControl.getContext(); |
| |
| bpmService.startTrackingBreakpoints(breakpointDmc, 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)); //$NON-NLS-1$ |
| List<String> commands = new ArrayList<String>(); |
| fGdbJtagDevice.doSetPC(pcRegister, commands); |
| queueCommands(commands, rm); |
| } else { |
| rm.done(); |
| } |
| } 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); //$NON-NLS-1$ |
| List<String> commands = new ArrayList<String>(); |
| fGdbJtagDevice.doStopAt(stopAt, commands); |
| queueCommands(commands, rm); |
| } else { |
| rm.done(); |
| } |
| } catch (CoreException e) { |
| rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, -1, "Cannot run the stop script", e)); //$NON-NLS-1$ |
| rm.done(); |
| } |
| } |
| }, |
| /* |
| * 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<String> commands = new ArrayList<String>(); |
| 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); //$NON-NLS-1$ |
| 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<MIInfo>(fCommandControl.getContext(), commands[i]), |
| new DataRequestMonitor<MIInfo>(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; |
| |
| public GDBJtagDSFFinalLaunchSequence(DsfExecutor executor, GdbLaunch launch, SessionType sessionType, boolean attach, IProgressMonitor pm) { |
| super(executor, pm, LaunchMessages.getString("FinalLaunchSequence.0"), LaunchMessages.getString("FinalLaunchSequence.1")); //$NON-NLS-1$ //$NON-NLS-2$ |
| fLaunch = launch; |
| fSessionType = sessionType; |
| fAttach = attach; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence#getSteps() |
| */ |
| @Override |
| public Step[] getSteps() { |
| return fSteps; |
| } |
| |
| /** |
| * @param config |
| * @return IGDBJtagDevice the selected Jtag device |
| * @throws CoreException |
| * @throws NullPointerException |
| */ |
| private IGDBJtagDevice getGDBJtagDevice (ILaunchConfiguration config) |
| throws CoreException, NullPointerException { |
| IGDBJtagDevice gdbJtagDevice = null; |
| String jtagDeviceName = config.getAttribute(IGDBJtagConstants.ATTR_JTAG_DEVICE, IGDBJtagConstants.DEFAULT_JTAG_DEVICE); //$NON-NLS-1$ |
| GDBJtagDeviceContribution[] availableDevices = GDBJtagDeviceContributionFactory.getInstance().getGDBJtagDeviceContribution(); |
| for (GDBJtagDeviceContribution availableDevice : availableDevices) { |
| if (jtagDeviceName.equals(availableDevice.getDeviceName())) { |
| gdbJtagDevice = availableDevice.getDevice(); |
| break; |
| } |
| } |
| return gdbJtagDevice; |
| } |
| |
| /** |
| * @param commands |
| * @return String commands in String format |
| */ |
| private String composeCommand(Collection<String> commands) { |
| if (commands.isEmpty()) |
| return null; |
| StringBuffer sb = new StringBuffer(); |
| Iterator<String> it = commands.iterator(); |
| while (it.hasNext()) { |
| sb.append(it.next()); |
| } |
| return sb.toString(); |
| } |
| } |