1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

New org.eclipse.dd.gdb.launch plugin to separate the launch logic

This commit is contained in:
Marc Khouzam 2008-03-10 19:53:15 +00:00
parent ca2922f0bb
commit ec69c08687
14 changed files with 1423 additions and 0 deletions

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.dd.gdb.launch</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,7 @@
#Mon Mar 03 11:58:56 EST 2008
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.5

View file

@ -0,0 +1,20 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Debug Services Framework GDB Launch Plug-in
Bundle-Vendor: Eclipse.org
Bundle-SymbolicName: org.eclipse.dd.gdb.launch; singleton:=true
Bundle-Version: 1.0.0
Bundle-Activator: org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.dd.dsf,
org.eclipse.dd.dsf.debug,
org.eclipse.dd.mi,
org.eclipse.dd.gdb,
org.eclipse.debug.core,
org.eclipse.cdt.core,
org.eclipse.cdt.launch,
org.eclipse.cdt.debug.core,
org.eclipse.cdt.debug.mi.core
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Export-Package: org.eclipse.dd.gdb.launch.launching

View file

@ -0,0 +1,24 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>About</title></head><body lang="EN-US">
<h2>About This Content</h2>
<p>June 5, 2007</p>
<h3>License</h3>
<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
indicated below, the Content is provided to you under the terms and conditions of the
Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, "Program" will mean the Content.</p>
<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
being redistributed by another party ("Redistributor") and different terms and conditions may
apply to your use of any object code in the Content. Check the Redistributor's license that was
provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
indicated below, the terms and conditions of the EPL still apply to any source code in the Content
and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
</body></html>

View file

@ -0,0 +1,7 @@
source.. = src/
output.. = bin/
bin.includes = plugin.xml,\
META-INF/,\
.,\
icons/,\
about.html

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
<extension point="org.eclipse.debug.core.launchConfigurationTypes">
<launchConfigurationType
sourceLocatorId="org.eclipse.cdt.debug.core.sourceLocator"
delegate="org.eclipse.dd.gdb.launch.launching.GdbLocalLaunchDelegate"
public="true"
sourcePathComputerId="org.eclipse.cdt.debug.core.sourcePathComputer"
name="Local C/C++ Application (Experimental - DSF)"
id="org.eclipse.dd.gdb.launch.localCLaunch"
modes="debug">
</launchConfigurationType>
<launchConfigurationType
delegate="org.eclipse.dd.gdb.launch.launching.GdbLocalLaunchDelegate"
id="org.eclipse.dd.gdb.launch.remoteCLaunch"
modes="debug"
name="Remote C/C++ Application (Experimental - DSF)"
public="true"
sourceLocatorId="org.eclipse.cdt.debug.core.sourceLocator"
sourcePathComputerId="org.eclipse.cdt.debug.core.sourcePathComputer">
</launchConfigurationType>
</extension>
</plugin>

View file

