/*******************************************************************************
* Copyright (c) 2004, 2011 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.MessageFormat;
import java.util.ArrayList;
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.command.MIGDBSetNewConsole;
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.core.variables.VariablesPlugin;
import org.eclipse.debug.core.ILaunch;
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 {
String factoryID = MIPlugin.getCommandFactory( config );
CommandFactory factory = MIPlugin.getDefault().getCommandFactoryManager().getCommandFactory( factoryID );
String miVersion = getMIVersion( config );
if ( factory != null ) {
factory.setMIVersion( miVersion );
}
return ( factory != null ) ? factory : new CommandFactory( miVersion );
}
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.ILaunch, org.eclipse.cdt.debug.mi.core.cdi.Session, org.eclipse.core.runtime.IProgressMonitor)
*/
protected void doStartSession( ILaunch launch, Session session, IProgressMonitor monitor ) throws CoreException {
ILaunchConfiguration config = launch.getLaunchConfiguration();
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 {
// TODO: need a better solution for new-console
MISession miSession = getMISession( session );
try {
CommandFactory factory = miSession.getCommandFactory();
MIGDBSetNewConsole newConsole = factory.createMIGDBSetNewConsole();
miSession.postCommand( newConsole );
MIInfo info = newConsole.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.
}
}
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[] { new Integer( 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 );
sharedMgr.setDeferredBreakpoint( target, false );
// 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.setStopOnSolibEvents( target, true );
sharedMgr.setDeferredBreakpoint( 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 );
}
// use file names instead of full paths
File[] autoSolibs = MICoreUtils.getAutoSolibs( config );
ArrayList libs = new ArrayList( autoSolibs.length );
for ( int j = 0; j < autoSolibs.length; ++j )
libs.add( new File( autoSolibs[j].getName() ) );
sharedMgr.autoLoadSymbols( (File[])libs.toArray( new File[libs.size()] ) );
if ( !autolib && !stopOnSolibEvents )
sharedMgr.setDeferredBreakpoint( target, libs.size() > 0 );
}
}
catch( CDIException e ) {
throw newCoreException( MIPlugin.getResourceString( "src.GDBDebugger.Error_initializing_shared_lib_options" ) + e.getMessage(), e ); //$NON-NLS-1$
}
}
protected String getWorkingDirectory( ILaunchConfiguration config ) throws CoreException {
IPath path = null;
String location = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, (String)null);
if (location != null) {
String expandedLocation = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(location);
if (expandedLocation.length() > 0) {
path = new Path(expandedLocation);
}
}
if(path == null){
path = getProjectPath( config );
}
CommandFactory factory = getCommandFactory( config );
return factory.getWorkingDirectory(path.toFile());
}
protected 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$
}
}