From 143d697e5e2e7fe4faa0d430e34df1f0656e6553 Mon Sep 17 00:00:00 2001 From: Mikhail Khodjaiants Date: Mon, 23 Jan 2006 20:25:43 +0000 Subject: [PATCH] Bug 119683: long messages during launch cause gdb to timeout, launch to fail. --- debug/org.eclipse.cdt.debug.mi.core/ChangeLog | 12 + .../eclipse/cdt/debug/mi/core/MISession.java | 131 +++++- .../plugin.properties | 6 +- .../org.eclipse.cdt.debug.mi.core/plugin.xml | 6 +- .../debug/mi/core/AbstractGDBCDIDebugger.java | 175 +++++++ .../debug/mi/core/CygwinGDBCDIDebugger2.java | 62 +++ .../cdt/debug/mi/core/GDBCDIDebugger2.java | 212 +++++++++ .../debug/mi/core/GDBServerCDIDebugger2.java | 122 +++++ .../eclipse/cdt/debug/mi/core/MIPlugin.java | 107 ++++- .../mi/core/MIPluginResources.properties | 7 + launch/org.eclipse.cdt.launch/ChangeLog | 6 + launch/org.eclipse.cdt.launch/plugin.xml | 6 +- .../internal/LocalCDILaunchDelegate.java | 440 ++++++++++++++++++ .../internal/ui/LaunchMessages.properties | 11 + 14 files changed, 1292 insertions(+), 11 deletions(-) create mode 100644 debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/AbstractGDBCDIDebugger.java create mode 100644 debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/CygwinGDBCDIDebugger2.java create mode 100644 debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/GDBCDIDebugger2.java create mode 100644 debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/GDBServerCDIDebugger2.java create mode 100644 launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalCDILaunchDelegate.java diff --git a/debug/org.eclipse.cdt.debug.mi.core/ChangeLog b/debug/org.eclipse.cdt.debug.mi.core/ChangeLog index 8078eed29b8..867ca5677d9 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/ChangeLog +++ b/debug/org.eclipse.cdt.debug.mi.core/ChangeLog @@ -1,3 +1,15 @@ +2006-01-23 Mikhail Khodjaiants + Bug 119683: long messages during launch cause gdb to timeout, launch to fail. + * plugin.xml + * plugin.properties + * MISession.java + + AbstractGDBCDIDebugger.java + + CygwinGDBCDIDebugger2.java + + GDBCDIDebugger2.java + + GDBServerCDIDebugger2.java + * MIPlugin.java + * MIPluginResources.properties + 2006-01-04 Mikhail Khodjaiants Bug 118900: Display libraries loaded in post-mortem debug. Applied with modifications the patch from Joanne Woo (jwoo.mvista.com). diff --git a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/MISession.java b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/MISession.java index fe4e46dfcda..46b79334a39 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/MISession.java +++ b/debug/org.eclipse.cdt.debug.mi.core/mi/org/eclipse/cdt/debug/mi/core/MISession.java @@ -99,6 +99,7 @@ public class MISession extends Observable { * @param miVersion * @param monitor * @throws MIException + * @deprecated */ public MISession(MIProcess process, IMITTY tty, int type, int commandTimeout, int launchTimeout, String miVersion, IProgressMonitor monitor) throws MIException { this(process, tty, type, new CommandFactory(miVersion), commandTimeout, launchTimeout, monitor); @@ -113,6 +114,7 @@ public class MISession extends Observable { * @param pty Terminal to use for the inferior. * @param timeout time in milliseconds to wait for command response. * @param type the type of debugin session. + * @deprecated */ public MISession(MIProcess process, IMITTY tty, int commandTimeout, int type, int launchTimeout) throws MIException { this(process, tty, type, commandTimeout, launchTimeout, MIVersion.MI1, new NullProgressMonitor()); @@ -130,6 +132,7 @@ public class MISession extends Observable { * @param Process gdb Process. * @param pty Terminal to use for the inferior. * @param timeout time in milliseconds to wait for command response. + * @deprecated */ public MISession(MIProcess process, IMITTY tty, int type, CommandFactory commandFactory, int commandTimeout, int launchTimeout, IProgressMonitor monitor) throws MIException { gdbProcess = process; @@ -156,7 +159,102 @@ public class MISession extends Observable { // initialize/setup setup(launchTimeout, new NullProgressMonitor()); } - + + /** + * Constructor for MISession. Creates MI wrapper for the given gdb process. + * + * @param type the type of debugging session: PROGRAM, ATTACH or CORE + * @param commandFactory the set of gdb/mi commands supported by given gdb + * @param Process a gdb process + * @param pty terminal to use for the inferior. + * @param timeout time in milliseconds to wait for command response. + * + * @since 3.1 + */ + public MISession(MIProcess process, IMITTY tty, int type, CommandFactory commandFactory, int commandTimeout) throws MIException { + gdbProcess = process; + inChannel = process.getInputStream(); + outChannel = process.getOutputStream(); + + factory = commandFactory; + cmdTimeout = commandTimeout; + + sessionType = type; + + parser = new MIParser(); + + inferior = new MIInferior(this, tty); + + txQueue = new CommandQueue(); + rxQueue = new CommandQueue(); + eventQueue = new Queue(); + + txThread = new TxThread(this); + rxThread = new RxThread(this); + eventThread = new EventThread(this); + + setup(); + + txThread.start(); + rxThread.start(); + eventThread.start(); + } + + /** + * No need to pass a progress monitor and a launch timeout. + * @since 3.1 + */ + protected void setup() throws MIException { + // The Process may have terminated earlier because + // of bad arguments etc .. check this here and bail out. + try { + gdbProcess.exitValue(); + InputStream err = gdbProcess.getErrorStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(err)); + String line = null; + try { + line = reader.readLine(); + reader.close(); + } catch (Exception e) { + // the reader may throw a NPE. + } + if (line == null) { + line = MIPlugin.getResourceString("src.MISession.Process_Terminated"); //$NON-NLS-1$ + } + throw new MIException(line); + } catch (IllegalThreadStateException e) { + // Ok, it means the process is alive. + } + } + + /** + * Initializes the gdb session. + * @since 3.1 + */ + public void start() throws MIException { + try { + initialize(); + } catch (MIException exc) { + // Kill the Transmition thread. + if (txThread.isAlive()) { + txThread.interrupt(); + } + // Kill the Receiving Thread. + if (rxThread.isAlive()) { + rxThread.interrupt(); + } + // Kill the event Thread. + if (eventThread.isAlive()) { + eventThread.interrupt(); + } + // rethrow up the exception. + throw exc; + } + } + + /** + * @deprecated use setup() without parameters + */ protected void setup(int launchTimeout, IProgressMonitor monitor) throws MIException { // The Process may have terminated earlier because // of bad arguments etc .. check this here and bail out. @@ -210,7 +308,38 @@ public class MISession extends Observable { throw exc; } } + + /** + * Turns off the "confirm" option of gdb. + * Sets witdth and height of gdb session to 0. + * @since 3.1 + */ + protected void initialize() throws MIException { + // Disable a certain number of irritations from gdb. + // Like confirmation and screen size. + MIGDBSet confirm = getCommandFactory().createMIGDBSet(new String[]{"confirm", "off"}); //$NON-NLS-1$ //$NON-NLS-2$ + postCommand(confirm); + confirm.getMIInfo(); + + MIGDBSet width = getCommandFactory().createMIGDBSet(new String[]{"width", "0"}); //$NON-NLS-1$ //$NON-NLS-2$ + postCommand(width); + width.getMIInfo(); + + MIGDBSet height = getCommandFactory().createMIGDBSet(new String[]{"height", "0"}); //$NON-NLS-1$ //$NON-NLS-2$ + postCommand(height); + height.getMIInfo(); + + useInterpreterExecConsole = canUseInterpreterExecConsole(); + + String prompt = getCLIPrompt(); + if (prompt != null) { + getMIParser().cliPrompt = prompt; + } + } + /** + * @deprecated use initialize() without parameters + */ protected void initialize(int launchTimeout, IProgressMonitor monitor) throws MIException { // Disable a certain number of irritations from gdb. // Like confirmation and screen size. diff --git a/debug/org.eclipse.cdt.debug.mi.core/plugin.properties b/debug/org.eclipse.cdt.debug.mi.core/plugin.properties index e333cedb9ca..9272aeb70dc 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/plugin.properties +++ b/debug/org.eclipse.cdt.debug.mi.core/plugin.properties @@ -11,6 +11,6 @@ pluginName=C/C++ Development Tools GDB/MI CDI Debugger Core providerName=Eclipse.org -GDBDebugger.name=GDB Debugger -CygwinGDBDebugger.name=Cygwin GDB Debugger -GDBServer.name=GDB Server +GDBDebugger.name=gdb Debugger +CygwinGDBDebugger.name=Cygwin gdb Debugger +GDBServer.name=gdbserver Debugger diff --git a/debug/org.eclipse.cdt.debug.mi.core/plugin.xml b/debug/org.eclipse.cdt.debug.mi.core/plugin.xml index ef7e709ff56..00276b71e8f 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/plugin.xml +++ b/debug/org.eclipse.cdt.debug.mi.core/plugin.xml @@ -9,7 +9,7 @@ name="%GDBDebugger.name" modes="run,core,attach" cpu="native" - class="org.eclipse.cdt.debug.mi.core.GDBCDIDebugger" + class="org.eclipse.cdt.debug.mi.core.GDBCDIDebugger2" id="org.eclipse.cdt.debug.mi.core.CDebugger"> diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/AbstractGDBCDIDebugger.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/AbstractGDBCDIDebugger.java new file mode 100644 index 00000000000..f803e33486a --- /dev/null +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/AbstractGDBCDIDebugger.java @@ -0,0 +1,175 @@ +/******************************************************************************* + * Copyright (c) 2004 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: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.mi.core; + +import java.io.File; +import java.text.DateFormat; +import java.text.MessageFormat; +import java.util.Date; +import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; +import org.eclipse.cdt.debug.core.ICDIDebugger2; +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; +import org.eclipse.cdt.debug.core.cdi.CDIException; +import org.eclipse.cdt.debug.core.cdi.ICDISession; +import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; +import org.eclipse.cdt.debug.mi.core.cdi.Session; +import org.eclipse.cdt.debug.mi.core.cdi.model.Target; +import org.eclipse.cdt.debug.mi.core.command.CommandFactory; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.model.IProcess; + +/** + * Base class for the gdb/mi-based ICDIDebugger extension point + * implementations. + */ +abstract public class AbstractGDBCDIDebugger implements ICDIDebugger2 { + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.core.ICDIDebugger#createDebuggerSession(org.eclipse.debug.core.ILaunch, org.eclipse.cdt.core.IBinaryParser.IBinaryObject, org.eclipse.core.runtime.IProgressMonitor) + */ + public ICDISession createDebuggerSession( ILaunch launch, IBinaryObject exe, IProgressMonitor monitor ) throws CoreException { + return createSession( launch, exe.getPath().toFile(), monitor ); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.core.ICDIDebugger2#createSession(org.eclipse.debug.core.ILaunch, java.io.File, org.eclipse.core.runtime.IProgressMonitor) + */ + public ICDISession createSession( ILaunch launch, File executable, IProgressMonitor monitor ) throws CoreException { + boolean failed = false; + if ( monitor == null ) { + monitor = new NullProgressMonitor(); + } + if ( monitor.isCanceled() ) { + throw new OperationCanceledException(); + } + ILaunchConfiguration config = launch.getLaunchConfiguration(); + Session session = createGDBSession( config, executable, monitor ); + if ( session != null ) { + ICDITarget[] targets = session.getTargets(); + for( int i = 0; i < targets.length; i++ ) { + Process debugger = session.getSessionProcess( targets[i] ); + if ( debugger != null ) { + IProcess debuggerProcess = DebugPlugin.newProcess( launch, debugger, renderDebuggerProcessLabel( config ) ); + launch.addProcess( debuggerProcess ); + } + try { + ((Target)targets[i]).getMISession().start(); + } + catch( MIException e ) { + failed = true; + throw newCoreException( e ); + } + } + } + try { + doStartSession( config, session, monitor ); + } + catch( CoreException e ) { + failed = true; + throw e; + } + finally { + try { + if ( failed || monitor.isCanceled() ) + session.terminate(); + } + catch( CDIException e1 ) { + } + } + return session; + } + + protected Session createGDBSession( ILaunchConfiguration config, File executable, IProgressMonitor monitor ) throws CoreException { + String gdb = config.getAttribute( IMILaunchConfigurationConstants.ATTR_DEBUG_NAME, "gdb" ); //$NON-NLS-1$ + CommandFactory factory = getCommandFactory( config ); + String[] extraArgs = getExtraArguments( config ); + boolean usePty = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_USE_TERMINAL, true ); + try { + return MIPlugin.getDefault().createSession( getSessionType( config ), gdb, factory, executable, extraArgs, usePty, monitor ); + } + catch( Exception e ) { + // Catch all wrap them up and rethrow + if ( e instanceof CoreException ) { + throw (CoreException)e; + } + throw newCoreException( e ); + } + } + + protected int getSessionType( ILaunchConfiguration config ) throws CoreException { + String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN ); + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN.equals( debugMode ) ) + return MISession.PROGRAM; + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH.equals( debugMode ) ) + return MISession.ATTACH; + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE.equals( debugMode ) ) + return MISession.CORE; + throw newCoreException( MIPlugin.getResourceString( "src.AbstractGDBCDIDebugger.0" ) + debugMode, null ); //$NON-NLS-1$ + } + + abstract protected String[] getExtraArguments( ILaunchConfiguration config ) throws CoreException; + + abstract protected CommandFactory getCommandFactory( ILaunchConfiguration config ) throws CoreException; + + protected void doStartSession( ILaunchConfiguration config, Session session, IProgressMonitor monitor ) throws CoreException { + } + + protected String renderDebuggerProcessLabel( ILaunchConfiguration config ) { + String format = "{0} ({1})"; //$NON-NLS-1$ + String timestamp = DateFormat.getInstance().format( new Date( System.currentTimeMillis() ) ); + String label = MIPlugin.getResourceString( "src.AbstractGDBCDIDebugger.0" ); //$NON-NLS-1$ + try { + label = config.getAttribute( IMILaunchConfigurationConstants.ATTR_DEBUG_NAME, "gdb" ); //$NON-NLS-1$ + } + catch( CoreException e ) { + } + return MessageFormat.format( format, new String[]{ label, timestamp } ); + } + + /** + * Throws a core exception with an error status object built from + * the lower level exception and error code. + * + * @param exception lower level exception associated with the error, + * or null if none + * @param code error code + */ + protected CoreException newCoreException( Throwable exception ) { + String message = MIPlugin.getResourceString( "src.AbstractGDBCDIDebugger.1" ); //$NON-NLS-1$ + return newCoreException( message, exception ); + } + + /** + * Throws a core exception with an error status object built from the given + * message, lower level exception, and error code. + * + * @param message the status message + * @param exception lower level exception associated with the error, + * or null if none + * @param code error code + */ + protected CoreException newCoreException( String message, Throwable exception ) { + int code = ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR; + String ID = MIPlugin.getUniqueIdentifier(); + MultiStatus status = new MultiStatus( ID, code, message, exception ); + status.add( new Status( IStatus.ERROR, ID, code, exception == null ? new String() : exception.getLocalizedMessage(), exception ) ); + return new CoreException( status ); + } +} diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/CygwinGDBCDIDebugger2.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/CygwinGDBCDIDebugger2.java new file mode 100644 index 00000000000..9453d036df4 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/CygwinGDBCDIDebugger2.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2004 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: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.mi.core; + +import org.eclipse.cdt.debug.mi.core.cdi.Session; +import org.eclipse.cdt.debug.mi.core.command.CommandFactory; +import org.eclipse.cdt.debug.mi.core.command.MIGDBSet; +import org.eclipse.cdt.debug.mi.core.output.MIInfo; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.debug.core.ILaunchConfiguration; + +/** + * Cygwin debugger extension point. + */ +public class CygwinGDBCDIDebugger2 extends GDBCDIDebugger2 { + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.mi.core.GDBCDIDebugger2#getCommandFactory(org.eclipse.debug.core.ILaunchConfiguration) + */ + protected CommandFactory getCommandFactory( ILaunchConfiguration config ) throws CoreException { + return new CygwinCommandFactory( getMIVersion( config ) ); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.mi.core.GDBCDIDebugger2#doStartSession(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.cdt.debug.mi.core.cdi.Session, org.eclipse.core.runtime.IProgressMonitor) + */ + protected void doStartSession( ILaunchConfiguration config, Session session, IProgressMonitor monitor ) throws CoreException { + // For windows we need to start the inferior in a new console window + // to separate the Inferior std{in,out,err} from gdb std{in,out,err} + MISession miSession = getMISession( session ); + try { + CommandFactory factory = miSession.getCommandFactory(); + MIGDBSet set = factory.createMIGDBSet( new String[]{ "new-console" } ); //$NON-NLS-1$ + miSession.postCommand( set ); + MIInfo info = set.getMIInfo(); + if ( info == null ) { + throw new MIException( MIPlugin.getResourceString( "src.common.No_answer" ) ); //$NON-NLS-1$ + } + } + catch( MIException e ) { + // We ignore this exception, for example + // on GNU/Linux the new-console is an error. + } + super.doStartSession( config, session, monitor ); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.mi.core.GDBCDIDebugger2#initializeLibraries(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.cdt.debug.mi.core.cdi.Session) + */ + protected void initializeLibraries( ILaunchConfiguration config, Session session ) throws CoreException { + // the "search-solib-path" and "stop-on-solib-events" options are not supported in CygWin + } +} diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/GDBCDIDebugger2.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/GDBCDIDebugger2.java new file mode 100644 index 00000000000..628509e1053 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/GDBCDIDebugger2.java @@ -0,0 +1,212 @@ +/******************************************************************************* + * Copyright (c) 2004 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: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.mi.core; + +import java.io.File; +import java.text.MessageFormat; +import java.util.Collections; +import java.util.List; +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; +import org.eclipse.cdt.debug.core.cdi.CDIException; +import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; +import org.eclipse.cdt.debug.mi.core.cdi.Session; +import org.eclipse.cdt.debug.mi.core.cdi.SharedLibraryManager; +import org.eclipse.cdt.debug.mi.core.cdi.model.Target; +import org.eclipse.cdt.debug.mi.core.command.CLITargetAttach; +import org.eclipse.cdt.debug.mi.core.command.CommandFactory; +import org.eclipse.cdt.debug.mi.core.output.MIInfo; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Path; +import org.eclipse.debug.core.ILaunchConfiguration; + +/** + * Implementing the cdebugger extension point for basic launch configurations. + */ +public class GDBCDIDebugger2 extends AbstractGDBCDIDebugger { + + protected String[] getExtraArguments( ILaunchConfiguration config ) throws CoreException { + String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN ); + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN.equals( debugMode ) ) + return getRunArguments( config ); + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH.equals( debugMode ) ) + return getAttachArguments( config ); + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE.equals( debugMode ) ) + return getCoreArguments( config ); + return new String[0]; + } + + protected String[] getRunArguments( ILaunchConfiguration config ) throws CoreException { + return new String[]{ getWorkingDirectory( config ), getCommandFile( config ) }; + } + + protected String[] getAttachArguments( ILaunchConfiguration config ) throws CoreException { + return new String[]{ getWorkingDirectory( config ), getCommandFile( config ) }; + } + + protected String[] getCoreArguments( ILaunchConfiguration config ) throws CoreException { + IPath coreFile = new Path( config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, (String)null ) ); + return new String[]{ getWorkingDirectory( config ), getCommandFile( config ), "-c", coreFile.toFile().getAbsolutePath() }; //$NON-NLS-1$ + } + + protected CommandFactory getCommandFactory( ILaunchConfiguration config ) throws CoreException { + return new CommandFactory( getMIVersion( config ) ); + } + + public static IPath getProjectPath( ILaunchConfiguration configuration ) throws CoreException { + String projectName = getProjectName( configuration ); + if ( projectName != null ) { + projectName = projectName.trim(); + if ( projectName.length() > 0 ) { + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject( projectName ); + IPath p = project.getLocation(); + if ( p != null ) { + return p; + } + } + } + return Path.EMPTY; + } + + public static String getProjectName( ILaunchConfiguration configuration ) throws CoreException { + return configuration.getAttribute( ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null ); + } + + protected String getMIVersion( ILaunchConfiguration config ) { + return MIPlugin.getMIVersion( config ); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.mi.core.AbstractGDBCDIDebugger#doStartSession(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.cdt.debug.mi.core.cdi.Session, org.eclipse.core.runtime.IProgressMonitor) + */ + protected void doStartSession( ILaunchConfiguration config, Session session, IProgressMonitor monitor ) throws CoreException { + initializeLibraries( config, session ); + if ( monitor.isCanceled() ) { + throw new OperationCanceledException(); + } + String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN ); + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN.equals( debugMode ) ) + startLocalGDBSession( config, session, monitor ); + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH.equals( debugMode ) ) + startAttachGDBSession( config, session, monitor ); + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE.equals( debugMode ) ) + startCoreGDBSession( config, session, monitor ); + } + + protected void startLocalGDBSession( ILaunchConfiguration config, Session session, IProgressMonitor monitor ) throws CoreException { + + } + + protected void startAttachGDBSession( ILaunchConfiguration config, Session session, IProgressMonitor monitor ) throws CoreException { + MISession miSession = getMISession( session ); + CommandFactory factory = miSession.getCommandFactory(); + int pid = -1; + try { + pid = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_ATTACH_PROCESS_ID, -1 ); + } + catch( CoreException e ) { + throw newCoreException( MIPlugin.getResourceString( "src.GDBCDIDebugger2.0" ), e ); //$NON-NLS-1$ + } + if ( pid <= 0 ) { + throw newCoreException( MIPlugin.getResourceString( "src.GDBCDIDebugger2.1" ), null ); //$NON-NLS-1$ + } + try { + CLITargetAttach attach = factory.createCLITargetAttach( pid ); + miSession.postCommand( attach ); + MIInfo info = attach.getMIInfo(); + if ( info == null ) { + throw new MIException( MIPlugin.getResourceString( "src.common.No_answer" ) ); //$NON-NLS-1$ + } + miSession.getMIInferior().setInferiorPID( pid ); + // @@@ for attach we nee to manually set the connected state + // attach does not send the ^connected ack + miSession.getMIInferior().setConnected(); + } + catch( MIException e ) { + throw newCoreException( MessageFormat.format( MIPlugin.getResourceString( "src.GDBCDIDebugger2.2" ), new Integer[] { Integer.valueOf( pid ) } ), e ); //$NON-NLS-1$ + } + // @@@ We have to set the suspended state manually + miSession.getMIInferior().setSuspended(); + miSession.getMIInferior().update(); + } + + protected void startCoreGDBSession( ILaunchConfiguration config, Session session, IProgressMonitor monitor ) throws CoreException { + getMISession( session ).getMIInferior().setSuspended(); + try { + session.getSharedLibraryManager().update(); + } + catch( CDIException e ) { + throw newCoreException( e ); + } + } + + protected MISession getMISession( Session session ) { + ICDITarget[] targets = session.getTargets(); + if ( targets.length == 0 || !(targets[0] instanceof Target) ) + return null; + return ((Target)targets[0]).getMISession(); + } + + protected void initializeLibraries( ILaunchConfiguration config, Session session ) throws CoreException { + try { + SharedLibraryManager sharedMgr = session.getSharedLibraryManager(); + boolean autolib = config.getAttribute( IMILaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB, IMILaunchConfigurationConstants.DEBUGGER_AUTO_SOLIB_DEFAULT ); + boolean stopOnSolibEvents = config.getAttribute( IMILaunchConfigurationConstants.ATTR_DEBUGGER_STOP_ON_SOLIB_EVENTS, IMILaunchConfigurationConstants.DEBUGGER_STOP_ON_SOLIB_EVENTS_DEFAULT ); + List p = config.getAttribute( IMILaunchConfigurationConstants.ATTR_DEBUGGER_SOLIB_PATH, Collections.EMPTY_LIST ); + ICDITarget[] dtargets = session.getTargets(); + for( int i = 0; i < dtargets.length; ++i ) { + Target target = (Target)dtargets[i]; + try { + sharedMgr.setAutoLoadSymbols( target, autolib ); + sharedMgr.setStopOnSolibEvents( target, stopOnSolibEvents ); + // The idea is that if the user set autolib, by default + // we provide with the capability of deferred breakpoints + // And we set setStopOnSolib events for them(but they should not see those things. + // + // If the user explicitly set stopOnSolibEvents well it probably + // means that they wanted to see those events so do no do deferred breakpoints. + if ( autolib && !stopOnSolibEvents ) { + sharedMgr.setDeferredBreakpoint( true ); + sharedMgr.setStopOnSolibEvents( target, true ); + } + } + catch( CDIException e ) { + // Ignore this error + // it seems to be a real problem on many gdb platform + } + if ( p.size() > 0 ) { + String[] oldPaths = sharedMgr.getSharedLibraryPaths( target ); + String[] paths = new String[oldPaths.length + p.size()]; + System.arraycopy( p.toArray( new String[p.size()] ), 0, paths, 0, p.size() ); + System.arraycopy( oldPaths, 0, paths, p.size(), oldPaths.length ); + sharedMgr.setSharedLibraryPaths( target, paths ); + } + } + } + catch( CDIException e ) { + throw newCoreException( MIPlugin.getResourceString( "src.GDBDebugger.Error_initializing_shared_lib_options" ) + e.getMessage(), e ); //$NON-NLS-1$ + } + } + + private String getWorkingDirectory( ILaunchConfiguration config ) throws CoreException { + File cwd = getProjectPath( config ).toFile(); + return "--cd=" + cwd.getAbsolutePath(); //$NON-NLS-1$ + } + + private String getCommandFile( ILaunchConfiguration config ) throws CoreException { + String gdbinit = config.getAttribute( IMILaunchConfigurationConstants.ATTR_GDB_INIT, IMILaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT ); + return (gdbinit != null && gdbinit.length() > 0) ? "--command=" + gdbinit : "--nx"; //$NON-NLS-1$ //$NON-NLS-2$ + } +} diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/GDBServerCDIDebugger2.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/GDBServerCDIDebugger2.java new file mode 100644 index 00000000000..ae731de1725 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/GDBServerCDIDebugger2.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2004 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: + * QNX Software Systems - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.mi.core; + +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; +import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; +import org.eclipse.cdt.debug.mi.core.cdi.Session; +import org.eclipse.cdt.debug.mi.core.cdi.model.Target; +import org.eclipse.cdt.debug.mi.core.command.CommandFactory; +import org.eclipse.cdt.debug.mi.core.command.MIGDBSet; +import org.eclipse.cdt.debug.mi.core.command.MITargetSelect; +import org.eclipse.cdt.debug.mi.core.output.MIInfo; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.debug.core.ILaunchConfiguration; + +/** + * Implementing the cdebugger extension point for gdbserver. + */ +public class GDBServerCDIDebugger2 extends GDBCDIDebugger2 { + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.mi.core.GDBCDIDebugger2#doStartSession(org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.cdt.debug.mi.core.cdi.Session, org.eclipse.core.runtime.IProgressMonitor) + */ + protected void doStartSession( ILaunchConfiguration config, Session session, IProgressMonitor monitor ) throws CoreException { + initializeLibraries( config, session ); + if ( monitor.isCanceled() ) { + throw new OperationCanceledException(); + } + String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN ); + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN.equals( debugMode ) ) + startGDBServerSession( config, session, monitor ); + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH.equals( debugMode ) ) { + String msg = MIPlugin.getResourceString( "src.GDBServerDebugger.GDBServer_attaching_unsupported" ); //$NON-NLS-1$ + throw newCoreException( msg, null ); + } + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE.equals( debugMode ) ) { + String msg = MIPlugin.getResourceString( "src.GDBServerDebugger.GDBServer_corefiles_unsupported" ); //$NON-NLS-1$ + throw newCoreException( msg, null ); + } + } + + protected void startGDBServerSession( ILaunchConfiguration config, Session session, IProgressMonitor monitor ) throws CoreException { + if ( monitor.isCanceled() ) { + throw new OperationCanceledException(); + } + ICDITarget[] targets = session.getTargets(); + int launchTimeout = MIPlugin.getLaunchTimeout(); + boolean tcpConnection = config.getAttribute( IGDBServerMILaunchConfigurationConstants.ATTR_REMOTE_TCP, false ); + // Set serial line parameters + if ( !tcpConnection ) { + String remoteBaud = config.getAttribute( IGDBServerMILaunchConfigurationConstants.ATTR_DEV_SPEED, "invalid" ); //$NON-NLS-1$ + for( int i = 0; i < targets.length; ++i ) { + if ( monitor.isCanceled() ) { + throw new OperationCanceledException(); + } + Target target = (Target)targets[i]; + MISession miSession = target.getMISession(); + CommandFactory factory = miSession.getCommandFactory(); + MIGDBSet setRemoteBaud = factory.createMIGDBSet( new String[]{ "remotebaud", remoteBaud } ); //$NON-NLS-1$ + // Set serial line parameters + MIInfo info = null; + MIException ex = null; + try { + // shouldn't we use the command timeout instead? + miSession.postCommand( setRemoteBaud, launchTimeout ); + info = setRemoteBaud.getMIInfo(); + } + catch( MIException e ) { + ex = e; + } + if ( info == null ) { + throw newCoreException( MIPlugin.getResourceString( "src.GDBServerDebugger.Can_not_set_Baud" ), ex ); //$NON-NLS-1$ + } + } + } + for( int i = 0; i < targets.length; ++i ) { + if ( monitor.isCanceled() ) { + throw new OperationCanceledException(); + } + Target target = (Target)targets[i]; + MISession miSession = target.getMISession(); + CommandFactory factory = miSession.getCommandFactory(); + String[] targetParams = getTargetParams( config, tcpConnection ); + MITargetSelect select = factory.createMITargetSelect( targetParams ); + MIInfo info = null; + MIException ex = null; + try { + miSession.postCommand( select, launchTimeout ); + info = select.getMIInfo(); + } + catch( MIException e ) { + ex = e; + } + if ( info == null ) { + throw newCoreException( MIPlugin.getResourceString( "src.GDBServerCDIDebugger.target_selection_failed" ), ex ); //$NON-NLS-1$ + } + } + } + + protected String[] getTargetParams( ILaunchConfiguration config, boolean tcpConnection ) throws CoreException { + String remote = null; + if ( tcpConnection ) { + remote = config.getAttribute( IGDBServerMILaunchConfigurationConstants.ATTR_HOST, "invalid" ); //$NON-NLS-1$ + remote += ":"; //$NON-NLS-1$ + remote += config.getAttribute( IGDBServerMILaunchConfigurationConstants.ATTR_PORT, "invalid" ); //$NON-NLS-1$ + } + else { + remote = config.getAttribute( IGDBServerMILaunchConfigurationConstants.ATTR_DEV, "invalid" ); //$NON-NLS-1$ + } + return new String[]{ "remote", remote }; //$NON-NLS-1$ + } +} diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java index 89eddb07983..88678425ee8 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPlugin.java @@ -15,9 +15,10 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; import java.util.MissingResourceException; import java.util.ResourceBundle; - import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.debug.mi.core.cdi.Session; import org.eclipse.cdt.debug.mi.core.command.CLITargetAttach; @@ -83,6 +84,8 @@ public class MIPlugin extends Plugin { * @param int * @throws MIException * @return MISession + * + * @deprecated */ public MISession createMISession(MIProcess process, IMITTY pty, int timeout, int type, int launchTimeout, String miVersion, IProgressMonitor monitor) throws MIException { return new MISession(process, pty, type, timeout, launchTimeout, miVersion, monitor); @@ -95,6 +98,8 @@ public class MIPlugin extends Plugin { * @param type * @throws MIException * @return MISession + * + * @deprecated */ public MISession createMISession(MIProcess process, IMITTY pty, int type, String miVersion, IProgressMonitor monitor) throws MIException { MIPlugin miPlugin = getDefault(); @@ -104,12 +109,18 @@ public class MIPlugin extends Plugin { return createMISession(process, pty, timeout, type, launchTimeout, miVersion, monitor); } + private MISession createMISession0(int type, MIProcess process, CommandFactory commandFactory, IMITTY pty, int timeout) throws MIException { + return new MISession(process, pty, type, commandFactory, timeout); + } + /** * Method createCSession; Create an new PTY instance and launch gdb in mi for local debug. * * @param program * @return ICDISession * @throws MIException + * + * @deprecated use createSession */ public Session createCSession(String gdb, String miVersion, File program, File cwd, String gdbinit, IProgressMonitor monitor) throws IOException, MIException { IMITTY pty = null; @@ -155,6 +166,8 @@ public class MIPlugin extends Plugin { * @param program * @return ICDISession * @throws IOException + * + * @deprecated use createSession */ public Session createCSession(String gdb, String miVersion, File program, File cwd, String gdbinit, IMITTY pty, IProgressMonitor monitor) throws IOException, MIException { if (gdb == null || gdb.length() == 0) { @@ -228,6 +241,8 @@ public class MIPlugin extends Plugin { * @param core * @return ICDISession * @throws IOException + * + * @deprecated use createSession */ public Session createCSession(String gdb, String miVersion, File program, File core, File cwd, String gdbinit, IProgressMonitor monitor) throws IOException, MIException { if (gdb == null || gdb.length() == 0) { @@ -277,6 +292,8 @@ public class MIPlugin extends Plugin { * @param pid * @return ICDISession * @throws IOException + * + * @deprecated use createSession */ public Session createCSession(String gdb, String miVersion, File program, int pid, String[] targetParams, File cwd, String gdbinit, IProgressMonitor monitor) throws IOException, MIException { if (gdb == null || gdb.length() == 0) { @@ -347,6 +364,84 @@ public class MIPlugin extends Plugin { return new Session(session, true); } + /** + * Starts a process by executing the following command: + * gdb -q -nw -i (extracted from the command factory) + * -tty (if usePTY is true) + * extraArgs program (if program is not null) + * + * @param sessionType the type of debugging session: + * MISession.PROGRAM, + * MISession.ATTACH + * or MISession.CORE + * @param gdb the name of the gdb file + * @param factory the command set supported by gdb + * @param program a program to debug or null + * @param extraArgs arguments to pass to gdb + * @param usePty whether to use pty or not + * @param monitor a progress monitor + * @return an instance of ICDISession + * @throws IOException + * @throws MIException + */ + public Session createSession(int sessionType, String gdb, CommandFactory factory, File program, String[] extraArgs, boolean usePty, IProgressMonitor monitor) throws IOException, MIException { + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + + if (gdb == null || gdb.length() == 0) { + gdb = GDB; + } + + IMITTY pty = null; + + if (usePty) { + try { + PTY pseudo = new PTY(); + pty = new MITTYAdapter(pseudo); + } catch (IOException e) { + // Should we not print/log this ? + } + } + + ArrayList argList = new ArrayList(extraArgs.length + 8); + argList.add(gdb); + argList.add("-q"); //$NON-NLS-1$ + argList.add("-nw"); //$NON-NLS-1$ + argList.add("-i"); //$NON-NLS-1$ + argList.add(factory.getMIVersion()); + if (pty != null) { + argList.add("-tty"); //$NON-NLS-1$ + argList.add(pty.getSlaveName()); + } + argList.addAll(Arrays.asList(extraArgs)); + if (program != null) { + argList.add(program.getAbsolutePath()); + } + String[] args = (String[])argList.toArray(new String[argList.size()]); + int launchTimeout = MIPlugin.getDefault().getPluginPreferences().getInt(IMIConstants.PREF_REQUEST_LAUNCH_TIMEOUT); + MIProcess pgdb = new MIProcessAdapter(args, launchTimeout, monitor); + + if (MIPlugin.getDefault().isDebugging()) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < args.length; ++i) { + sb.append(args[i]); + sb.append(' '); + } + MIPlugin.getDefault().debugLog(sb.toString()); + } + + MISession miSession; + try { + miSession = createMISession0(sessionType, pgdb, factory, pty, getCommandTimeout()); + } catch (MIException e) { + pgdb.destroy(); + throw e; + } + + return new Session(miSession); + } + /** * Convenience method which returns the unique identifier of this plugin. */ @@ -407,6 +502,16 @@ public class MIPlugin extends Plugin { super.stop(context); } + public static int getCommandTimeout() { + Preferences prefs = getDefault().getPluginPreferences(); + return prefs.getInt(IMIConstants.PREF_REQUEST_TIMEOUT); + } + + public static int getLaunchTimeout() { + Preferences prefs = plugin.getPluginPreferences(); + return prefs.getInt(IMIConstants.PREF_REQUEST_LAUNCH_TIMEOUT); + } + public static String getMIVersion( ILaunchConfiguration config ) { String miVersion = ""; //$NON-NLS-1$ try { diff --git a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPluginResources.properties b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPluginResources.properties index eda3217780e..ee74d64d21b 100644 --- a/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPluginResources.properties +++ b/debug/org.eclipse.cdt.debug.mi.core/src/org/eclipse/cdt/debug/mi/core/MIPluginResources.properties @@ -10,10 +10,14 @@ ############################################################################### src.common.No_answer=No answer +src.GDBCDIDebugger2.0=Unable to get pid. +src.GDBCDIDebugger2.1=Invalid pid. +src.GDBCDIDebugger2.2=Attach to process {0} failed. src.GDBServerDebugger.Error_initializing=Error initializing: src.GDBServerDebugger.Can_not_set_Baud=Can not set Baud src.GDBServerDebugger.GDBServer_attaching_unsupported=GDBServer does not support attaching src.GDBServerDebugger.GDBServer_corefiles_unsupported=GDBServer does not support core files +src.GDBServerCDIDebugger.target_selection_failed=Target selection failed. src.GDBDebugger.Error_initializing_shared_lib_options=Error initializing shared library options: src.GDBDebugger.Error_creating_session=Error creating session: src.GDBDebugger.Error_launch_timeout=Launch timeout @@ -29,3 +33,6 @@ src.MIInferior.target_is_suspended=target is suspended src.MIInferior.No_session=No MI Session src.MIInferior.Failed_to_interrupt=Failed to interrupt +src.AbstractGDBCDIDebugger.0=Invalid session type: +src.AbstractGDBCDIDebugger.0=Debugger Process +src.AbstractGDBCDIDebugger.1=Error creating session diff --git a/launch/org.eclipse.cdt.launch/ChangeLog b/launch/org.eclipse.cdt.launch/ChangeLog index 38e1f300502..1ddee5a5a40 100644 --- a/launch/org.eclipse.cdt.launch/ChangeLog +++ b/launch/org.eclipse.cdt.launch/ChangeLog @@ -1,3 +1,9 @@ +2006-01-23 Mikhail Khodjaiants + Bug 119683: long messages during launch cause gdb to timeout, launch to fail. + + LocalCDILaunchDelegate.java + * LaunchMessages.properties + * plugin.xml + 2006-01-06 Mikhail Khodjaiants Bug 120509: CDebuggerTab invokes wong initialization code (in addition to right code). * CDebuggerTab.java diff --git a/launch/org.eclipse.cdt.launch/plugin.xml b/launch/org.eclipse.cdt.launch/plugin.xml index 704c5598f02..21198619883 100644 --- a/launch/org.eclipse.cdt.launch/plugin.xml +++ b/launch/org.eclipse.cdt.launch/plugin.xml @@ -6,7 +6,7 @@ point="org.eclipse.debug.core.launchConfigurationTypes"> ERR_WORKING_DIRECTORY_NOT_SUPPORTED is queried to see if + * the exec should be re-executed without specifying a working directory. + * + * @param cmdLine + * the command line + * @param workingDirectory + * the working directory, or null + * @return the resulting process or null if the exec is + * cancelled + * @see Runtime + */ + protected Process exec( String[] cmdLine, String[] environ, File workingDirectory, boolean usePty ) throws CoreException { + Process p = null; + try { + if ( workingDirectory == null ) { + p = ProcessFactory.getFactory().exec( cmdLine, environ ); + } + else { + if ( usePty && PTY.isSupported() ) { + p = ProcessFactory.getFactory().exec( cmdLine, environ, workingDirectory, new PTY() ); + } + else { + p = ProcessFactory.getFactory().exec( cmdLine, environ, workingDirectory ); + } + } + } + catch( IOException e ) { + if ( p != null ) { + p.destroy(); + } + abort( LaunchMessages.getString( "LocalCDILaunchDelegate.8" ), e, ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR ); //$NON-NLS-1$ + } + catch( NoSuchMethodError e ) { + // attempting launches on 1.2.* - no ability to set working + // directory + IStatus status = new Status( IStatus.ERROR, LaunchUIPlugin.getUniqueIdentifier(), ICDTLaunchConfigurationConstants.ERR_WORKING_DIRECTORY_NOT_SUPPORTED, LaunchMessages.getString( "LocalCDILaunchDelegate.9" ), e ); //$NON-NLS-1$ + IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler( status ); + if ( handler != null ) { + Object result = handler.handleStatus( status, this ); + if ( result instanceof Boolean && ((Boolean)result).booleanValue() ) { + p = exec( cmdLine, environ, null, usePty ); + } + } + } + return p; + } + + protected int promptForProcessID( ILaunchConfiguration config ) throws CoreException { + IStatus fPromptStatus = new Status( IStatus.INFO, "org.eclipse.debug.ui", 200, "", null ); //$NON-NLS-1$//$NON-NLS-2$ + IStatus processPrompt = new Status( IStatus.INFO, "org.eclipse.cdt.launch", 100, "", null ); //$NON-NLS-1$//$NON-NLS-2$ + // consult a status handler + IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler( fPromptStatus ); + if ( prompter != null ) { + Object result = prompter.handleStatus( processPrompt, config ); + if ( result instanceof Integer ) { + return ((Integer)result).intValue(); + } + } + return -1; + } + + protected IPath promptForCoreFilePath( final IProject project, final ICDebugConfiguration debugConfig ) throws CoreException { + IStatus fPromptStatus = new Status( IStatus.INFO, "org.eclipse.debug.ui", 200, "", null ); //$NON-NLS-1$//$NON-NLS-2$ + IStatus processPrompt = new Status( IStatus.INFO, "org.eclipse.cdt.launch", 101, "", null ); //$NON-NLS-1$//$NON-NLS-2$ + // consult a status handler + IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler( fPromptStatus ); + if ( prompter != null ) { + Object result = prompter.handleStatus( processPrompt, new Object[]{ project, debugConfig } ); + if ( result instanceof IPath ) { + return (IPath)result; + } + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#preLaunchCheck(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.core.runtime.IProgressMonitor) + */ + public boolean preLaunchCheck( ILaunchConfiguration config, String mode, IProgressMonitor monitor ) throws CoreException { + // no pre launch check for core file + if ( mode.equals( ILaunchManager.DEBUG_MODE ) ) { + if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE.equals( config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN ) ) ) + return true; + } + return super.preLaunchCheck( config, mode, monitor ); + } + + private void setRuntimeOptions( ILaunchConfiguration config, ICDISession session ) throws CoreException { + String arguments[] = getProgramArgumentsArray( config ); + try { + ICDITarget[] dtargets = session.getTargets(); + for( int i = 0; i < dtargets.length; ++i ) { + ICDIRuntimeOptions opt = dtargets[i].getRuntimeOptions(); + opt.setArguments( arguments ); + File wd = getWorkingDirectory( config ); + if ( wd != null ) { + opt.setWorkingDirectory( wd.getAbsolutePath() ); + } + opt.setEnvironment( getEnvironmentAsProperty( config ) ); + } + } + catch( CDIException e ) { + abort( LaunchMessages.getString( "LocalCDILaunchDelegate.10" ), e, ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR ); //$NON-NLS-1$ + } + } + + private ICDISession createCDISession( ILaunchConfiguration config, ILaunch launch, ICDebugConfiguration debugConfig, IProgressMonitor monitor ) throws CoreException { + ICDISession session = null; + ICDIDebugger debugger = debugConfig.createDebugger(); + if ( debugger instanceof ICDIDebugger2 ) + session = launchDebugSession( config, launch, (ICDIDebugger2)debugger, monitor ); + else + // support old debugger types + session = launchOldDebugSession( config, launch, debugger, monitor ); + return session; + } +} diff --git a/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/ui/LaunchMessages.properties b/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/ui/LaunchMessages.properties index fa333668407..c4b3c48a34c 100644 --- a/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/ui/LaunchMessages.properties +++ b/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/ui/LaunchMessages.properties @@ -143,3 +143,14 @@ Launch.common.QualifierColon=Qualifier: Launch.common.Browse_1=&Browse... Launch.common.Browse_2=B&rowse... Launch.common.Project_does_not_exist=Project does not exist +LocalCDILaunchDelegate.0=Launching Local C/C++ Application +LocalCDILaunchDelegate.1=Launching debugger session +LocalCDILaunchDelegate.2=Debugging local C/C++ application +LocalCDILaunchDelegate.3=Attaching to Local C/C++ Application +LocalCDILaunchDelegate.4=No Process ID selected. +LocalCDILaunchDelegate.5=Launching postmortem debugger session +LocalCDILaunchDelegate.6=No core file selected +LocalCDILaunchDelegate.7=Core file does not exist or is not readable. +LocalCDILaunchDelegate.8=Error starting process. +LocalCDILaunchDelegate.9=Eclipse runtime does not support working directory. +LocalCDILaunchDelegate.10=Failed to set program arguments, environment or working directory.