From 6be52837ae6861f2b2306e9f774dec7a420dff8f Mon Sep 17 00:00:00 2001 From: Iulia Vasii Date: Mon, 29 Sep 2014 17:24:55 +0300 Subject: [PATCH] Bug 445360 - Can't debug when GDB path contains spaces. Separate gdb command from its arguments. In java 7, Runtime.exec(String,...) methods were improved and applications that are using these methods with commands that contain spaces in the program name will fail. Is is encouraged to use Runtime.exec(String[],...) instead to separate command from its arguments. See documentation: http://www.oracle.com/technetwork/java/javase/7u21-relnotes-1932873.html#jruntime Change-Id: I03d44284c07be4eb26b393c35e620a79a803ab96 Signed-off-by: Iulia Vasii Reviewed-on: https://git.eclipse.org/r/34052 Tested-by: Hudson CI Reviewed-by: Marc Khouzam Tested-by: Marc Khouzam --- .../cdt/dsf/gdb/launching/LaunchUtils.java | 11 ++-- .../cdt/dsf/gdb/service/GDBBackend.java | 59 ++++++++++++++----- 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java index bb1bf59196f..9145957ecb4 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java @@ -11,6 +11,7 @@ * Sergey Prigogin (Google) * Marc Khouzam (Ericsson) - Add timer when fetching GDB version (Bug 376203) * Marc Khouzam (Ericsson) - Better error reporting when obtaining GDB version (Bug 424996) + * Iulia Vasii (Freescale Semiconductor) - Separate GDB command from its arguments (Bug 445360) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.launching; @@ -36,6 +37,7 @@ import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.CoreModelUtil; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.parser.util.StringUtil; import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; import org.eclipse.cdt.core.settings.model.ICProjectDescription; @@ -297,11 +299,12 @@ public class LaunchUtils { * A timeout is scheduled which will kill the process if it takes too long. */ public static String getGDBVersion(final ILaunchConfiguration configuration) throws CoreException { - String cmd = getGDBPath(configuration).toOSString() + " --version"; //$NON-NLS-1$ + String cmd = getGDBPath(configuration).toOSString(); + String[] args = new String[] { cmd, "--version" }; //$NON-NLS-1$ Process process = null; Job timeoutJob = null; try { - process = ProcessFactory.getFactory().exec(cmd, getLaunchEnvironment(configuration)); + process = ProcessFactory.getFactory().exec(args, getLaunchEnvironment(configuration)); // Start a timeout job to make sure we don't get stuck waiting for // an answer from a gdb that is hanging @@ -336,13 +339,13 @@ public class LaunchUtils { } throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, - "Could not determine GDB version using command: " + cmd, //$NON-NLS-1$ + "Could not determine GDB version using command: " + StringUtil.join(args, " "), //$NON-NLS-1$ //$NON-NLS-2$ detailedException)); } return gdbVersion; } catch (IOException e) { throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, - "Error with command: " + cmd, e));//$NON-NLS-1$ + "Error with command: " + StringUtil.join(args, " "), e));//$NON-NLS-1$ //$NON-NLS-2$ } finally { // If we get here we are obviously not stuck reading the stream so we can cancel the timeout job. // Note that it may already have executed, but that is not a problem. diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java index 50b0c3e5c87..0ea5ab12497 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java @@ -11,6 +11,7 @@ * Ericsson * Marc Khouzam (Ericsson) - Use the new IMIBackend2 interface (Bug 350837) * Mark Bozeman (Mentor Graphics) - Report GDB start failures (Bug 376203) + * Iulia Vasii (Freescale Semiconductor) - Separate GDB command from its arguments (Bug 445360) *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.service; @@ -28,6 +29,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.parser.util.StringUtil; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; @@ -180,25 +182,35 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa return LaunchUtils.getGDBPath(fLaunchConfiguration); } - /* + /** * Options for GDB process. * Allow subclass to override. + * @deprecated Use {@link #getGDBCommandLineArray()} instead */ + @Deprecated protected String getGDBCommandLine() { - StringBuffer gdbCommandLine = new StringBuffer(getGDBPath().toOSString()); + String cmdArray[] = getGDBCommandLineArray(); + return StringUtil.join(cmdArray, " "); //$NON-NLS-1$ + } + /** + * Options for GDB process. + * Returns the GDB command and its arguments as an array. + * Allow subclass to override. + * @since 4.6 + */ + protected String[] getGDBCommandLineArray() { // The goal here is to keep options to an absolute minimum. - // All configuration should be done in the launch sequence + // All configuration should be done in the final launch sequence // to allow for more flexibility. - gdbCommandLine.append(" --interpreter"); //$NON-NLS-1$ - // We currently work with MI version 2. Don't use just 'mi' because it - // points to the latest MI version, while we want mi2 specifically. - gdbCommandLine.append(" mi2"); //$NON-NLS-1$ - // Don't read the gdbinit file here. It is read explicitly in - // the LaunchSequence to make it easier to customize. - gdbCommandLine.append(" --nx"); //$NON-NLS-1$ - - return gdbCommandLine.toString(); + return new String[] { getGDBPath().toOSString(), // This could contain spaces + "--interpreter", //$NON-NLS-1$ + // We currently work with MI version 2. Don't use just 'mi' because it + // points to the latest MI version, while we want mi2 specifically. + "mi2", //$NON-NLS-1$ + // Don't read the gdbinit file here. It is read explicitly in + // the LaunchSequence to make it easier to customize. + "--nx" }; //$NON-NLS-1$ } @Override @@ -361,10 +373,12 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa IGDBLaunchConfigurationConstants.DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND_DEFAULT); } - /* + /** * Launch GDB process. * Allow subclass to override. + * @deprecated Use {@link #launchGDBProcess(String[])} instead */ + @Deprecated protected Process launchGDBProcess(String commandLine) throws CoreException { Process proc = null; try { @@ -376,6 +390,23 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa return proc; } + + /** + * Launch GDB process with command and arguments. + * Allow subclass to override. + * @since 4.6 + */ + protected Process launchGDBProcess(String[] commandLine) throws CoreException { + Process proc = null; + try { + proc = ProcessFactory.getFactory().exec(commandLine, LaunchUtils.getLaunchEnvironment(fLaunchConfiguration)); + } catch (IOException e) { + String message = "Error while launching command: " + StringUtil.join(commandLine, " "); //$NON-NLS-1$ //$NON-NLS-2$ + throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, message, e)); + } + + return proc; + } public Process getProcess() { return fProcess; @@ -542,7 +573,7 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend, IMIBa return Status.OK_STATUS; } - String commandLine = getGDBCommandLine(); + String[] commandLine = getGDBCommandLineArray(); try { fProcess = launchGDBProcess(commandLine);