/******************************************************************************* * Copyright (c) 2004, 2009 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 com.ibm.icu.text.DateFormat; import com.ibm.icu.text.MessageFormat; import java.util.Date; import java.util.Map; 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.ICDISessionConfiguration; 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.IPath; 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.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.variables.VariablesPlugin; 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 <code>ICDIDebugger</code> 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(); } boolean verboseMode = verboseMode( launch.getLaunchConfiguration() ); boolean breakpointsFullPath = getBreakpointsWithFullNameAttribute(launch.getLaunchConfiguration() ); Session session = createGDBSession( launch, executable, monitor ); if ( session != null ) { try { ICDITarget[] targets = session.getTargets(); for( int i = 0; i < targets.length; i++ ) { Process debugger = session.getSessionProcess( targets[i] ); if ( debugger != null ) { IProcess debuggerProcess = createGDBProcess( (Target)targets[i], launch, debugger, renderDebuggerProcessLabel( launch ), null ); launch.addProcess( debuggerProcess ); } Target target = (Target)targets[i]; target.enableVerboseMode( verboseMode ); target.getMISession().setBreakpointsWithFullName(breakpointsFullPath); target.getMISession().start(); } doStartSession( launch, session, monitor ); } catch( MIException e ) { failed = true; throw newCoreException( e ); } catch( CoreException e ) { failed = true; throw e; } finally { try { if ( (failed || monitor.isCanceled()) && session != null ) session.terminate(); } catch( CDIException e1 ) { } } } return session; } protected Session createGDBSession( ILaunch launch, File executable, IProgressMonitor monitor ) throws CoreException { Session session = null; IPath gdbPath = getGDBPath( launch ); ILaunchConfiguration config = launch.getLaunchConfiguration(); CommandFactory factory = getCommandFactory( config ); String[] extraArgs = getExtraArguments( config ); boolean usePty = usePty( config ); try { session = MIPlugin.getDefault().createSession( getSessionType( config ), gdbPath.toOSString(), factory, executable, extraArgs, usePty, monitor ); ICDISessionConfiguration sessionConfig = getSessionConfiguration( session ); if ( sessionConfig != null ) { session.setConfiguration( sessionConfig ); } } catch( OperationCanceledException e ) { } catch( Exception e ) { // Catch all wrap them up and rethrow if ( e instanceof CoreException ) { throw (CoreException)e; } throw newCoreException( e ); } return session; } 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$ } protected String[] getExtraArguments( ILaunchConfiguration config ) throws CoreException { return new String[0]; } protected boolean usePty( ILaunchConfiguration config ) throws CoreException { return config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_USE_TERMINAL, true ); } abstract protected CommandFactory getCommandFactory( ILaunchConfiguration config ) throws CoreException; protected void doStartSession( ILaunch launch, Session session, IProgressMonitor monitor ) throws CoreException { } protected String renderDebuggerProcessLabel( ILaunch launch ) { String format = "{0} ({1})"; //$NON-NLS-1$ String timestamp = DateFormat.getInstance().format( new Date( System.currentTimeMillis() ) ); String label = MIPlugin.getResourceString( "src.AbstractGDBCDIDebugger.2" ); //$NON-NLS-1$ try { IPath path = getGDBPath( launch ); label = path.toOSString(); } catch( CoreException e ) { } return MessageFormat.format( format, new String[]{ label, timestamp } ); } protected IPath getGDBPath(ILaunch launch) throws CoreException { ILaunchConfiguration config = launch.getLaunchConfiguration(); String command = config.getAttribute(IMILaunchConfigurationConstants.ATTR_DEBUG_NAME, IMILaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT); try { command = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(command, false); } catch (Exception e) { MIPlugin.log(e); // take value of command as it } return new Path(command); } protected ICDISessionConfiguration getSessionConfiguration( ICDISession session ) { return null; } /** * 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 <code>null</code> 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 <code>null</code> 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 ); } protected IProcess createGDBProcess( Target target, ILaunch launch, Process process, String label, Map attributes ) { return new GDBProcess( target, launch, process, label, attributes ); } protected boolean verboseMode( ILaunchConfiguration config ) { boolean result = IMILaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT; try { return config.getAttribute( IMILaunchConfigurationConstants.ATTR_DEBUGGER_VERBOSE_MODE, result ); } catch( CoreException e ) { // use default } return result; } protected boolean getBreakpointsWithFullNameAttribute( ILaunchConfiguration config ) { boolean result = IMILaunchConfigurationConstants.DEBUGGER_FULLPATH_BREAKPOINTS_DEFAULT; try { return config.getAttribute( IMILaunchConfigurationConstants.ATTR_DEBUGGER_FULLPATH_BREAKPOINTS, result ); } catch( CoreException e ) { // use default } return result; } }