@ -0,0 +1,120 @@
/*******************************************************************************
* Copyright (c) 2008 Ericsson 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:
* Ericsson - initial API and implementation
*******************************************************************************/
package org.eclipse.dd.gdb.launch.internal;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.Query;
import org.eclipse.dd.gdb.launch.launching.GdbLaunch;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.osgi.framework.BundleContext;
/**
* The activator class controls the plug-in life cycle
*/
public class GdbLaunchPlugin extends Plugin {
// The plug-in ID
public static final String PLUGIN_ID = "org.eclipse.dd.gdb"; //$NON-NLS-1$
// The shared instance
private static GdbLaunchPlugin plugin;
private static BundleContext fgBundleContext;
/**
* The constructor
*/
public GdbLaunchPlugin() {
}
/*
* (non-Javadoc)
* @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
*/
@Override
public void start(BundleContext context) throws Exception {
fgBundleContext = context;
super.start(context);
plugin = this;
}
/*
* (non-Javadoc)
* @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
*/
@Override
public void stop(BundleContext context) throws Exception {
shutdownActiveLaunches();
plugin = null;
super.stop(context);
fgBundleContext = null;
}
/**
* Returns the shared instance
*
* @return the shared instance
*/
public static GdbLaunchPlugin getDefault() {
return plugin;
}
public static BundleContext getBundleContext() {
return fgBundleContext;
}
/**
* Shuts down any active launches. We must shutdown any active sessions
* and services associated with this plugin before this plugin is stopped.
* Any attempts to use the plugins {@link BundleContext} after the plugin
* is shut down will result in exceptions.
*/
private void shutdownActiveLaunches() {
for (ILaunch launch : DebugPlugin.getDefault().getLaunchManager().getLaunches()) {
if (launch instanceof GdbLaunch && ((GdbLaunch)launch).getSession().isActive()) {
final GdbLaunch gdbLaunch = (GdbLaunch)launch;
Query<Object> launchShutdownQuery = new Query<Object>() {
@Override
protected void execute(DataRequestMonitor<Object> rm) {
gdbLaunch.shutdownSession(rm);
}
};
try {
gdbLaunch.getSession().getExecutor().execute(launchShutdownQuery);
} catch (RejectedExecutionException e) {
// We can get this exception if the session is shutdown concurrently
// to this method running.
break;
}
// The Query.get() method is a synchronous call which blocks until the
// query completes.
try {
launchShutdownQuery.get();
} catch (InterruptedException e) {
getLog().log(new Status(IStatus.ERROR, PLUGIN_ID, "InterruptedException while shutting down PDA debugger launch " + gdbLaunch, e.getCause())); //$NON-NLS-1$
} catch (ExecutionException e) {
getLog().log(new Status(IStatus.ERROR, PLUGIN_ID, "Exception while shutting down PDA debugger launch " + gdbLaunch, e.getCause())); //$NON-NLS-1$
}
}
}
}
}

View file

@ -0,0 +1,175 @@
/*******************************************************************************
* Copyright (c) 2006 Wind River 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.dd.gdb.launch.launching;
import java.util.concurrent.ExecutionException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.dd.dsf.concurrent.DefaultDsfExecutor;
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.concurrent.ImmediateExecutor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.concurrent.Sequence;
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
import org.eclipse.dd.dsf.service.DsfServicesTracker;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin;
import org.eclipse.dd.gdb.service.command.GDBControl;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.Launch;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.model.ITerminate;
/**
* The only object in the model that implements the traditional interfaces.
*/
@ThreadSafe
public class GdbLaunch extends Launch
implements ITerminate
{
private DefaultDsfExecutor fExecutor;
private DsfSession fSession;
private DsfServicesTracker fTracker;
private boolean fInitialized = false;
private boolean fShutDown = false;
public GdbLaunch(ILaunchConfiguration launchConfiguration, String mode, ISourceLocator locator) {
super(launchConfiguration, mode, locator);
// Create the dispatch queue to be used by debugger control and services
// that belong to this launch
final DefaultDsfExecutor dsfExecutor = new DefaultDsfExecutor(GdbLocalLaunchDelegate.GDB_DEBUG_MODEL_ID);
dsfExecutor.prestartCoreThread();
fExecutor = dsfExecutor;
fSession = DsfSession.startSession(fExecutor, GdbLocalLaunchDelegate.GDB_DEBUG_MODEL_ID);
}
public DsfExecutor getDsfExecutor() { return fExecutor; }
@ConfinedToDsfExecutor("getExecutor")
public void initializeControl()
throws CoreException
{
Runnable initRunnable = new DsfRunnable() {
public void run() {
fTracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), fSession.getId());
fSession.addServiceEventListener(GdbLaunch.this, null);
fInitialized = true;
fireChanged();
}
};
// Invoke the execution code and block waiting for the result.
try {
fExecutor.submit(initRunnable).get();
} catch (InterruptedException e) {
new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Error initializing launch", e); //$NON-NLS-1$
} catch (ExecutionException e) {
new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Error initializing launch", e); //$NON-NLS-1$
}
}
public DsfSession getSession() { return fSession; }
///////////////////////////////////////////////////////////////////////////
// IServiceEventListener
@DsfServiceEventHandler public void eventDispatched(GDBControl.ExitedEvent event) {
shutdownSession(new RequestMonitor(ImmediateExecutor.getInstance(), null));
}
///////////////////////////////////////////////////////////////////////////
// ITerminate
@Override
public boolean canTerminate() {
return super.canTerminate() && fInitialized && !fShutDown;
}
@Override
public boolean isTerminated() {
return super.isTerminated() || fShutDown;
}
@Override
public void terminate() throws DebugException {
if (fShutDown) return;
super.terminate();
}
// ITerminate
///////////////////////////////////////////////////////////////////////////
/**
* Shuts down the services, the session and the executor associated with
* this launch.
* <p>
* Note: The argument request monitor to this method should NOT use the
* executor that belongs to this launch. By the time the shutdown is
* complete, this executor will not be dispatching anymore and the
* request monitor will never be invoked. Instead callers should use
* the {@link ImmediateExecutor}.
* </p>
* @param rm The request monitor invoked when the shutdown is complete.
*/
@ConfinedToDsfExecutor("getSession().getExecutor()")
public void shutdownSession(final RequestMonitor rm) {
if (fShutDown) {
rm.done();
return;
}
fShutDown = true;
Sequence shutdownSeq = new ShutdownSequence(
getDsfExecutor(), fSession.getId(),
new RequestMonitor(fSession.getExecutor(), rm) {
@Override
public void handleCompleted() {
fSession.removeServiceEventListener(GdbLaunch.this);
if (!getStatus().isOK()) {
GdbLaunchPlugin.getDefault().getLog().log(new MultiStatus(
GdbLaunchPlugin.PLUGIN_ID, -1, new IStatus[]{getStatus()}, "Session shutdown failed", null)); //$NON-NLS-1$
}
// Last order of business, shutdown the dispatch queue.
fTracker.dispose();
fTracker = null;
DsfSession.endSession(fSession);
// endSession takes a full dispatch to distribute the
// session-ended event, finish step only after the dispatch.
fExecutor.shutdown();
fExecutor = null;
fireTerminate();
rm.setStatus(getStatus());
rm.done();
}
});
fExecutor.execute(shutdownSeq);
}
@SuppressWarnings("unchecked")
@Override
public Object getAdapter(Class adapter) {
// Must force adapters to be loaded.
Platform.getAdapterManager().loadAdapter(this, adapter.getName());
return super.getAdapter(adapter);
}
}

