diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IDebugNewExecutableHandler.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IDebugNewExecutableHandler.java new file mode 100644 index 00000000000..ecde45f0427 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IDebugNewExecutableHandler.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics 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: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.debug.core.model; + +import org.eclipse.debug.core.commands.IDebugCommandHandler; + +/** + * Command handler for the "Debug New Executable" command. + * + * @since 7.3 + */ +public interface IDebugNewExecutableHandler extends IDebugCommandHandler { +} diff --git a/debug/org.eclipse.cdt.debug.ui/icons/obj16/new_exec.gif b/debug/org.eclipse.cdt.debug.ui/icons/obj16/new_exec.gif new file mode 100755 index 00000000000..78ca91c6dab Binary files /dev/null and b/debug/org.eclipse.cdt.debug.ui/icons/obj16/new_exec.gif differ diff --git a/debug/org.eclipse.cdt.debug.ui/plugin.properties b/debug/org.eclipse.cdt.debug.ui/plugin.properties index 34cbb7d2d35..2266d66e86e 100644 --- a/debug/org.eclipse.cdt.debug.ui/plugin.properties +++ b/debug/org.eclipse.cdt.debug.ui/plugin.properties @@ -242,3 +242,9 @@ OpenNewView.name = Open New View # Disassembly Ruler Column extension point extPoint.disassemblyRulerColumn=Disassembly Ruler Column + +# Debug New Executable Command +DebugNewExecutable.name=Debug New Executable +DebugNewExecutable.description=Debug a new executable +DebugNewExecutable.label=Debug New Executable... +DebugNewExecutable.tooltip=Debug a new executable diff --git a/debug/org.eclipse.cdt.debug.ui/plugin.xml b/debug/org.eclipse.cdt.debug.ui/plugin.xml index 0188aa81f49..d2b3fc1b6f1 100644 --- a/debug/org.eclipse.cdt.debug.ui/plugin.xml +++ b/debug/org.eclipse.cdt.debug.ui/plugin.xml @@ -2012,7 +2012,12 @@ id="org.eclipse.cdt.debug.ui.command.connect" name="%Connect.name"> - + + @@ -2079,6 +2084,10 @@ class="org.eclipse.cdt.debug.internal.ui.commands.ConnectCommandHandler" commandId="org.eclipse.cdt.debug.ui.command.connect"> + + @@ -2520,6 +2529,28 @@ + + + + + getCommandType() { + return IDebugNewExecutableHandler.class; + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbAdapterFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbAdapterFactory.java index a35c0913306..51d5f2ea88b 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbAdapterFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbAdapterFactory.java @@ -19,6 +19,7 @@ import java.util.WeakHashMap; import org.eclipse.cdt.debug.core.model.ICBreakpoint; import org.eclipse.cdt.debug.core.model.IConnectHandler; +import org.eclipse.cdt.debug.core.model.IDebugNewExecutableHandler; import org.eclipse.cdt.debug.core.model.IResumeWithoutSignalHandler; import org.eclipse.cdt.debug.core.model.IReverseResumeHandler; import org.eclipse.cdt.debug.core.model.IReverseStepIntoHandler; @@ -49,6 +50,7 @@ import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbDisconnectCommand; import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbRestartCommand; import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbSteppingModeTarget; import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbConnectCommand; +import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbDebugNewExecutableCommand; import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbResumeWithoutSignalCommand; import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseResumeCommand; import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseStepIntoCommand; @@ -114,6 +116,7 @@ public class GdbAdapterFactory final GdbResumeWithoutSignalCommand fResumeWithoutSignalCommand; final GdbRestartCommand fRestartCommand; final DsfTerminateCommand fTerminateCommand; + final GdbDebugNewExecutableCommand fDebugNewExecutableCommand; final GdbConnectCommand fConnectCommand; final GdbDisconnectCommand fDisconnectCommand; final IDebugModelProvider fDebugModelProvider; @@ -162,7 +165,8 @@ public class GdbAdapterFactory fResumeWithoutSignalCommand = new GdbResumeWithoutSignalCommand(session); fRestartCommand = new GdbRestartCommand(session, fLaunch); fTerminateCommand = new DsfTerminateCommand(session); - fConnectCommand = new GdbConnectCommand(session); + fDebugNewExecutableCommand = new GdbDebugNewExecutableCommand(session, fLaunch); + fConnectCommand = new GdbConnectCommand(session, fLaunch); fDisconnectCommand = new GdbDisconnectCommand(session); fSuspendTrigger = new GdbSuspendTrigger(session, fLaunch); fModelSelectionPolicyFactory = new DefaultDsfModelSelectionPolicyFactory(); @@ -189,6 +193,7 @@ public class GdbAdapterFactory session.registerModelAdapter(IRestartHandler.class, fRestartCommand); session.registerModelAdapter(ITerminateHandler.class, fTerminateCommand); session.registerModelAdapter(IConnectHandler.class, fConnectCommand); + session.registerModelAdapter(IDebugNewExecutableHandler.class, fDebugNewExecutableCommand); session.registerModelAdapter(IDisconnectHandler.class, fDisconnectCommand); session.registerModelAdapter(IModelSelectionPolicyFactory.class, fModelSelectionPolicyFactory); session.registerModelAdapter(IRefreshAllTarget.class, fRefreshAllTarget); @@ -249,6 +254,7 @@ public class GdbAdapterFactory session.unregisterModelAdapter(IRestartHandler.class); session.unregisterModelAdapter(ITerminateHandler.class); session.unregisterModelAdapter(IConnectHandler.class); + session.unregisterModelAdapter(IDebugNewExecutableHandler.class); session.unregisterModelAdapter(IDisconnectHandler.class); session.unregisterModelAdapter(IModelSelectionPolicyFactory.class); session.unregisterModelAdapter(IRefreshAllTarget.class); @@ -279,6 +285,7 @@ public class GdbAdapterFactory fRestartCommand.dispose(); fTerminateCommand.dispose(); fConnectCommand.dispose(); + fDebugNewExecutableCommand.dispose(); fDisconnectCommand.dispose(); fSuspendTrigger.dispose(); fReverseToggleTarget.dispose(); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbConnectCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbConnectCommand.java index d797a6e48ae..5a50b774632 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbConnectCommand.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbConnectCommand.java @@ -20,6 +20,7 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.RejectedExecutionException; +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.debug.core.model.IConnectHandler; import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; @@ -35,9 +36,11 @@ import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMData; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext; +import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; import org.eclipse.cdt.dsf.gdb.actions.IConnect; import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; import org.eclipse.cdt.dsf.gdb.internal.ui.actions.ProcessInfo; +import org.eclipse.cdt.dsf.gdb.internal.ui.launching.NewExecutableInfo; import org.eclipse.cdt.dsf.gdb.internal.ui.launching.LaunchUIMessages; import org.eclipse.cdt.dsf.gdb.internal.ui.launching.ProcessPrompter; import org.eclipse.cdt.dsf.gdb.internal.ui.launching.ProcessPrompter.PrompterInfo; @@ -68,7 +71,8 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.progress.UIJob; public class GdbConnectCommand extends AbstractDebugCommand implements IConnectHandler, IConnect { - + + private final GdbLaunch fLaunch; private final DsfExecutor fExecutor; private final DsfServicesTracker fTracker; @@ -82,7 +86,8 @@ public class GdbConnectCommand extends AbstractDebugCommand implements IConnectH // the binary location for a local attach session. private Map fProcessNameToBinaryMap = new HashMap(); - public GdbConnectCommand(DsfSession session) { + public GdbConnectCommand(DsfSession session, GdbLaunch launch) { + fLaunch = launch; fExecutor = session.getExecutor(); fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId()); } @@ -143,10 +148,12 @@ public class GdbConnectCommand extends AbstractDebugCommand implements IConnectH IProcessExtendedInfo[] fProcessList = null; DataRequestMonitor fRequestMonitor; boolean fNewProcessSupported; + boolean fRemote; - public PromptForPidJob(String name, boolean newProcessSupported, IProcessExtendedInfo[] procs, DataRequestMonitor rm) { + public PromptForPidJob(String name, boolean newProcessSupported, boolean remote, IProcessExtendedInfo[] procs, DataRequestMonitor rm) { super(name); fNewProcessSupported = newProcessSupported; + fRemote = remote; fProcessList = procs; fRequestMonitor = rm; } @@ -158,11 +165,11 @@ public class GdbConnectCommand extends AbstractDebugCommand implements IConnectH null); try { - PrompterInfo info = new PrompterInfo(fNewProcessSupported, fProcessList); + PrompterInfo info = new PrompterInfo(fNewProcessSupported, fRemote, fProcessList); Object result = new ProcessPrompter().handleStatus(null, info); if (result == null) { fRequestMonitor.cancel(); - } else if (result instanceof IProcessExtendedInfo[] || result instanceof String) { + } else if (result instanceof IProcessExtendedInfo[] || result instanceof NewExecutableInfo) { fRequestMonitor.setData(result); } else if (result instanceof Integer) { // This is the case where the user typed in a pid number directly @@ -288,9 +295,11 @@ public class GdbConnectCommand extends AbstractDebugCommand implements IConnectH public void run() { final IProcesses procService = fTracker.getService(IProcesses.class); ICommandControlService commandControl = fTracker.getService(ICommandControlService.class); + IGDBBackend backend = fTracker.getService(IGDBBackend.class); - if (procService != null && commandControl != null) { + if (procService != null && commandControl != null && backend != null) { final ICommandControlDMContext controlCtx = commandControl.getContext(); + final boolean remote = backend.getSessionType() == SessionType.REMOTE; // First check if the "New..." button should be enabled. procService.isDebugNewProcessSupported(controlCtx, new DataRequestMonitor(fExecutor, rm) { @@ -314,7 +323,8 @@ public class GdbConnectCommand extends AbstractDebugCommand implements IConnectH // Prompt the user to choose one or more processes, or to start a new one new PromptForPidJob( LaunchUIMessages.getString("ProcessPrompter.PromptJob"), //$NON-NLS-1$ - newProcessSupported, + newProcessSupported, + remote, procInfoList.toArray(new IProcessExtendedInfo[procInfoList.size()]), new DataRequestMonitor(fExecutor, rm) { @Override @@ -325,9 +335,9 @@ public class GdbConnectCommand extends AbstractDebugCommand implements IConnectH @Override protected void handleSuccess() { Object data = getData(); - if (data instanceof String) { + if (data instanceof NewExecutableInfo) { // User wants to start a new process - startNewProcess(controlCtx, (String)data, rm); + startNewProcess(controlCtx, (NewExecutableInfo)data, rm); } else if (data instanceof IProcessExtendedInfo[]) { attachToProcesses(controlCtx, (IProcessExtendedInfo[])data, rm); } else { @@ -412,11 +422,23 @@ public class GdbConnectCommand extends AbstractDebugCommand implements IConnectH }); } - private void startNewProcess(ICommandControlDMContext controlDmc, String binaryPath, RequestMonitor rm) { + private void startNewProcess(ICommandControlDMContext controlDmc, NewExecutableInfo info, RequestMonitor rm) { IGDBProcesses procService = fTracker.getService(IGDBProcesses.class); - procService.debugNewProcess( - controlDmc, binaryPath, - new HashMap(), new DataRequestMonitor(fExecutor, rm)); + try { + @SuppressWarnings("unchecked") + Map attributes = fLaunch.getLaunchConfiguration().getAttributes(); + attributes.put(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REMOTE_BINARY, info.getTargetPath()); + attributes.put(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, info.getArguments()); + procService.debugNewProcess( + controlDmc, + info.getHostPath(), + attributes, + new DataRequestMonitor(fExecutor, rm)); + } + catch(CoreException e) { + rm.setStatus(e.getStatus()); + rm.done(); + } } private void attachToProcesses(final ICommandControlDMContext controlDmc, IProcessExtendedInfo[] processes, final RequestMonitor rm) { diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbDebugNewExecutableCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbDebugNewExecutableCommand.java new file mode 100644 index 00000000000..4631445ea5c --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbDebugNewExecutableCommand.java @@ -0,0 +1,213 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics 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: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.internal.ui.commands; + +import java.util.Map; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.RejectedExecutionException; + +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; +import org.eclipse.cdt.debug.core.model.IDebugNewExecutableHandler; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.DsfExecutor; +import org.eclipse.cdt.dsf.concurrent.DsfRunnable; +import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.Query; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.service.IProcesses; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; +import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.dsf.gdb.internal.ui.launching.NewExecutableInfo; +import org.eclipse.cdt.dsf.gdb.internal.ui.launching.NewExecutableDialog; +import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; +import org.eclipse.cdt.dsf.gdb.service.IGDBBackend; +import org.eclipse.cdt.dsf.gdb.service.SessionType; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.IRequest; +import org.eclipse.debug.core.commands.AbstractDebugCommand; +import org.eclipse.debug.core.commands.IEnabledStateRequest; +import org.eclipse.jface.window.Window; +import org.eclipse.ui.progress.UIJob; + +public class GdbDebugNewExecutableCommand extends AbstractDebugCommand implements IDebugNewExecutableHandler { + + private class PromptJob extends UIJob { + + private DataRequestMonitor fRequestMonitor; + private boolean fRemote = false; + + private PromptJob( boolean remote, DataRequestMonitor rm ) { + super( Messages.GdbDebugNewExecutableCommand_New_Executable_Prompt_Job ); + fRemote = remote; + fRequestMonitor = rm; + } + + @Override + public IStatus runInUIThread( IProgressMonitor monitor ) { + int flags = ( fRemote ) ? NewExecutableDialog.REMOTE : 0; + NewExecutableDialog dialog = new NewExecutableDialog( GdbUIPlugin.getShell(), flags ); + final boolean canceled = dialog.open() == Window.CANCEL; + final NewExecutableInfo info = dialog.getExecutableInfo(); + fExecutor.execute( new DsfRunnable() { + + @Override + public void run() { + if ( canceled ) + fRequestMonitor.cancel(); + else + fRequestMonitor.setData( info ); + fRequestMonitor.done(); + } + } ); + return Status.OK_STATUS; + } + } + + private final GdbLaunch fLaunch; + private final DsfExecutor fExecutor; + private final DsfServicesTracker fTracker; + + public GdbDebugNewExecutableCommand( DsfSession session, GdbLaunch launch ) { + super(); + fLaunch = launch; + fExecutor = session.getExecutor(); + fTracker = new DsfServicesTracker( GdbUIPlugin.getBundleContext(), session.getId() ); + } + + public boolean canDebugNewExecutable() { + + Query canDebugQuery = new Query() { + @Override + public void execute( DataRequestMonitor rm ) { + IProcesses procService = fTracker.getService( IProcesses.class ); + ICommandControlService commandControl = fTracker.getService( ICommandControlService.class ); + + if ( procService == null || commandControl == null ) { + rm.setData( false ); + rm.done(); + return; + } + procService.isDebugNewProcessSupported( commandControl.getContext(), rm ); + } + }; + try { + fExecutor.execute( canDebugQuery ); + return canDebugQuery.get(); + } + catch( InterruptedException e ) { + } + catch( ExecutionException e ) { + } + catch( RejectedExecutionException e ) { + // Can be thrown if the session is shutdown + } + return false; + } + + public void debugNewExecutable( final RequestMonitor rm ) { + IGDBBackend backend = fTracker.getService( IGDBBackend.class ); + final IProcesses procService = fTracker.getService( IProcesses.class ); + final ICommandControlService commandControl = fTracker.getService( ICommandControlService.class ); + if ( backend == null || procService == null || commandControl == null ) { + rm.setStatus( new Status( IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, "Service is not available" ) ); //$NON-NLS-1$ + rm.done(); + return; + } + + PromptJob job = new PromptJob( + backend.getSessionType() == SessionType.REMOTE, + new DataRequestMonitor( fExecutor, rm ){ + + @Override + protected void handleCancel() { + rm.cancel(); + rm.done(); + }; + + @Override + protected void handleSuccess() { + try { + @SuppressWarnings( "unchecked" ) + Map attributes = getLaunchConfiguration().getAttributes(); + attributes.put( IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REMOTE_BINARY, getData().getTargetPath() ); + attributes.put( ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, getData().getArguments() ); + procService.debugNewProcess( + commandControl.getContext(), + getData().getHostPath(), + attributes, + new ImmediateDataRequestMonitor( rm ) ); + } + catch( CoreException e ) { + rm.setStatus( e.getStatus() ); + rm.done(); + } + }; + } ); + job.schedule(); + } + + @Override + protected void doExecute( Object[] targets, IProgressMonitor monitor, IRequest request ) throws CoreException { + Query query = new Query() { + + @Override + protected void execute( DataRequestMonitor rm ) { + debugNewExecutable( rm ); + } + }; + try { + fExecutor.execute( query ); + query.get(); + } + catch( InterruptedException e ) { + } + catch( ExecutionException e ) { + } + catch( CancellationException e ) { + // Nothing to do, just ignore the command since the user + // cancelled it. + } + catch( RejectedExecutionException e ) { + // Can be thrown if the session is shutdown + } + } + + @Override + protected boolean isExecutable( Object[] targets, IProgressMonitor monitor, IEnabledStateRequest request ) throws CoreException { + return canDebugNewExecutable(); + } + + @Override + protected Object getTarget( Object element ) { + if ( element instanceof GdbLaunch || element instanceof IDMVMContext ) + return element; + return null; + } + + public void dispose() { + fTracker.dispose(); + } + + private ILaunchConfiguration getLaunchConfiguration() { + return fLaunch.getLaunchConfiguration(); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/Messages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/Messages.java new file mode 100644 index 00000000000..a8d5629cd7f --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/Messages.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2012 Mentor Graphics 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: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.internal.ui.commands; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + + public static String GdbDebugNewExecutableCommand_Arguments; + + public static String GdbDebugNewExecutableCommand_Binary; + + public static String GdbDebugNewExecutableCommand_Binary_file_does_not_exist; + + public static String GdbDebugNewExecutableCommand_Binary_must_be_specified; + + public static String GdbDebugNewExecutableCommand_Binary_on_host; + + public static String GdbDebugNewExecutableCommand_Binary_on_target; + + public static String GdbDebugNewExecutableCommand_Binary_on_target_must_be_specified; + + public static String GdbDebugNewExecutableCommand_Browse; + + public static String GdbDebugNewExecutableCommand_Debug_New_Executable; + + public static String GdbDebugNewExecutableCommand_Host_binary_file_does_not_exist; + + public static String GdbDebugNewExecutableCommand_Host_binary_must_be_specified; + + public static String GdbDebugNewExecutableCommand_Invalid_binary; + + public static String GdbDebugNewExecutableCommand_Invalid_host_binary; + + public static String GdbDebugNewExecutableCommand_New_Executable_Prompt_Job; + + public static String GdbDebugNewExecutableCommand_Select_binaries_on_host_and_target; + + public static String GdbDebugNewExecutableCommand_Select_Binary; + + public static String GdbDebugNewExecutableCommand_Select_binary_and_specify_arguments; + static { + // initialize resource bundle + NLS.initializeMessages( Messages.class.getName(), Messages.class ); + } + + private Messages() { + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/Messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/Messages.properties new file mode 100644 index 00000000000..d601bc6d839 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/Messages.properties @@ -0,0 +1,28 @@ +############################################################################### +# Copyright (c) 2012 Mentor Graphics 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: +# Mentor Graphics - Initial API and implementation +############################################################################### + +GdbDebugNewExecutableCommand_Arguments=Arguments: +GdbDebugNewExecutableCommand_Binary=Binary: +GdbDebugNewExecutableCommand_Binary_file_does_not_exist=Binary file does not exist +GdbDebugNewExecutableCommand_Binary_must_be_specified=Binary must be specified +GdbDebugNewExecutableCommand_Binary_on_host=Binary on host: +GdbDebugNewExecutableCommand_Binary_on_target=Binary on target: +GdbDebugNewExecutableCommand_Binary_on_target_must_be_specified=Binary on target must be specified +GdbDebugNewExecutableCommand_Browse=Browse... +GdbDebugNewExecutableCommand_Debug_New_Executable=Debug New Executable +GdbDebugNewExecutableCommand_Host_binary_file_does_not_exist=Host binary file does not exist +GdbDebugNewExecutableCommand_Host_binary_must_be_specified=Host binary must be specified +GdbDebugNewExecutableCommand_Invalid_binary=Invalid binary +GdbDebugNewExecutableCommand_Invalid_host_binary=Invalid host binary +GdbDebugNewExecutableCommand_New_Executable_Prompt_Job=New Executable Prompt Job +GdbDebugNewExecutableCommand_Select_binaries_on_host_and_target=Select binaries on the host and the target and specify the arguments +GdbDebugNewExecutableCommand_Select_Binary=Select Binary +GdbDebugNewExecutableCommand_Select_binary_and_specify_arguments=Select a binary and specify the arguments diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/NewExecutableDialog.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/NewExecutableDialog.java new file mode 100644 index 00000000000..7c65e7be5eb --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/NewExecutableDialog.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2013 Mentor Graphics 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: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.internal.ui.launching; + +import java.io.File; + +import org.eclipse.cdt.dsf.gdb.internal.ui.commands.Messages; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +public class NewExecutableDialog extends TitleAreaDialog { + + public static final int REMOTE = 0x1; + + private int fFlags = 0; + private NewExecutableInfo fInfo = null; + + private Text fHostBinaryText; + private Text fTargetBinaryText; + private Text fArgumentsText; + + public NewExecutableDialog( Shell parentShell, int flags ) { + super( parentShell ); + setShellStyle( getShellStyle() | SWT.RESIZE ); + fFlags = flags; + } + + @Override + protected Control createContents( Composite parent ) { + Control control = super.createContents( parent ); + validate(); + return control; + } + + @Override + protected Control createDialogArea( Composite parent ) { + boolean remote = (fFlags & REMOTE) > 0; + + getShell().setText( Messages.GdbDebugNewExecutableCommand_Debug_New_Executable ); + setTitle( Messages.GdbDebugNewExecutableCommand_Select_Binary ); + String message = ( remote ) ? + Messages.GdbDebugNewExecutableCommand_Select_binaries_on_host_and_target : + Messages.GdbDebugNewExecutableCommand_Select_binary_and_specify_arguments; + setMessage( message ); + + Composite control = (Composite)super.createDialogArea( parent ); + Composite comp = new Composite( control, SWT.NONE ); + GridData gd = new GridData( SWT.FILL, SWT.FILL, true, true ); + GridLayout layout = new GridLayout( 3, false ); + comp.setLayout( layout ); + comp.setLayoutData( gd ); + + new Label( comp, SWT.None ).setText( remote ? Messages.GdbDebugNewExecutableCommand_Binary_on_host : Messages.GdbDebugNewExecutableCommand_Binary ); + fHostBinaryText = new Text( comp, SWT.BORDER ); + fHostBinaryText.setLayoutData( new GridData( SWT.FILL, SWT.CENTER, true, false ) ); + fHostBinaryText.addModifyListener( new ModifyListener() { + + @Override + public void modifyText( ModifyEvent e ) { + validate(); + } + } ); + Button browseButton = new Button( comp, SWT.PUSH ); + browseButton.setText( Messages.GdbDebugNewExecutableCommand_Browse ); + browseButton.setFont( JFaceResources.getDialogFont() ); + setButtonLayoutData( browseButton ); + browseButton.addSelectionListener( new SelectionAdapter() { + + @Override + public void widgetSelected( SelectionEvent e ) { + FileDialog dialog = new FileDialog( getShell() ); + dialog.setFileName( fHostBinaryText.getText() ); + String result = dialog.open(); + if ( result != null ) { + fHostBinaryText.setText( result ); + } + } + } ); + + if ( remote ) { + new Label( comp, SWT.None ).setText( Messages.GdbDebugNewExecutableCommand_Binary_on_target ); + fTargetBinaryText = new Text( comp, SWT.BORDER ); + fTargetBinaryText.setLayoutData( new GridData( SWT.FILL, SWT.CENTER, true, false, 2, 1 ) ); + fTargetBinaryText.addModifyListener( new ModifyListener() { + + @Override + public void modifyText( ModifyEvent e ) { + validate(); + } + } ); + } + + new Label( comp, SWT.None ).setText( Messages.GdbDebugNewExecutableCommand_Arguments ); + fArgumentsText = new Text( comp, SWT.BORDER ); + fArgumentsText.setLayoutData( new GridData( SWT.FILL, SWT.CENTER, true, false, 2, 1 ) ); + + return control; + } + + @Override + protected void okPressed() { + String targetPath = ( fTargetBinaryText != null ) ? fTargetBinaryText.getText().trim() : null; + String args = fArgumentsText.getText().trim(); + fInfo = new NewExecutableInfo( fHostBinaryText.getText().trim(), targetPath, args ); + super.okPressed(); + } + + public NewExecutableInfo getExecutableInfo() { + return fInfo; + } + + private void validate() { + boolean remote = (fFlags & REMOTE) > 0; + StringBuilder sb = new StringBuilder(); + String hostBinary = fHostBinaryText.getText().trim(); + if ( hostBinary.isEmpty() ) { + sb.append( ( remote ) ? + Messages.GdbDebugNewExecutableCommand_Host_binary_must_be_specified : + Messages.GdbDebugNewExecutableCommand_Binary_must_be_specified ); + } + else { + File file = new File( hostBinary ); + if ( !file.exists() ) { + sb.append( ( remote ) ? + Messages.GdbDebugNewExecutableCommand_Host_binary_file_does_not_exist : + Messages.GdbDebugNewExecutableCommand_Binary_file_does_not_exist ); + } + else if ( file.isDirectory() ) { + sb.append( ( remote ) ? + Messages.GdbDebugNewExecutableCommand_Invalid_host_binary : + Messages.GdbDebugNewExecutableCommand_Invalid_binary ); + } + } + if ( fTargetBinaryText != null ) { + if ( fTargetBinaryText.getText().trim().length() == 0 ) { + if ( sb.length() != 0 ) { + sb.append( "\n " ); //$NON-NLS-1$ + } + sb.append( Messages.GdbDebugNewExecutableCommand_Binary_on_target_must_be_specified ); + } + } + setErrorMessage( ( sb.length() != 0 ) ? sb.toString() : null ); + getButton( IDialogConstants.OK_ID ).setEnabled( getErrorMessage() == null ); + } +} \ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/NewExecutableInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/NewExecutableInfo.java new file mode 100644 index 00000000000..1f88a279bde --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/NewExecutableInfo.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2013 Mentor Graphics 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: + * Mentor Graphics - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.internal.ui.launching; + +/** + * This class provides information required to start + * debugging an executable. + */ +public class NewExecutableInfo { + private String fHostPath; + private String fTargetPath; + private String fArguments; + + public NewExecutableInfo(String hostPath, String targetPath, String args) { + super(); + fHostPath = hostPath; + fTargetPath = targetPath; + fArguments = args; + } + + /** + * Returns the path of the executable on the host + */ + public String getHostPath() { + return fHostPath; + } + + /** + * For remote sessions returns the path of the executable + * on the target. Otherwise returns null. + */ + public String getTargetPath() { + return fTargetPath; + } + + /** + * Returns the arguments to pass to the executable, or null + */ + public String getArguments() { + return fArguments; + } +} \ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java index 8df673aa10c..b50e0ce4a68 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java @@ -34,10 +34,12 @@ public class ProcessPrompter implements IStatusHandler { public static class PrompterInfo { public boolean supportsNewProcess; + public boolean remote; public IProcessExtendedInfo[] processList; - public PrompterInfo(boolean supportsNew, IProcessExtendedInfo[] list) { + public PrompterInfo(boolean supportsNew, boolean remote, IProcessExtendedInfo[] list) { supportsNewProcess = supportsNew; + this.remote = remote; processList = list; } } @@ -162,7 +164,8 @@ public class ProcessPrompter implements IStatusHandler { }; // Display the list of processes and have the user choose - ProcessPrompterDialog dialog = new ProcessPrompterDialog(shell, provider, qprovider, prompterInfo.supportsNewProcess); + ProcessPrompterDialog dialog = + new ProcessPrompterDialog(shell, provider, qprovider, prompterInfo.supportsNewProcess, prompterInfo.remote); dialog.setTitle(LaunchUIMessages.getString("LocalAttachLaunchDelegate.Select_Process")); //$NON-NLS-1$ dialog.setMessage(LaunchUIMessages.getString("LocalAttachLaunchDelegate.Select_Process_to_attach_debugger_to")); //$NON-NLS-1$ @@ -172,9 +175,9 @@ public class ProcessPrompter implements IStatusHandler { dialog.setElements(plist); if (dialog.open() == Window.OK) { // First check if the user pressed the New button - String binaryPath = dialog.getBinaryPath(); - if (binaryPath != null) { - return binaryPath; + NewExecutableInfo execInfo = dialog.getExecutableInfo(); + if (execInfo != null) { + return execInfo; } Object[] results = dialog.getResult(); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompterDialog.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompterDialog.java index 92f6ee216bd..623c148e386 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompterDialog.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompterDialog.java @@ -13,12 +13,12 @@ package org.eclipse.cdt.dsf.gdb.internal.ui.launching; import java.util.Arrays; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; @@ -42,13 +42,15 @@ import org.eclipse.ui.dialogs.TwoPaneElementSelector; */ public class ProcessPrompterDialog extends TwoPaneElementSelector { private static final int NEW_BUTTON_ID = 9876; - private String fBinaryPath; + private NewExecutableInfo fExecInfo; private boolean fSupportsNewProcess; + private boolean fRemote; public ProcessPrompterDialog(Shell parent, ILabelProvider elementRenderer, - ILabelProvider qualifierRenderer, boolean supportsNewProcess) { + ILabelProvider qualifierRenderer, boolean supportsNewProcess, boolean remote) { super(parent, elementRenderer, qualifierRenderer); fSupportsNewProcess = supportsNewProcess; + fRemote = remote; } @Override @@ -62,19 +64,16 @@ public class ProcessPrompterDialog extends TwoPaneElementSelector { @Override protected void buttonPressed(int buttonId) { if (buttonId == NEW_BUTTON_ID) { - FileDialog fd = new FileDialog(getShell(), SWT.NONE); - fBinaryPath = fd.open(); - - setReturnCode(OK); - close(); + NewExecutableDialog dialog = new NewExecutableDialog(getShell(), (fRemote) ? NewExecutableDialog.REMOTE : 0); + if (dialog.open() == IDialogConstants.OK_ID) { + fExecInfo = dialog.getExecutableInfo(); + setReturnCode(OK); + close(); + } } super.buttonPressed(buttonId); } - public String getBinaryPath() { - return fBinaryPath; - } - /* * The result should be every selected element. */ @@ -116,4 +115,8 @@ public class ProcessPrompterDialog extends TwoPaneElementSelector { }); return list; } + + public NewExecutableInfo getExecutableInfo() { + return fExecInfo; + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGDBLaunchConfigurationConstants.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGDBLaunchConfigurationConstants.java index 0f1cf56d63b..74bdabda65e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGDBLaunchConfigurationConstants.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGDBLaunchConfigurationConstants.java @@ -114,6 +114,13 @@ public class IGDBLaunchConfigurationConstants { */ public static final String ATTR_DEBUGGER_TRACEPOINT_MODE = GdbPlugin.PLUGIN_ID + ".TRACEPOINT_MODE"; //$NON-NLS-1$ + /** + * Launch configuration attribute key. The value is a String specifying the path of the executable + * on the target. + * @since 4.2 + */ + public static final String ATTR_DEBUGGER_REMOTE_BINARY = GdbPlugin.PLUGIN_ID + ".REMOTE_BINARY"; //$NON-NLS-1$ + /** * Launch configuration attribute value. The key is ATTR_DEBUG_NAME. */ diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java index 87c79a79e94..efaa5bdb475 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java @@ -19,6 +19,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.debug.core.model.IConnectHandler; +import org.eclipse.cdt.debug.core.model.IDebugNewExecutableHandler; import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; @@ -295,7 +296,10 @@ public class GdbLaunch extends DsfLaunch if (adapter.equals(IConnectHandler.class)) return getSession().getModelAdapter(adapter); - // Must force adapters to be loaded. + if (adapter.equals(IDebugNewExecutableHandler.class)) + return getSession().getModelAdapter(adapter); + + // Must force adapters to be loaded. Platform.getAdapterManager().loadAdapter(this, adapter.getName()); return super.getAdapter(adapter); } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence.java index ba0797d0f3b..acd2c10c2cc 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence.java @@ -200,9 +200,13 @@ public class DebugNewProcessSequence extends ReflectionSequence { @Execute public void stepSetArguments(RequestMonitor rm) { try { - String args = fBackend.getProgramArguments(); + String args = CDebugUtils.getAttribute( + fAttributes, + ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, + ""); //$NON-NLS-1$ - if (args != null) { + if (args.length() != 0) { + args = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(args); String[] argArray = CommandLineUtil.argumentsToArray(args); fCommandControl.queueCommand( fCommandFactory.createMIGDBSetArgs(getContainerContext(), argArray), diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence_7_2.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence_7_2.java index c7238712b59..40685bb3d89 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence_7_2.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/DebugNewProcessSequence_7_2.java @@ -15,15 +15,19 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import org.eclipse.cdt.debug.core.CDebugUtils; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; +import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; import org.eclipse.cdt.dsf.mi.service.command.output.MIAddInferiorInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; @@ -40,14 +44,23 @@ public class DebugNewProcessSequence_7_2 extends DebugNewProcessSequence { private IGDBControl fGdbControl; private IGDBProcesses fProcService; + private IGDBBackend fBackend; + private CommandFactory fCommandFactory; private String fSessionId; private final boolean fInitialProcess; + private final Map fAttributes; - public DebugNewProcessSequence_7_2(DsfExecutor executor, boolean isInitial, IDMContext dmc, String file, - Map attributes, DataRequestMonitor rm) { + public DebugNewProcessSequence_7_2( + DsfExecutor executor, + boolean isInitial, + IDMContext dmc, + String file, + Map attributes, + DataRequestMonitor rm) { super(executor, isInitial, dmc, file, attributes, rm); fSessionId = dmc.getSessionId(); fInitialProcess = isInitial; + fAttributes = attributes; } @Override @@ -60,13 +73,14 @@ public class DebugNewProcessSequence_7_2 extends DebugNewProcessSequence { // Now insert our steps right after the initialization of the base class. orderList.add(orderList.indexOf("stepInitializeBaseSequence") + 1, "stepInitializeSequence_7_2"); //$NON-NLS-1$ //$NON-NLS-2$ orderList.add(orderList.indexOf("stepInitializeSequence_7_2") + 1, "stepAddInferior"); //$NON-NLS-1$ //$NON-NLS-2$ + orderList.add(orderList.indexOf("stepSetExecutable") + 1, "stepSetRemoteExecutable"); //$NON-NLS-1$ //$NON-NLS-2$ return orderList.toArray(new String[orderList.size()]); } return null; } - + /** * Initialize the members of the DebugNewProcessSequence_7_2 class. * This step is mandatory for the rest of the sequence to complete. @@ -76,14 +90,17 @@ public class DebugNewProcessSequence_7_2 extends DebugNewProcessSequence { DsfServicesTracker tracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fSessionId); fGdbControl = tracker.getService(IGDBControl.class); fProcService = tracker.getService(IGDBProcesses.class); + fBackend = tracker.getService(IGDBBackend.class); tracker.dispose(); - if (fGdbControl == null || fProcService == null) { + if (fGdbControl == null || fProcService == null || fBackend == null) { rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Cannot obtain service", null)); //$NON-NLS-1$ rm.done(); return; } + fCommandFactory = fGdbControl.getCommandFactory(); + rm.done(); } @@ -119,5 +136,37 @@ public class DebugNewProcessSequence_7_2 extends DebugNewProcessSequence { rm.done(); } }); + } + + /** + * Set remote executable. + * @since 4.2 + */ + @Execute + public void stepSetRemoteExecutable(final RequestMonitor rm) { + if (fBackend.getSessionType() == SessionType.REMOTE && fBackend.getIsAttachSession()) { + String remoteBinary = CDebugUtils.getAttribute( + fAttributes, + IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REMOTE_BINARY, + ""); //$NON-NLS-1$ + if (remoteBinary.length() == 0) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Binary on host is not specified")); //$NON-NLS-1$ + rm.done(); + return; + } + + fGdbControl.queueCommand( + fCommandFactory.createMIGDBSet( + getContainerContext(), + new String[] { + "remote", //$NON-NLS-1$ + "exec-file", //$NON-NLS-1$ + remoteBinary, + }), + new ImmediateDataRequestMonitor(rm)); + } + else { + rm.done(); } } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_2.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_2.java index d9ab8bc5851..4a313fc1d95 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_2.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_2.java @@ -469,10 +469,14 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 { return false; } - // We don't yet support starting a new process on a remote target - // Bug 344890 - if (type == SessionType.REMOTE && fBackend.getIsAttachSession()) { - return false; + // Multi-process does not work for all-stop right now + IMIRunControl runControl = getServicesTracker().getService(IMIRunControl.class); + if (runControl != null && runControl.getRunMode() == MIRunMode.ALL_STOP) { + // Only one process is allowed in all-stop (for now) + return getNumConnected() == 0; + // NOTE: when we support multi-process in all-stop mode, + // we will need to interrupt the target to when starting + // the new process. } return true; diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java index 6f8a2fd69fd..e88e9b6b3ca 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/StartOrRestartProcessSequence_7_0.java @@ -260,10 +260,9 @@ public class StartOrRestartProcessSequence_7_0 extends ReflectionSequence { */ @Execute public void stepInitializeInputOutput(final RequestMonitor rm) { - if (fBackend.getSessionType() == SessionType.REMOTE && !fBackend.getIsAttachSession()) { - // Remote non-attach sessions don't support multi-process and therefore will not - // start new processes. Those sessions will only start the one process, which should - // not have a console, because it's output is handled by GDB server. + if (fBackend.getSessionType() == SessionType.REMOTE) { + // The program input and output for a remote session is handled by gdbserver. + // Therefore, no need to create a pty. fPty = null; rm.done(); } else { @@ -296,11 +295,9 @@ public class StartOrRestartProcessSequence_7_0 extends ReflectionSequence { */ @Execute public void stepCreateConsole(final RequestMonitor rm) { - if (fBackend.getSessionType() == SessionType.REMOTE && !fBackend.getIsAttachSession()) { - // Remote non-attach sessions don't support multi-process and therefore will not - // start new processes. Those sessions will only start the one process, which should - // not have a console, because it's output is handled by GDB server. Therefore, - // no need to create an inferior process and add it to the launch + if (fBackend.getSessionType() == SessionType.REMOTE) { + // The program output for a remote session is handled by gdbserver. Therefore, + // no need to create an inferior process and add it to the launch. rm.done(); return; }