blob: 060e6a7ccb983a9571a62b9aa4eafca5f4fbbc59 [file] [log] [blame]
/*******************************************************************************
* 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)
*/
@Override
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)
*/
@Override
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;
}
}