View file

@ -0,0 +1,291 @@
/*******************************************************************************
* Copyright (c) 2004, 2006 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.dd.gdb.launch.launching;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.launch.AbstractCLaunchDelegate;
import org.eclipse.cdt.launch.internal.ui.LaunchMessages;
import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin;
import org.eclipse.cdt.utils.pty.PTY;
import org.eclipse.cdt.utils.spawner.ProcessFactory;
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.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
import org.eclipse.dd.dsf.debug.model.DsfMemoryBlockRetrieval;
import org.eclipse.dd.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.dd.dsf.service.DsfServicesTracker;
import org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin;
import org.eclipse.dd.gdb.service.command.GDBControl;
import org.eclipse.dd.mi.service.command.AbstractCLIProcess;
import org.eclipse.dd.mi.service.command.MIInferiorProcess;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.IStatusHandler;
import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2;
import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
import org.eclipse.debug.core.model.IPersistableSourceLocator;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2;
/**
* The launch configuration delegate for the CDI debugger session types.
*/
@ThreadSafe
public class GdbLocalLaunchDelegate extends AbstractCLaunchDelegate
implements ILaunchConfigurationDelegate2
{
public final static String GDB_DEBUG_MODEL_ID = "org.eclipse.dd.gdb"; //$NON-NLS-1$
/* (non-Javadoc)
* @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#launch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
if ( monitor == null ) {
monitor = new NullProgressMonitor();
}
if ( mode.equals( ILaunchManager.DEBUG_MODE ) ) {
launchDebugger( config, launch, monitor );
}
}
private void launchDebugger( ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
monitor.beginTask("Launching debugger session", 10); //$NON-NLS-1$
if ( monitor.isCanceled() ) {
return;
}
try {
String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN );
if ( debugMode.equals( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN ) ) {
launchLocalDebugSession( config, launch, monitor );
}
}
finally {
monitor.done();
}
}
private void launchLocalDebugSession( final ILaunchConfiguration config, ILaunch l, IProgressMonitor monitor ) throws CoreException {
if ( monitor.isCanceled() ) {
return;
}
final GdbLaunch launch = (GdbLaunch)l;
monitor.subTask( "Debugging local C/C++ application" ); //$NON-NLS-1$
IPath exePath = verifyProgramPath( config );
ICProject project = verifyCProject( config );
if ( exePath != null ) {
verifyBinary( project, exePath );
}
setDefaultSourceLocator(launch, config);
monitor.worked( 1 );
// Create and invoke the launch sequence to create the debug control and services
final LaunchSequence launchSequence =
new LaunchSequence(launch.getSession(), launch, exePath);
launch.getSession().getExecutor().execute(launchSequence);
try {
launchSequence.get();
} catch (InterruptedException e1) {
throw new DebugException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Interrupted Exception in dispatch thread", e1)); //$NON-NLS-1$
} catch (ExecutionException e1) {
throw new DebugException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in launch sequence", e1.getCause())); //$NON-NLS-1$
}
launch.initializeControl();
// Add the CLI and "inferior" process objects to the launch.
final AtomicReference<AbstractCLIProcess> cliProcessRef = new AtomicReference<AbstractCLIProcess>();
final AtomicReference<MIInferiorProcess> inferiorProcessRef = new AtomicReference<MIInferiorProcess>();
try {
launch.getDsfExecutor().submit( new Callable<Object>() {
public Object call() throws CoreException {
DsfServicesTracker tracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), launch.getSession().getId());
GDBControl gdb = tracker.getService(GDBControl.class);
if (gdb != null) {
cliProcessRef.set(gdb.getCLIProcess());
inferiorProcessRef.set(gdb.getInferiorProcess());
}
tracker.dispose();
return null;
}
}).get();
launch.addProcess(DebugPlugin.newProcess(launch, cliProcessRef.get(), "gdb")); //$NON-NLS-1$
launch.addProcess(DebugPlugin.newProcess(launch, inferiorProcessRef.get(), exePath.lastSegment()));
} catch (InterruptedException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
} catch (ExecutionException e) {
throw (CoreException)e.getCause();
} catch (RejectedExecutionException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
}
// Create a memory retrieval and register it with session
try {
launch.getDsfExecutor().submit( new Callable<Object>() {
public Object call() throws CoreException {
DsfServicesTracker tracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), launch.getSession().getId());
GDBControl gdbControl = tracker.getService(GDBControl.class);
if (gdbControl != null) {
IMemoryBlockRetrieval memRetrieval = new DsfMemoryBlockRetrieval(
GDB_DEBUG_MODEL_ID, config, (IMemoryDMContext)gdbControl.getControlDMContext());
launch.getSession().registerModelAdapter(IMemoryBlockRetrieval.class, memRetrieval);
((DsfMemoryBlockRetrieval) memRetrieval).initialize();
}
tracker.dispose();
return null;
}
}).get();
} catch (InterruptedException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
} catch (ExecutionException e) {
throw (CoreException)e.getCause();
} catch (RejectedExecutionException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#getPluginID()
*/
@Override
protected String getPluginID() {
return LaunchUIPlugin.getUniqueIdentifier();
}
/**
* Performs a runtime exec on the given command line in the context of the
* specified working directory, and returns the resulting process. If the
* current runtime does not support the specification of a working
* directory, the status handler for error code
* <code>ERR_WORKING_DIRECTORY_NOT_SUPPORTED</code> 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 <code>null</code>
* @return the resulting process or <code>null</code> 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( "Error starting process.", 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( "LocalDsfLaunchDelegate.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;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#preLaunchCheck(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
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 );
}
///////////////////////////////////////////////////////////////////////////
// ILaunchConfigurationDelegate2
@Override
public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
return false;
}
@Override
public boolean finalLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
return true;
}
@Override
public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
// Need to configure the source locator before creating the launch
// because once the launch is created and added to launch manager,
// the adapters will be created for the whole session, including
// the source lookup adapter.
ISourceLocator locator = getSourceLocator(configuration);
return new GdbLaunch(configuration, mode, locator);
}
private ISourceLocator getSourceLocator(ILaunchConfiguration configuration) throws CoreException {
String type = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String)null);
if (type == null) {
type = configuration.getType().getSourceLocatorId();
}
if (type != null) {
IPersistableSourceLocator locator = DebugPlugin.getDefault().getLaunchManager().newSourceLocator(type);
String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String)null);
if (memento == null) {
locator.initializeDefaults(configuration);
} else {
if(locator instanceof IPersistableSourceLocator2)
((IPersistableSourceLocator2)locator).initializeFromMemento(memento, configuration);
else
locator.initializeFromMemento(memento);
}
return locator;
}
return null;
}
}

View file

@ -0,0 +1,301 @@
/*******************************************************************************
* Copyright (c) 2008 Ericsson 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:
* Ericsson - Initial API and implementation
*******************************************************************************/
package org.eclipse.dd.gdb.launch.launching;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.launch.AbstractCLaunchDelegate;
import org.eclipse.cdt.launch.internal.ui.LaunchMessages;
import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin;
import org.eclipse.cdt.utils.pty.PTY;
import org.eclipse.cdt.utils.spawner.ProcessFactory;
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.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
import org.eclipse.dd.dsf.debug.model.DsfMemoryBlockRetrieval;
import org.eclipse.dd.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.dd.dsf.service.DsfServicesTracker;
import org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin;
import org.eclipse.dd.gdb.service.command.GDBControl;
import org.eclipse.dd.mi.service.command.AbstractCLIProcess;
import org.eclipse.dd.mi.service.command.MIInferiorProcess;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.IStatusHandler;
import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2;
import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
import org.eclipse.debug.core.model.IPersistableSourceLocator;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2;
/**
* The launch configuration delegate for the CDI debugger session types.
*/
@ThreadSafe
public class GdbRemoteLaunchDelegate extends AbstractCLaunchDelegate
implements ILaunchConfigurationDelegate2
{
public final static String GDB_DEBUG_MODEL_ID = "org.eclipse.dd.gdb"; //$NON-NLS-1$
/* (non-Javadoc)
* @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#launch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
if ( monitor == null ) {
monitor = new NullProgressMonitor();
}
if ( mode.equals( ILaunchManager.DEBUG_MODE ) ) {
launchDebugger( config, launch, monitor );
}
}
private void launchDebugger( ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
monitor.beginTask("Launching debugger session", 10); //$NON-NLS-1$
if ( monitor.isCanceled() ) {
return;
}
try {
// Hack until we fix the tabs
try {
ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy();
wc.setAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE );
wc.doSave();
}
catch( CoreException e ) {
}
// END HACK
String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE );
if ( debugMode.equals( IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE ) ) {
launchRemoteDebugSession( config, launch, monitor );
}
}
finally {
monitor.done();
}
}
private void launchRemoteDebugSession( final ILaunchConfiguration config, ILaunch l, IProgressMonitor monitor ) throws CoreException {
if ( monitor.isCanceled() ) {
return;
}
final GdbLaunch launch = (GdbLaunch)l;
monitor.subTask( "Debugging remote C/C++ application" ); //$NON-NLS-1$
IPath exePath = verifyProgramPath( config );
ICProject project = verifyCProject( config );
if ( exePath != null ) {
verifyBinary( project, exePath );
}
setDefaultSourceLocator(launch, config);
monitor.worked( 1 );
// Create and invoke the launch sequence to create the debug control and services
final LaunchSequence launchSequence =
new LaunchSequence(launch.getSession(), launch, exePath);
launch.getSession().getExecutor().execute(launchSequence);
try {
launchSequence.get();
} catch (InterruptedException e1) {
throw new DebugException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Interrupted Exception in dispatch thread", e1)); //$NON-NLS-1$
} catch (ExecutionException e1) {
throw new DebugException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in launch sequence", e1.getCause())); //$NON-NLS-1$
}
launch.initializeControl();
// Add the CLI and "inferior" process objects to the launch.
final AtomicReference<AbstractCLIProcess> cliProcessRef = new AtomicReference<AbstractCLIProcess>();
final AtomicReference<MIInferiorProcess> inferiorProcessRef = new AtomicReference<MIInferiorProcess>();
try {
launch.getDsfExecutor().submit( new Callable<Object>() {
public Object call() throws CoreException {
DsfServicesTracker tracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), launch.getSession().getId());
GDBControl gdb = tracker.getService(GDBControl.class);
if (gdb != null) {
cliProcessRef.set(gdb.getCLIProcess());
inferiorProcessRef.set(gdb.getInferiorProcess());
}
tracker.dispose();
return null;
}
}).get();
launch.addProcess(DebugPlugin.newProcess(launch, cliProcessRef.get(), "gdb")); //$NON-NLS-1$
launch.addProcess(DebugPlugin.newProcess(launch, inferiorProcessRef.get(), exePath.lastSegment()));
} catch (InterruptedException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
} catch (ExecutionException e) {
throw (CoreException)e.getCause();
} catch (RejectedExecutionException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
}
// Create a memory retrieval and register it with session
try {
launch.getDsfExecutor().submit( new Callable<Object>() {
public Object call() throws CoreException {
DsfServicesTracker tracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), launch.getSession().getId());
GDBControl gdbControl = tracker.getService(GDBControl.class);
if (gdbControl != null) {
IMemoryBlockRetrieval memRetrieval = new DsfMemoryBlockRetrieval(
GDB_DEBUG_MODEL_ID, config, (IMemoryDMContext)gdbControl.getControlDMContext());
launch.getSession().registerModelAdapter(IMemoryBlockRetrieval.class, memRetrieval);
((DsfMemoryBlockRetrieval) memRetrieval).initialize();
}
tracker.dispose();
return null;
}
}).get();
} catch (InterruptedException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
} catch (ExecutionException e) {
throw (CoreException)e.getCause();
} catch (RejectedExecutionException e) {
throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#getPluginID()
*/
@Override
protected String getPluginID() {
return LaunchUIPlugin.getUniqueIdentifier();
}
/**
* Performs a runtime exec on the given command line in the context of the
* specified working directory, and returns the resulting process. If the
* current runtime does not support the specification of a working
* directory, the status handler for error code
* <code>ERR_WORKING_DIRECTORY_NOT_SUPPORTED</code> 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 <code>null</code>
* @return the resulting process or <code>null</code> 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( "Error starting process.", 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( "LocalDsfLaunchDelegate.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;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#preLaunchCheck(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
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 );
}
///////////////////////////////////////////////////////////////////////////
// ILaunchConfigurationDelegate2
@Override
public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
return false;
}
@Override
public boolean finalLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
return true;
}
@Override
public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
// Need to configure the source locator before creating the launch
// because once the launch is created and added to launch manager,
// the adapters will be created for the whole session, including
// the source lookup adapter.
ISourceLocator locator = getSourceLocator(configuration);
return new GdbLaunch(configuration, mode, locator);
}
private ISourceLocator getSourceLocator(ILaunchConfiguration configuration) throws CoreException {
String type = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String)null);
if (type == null) {
type = configuration.getType().getSourceLocatorId();
}
if (type != null) {
IPersistableSourceLocator locator = DebugPlugin.getDefault().getLaunchManager().newSourceLocator(type);
String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String)null);
if (memento == null) {
locator.initializeDefaults(configuration);
} else {
if(locator instanceof IPersistableSourceLocator2)
((IPersistableSourceLocator2)locator).initializeFromMemento(memento, configuration);
else
locator.initializeFromMemento(memento);
}
return locator;
}
return null;
}
}

View file

@ -0,0 +1,7 @@
package org.eclipse.dd.gdb.launch.launching;
public class IGDBLaunchConfigurationConstants {
public static final String DEBUGGER_MODE_REMOTE = "remote";
}

View file

@ -0,0 +1,233 @@
/*******************************************************************************
* Copyright (c) 2006 Wind River 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.dd.gdb.launch.launching;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
import org.eclipse.cdt.debug.mi.core.IMILaunchConfigurationConstants;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.concurrent.Sequence;
import org.eclipse.dd.dsf.debug.service.StepQueueManager;
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin;
import org.eclipse.dd.gdb.service.GDBRunControl;
import org.eclipse.dd.gdb.service.command.GDBControl;
import org.eclipse.dd.mi.service.CSourceLookup;
import org.eclipse.dd.mi.service.ExpressionService;
import org.eclipse.dd.mi.service.MIBreakpoints;
import org.eclipse.dd.mi.service.MIBreakpointsManager;
import org.eclipse.dd.mi.service.MIDisassembly;
import org.eclipse.dd.mi.service.MIMemory;
import org.eclipse.dd.mi.service.MIModules;
import org.eclipse.dd.mi.service.MIRegisters;
import org.eclipse.dd.mi.service.MIStack;
import org.eclipse.dd.mi.service.command.commands.MIBreakInsert;
import org.eclipse.dd.mi.service.command.commands.MIExecRun;
import org.eclipse.dd.mi.service.command.output.MIBreakInsertInfo;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.debug.core.DebugException;
public class LaunchSequence extends Sequence {
Step[] fSteps = new Step[] {
// Create and initialize the Connection service.
new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
//
// Create the connection.
//
fCommandControl = new GDBControl(
fSession, getGDBPath(), fExecPath, GDBControl.SessionType.RUN, 30);
fCommandControl.initialize(requestMonitor);
}
},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new GDBRunControl(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new StepQueueManager(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new MIMemory(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new MIModules(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new MIStack(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new ExpressionService(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
fSourceLookup = new CSourceLookup(fSession);
fSourceLookup.initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
fSourceLookup.setSourceLookupDirector(
fCommandControl.getGDBDMContext(),
((CSourceLookupDirector)fLaunch.getSourceLocator()));
requestMonitor.done();
}},
new Step() { @Override
public void execute(final RequestMonitor requestMonitor) {
// Create the low-level breakpoint service
final MIBreakpoints bpService = new MIBreakpoints(fSession);
bpService.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
@Override
protected void handleOK() {
requestMonitor.done();
}
});
}},
new Step() { @Override
public void execute(final RequestMonitor requestMonitor) {
// Create high-level breakpoint service and install breakpoints
// for the GDB debug context.
final MIBreakpointsManager bpmService = new MIBreakpointsManager(fSession, CDebugCorePlugin.PLUGIN_ID);
bpmService.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
@Override
protected void handleOK() {
bpmService.startTrackingBreakpoints(fCommandControl.getGDBDMContext(), requestMonitor);
}
});
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new MIRegisters(fSession).initialize(requestMonitor);
}},
new Step() { @Override
public void execute(RequestMonitor requestMonitor) {
new MIDisassembly(fSession).initialize(requestMonitor);
}},
/*
* If needed, insert breakpoint at main and run to it.
*/
new Step() {
private boolean fStopInMain = false;
private String fStopSymbol = null;
/**
* @return The return value actually indicates whether the get operation succeeded,
* not whether to stop.
*/
private boolean readStopAtMain(RequestMonitor requestMonitor) {
try {
fStopInMain = fLaunch.getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false );
} catch (CoreException e) {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, -1, "Cannot retrieve the entry point symbol", e)); //$NON-NLS-1$
requestMonitor.done();
return false;
}
return true;
}
private boolean readStopSymbol(RequestMonitor requestMonitor) {
try {
fStopSymbol = fLaunch.getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT );
} catch (CoreException e) {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, DebugException.CONFIGURATION_INVALID, "Cannot retrieve the entry point symbol", e)); //$NON-NLS-1$
requestMonitor.done();
return false;
}
return true;
}
@Override
public void execute(final RequestMonitor requestMonitor) {
if (!readStopAtMain(requestMonitor)) return;
if (!fStopInMain) {
// Just start the program.
fCommandControl.queueCommand(
new MIExecRun((IContainerDMContext)fCommandControl.getControlDMContext(), new String[0]),
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
@Override
protected void handleOK() {
requestMonitor.done();
}
}
);
} else {
if (!readStopSymbol(requestMonitor)) return;
// Insert a breakpoint at the requested stop symbol.
fCommandControl.queueCommand(
new MIBreakInsert(
(IBreakpointsTargetDMContext)fCommandControl.getControlDMContext(),
true, false, null, 0, fStopSymbol, 0),
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), requestMonitor) {
@Override
protected void handleOK() {
// After the break-insert is done, execute the -exec-run command.
fCommandControl.queueCommand(
new MIExecRun((IContainerDMContext)fCommandControl.getControlDMContext(), new String[0]),
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
@Override
protected void handleOK() {
requestMonitor.done();
}
}
);
}
});
}
}
},
};
DsfSession fSession;
GdbLaunch fLaunch;
IPath fExecPath;
GDBControl fCommandControl;
CSourceLookup fSourceLookup;
public LaunchSequence(DsfSession session, GdbLaunch launch, IPath execPath) {
super(session.getExecutor());
fSession = session;
fLaunch = launch;
fExecPath = execPath;
}
@Override
public Step[] getSteps() {
return fSteps;
}
private IPath getGDBPath() {
IPath retVal = new Path("gdb.exe"); //$NON-NLS-1$
try {
retVal = new Path( fLaunch.getLaunchConfiguration().getAttribute( IMILaunchConfigurationConstants.ATTR_DEBUG_NAME, IMILaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT ) );
} catch (CoreException e) {
}
return retVal;
}
}

View file

@ -0,0 +1,179 @@
/*******************************************************************************
* Copyright (c) 2006 Wind River 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.dd.gdb.launch.launching;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.concurrent.Sequence;
import org.eclipse.dd.dsf.service.DsfServicesTracker;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin;
import org.eclipse.dd.gdb.service.GDBRunControl;
import org.eclipse.dd.gdb.service.command.GDBControl;
import org.eclipse.dd.mi.service.CSourceLookup;
import org.eclipse.dd.mi.service.ExpressionService;
import org.eclipse.dd.mi.service.MIBreakpoints;
import org.eclipse.dd.mi.service.MIBreakpointsManager;
import org.eclipse.dd.mi.service.MIDisassembly;
import org.eclipse.dd.mi.service.MIMemory;
import org.eclipse.dd.mi.service.MIModules;
import org.eclipse.dd.mi.service.MIRegisters;
import org.eclipse.dd.mi.service.MIStack;
public class ShutdownSequence extends Sequence {
String fSessionId;
String fApplicationName;
String fDebugModelId;
DsfServicesTracker fTracker;
public ShutdownSequence(DsfExecutor executor, String sessionId, RequestMonitor requestMonitor) {
super(executor, requestMonitor);
fSessionId = sessionId;
}
@Override
public Step[] getSteps() {
return fSteps;
}
private final Step[] fSteps = new Step[] { new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
assert GdbLaunchPlugin.getBundleContext() != null;
fTracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), fSessionId);
requestMonitor.done();
}
@Override
public void rollBack(RequestMonitor requestMonitor) {
fTracker.dispose();
fTracker = null;
requestMonitor.done();
}
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
shutdownService(MIDisassembly.class, requestMonitor);
}
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
shutdownService(MIRegisters.class, requestMonitor);
}
// TODO: As Pawel about the necessity of this step
// Not clear on the purpose of this step since the next one does it also
// (stopTrackingBreakpoints() is called as part of the shutdown method)
// Besides, the run control is already gone so removing breakpoints from
// the back-end is bound to fail...
// }, new Step() {
// @Override
// public void execute(final RequestMonitor requestMonitor) {
// MIBreakpointsManager bpm = fTracker.getService(MIBreakpointsManager.class);
// GDBControl commandControl = fTracker.getService(GDBControl.class);
// if (bpm != null && commandControl != null) {
// bpm.stopTrackingBreakpoints(
// commandControl.getGDBDMContext(),
// new RequestMonitor(getExecutor(), requestMonitor) {
// @Override
// protected void handleCompleted() {
// // If un-installing breakpoints fails, log the error but continue shutting down.
// if (!getStatus().isOK()) {
// DsfGdbLaunchPlugin.getDefault().getLog().log(getStatus());
// }
// requestMonitor.done();
// }
// });
// } else {
// requestMonitor.setStatus(new Status(IStatus.ERROR, DsfGdbLaunchPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR,
// "Needed services not found.", null)); //$NON-NLS-1$
// requestMonitor.done();
// }
// }
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
shutdownService(MIBreakpointsManager.class, requestMonitor);
}
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
shutdownService(MIBreakpoints.class, requestMonitor);
}
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
shutdownService(CSourceLookup.class, requestMonitor);
}
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
shutdownService(ExpressionService.class, requestMonitor);
}
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
shutdownService(MIStack.class, requestMonitor);
}
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
shutdownService(MIModules.class, requestMonitor);
}
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
shutdownService(MIMemory.class, requestMonitor);
}
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
shutdownService(GDBRunControl.class, requestMonitor);
}
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
shutdownService(GDBControl.class, requestMonitor);
}
}, new Step() {
@Override
public void execute(RequestMonitor requestMonitor) {
fTracker.dispose();
fTracker = null;
requestMonitor.done();
}
} };
@SuppressWarnings("unchecked")
private void shutdownService(Class clazz, final RequestMonitor requestMonitor) {
IDsfService service = fTracker.getService(clazz);
if (service != null) {
service.shutdown(new RequestMonitor(getExecutor(), requestMonitor) {
@Override
protected void handleCompleted() {
if (!getStatus().isOK()) {
GdbLaunchPlugin.getDefault().getLog().log(getStatus());
}
requestMonitor.done();
}
});
} else {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR,
"Service '" + clazz.getName() + "' not found.", null)); //$NON-NLS-1$//$NON-NLS-2$
requestMonitor.done();
}
}
}