1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-03 07:05:24 +02:00

[179102] Re-aligned plugin and package names to confirm with Eclipse policy.

This commit is contained in:
Pawel Piech 2008-02-13 20:34:29 +00:00
parent e98b65ea7c
commit dd1daa7a85
185 changed files with 21317 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.ui</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,65 @@
#Thu Jun 07 11:08:08 PDT 2007
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
org.eclipse.jdt.core.compiler.problem.nullReference=ignore
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=error
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.5

View file

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

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,8 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
plugin.xml,\
about.html,\
icons/

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
<extension point="org.eclipse.debug.ui.launchConfigurationTabGroups">
<launchConfigurationTabGroup
type="org.eclipse.dd.mi.launch.localCLaunch"
class="org.eclipse.dd.gdb.internal.ui.launching.DsfMIlRunLaunchConfigurationTabGroup"
id="org.eclipse.dd.mi.launch.localRunLaunchTabGroup">
</launchConfigurationTabGroup>
</extension>
<extension point="org.eclipse.debug.ui.launchConfigurationTypeImages">
<launchConfigurationTypeImage
icon="icons/full/obj16/c_app.gif"
configTypeID="org.eclipse.dd.mi.launch.localCLaunch"
id="org.eclipse.dd.mi.launch.localRunLaunchImage">
</launchConfigurationTypeImage>
</extension>
<extension point="org.eclipse.core.runtime.adapters">
<factory
class="org.eclipse.dd.gdb.internal.ui.GdbAdapterFactory"
adaptableType="org.eclipse.dd.gdb.launching.GdbLaunch">
<adapter type="org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider"/>
<adapter type="org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory"/>
<adapter type="org.eclipse.debug.ui.contexts.ISuspendTrigger"/>
<adapter type="org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory"/>
</factory>
</extension>
<extension point="org.eclipse.debug.ui.memoryRenderings">
<renderingBindings
defaultIds="org.eclipse.debug.ui.rendering.raw_memory"
primaryId="org.eclipse.debug.ui.rendering.raw_memory"
renderingIds="org.eclipse.debug.ui.rendering.raw_memory,org.eclipse.debug.ui.rendering.ascii,org.eclipse.debug.ui.rendering.signedint,org.eclipse.debug.ui.rendering.unsignedint">
<enablement>
<instanceof value="org.eclipse.dd.dsf.debug.model.DsfMemoryBlock"/>
</enablement>
</renderingBindings>
</extension>
<extension point="org.eclipse.ui.propertyPages">
<page class="org.eclipse.dd.gdb.internal.ui.breakpoints.CBreakpointGdbThreadFilterPage"
id="org.eclipse.dd.dsf.gdb.breakpoint.filtering"
name="Filter">
<filter name="debugModelId" value="org.eclipse.dd.dsf.gdb"/>
<enabledWhen>
<adapt type="org.eclipse.cdt.debug.core.model.ICBreakpoint"/>
</enabledWhen>
</page>
</extension>
</plugin>

View file

@ -0,0 +1,213 @@
/*******************************************************************************
* 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.internal.ui;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
import org.eclipse.dd.dsf.debug.ui.actions.DsfResumeCommand;
import org.eclipse.dd.dsf.debug.ui.actions.DsfStepIntoCommand;
import org.eclipse.dd.dsf.debug.ui.actions.DsfStepOverCommand;
import org.eclipse.dd.dsf.debug.ui.actions.DsfStepReturnCommand;
import org.eclipse.dd.dsf.debug.ui.actions.DsfSuspendCommand;
import org.eclipse.dd.dsf.debug.ui.contexts.DsfSuspendTrigger;
import org.eclipse.dd.dsf.debug.ui.sourcelookup.MISourceDisplayAdapter;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.gdb.internal.ui.actions.DsfTerminateCommand;
import org.eclipse.dd.gdb.internal.ui.viewmodel.GdbViewModelAdapter;
import org.eclipse.dd.gdb.launching.GdbLaunch;
import org.eclipse.dd.gdb.launching.GdbLaunchDelegate;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchesListener2;
import org.eclipse.debug.core.commands.IResumeHandler;
import org.eclipse.debug.core.commands.IStepIntoHandler;
import org.eclipse.debug.core.commands.IStepOverHandler;
import org.eclipse.debug.core.commands.IStepReturnHandler;
import org.eclipse.debug.core.commands.ISuspendHandler;
import org.eclipse.debug.core.commands.ITerminateHandler;
import org.eclipse.debug.core.model.IDebugModelProvider;
import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory;
import org.eclipse.debug.ui.contexts.ISuspendTrigger;
import org.eclipse.debug.ui.sourcelookup.ISourceDisplay;
/**
* This implementation of platform adapter factory only retrieves the adapters
* for the launch object. But it also manages the creation and descruction
* of the session-based adapters which are returned by the
* IDMContext.getAdapter() methods.
*/
@ThreadSafe
@SuppressWarnings({"restriction"})
public class GdbAdapterFactory
implements IAdapterFactory, ILaunchesListener2
{
@Immutable
class SessionAdapterSet {
final GdbLaunch fLaunch;
final GdbViewModelAdapter fViewModelAdapter;
final MISourceDisplayAdapter fSourceDisplayAdapter;
final DsfStepIntoCommand fStepIntoCommand;
final DsfStepOverCommand fStepOverCommand;
final DsfStepReturnCommand fStepReturnCommand;
final DsfSuspendCommand fSuspendCommand;
final DsfResumeCommand fResumeCommand;
final DsfTerminateCommand fTerminateCommand;
final IDebugModelProvider fDebugModelProvider;
final DsfSuspendTrigger fSuspendTrigger;
SessionAdapterSet(GdbLaunch launch) {
fLaunch = launch;
DsfSession session = launch.getSession();
fViewModelAdapter = new GdbViewModelAdapter(session);
if (launch.getSourceLocator() instanceof ISourceLookupDirector) {
fSourceDisplayAdapter = new MISourceDisplayAdapter(session, (ISourceLookupDirector)launch.getSourceLocator());
} else {
fSourceDisplayAdapter = null;
}
session.registerModelAdapter(ISourceDisplay.class, fSourceDisplayAdapter);
fStepIntoCommand = new DsfStepIntoCommand(session);
fStepOverCommand = new DsfStepOverCommand(session);
fStepReturnCommand = new DsfStepReturnCommand(session);
fSuspendCommand = new DsfSuspendCommand(session);
fResumeCommand = new DsfResumeCommand(session);
fTerminateCommand = new DsfTerminateCommand(session);
fSuspendTrigger = new DsfSuspendTrigger(session, fLaunch);
session.registerModelAdapter(IStepIntoHandler.class, fStepIntoCommand);
session.registerModelAdapter(IStepOverHandler.class, fStepOverCommand);
session.registerModelAdapter(IStepReturnHandler.class, fStepReturnCommand);
session.registerModelAdapter(ISuspendHandler.class, fSuspendCommand);
session.registerModelAdapter(IResumeHandler.class, fResumeCommand);
session.registerModelAdapter(ITerminateHandler.class, fTerminateCommand);
fDebugModelProvider = new IDebugModelProvider() {
// @see org.eclipse.debug.core.model.IDebugModelProvider#getModelIdentifiers()
public String[] getModelIdentifiers() {
return new String[] { GdbLaunchDelegate.GDB_DEBUG_MODEL_ID };
}
};
session.registerModelAdapter(IDebugModelProvider.class, fDebugModelProvider);
/*
* Registering the launch as an adapter, ensures that this launch,
* and debug model ID will be associated with all DMContexts from this
* session.
*/
session.registerModelAdapter(ILaunch.class, fLaunch);
}
void dispose() {
DsfSession session = fLaunch.getSession();
fViewModelAdapter.dispose();
session.unregisterModelAdapter(ISourceDisplay.class);
if (fSourceDisplayAdapter != null) fSourceDisplayAdapter.dispose();
session.unregisterModelAdapter(IStepIntoHandler.class);
session.unregisterModelAdapter(IStepOverHandler.class);
session.unregisterModelAdapter(IStepReturnHandler.class);
session.unregisterModelAdapter(ISuspendHandler.class);
session.unregisterModelAdapter(IResumeHandler.class);
session.unregisterModelAdapter(ITerminateHandler.class);
fStepIntoCommand.dispose();
fStepOverCommand.dispose();
fStepReturnCommand.dispose();
fSuspendCommand.dispose();
fResumeCommand.dispose();
fTerminateCommand.dispose();
fSuspendTrigger.dispose();
}
}
private Map<GdbLaunch, SessionAdapterSet> fLaunchAdapterSets =
Collections.synchronizedMap(new HashMap<GdbLaunch, SessionAdapterSet>());
public GdbAdapterFactory() {
DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
}
/**
* This method only actually returns adapters for the launch object.
*/
@SuppressWarnings("unchecked")
public Object getAdapter(Object adaptableObject, Class adapterType) {
if (!(adaptableObject instanceof GdbLaunch)) return null;
GdbLaunch launch = (GdbLaunch)adaptableObject;
// Find the correct set of adapters based on the launch session-ID. If not found
// it means that we have a new launch and new session, and we have to create a
// new set of adapters.
DsfSession session = launch.getSession();
if (session == null) return null;
SessionAdapterSet adapterSet;
synchronized(fLaunchAdapterSets) {
adapterSet = fLaunchAdapterSets.get(launch);
if (adapterSet == null) {
adapterSet = new SessionAdapterSet(launch);
fLaunchAdapterSets.put(launch, adapterSet);
}
}
// Returns the adapter type for the launch object.
if (adapterType.equals(IElementContentProvider.class)) return adapterSet.fViewModelAdapter;
else if (adapterType.equals(IModelProxyFactory.class)) return adapterSet.fViewModelAdapter;
else if (adapterType.equals(IColumnPresentationFactory.class)) return adapterSet.fViewModelAdapter;
else if (adapterType.equals(ISuspendTrigger.class)) return adapterSet.fSuspendTrigger;
else return null;
}
@SuppressWarnings("unchecked")
public Class[] getAdapterList() {
return new Class[] {
IElementContentProvider.class, IModelProxyFactory.class, ISuspendTrigger.class,
IColumnPresentationFactory.class
};
}
public void launchesRemoved(ILaunch[] launches) {
// Dispose the set of adapters for a launch only after the launch is
// removed.
for (ILaunch launch : launches) {
if (launch instanceof GdbLaunch) {
synchronized(fLaunchAdapterSets) {
if ( fLaunchAdapterSets.containsKey(launch) ) {
fLaunchAdapterSets.remove(launch).dispose();
}
}
}
}
}
public void launchesTerminated(ILaunch[] launches) {
}
public void launchesAdded(ILaunch[] launches) {
}
public void launchesChanged(ILaunch[] launches) {
}
}

View file

@ -0,0 +1,59 @@
package org.eclipse.dd.gdb.internal.ui;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
/**
* The activator class controls the plug-in life cycle
*/
public class GdbUIPlugin extends AbstractUIPlugin {
// The plug-in ID
public static final String PLUGIN_ID = "org.eclipse.dd.gdb.ui"; //$NON-NLS-1$
// The shared instance
private static GdbUIPlugin plugin;
private static BundleContext fgBundleContext;
/**
* The constructor
*/
public GdbUIPlugin() {
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#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.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
*/
@Override
public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);
fgBundleContext = null;
}
/**
* Returns the shared instance
*
* @return the shared instance
*/
public static GdbUIPlugin getDefault() {
return plugin;
}
public static BundleContext getBundleContext() {
return fgBundleContext;
}
}

View file

@ -0,0 +1,96 @@
/*******************************************************************************
* 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.internal.ui.actions;
import org.eclipse.dd.dsf.concurrent.DsfExecutor;
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.debug.ui.actions.DsfCommandRunnable;
import org.eclipse.dd.dsf.service.DsfServicesTracker;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.dd.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.dd.gdb.service.command.GDBControl;
import org.eclipse.debug.core.commands.IDebugCommandRequest;
import org.eclipse.debug.core.commands.IEnabledStateRequest;
import org.eclipse.debug.core.commands.ITerminateHandler;
public class DsfTerminateCommand implements ITerminateHandler {
private final DsfExecutor fExecutor;
private final DsfServicesTracker fTracker;
public DsfTerminateCommand(DsfSession session) {
fExecutor = session.getExecutor();
fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
}
public void dispose() {
fTracker.dispose();
}
// Run control may not be avilable after a connection is terminated and shut down.
public void canExecute(final IEnabledStateRequest request) {
if (request.getElements().length != 1 ||
!(request.getElements()[0] instanceof IDMVMContext) )
{
request.setEnabled(false);
request.done();
return;
}
// Javac doesn't like the cast to "(AbstractDMVMLayoutNode<?>.DMVMContext)" need to use the
// construct below and suppress warnings.
IDMVMContext vmc = (IDMVMContext)request.getElements()[0];
final IExecutionDMContext dmc = DMContexts.getAncestorOfType(vmc.getDMContext(), IExecutionDMContext.class);
if (dmc == null) {
request.setEnabled(false);
request.done();
return;
}
fExecutor.execute(
new DsfRunnable() {
public void run() {
// Get the processes service and the exec context.
GDBControl gdbControl = fTracker.getService(GDBControl.class);
if (gdbControl == null || dmc == null) {
// Context or service already invalid.
request.setEnabled(false);
request.done();
} else {
// Check the teriminate.
request.setEnabled(!gdbControl.isGDBExited());
request.done();
}
}
});
}
public boolean execute(final IDebugCommandRequest request) {
if (request.getElements().length != 1) {
request.done();
return false;
}
fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
@Override public void doExecute() {
GDBControl gdbControl = fTracker.getService(GDBControl.class);
if (gdbControl != null) {
gdbControl.terminate(new RequestMonitor(fExecutor, null));
}
}
});
return false;
}
}

View file

@ -0,0 +1,84 @@
/*******************************************************************************
* 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.internal.ui.breakpoints;
import org.eclipse.cdt.debug.core.model.ICBreakpoint;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.dd.gdb.breakpoints.CBreakpointGdbThreadsFilterExtension;
import org.eclipse.dd.gdb.launching.GdbLaunchDelegate;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.dialogs.PropertyPage;
public class CBreakpointGdbThreadFilterPage extends PropertyPage {
private GdbThreadFilterEditor fThreadFilterEditor;
/* (non-Javadoc)
* @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createContents( Composite parent ) {
noDefaultAndApplyButton();
Composite mainComposite = new Composite( parent, SWT.NONE );
mainComposite.setFont( parent.getFont() );
mainComposite.setLayout( new GridLayout() );
mainComposite.setLayoutData( new GridData( GridData.FILL_BOTH ) );
createThreadFilterEditor( mainComposite );
setValid( true );
return mainComposite;
}
public ICBreakpoint getBreakpoint() {
return (ICBreakpoint)getElement().getAdapter(ICBreakpoint.class);
}
public CBreakpointGdbThreadsFilterExtension getFilterExtension() {
ICBreakpoint bp = getBreakpoint();
if (bp != null) {
try {
CBreakpointGdbThreadsFilterExtension filter =
(CBreakpointGdbThreadsFilterExtension) bp.getExtension(
GdbLaunchDelegate.GDB_DEBUG_MODEL_ID, CBreakpointGdbThreadsFilterExtension.class);
filter.initialize(bp);
return filter;
} catch (CoreException e) {}
}
return null;
}
protected void createThreadFilterEditor( Composite parent ) {
fThreadFilterEditor = new GdbThreadFilterEditor( parent, this );
}
protected GdbThreadFilterEditor getThreadFilterEditor() {
return fThreadFilterEditor;
}
/* (non-Javadoc)
* @see org.eclipse.jface.preference.IPreferencePage#performOk()
*/
@Override
public boolean performOk() {
doStore();
return super.performOk();
}
/**
* Stores the values configured in this page.
*/
protected void doStore() {
fThreadFilterEditor.doStore();
}
}

View file

@ -0,0 +1,537 @@
/*******************************************************************************
* Copyright (c) 2004, 2005 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.internal.ui.breakpoints;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.ImmediateExecutor;
import org.eclipse.dd.dsf.concurrent.Query;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.gdb.breakpoints.CBreakpointGdbThreadsFilterExtension;
import org.eclipse.dd.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.dd.gdb.launching.GdbLaunch;
import org.eclipse.dd.gdb.service.GDBRunControl;
import org.eclipse.dd.gdb.service.GDBRunControl.GDBThreadData;
import org.eclipse.dd.gdb.service.command.GDBControl;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.osgi.util.tracker.ServiceTracker;
public class GdbThreadFilterEditor {
/**
* Comment for ThreadFilterEditor.
*/
public class CheckHandler implements ICheckStateListener {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged(org.eclipse.jface.viewers.CheckStateChangedEvent)
*/
public void checkStateChanged(CheckStateChangedEvent event) {
Object element = event.getElement();
if (element instanceof IContainerDMContext) {
checkTarget((IContainerDMContext) element, event.getChecked());
} else if (element instanceof IExecutionDMContext) {
checkThread((IExecutionDMContext) element, event.getChecked());
}
}
/**
* Check or uncheck a debug target in the tree viewer. When a debug
* target is checked, attempt to check all of the target's threads by
* default. When a debug target is unchecked, uncheck all its threads.
*/
protected void checkTarget(IContainerDMContext target, boolean checked) {
getThreadViewer().setChecked(target, checked);
getThreadViewer().setGrayed(target, false);
getThreadViewer().expandToLevel(target, AbstractTreeViewer.ALL_LEVELS);
IExecutionDMContext[] threads = syncGetThreads(target);
for (int i = 0; i < threads.length; i++) {
getThreadViewer().setChecked(threads[i], checked);
getThreadViewer().setGrayed(threads[i], false);
}
}
/**
* Check or uncheck a thread. Update the thread's debug target.
*/
protected void checkThread(IExecutionDMContext thread, boolean checked) {
getThreadViewer().setChecked(thread, checked);
IContainerDMContext target = DMContexts.getAncestorOfType(thread, IContainerDMContext.class);
IExecutionDMContext[] threads = syncGetThreads(target);
int checkedNumber = 0;
for (int i = 0; i < threads.length; i++) {
if (getThreadViewer().getChecked(threads[i])) {
++checkedNumber;
}
}
if (checkedNumber == 0) {
getThreadViewer().setChecked(target, false);
getThreadViewer().setGrayed(target, false);
} else if (checkedNumber == threads.length) {
getThreadViewer().setChecked(target, true);
getThreadViewer().setGrayed(target, false);
} else {
getThreadViewer().setGrayChecked(target, true);
}
}
}
/**
* Comment for ThreadFilterEditor.
*/
public class ThreadFilterContentProvider implements ITreeContentProvider {
/**
* Constructor for ThreadFilterContentProvider.
*/
public ThreadFilterContentProvider() {
super();
// TODO Auto-generated constructor stub
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
*/
public Object[] getChildren(Object parent) {
if (parent instanceof IContainerDMContext) {
return syncGetThreads((IContainerDMContext) parent);
}
if (parent instanceof ILaunchManager) {
List<Object> children = new ArrayList<Object>();
ILaunch[] launches = ((ILaunchManager) parent).getLaunches();
IContainerDMContext target;
for (int i = 0; i < launches.length; i++) {
if (launches[i] instanceof GdbLaunch) {
target = syncGetContainer((GdbLaunch) launches[i]);
if (target != null) {
children.add(target);
}
}
}
return children.toArray();
}
return new Object[0];
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
*/
public Object getParent(Object element) {
if (element instanceof IContainerDMContext) {
return DebugPlugin.getDefault().getLaunchManager();
}
if (element instanceof IExecutionDMContext) {
return DMContexts.getAncestorOfType((IExecutionDMContext) element, IContainerDMContext.class);
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
*/
public boolean hasChildren(Object element) {
return getChildren(element).length > 0;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
*/
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
*/
public void dispose() {
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
* java.lang.Object, java.lang.Object)
*/
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
public class ThreadFilterLabelProvider extends LabelProvider {
@Override
public Image getImage(Object element) {
if (element instanceof IContainerDMContext) {
return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_DEBUG_TARGET);
} else {
return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING);
}
}
@Override
public String getText(Object element) {
if (element instanceof IContainerDMContext) {
return syncGetContainerLabel((IContainerDMContext)element);
} else {
return syncGetThreadLabel((IExecutionDMContext)element);
}
}
}
private CBreakpointGdbThreadFilterPage fPage;
private CheckboxTreeViewer fThreadViewer;
private ThreadFilterContentProvider fContentProvider;
private CheckHandler fCheckHandler;
/**
* Constructor for ThreadFilterEditor.
*/
public GdbThreadFilterEditor(Composite parent, CBreakpointGdbThreadFilterPage page) {
fPage = page;
fContentProvider = new ThreadFilterContentProvider();
fCheckHandler = new CheckHandler();
createThreadViewer(parent);
}
protected CBreakpointGdbThreadFilterPage getPage() {
return fPage;
}
private void createThreadViewer(Composite parent) {
Label label = new Label(parent, SWT.NONE);
label.setText("&Restrict to Selected Targets and Threads:"); //$NON-NLS-1$
label.setFont(parent.getFont());
label.setLayoutData(new GridData());
GridData data = new GridData(GridData.FILL_BOTH);
data.heightHint = 100;
fThreadViewer = new CheckboxTreeViewer(parent, SWT.BORDER);
fThreadViewer.addCheckStateListener(fCheckHandler);
fThreadViewer.getTree().setLayoutData(data);
fThreadViewer.getTree().setFont(parent.getFont());
fThreadViewer.setContentProvider(fContentProvider);
fThreadViewer.setLabelProvider(new ThreadFilterLabelProvider());
fThreadViewer.setInput(DebugPlugin.getDefault().getLaunchManager());
setInitialCheckedState();
}
/**
* Returns the debug targets that appear in the tree
*/
protected IContainerDMContext[] getDebugTargets() {
Object input = fThreadViewer.getInput();
if (!(input instanceof ILaunchManager)) {
return new IContainerDMContext[0];
}
List<Object> targets = new ArrayList<Object>();
ILaunch[] launches = ((ILaunchManager) input).getLaunches();
IContainerDMContext target;
for (int i = 0; i < launches.length; i++) {
if (launches[i] instanceof GdbLaunch) {
target = syncGetContainer((GdbLaunch) launches[i]);
if (target != null) {
targets.add(target);
}
}
}
return targets.toArray(new IContainerDMContext[targets.size()]);
}
protected CheckboxTreeViewer getThreadViewer() {
return fThreadViewer;
}
/**
* Sets the initial checked state of the tree viewer. The initial state
* should reflect the current state of the breakpoint. If the breakpoint has
* a thread filter in a given thread, that thread should be checked.
*/
protected void setInitialCheckedState() {
CBreakpointGdbThreadsFilterExtension filterExtension = fPage.getFilterExtension();
try {
IContainerDMContext[] targets = filterExtension.getTargetFilters();
// TODO: Hack to properly initialize the target/thread list
// Should be done in filterExtension.initialize() but we don't know
// how to get the target list from an ICBreakpoint...
if (targets.length == 0) {
targets = getDebugTargets();
for (IContainerDMContext target : targets) {
filterExtension.setTargetFilter(target);
}
}
// TODO: End of hack
for (int i = 0; i < targets.length; i++) {
IExecutionDMContext[] filteredThreads = filterExtension.getThreadFilters(targets[i]);
if (filteredThreads != null) {
for (int j = 0; j < filteredThreads.length; ++j)
fCheckHandler.checkThread(filteredThreads[j], true);
} else {
fCheckHandler.checkTarget(targets[i], true);
}
}
} catch (CoreException e) {
CDebugUIPlugin.log(e);
}
}
protected void doStore() {
CBreakpointGdbThreadsFilterExtension filterExtension = fPage.getFilterExtension();
IContainerDMContext[] targets = getDebugTargets();
for (int i = 0; i < targets.length; ++i) {
try {
if (getThreadViewer().getChecked(targets[i])) {
if (getThreadViewer().getGrayed(targets[i])) {
IExecutionDMContext[] threads = getTargetThreadFilters(targets[i]);
filterExtension.setThreadFilters(threads);
} else {
filterExtension.setTargetFilter(targets[i]);
}
} else {
filterExtension.removeTargetFilter(targets[i]);
}
DebugPlugin.getDefault().getBreakpointManager().fireBreakpointChanged(fPage.getBreakpoint());
} catch (CoreException e) {
CDebugUIPlugin.log(e);
}
}
}
private IExecutionDMContext[] getTargetThreadFilters(IContainerDMContext target) {
Object[] threads = ((ITreeContentProvider) getThreadViewer().getContentProvider()).getChildren(target);
ArrayList<Object> list = new ArrayList<Object>(threads.length);
for (int i = 0; i < threads.length; ++i) {
if (getThreadViewer().getChecked(threads[i]))
list.add(threads[i]);
}
return list.toArray(new IExecutionDMContext[list.size()]);
}
private IContainerDMContext syncGetContainer(final GdbLaunch launch) {
final DsfSession session = launch.getSession();
class ContainerQuery extends Query<IContainerDMContext> {
@Override
protected void execute(DataRequestMonitor<IContainerDMContext> rm) {
if (!session.isActive()) {
rm.setStatus(getFailStatus(IDsfService.INVALID_STATE, "Launch's session not active.")); //$NON-NLS-1$
rm.done();
return;
}
ServiceTracker tracker = new ServiceTracker(GdbUIPlugin.getBundleContext(), GDBControl.class
.getName(), null);
tracker.open();
GDBControl gdbControl = (GDBControl) tracker.getService();
if (gdbControl != null) {
rm.setData(gdbControl.getGDBDMContext());
} else {
rm.setStatus(getFailStatus(IDsfService.INVALID_STATE, "GDB Control not accessible.")); //$NON-NLS-1$
}
rm.done();
tracker.close();
}
}
ContainerQuery query = new ContainerQuery();
try {
session.getExecutor().execute(query);
return query.get();
} catch (RejectedExecutionException e) {
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return null;
}
private IExecutionDMContext[] syncGetThreads(final IContainerDMContext container) {
final DsfSession session = DsfSession.getSession(container.getSessionId());
if (session == null) {
return new IExecutionDMContext[0];
}
class ThreadsQuery extends Query<IExecutionDMContext[]> {
@Override
protected void execute(DataRequestMonitor<IExecutionDMContext[]> rm) {
if (!session.isActive()) {
rm.setStatus(getFailStatus(IDsfService.INVALID_STATE, "Container's session not active.")); //$NON-NLS-1$
rm.done();
return;
}
ServiceTracker tracker = new ServiceTracker(GdbUIPlugin.getBundleContext(), IRunControl.class
.getName(), null);
tracker.open();
IRunControl runControl = (IRunControl) tracker.getService();
if (runControl != null) {
runControl.getExecutionContexts(container, rm);
} else {
rm.setStatus(getFailStatus(IDsfService.INVALID_STATE, "GDB Control not accessible.")); //$NON-NLS-1$
rm.done();
}
tracker.close();
}
}
ThreadsQuery query = new ThreadsQuery();
try {
session.getExecutor().execute(query);
return query.get();
} catch (RejectedExecutionException e) {
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return new IExecutionDMContext[0];
}
private String syncGetContainerLabel(final IContainerDMContext container) {
final DsfSession session = DsfSession.getSession(container.getSessionId());
if (session == null) {
return "Error reading data"; //$NON-NLS-1$
}
class ContainerLabelQuery extends Query<String> {
@Override
protected void execute(DataRequestMonitor<String> rm) {
if (!session.isActive()) {
rm.setStatus(getFailStatus(IDsfService.INVALID_STATE, "Container's session not active.")); //$NON-NLS-1$
rm.done();
return;
}
ServiceTracker tracker = new ServiceTracker(GdbUIPlugin.getBundleContext(), GDBControl.class
.getName(), null);
tracker.open();
GDBControl gdbControl = (GDBControl) tracker.getService();
if (gdbControl != null) {
rm.setData(gdbControl.getExecutablePath().toOSString());
} else {
rm.setStatus(getFailStatus(IDsfService.INVALID_STATE, "GDB Control not accessible.")); //$NON-NLS-1$
}
rm.done();
tracker.close();
}
}
ContainerLabelQuery query = new ContainerLabelQuery();
try {
session.getExecutor().execute(query);
return query.get();
} catch (RejectedExecutionException e) {
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return "Error reading data"; //$NON-NLS-1$
}
private String syncGetThreadLabel(final IExecutionDMContext thread) {
final DsfSession session = DsfSession.getSession(thread.getSessionId());
if (session == null) {
return "Error reading data"; //$NON-NLS-1$
}
class ThreadLabelQuery extends Query<String> {
@Override
protected void execute(final DataRequestMonitor<String> rm) {
if (!session.isActive()) {
rm.setStatus(getFailStatus(IDsfService.INVALID_STATE, "Container's session not active.")); //$NON-NLS-1$
rm.done();
return;
}
ServiceTracker tracker = new ServiceTracker(GdbUIPlugin.getBundleContext(), GDBRunControl.class
.getName(), null);
tracker.open();
GDBRunControl runControl = (GDBRunControl) tracker.getService();
if (runControl != null) {
runControl.getThreadData((IMIExecutionDMContext) thread, new DataRequestMonitor<GDBThreadData>(
ImmediateExecutor.getInstance(), rm) {
@Override
protected void handleOK() {
final StringBuilder builder = new StringBuilder("Thread["); //$NON-NLS-1$
builder.append(((IMIExecutionDMContext)thread).getThreadId());
builder.append("] "); //$NON-NLS-1$
builder.append(getData().getId());
builder.append(getData().getName());
rm.setData(builder.toString());
rm.done();
}
});
} else {
rm.setStatus(getFailStatus(IDsfService.INVALID_STATE, "GDB Control not accessible.")); //$NON-NLS-1$
rm.done();
}
tracker.close();
}
}
ThreadLabelQuery query = new ThreadLabelQuery();
try {
session.getExecutor().execute(query);
return query.get();
} catch (RejectedExecutionException e) {
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return "Error reading data"; //$NON-NLS-1$
}
private Status getFailStatus(int code, String message) {
return new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, code, message, null);
}
}

View file

@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2005 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.internal.ui.launching;
import org.eclipse.cdt.launch.ui.CDebuggerTab;
import org.eclipse.cdt.launch.ui.CMainTab;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
import org.eclipse.debug.ui.CommonTab;
import org.eclipse.debug.ui.ILaunchConfigurationDialog;
import org.eclipse.debug.ui.ILaunchConfigurationTab;
import org.eclipse.debug.ui.sourcelookup.SourceLookupTab;
public class DsfMIlRunLaunchConfigurationTabGroup extends AbstractLaunchConfigurationTabGroup {
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTabGroup#createTabs(org.eclipse.debug.ui.ILaunchConfigurationDialog, java.lang.String)
*/
public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
new CMainTab(true),
new CDebuggerTab(false),
new SourceLookupTab(),
new CommonTab()
};
setTabs(tabs);
}
}

View file

@ -0,0 +1,60 @@
/*******************************************************************************
* 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.internal.ui.viewmodel;
import org.eclipse.cdt.debug.ui.ICDebugUIConstants;
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.ExpressionVMProvider;
import org.eclipse.dd.dsf.debug.ui.viewmodel.modules.ModulesVMProvider;
import org.eclipse.dd.dsf.debug.ui.viewmodel.register.RegisterVMProvider;
import org.eclipse.dd.dsf.debug.ui.viewmodel.variable.VariableVMProvider;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMAdapter;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.dd.gdb.internal.ui.viewmodel.launch.LaunchVMProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
import org.eclipse.debug.ui.IDebugUIConstants;
/*
*
*/
@ThreadSafe
@SuppressWarnings("restriction")
public class GdbViewModelAdapter extends AbstractDMVMAdapter
{
public GdbViewModelAdapter(DsfSession session) {
super(session);
getSession().registerModelAdapter(IColumnPresentationFactory.class, this);
}
@Override
public void dispose() {
getSession().unregisterModelAdapter(IColumnPresentationFactory.class);
super.dispose();
}
@Override
protected AbstractDMVMProvider createViewModelProvider(IPresentationContext context) {
if ( IDebugUIConstants.ID_DEBUG_VIEW.equals(context.getId()) ) {
return new LaunchVMProvider(this, context, getSession());
} else if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(context.getId()) ) {
return new VariableVMProvider(this, context, getSession());
} else if (IDebugUIConstants.ID_REGISTER_VIEW.equals(context.getId()) ) {
return new RegisterVMProvider(this, context, getSession());
} else if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(context.getId()) ) {
return new ExpressionVMProvider(this, context, getSession());
} else if (ICDebugUIConstants.ID_MODULES_VIEW.equals(context.getId()) ) {
return new ModulesVMProvider(this, context, getSession());
}
return null;
}
}

View file

@ -0,0 +1,146 @@
/*******************************************************************************
* Copyright (c) 2006 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.internal.ui.viewmodel.launch;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.IDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExitedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.IStartedDMEvent;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.dd.gdb.service.GDBRunControl;
import org.eclipse.dd.gdb.service.GDBRunControl.GDBProcessData;
import org.eclipse.dd.gdb.service.command.GDBControl;
import org.eclipse.dd.gdb.service.command.GDBControlDMContext;
import org.eclipse.dd.gdb.service.command.GDBControl.StartedEvent;
import org.eclipse.dd.mi.service.command.AbstractMIControl;
import org.eclipse.dd.mi.service.command.MIControlDMContext;
import org.eclipse.dd.mi.service.command.events.MIInferiorExitEvent;
import org.eclipse.dd.mi.service.command.events.MIInferiorSignalExitEvent;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
@SuppressWarnings("restriction")
public class ContainerVMNode extends AbstractDMVMNode
implements IElementLabelProvider
{
public ContainerVMNode(AbstractDMVMProvider provider, DsfSession session) {
super(provider, session, IRunControl.IExecutionDMContext.class);
}
@Override
protected void updateElementsInSessionThread(IChildrenUpdate update) {
if (!checkService(AbstractMIControl.class, null, update)) return;
MIControlDMContext containerCtx = getServicesTracker().getService(AbstractMIControl.class).getControlDMContext();
update.setChild(createVMContext(containerCtx), 0);
update.done();
}
public void update(final ILabelUpdate[] updates) {
try {
getSession().getExecutor().execute(new DsfRunnable() {
public void run() {
updateLabelInSessionThread(updates);
}});
} catch (RejectedExecutionException e) {
for (ILabelUpdate update : updates) {
handleFailedUpdate(update);
}
}
}
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
for (final ILabelUpdate update : updates) {
if (!checkService(GDBRunControl.class, null, update)) continue;
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class);
final GDBControlDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), GDBControlDMContext.class);
String imageKey = null;
if (runControl.isSuspended(dmc)) {
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED;
} else {
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING;
}
update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0);
runControl.getProcessData(
dmc,
new DataRequestMonitor<GDBProcessData>(getExecutor(), null) {
@Override
public void handleCompleted() {
if (!getStatus().isOK()) {
update.done();
return;
}
update.setLabel(getData().getName(), 0);
update.done();
}
});
}
}
public int getDeltaFlags(Object e) {
if(e instanceof IStartedDMEvent || e instanceof IExitedDMEvent) {
return IModelDelta.CONTENT;
} else if(e instanceof IRunControl.IContainerResumedDMEvent ||
e instanceof IRunControl.IContainerSuspendedDMEvent)
{
return IModelDelta.CONTENT;
} else if (e instanceof GDBControl.ExitedEvent ||
e instanceof MIInferiorExitEvent ||
e instanceof MIInferiorSignalExitEvent)
{
return IModelDelta.CONTENT;
}
if (e instanceof StartedEvent) {
return IModelDelta.EXPAND | IModelDelta.SELECT;
}
return IModelDelta.NO_CHANGE;
}
public void buildDelta(Object e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
if(e instanceof IRunControl.IContainerResumedDMEvent ||
e instanceof IRunControl.IContainerSuspendedDMEvent)
{
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
} else if (e instanceof IStartedDMEvent || e instanceof IExitedDMEvent) {
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
} else if (e instanceof GDBControl.ExitedEvent ||
e instanceof MIInferiorExitEvent ||
e instanceof MIInferiorSignalExitEvent)
{
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
}
if (e instanceof StartedEvent) {
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.EXPAND | IModelDelta.SELECT);
}
requestMonitor.done();
}
}

View file

@ -0,0 +1,129 @@
/*******************************************************************************
* 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
* Ericsson - Modified for new functionality
*******************************************************************************/
package org.eclipse.dd.gdb.internal.ui.viewmodel.launch;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
import org.eclipse.dd.dsf.debug.ui.viewmodel.launch.LaunchRootVMNode;
import org.eclipse.dd.dsf.debug.ui.viewmodel.launch.StackFramesVMNode;
import org.eclipse.dd.dsf.debug.ui.viewmodel.launch.StandardProcessVMNode;
import org.eclipse.dd.dsf.debug.ui.viewmodel.launch.LaunchRootVMNode.LaunchesEvent;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchesListener2;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
/**
*
*/
@SuppressWarnings("restriction")
public class LaunchVMProvider extends AbstractDMVMProvider
implements IDebugEventSetListener, ILaunchesListener2
{
@ThreadSafe
public LaunchVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session)
{
super(adapter, presentationContext, session);
IRootVMNode launchNode = new LaunchRootVMNode(this);
setRootNode(launchNode);
// Container node to contain all processes and threads
IVMNode containerNode = new ContainerVMNode(this, getSession());
IVMNode processesNode = new StandardProcessVMNode(this);
addChildNodes(launchNode, new IVMNode[] { containerNode, processesNode});
IVMNode threadsNode = new ThreadVMNode(this, getSession());
addChildNodes(containerNode, new IVMNode[] { threadsNode });
IVMNode stackFramesNode = new StackFramesVMNode(this, getSession());
addChildNodes(threadsNode, new IVMNode[] { stackFramesNode });
DebugPlugin.getDefault().addDebugEventListener(this);
DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
}
public void handleDebugEvents(final DebugEvent[] events) {
if (isDisposed()) return;
// We're in session's executor thread. Re-dispach to VM Adapter
// executor thread and then call root layout node.
try {
getExecutor().execute(new Runnable() {
public void run() {
if (isDisposed()) return;
for (final DebugEvent event : events) {
handleEvent(event);
}
}});
} catch (RejectedExecutionException e) {
// Ignore. This exception could be thrown if the provider is being
// shut down.
}
}
@Override
public void dispose() {
DebugPlugin.getDefault().removeDebugEventListener(this);
DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
super.dispose();
}
public void launchesAdded(ILaunch[] launches) {
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.ADDED));
}
public void launchesRemoved(ILaunch[] launches) {
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.REMOVED));
}
public void launchesChanged(ILaunch[] launches) {
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.CHANGED));
}
public void launchesTerminated(ILaunch[] launches) {
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.TERMINATED));
}
private void handleLaunchesEvent(final LaunchesEvent event) {
if (isDisposed()) return;
// We're in session's executor thread. Re-dispach to VM Adapter
// executor thread and then call root layout node.
try {
getExecutor().execute(new Runnable() {
public void run() {
if (isDisposed()) return;
IRootVMNode rootLayoutNode = getRootVMNode();
if (rootLayoutNode != null && rootLayoutNode.getDeltaFlags(event) != 0) {
handleEvent(event);
}
}});
} catch (RejectedExecutionException e) {
// Ignore. This exception could be thrown if the provider is being
// shut down.
}
}
}

View file

@ -0,0 +1,308 @@
/*******************************************************************************
* 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
* Ericsson - Modified for multi threaded functionality
*******************************************************************************/
package org.eclipse.dd.gdb.internal.ui.viewmodel.launch;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.datamodel.IDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerResumedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMData;
import org.eclipse.dd.dsf.debug.service.IRunControl.IResumedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
import org.eclipse.dd.dsf.internal.ui.DsfUIPlugin;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
import org.eclipse.dd.dsf.ui.viewmodel.ModelProxyInstalledEvent;
import org.eclipse.dd.dsf.ui.viewmodel.VMChildrenUpdate;
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.dd.gdb.service.GDBRunControl;
import org.eclipse.dd.gdb.service.GDBRunControl.GDBThreadData;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
@SuppressWarnings("restriction")
public class ThreadVMNode extends AbstractDMVMNode
implements IElementLabelProvider
{
public ThreadVMNode(AbstractDMVMProvider provider, DsfSession session) {
super(provider, session, IExecutionDMContext.class);
}
@Override
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
if (!checkService(IRunControl.class, null, update)) return;
final IContainerDMContext contDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IContainerDMContext.class);
if (contDmc == null) {
handleFailedUpdate(update);
return;
}
getServicesTracker().getService(IRunControl.class).getExecutionContexts(contDmc,
new DataRequestMonitor<IExecutionDMContext[]>(getSession().getExecutor(), null){
@Override
public void handleCompleted() {
if (!getStatus().isOK()) {
handleFailedUpdate(update);
return;
}
fillUpdateWithVMCs(update, getData());
update.done();
}
});
}
public void update(final ILabelUpdate[] updates) {
try {
getSession().getExecutor().execute(new DsfRunnable() {
public void run() {
updateLabelInSessionThread(updates);
}});
} catch (RejectedExecutionException e) {
for (ILabelUpdate update : updates) {
handleFailedUpdate(update);
}
}
}
@Override
public void getContextsForEvent(VMDelta parentDelta, Object e, final DataRequestMonitor<IVMContext[]> rm) {
if(e instanceof IContainerResumedDMEvent) {
IDMContext triggerContext = ((IContainerResumedDMEvent)e).getTriggeringContext();
if (triggerContext != null) {
rm.setData(new IVMContext[] { createVMContext(triggerContext) });
rm.done();
return;
}
} else if(e instanceof IContainerSuspendedDMEvent) {
IDMContext triggerContext = ((IContainerSuspendedDMEvent)e).getTriggeringContext();
if (triggerContext != null) {
rm.setData(new IVMContext[] { createVMContext(triggerContext) });
rm.done();
return;
}
} else if (e instanceof ModelProxyInstalledEvent) {
getThreadVMCForModelProxyInstallEvent(
parentDelta,
new DataRequestMonitor<VMContextInfo>(getExecutor(), rm) {
@Override
protected void handleCompleted() {
if (getStatus().isOK()) {
rm.setData(new IVMContext[] { getData().fVMContext });
} else {
rm.setData(new IVMContext[0]);
}
rm.done();
}
});
return;
}
super.getContextsForEvent(parentDelta, e, rm);
}
private static class VMContextInfo {
final IVMContext fVMContext;
final int fIndex;
final boolean fIsSuspended;
VMContextInfo(IVMContext vmContext, int index, boolean isSuspended) {
fVMContext = vmContext;
fIndex = index;
fIsSuspended = isSuspended;
}
}
private void getThreadVMCForModelProxyInstallEvent(VMDelta parentDelta, final DataRequestMonitor<VMContextInfo> rm) {
getVMProvider().updateNode(this, new VMChildrenUpdate(
parentDelta, getVMProvider().getPresentationContext(), -1, -1,
new DataRequestMonitor<List<Object>>(getExecutor(), rm) {
@Override
protected void handleOK() {
try {
getSession().getExecutor().execute(new DsfRunnable() {
public void run() {
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class);
if (runControl != null) {
int vmcIdx = -1;
int suspendedVmcIdx = -1;
for (int i = 0; i < getData().size(); i++) {
if (getData().get(i) instanceof IDMVMContext) {
IDMVMContext vmc = (IDMVMContext)getData().get(i);
IExecutionDMContext execDmc = DMContexts.getAncestorOfType(
vmc.getDMContext(), IExecutionDMContext.class);
if (execDmc != null) {
vmcIdx = vmcIdx < 0 ? i : vmcIdx;
if (runControl.isSuspended(execDmc)) {
suspendedVmcIdx = suspendedVmcIdx < 0 ? i : suspendedVmcIdx;
}
}
}
}
if (suspendedVmcIdx >= 0) {
rm.setData(new VMContextInfo(
(IVMContext)getData().get(suspendedVmcIdx), suspendedVmcIdx, true));
} else if (vmcIdx >= 0) {
rm.setData(new VMContextInfo((IVMContext)getData().get(vmcIdx), vmcIdx, false));
} else {
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, "No threads available", null)); //$NON-NLS-1$
}
rm.done();
} else {
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, "No threads available", null)); //$NON-NLS-1$
rm.done();
}
}
});
} catch (RejectedExecutionException e) {
rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.NOT_SUPPORTED, "", null)); //$NON-NLS-1$
rm.done();
}
}
}));
}
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
for (final ILabelUpdate update : updates) {
if (!checkService(GDBRunControl.class, null, update)) continue;
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class);
final IMIExecutionDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IMIExecutionDMContext.class);
String imageKey = null;
if (getServicesTracker().getService(IRunControl.class).isSuspended(dmc)) {
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED;
} else {
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING;
}
update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0);
// Find the Reason for the State
runControl.getExecutionData(dmc,
new DataRequestMonitor<IExecutionDMData>(getSession().getExecutor(), null) {
@Override
public void handleCompleted(){
if (!getStatus().isOK()) {
handleFailedUpdate(update);
return;
}
// We're in a new dispatch cycle, and we have to check whether the
// service reference is still valid.
if (!checkService(GDBRunControl.class, null, update)) return;
final StateChangeReason reason = getData().getStateChangeReason();
// Retrieve the rest of the thread information
runControl.getThreadData(
dmc,
new DataRequestMonitor<GDBThreadData>(getSession().getExecutor(), null) {
@Override
public void handleCompleted() {
if (!getStatus().isOK()) {
update.done();
return;
}
// Create Labels of type Thread[GDBthreadId]RealThreadID/Name (State: Reason)
// Thread[1] 3457 (Suspended:BREAKPOINT)
final StringBuilder builder = new StringBuilder("Thread["); //$NON-NLS-1$
builder.append(dmc.getThreadId());
builder.append("] "); //$NON-NLS-1$
builder.append(getData().getId());
builder.append(getData().getName());
if(getServicesTracker().getService(IRunControl.class).isSuspended(dmc))
builder.append(" (Suspended"); //$NON-NLS-1$
else
builder.append(" (Running"); //$NON-NLS-1$
// Reason will be null before ContainerSuspendEvent is fired
if(reason != null) {
builder.append(" : "); //$NON-NLS-1$
builder.append(reason);
}
builder.append(")"); //$NON-NLS-1$
update.setLabel(builder.toString(), 0);
update.done();
}
});
}
});
}
}
public int getDeltaFlags(Object e) {
if(e instanceof IResumedDMEvent || e instanceof ISuspendedDMEvent) {
return IModelDelta.CONTENT;
}
if (e instanceof ModelProxyInstalledEvent) {
return IModelDelta.SELECT | IModelDelta.EXPAND;
}
return IModelDelta.NO_CHANGE;
}
public void buildDelta(Object e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
if(e instanceof IContainerResumedDMEvent) {
IDMContext triggeringContext = ((IContainerResumedDMEvent)e).getTriggeringContext();
if (triggeringContext != null) {
parentDelta.addNode(createVMContext(triggeringContext), IModelDelta.CONTENT);
}
rm.done();
} else if (e instanceof IContainerSuspendedDMEvent) {
IDMContext triggeringContext = ((IContainerSuspendedDMEvent)e).getTriggeringContext();
if (triggeringContext != null) {
parentDelta.addNode(createVMContext(triggeringContext), IModelDelta.CONTENT);
}
rm.done();
} else if(e instanceof IResumedDMEvent || e instanceof ISuspendedDMEvent) {
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
rm.done();
} else if (e instanceof ModelProxyInstalledEvent) {
getThreadVMCForModelProxyInstallEvent(
parentDelta,
new DataRequestMonitor<VMContextInfo>(getExecutor(), rm) {
@Override
protected void handleCompleted() {
if (getStatus().isOK()) {
parentDelta.addNode(
getData().fVMContext, nodeOffset + getData().fIndex,
IModelDelta.EXPAND | (getData().fIsSuspended ? 0 : IModelDelta.SELECT));
}
rm.done();
}
});
}
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="org/eclipse/dd/dsf/mi/core/output/MIDataListRegisterValuesInfo.java" 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 @@
org.eclipse.dd.mi.core/debug = false

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.dd.mi</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,65 @@
#Thu Jun 07 11:05:32 PDT 2007
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
org.eclipse.jdt.core.compiler.problem.nullReference=ignore
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=error
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.5

View file

@ -0,0 +1,3 @@
#Sun Aug 06 18:13:46 CEST 2006
eclipse.preferences.version=1
internal.default.compliance=default

View file

@ -0,0 +1,24 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: GDB/MI Protocol-based DSF Debugger Integration Core
Bundle-Vendor: Eclipse.org
Bundle-SymbolicName: org.eclipse.dd.mi;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: org.eclipse.dd.mi.internal.MIPlugin
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.debug.core,
org.eclipse.core.resources,
org.eclipse.core.variables,
org.eclipse.dd.dsf,
org.eclipse.dd.dsf.debug,
org.eclipse.cdt.debug.core,
org.eclipse.cdt.core
Export-Package:
org.eclipse.dd.mi.service,
org.eclipse.dd.mi.service.command,
org.eclipse.dd.mi.service.command.commands,
org.eclipse.dd.mi.service.command.events,
org.eclipse.dd.mi.service.command.output
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ActivationPolicy: lazy

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 = META-INF/,\
.,\
plugin.xml,\
plugin.properties,\
about.html

View file

@ -0,0 +1,13 @@
###############################################################################
# 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
###############################################################################
pluginName=DSDP/DD GDB/MI Debugger Implementation using DSF
providerName=Eclipse.org

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
</plugin>

View file

@ -0,0 +1,94 @@
/*******************************************************************************
* 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.mi.internal;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Plugin;
import org.osgi.framework.BundleContext;
/**
* Plugin class.
*/
public class MIPlugin extends Plugin {
public static final String PLUGIN_ID = "org.eclipse.dsdp.debug.gdb.core"; //$NON-NLS-1$
// Debugging flag
public static boolean DEBUG = false;
//The shared instance.
private static MIPlugin fgPlugin;
private static BundleContext fgBundleContext;
/**
* The constructor.
*/
public MIPlugin() {
fgPlugin = this;
}
/**
* This method is called upon plug-in activation
*/
@Override
public void start(BundleContext context) throws Exception {
fgBundleContext = context;
super.start(context);
DEBUG = "true".equals(Platform.getDebugOption("org.eclipse.dd.mi.core/debug")); //$NON-NLS-1$//$NON-NLS-2$
}
/**
* This method is called when the plug-in is stopped
*/
@Override
public void stop(BundleContext context) throws Exception {
super.stop(context);
fgBundleContext = null;
}
/**
* Returns the shared instance.
*
* @return the shared instance.
*/
public static MIPlugin getDefault() {
return fgPlugin;
}
public static BundleContext getBundleContext() {
return fgBundleContext;
}
public static void debug(String message) {
if (DEBUG) {
System.out.print(message);
}
}
public static String getDebugTime() {
StringBuilder traceBuilder = new StringBuilder();
// Record the time
long time = System.currentTimeMillis();
long seconds = (time / 1000) % 1000;
if (seconds < 100) traceBuilder.append('0');
if (seconds < 10) traceBuilder.append('0');
traceBuilder.append(seconds);
traceBuilder.append(',');
long millis = time % 1000;
if (millis < 100) traceBuilder.append('0');
if (millis < 10) traceBuilder.append('0');
traceBuilder.append(millis);
return traceBuilder.toString();
}
}

View file

@ -0,0 +1,140 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
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.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.debug.service.ISourceLookup;
import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.osgi.framework.BundleContext;
/**
* ISourceLookup service implementation based on the CDT CSourceLookupDirector.
*/
public class CSourceLookup extends AbstractDsfService implements ISourceLookup {
private Map<ISourceLookupDMContext,CSourceLookupDirector> fDirectors = new HashMap<ISourceLookupDMContext,CSourceLookupDirector>();
public CSourceLookup(DsfSession session) {
super(session);
}
@Override
protected BundleContext getBundleContext() {
return MIPlugin.getBundleContext();
}
public void setSourceLookupDirector(ISourceLookupDMContext ctx, CSourceLookupDirector director) {
fDirectors.put(ctx, director);
}
@Override
public void initialize(final RequestMonitor requestMonitor) {
super.initialize(
new RequestMonitor(getExecutor(), requestMonitor) {
@Override
protected void handleOK() {
doInitialize(requestMonitor);
}});
}
private void doInitialize(final RequestMonitor requestMonitor) {
// Register this service
register(new String[] { CSourceLookup.class.getName(), ISourceLookup.class.getName() }, new Hashtable<String, String>());
requestMonitor.done();
}
@Override
public void shutdown(final RequestMonitor requestMonitor) {
unregister();
super.shutdown(requestMonitor);
}
public void getDebuggerPath(ISourceLookupDMContext sourceLookupCtx, Object source, final DataRequestMonitor<String> rm)
{
if (! (source instanceof String)) {
// In future if needed other elements such as URIs could be supported.
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.NOT_SUPPORTED, "Only string source element is supported", null)); //$NON-NLS-1$);
rm.done();
return;
}
final String sourceString = (String) source;
if (!fDirectors.containsKey(sourceLookupCtx) ){
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "No source director configured for given context", null)); //$NON-NLS-1$);
rm.done();
return;
}
final CSourceLookupDirector director = fDirectors.get(sourceLookupCtx);
new Job("Lookup Debugger Path") { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
IPath debuggerPath = director.getCompilationPath(sourceString);
if (debuggerPath != null) {
rm.setData(debuggerPath.toString());
} else {
rm.setData(sourceString);
}
rm.done();
return Status.OK_STATUS;
}
}.schedule();
}
public void getSource(ISourceLookupDMContext sourceLookupCtx, final String debuggerPath, final DataRequestMonitor<Object> rm)
{
if (!fDirectors.containsKey(sourceLookupCtx) ){
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "No source director configured for given context", null)); //$NON-NLS-1$);
rm.done();
return;
}
final CSourceLookupDirector director = fDirectors.get(sourceLookupCtx);
new Job("Lookup Source") { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
Object[] sources;
try {
sources = director.findSourceElements(debuggerPath);
if (sources == null || sources.length == 0) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, "No sources found", null)); //$NON-NLS-1$);
} else {
rm.setData(sources[0]);
}
} catch (CoreException e) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, "Source lookup failed", e)); //$NON-NLS-1$);
} finally {
rm.done();
}
return Status.OK_STATUS;
}
}.schedule();
}
}

View file

@ -0,0 +1,898 @@
/*******************************************************************************
* 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
* Ericsson - Modified for handling of multiple execution contexts
*******************************************************************************/
package org.eclipse.dd.mi.service;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.utils.Addr32;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.runtime.IStatus;
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.datamodel.AbstractDMContext;
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IExpressions;
import org.eclipse.dd.dsf.debug.service.IFormattedValues;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IMemory.IMemoryChangedEvent;
import org.eclipse.dd.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.dsf.debug.service.command.CommandCache;
import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.command.commands.ExprMetaGetAttributes;
import org.eclipse.dd.mi.service.command.commands.ExprMetaGetChildCount;
import org.eclipse.dd.mi.service.command.commands.ExprMetaGetChildren;
import org.eclipse.dd.mi.service.command.commands.ExprMetaGetValue;
import org.eclipse.dd.mi.service.command.commands.ExprMetaGetVar;
import org.eclipse.dd.mi.service.command.commands.MIDataEvaluateExpression;
import org.eclipse.dd.mi.service.command.output.ExprMetaGetAttributesInfo;
import org.eclipse.dd.mi.service.command.output.ExprMetaGetChildCountInfo;
import org.eclipse.dd.mi.service.command.output.ExprMetaGetChildrenInfo;
import org.eclipse.dd.mi.service.command.output.ExprMetaGetValueInfo;
import org.eclipse.dd.mi.service.command.output.ExprMetaGetVarInfo;
import org.eclipse.dd.mi.service.command.output.MIDataEvaluateExpressionInfo;
import org.osgi.framework.BundleContext;
/**
* This class implements a debugger expression evaluator as a DSF service. The
* primary interface that clients of this class should use is IExpressions.
*/
public class ExpressionService extends AbstractDsfService implements IExpressions {
/**
* This class represents the two expressions that characterize an Expression Context.
*/
public static class ExpressionInfo {
private final String fullExpression;
private final String relativeExpression;
public ExpressionInfo(String full, String relative) {
fullExpression = full;
relativeExpression = relative;
}
public String getFullExpr() { return fullExpression; }
public String getRelExpr() { return relativeExpression; }
@Override
public boolean equals(Object other) {
if (other instanceof ExpressionInfo) {
if (fullExpression == null ? ((ExpressionInfo) other).fullExpression == null :
fullExpression.equals(((ExpressionInfo) other).fullExpression)) {
if (relativeExpression == null ? ((ExpressionInfo) other).relativeExpression == null :
relativeExpression.equals(((ExpressionInfo) other).relativeExpression)) {
return true;
}
}
}
return false;
}
@Override
public int hashCode() {
return (fullExpression == null ? 0 : fullExpression.hashCode()) ^
(relativeExpression == null ? 0 : relativeExpression.hashCode());
}
@Override
public String toString() {
return "[" + fullExpression +", " + relativeExpression + "]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
}
}
/**
* This class represents an expression.
*/
protected static class MIExpressionDMC extends AbstractDMContext implements IExpressionDMContext {
/**
* This field holds an expression to be evaluated.
*/
private ExpressionInfo exprInfo;
/**
* ExpressionDMC Constructor for expression to be evaluated in context of
* a stack frame.
*
* @param sessionId
* The session ID in which this context is created.
* @param expression
* The expression to be described by this ExpressionDMC
* @param relExpr
* The relative expression if this expression was created as a child
* @param frameCtx
* The parent stack frame context for this ExpressionDMC.
*/
public MIExpressionDMC(String sessionId, String expression, String relExpr, IFrameDMContext frameCtx) {
this(sessionId, expression, relExpr, (IDMContext)frameCtx);
}
/**
* ExpressionDMC Constructor for expression to be evaluated in context of
* an thread.
*
* @param sessionId
* The session ID in which this context is created.
* @param expression
* The expression to be described by this ExpressionDMC
* @param relExpr
* The relative expression if this expression was created as a child
* @param execCtx
* The parent thread context for this ExpressionDMC.
*/
public MIExpressionDMC(String sessionId, String expression, String relExpr, IMIExecutionDMContext execCtx) {
this(sessionId, expression, relExpr, (IDMContext)execCtx);
}
/**
* ExpressionDMC Constructor for expression to be evaluated in context of
* a memory space.
*
* @param sessionId
* The session ID in which this context is created.
* @param expression
* The expression to be described by this ExpressionDMC
* @param relExpr
* The relative expression if this expression was created as a child
* @param memoryCtx
* The parent memory space context for this ExpressionDMC.
*/
public MIExpressionDMC(String sessionId, String expression, String relExpr, IMemoryDMContext memoryCtx) {
this(sessionId, expression, relExpr, (IDMContext)memoryCtx);
}
private MIExpressionDMC(String sessionId, String expr, String relExpr, IDMContext parent) {
super(sessionId, new IDMContext[] { parent });
exprInfo = new ExpressionInfo(expr, relExpr);
}
/**
* @return True if the two objects are equal, false otherwise.
*/
@Override
public boolean equals(Object other) {
return super.baseEquals(other) && exprInfo.equals(((MIExpressionDMC)other).exprInfo);
}
/**
*
* @return The hash code of this ExpressionDMC object.
*/
@Override
public int hashCode() {
return super.baseHashCode() + exprInfo.hashCode();
}
/**
*
* @return A string representation of this ExpressionDMC (including the
* expression to which it is bound).
*/
@Override
public String toString() {
return baseToString() + ".expr" + exprInfo.toString(); //$NON-NLS-1$
}
/**
* @return The full expression string represented by this ExpressionDMC
*/
public String getExpression() {
return exprInfo.getFullExpr();
}
/**
* @return The relative expression string represented by this ExpressionDMC
*/
public String getRelativeExpression() {
return exprInfo.getRelExpr();
}
}
protected static class InvalidContextExpressionDMC extends AbstractDMContext
implements IExpressionDMContext
{
private final String expression;
public InvalidContextExpressionDMC(String sessionId, String expr, IDMContext parent) {
super(sessionId, new IDMContext[] { parent });
expression = expr;
}
@Override
public boolean equals(Object other) {
return super.baseEquals(other) &&
expression == null ? ((InvalidContextExpressionDMC) other).getExpression() == null : expression.equals(((InvalidContextExpressionDMC) other).getExpression());
}
@Override
public int hashCode() {
return expression == null ? super.baseHashCode() : super.baseHashCode() ^ expression.hashCode();
}
@Override
public String toString() {
return baseToString() + ".invalid_expr[" + expression + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
public String getExpression() {
return expression;
}
}
/**
* Contains the address of an expression as well as the size of its type.
*/
protected static class ExpressionDMAddress implements IExpressionDMAddress {
IAddress fAddr;
int fSize;
public ExpressionDMAddress(IAddress addr, int size) {
fAddr = addr;
fSize = size;
}
public ExpressionDMAddress(String addrStr, int size) {
fSize = size;
// We must count the "0x" and that
// is why we compare with 10 characters
// instead of 8
if (addrStr.length() <= 10) {
fAddr = new Addr32(addrStr);
} else {
fAddr = new Addr64(addrStr);
}
}
public IAddress getAddress() { return fAddr; }
public int getSize() { return fSize; }
@Override
public boolean equals(Object other) {
if (other instanceof ExpressionDMAddress) {
ExpressionDMAddress otherAddr = (ExpressionDMAddress) other;
return (fSize == otherAddr.getSize()) &&
(fAddr == null ? otherAddr.getAddress() == null : fAddr.equals(otherAddr.getAddress()));
}
return false;
}
@Override
public int hashCode() {
return (fAddr == null ? 0 :fAddr.hashCode()) + fSize;
}
@Override
public String toString() {
return (fAddr == null ? "null" : "(0x" + fAddr.toString()) + ", " + fSize + ")"; //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
}
}
/**
* This class represents the static data referenced by an instance of ExpressionDMC,
* such as its type and number of children; it does not contain the value or format
* of the expression.
*/
protected static class ExpressionDMData implements IExpressionDMData {
// This is the relative expression, such as the name of a field within a structure,
// in contrast to the fully-qualified expression contained in the ExpressionDMC,
// which refers to the full name, including parent structure.
private final String relativeExpression;
private final String exprType;
private final int numChildren;
private final boolean editable;
/**
* ExpressionDMData constructor.
*/
public ExpressionDMData(String expr, String type, int num, boolean edit) {
relativeExpression = expr;
exprType = type;
numChildren = num;
editable = edit;
}
public BasicType getBasicType() {
return null;
}
public String getEncoding() {
return null;
}
public Map<String, Integer> getEnumerations() {
return new HashMap<String, Integer>();
}
public String getName() {
return relativeExpression;
}
public IRegisterDMContext getRegister() {
return null;
}
// See class VariableVMNode for an example of usage of this method
public String getStringValue() {
return null;
}
public String getTypeId() {
return null;
}
public String getTypeName() {
return exprType;
}
public int getNumChildren() {
return numChildren;
}
public boolean isEditable() {
return editable;
}
@Override
public boolean equals(Object other) {
if (other instanceof ExpressionDMData) {
ExpressionDMData otherData = (ExpressionDMData) other;
return (getNumChildren() == otherData.getNumChildren()) &&
(getTypeName() == null ? otherData.getTypeName() == null : getTypeName().equals(otherData.getTypeName())) &&
(getName() == null ? otherData.getName() == null : getName().equals(otherData.getName()));
}
return false;
}
@Override
public int hashCode() {
return relativeExpression == null ? 0 : relativeExpression.hashCode() +
exprType == null ? 0 : exprType.hashCode() + numChildren;
}
@Override
public String toString() {
return "relExpr=" + relativeExpression + ", type=" + exprType + ", numchildren=" + numChildren; //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
}
}
/**
* Event generated every time an expression is changed by the ExpressionService.
*
* A client wishing to receive such events has to register as a service
* event listener and implement the corresponding eventDispatched method.
*
* E.g.:
*
* getSession().addServiceEventListener(listenerObject, null);
*
* @DsfServiceEventHandler
* public void eventDispatched(ExpressionChangedEvent e) {
* IExpressionDMContext context = e.getDMContext();
* // do something...
* }
*/
protected static class ExpressionChangedEvent extends AbstractDMEvent<IExpressionDMContext>
implements IExpressionChangedDMEvent {
public ExpressionChangedEvent(IExpressionDMContext context) {
super(context);
}
}
// This field holds a reference to to the data model context for this service.
private CommandCache fExpressionCache;
private MIVariableManager varManager;
public ExpressionService(DsfSession session) {
super(session);
}
/**
* This method initializes this service.
*
* @param requestMonitor
* The request monitor indicating the operation is finished
*/
@Override
public void initialize(final RequestMonitor requestMonitor) {
super.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
@Override
protected void handleOK() {
doInitialize(requestMonitor);
}
});
}
/**
* This method initializes this service after our superclass's initialize()
* method succeeds.
*
* @param requestMonitor
* The call-back object to notify when this service's
* initialization is done.
*/
private void doInitialize(RequestMonitor requestMonitor) {
// Register to receive service events for this session.
getSession().addServiceEventListener(this, null);
// Register this service.
register(new String[] { IExpressions.class.getName(),
ExpressionService.class.getName() },
new Hashtable<String, String>());
// Create the expressionService-specific CommandControl which is our
// variable object manager.
// It will deal with the meta-commands, before sending real MI commands
// to the back-end, through the MICommandControl service
// It must be created after the ExpressionService is registered
// since it will need to find it.
varManager = new MIVariableManager(getSession(), getServicesTracker());
// Create the meta command cache which will use the variable manager
// to actually send MI commands to the back-end
fExpressionCache = new CommandCache(varManager);
requestMonitor.done();
}
/**
* This method shuts down this service. It unregisters the service, stops
* receiving service events, and calls the superclass shutdown() method to
* finish the shutdown process.
*
* @return void
*/
@Override
public void shutdown(RequestMonitor requestMonitor) {
unregister();
varManager.shutdown();
getSession().removeServiceEventListener(this);
super.shutdown(requestMonitor);
}
/**
* @return The bundle context of the plug-in to which this service belongs.
*/
@Override
protected BundleContext getBundleContext() {
return MIPlugin.getBundleContext();
}
/**
* Create an expression context with the same full and relative expression
*/
public IExpressionDMContext createExpression(IDMContext ctx, String expression) {
return createExpression(ctx, expression, expression);
}
/**
* Create an expression context.
*/
public IExpressionDMContext createExpression(IDMContext ctx, String expression, String relExpr) {
IFrameDMContext frameDmc = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
if (frameDmc != null) {
return new MIExpressionDMC(getSession().getId(), expression, relExpr, frameDmc);
}
IMIExecutionDMContext execCtx = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
if (execCtx != null) {
return new MIExpressionDMC(getSession().getId(), expression, relExpr, execCtx);
}
IMemoryDMContext memoryCtx = DMContexts.getAncestorOfType(ctx, IMemoryDMContext.class);
if (memoryCtx != null) {
return new MIExpressionDMC(getSession().getId(), expression, relExpr, memoryCtx);
}
// Don't care about the relative expression at this point
return new InvalidContextExpressionDMC(getSession().getId(), expression, ctx);
}
/**
* @see IFormattedValues.getFormattedValueContext(IFormattedDataDMContext, String)
*
* @param dmc
* The context describing the data for which we want to create
* a Formatted context.
* @param formatId
* The format that will be used to create the Formatted context
*
* @return A FormattedValueDMContext that can be used to obtain the value
* of an expression in a specific format.
*/
public FormattedValueDMContext getFormattedValueContext(
IFormattedDataDMContext dmc, String formatId) {
return new FormattedValueDMContext(this, dmc, formatId);
}
/**
* @see IFormattedValues.getAvailableFormats(IFormattedDataDMContext, DataRequestMonitor)
*
* @param dmc
* The context describing the data for which we want to know
* which formats are available.
* @param rm
* The data request monitor for this asynchronous operation.
*
*/
public void getAvailableFormats(IFormattedDataDMContext dmc,
final DataRequestMonitor<String[]> rm) {
rm.setData(new String[] { IFormattedValues.BINARY_FORMAT,
IFormattedValues.NATURAL_FORMAT, IFormattedValues.HEX_FORMAT,
IFormattedValues.OCTAL_FORMAT, IFormattedValues.DECIMAL_FORMAT });
rm.done();
}
/**
* This method obtains the model data for a given ExpressionDMC object or
* for a FormattedValueDMC, or for this DSF service.
*
* @param dmc
* The context for which we are requesting the data
* @param rm
* The request monitor that will contain the requested data
*/
@SuppressWarnings("unchecked")
public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
if (dmc instanceof MIExpressionDMC) {
getExpressionData((MIExpressionDMC) dmc,
(DataRequestMonitor<IExpressionDMData>) rm);
} else if (dmc instanceof FormattedValueDMContext) {
getFormattedExpressionValue((FormattedValueDMContext) dmc,
(DataRequestMonitor<FormattedValueDMData>) rm);
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
}
}
/**
* Obtains the static data of an expression represented
* by an ExpressionDMC object (<tt>dmc</tt>).
*
* @param dmc
* The ExpressionDMC for the expression to be evaluated.
* @param rm
* The data request monitor that will contain the requested data
*/
public void getExpressionData(
final IExpressionDMContext dmc,
final DataRequestMonitor<IExpressionDMData> rm)
{
if (dmc instanceof MIExpressionDMC) {
fExpressionCache.execute(
new ExprMetaGetVar(dmc),
new DataRequestMonitor<ExprMetaGetVarInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(new ExpressionDMData(getData().getExpr(),
getData().getType(), getData().getNumChildren(), getData().getEditable()));
rm.done();
}
});
} else if (dmc instanceof InvalidContextExpressionDMC) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
rm.done();
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid expression context.", null)); //$NON-NLS-1$
rm.done();
}
}
/**
* Obtains the address of an expression and the size of its type.
*
* @param dmc
* The ExpressionDMC for the expression.
* @param rm
* The data request monitor that will contain the requested data
*/
public void getExpressionAddressData(
IExpressionDMContext dmc,
final DataRequestMonitor<IExpressionDMAddress> rm) {
// First create an address expression and a size expression
// to be used in back-end calls
final IExpressionDMContext addressDmc =
createExpression( dmc, "&(" + dmc.getExpression() + ")" );//$NON-NLS-1$//$NON-NLS-2$
final IExpressionDMContext sizeDmc =
createExpression( dmc, "sizeof(" + dmc.getExpression() + ")" ); //$NON-NLS-1$//$NON-NLS-2$
if (addressDmc instanceof InvalidContextExpressionDMC || sizeDmc instanceof InvalidContextExpressionDMC) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
rm.done();
} else {
fExpressionCache.execute(
new MIDataEvaluateExpression<MIDataEvaluateExpressionInfo>(addressDmc),
new DataRequestMonitor<MIDataEvaluateExpressionInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
final String addrStr = getData().getValue();
fExpressionCache.execute(
new MIDataEvaluateExpression<MIDataEvaluateExpressionInfo>(sizeDmc),
new DataRequestMonitor<MIDataEvaluateExpressionInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
try {
int size = Integer.parseInt(getData().getValue());
rm.setData(new ExpressionDMAddress(addrStr, size));
} catch (NumberFormatException e) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE,
"Unexpected size format from backend: " + getData().getValue(), null)); //$NON-NLS-1$
}
rm.done();
}
});
}
});
}
}
/**
* Obtains the value of an expression in a specific format.
*
* @param dmc
* The context for the format of the value requested and
* for the expression to be evaluated. The expression context
* should be a parent of the FormattedValueDMContext.
* @param rm
* The data request monitor that will contain the requested data
*/
public void getFormattedExpressionValue(
final FormattedValueDMContext dmc,
final DataRequestMonitor<FormattedValueDMData> rm)
{
// We need to make sure the FormattedValueDMContext also holds an ExpressionContext,
// or else this method cannot do its work.
// Note that we look for MIExpressionDMC and not IExpressionDMC, because getting
// looking for IExpressionDMC could yield InvalidContextExpressionDMC which is still
// not what we need to have.
if (DMContexts.getAncestorOfType(dmc, MIExpressionDMC.class) == null ) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
rm.done();
} else {
fExpressionCache.execute(
new ExprMetaGetValue(dmc),
new DataRequestMonitor<ExprMetaGetValueInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(new FormattedValueDMData(getData().getValue()));
rm.done();
}
});
}
}
/* Not implemented
*
* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IExpressions#getBaseExpressions(org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
*/
public void getBaseExpressions(IExpressionDMContext exprContext,
DataRequestMonitor<IExpressionDMContext[]> rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
/**
* Retrieves the children expressions of the specified expression
*
* @param exprCtx
* The context for the expression for which the children
* should be retrieved.
* @param rm
* The data request monitor that will contain the requested data
*/
public void getSubExpressions(final IExpressionDMContext dmc,
final DataRequestMonitor<IExpressionDMContext[]> rm)
{
if (dmc instanceof MIExpressionDMC) {
fExpressionCache.execute(
new ExprMetaGetChildren(dmc),
new DataRequestMonitor<ExprMetaGetChildrenInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
ExpressionInfo[] childrenExpr = getData().getChildrenExpressions();
IExpressionDMContext[] childArray = new IExpressionDMContext[childrenExpr.length];
for (int i=0; i<childArray.length; i++) {
childArray[i] = createExpression(
dmc.getParents()[0],
childrenExpr[i].getFullExpr(),
childrenExpr[i].getRelExpr());
}
rm.setData(childArray);
rm.done();
}
});
} else if (dmc instanceof InvalidContextExpressionDMC) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
rm.done();
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid expression context.", null)); //$NON-NLS-1$
rm.done();
}
}
/**
* Retrieves a range of children expressions of the specified expression
*
* @param exprCtx
* The context for the expression for which the children
* should be retrieved.
* @param startIndex
* The starting index within the list of all children of the parent
* expression.
* @param length
* The length or number of elements of the range requested
* @param rm
* The data request monitor that will contain the requested data
*/
public void getSubExpressions(IExpressionDMContext exprCtx, final int startIndex,
final int length, final DataRequestMonitor<IExpressionDMContext[]> rm) {
getSubExpressions(
exprCtx,
new DataRequestMonitor<IExpressionDMContext[]>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData((IExpressionDMContext[])Arrays.asList(getData()).subList(startIndex, startIndex + length).toArray());
rm.done();
}
});
}
/**
* Retrieves the count of children expressions of the specified expression
*
* @param exprCtx
* The context for the expression for which the children count
* should be retrieved.
* @param rm
* The data request monitor that will contain the requested data
*/
public void getSubExpressionCount(IExpressionDMContext dmc,
final DataRequestMonitor<Integer> rm)
{
if (dmc instanceof MIExpressionDMC) {
fExpressionCache.execute(
new ExprMetaGetChildCount(dmc),
new DataRequestMonitor<ExprMetaGetChildCountInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(getData().getChildNum());
rm.done();
}
});
} else if (dmc instanceof InvalidContextExpressionDMC) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
rm.done();
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid expression context.", null)); //$NON-NLS-1$
rm.done();
}
}
/**
* This method indicates if an expression can be written to.
*
* @param dmc: The data model context representing an expression.
*
* @param rm: Data Request monitor containing True if this expression's value can be edited. False otherwise.
*/
public void canWriteExpression(IExpressionDMContext dmc, final DataRequestMonitor<Boolean> rm) {
if (dmc instanceof MIExpressionDMC) {
fExpressionCache.execute(
new ExprMetaGetAttributes(dmc),
new DataRequestMonitor<ExprMetaGetAttributesInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(getData().getEditable());
rm.done();
}
});
} else if (dmc instanceof InvalidContextExpressionDMC) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
rm.done();
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid expression context.", null)); //$NON-NLS-1$
rm.done();
}
}
/**
* Changes the value of the specified expression based on the new value and format.
*
* @param expressionContext
* The context for the expression for which the value
* should be changed.
* @param expressionValue
* The new value for the specified expression
* @param formatId
* The format in which the value is specified
* @param rm
* The request monitor that will indicate the completion of the operation
*/
public void writeExpression(final IExpressionDMContext dmc, String expressionValue,
String formatId, final RequestMonitor rm) {
if (dmc instanceof MIExpressionDMC) {
// This command must not be cached, since it changes the state of the back-end.
// We must send it directly to the variable manager
varManager.writeValue(
dmc,
expressionValue,
formatId,
new RequestMonitor(getExecutor(), rm) {
@Override
protected void handleOK() {
// A value has changed, we should remove any references to that
// value in our cache. Since we don't have such granularity,
// we must clear the entire cache.
// We cannot use the context to do a more-specific reset, because
// the same global variable can be set with different contexts
fExpressionCache.reset();
// Issue event that the expression has changed
getSession().dispatchEvent(new ExpressionChangedEvent(dmc), getProperties());
rm.done();
}
});
} else if (dmc instanceof InvalidContextExpressionDMC) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
rm.done();
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid expression context.", null)); //$NON-NLS-1$
rm.done();
}
}
@DsfServiceEventHandler
public void eventDispatched(IRunControl.IResumedDMEvent e) {
fExpressionCache.setTargetAvailable(false);
if (e.getReason() != StateChangeReason.STEP) {
fExpressionCache.reset();
}
}
@DsfServiceEventHandler
public void eventDispatched(IRunControl.ISuspendedDMEvent e) {
fExpressionCache.setTargetAvailable(true);
fExpressionCache.reset();
}
@DsfServiceEventHandler
public void eventDispatched(IMemoryChangedEvent e) {
fExpressionCache.reset();
// We must also deal with our MIVariableManager since it
// caches variable values, which may now have changed
}
}

View file

@ -0,0 +1,27 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
/**
* An execution context object. In the GDB/MI protocol, threads are represented
* by an integer identifier, which is the basis for this context. The parent of this
* context should always be a container context.
*/
public interface IMIExecutionDMContext extends IExecutionDMContext
{
/**
* Returns the GDB/MI thread identifier of this context.
* @return
*/
public int getThreadId();
}

View file

@ -0,0 +1,267 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointDMData;
import org.eclipse.dd.mi.service.command.output.MIBreakpoint;
public class MIBreakpointDMData implements IBreakpointDMData {
/**
* MI-specific breakpoint attributes markers.
*/
public static final String DSFMIBREAKPOINT = "org.eclipse.dd.dsf.debug.breakpoint.mi"; //$NON-NLS-1$
public static final String NUMBER = DSFMIBREAKPOINT + ".number"; //$NON-NLS-1$
public static final String TYPE = DSFMIBREAKPOINT + ".type"; //$NON-NLS-1$
public static final String THREAD_ID = DSFMIBREAKPOINT + ".threadId"; //$NON-NLS-1$
public static final String FULL_NAME = DSFMIBREAKPOINT + ".fullName"; //$NON-NLS-1$
public static final String HITS = DSFMIBREAKPOINT + ".hits"; //$NON-NLS-1$
public static final String IS_TEMPORARY = DSFMIBREAKPOINT + ".isTemporary"; //$NON-NLS-1$
public static final String IS_HARDWARE = DSFMIBREAKPOINT + ".isHardware"; //$NON-NLS-1$
public static final String LOCATION = DSFMIBREAKPOINT + ".location"; //$NON-NLS-1$
// Back-end breakpoint object
private final MIBreakpoint fBreakpoint;
private final Map<String, Object> fProperties;
// Breakpoint types
public static enum MIBreakpointNature { UNKNOWN, BREAKPOINT, WATCHPOINT, CATCHPOINT };
private final MIBreakpointNature fNature;
///////////////////////////////////////////////////////////////////////////
// Constructors
///////////////////////////////////////////////////////////////////////////
/**
* Copy constructor
*
* @param other
*/
public MIBreakpointDMData(MIBreakpointDMData other) {
fBreakpoint = new MIBreakpoint(other.fBreakpoint);
fProperties = new HashMap<String, Object>(other.fProperties);
fNature = other.fNature;
}
/**
* Constructs a DsfMIBreakpoint from a back-end object
*
* @param dsfMIBreakpoint back-end breakpoint
*/
public MIBreakpointDMData(MIBreakpoint dsfMIBreakpoint) {
// We only support breakpoint and watchpoint (so far)
fBreakpoint = dsfMIBreakpoint;
fNature = dsfMIBreakpoint.isWatchpoint() ? MIBreakpointNature.WATCHPOINT : MIBreakpointNature.BREAKPOINT;
fProperties = new HashMap<String,Object>();
switch (fNature) {
case BREAKPOINT:
{
// Generic breakpoint attributes
fProperties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT);
fProperties.put(MIBreakpoints.FILE_NAME, dsfMIBreakpoint.getFile());
fProperties.put(MIBreakpoints.LINE_NUMBER, dsfMIBreakpoint.getLine());
fProperties.put(MIBreakpoints.FUNCTION, dsfMIBreakpoint.getFunction());
fProperties.put(MIBreakpoints.ADDRESS, dsfMIBreakpoint.getAddress());
fProperties.put(MIBreakpoints.CONDITION, dsfMIBreakpoint.getCondition());
fProperties.put(MIBreakpoints.IGNORE_COUNT, dsfMIBreakpoint.getIgnoreCount());
fProperties.put(MIBreakpoints.IS_ENABLED, new Boolean(dsfMIBreakpoint.isEnabled()));
// MI-specific breakpoint attributes
fProperties.put(NUMBER, dsfMIBreakpoint.getNumber());
fProperties.put(TYPE, dsfMIBreakpoint.getType());
fProperties.put(THREAD_ID, dsfMIBreakpoint.getThreadId());
fProperties.put(FULL_NAME, dsfMIBreakpoint.getFullName());
fProperties.put(HITS, dsfMIBreakpoint.getTimes());
fProperties.put(IS_TEMPORARY, new Boolean(dsfMIBreakpoint.isTemporary()));
fProperties.put(IS_HARDWARE, new Boolean(dsfMIBreakpoint.isHardware()));
fProperties.put(LOCATION, formatLocation());
break;
}
case WATCHPOINT:
{
// Generic breakpoint attributes
fProperties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.WATCHPOINT);
fProperties.put(MIBreakpoints.EXPRESSION, dsfMIBreakpoint.getExpression());
fProperties.put(MIBreakpoints.READ, dsfMIBreakpoint.isAccessWatchpoint() || dsfMIBreakpoint.isReadWatchpoint());
fProperties.put(MIBreakpoints.WRITE, dsfMIBreakpoint.isAccessWatchpoint() || dsfMIBreakpoint.isWriteWatchpoint());
// MI-specific breakpoint attributes
fProperties.put(NUMBER, dsfMIBreakpoint.getNumber());
break;
}
// Not reachable
default:
{
fProperties.put(MIBreakpoints.BREAKPOINT_TYPE, null);
break;
}
}
}
/**
* Formats the LOCATION synthetic property from the existing fields
*
* @return The location string
*/
private String formatLocation() {
// Unlikely default location
String location = fBreakpoint.getAddress();
// Get the relevant parameters
String fileName = fBreakpoint.getFile();
Integer lineNumber = fBreakpoint.getLine();
String function = fBreakpoint.getFunction();
if (!fileName.equals("")) { //$NON-NLS-1$
if (lineNumber != -1) {
location = fileName + ":" + lineNumber; //$NON-NLS-1$
} else {
location = fileName + ":" + function; //$NON-NLS-1$
}
}
return location;
}
/**
* Checks for equality
*
* @param other
* @return
*/
public boolean equals(MIBreakpointDMData other) {
return (fNature == other.fNature) && (fProperties.equals(other.fProperties));
}
///////////////////////////////////////////////////////////////////////////
// IBreakpointDMData
///////////////////////////////////////////////////////////////////////////
public String getBreakpointType() {
return (String) fProperties.get(MIBreakpoints.BREAKPOINT_TYPE);
}
public int getReference() {
return fBreakpoint.getNumber();
}
public IAddress[] getAddresses() {
IAddress[] addresses = new IAddress[1];
addresses[0] = new Addr64(fBreakpoint.getAddress());
return addresses;
}
public String getCondition() {
return fBreakpoint.getCondition();
}
public String getExpression() {
return fBreakpoint.getExpression();
}
public String getFileName() {
return fBreakpoint.getFile();
}
public String getFunctionName() {
return fBreakpoint.getFunction();
}
public int getIgnoreCount() {
return fBreakpoint.getIgnoreCount();
}
public int getLineNumber() {
return fBreakpoint.getLine();
}
public boolean isEnabled() {
return fBreakpoint.isEnabled();
}
///////////////////////////////////////////////////////////////////////////
// MIBreakpointDMData
///////////////////////////////////////////////////////////////////////////
public int getNumber() {
return fBreakpoint.getNumber();
}
public String getThreadId() {
return fBreakpoint.getThreadId();
}
public boolean isTemporary() {
return fBreakpoint.isTemporary();
}
public boolean isHardware() {
return fBreakpoint.isHardware();
}
public String getLocation() {
return (String) fProperties.get(LOCATION);
}
public int getHits() {
return fBreakpoint.getTimes();
}
public String getFullName() {
return fBreakpoint.getFullName();
}
public String getType() {
return fBreakpoint.getType();
}
public void setCondition(String condition) {
fBreakpoint.setCondition(condition);
fProperties.put(MIBreakpoints.CONDITION, condition);
}
public void setIgnoreCount(int ignoreCount) {
fBreakpoint.setIgnoreCount(ignoreCount);
fProperties.put(MIBreakpoints.IGNORE_COUNT, ignoreCount);
}
public void setEnabled(boolean isEnabled) {
fBreakpoint.setEnabled(isEnabled);
fProperties.put(MIBreakpoints.IS_ENABLED, isEnabled);
}
public boolean isReadWatchpoint() {
return fBreakpoint.isReadWatchpoint();
}
public boolean isWriteWatchpoint() {
return fBreakpoint.isWriteWatchpoint();
}
public boolean isAccessWatchpoint() {
return fBreakpoint.isAccessWatchpoint();
}
}

View file

@ -0,0 +1,956 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.AbstractDMContext;
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IBreakpoints;
import org.eclipse.dd.dsf.debug.service.command.ICommandControl;
import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.command.commands.MIBreakAfter;
import org.eclipse.dd.mi.service.command.commands.MIBreakCondition;
import org.eclipse.dd.mi.service.command.commands.MIBreakDelete;
import org.eclipse.dd.mi.service.command.commands.MIBreakDisable;
import org.eclipse.dd.mi.service.command.commands.MIBreakEnable;
import org.eclipse.dd.mi.service.command.commands.MIBreakInsert;
import org.eclipse.dd.mi.service.command.commands.MIBreakList;
import org.eclipse.dd.mi.service.command.commands.MIBreakWatch;
import org.eclipse.dd.mi.service.command.events.MIGDBExitEvent;
import org.eclipse.dd.mi.service.command.events.MIWatchpointScopeEvent;
import org.eclipse.dd.mi.service.command.output.MIBreakInsertInfo;
import org.eclipse.dd.mi.service.command.output.MIBreakListInfo;
import org.eclipse.dd.mi.service.command.output.MIBreakpoint;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.osgi.framework.BundleContext;
/**
* Initial breakpoint service implementation.
* Implements the IBreakpoints interface.
*/
public class MIBreakpoints extends AbstractDsfService implements IBreakpoints
{
/**
* Breakpoint attributes markers used in the map parameters of insert/updateBreakpoint().
* All are optional with the possible exception of TYPE. It is the responsibility of the
* service to ensure that the set of attributes provided is sufficient to create/update
* a valid breakpoint on the back-end.
*/
public static final String PREFIX = "org.eclipse.dd.dsf.debug.breakpoint"; //$NON-NLS-1$
// General markers
public static final String BREAKPOINT_TYPE = PREFIX + ".type"; //$NON-NLS-1$
public static final String BREAKPOINT = "breakpoint"; //$NON-NLS-1$
public static final String WATCHPOINT = "watchpoint"; //$NON-NLS-1$
public static final String CATCHPOINT = "catchpoint"; //$NON-NLS-1$
// Basic set of breakpoint attribute markers
public static final String FILE_NAME = PREFIX + ".fileName"; //$NON-NLS-1$
public static final String LINE_NUMBER = PREFIX + ".lineNumber"; //$NON-NLS-1$
public static final String FUNCTION = PREFIX + ".function"; //$NON-NLS-1$
public static final String ADDRESS = PREFIX + ".address"; //$NON-NLS-1$
public static final String CONDITION = PREFIX + ".condition"; //$NON-NLS-1$
public static final String IGNORE_COUNT = PREFIX + ".ignoreCount"; //$NON-NLS-1$
public static final String IS_ENABLED = PREFIX + ".isEnabled"; //$NON-NLS-1$
// Basic set of watchpoint attribute markers
public static final String EXPRESSION = PREFIX + ".expression"; //$NON-NLS-1$
public static final String READ = PREFIX + ".read"; //$NON-NLS-1$
public static final String WRITE = PREFIX + ".write"; //$NON-NLS-1$
// Services
ICommandControl fConnection;
// Service breakpoints tracking
// The breakpoints are stored per context and keyed on the back-end breakpoint reference
private Map<IBreakpointsTargetDMContext, Map<Integer, MIBreakpointDMData>> fBreakpoints =
new HashMap<IBreakpointsTargetDMContext, Map<Integer, MIBreakpointDMData>>();
// Error messages
final String NULL_STRING = ""; //$NON-NLS-1$
final String UNKNOWN_EXECUTION_CONTEXT = "Unknown execution context"; //$NON-NLS-1$
final String UNKNOWN_BREAKPOINT_CONTEXT = "Unknown breakpoint context"; //$NON-NLS-1$
final String UNKNOWN_BREAKPOINT_TYPE = "Unknown breakpoint type"; //$NON-NLS-1$
final String UNKNOWN_BREAKPOINT = "Unknown breakpoint"; //$NON-NLS-1$
final String BREAKPOINT_INSERTION_FAILURE = "Breakpoint insertion failure"; //$NON-NLS-1$
final String WATCHPOINT_INSERTION_FAILURE = "Watchpoint insertion failure"; //$NON-NLS-1$
final String INVALID_CONDITION = "Invalid condition"; //$NON-NLS-1$
///////////////////////////////////////////////////////////////////////////
// Breakpoint Events
///////////////////////////////////////////////////////////////////////////
public class BreakpointsChangedEvent extends AbstractDMEvent<IBreakpointsTargetDMContext> implements IBreakpointsChangedEvent {
private IBreakpointDMContext[] fEventBreakpoints;
public BreakpointsChangedEvent(IBreakpointDMContext bp) {
super(DMContexts.getAncestorOfType(bp, IBreakpointsTargetDMContext.class));
fEventBreakpoints = new IBreakpointDMContext[] { bp };
}
public IBreakpointDMContext[] getBreakpoints() {
return fEventBreakpoints;
}
}
public class BreakpointAddedEvent extends BreakpointsChangedEvent implements IBreakpointsAddedEvent {
public BreakpointAddedEvent(IBreakpointDMContext context) {
super(context);
}
}
public class BreakpointUpdatedEvent extends BreakpointsChangedEvent implements IBreakpointsUpdatedEvent {
public BreakpointUpdatedEvent(IBreakpointDMContext context) {
super(context);
}
}
public class BreakpointRemovedEvent extends BreakpointsChangedEvent implements IBreakpointsRemovedEvent {
public BreakpointRemovedEvent(IBreakpointDMContext context) {
super(context);
}
}
///////////////////////////////////////////////////////////////////////////
// IBreakpointDMContext
// Used to hold the back-end breakpoint references. The reference can then
// be used to get the actual DsfMIBreakpoint.
///////////////////////////////////////////////////////////////////////////
@Immutable
public static final class MIBreakpointDMContext extends AbstractDMContext implements IBreakpointDMContext {
// The breakpoint reference
private final Integer fReference;
/**
* @param service the Breakpoint service
* @param parents the parent contexts
* @param reference the DsfMIBreakpoint reference
*/
public MIBreakpointDMContext(MIBreakpoints service, IDMContext[] parents, int reference) {
super(service.getSession().getId(), parents);
fReference = reference;
}
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IBreakpoints.IDsfBreakpointDMContext#getReference()
*/
public int getReference() {
return fReference;
}
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
return baseEquals(obj) && (fReference == ((MIBreakpointDMContext) obj).fReference);
}
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.datamodel.AbstractDMContext#hashCode()
*/
@Override
public int hashCode() {
return baseHashCode() + fReference.hashCode();
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return baseToString() + ".reference(" + fReference + ")"; //$NON-NLS-1$//$NON-NLS-2$*/
}
}
///////////////////////////////////////////////////////////////////////////
// AbstractDsfService
///////////////////////////////////////////////////////////////////////////
/**
* The service constructor
*
* @param session The debugging session
*/
public MIBreakpoints(DsfSession session) {
super(session);
}
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.service.AbstractDsfService#initialize(org.eclipse.dd.dsf.concurrent.RequestMonitor)
*/
@Override
public void initialize(final RequestMonitor rm) {
super.initialize(new RequestMonitor(getExecutor(), rm) {
@Override
protected void handleOK() {
doInitialize(rm);
}
});
}
/*
* Asynchronous service initialization
*/
private void doInitialize(final RequestMonitor rm) {
// Get the services references
fConnection = getServicesTracker().getService(ICommandControl.class);
// Register for the useful events
getSession().addServiceEventListener(this, null);
// Register this service
register(new String[] { IBreakpoints.class.getName(), MIBreakpoints.class.getName() },
new Hashtable<String, String>());
rm.done();
}
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.service.AbstractDsfService#shutdown(org.eclipse.dd.dsf.concurrent.RequestMonitor)
*/
@Override
public void shutdown(final RequestMonitor rm) {
unregister();
getSession().removeServiceEventListener(this);
rm.done();
}
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.service.AbstractDsfService#getBundleContext()
*/
@Override
protected BundleContext getBundleContext() {
return MIPlugin.getBundleContext();
}
///////////////////////////////////////////////////////////////////////////
// IServiceEventListener
///////////////////////////////////////////////////////////////////////////
/*
* When a watchpoint goes out of scope, it is automatically removed from
* the back-end. To keep our internal state synchronized, we have to
* remove it from our breakpoints map.
*/
@DsfServiceEventHandler
public void eventDispatched(MIWatchpointScopeEvent e) {
// PP:
IBreakpointsTargetDMContext bpContext = DMContexts.getAncestorOfType(e.getDMContext(), IBreakpointsTargetDMContext.class);
if (bpContext != null) {
Map<Integer, MIBreakpointDMData> contextBps = fBreakpoints.get(bpContext);
if (contextBps != null) {
contextBps.remove(e.getNumber());
}
}
}
@DsfServiceEventHandler
public void eventDispatched(MIGDBExitEvent e) {
// TODO: Remove the installed breakpoints from the back-end
}
///////////////////////////////////////////////////////////////////////////
// IBreakpoints interface
///////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------
// getBreakpoints
//-------------------------------------------------------------------------
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IBreakpoints#getBreakpoints(org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
*/
public void getBreakpoints(final IBreakpointsTargetDMContext context, final DataRequestMonitor<IBreakpointDMContext[]> drm)
{
// Validate the context
if (context == null) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_EXECUTION_CONTEXT, null));
drm.done();
return;
}
// Select the breakpoints context map
// If it doesn't exist then no breakpoint was ever inserted for this breakpoint space.
// In that case, return an empty list.
final Map<Integer, MIBreakpointDMData> breakpointContext = fBreakpoints.get(context);
if (breakpointContext == null) {
drm.setData(new IBreakpointDMContext[0]);
drm.done();
return;
}
// Execute the command
fConnection.queueCommand(new MIBreakList(context),
new DataRequestMonitor<MIBreakListInfo>(getExecutor(), drm) {
@Override
protected void handleOK() {
// Refresh the breakpoints map and format the result
breakpointContext.clear();
MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
IBreakpointDMContext[] result = new IBreakpointDMContext[breakpoints.length];
for (int i = 0; i < breakpoints.length; i++) {
MIBreakpointDMData breakpoint = new MIBreakpointDMData(breakpoints[i]);
int reference = breakpoint.getReference();
result[i] = new MIBreakpointDMContext(MIBreakpoints.this, new IDMContext[] { context }, reference);
breakpointContext.put(reference, breakpoint);
}
drm.setData(result);
drm.done();
}
});
}
//-------------------------------------------------------------------------
// getBreakpointDMData
//-------------------------------------------------------------------------
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IBreakpoints#getBreakpointDMData(org.eclipse.dd.dsf.debug.service.IBreakpoints.IDsfBreakpointDMContext, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
*/
public void getBreakpointDMData(IBreakpointDMContext dmc, DataRequestMonitor<IBreakpointDMData> drm)
{
// Validate the breakpoint context
if (dmc == null) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null));
drm.done();
return;
}
// Validate the breakpoint type
MIBreakpointDMContext breakpoint;
if (dmc instanceof MIBreakpointDMContext) {
breakpoint = (MIBreakpointDMContext) dmc;
}
else {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_TYPE, null));
drm.done();
return;
}
// Validate the target context
IBreakpointsTargetDMContext context = DMContexts.getAncestorOfType(breakpoint, IBreakpointsTargetDMContext.class);
if (context == null) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_EXECUTION_CONTEXT, null));
drm.done();
return;
}
// Select the breakpoints context map
Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context);
if (contextBreakpoints == null) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT, null));
drm.done();
return;
}
// No need to go to the back-end for this one
IBreakpointDMData breakpointCopy = new MIBreakpointDMData(contextBreakpoints.get(breakpoint.getReference()));
drm.setData(breakpointCopy);
drm.done();
}
//-------------------------------------------------------------------------
// insertBreakpoint
//-------------------------------------------------------------------------
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IBreakpoints#insertBreakpoint(org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext, java.util.Map, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
*/
public void insertBreakpoint(IBreakpointsTargetDMContext context, Map<String, Object> attributes, DataRequestMonitor<IBreakpointDMContext> drm) {
// Validate the context
if (context == null) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_EXECUTION_CONTEXT, null));
drm.done();
return;
}
// Select the breakpoints context map. If it doesn't exist, create it.
Map<Integer, MIBreakpointDMData> breakpointContext = fBreakpoints.get(context);
if (breakpointContext == null) {
breakpointContext = new HashMap<Integer, MIBreakpointDMData>();
fBreakpoints.put(context, breakpointContext);
}
// Validate the breakpoint type
String type = (String) attributes.get(BREAKPOINT_TYPE);
if (type == null) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_TYPE, null));
drm.done();
return;
}
// And go...
if (type.equals(BREAKPOINT)) {
addBreakpoint(context, attributes, drm);
}
else if (type.equals(WATCHPOINT)) {
addWatchpoint(context, attributes, drm);
}
else {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_TYPE, null));
drm.done();
}
}
/**
* @param map
* @param key
* @param defaultValue
* @return
*/
public Object getProperty(Map<String, Object> map, String key, Object defaultValue) {
return (map.containsKey(key) && (map.get(key) != null)) ? map.get(key) : defaultValue;
}
/**
* @param attributes
* @return
*/
private String formatLocation(Map<String, Object> attributes) {
// Unlikely default location
String location = (String) getProperty(attributes, ADDRESS, NULL_STRING);
// Get the relevant parameters
String fileName = (String) getProperty(attributes, FILE_NAME, NULL_STRING);
Integer lineNumber = (Integer) getProperty(attributes, LINE_NUMBER, -1);
String function = (String) getProperty(attributes, FUNCTION, NULL_STRING);
if (!fileName.equals(NULL_STRING)) {
if (lineNumber != -1) {
location = fileName + ":" + lineNumber; //$NON-NLS-1$
} else {
location = fileName + ":" + function; //$NON-NLS-1$
}
}
return location;
}
/**
* Add a breakpoint of type BREAKPOINT
*
* @param context
* @param breakpoint
* @param drm
*/
private void addBreakpoint(final IBreakpointsTargetDMContext context, final Map<String, Object> attributes, final DataRequestMonitor<IBreakpointDMContext> drm)
{
// Select the context breakpoints map
final Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context);
if (contextBreakpoints == null) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null));
drm.done();
return;
}
// Extract the relevant parameters (providing default values to avoid potential NPEs)
String location = formatLocation(attributes);
Boolean isTemporary = (Boolean) getProperty(attributes, MIBreakpointDMData.IS_TEMPORARY, false);
Boolean isHardware = (Boolean) getProperty(attributes, MIBreakpointDMData.IS_HARDWARE, false);
final String condition = (String) getProperty(attributes, CONDITION, NULL_STRING);
Integer ignoreCount = (Integer) getProperty(attributes, IGNORE_COUNT, 0 );
String threadId = (String) getProperty(attributes, MIBreakpointDMData.THREAD_ID, "0"); //$NON-NLS-1$
int tid = Integer.parseInt(threadId);
// The DataRequestMonitor for the add request
DataRequestMonitor<MIBreakInsertInfo> addBreakpointDRM =
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), drm) {
@Override
protected void handleOK() {
// With MI, an invalid location won't generate an error
if (getData().getMIBreakpoints().length == 0) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, BREAKPOINT_INSERTION_FAILURE, null));
drm.done();
return;
}
// Create a breakpoint object and store it in the map
final MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(getData().getMIBreakpoints()[0]);
int reference = newBreakpoint.getNumber();
if (reference == -1) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, BREAKPOINT_INSERTION_FAILURE, null));
drm.done();
return;
}
contextBreakpoints.put(reference, newBreakpoint);
// Format the return value
MIBreakpointDMContext dmc = new MIBreakpointDMContext(MIBreakpoints.this, new IDMContext[] { context }, reference);
drm.setData(dmc);
// Flag the event
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
// By default the breakpoint is enabled at creation
// If it wasn't supposed to be, then disable it right away
Map<String,Object> delta = new HashMap<String,Object>();
delta.put(IS_ENABLED, getProperty(attributes, IS_ENABLED, true));
modifyBreakpoint(dmc, delta, drm, false);
}
@Override
protected void handleError() {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, BREAKPOINT_INSERTION_FAILURE, null));
drm.done();
}
};
// Execute the command
fConnection.queueCommand(
new MIBreakInsert(context, isTemporary, isHardware, condition, ignoreCount, location, tid), addBreakpointDRM);
}
/**
* Add a breakpoint of type WATCHPOINT
*
* @param context
* @param watchpoint
* @param drm
*/
private void addWatchpoint(final IBreakpointsTargetDMContext context, final Map<String, Object> attributes, final DataRequestMonitor<IBreakpointDMContext> drm)
{
// Pick the context breakpoints map
final Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context);
if (contextBreakpoints == null) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null));
drm.done();
return;
}
// Extract the relevant parameters (providing default values to avoid potential NPEs)
String expression = (String) getProperty(attributes, EXPRESSION, NULL_STRING);
boolean isRead = (Boolean) getProperty(attributes, READ, false);
boolean isWrite = (Boolean) getProperty(attributes, WRITE, false);
// The DataRequestMonitor for the add request
DataRequestMonitor<MIBreakInsertInfo> addWatchpointDRM =
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), drm) {
@Override
protected void handleOK() {
// With MI, an invalid location won't generate an error
if (getData().getMIBreakpoints().length == 0) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, WATCHPOINT_INSERTION_FAILURE, null));
drm.done();
return;
}
// Create a breakpoint object and store it in the map
final MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(getData().getMIBreakpoints()[0]);
int reference = newBreakpoint.getNumber();
if (reference == -1) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, WATCHPOINT_INSERTION_FAILURE, null));
drm.done();
return;
}
contextBreakpoints.put(reference, newBreakpoint);
// Format the return value
IBreakpointDMContext dmc = new MIBreakpointDMContext(MIBreakpoints.this, new IDMContext[] { context }, reference);
drm.setData(dmc);
// Flag the event
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
// Condition, ignore count and state can not be specified at watchpoint creation time.
// Therefore, we have to update the watchpoint if any of these is present
Map<String,Object> delta = new HashMap<String,Object>();
delta.put(CONDITION, getProperty(attributes, CONDITION, NULL_STRING));
delta.put(IGNORE_COUNT, getProperty(attributes, IGNORE_COUNT, 0 ));
delta.put(IS_ENABLED, getProperty(attributes, IS_ENABLED, true));
modifyBreakpoint(dmc, delta, drm, false);
}
@Override
protected void handleError() {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, WATCHPOINT_INSERTION_FAILURE, null));
drm.done();
}
};
// Execute the command
fConnection.queueCommand(new MIBreakWatch(context, isRead, isWrite, expression), addWatchpointDRM);
}
//-------------------------------------------------------------------------
// removeBreakpoint
//-------------------------------------------------------------------------
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IBreakpoints#removeBreakpoint(org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointDMContext, org.eclipse.dd.dsf.concurrent.RequestMonitor)
*/
public void removeBreakpoint(final IBreakpointDMContext dmc, final RequestMonitor rm) {
// Validate the breakpoint context
if (dmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null));
rm.done();
return;
}
// Validate the breakpoint type
MIBreakpointDMContext breakpointCtx;
if (dmc instanceof MIBreakpointDMContext) {
breakpointCtx = (MIBreakpointDMContext) dmc;
}
else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_TYPE, null));
rm.done();
return;
}
// Validate the target context
IBreakpointsTargetDMContext context = DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class);
if (context == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_EXECUTION_CONTEXT, null));
rm.done();
return;
}
// Pick the context breakpoints map
final Map<Integer,MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context);
if (contextBreakpoints == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT, null));
rm.done();
return;
}
// Validate the breakpoint
final int reference = breakpointCtx.getReference();
MIBreakpointDMData breakpoint = contextBreakpoints.get(reference);
if (breakpoint == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT, null));
rm.done();
return;
}
// Queue the command
fConnection.queueCommand(
new MIBreakDelete(context, new int[] { reference }),
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
protected void handleCompleted() {
if (getStatus().isOK()) {
getSession().dispatchEvent(new BreakpointRemovedEvent(dmc), getProperties());
contextBreakpoints.remove(reference);
}
rm.done();
}
});
}
// -------------------------------------------------------------------------
// updateBreakpoint
//-------------------------------------------------------------------------
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IBreakpoints#updateBreakpoint(org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointDMContext, java.util.Map, org.eclipse.dd.dsf.concurrent.RequestMonitor)
*/
public void updateBreakpoint(IBreakpointDMContext dmc, Map<String, Object> properties, RequestMonitor rm)
{
// Validate the breakpoint context
if (dmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null));
rm.done();
return;
}
// Validate the breakpoint type
MIBreakpointDMContext breakpointCtx;
if (dmc instanceof MIBreakpointDMContext) {
breakpointCtx = (MIBreakpointDMContext) dmc;
}
else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_TYPE, null));
rm.done();
return;
}
// Validate the context
IBreakpointsTargetDMContext context = DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class);
if (context == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_EXECUTION_CONTEXT, null));
rm.done();
return;
}
// Pick the context breakpoints map
final Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context);
if (contextBreakpoints == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT, null));
rm.done();
return;
}
// Validate the breakpoint
final int reference = breakpointCtx.getReference();
MIBreakpointDMData breakpoint = contextBreakpoints.get(reference);
if (breakpoint == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT, null));
rm.done();
return;
}
modifyBreakpoint(dmc, properties, rm, true);
}
/**
* @param dmc
* @param properties
* @param rm
* @param generateUpdateEvent
*/
private void modifyBreakpoint(final IBreakpointDMContext dmc, Map<String, Object> attributes, final RequestMonitor rm, final boolean generateUpdateEvent)
{
// Use a working copy of the attributes since we are going to tamper happily with them
Map<String, Object> properties = new HashMap<String, Object>(attributes);
// Retrieve the breakpoint parameters
// At this point, we know their are OK so there is no need to re-validate
MIBreakpointDMContext breakpointCtx = (MIBreakpointDMContext) dmc;
IBreakpointsTargetDMContext context = DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class);
final Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context);
final int reference = breakpointCtx.getReference();
MIBreakpointDMData breakpoint = contextBreakpoints.get(reference);
// Track the number of change requests
int numberOfChanges = 0;
final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) {
@Override
protected void handleOK() {
if (generateUpdateEvent)
getSession().dispatchEvent(new BreakpointUpdatedEvent(dmc), getProperties());
rm.done();
}
};
// Determine if the breakpoint condition changed
String conditionAttribute = CONDITION;
if (properties.containsKey(conditionAttribute)) {
String oldValue = breakpoint.getCondition();
String newValue = (String) properties.get(conditionAttribute);
if (newValue == null) newValue = NULL_STRING;
if (!oldValue.equals(newValue)) {
changeCondition(context, reference, newValue, countingRm);
numberOfChanges++;
}
properties.remove(conditionAttribute);
}
// Determine if the breakpoint ignore count changed
String ignoreCountAttribute = IGNORE_COUNT;
if (properties.containsKey(ignoreCountAttribute)) {
Integer oldValue = breakpoint.getIgnoreCount();
Integer newValue = (Integer) properties.get(ignoreCountAttribute);
if (newValue == null) newValue = 0;
if (!oldValue.equals(newValue)) {
changeIgnoreCount(context, reference, newValue, countingRm);
numberOfChanges++;
}
properties.remove(ignoreCountAttribute);
}
// Determine if the breakpoint state changed
String enableAttribute = IS_ENABLED;
if (properties.containsKey(enableAttribute)) {
Boolean oldValue = breakpoint.isEnabled();
Boolean newValue = (Boolean) properties.get(enableAttribute);
if (newValue == null) newValue = false;
if (!oldValue.equals(newValue)) {
numberOfChanges++;
if (newValue)
enableBreakpoint(context, reference, countingRm);
else
disableBreakpoint(context, reference, countingRm);
}
properties.remove(enableAttribute);
}
// Set the number of completions required
countingRm.setDoneCount(numberOfChanges);
}
/**
* Update the breakpoint condition
*
* @param context
* @param dmc
* @param condition
* @param rm
*/
private void changeCondition(IBreakpointsTargetDMContext context,
final int reference, final String condition, final RequestMonitor rm)
{
// Pick the context breakpoints map
final Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context);
if (contextBreakpoints == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null));
rm.done();
return;
}
// Queue the command
fConnection.queueCommand(
new MIBreakCondition(context, reference, condition),
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
protected void handleCompleted() {
MIBreakpointDMData breakpoint = contextBreakpoints.get(reference);
if (breakpoint == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT, null));
rm.done();
return;
}
if (getStatus().isOK()) {
breakpoint.setCondition(condition);
}
else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, INVALID_CONDITION, null));
breakpoint.setCondition(NULL_STRING);
}
rm.done();
}
});
}
/**
* Update the breakpoint ignoreCount
*
* @param context
* @param reference
* @param ignoreCount
* @param rm
*/
private void changeIgnoreCount(IBreakpointsTargetDMContext context,
final int reference, final int ignoreCount, final RequestMonitor rm)
{
// Pick the context breakpoints map
final Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context);
if (contextBreakpoints == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null));
rm.done();
return;
}
// Queue the command
fConnection.queueCommand(
new MIBreakAfter(context, reference, ignoreCount),
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
MIBreakpointDMData breakpoint = contextBreakpoints.get(reference);
if (breakpoint == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT, null));
rm.done();
return;
}
breakpoint.setIgnoreCount(ignoreCount);
rm.done();
}
});
}
/**
* Enable the breakpoint
*
* @param context
* @param reference
* @param rm
*/
private void enableBreakpoint(IBreakpointsTargetDMContext context,
final int reference, final RequestMonitor rm)
{
// Pick the context breakpoints map
final Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context);
if (contextBreakpoints == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null));
rm.done();
return;
}
// Queue the command
fConnection.queueCommand(
new MIBreakEnable(context, new int[] { reference }),
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
MIBreakpointDMData breakpoint = contextBreakpoints.get(reference);
if (breakpoint == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT, null));
rm.done();
return;
}
breakpoint.setEnabled(true);
rm.done();
}
});
}
/**
* Disable the breakpoint
*
* @param context
* @param dmc
* @param rm
*/
private void disableBreakpoint(IBreakpointsTargetDMContext context,
final int reference, final RequestMonitor rm)
{
// Pick the context breakpoints map
final Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context);
if (contextBreakpoints == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT_CONTEXT, null));
rm.done();
return;
}
// Queue the command
fConnection.queueCommand(
new MIBreakDisable(context, new int[] { reference }),
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
MIBreakpointDMData breakpoint = contextBreakpoints.get(reference);
if (breakpoint == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, UNKNOWN_BREAKPOINT, null));
rm.done();
return;
}
breakpoint.setEnabled(false);
rm.done();
}
});
}
}

View file

@ -0,0 +1,185 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.breakpointactions.IBreakpointAction;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.model.IBreakpoint;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
public class MIBreakpointsActionManager {
public static final String BREAKPOINT_ACTION_ATTRIBUTE = "BREAKPOINT_ACTIONS"; //$NON-NLS-1$
private static final String BREAKPOINT_ACTION_DATA = "BreakpointActionManager.actionData"; //$NON-NLS-1$
private ArrayList breakpointActions = null;
public MIBreakpointsActionManager() {
}
public void executeActions(final IBreakpoint breakpoint, final IAdaptable context) {
if (breakpoint != null) {
IMarker marker = breakpoint.getMarker();
String actionNames = marker.getAttribute(BREAKPOINT_ACTION_ATTRIBUTE, ""); //$NON-NLS-1$
final String[] actions = actionNames.split(",");
if (actions.length > 0){
Job job = new Job("Execute breakpoint actions") {
public IStatus run(final IProgressMonitor monitor) {
return doExecuteActions(breakpoint, context, actions, monitor);
}
};
job.schedule();
try {
// wait for actions to execute
job.join();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private IStatus doExecuteActions(final IBreakpoint breakpoint, final IAdaptable context, String[] actions, IProgressMonitor monitor) {
try {
for (int i = 0; i < actions.length && !monitor.isCanceled(); i++) {
String actionName = actions[i];
IBreakpointAction action = findBreakpointAction(actionName);
if (action != null) {
monitor.setTaskName(action.getSummary());
IStatus status = action.execute(breakpoint, context, monitor);
if (status.getCode() != IStatus.OK) {
// do not log status if user canceled.
if (status.getCode() != IStatus.CANCEL)
CDebugCorePlugin.log(status);
return status;
}
}
monitor.worked(1);
}
} catch (Exception e) {
return new Status( IStatus.ERROR, CDebugCorePlugin.getUniqueIdentifier(), CDebugCorePlugin.INTERNAL_ERROR, "Internal Error", e );
}
return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
}
public IBreakpointAction findBreakpointAction(String name) {
for (Iterator iter = getBreakpointActions().iterator(); iter.hasNext();) {
IBreakpointAction action = (IBreakpointAction) iter.next();
if (action.getName().equals(name))
return action;
}
return null;
}
public ArrayList getBreakpointActions() {
if (breakpointActions == null) {
breakpointActions = new ArrayList();
loadActionData();
}
return breakpointActions;
}
private void loadActionData() {
String actionData = CDebugCorePlugin.getDefault().getPluginPreferences().getString(BREAKPOINT_ACTION_DATA);
if (actionData == null || actionData.length() == 0)
return;
Element root = null;
DocumentBuilder parser;
try {
parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
parser.setErrorHandler(new DefaultHandler());
root = parser.parse(new InputSource(new StringReader(actionData))).getDocumentElement();
NodeList nodeList = root.getChildNodes();
int entryCount = nodeList.getLength();
for (int i = 0; i < entryCount; i++) {
Node node = nodeList.item(i);
short type = node.getNodeType();
if (type == Node.ELEMENT_NODE) {
Element subElement = (Element) node;
String nodeName = subElement.getNodeName();
if (nodeName.equalsIgnoreCase("actionEntry")) { //$NON-NLS-1$
String name = subElement.getAttribute("name"); //$NON-NLS-1$
if (name == null)
throw new Exception();
String value = subElement.getAttribute("value"); //$NON-NLS-1$
if (value == null)
throw new Exception();
String className = subElement.getAttribute("class"); //$NON-NLS-1$
if (className == null)
throw new Exception();
IBreakpointAction action = createActionFromClassName(name, className);
action.initializeFromMemento(value);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private IBreakpointAction createActionFromClassName(String name, String className) {
IBreakpointAction action = null;
IExtension[] actionExtensions = CDebugCorePlugin.getDefault().getBreakpointActionManager().getBreakpointActionExtensions();
try {
for (int i = 0; i < actionExtensions.length && action == null; i++) {
IConfigurationElement[] elements = actionExtensions[i].getConfigurationElements();
for (int j = 0; j < elements.length && action == null; j++) {
IConfigurationElement element = elements[j];
if (element.getName().equals(CDebugCorePlugin.ACTION_TYPE_ELEMENT)) {
if (element.getAttribute("class").equals(className)) { //$NON-NLS-1$
action = (IBreakpointAction) element.createExecutableExtension("class"); //$NON-NLS-1$
action.setName(name);
CDebugCorePlugin.getDefault().getBreakpointActionManager().addAction(action);
}
}
}
}
} catch (CoreException e) {
e.printStackTrace();
}
return action;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,109 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service;
import java.math.BigInteger;
/**
* Help class to specify formats.
*/
public final class MIFormat {
public final static int HEXADECIMAL = 0;
public final static int OCTAL = 1;
public final static int BINARY = 2;
public final static int DECIMAL = 3;
public final static int RAW = 4;
public final static int NATURAL = 5;
public final static int FLOAT = 10;
public final static int ADDRESS = 11;
public final static int INSTRUCTION = 12;
public final static int CHAR = 13;
public final static int STRING = 14;
public final static int UNSIGNED = 15;
// no instanciation.
private MIFormat() {
}
/**
* We are assuming that GDB will print the address in hex format
* like:
* 0xbfffe5f0 "hello"
* (int *) 0xbfffe2b8
*
* @param buffer
* @return
*/
public static BigInteger decodeAdress(String buffer) {
int radix = 10;
int cursor = 0;
int offset = 0;
int len = buffer.length();
if ((offset = buffer.indexOf("0x")) != -1 || //$NON-NLS-1$
(offset = buffer.indexOf("0X")) != -1) { //$NON-NLS-1$
radix = 16;
cursor = offset + 2;
}
while (cursor < len && Character.digit(buffer.charAt(cursor), radix) != -1) {
cursor++;
}
String s = buffer.substring(offset, cursor);
return getBigInteger(s);
}
public static BigInteger getBigInteger(String address) {
int index = 0;
int radix = 10;
boolean negative = false;
// Handle zero length
address = address.trim();
if (address.length() == 0) {
return BigInteger.ZERO;
}
// Handle minus sign, if present
if (address.startsWith("-")) { //$NON-NLS-1$
negative = true;
index++;
}
if (address.startsWith("0x", index) || address.startsWith("0X", index)) { //$NON-NLS-1$ //$NON-NLS-2$
index += 2;
radix = 16;
} else if (address.startsWith("#", index)) { //$NON-NLS-1$
index ++;
radix = 16;
} else if (address.startsWith("0", index) && address.length() > 1 + index) { //$NON-NLS-1$
index ++;
radix = 8;
}
if (index > 0) {
address = address.substring(index);
}
if (negative) {
address = "-" + address; //$NON-NLS-1$
}
try {
return new BigInteger(address, radix);
} catch (NumberFormatException e) {
// ...
// What can we do ???
}
return BigInteger.ZERO;
}
}

View file

@ -0,0 +1,895 @@
/*******************************************************************************
* Copyright (c) 2007 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
* Ericsson AB - expanded from initial stub
* Ericsson AB - added support for event handling
* Ericsson AB - added memory cache
*******************************************************************************/
package org.eclipse.dd.mi.service;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.ListIterator;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IExpressions;
import org.eclipse.dd.dsf.debug.service.IMemory;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMAddress;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
import org.eclipse.dd.dsf.debug.service.command.CommandCache;
import org.eclipse.dd.dsf.debug.service.command.ICommandControl;
import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.ExpressionService.ExpressionChangedEvent;
import org.eclipse.dd.mi.service.command.commands.MIDataReadMemory;
import org.eclipse.dd.mi.service.command.commands.MIDataWriteMemory;
import org.eclipse.dd.mi.service.command.output.MIDataReadMemoryInfo;
import org.eclipse.dd.mi.service.command.output.MIDataWriteMemoryInfo;
import org.eclipse.debug.core.model.MemoryByte;
import org.osgi.framework.BundleContext;
/**
* Memory service implementation
*/
public class MIMemory extends AbstractDsfService implements IMemory {
public class MemoryChangedEvent extends AbstractDMEvent<IMemoryDMContext>
implements IMemoryChangedEvent
{
IAddress[] fAddresses;
IDMContext fContext;
public MemoryChangedEvent(IMemoryDMContext context, IAddress[] addresses) {
super(context);
fAddresses = addresses;
}
public IAddress[] getAddresses() {
return fAddresses;
}
}
@SuppressWarnings("unused")
private MIRunControl fRunControl;
private MIMemoryCache fMemoryCache;
/**
* Constructor
*/
public MIMemory(DsfSession session) {
super(session);
}
///////////////////////////////////////////////////////////////////////////
// AbstractDsfService overrides
///////////////////////////////////////////////////////////////////////////
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.service.AbstractDsfService#initialize(org.eclipse.dd.dsf.concurrent.RequestMonitor)
*
* This function is called during the launch sequence (where the service is
* instantiated). See LaunchSequence.java.
*/
@Override
public void initialize(final RequestMonitor requestMonitor) {
super.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
@Override
protected void handleOK() {
doInitialize(requestMonitor);
}
});
}
/*
* Initialization function:
* - Register the service
* - Create the command cache
* - Register self to service events
*
* @param requestMonitor
*/
private void doInitialize(final RequestMonitor requestMonitor) {
// Register this service
register(new String[] { MIMemory.class.getName(), IMemory.class.getName() }, new Hashtable<String, String>());
// Get the RunControl so we can retrieve the current Execution context
fRunControl = getServicesTracker().getService(MIRunControl.class);
// Create the memory requests cache
fMemoryCache = new MIMemoryCache();
// Register as service event listener
getSession().addServiceEventListener(this, null);
// Done
requestMonitor.done();
}
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.service.AbstractDsfService#shutdown(org.eclipse.dd.dsf.concurrent.RequestMonitor)
*/
@Override
public void shutdown(final RequestMonitor requestMonitor) {
// Unregister this service
unregister();
// Remove event listener
getSession().removeServiceEventListener(this);
// Clear the cache
fMemoryCache.reset();
// Complete the shutdown
super.shutdown(requestMonitor);
}
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.service.AbstractDsfService#getBundleContext()
*/
@Override
protected BundleContext getBundleContext() {
return MIPlugin.getBundleContext();
}
///////////////////////////////////////////////////////////////////////////
// IMemory
///////////////////////////////////////////////////////////////////////////
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IMemory#getMemory(org.eclipse.dd.dsf.datamodel.IDMContext, org.eclipse.cdt.core.IAddress, long, int, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
*/
public void getMemory(IMemoryDMContext memoryDMC, IAddress address, long offset,
int word_size, int count, DataRequestMonitor<MemoryByte[]> drm)
{
// Validate the context
if (memoryDMC == null) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
drm.done();
return;
}
// Validate the word size
// NOTE: We only accept 1 byte words for this implementation
if (word_size != 1) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.NOT_SUPPORTED, "Word size not supported (!= 1)", null)); //$NON-NLS-1$
drm.done();
return;
}
// Validate the byte count
if (count < 0) {
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Invalid word count (< 0)", null)); //$NON-NLS-1$
drm.done();
return;
}
// All is clear: go for it
fMemoryCache.getMemory(memoryDMC, address.add(offset), word_size, count, drm);
}
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IMemory#setMemory(org.eclipse.dd.dsf.datamodel.IDMContext, org.eclipse.cdt.core.IAddress, long, int, byte[], org.eclipse.dd.dsf.concurrent.RequestMonitor)
*/
public void setMemory(IMemoryDMContext memoryDMC, IAddress address, long offset,
int word_size, int count, byte[] buffer, RequestMonitor rm)
{
// Validate the context
if (memoryDMC == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
rm.done();
return;
}
// Validate the word size
// NOTE: We only accept 1 byte words for this implementation
if (word_size != 1) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.NOT_SUPPORTED, "Word size not supported (!= 1)", null)); //$NON-NLS-1$
rm.done();
return;
}
// Validate the byte count
if (count < 0) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Invalid word count (< 0)", null)); //$NON-NLS-1$
rm.done();
return;
}
// Validate the buffer size
if (buffer.length < count) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Buffer too short", null)); //$NON-NLS-1$
rm.done();
return;
}
// All is clear: go for it
fMemoryCache.setMemory(memoryDMC, address, offset, word_size, count, buffer, rm);
}
/* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IMemory#fillMemory(org.eclipse.dd.dsf.datamodel.IDMContext, org.eclipse.cdt.core.IAddress, long, int, byte[], org.eclipse.dd.dsf.concurrent.RequestMonitor)
*/
public void fillMemory(IMemoryDMContext memoryDMC, IAddress address, long offset,
int word_size, int count, byte[] pattern, RequestMonitor rm)
{
// Validate the context
if (memoryDMC == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
rm.done();
return;
}
// Validate the word size
// NOTE: We only accept 1 byte words for this implementation
if (word_size != 1) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.NOT_SUPPORTED, "Word size not supported (!= 1)", null)); //$NON-NLS-1$
rm.done();
return;
}
// Validate the repeat count
if (count < 0) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Invalid repeat count (< 0)", null)); //$NON-NLS-1$
rm.done();
return;
}
// Validate the pattern
if (pattern.length < 1) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Empty pattern", null)); //$NON-NLS-1$
rm.done();
return;
}
// Create an aggregate buffer so we can write in 1 shot
int length = pattern.length;
byte[] buffer = new byte[count * length];
for (int i = 0; i < count; i++) {
System.arraycopy(pattern, 0, buffer, i * length, length);
}
// All is clear: go for it
fMemoryCache.setMemory(memoryDMC, address, offset, word_size, count * length, buffer, rm);
}
//////////////////////////////////////////////////////////////////////////
// Event handlers
//////////////////////////////////////////////////////////////////////////
@DsfServiceEventHandler
public void eventDispatched(IRunControl.IResumedDMEvent e) {
fMemoryCache.setTargetAvailable(false);
if (e.getReason() != StateChangeReason.STEP) {
fMemoryCache.reset();
}
}
@DsfServiceEventHandler
public void eventDispatched(IRunControl.ISuspendedDMEvent e) {
fMemoryCache.setTargetAvailable(true);
fMemoryCache.reset();
}
@DsfServiceEventHandler
public void eventDispatched(ExpressionChangedEvent e) {
// Get the context and expression service handle
final IExpressionDMContext context = e.getDMContext();
IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
// Get the variable information and update the corresponding memory locations
if (expressionService != null) {
expressionService.getExpressionAddressData(context,
new DataRequestMonitor<IExpressionDMAddress>(getExecutor(), null) {
@Override
protected void handleOK() {
// Figure out which memory area was modified
IExpressionDMAddress expression = getData();
final int count = expression.getSize();
IAddress expAddress = expression.getAddress();
final Addr64 address;
if (expAddress instanceof Addr64)
address = (Addr64) expAddress;
else
address = new Addr64(expAddress.getValue());
final IMemoryDMContext memoryDMC = DMContexts.getAncestorOfType(context, IMemoryDMContext.class);
fMemoryCache.refreshMemory(memoryDMC, address, 0, 1, count,
new RequestMonitor(getExecutor(), null));
}
});
}
}
///////////////////////////////////////////////////////////////////////////
// SortedLinkedlist
///////////////////////////////////////////////////////////////////////////
// This class is really the equivalent of a C struct (old habits die hard...)
// For simplicity, everything is public.
private class MemoryBlock {
public IAddress fAddress;
public long fLength;
public MemoryByte[] fBlock;
public MemoryBlock(IAddress address, long length, MemoryByte[] block) {
fAddress = address;
fLength = length;
fBlock = block;
}
}
// Address-ordered data structure to cache the memory blocks.
// Contiguous blocks are merged if possible.
@SuppressWarnings("serial")
private class SortedMemoryBlockList extends LinkedList<MemoryBlock> {
public SortedMemoryBlockList() {
super();
}
// Insert the block in the sorted linked list and merge contiguous
// blocks if necessary
@Override
@SuppressWarnings("unchecked")
public boolean add(MemoryBlock block) {
// If the list is empty, just store the block
if (isEmpty()) {
addFirst(block);
return true;
}
// Insert the block at the correct location and then
// merge the blocks if possible
ListIterator<MemoryBlock> it = listIterator();
while (it.hasNext()) {
int index = it.nextIndex();
MemoryBlock item = it.next();
if (block.fAddress.compareTo(item.fAddress) < 0) {
add(index, block);
compact(index);
return true;
}
}
// Put at the end of the list and merge if necessary
addLast(block);
compact(size() - 1);
return true;
}
// Merge this block with its contiguous neighbors (if any)
// Note: Merge is not performed if resulting block size would exceed MAXINT
private void compact(int index) {
MemoryBlock newBlock = get(index);
// Case where the block is to be merged with the previous block
if (index > 0) {
MemoryBlock prevBlock = get(index - 1);
IAddress endOfPreviousBlock = prevBlock.fAddress.add(prevBlock.fLength);
if (endOfPreviousBlock.distanceTo(newBlock.fAddress).longValue() == 0) {
long newLength = prevBlock.fLength + newBlock.fLength;
if (newLength <= Integer.MAX_VALUE) {
MemoryByte[] block = new MemoryByte[(int) newLength] ;
System.arraycopy(prevBlock.fBlock, 0, block, 0, (int) prevBlock.fLength);
System.arraycopy(newBlock.fBlock, 0, block, (int) prevBlock.fLength, (int) newBlock.fLength);
newBlock = new MemoryBlock(prevBlock.fAddress, newLength, block);
remove(index);
index -= 1;
set(index, newBlock);
}
}
}
// Case where the block is to be merged with the following block
int lastIndex = size() - 1;
if (index < lastIndex) {
MemoryBlock nextBlock = get(index + 1);
IAddress endOfNewBlock = newBlock.fAddress.add(newBlock.fLength);
if (endOfNewBlock.distanceTo(nextBlock.fAddress).longValue() == 0) {
long newLength = newBlock.fLength + nextBlock.fLength;
if (newLength <= Integer.MAX_VALUE) {
MemoryByte[] block = new MemoryByte[(int) newLength] ;
System.arraycopy(newBlock.fBlock, 0, block, 0, (int) newBlock.fLength);
System.arraycopy(nextBlock.fBlock, 0, block, (int) newBlock.fLength, (int) nextBlock.fLength);
newBlock = new MemoryBlock(newBlock.fAddress, newLength, block);
set(index, newBlock);
remove(index + 1);
}
}
}
}
}
///////////////////////////////////////////////////////////////////////////
// MIMemoryCache
///////////////////////////////////////////////////////////////////////////
private class MIMemoryCache {
// Back-end commands cache
private CommandCache fCommandCache;
// The memory cache data structure
private SortedMemoryBlockList fMemoryBlockList;
public MIMemoryCache() {
// Create the command cache
fCommandCache = new CommandCache(getServicesTracker().getService(ICommandControl.class));
// Create the memory block cache
fMemoryBlockList = new SortedMemoryBlockList();
}
public void reset() {
// Clear the command cache
fCommandCache.reset();
// Clear the memory cache
fMemoryBlockList.clear();
}
public void setTargetAvailable(boolean isAvailable) {
fCommandCache.setTargetAvailable(isAvailable);
}
public boolean isTargetAvailable() {
return fCommandCache.isTargetAvailable();
}
/**
* This function walks the address-sorted memory block list to identify
* the 'missing' blocks (i.e. the holes) that need to be fetched on the target.
*
* The idea is fairly simple but an illustration could perhaps help.
* Assume the cache holds a number of cached memory blocks with gaps i.e.
* there is un-cached memory areas between blocks A, B and C:
*
* +---------+ +---------+ +---------+
* + A + + B + + C +
* +---------+ +---------+ +---------+
* : : : : : :
* [a] : : [b] : : [c] : : [d]
* : : : : : :
* [e---+--] : [f--+---------+--] : :
* [g---+---------+------+---------+------+---------+----]
* : : : : : :
* : [h] : : [i----+--] : :
*
*
* We have the following cases to consider.The requested block [a-i] either:
*
* [1] Fits entirely before A, in one of the gaps, or after C
* with no overlap and no contiguousness (e.g. [a], [b], [c] and [d])
* -> Add the requested block to the list of blocks to fetch
*
* [2] Starts before an existing block but overlaps part of it, possibly
* spilling in the gap following the cached block (e.g. [e], [f] and [g])
* -> Determine the length of the missing part (< count)
* -> Add a request to fill the gap before the existing block
* -> Update the requested block for the next iteration:
* - Start address to point just after the end of the cached block
* - Count reduced by cached block length (possibly becoming negative, e.g. [e])
* At this point, the updated requested block starts just beyond the cached block
* for the next iteration.
*
* [3] Starts at or into an existing block and overlaps part of it ([h] and [i])
* -> Update the requested block for the next iteration:
* - Start address to point just after the end of the cached block
* - Count reduced by length to end of cached block (possibly becoming negative, e.g. [h])
* At this point, the updated requested block starts just beyond the cached block
* for the next iteration.
*
* We iterate over the cached blocks list until there is no entry left or until
* the remaining requested block count is <= 0, meaning the result list contains
* only the sub-blocks needed to fill the gap(s), if any.
*
* (As is often the case, it takes much more typing to explain it than to just do it :-)
*
* @param reqBlockStart The address of the requested block
* @param count Its length
* @return A list of the sub-blocks to fetch in order to fill enough gaps in the memory cache
* to service the request
*/
private LinkedList<MemoryBlock> getListOfMissingBlocks(IAddress reqBlockStart, int count) {
LinkedList<MemoryBlock> list = new LinkedList<MemoryBlock>();
ListIterator<MemoryBlock> it = fMemoryBlockList.listIterator();
// Look for holes in the list of memory blocks
while (it.hasNext() && count > 0) {
MemoryBlock cachedBlock = it.next();
IAddress cachedBlockStart = cachedBlock.fAddress;
IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLength);
// Case where we miss a block before the cached block
if (reqBlockStart.distanceTo(cachedBlockStart).longValue() >= 0) {
int length = (int) Math.min(reqBlockStart.distanceTo(cachedBlockStart).longValue(), count);
// If both blocks start at the same location, no need to create a new cached block
if (length > 0) {
MemoryBlock newBlock = new MemoryBlock(reqBlockStart, length, new MemoryByte[0]);
list.add(newBlock);
}
// Adjust request block start and length for the next iteration
reqBlockStart = cachedBlockEnd;
count -= length + cachedBlock.fLength;
}
// Case where the requested block starts somewhere in the cached block
else if (cachedBlockStart.distanceTo(reqBlockStart).longValue() > 0
&& reqBlockStart.distanceTo(cachedBlockEnd).longValue() >= 0)
{
// Start of the requested block already in cache
// Adjust request block start and length for the next iteration
count -= reqBlockStart.distanceTo(cachedBlockEnd).longValue();
reqBlockStart = cachedBlockEnd;
}
}
// Case where we miss a block at the end of the cache
if (count > 0) {
MemoryBlock newBlock = new MemoryBlock(reqBlockStart, count, new MemoryByte[0]);
list.add(newBlock);
}
return list;
}
/**
* This function walks the address-sorted memory block list to get the
* cached memory bytes (possibly from multiple contiguous blocks).
* This function is called *after* the missing blocks have been read from
* the back end i.e. the requested memory is all cached.
*
* Again, this is fairly simple. As we loop over the address-ordered list,
* There are really only 2 cases:
*
* [1] The requested block fits entirely in the cached block ([a] or [b])
* [2] The requested block starts in a cached block and ends in the
* following (contiguous) one ([c]) in which case it is treated
* as 2 contiguous requests ([c'] and [c"])
*
* +--------------+--------------+
* + A + B +
* +--------------+--------------+
* : [a----] : [b-----] :
* : : :
* : [c-----+------] :
* : [c'---]+[c"---] :
*
* @param reqBlockStart The address of the requested block
* @param count Its length
* @return The cached memory content
*/
private MemoryByte[] getMemoryBlockFromCache(IAddress reqBlockStart, int count) {
IAddress reqBlockEnd = reqBlockStart.add(count);
MemoryByte[] resultBlock = new MemoryByte[count];
ListIterator<MemoryBlock> iter = fMemoryBlockList.listIterator();
while (iter.hasNext()) {
MemoryBlock cachedBlock = iter.next();
IAddress cachedBlockStart = cachedBlock.fAddress;
IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLength);
// Case where the cached block overlaps completely the requested memory block
if (cachedBlockStart.distanceTo(reqBlockStart).longValue() >= 0
&& reqBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0)
{
int pos = (int) cachedBlockStart.distanceTo(reqBlockStart).longValue();
System.arraycopy(cachedBlock.fBlock, pos, resultBlock, 0, count);
}
// Case where the beginning of the cached block is within the requested memory block
else if (reqBlockStart.distanceTo(cachedBlockStart).longValue() >= 0
&& cachedBlockStart.distanceTo(reqBlockEnd).longValue() > 0)
{
int pos = (int) reqBlockStart.distanceTo(cachedBlockStart).longValue();
int length = (int) Math.min(cachedBlock.fLength, count - pos);
System.arraycopy(cachedBlock.fBlock, 0, resultBlock, pos, length);
}
// Case where the end of the cached block is within the requested memory block
else if (cachedBlockStart.distanceTo(reqBlockStart).longValue() >= 0
&& reqBlockStart.distanceTo(cachedBlockEnd).longValue() > 0)
{
int pos = (int) cachedBlockStart.distanceTo(reqBlockStart).longValue();
int length = (int) Math.min(cachedBlock.fLength - pos, count);
System.arraycopy(cachedBlock.fBlock, pos, resultBlock, 0, length);
}
}
return resultBlock;
}
/**
* This function walks the address-sorted memory block list and updates
* the content with the actual memory just read from the target.
*
* @param modBlockStart
* @param count
* @param modBlock
*/
private void updateMemoryCache(IAddress modBlockStart, int count, MemoryByte[] modBlock) {
IAddress modBlockEnd = modBlockStart.add(count);
ListIterator<MemoryBlock> iter = fMemoryBlockList.listIterator();
while (iter.hasNext()) {
MemoryBlock cachedBlock = iter.next();
IAddress cachedBlockStart = cachedBlock.fAddress;
IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLength);
// For now, we only bother to update bytes already cached.
// Note: In a better implementation (v1.1), we would augment
// the cache with the missing memory blocks since we went
// through the pains of reading them in the first place.
// (this is left as an exercise to the reader :-)
// Case where the modified block is completely included in the cached block
if (cachedBlockStart.distanceTo(modBlockStart).longValue() >= 0
&& modBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0)
{
int pos = (int) cachedBlockStart.distanceTo(modBlockStart).longValue();
System.arraycopy(modBlock, 0, cachedBlock.fBlock, pos, count);
}
// Case where the beginning of the modified block is within the cached block
else if (cachedBlockStart.distanceTo(modBlockStart).longValue() >= 0
&& modBlockStart.distanceTo(cachedBlockEnd).longValue() > 0)
{
int pos = (int) cachedBlockStart.distanceTo(modBlockStart).longValue();
int length = (int) cachedBlockStart.distanceTo(modBlockEnd).longValue();
System.arraycopy(modBlock, 0, cachedBlock.fBlock, pos, length);
}
// Case where the end of the modified block is within the cached block
else if (cachedBlockStart.distanceTo(modBlockEnd).longValue() > 0
&& modBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0)
{
int pos = (int) modBlockStart.distanceTo(cachedBlockStart).longValue();
int length = (int) cachedBlockStart.distanceTo(modBlockEnd).longValue();
System.arraycopy(modBlock, pos, cachedBlock.fBlock, 0, length);
}
}
return;
}
/**
* @param memoryDMC
* @param address the memory block address (on the target)
* @param word_size the size, in bytes, of an addressable item
* @param count the number of bytes to read
* @param drm the asynchronous data request monitor
*/
public void getMemory(IMemoryDMContext memoryDMC, final IAddress address, final int word_size,
final int count, final DataRequestMonitor<MemoryByte[]> drm)
{
// Determine the number of read requests to issue
LinkedList<MemoryBlock> missingBlocks = getListOfMissingBlocks(address, count);
int numberOfRequests = missingBlocks.size();
// A read request will be issued for each block needed
// so we need to keep track of the count
final CountingRequestMonitor countingRM =
new CountingRequestMonitor(getExecutor(), drm) {
@Override
protected void handleOK() {
// We received everything so read the result from the memory cache
drm.setData(getMemoryBlockFromCache(address, count));
drm.done();
}
};
countingRM.setDoneCount(numberOfRequests);
// Issue the read requests
for (int i = 0; i < numberOfRequests; i++) {
MemoryBlock block = missingBlocks.get(i);
final IAddress startAddress = block.fAddress;
final int length = (int) block.fLength;
readMemoryBlock(memoryDMC, startAddress, 0, word_size, length,
new DataRequestMonitor<MemoryByte[]>(getSession().getExecutor(), drm) {
@Override
protected void handleOK() {
MemoryByte[] block = new MemoryByte[count];
block = getData();
MemoryBlock memoryBlock = new MemoryBlock(startAddress, length, block);
fMemoryBlockList.add(memoryBlock);
countingRM.done();
}
});
}
}
/**
* @param memoryDMC
* @param address the memory block address (on the target)
* @param offset the offset from the start address
* @param word_size the size, in bytes, of an addressable item
* @param count the number of bytes to write
* @param buffer the source buffer
* @param rm the asynchronous request monitor
*/
public void setMemory(final IMemoryDMContext memoryDMC, final IAddress address,
final long offset, final int word_size, final int count, final byte[] buffer,
final RequestMonitor rm)
{
writeMemoryBlock(
memoryDMC, address, offset, word_size, count, buffer,
new RequestMonitor(getSession().getExecutor(), rm) {
@Override
protected void handleOK() {
// Clear the command cache (otherwise we can't guarantee
// that the subsequent memory read will be correct)
fCommandCache.reset();
// Asynchronous update of the memory cache
final DataRequestMonitor<MemoryByte[]> drm =
new DataRequestMonitor<MemoryByte[]>(getExecutor(), rm) {
@Override
protected void handleOK() {
updateMemoryCache(address.add(offset), count, getData());
// Send the MemoryChangedEvent
IAddress[] addresses = new IAddress[count];
for (int i = 0; i < count; i++) {
addresses[i] = address.add(offset + i);
}
getSession().dispatchEvent(new MemoryChangedEvent(memoryDMC, addresses), getProperties());
// Finally...
rm.done();
}
};
// Re-read the modified memory block
readMemoryBlock(memoryDMC, address, offset, word_size, count,
new DataRequestMonitor<MemoryByte[]>(getExecutor(), drm) {
@Override
public void handleOK() {
drm.setData(getData());
drm.done();
}
});
}
});
}
/**
* @param memoryDMC
* @param address
* @param offset
* @param word_size
* @param count
* @param rm
*/
public void refreshMemory(final IMemoryDMContext memoryDMC, final IAddress address,
final long offset, final int word_size, final int count, final RequestMonitor rm)
{
// Check if we already cache part of this memory area (which means it
// is used by a memory service client that will have to be updated)
LinkedList<MemoryBlock> list = fMemoryCache.getListOfMissingBlocks(address, count);
int sizeToRead = 0;
for (MemoryBlock block : list) {
sizeToRead += block.fLength;
}
// If none of the requested memory is in cache, just get out
if (sizeToRead == count) {
rm.done();
return;
}
// Prepare the data for the MemoryChangedEvent
final IAddress[] addresses = new IAddress[count];
for (int i = 0; i < count; i++) {
addresses[i] = address.add(i);
}
// Read the corresponding memory block
fMemoryCache.fCommandCache.reset();
fMemoryCache.readMemoryBlock(memoryDMC, address, 0, 1, count,
new DataRequestMonitor<MemoryByte[]>(getExecutor(), rm) {
@Override
public void handleOK() {
fMemoryCache.updateMemoryCache(address, count, getData());
getSession().dispatchEvent(new MemoryChangedEvent(memoryDMC, addresses), getProperties());
rm.done();
}
});
}
///////////////////////////////////////////////////////////////////////
// Back-end functions
///////////////////////////////////////////////////////////////////////
/**
* @param memoryDMC
* @param address
* @param offset
* @param word_size
* @param count
* @param drm
*/
private void readMemoryBlock(IMemoryDMContext memoryDMC, IAddress address, final long offset,
final int word_size, final int count, final DataRequestMonitor<MemoryByte[]> drm)
{
/* To simplify the parsing of the MI result, we request the output to
* be on 1 row of [count] columns, no char interpretation.
*/
int mode = MIFormat.HEXADECIMAL;
int nb_rows = 1;
int nb_cols = count;
Character asChar = null;
fCommandCache.execute(
new MIDataReadMemory(memoryDMC, offset, address.toString(), mode, word_size, nb_rows, nb_cols, asChar),
new DataRequestMonitor<MIDataReadMemoryInfo>(getExecutor(), drm) {
@Override
protected void handleOK() {
// Retrieve the memory block
drm.setData(getData().getMIMemoryBlock());
drm.done();
}
}
);
}
/**
* @param memoryDMC
* @param address
* @param offset
* @param word_size
* @param count
* @param buffer
* @param rm
*/
private void writeMemoryBlock(final IMemoryDMContext memoryDMC, final IAddress address, final long offset,
final int word_size, final int count, final byte[] buffer, final RequestMonitor rm)
{
// Each byte is written individually (GDB power...)
// so we need to keep track of the count
final CountingRequestMonitor countingRM =
new CountingRequestMonitor(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.done();
}
};
countingRM.setDoneCount(count);
// We will format the individual bytes in decimal
int format = MIFormat.DECIMAL;
String baseAddress = address.toString();
// Issue an MI request for each byte to write
for (int i = 0; i < count; i++) {
String value = new Byte(buffer[i]).toString();
fCommandCache.execute(
new MIDataWriteMemory(memoryDMC, offset + i, baseAddress, format, word_size, value),
new DataRequestMonitor<MIDataWriteMemoryInfo>(getExecutor(), countingRM)
);
}
}
}
}

View file

@ -0,0 +1,217 @@
/*******************************************************************************
* Copyright (c) 2007 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
* Ericsson AB - Modules implementation for GDB
*******************************************************************************/
package org.eclipse.dd.mi.service;
import java.math.BigInteger;
import java.util.Hashtable;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.core.runtime.IStatus;
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.datamodel.AbstractDMContext;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IModules;
import org.eclipse.dd.dsf.debug.service.command.CommandCache;
import org.eclipse.dd.dsf.debug.service.command.ICommandControl;
import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.command.commands.CLIInfoSharedLibrary;
import org.eclipse.dd.mi.service.command.output.CLIInfoSharedLibraryInfo;
import org.eclipse.dd.mi.service.command.output.CLIInfoSharedLibraryInfo.DsfMISharedInfo;
import org.osgi.framework.BundleContext;
/**
*
*/
public class MIModules extends AbstractDsfService implements IModules {
private CommandCache fModulesCache;
public MIModules(DsfSession session) {
super(session);
}
@Override
protected BundleContext getBundleContext() {
return MIPlugin.getBundleContext();
}
@Override
public void initialize(final RequestMonitor requestMonitor) {
super.initialize(
new RequestMonitor(getExecutor(), requestMonitor) {
@Override
protected void handleOK() {
doInitialize(requestMonitor);
}});
}
private void doInitialize(RequestMonitor requestMonitor) {
// Cache for holding Modules data
fModulesCache = new CommandCache(getServicesTracker().getService(ICommandControl.class));
/*
* Make ourselves known so clients can use us.
*/
register(new String[]{IModules.class.getName(), MIModules.class.getName()}, new Hashtable<String,String>());
requestMonitor.done();
}
@Override
public void shutdown(RequestMonitor requestMonitor) {
unregister();
super.shutdown(requestMonitor);
}
static class ModuleDMContext extends AbstractDMContext implements IModuleDMContext {
private final String fFile;
ModuleDMContext(MIModules service, IDMContext[] parents, String file) {
super(service, parents);
fFile = file;
}
@Override
public boolean equals(Object obj) {
return baseEquals(obj) && fFile.equals(((ModuleDMContext)obj).fFile);
}
@Override
public int hashCode() {
return baseHashCode() + fFile.hashCode();
}
}
static class ModuleDMData implements IModuleDMData {
private final String fFile;
private final String fFromAddress;
private final String fToAddress;
private final boolean fIsSymbolsRead;
public ModuleDMData(ModuleDMContext dmc) {
fFile = dmc.fFile;
fFromAddress = null;
fToAddress = null;
fIsSymbolsRead = false;
}
public ModuleDMData(String fileName, String fromAddress, String toAddress, boolean isSymsRead){
fFile = fileName;
fFromAddress = fromAddress;
fToAddress = toAddress;
fIsSymbolsRead = isSymsRead;
}
public String getFile() {
return fFile;
}
public String getName() {
return fFile;
}
public long getTimeStamp() {
return 0;
}
public String getBaseAddress() {
return fFromAddress;
}
public String getToAddress() {
return fToAddress;
}
public boolean isSymbolsLoaded() {
return fIsSymbolsRead;
}
public long getSize() {
long result = 0;
if(getBaseAddress() == null || getToAddress() == null)
return result;
BigInteger start = MIFormat.getBigInteger(getBaseAddress());
BigInteger end = MIFormat.getBigInteger(getToAddress());
if ( end.compareTo( start ) > 0 )
result = end.subtract( start ).longValue();
return result;
}
}
public void getModules(final ISymbolDMContext symCtx, final DataRequestMonitor<IModuleDMContext[]> rm) {
if(symCtx != null){
fModulesCache.execute(new CLIInfoSharedLibrary(symCtx),
new DataRequestMonitor<CLIInfoSharedLibraryInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(makeModuleContexts(symCtx, getData()));
rm.done();
}
});
}
else{
rm.setData(new IModuleDMContext[] { new ModuleDMContext(this, DMContexts.EMPTY_CONTEXTS_ARRAY, "example module 1"), new ModuleDMContext(this, DMContexts.EMPTY_CONTEXTS_ARRAY, "example module 2") }); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
}
}
private IModuleDMContext[] makeModuleContexts(IDMContext symCtxt, CLIInfoSharedLibraryInfo info){
DsfMISharedInfo[] sharedInfos = info.getMIShared();
ModuleDMContext[] modules = new ModuleDMContext[sharedInfos.length];
int i = 0;
for(DsfMISharedInfo shared : sharedInfos){
modules[i++] = new ModuleDMContext(this, new IDMContext[]{symCtxt}, shared.getName());
}
return modules;
}
public void getModuleData(final IModuleDMContext dmc, final DataRequestMonitor<IModuleDMData> rm) {
assert dmc != null;
if (dmc instanceof ModuleDMContext) {
fModulesCache.execute(new CLIInfoSharedLibrary(dmc),
new DataRequestMonitor<CLIInfoSharedLibraryInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData( createSharedLibInfo((ModuleDMContext)dmc, getData()) );
rm.done();
}
});
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DM Context", null)); //$NON-NLS-1$
rm.done();
}
}
private IModuleDMData createSharedLibInfo(ModuleDMContext dmc, CLIInfoSharedLibraryInfo info){
for (CLIInfoSharedLibraryInfo.DsfMISharedInfo shared : info.getMIShared()) {
if(shared.getName().equals(dmc.fFile)){
return new ModuleDMData(shared.getName(), shared.getFrom(), shared.getTo(), shared.isRead());
}
}
return new ModuleDMData("","", "", false); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public void calcAddressInfo(ISymbolDMContext symCtx, String file, int line, int col, DataRequestMonitor<AddressRange[]> rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Functionality not supported", null)); //$NON-NLS-1$
rm.done();
}
public void calcLineInfo(ISymbolDMContext symCtx, IAddress address, DataRequestMonitor<LineInfo[]> rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Functionality not supported", null)); //$NON-NLS-1$
rm.done();
}
}

View file

@ -0,0 +1,583 @@
/*******************************************************************************
* 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
* Ericsson - Modified for additional features in DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service;
import java.util.Hashtable;
import org.eclipse.core.runtime.IStatus;
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.datamodel.AbstractDMContext;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IRegisters;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMData;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
import org.eclipse.dd.dsf.debug.service.command.CommandCache;
import org.eclipse.dd.dsf.debug.service.command.ICommandControl;
import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.command.commands.MIDataListRegisterNames;
import org.eclipse.dd.mi.service.command.commands.MIDataListRegisterValues;
import org.eclipse.dd.mi.service.command.output.MIDataListRegisterNamesInfo;
import org.eclipse.dd.mi.service.command.output.MIDataListRegisterValuesInfo;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MIRegisterValue;
import org.osgi.framework.BundleContext;
/**
*
* <p>
* Implementation note:
* This class implements event handlers for the events that are generated by
* this service itself. When the event is dispatched, these handlers will
* be called first, before any of the clients. These handlers update the
* service's internal state information to make them consistent with the
* events being issued. Doing this in the handlers as opposed to when
* the events are generated, guarantees that the state of the service will
* always be consistent with the events.
*/
public class MIRegisters extends AbstractDsfService implements IRegisters {
private static final String BLANK_STRING = ""; //$NON-NLS-1$
/*
* Support class used to construct Register Group DMCs.
*/
public static class MIRegisterGroupDMC extends AbstractDMContext implements IRegisterGroupDMContext {
private int fGroupNo;
private String fGroupName;
public MIRegisterGroupDMC(MIRegisters service, IContainerDMContext contDmc, int groupNo, String groupName) {
super(service.getSession().getId(), new IDMContext[] { contDmc });
fGroupNo = groupNo;
fGroupName = groupName;
}
public int getGroupNo() { return fGroupNo; }
public String getName() { return fGroupName; }
@Override
public boolean equals(Object other) {
return ((super.baseEquals(other)) && (((MIRegisterGroupDMC) other).fGroupNo == fGroupNo) &&
(((MIRegisterGroupDMC) other).fGroupName.equals(fGroupName)));
}
@Override
public int hashCode() { return super.baseHashCode() ^ fGroupNo; }
@Override
public String toString() { return baseToString() + ".group[" + fGroupNo + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
}
/*
* Support class used to construct Register DMCs.
*/
public static class MIRegisterDMC extends AbstractDMContext implements IRegisterDMContext {
private int fRegNo;
private String fRegName;
public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, int regNo, String regName) {
super(service.getSession().getId(),
new IDMContext[] { group });
fRegNo = regNo;
fRegName = regName;
}
public MIRegisterDMC(MIRegisters service, MIRegisterGroupDMC group, IMIExecutionDMContext execDmc, int regNo, String regName) {
super(service.getSession().getId(),
new IDMContext[] { execDmc, group });
fRegNo = regNo;
fRegName = regName;
}
public int getRegNo() { return fRegNo; }
public String getName() { return fRegName; }
@Override
public boolean equals(Object other) {
return ((super.baseEquals(other)) && (((MIRegisterDMC) other).fRegNo == fRegNo) &&
(((MIRegisterDMC) other).fRegName.equals(fRegName)));
}
@Override
public int hashCode() { return super.baseHashCode() ^ fRegNo; }
@Override
public String toString() { return baseToString() + ".register[" + fRegNo + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
}
/*
* Event class to notify register value is changed
*/
public static class RegisterChangedDMEvent implements IRegisters.IRegisterChangedDMEvent {
private final IRegisterDMContext fRegisterDmc;
RegisterChangedDMEvent(IRegisterDMContext registerDMC) {
fRegisterDmc = registerDMC;
}
public IRegisterDMContext getDMContext() {
return fRegisterDmc;
}
}
/*
* Internal control variables.
*/
private MIRegisterGroupDMC fGeneralRegistersGroupDMC;
private CommandCache fRegisterNameCache; // Cache for holding the Register Names in the single Group
private CommandCache fRegisterValueCache; // Cache for holding the Register Values
public MIRegisters(DsfSession session)
{
super(session);
}
@Override
protected BundleContext getBundleContext()
{
return MIPlugin.getBundleContext();
}
@Override
public void initialize(final RequestMonitor requestMonitor) {
super.initialize(
new RequestMonitor(getExecutor(), requestMonitor) {
@Override
protected void handleOK() {
doInitialize(requestMonitor);
}});
}
private void doInitialize(RequestMonitor requestMonitor) {
/*
* Create the lower level register cache.
*/
fRegisterValueCache = new CommandCache(getServicesTracker().getService(ICommandControl.class));
fRegisterNameCache = new CommandCache(getServicesTracker().getService(ICommandControl.class));
/*
* Signup so we see events. We use these events to decide how to manage
* any local caches we are providing as well as the lower level register
* cache we create to get/set registers on the target.
*/
getSession().addServiceEventListener(this, null);
/*
* Make ourselves known so clients can use us.
*/
register(new String[]{IRegisters.class.getName(), MIRegisters.class.getName()}, new Hashtable<String,String>());
requestMonitor.done();
}
@Override
public void shutdown(RequestMonitor requestMonitor)
{
unregister();
getSession().removeServiceEventListener(this);
super.shutdown(requestMonitor);
}
public boolean isValid() { return true; }
@SuppressWarnings("unchecked")
public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
/*
* This is the method which is called when actual results need to be returned. We
* can be called either with a service DMC for which we return oureslves or we can
* be called with the DMC's we have handed out. If the latter is the case then we
* datamine by talking to the Debug Engine.
*/
if (dmc instanceof MIRegisterGroupDMC) {
getRegisterGroupData((MIRegisterGroupDMC)dmc, (DataRequestMonitor<IRegisterGroupDMData>)rm);
} else if (dmc instanceof MIRegisterDMC) {
getRegisterData((MIRegisterDMC)dmc, (DataRequestMonitor<IRegisterDMData>)rm);
} else if (dmc instanceof FormattedValueDMContext) {
getFormattedExpressionValue((FormattedValueDMContext)dmc, (DataRequestMonitor<FormattedValueDMData>)rm);
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, -1, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
}
}
public void getFormattedExpressionValue(FormattedValueDMContext dmc, DataRequestMonitor<FormattedValueDMData> rm) {
if (dmc.getParents().length == 1 && dmc.getParents()[0] instanceof MIRegisterDMC) {
getRegisterDataValue( (MIRegisterDMC) dmc.getParents()[0], dmc.getFormatID(), rm);
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
}
}
public void getRegisterGroupData(IRegisterGroupDMContext regGroupDmc, DataRequestMonitor<IRegisterGroupDMData> rm) {
/**
* For the GDB GDBMI implementation there is only on group. The GPR and FPU registers are grouped into
* one set. We are going to hard wire this set as the "General Registers".
*/
class RegisterGroupData implements IRegisterGroupDMData {
public String getName() { return "General Registers"; } //$NON-NLS-1$
public String getDescription() { return "General Purpose and FPU Register Group"; } //$NON-NLS-1$
}
rm.setData( new RegisterGroupData() ) ;
rm.done();
}
public void getBitFieldData(IBitFieldDMContext dmc, DataRequestMonitor<IBitFieldDMData> rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Bit fields not yet supported", null)); //$NON-NLS-1$
rm.done();
}
/**
* For the GDB GDBMI implementation there is only on group. We represent
* this group as a single list we maintain within this service. So we
* need to search this list to see if we have a current value.
*/
public void getRegisterData(IRegisterDMContext regDmc , final DataRequestMonitor<IRegisterDMData> rm) {
if (regDmc instanceof MIRegisterDMC) {
final MIRegisterDMC miRegDmc = (MIRegisterDMC)regDmc;
IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(regDmc, IMIExecutionDMContext.class);
// Create register DMC with name if execution DMC is not present.
if(execDmc == null){
rm.setData(new RegisterData(miRegDmc.getName(), BLANK_STRING, false));
rm.done();
return;
}
int[] regnos = {miRegDmc.getRegNo()};
fRegisterValueCache.execute(
new MIDataListRegisterValues(execDmc, MIFormat.HEXADECIMAL, regnos),
new DataRequestMonitor<MIDataListRegisterValuesInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
// Retrieve the register value.
MIRegisterValue[] regValue = getData().getMIRegisterValues();
// If the list is empty just return empty handed.
if (regValue.length == 0) {
assert false : "Backend protocol error"; //$NON-NLS-1$
//done.setStatus(new Status(IStatus.ERROR, IDsfService.INTERNAL_ERROR ,));
rm.done();
return;
}
// We can determine if the register is floating point because
// GDB returns this additional information as part of the value.
MIRegisterValue reg = regValue[0];
boolean isFloat = false;
if ( reg.getValue().contains("float")) { //$NON-NLS-1$
isFloat = true;
}
// Return the new register attributes.
rm.setData(new RegisterData(miRegDmc.getName(), BLANK_STRING, isFloat));
rm.done();
}
});
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
}
}
private void getRegisterDataValue( final MIRegisterDMC regDmc, final String formatId, final DataRequestMonitor<FormattedValueDMData> rm) {
IMIExecutionDMContext miExecDmc = DMContexts.getAncestorOfType(regDmc, IMIExecutionDMContext.class);
if(miExecDmc == null){
// Set value to blank if execution dmc is not present
rm.setData( new FormattedValueDMData( BLANK_STRING ) );
rm.done();
return;
}
// Select the format to be shown
int NumberFormat = MIFormat.HEXADECIMAL;
if ( HEX_FORMAT.equals ( formatId ) ) { NumberFormat = MIFormat.HEXADECIMAL; }
if ( OCTAL_FORMAT.equals ( formatId ) ) { NumberFormat = MIFormat.OCTAL; }
if ( NATURAL_FORMAT.equals( formatId ) ) { NumberFormat = MIFormat.NATURAL; }
if ( BINARY_FORMAT.equals ( formatId ) ) { NumberFormat = MIFormat.BINARY; }
if ( DECIMAL_FORMAT.equals( formatId ) ) { NumberFormat = MIFormat.DECIMAL; }
int[] regnos = {regDmc.getRegNo()};
fRegisterValueCache.execute(
new MIDataListRegisterValues(miExecDmc, NumberFormat, regnos),
new DataRequestMonitor<MIDataListRegisterValuesInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
// Retrieve the register value.
MIRegisterValue[] regValue = getData().getMIRegisterValues();
// If the list is empty just return empty handed.
if (regValue.length == 0) {
assert false : "Backend protocol error"; //$NON-NLS-1$
//done.setStatus(new Status(IStatus.ERROR, IDsfService.INTERNAL_ERROR ,));
rm.done();
return;
}
MIRegisterValue reg = regValue[0];
// Return the new register value.
rm.setData( new FormattedValueDMData( reg.getValue() ) );
rm.done();
}
});
}
static class RegisterData implements IRegisterDMData {
final private String fRegName;
final private String fRegDesc;
final private boolean fIsFloat;
public RegisterData(String regName, String regDesc, boolean isFloat ) {
fRegName = regName;
fRegDesc = regDesc;
fIsFloat = isFloat;
}
public boolean isReadable() { return true; }
public boolean isReadOnce() { return false; }
public boolean isWriteable() { return true; }
public boolean isWriteOnce() { return false; }
public boolean hasSideEffects() { return false; }
public boolean isVolatile() { return true; }
public boolean isFloat() { return fIsFloat; }
public String getName() { return fRegName; }
public String getDescription() { return fRegDesc; }
}
// Wraps a list of registers in DMContexts.
private MIRegisterDMC[] makeRegisterDMCs(MIRegisterGroupDMC groupDmc, String[] regNames) {
return makeRegisterDMCs(groupDmc, null, regNames);
}
// Wraps a list of registers in DMContexts.
private MIRegisterDMC[] makeRegisterDMCs(MIRegisterGroupDMC groupDmc, IMIExecutionDMContext execDmc, String[] regNames) {
MIRegisterDMC[] regDmcList = new MIRegisterDMC[regNames.length];
int regNo = 0 ;
for (String regName : regNames) {
if(execDmc != null)
regDmcList[regNo] = new MIRegisterDMC(this, groupDmc, execDmc, regNo, regName);
else
regDmcList[regNo] = new MIRegisterDMC(this, groupDmc, regNo, regName);
regNo++;
}
return regDmcList;
}
/*
* Event handling section. These event handlers control the caching state of the
* register caches. This service creates several cache objects. Not all of which
* need to be flushed. These handlers maintain the state of the caches.
*/
@DsfServiceEventHandler public void eventDispatched(IRunControl.IResumedDMEvent e) {
fRegisterValueCache.setTargetAvailable(false);
if (e.getReason() != StateChangeReason.STEP) {
fRegisterValueCache.reset();
}
}
@DsfServiceEventHandler public void eventDispatched(
IRunControl.ISuspendedDMEvent e) {
fRegisterValueCache.setTargetAvailable(true);
fRegisterValueCache.reset();
}
@DsfServiceEventHandler
public void eventDispatched(final IRegisters.IRegisterChangedDMEvent e) {
fRegisterValueCache.reset();
}
/*
* These are the public interfaces for this service.
*
* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IRegisters#getRegisterGroups(org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext, org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
*/
public void getRegisterGroups(IDMContext ctx, DataRequestMonitor<IRegisterGroupDMContext[]> rm ) {
IContainerDMContext contDmc = DMContexts.getAncestorOfType(ctx, IContainerDMContext.class);
if (contDmc == null) {
rm.setStatus( new Status( IStatus.ERROR , MIPlugin.PLUGIN_ID , INVALID_HANDLE , "Container context not found", null ) ) ; //$NON-NLS-1$
rm.done();
return;
}
if (fGeneralRegistersGroupDMC == null) {
fGeneralRegistersGroupDMC = new MIRegisterGroupDMC( this , contDmc, 0 , "General Registers" ) ; //$NON-NLS-1$
}
MIRegisterGroupDMC[] groupDMCs = new MIRegisterGroupDMC[] { fGeneralRegistersGroupDMC };
rm.setData(groupDMCs) ;
rm.done() ;
}
/*
* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IRegisters#getRegisters(org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupDMContext, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
*/
public void getRegisters(final IDMContext dmc, final DataRequestMonitor<IRegisterDMContext[]> rm) {
final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(dmc, MIRegisterGroupDMC.class);
if ( groupDmc == null ) {
rm.setStatus( new Status( IStatus.ERROR , MIPlugin.PLUGIN_ID , INVALID_HANDLE , "RegisterGroup context not found", null ) ) ; //$NON-NLS-1$
rm.done();
return;
}
final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class);
if ( containerDmc == null ) {
rm.setStatus( new Status( IStatus.ERROR , MIPlugin.PLUGIN_ID , INVALID_HANDLE , "Container context not found" , null ) ) ; //$NON-NLS-1$
rm.done();
return;
}
// There is only one group and its number must be 0.
if ( groupDmc.getGroupNo() == 0 ) {
final IMIExecutionDMContext executionDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class);
fRegisterNameCache.execute(
new MIDataListRegisterNames(containerDmc),
new DataRequestMonitor<MIDataListRegisterNamesInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
// Retrieve the register names.
String[] regNames = getData().getRegisterNames() ;
// If the list is empty just return empty handed.
if ( regNames.length == 0 ) {
rm.done();
return;
}
// Create DMContexts for each of the register names.
if(executionDmc == null)
rm.setData(makeRegisterDMCs(groupDmc, regNames));
else
rm.setData(makeRegisterDMCs(groupDmc, executionDmc, regNames));
rm.done();
}
});
} else {
rm.setStatus(new Status(IStatus.ERROR , MIPlugin.PLUGIN_ID , INTERNAL_ERROR , "Invalid group = " + groupDmc , null)); //$NON-NLS-1$
rm.done();
}
}
/*
* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IRegisters#getBitFields(org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterDMContext, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
*/
public void getBitFields( IRegisterDMContext regDmc , DataRequestMonitor<IBitFieldDMContext[]> rm ) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "BitField not supported", null)); //$NON-NLS-1$
rm.done();
}
/*
* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IRegisters#writeRegister(org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterDMContext, java.lang.String, java.lang.String, org.eclipse.dd.dsf.concurrent.RequestMonitor)
*/
public void writeRegister(IRegisterDMContext regCtx, final String regValue, final String formatId, final RequestMonitor rm) {
MIRegisterGroupDMC grpDmc = DMContexts.getAncestorOfType(regCtx, MIRegisterGroupDMC.class);
if ( grpDmc == null ) {
rm.setStatus( new Status( IStatus.ERROR , MIPlugin.PLUGIN_ID , INVALID_HANDLE , "RegisterGroup context not found" , null ) ) ; //$NON-NLS-1$
rm.done();
return;
}
final MIRegisterDMC regDmc = (MIRegisterDMC)regCtx;
// There is only one group and its number must be 0.
if ( grpDmc.getGroupNo() == 0 ) {
final ExpressionService exprService = getServicesTracker().getService(ExpressionService.class);
String regName = regDmc.getName();
final IExpressionDMContext exprCtxt = exprService.createExpression(regCtx, "$" + regName); //$NON-NLS-1$
exprService.getModelData(exprCtxt, new DataRequestMonitor<IExpressionDMData>(getExecutor(), rm) {
@Override
protected void handleOK() {
// Evaluate the expression - request HEX since it works in every case
final FormattedValueDMContext valueDmc = exprService.getFormattedValueContext(exprCtxt, formatId);
exprService.getModelData(
valueDmc,
new DataRequestMonitor<FormattedValueDMData>(getExecutor(), null) {
@Override
protected void handleOK() {
if(! regValue.equals(getData().getFormattedValue()) || ! valueDmc.getFormatID().equals(formatId)){
exprService.writeExpression(exprCtxt, regValue, formatId, new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
generateRegisterChangedEvent(regDmc);
}
});
}//if
rm.done();
}//handleOK
}
);
}
});
}
else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Invalid group = " + grpDmc, null)); //$NON-NLS-1$
rm.done();
}
}
/*
* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IRegisters#writeBitField(org.eclipse.dd.dsf.debug.service.IRegisters.IBitFieldDMContext, java.lang.String, java.lang.String, org.eclipse.dd.dsf.concurrent.RequestMonitor)
*/
public void writeBitField(IBitFieldDMContext bitFieldCtx, String bitFieldValue, String formatId, RequestMonitor rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Writing bit field not supported", null)); //$NON-NLS-1$
rm.done();
}
/*
* (non-Javadoc)
* @see org.eclipse.dd.dsf.debug.service.IRegisters#writeBitField(org.eclipse.dd.dsf.debug.service.IRegisters.IBitFieldDMContext, org.eclipse.dd.dsf.debug.service.IRegisters.IMnemonic, org.eclipse.dd.dsf.concurrent.RequestMonitor)
*/
public void writeBitField(IBitFieldDMContext bitFieldCtx, IMnemonic mnemonic, RequestMonitor rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Writing bit field not supported", null)); //$NON-NLS-1$
rm.done();
}
public void getAvailableFormats(IFormattedDataDMContext dmc, DataRequestMonitor<String[]> rm) {
rm.setData(new String[] { HEX_FORMAT, DECIMAL_FORMAT, OCTAL_FORMAT, BINARY_FORMAT, NATURAL_FORMAT });
rm.done();
}
public FormattedValueDMContext getFormattedValueContext(IFormattedDataDMContext dmc, String formatId) {
if ( dmc instanceof MIRegisterDMC ) {
MIRegisterDMC regDmc = (MIRegisterDMC) dmc;
return( new FormattedValueDMContext( this, regDmc, formatId));
}
return null;
}
private void generateRegisterChangedEvent(IRegisterDMContext dmc ) {
getSession().dispatchEvent(new RegisterChangedDMEvent(dmc), getProperties());
}
}

View file

@ -0,0 +1,668 @@
/*******************************************************************************
* 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
* Ericsson AB - Modified for handling of multiple threads
*******************************************************************************/
package org.eclipse.dd.mi.service;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.AbstractDMContext;
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.datamodel.IDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.dsf.debug.service.command.CommandCache;
import org.eclipse.dd.dsf.debug.service.command.ICommandControl;
import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.command.commands.MIExecContinue;
import org.eclipse.dd.mi.service.command.commands.MIExecFinish;
import org.eclipse.dd.mi.service.command.commands.MIExecInterrupt;
import org.eclipse.dd.mi.service.command.commands.MIExecNext;
import org.eclipse.dd.mi.service.command.commands.MIExecStep;
import org.eclipse.dd.mi.service.command.commands.MIExecUntil;
import org.eclipse.dd.mi.service.command.commands.MIThreadListIds;
import org.eclipse.dd.mi.service.command.events.MIBreakpointHitEvent;
import org.eclipse.dd.mi.service.command.events.MIErrorEvent;
import org.eclipse.dd.mi.service.command.events.MIEvent;
import org.eclipse.dd.mi.service.command.events.MIGDBExitEvent;
import org.eclipse.dd.mi.service.command.events.MIRunningEvent;
import org.eclipse.dd.mi.service.command.events.MISharedLibEvent;
import org.eclipse.dd.mi.service.command.events.MISignalEvent;
import org.eclipse.dd.mi.service.command.events.MISteppingRangeEvent;
import org.eclipse.dd.mi.service.command.events.MIStoppedEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadCreatedEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadExitEvent;
import org.eclipse.dd.mi.service.command.events.MIWatchpointTriggerEvent;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MIThreadListIdsInfo;
import org.osgi.framework.BundleContext;
/**
*
* <p>
* Implementation note:
* This class implements event handlers for the events that are generated by
* this service itself. When the event is dispatched, these handlers will
* be called first, before any of the clients. These handlers update the
* service's internal state information to make them consistent with the
* events being issued. Doing this in the handlers as opposed to when
* the events are generated, guarantees that the state of the service will
* always be consistent with the events.
* The purpose of this pattern is to allow clients that listen to service
* events and track service state, to be perfectly in sync with the service
* state.
*/
public class MIRunControl extends AbstractDsfService implements IRunControl
{
protected class MIExecutionDMC extends AbstractDMContext
implements IMIExecutionDMContext
{
/**
* Integer ID that is used to identify the thread in the GDB/MI protocol.
*/
private final int fThreadId;
/**
* Constructor for the context. It should not be called directly by clients.
* Instead clients should call {@link MIRunControl#createMIExecutionContext(IContainerDMContext, int)}
* to create instances of this context based on the thread ID.
* <p/>
* Classes extending {@link MIRunControl} may also extend this class to include
* additional information in the context.
*
* @param sessionId Session that this context belongs to.
* @param containerDmc The container that this context belongs to.
* @param threadId GDB/MI thread identifier.
*/
protected MIExecutionDMC(String sessionId, IContainerDMContext containerDmc, int threadId) {
super(sessionId, containerDmc != null ? new IDMContext[] { containerDmc } : new IDMContext[0]);
fThreadId = threadId;
}
/**
* Returns the GDB/MI thread identifier of this context.
* @return
*/
public int getThreadId(){
return fThreadId;
}
@Override
public String toString() { return baseToString() + ".thread[" + fThreadId + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
@Override
public boolean equals(Object obj) {
return super.baseEquals(obj) && ((MIExecutionDMC)obj).fThreadId == fThreadId;
}
@Override
public int hashCode() { return super.baseHashCode() ^ fThreadId; }
}
@Immutable
private static class ExecutionData implements IExecutionDMData {
private final StateChangeReason fReason;
ExecutionData(StateChangeReason reason) {
fReason = reason;
}
public StateChangeReason getStateChangeReason() { return fReason; }
}
/**
* Base class for events generated by the MI Run Control service. Most events
* generated by the MI Run Control service are directly caused by some MI event.
* Other services may need access to the extended MI data carried in the event.
*
* @param <V> DMC that this event refers to
* @param <T> MIInfo object that is the direct cause of this event
* @see MIRunControl
*/
@Immutable
protected static class RunControlEvent<V extends IDMContext, T extends MIEvent<? extends IDMContext>> extends AbstractDMEvent<V>
implements IDMEvent<V>
{
final private T fMIInfo;
public RunControlEvent(V dmc, T miInfo) {
super(dmc);
fMIInfo = miInfo;
}
public T getMIEvent() { return fMIInfo; }
}
/**
* Indicates that the given thread has been suspended.
*/
@Immutable
protected static class SuspendedEvent extends RunControlEvent<IExecutionDMContext, MIStoppedEvent>
implements ISuspendedDMEvent
{
SuspendedEvent(IExecutionDMContext ctx, MIStoppedEvent miInfo) {
super(ctx, miInfo);
}
public StateChangeReason getReason() {
if (getMIEvent() instanceof MIBreakpointHitEvent) {
return StateChangeReason.BREAKPOINT;
} else if (getMIEvent() instanceof MISteppingRangeEvent) {
return StateChangeReason.STEP;
} else if (getMIEvent() instanceof MISharedLibEvent) {
return StateChangeReason.SHAREDLIB;
}else if (getMIEvent() instanceof MISignalEvent) {
return StateChangeReason.SIGNAL;
}else if (getMIEvent() instanceof MIWatchpointTriggerEvent) {
return StateChangeReason.WATCHPOINT;
}else if (getMIEvent() instanceof MIErrorEvent) {
return StateChangeReason.ERROR;
}else {
return StateChangeReason.USER_REQUEST;
}
}
}
@Immutable
protected static class ContainerSuspendedEvent extends SuspendedEvent
implements IContainerSuspendedDMEvent
{
final IExecutionDMContext triggeringDmc;
ContainerSuspendedEvent(IContainerDMContext containerDmc, MIStoppedEvent miInfo, IExecutionDMContext triggeringDmc) {
super(containerDmc, miInfo);
this.triggeringDmc = triggeringDmc;
}
public IExecutionDMContext getTriggeringContext() {
return triggeringDmc;
}
}
@Immutable
protected static class ResumedEvent extends RunControlEvent<IExecutionDMContext, MIRunningEvent>
implements IResumedDMEvent
{
ResumedEvent(IExecutionDMContext ctx, MIRunningEvent miInfo) {
super(ctx, miInfo);
}
public StateChangeReason getReason() {
switch(getMIEvent().getType()) {
case MIRunningEvent.CONTINUE:
return StateChangeReason.USER_REQUEST;
case MIRunningEvent.NEXT:
case MIRunningEvent.NEXTI:
return StateChangeReason.STEP;
case MIRunningEvent.STEP:
case MIRunningEvent.STEPI:
return StateChangeReason.STEP;
case MIRunningEvent.FINISH:
return StateChangeReason.STEP;
case MIRunningEvent.UNTIL:
case MIRunningEvent.RETURN:
break;
}
return StateChangeReason.UNKNOWN;
}
}
@Immutable
protected static class ContainerResumedEvent extends ResumedEvent
implements IContainerResumedDMEvent
{
final IExecutionDMContext triggeringDmc;
ContainerResumedEvent(IContainerDMContext containerDmc, MIRunningEvent miInfo, IExecutionDMContext triggeringDmc) {
super(containerDmc, miInfo);
this.triggeringDmc = triggeringDmc;
}
public IExecutionDMContext getTriggeringContext() {
return triggeringDmc;
}
}
@Immutable
protected static class StartedDMEvent extends RunControlEvent<IContainerDMContext,MIThreadCreatedEvent>
implements IStartedDMEvent{
private final IMIExecutionDMContext fExecutionDmc;
StartedDMEvent(IContainerDMContext containerDmc, IMIExecutionDMContext executionDmc, MIThreadCreatedEvent miInfo) {
super(containerDmc, miInfo);
fExecutionDmc = executionDmc;
}
public IExecutionDMContext getExecutionContext(){
return fExecutionDmc;
}
}
@Immutable
protected static class ExitedDMEvent extends RunControlEvent<IContainerDMContext,MIThreadExitEvent>
implements IExitedDMEvent{
private final IMIExecutionDMContext fExecutionDmc;
ExitedDMEvent(IContainerDMContext containerDmc, IMIExecutionDMContext executionDmc, MIThreadExitEvent miInfo) {
super(containerDmc, miInfo);
fExecutionDmc = executionDmc;
}
public IExecutionDMContext getExecutionContext(){
return fExecutionDmc;
}
}
private ICommandControl fConnection;
private CommandCache fMICommandCache;
// state flags
private boolean fSuspended = true;
private boolean fResumePending = false;
private boolean fStepping = false;
private boolean fTerminated = false;
private StateChangeReason fStateChangeReason;
private IExecutionDMContext fStateChangeTriggeringContext;
private static final int NO_THREAD_ID = 0;
public MIRunControl(DsfSession session) {
super(session);
}
@Override
public void initialize(final RequestMonitor rm) {
super.initialize(
new RequestMonitor(getExecutor(), rm) {
@Override
protected void handleOK() {
doInitialize(rm);
}});
}
private void doInitialize(final RequestMonitor rm) {
fConnection = getServicesTracker().getService(ICommandControl.class);
fMICommandCache = new CommandCache(fConnection);
getSession().addServiceEventListener(this, null);
//register(new String[]{IRunControl.class.getName(), MIRunControl.class.getName()}, new Hashtable<String,String>());
rm.done();
}
@Override
public void shutdown(final RequestMonitor rm) {
getSession().removeServiceEventListener(this);
fMICommandCache.reset();
super.shutdown(rm);
}
public boolean isValid() { return true; }
@SuppressWarnings("unchecked")
public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
if (dmc instanceof IExecutionDMContext) {
getExecutionData((IExecutionDMContext)dmc, (DataRequestMonitor<IExecutionDMData>)rm);
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
}
}
public CommandCache getCache() { return fMICommandCache; }
public IMIExecutionDMContext createMIExecutionContext(IContainerDMContext container, int threadId) {
return new MIExecutionDMC(getSession().getId(), container, threadId);
}
//
// Running event handling
//
@DsfServiceEventHandler
public void eventDispatched(final MIRunningEvent e) {
IDMEvent<?> event = null;
// Find the container context, which is used in multi-threaded debugging.
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(e.getDMContext(), IContainerDMContext.class);
if (containerDmc != null) {
// Set the triggering context only if it's different than the container context.
IExecutionDMContext triggeringCtx = !e.getDMContext().equals(containerDmc) ? e.getDMContext() : null;
event = new ContainerResumedEvent(containerDmc, e, triggeringCtx);
} else {
event = new ResumedEvent(e.getDMContext(), e);
}
getSession().dispatchEvent(event, getProperties());
}
//
// Suspended event handling
//
@DsfServiceEventHandler
public void eventDispatched(final MIStoppedEvent e) {
IDMEvent<?> event = null;
// Find the container context, which is used in multi-threaded debugging.
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(e.getDMContext(), IContainerDMContext.class);
if (containerDmc != null) {
// Set the triggering context only if it's different than the container context.
IExecutionDMContext triggeringCtx = !e.getDMContext().equals(containerDmc) ? e.getDMContext() : null;
event = new ContainerSuspendedEvent(containerDmc, e, triggeringCtx);
} else {
event = new SuspendedEvent(e.getDMContext(), e);
}
getSession().dispatchEvent(event, getProperties());
}
//
// Thread Created event handling
// When a new thread is created - OOB Event fired ~"[New Thread 1077300144 (LWP 7973)]\n"
//
@DsfServiceEventHandler
public void eventDispatched(final MIThreadCreatedEvent e) {
IContainerDMContext containerDmc = e.getDMContext();
IMIExecutionDMContext executionCtx = e.getId() != -1 ? new MIExecutionDMC(getSession().getId(), containerDmc, e.getId()) : null;
getSession().dispatchEvent(new StartedDMEvent(containerDmc, executionCtx, e), getProperties());
}
//
// Thread exit event handling
// When a new thread is destroyed - OOB Event fired "
//
@DsfServiceEventHandler
public void eventDispatched(final MIThreadExitEvent e) {
IContainerDMContext containerDmc = e.getDMContext();
IMIExecutionDMContext executionCtx = e.getId() != -1 ? new MIExecutionDMC(getSession().getId(), containerDmc, e.getId()) : null;
getSession().dispatchEvent(new ExitedDMEvent(containerDmc, executionCtx, e), getProperties());
}
@DsfServiceEventHandler
public void eventDispatched(ContainerResumedEvent e) {
fSuspended = false;
fResumePending = false;
fStateChangeReason = e.getReason();
fMICommandCache.setTargetAvailable(false);
//fStateChangeTriggeringContext = e.getTriggeringContext();
if (e.getReason().equals(StateChangeReason.STEP)) {
fStepping = true;
} else {
fMICommandCache.reset();
}
}
@DsfServiceEventHandler
public void eventDispatched(ContainerSuspendedEvent e) {
fMICommandCache.setTargetAvailable(true);
fMICommandCache.reset();
fStateChangeReason = e.getReason();
fStateChangeTriggeringContext = e.getTriggeringContext();
fSuspended = true;
fStepping = false;
}
@DsfServiceEventHandler
public void eventDispatched(MIGDBExitEvent e) {
fTerminated = true;
}
// Event handler when New thread is created
@DsfServiceEventHandler
public void eventDispatched(StartedDMEvent e) {
}
// Event handler when a thread is destroyed
@DsfServiceEventHandler
public void eventDispatched(ExitedDMEvent e) {
fMICommandCache.reset(e.getExecutionContext());
}
///////////////////////////////////////////////////////////////////////////
// AbstractService
@Override
protected BundleContext getBundleContext() {
return MIPlugin.getBundleContext();
}
///////////////////////////////////////////////////////////////////////////
// IRunControl
public boolean canResume(IExecutionDMContext context) {
return !fTerminated && isSuspended(context) && !fResumePending;
}
public boolean canSuspend(IExecutionDMContext context) {
return !fTerminated && !isSuspended(context);
}
public boolean isSuspended(IExecutionDMContext context) {
return !fTerminated && fSuspended;
}
public boolean isStepping(IExecutionDMContext context) {
return !fTerminated && fStepping;
}
public void resume(IExecutionDMContext context, final RequestMonitor rm) {
assert context != null;
if (canResume(context)) {
fResumePending = true;
// Cygwin GDB will accept commands and execute them after the step
// which is not what we want, so mark the target as unavailable
// as soon as we send a resume command.
fMICommandCache.setTargetAvailable(false);
MIExecContinue cmd = null;
if(context instanceof IContainerDMContext)
cmd = new MIExecContinue(context);
else{
IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
if (dmc == null){
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Given context: " + context + " is not an execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
cmd = new MIExecContinue(dmc);//, new String[0]);
}
fConnection.queueCommand(
cmd,
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.done();
}
}
);
}else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Given context: " + context + ", is already running.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
}
}
public void suspend(IExecutionDMContext context, final RequestMonitor rm){
assert context != null;
if (canSuspend(context)) {
MIExecInterrupt cmd = null;
if(context instanceof IContainerDMContext){
cmd = new MIExecInterrupt(context);
}
else {
IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
if (dmc == null){
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Given context: " + context + " is not an execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
cmd = new MIExecInterrupt(dmc);
}
fConnection.queueCommand(
cmd,
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.done();
}
}
);
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Given context: " + context + ", is already suspended.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
}
}
public boolean canStep(IExecutionDMContext context) {
return canResume(context);
}
public void step(IExecutionDMContext context, StepType stepType, final RequestMonitor rm) {
assert context != null;
IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
if (dmc == null){
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Given context: " + context + " is not an execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
if (!canResume(context)) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_STATE, "Cannot resume context", null)); //$NON-NLS-1$
rm.done();
return;
}
fResumePending = true;
fStepping = true;
fMICommandCache.setTargetAvailable(false);
switch(stepType) {
case STEP_INTO:
fConnection.queueCommand(
new MIExecStep(dmc, 1), new DataRequestMonitor<MIInfo>(getExecutor(), rm) {}
);
break;
case STEP_OVER:
fConnection.queueCommand(
new MIExecNext(dmc), new DataRequestMonitor<MIInfo>(getExecutor(), rm) {});
break;
case STEP_RETURN:
// The -exec-finish command operates on the selected stack frame, but here we always
// want it to operate on the stop stack frame. So we manually create a top-frame
// context to use with the MI command.
// We get a local instance of the stack service because the stack service can be shut
// down before the run control service is shut down. So it is possible for the
// getService() reqeust below to return null.
MIStack stackService = getServicesTracker().getService(MIStack.class);
if (stackService != null) {
IFrameDMContext topFrameDmc = stackService.createFrameDMContext(dmc, 0);
fConnection.queueCommand(
new MIExecFinish(topFrameDmc), new DataRequestMonitor<MIInfo>(getExecutor(), rm) {});
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Cannot create context for command, stack service not available.", null)); //$NON-NLS-1$
rm.done();
}
break;
default:
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Given step type not supported", null)); //$NON-NLS-1$
rm.done();
}
}
public boolean canInstructionStep(IExecutionDMContext context) {
return false;
}
public void instructionStep(IExecutionDMContext context, StepType stepType, RequestMonitor rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Operation not implemented", null)); //$NON-NLS-1$
rm.done();
}
public void getExecutionContexts(final IContainerDMContext containerDmc, final DataRequestMonitor<IExecutionDMContext[]> rm) {
fMICommandCache.execute(
new MIThreadListIds(containerDmc),
new DataRequestMonitor<MIThreadListIdsInfo>(
getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(makeExecutionDMCs(containerDmc, getData()));
rm.done();
}
});
}
private IExecutionDMContext[] makeExecutionDMCs(IContainerDMContext containerCtx, MIThreadListIdsInfo info) {
if (info.getThreadIds().length == 0) {
//Main thread always exist even if it is not reported by GDB.
//So create thread-id= 0 when no thread is reported
return new IMIExecutionDMContext[]{new MIExecutionDMC(getSession().getId(), containerCtx, NO_THREAD_ID)};
} else {
IExecutionDMContext[] executionDmcs = new IMIExecutionDMContext[info.getThreadIds().length];
for (int i = 0; i < info.getThreadIds().length; i++) {
executionDmcs[i] = new MIExecutionDMC(getSession().getId(), containerCtx, info.getThreadIds()[i]);
}
return executionDmcs;
}
}
public void getExecutionData(IExecutionDMContext dmc, DataRequestMonitor<IExecutionDMData> rm){
if (dmc instanceof IContainerDMContext) {
rm.setData( new ExecutionData(fStateChangeReason) );
} else if (dmc instanceof IMIExecutionDMContext) {
StateChangeReason reason = dmc.equals(fStateChangeTriggeringContext) ? fStateChangeReason : StateChangeReason.CONTAINER;
rm.setData(new ExecutionData(reason));
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Given context: " + dmc + " is not an execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
}
rm.done();
}
/*
* Run selected execution thread to a given line number.
*/
// Later add support for Address and function.
// skipBreakpoints is not used at the moment. Implement later
public void runToLine(IExecutionDMContext context, String fileName, String lineNo, boolean skipBreakpoints, final DataRequestMonitor<MIInfo> rm){
assert context != null;
IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
if (dmc == null){
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Given context: " + context + " is not an execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
if (canResume(context)) {
fResumePending = true;
fMICommandCache.setTargetAvailable(false);
fConnection.queueCommand(new MIExecUntil(dmc, fileName + ":" + lineNo), //$NON-NLS-1$
new DataRequestMonitor<MIInfo>(
getExecutor(), rm) {
@Override
protected void handleOK() {
rm.done();
}
});
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE,
"Cannot resume given DMC.", null)); //$NON-NLS-1$
rm.done();
}
}
}

View file

@ -0,0 +1,559 @@
/*******************************************************************************
* 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
* Ericsson - Modified for handling of multiple execution contexts
*******************************************************************************/
package org.eclipse.dd.mi.service;
import java.util.Hashtable;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.utils.Addr32;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.runtime.IStatus;
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.datamodel.AbstractDMContext;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IStack;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.command.commands.MIStackInfoDepth;
import org.eclipse.dd.mi.service.command.commands.MIStackListArguments;
import org.eclipse.dd.mi.service.command.commands.MIStackListFrames;
import org.eclipse.dd.mi.service.command.commands.MIStackListLocals;
import org.eclipse.dd.mi.service.command.events.MIStoppedEvent;
import org.eclipse.dd.mi.service.command.output.MIArg;
import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIStackInfoDepthInfo;
import org.eclipse.dd.mi.service.command.output.MIStackListArgumentsInfo;
import org.eclipse.dd.mi.service.command.output.MIStackListFramesInfo;
import org.eclipse.dd.mi.service.command.output.MIStackListLocalsInfo;
import org.osgi.framework.BundleContext;
public class MIStack extends AbstractDsfService
implements IStack
{
protected static class MIFrameDMC extends AbstractDMContext
implements IFrameDMContext
{
private final int fLevel;
// public MIFrameDMC(MIStack service, int level) {
public MIFrameDMC(String sessionId, IExecutionDMContext execDmc, int level) {
super(sessionId, new IDMContext[] { execDmc });
fLevel = level;
}
public int getLevel() { return fLevel; }
@Override
public boolean equals(Object other) {
return super.baseEquals(other) && ((MIFrameDMC)other).fLevel == fLevel;
}
@Override
public int hashCode() {
return super.baseHashCode() ^ fLevel;
}
@Override
public String toString() {
return baseToString() + ".frame[" + fLevel + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
}
protected static class MIVariableDMC extends AbstractDMContext
implements IVariableDMContext
{
public enum Type { ARGUMENT, LOCAL }
final private Type fType;
final private int fIndex;
public MIVariableDMC(MIStack service, IFrameDMContext frame, Type type, int index) {
super(service, new IDMContext[] { frame });
fIndex = index;
fType = type;
}
public int getIndex() { return fIndex; }
public Type getType() { return fType; }
@Override
public boolean equals(Object other) {
return super.baseEquals(other) &&
((MIVariableDMC)other).fType == fType &&
((MIVariableDMC)other).fIndex == fIndex;
}
@Override
public int hashCode() {
int typeFactor = 0;
if (fType == Type.LOCAL) typeFactor = 2;
else if (fType == Type.ARGUMENT) typeFactor = 3;
return super.baseHashCode() ^ typeFactor ^ fIndex;
}
@Override
public String toString() {
return baseToString() + ".variable(" + fType + ")[" + fIndex + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
private MIRunControl fRunControl;
private MIStoppedEvent fCachedStoppedEvent;
public MIStack(DsfSession session)
{
super(session);
}
@Override
protected BundleContext getBundleContext()
{
return MIPlugin.getBundleContext();
}
@Override
public void initialize(final RequestMonitor rm) {
super.initialize(
new RequestMonitor(getExecutor(), rm) {
@Override
protected void handleOK() {
doInitialize(rm);
}
});
}
private void doInitialize(RequestMonitor rm) {
fRunControl = getServicesTracker().getService(MIRunControl.class);
getSession().addServiceEventListener(this, null);
register(new String[]{IStack.class.getName(), MIStack.class.getName()}, new Hashtable<String,String>());
rm.done();
}
@Override
public void shutdown(RequestMonitor rm)
{
unregister();
getSession().removeServiceEventListener(this);
super.shutdown(rm);
}
@SuppressWarnings("unchecked")
public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
if (dmc instanceof MIFrameDMC) {
getFrameData((MIFrameDMC)dmc, (DataRequestMonitor<IFrameDMData>)rm);
// getFrameData invokes rm
} else if (dmc instanceof MIVariableDMC) {
getVariableData((MIVariableDMC)dmc, (DataRequestMonitor<IVariableDMData>)rm);
// getVariablesData invokes rm
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
}
}
/**
* Creates a frame context. This method is intended to be used by other MI
* services and sub-classes which need to create a frame context directly.
* <p>
* Sub-classes can override this method to provide custom stack frame
* context implementation.
* </p>
* @param execDmc Execution context that this frame is to be a child of.
* @param level Level of the new context.
* @return A new frame context.
*/
public IFrameDMContext createFrameDMContext(IExecutionDMContext execDmc, int level) {
return new MIFrameDMC(getSession().getId(), execDmc, level);
}
public boolean isStackAvailable(IDMContext context) {
IExecutionDMContext execCtx = DMContexts.getAncestorOfType(context, IExecutionDMContext.class);
return execCtx != null && (fRunControl.isSuspended(execCtx) || (fRunControl.isStepping(execCtx)));
}
public void getFrames(final IDMContext ctx, final DataRequestMonitor<IFrameDMContext[]> rm) {
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
if (execDmc == null) {
//rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, -1, "No frame context found in " + ctx, null)); //$NON-NLS-1$
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context" + ctx, null)); //$NON-NLS-1$
rm.done();
return;
}
fRunControl.getCache().execute(
new MIStackListFrames(execDmc),
new DataRequestMonitor<MIStackListFramesInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(getFrames(execDmc, getData()));
rm.done();
}
});
}
public void getTopFrame(final IDMContext ctx, final DataRequestMonitor<IFrameDMContext> rm) {
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
if (execDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context" + ctx, null)); //$NON-NLS-1$
rm.done();
return;
}
// Try to retrieve the top stack frame from the cached stopped event.
if (fCachedStoppedEvent != null &&
fCachedStoppedEvent.getFrame() != null &&
execDmc.equals(fCachedStoppedEvent.getDMContext()))
{
rm.setData(createFrameDMContext(execDmc, fCachedStoppedEvent.getFrame().getLevel()));
rm.done();
return;
}
// If stopped event is not available or doesn't contain frame info,
// query the full list of frames.
getFrames(
ctx,
new DataRequestMonitor<IFrameDMContext[]>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(getData()[0]);
rm.done();
}
});
}
//private MIFrameDMC[] getFrames(DsfMIStackListFramesInfo info) {
private IFrameDMContext[] getFrames(IMIExecutionDMContext execDmc, MIStackListFramesInfo info) {
IFrameDMContext[] frameDMCs = new MIFrameDMC[info.getMIFrames().length];
for (int i = 0; i < info.getMIFrames().length; i++) {
//frameDMCs[i] = new MIFrameDMC(this, info.getMIFrames()[i].getLevel());
frameDMCs[i] = createFrameDMContext(execDmc, info.getMIFrames()[i].getLevel());
}
return frameDMCs;
}
public void getFrameData(final IFrameDMContext frameDmc, final DataRequestMonitor<IFrameDMData> rm) {
if (!(frameDmc instanceof MIFrameDMC)) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context type " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
final MIFrameDMC miFrameDmc = (MIFrameDMC)frameDmc;
IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class);
if (execDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
/**
* Base class for the IFrameDMData object that uses an MIFrame object to
* provide the data. Sub-classes must provide the MIFrame object
*/
abstract class FrameData implements IFrameDMData
{
abstract protected MIFrame getMIFrame();
public IAddress getAddress() {
String addr = getMIFrame().getAddress();
if (addr.startsWith("0x")) { //$NON-NLS-1$
addr = addr.substring(2);
}
if (addr.length() <= 8) {
return new Addr32(getMIFrame().getAddress());
} else {
return new Addr64(getMIFrame().getAddress());
}
}
public int getColumn() { return 0; }
public String getFile() { return getMIFrame().getFile(); }
public int getLine() { return getMIFrame().getLine(); }
public String getFunction() { return getMIFrame().getFunction(); }
@Override
public String toString() { return getMIFrame().toString(); }
}
// If requested frame is the top stack frame, try to retrieve it from
// the stopped event data.
class FrameDataFromStoppedEvent extends FrameData {
private final MIStoppedEvent fEvent;
FrameDataFromStoppedEvent(MIStoppedEvent event) { fEvent = event; }
@Override
protected MIFrame getMIFrame() { return fEvent.getFrame(); }
}
// Retrieve the top stack frame from the stopped event only if the selected thread is the one on which stopped event
// is raised
if (fCachedStoppedEvent != null &&
execDmc.equals(fCachedStoppedEvent.getDMContext()) &&
miFrameDmc.fLevel == 0 &&
fCachedStoppedEvent.getFrame() != null)
{
rm.setData(new FrameDataFromStoppedEvent(fCachedStoppedEvent));
rm.done();
return;
}
// If not, retrieve the full list of frame data.
class FrameDataFromMIStackFrameListInfo extends FrameData {
private MIStackListFramesInfo fFrameDataCacheInfo;
private int fFrameIndex;
FrameDataFromMIStackFrameListInfo(MIStackListFramesInfo info, int index) {
fFrameDataCacheInfo = info;
fFrameIndex = index;
}
@Override
protected MIFrame getMIFrame() { return fFrameDataCacheInfo.getMIFrames()[fFrameIndex]; }
}
fRunControl.getCache().execute(
new MIStackListFrames(execDmc),
new DataRequestMonitor<MIStackListFramesInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
// Find the index to the correct MI frame object.
int idx = findFrameIndex(getData().getMIFrames(), miFrameDmc.fLevel);
if (idx == -1) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid frame " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
// Create the data object.
rm.setData(new FrameDataFromMIStackFrameListInfo(getData(), idx));
rm.done();
}
});
}
public void getArguments(final IFrameDMContext frameDmc, final DataRequestMonitor<IVariableDMContext[]> rm) {
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class);
if (execDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
// If requested frame is the top stack frame, try to retrieve it from
// the stopped event data.
if (frameDmc.getLevel() == 0 &&
fCachedStoppedEvent != null &&
fCachedStoppedEvent.getFrame() != null &&
execDmc.equals(fCachedStoppedEvent.getDMContext()) &&
fCachedStoppedEvent.getFrame().getArgs() != null)
{
rm.setData(makeVariableDMCs(
frameDmc, MIVariableDMC.Type.ARGUMENT, fCachedStoppedEvent.getFrame().getArgs().length));
rm.done();
return;
}
// If not, retrieve the full list of frame data.
fRunControl.getCache().execute(
new MIStackListArguments(execDmc, true),
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
// Find the index to the correct MI frame object.
// Note: this is a short-cut, but it won't work once we implement retrieving
// partial lists of stack frames.
int idx = frameDmc.getLevel();
if (idx == -1) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_STATE, "Invalid frame " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
// Create the variable array out of MIArg array.
MIArg[] args = getData().getMIFrames()[idx].getArgs();
if (args == null) args = new MIArg[0];
rm.setData(makeVariableDMCs(frameDmc, MIVariableDMC.Type.ARGUMENT, args.length));
rm.done();
}
});
}
public void getVariableData(IVariableDMContext variableDmc, final DataRequestMonitor<IVariableDMData> rm) {
if (!(variableDmc instanceof MIVariableDMC)) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context type " + variableDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
final MIVariableDMC miVariableDmc = (MIVariableDMC)variableDmc;
// Extract the frame DMC from the variable DMC.
final MIFrameDMC frameDmc = DMContexts.getAncestorOfType(variableDmc, MIFrameDMC.class);
if (frameDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "No frame context found in " + variableDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class);
if (execDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
/**
* Same as with frame objects, this is a base class for the IVariableDMData object that uses an MIArg object to
* provide the data. Sub-classes must supply the MIArg object.
*/
class VariableData implements IVariableDMData {
private MIArg dsfMIArg;
VariableData(MIArg arg){
dsfMIArg = arg;
}
public String getName() { return dsfMIArg.getName(); }
public String getValue() { return dsfMIArg.getValue(); }
@Override
public String toString() { return dsfMIArg.toString(); }
}
// Check if the stopped event can be used to extract the variable value.
if (execDmc != null && miVariableDmc.fType == MIVariableDMC.Type.ARGUMENT &&
frameDmc.fLevel == 0 && fCachedStoppedEvent != null && fCachedStoppedEvent.getFrame() != null &&
execDmc.equals(fCachedStoppedEvent.getDMContext()) &&
fCachedStoppedEvent.getFrame().getArgs() != null)
{
if (miVariableDmc.fIndex >= fCachedStoppedEvent.getFrame().getArgs().length) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, -1, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
rm.setData(new VariableData(fCachedStoppedEvent.getFrame().getArgs()[miVariableDmc.fIndex]));
rm.done();
return;
}
if (miVariableDmc.fType == MIVariableDMC.Type.ARGUMENT){
fRunControl.getCache().execute(
new MIStackListArguments(execDmc, true),
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
// Find the correct frame and argument
if ( frameDmc.fLevel >= getData().getMIFrames().length ||
miVariableDmc.fIndex >= getData().getMIFrames()[frameDmc.fLevel].getArgs().length )
{
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
// Create the data object.
rm.setData(new VariableData(getData().getMIFrames()[frameDmc.fLevel].getArgs()[miVariableDmc.fIndex]));
rm.done();
}});
}//if
if (miVariableDmc.fType == MIVariableDMC.Type.LOCAL){
fRunControl.getCache().execute(
new MIStackListLocals(frameDmc, true),
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
// Create the data object.
rm.setData(new VariableData(getData().getLocals()[miVariableDmc.fIndex]));
rm.done();
}
});
}//if
}
private MIVariableDMC[] makeVariableDMCs(IFrameDMContext frame, MIVariableDMC.Type type, int count) {
MIVariableDMC[] variables = new MIVariableDMC[count];
for (int i = 0; i < count; i++) {
variables[i]= new MIVariableDMC(this, frame, type, i);
}
return variables;
}
private int findFrameIndex(MIFrame[] frames, int level) {
for (int idx = 0; idx < frames.length; idx++) {
if (frames[idx].getLevel() == level) {
return idx;
}
}
return -1;
}
public void getLocals(final IFrameDMContext frameDmc, final DataRequestMonitor<IVariableDMContext[]> rm) {
fRunControl.getCache().execute(
new MIStackListLocals(frameDmc, true),
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(makeVariableDMCs(frameDmc, MIVariableDMC.Type.LOCAL, getData().getLocals().length));
rm.done();
}
});
}
public void getStackDepth(IDMContext dmc, final int maxDepth, final DataRequestMonitor<Integer> rm) {
IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class);
if (execDmc != null) {
MIStackInfoDepth depthCommand = null;
if (maxDepth > 0) depthCommand = new MIStackInfoDepth(execDmc, maxDepth);
else depthCommand = new MIStackInfoDepth(execDmc);
fRunControl.getCache().execute(
depthCommand,
new DataRequestMonitor<MIStackInfoDepthInfo>(getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(getData().getDepth());
rm.done();
}
});
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
rm.done();
}
}
// IServiceEventListener
@DsfServiceEventHandler public void eventDispatched(IRunControl.IResumedDMEvent e) {
if (e.getReason() != StateChangeReason.STEP) {
fCachedStoppedEvent = null;
}
}
// @DsfServiceEventHandler public void eventDispatched(MIRunControl.SuspendedEvent e) {
@DsfServiceEventHandler public void eventDispatched(MIRunControl.ContainerSuspendedEvent e) {
fCachedStoppedEvent = e.getMIEvent();
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,320 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for additional features in DSF Reference implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.command.ICommand;
import org.eclipse.dd.dsf.debug.service.command.ICommandListener;
import org.eclipse.dd.dsf.debug.service.command.ICommandResult;
import org.eclipse.dd.dsf.debug.service.command.IEventListener;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.command.commands.CLICommand;
import org.eclipse.dd.mi.service.command.commands.MIInterpreterExecConsole;
import org.eclipse.dd.mi.service.command.commands.RawCommand;
import org.eclipse.dd.mi.service.command.output.MIConsoleStreamOutput;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MILogStreamOutput;
import org.eclipse.dd.mi.service.command.output.MIOOBRecord;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
* This Process implementation tracks the process the GDB process. This
* process object is displayed in Debug view and is used to
* accept CLI commands and to write their output to the console.
*
* @see org.eclipse.debug.core.model.IProcess
*/
@ThreadSafe
public abstract class AbstractCLIProcess extends Process
implements IEventListener, ICommandListener
{
public static final String PRIMARY_PROMPT = "(gdb)"; //$NON-NLS-1$
public static final String SECONDARY_PROMPT = ">"; //$NON-NLS-1$
private final DsfSession fSession;
private final AbstractMIControl fCommandControl;
private final OutputStream fOutputStream = new CLIOutputStream();
// Client process console stream.
private final PipedInputStream fMIInConsolePipe;
private final PipedOutputStream fMIOutConsolePipe;
private final PipedInputStream fMIInLogPipe;
private final PipedOutputStream fMIOutLogPipe;
private final boolean fUseExecConsole;
private boolean fDisposed = false;
/**
* Counter for tracking console commands sent by services.
*
* Services may issue console commands when the available MI commands are
* not sufficient. However, these commands may produce console and log
* output which should not be written to the user CLI terminal.
*
* This counter is incremented any time a console command is seen which was
* not generated by this class. It is decremented whenever a service CLI
* command is finished. When counter value is 0, the CLI process writes
* the console output.
*/
private int fSuppressConsoleOutputCounter = 0;
private int fPrompt = 1; // 1 --> Primary prompt "(gdb)"; 2 --> Secondary Prompt ">"
@ConfinedToDsfExecutor("fSession#getExecutor")
public AbstractCLIProcess(AbstractMIControl commandControl, boolean useExecConsole) throws IOException {
fSession = commandControl.getSession();
fCommandControl = commandControl;
fUseExecConsole = useExecConsole;
commandControl.addEventListener(this);
commandControl.addCommandListener(this);
PipedInputStream miInConsolePipe = null;
PipedOutputStream miOutConsolePipe = null;
PipedInputStream miInLogPipe = null;
PipedOutputStream miOutLogPipe = null;
try {
miOutConsolePipe = new PipedOutputStream();
miInConsolePipe = new PipedInputStream(miOutConsolePipe);
miOutLogPipe = new PipedOutputStream();
miInLogPipe = new PipedInputStream(miOutLogPipe);
} catch (IOException e) {
ILog log = MIPlugin.getDefault().getLog();
if (log != null) {
log.log(new Status(
IStatus.ERROR, MIPlugin.PLUGIN_ID, -1, "Error when creating log pipes", e)); //$NON-NLS-1$
}
}
// Must initialize these outside of the try block because they are final.
fMIOutConsolePipe = miOutConsolePipe;
fMIInConsolePipe = miInConsolePipe;
fMIOutLogPipe = miOutLogPipe;
fMIInLogPipe = miInLogPipe;
}
protected DsfSession getSession() { return fSession; }
protected AbstractMIControl getCommandControl() { return fCommandControl; }
protected boolean isDisposed() { return fDisposed; }
@ConfinedToDsfExecutor("fSession#getExecutor")
public void dispose() {
fCommandControl.removeEventListener(this);
fCommandControl.removeCommandListener(this);
closeIO();
fDisposed = true;
}
private void closeIO() {
try {
fMIOutConsolePipe.close();
} catch (IOException e) {}
try {
fMIInConsolePipe.close();
} catch (IOException e) {}
try {
fMIOutLogPipe.close();
} catch (IOException e) {}
try {
fMIInLogPipe.close();
} catch (IOException e) {}
}
/**
* @see java.lang.Process#getErrorStream()
*/
@Override
public InputStream getErrorStream() {
return fMIInLogPipe;
}
/**
* @see java.lang.Process#getInputStream()
*/
@Override
public InputStream getInputStream() {
return fMIInConsolePipe;
}
/**
* @see java.lang.Process#getOutputStream()
*/
@Override
public OutputStream getOutputStream() {
return fOutputStream;
}
public void eventReceived(Object output) {
if (fSuppressConsoleOutputCounter > 0) return;
for (MIOOBRecord oobr : ((MIOutput)output).getMIOOBRecords()) {
if (oobr instanceof MIConsoleStreamOutput)
{
MIConsoleStreamOutput out = (MIConsoleStreamOutput) oobr;
String str = out.getString();
// Process the console stream too.
setPrompt(str);
try {
fMIOutConsolePipe.write(str.getBytes());
fMIOutConsolePipe.flush();
} catch (IOException e) {
}
} else if (oobr instanceof MILogStreamOutput) {
MILogStreamOutput out = (MILogStreamOutput) oobr;
String str = out.getString();
if (str != null) {
try {
fMIOutLogPipe.write(str.getBytes());
fMIOutLogPipe.flush();
} catch (IOException e) {
}
}
}
}
}
public void commandQueued(ICommand<? extends ICommandResult> command) {
// Ignore
}
public void commandSent(ICommand<? extends ICommandResult> command) {
// Check if the command is a CLI command and if it did not originate from this class.
if (command instanceof CLICommand<?> &&
!(command instanceof ProcessCLICommand || command instanceof ProcessMIInterpreterExecConsole))
{
fSuppressConsoleOutputCounter++;
}
}
public void commandRemoved(ICommand<? extends ICommandResult> command) {
// Ignore
}
public void commandDone(ICommand<? extends ICommandResult> command, ICommandResult result) {
if (command instanceof CLICommand<?> &&
!(command instanceof ProcessCLICommand || command instanceof ProcessMIInterpreterExecConsole))
{
fSuppressConsoleOutputCounter--;
}
}
void setPrompt(String line) {
fPrompt = 0;
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=109733
if (line == null)
return;
line = line.trim();
if (line.equals(PRIMARY_PROMPT)) {
fPrompt = 1;
} else if (line.equals(SECONDARY_PROMPT)) {
fPrompt = 2;
}
}
public boolean inPrimaryPrompt() {
return fPrompt == 1;
}
public boolean inSecondaryPrompt() {
return fPrompt == 2;
}
private class CLIOutputStream extends OutputStream {
private final StringBuffer buf = new StringBuffer();
@Override
public void write(int b) throws IOException {
buf.append((char)b);
if (b == '\n') {
// Throw away the newline.
final String bufString = buf.toString().trim();
buf.setLength(0);
try {
fSession.getExecutor().execute(new DsfRunnable() { public void run() {
try {
post(bufString);
} catch (IOException e) {
// Pipe closed.
}
}});
} catch (RejectedExecutionException e) {
// Session disposed.
}
}
}
// Encapsulate the string sent to gdb in a fake
// command and post it to the TxThread.
public void post(String str) throws IOException {
if (isDisposed()) return;
ICommand<MIInfo> cmd = null;
// 1-
// if We have the secondary prompt it means
// that GDB is waiting for more feedback, use a RawCommand
// 2-
// Do not use the interpreterexec for stepping operation
// the UI will fall out of step.
// 3-
// Normal Command Line Interface.
boolean secondary = inSecondaryPrompt();
if (secondary) {
cmd = new RawCommand(getCommandControl().getControlDMContext(), str);
}
else if (fUseExecConsole && ! CLIEventProcessor.isSteppingOperation(str))
{
cmd = new ProcessMIInterpreterExecConsole(getCommandControl().getControlDMContext(), str);
}
else {
cmd = new ProcessCLICommand(getCommandControl().getControlDMContext(), str);
}
final ICommand<MIInfo> finalCmd = cmd;
fSession.getExecutor().execute(new DsfRunnable() { public void run() {
if (isDisposed()) return;
// Do not wait around for the answer.
getCommandControl().queueCommand(finalCmd, null);
}});
}
}
private class ProcessCLICommand extends CLICommand<MIInfo> {
public ProcessCLICommand(IDMContext ctx, String oper) {
super(ctx, oper);
}
}
private class ProcessMIInterpreterExecConsole extends MIInterpreterExecConsole<MIInfo> {
public ProcessMIInterpreterExecConsole(IDMContext ctx, String cmd) {
super(ctx, cmd);
}
}
}

View file

@ -0,0 +1,736 @@
/*******************************************************************************
* 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
* Ericsson - Modified for handling of multiple stacks and threads
*******************************************************************************/
package org.eclipse.dd.mi.service.command;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.dsf.debug.service.command.ICommand;
import org.eclipse.dd.dsf.debug.service.command.ICommandControl;
import org.eclipse.dd.dsf.debug.service.command.ICommandListener;
import org.eclipse.dd.dsf.debug.service.command.ICommandResult;
import org.eclipse.dd.dsf.debug.service.command.IEventListener;
import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.commands.MICommand;
import org.eclipse.dd.mi.service.command.commands.MIStackSelectFrame;
import org.eclipse.dd.mi.service.command.commands.MIThreadSelect;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MIList;
import org.eclipse.dd.mi.service.command.output.MIOOBRecord;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIParser;
import org.eclipse.dd.mi.service.command.output.MIResult;
import org.eclipse.dd.mi.service.command.output.MIResultRecord;
import org.eclipse.dd.mi.service.command.output.MIValue;
/**
* Base implementation of an MI control service. It provides basic handling
* of input/output channels, and processing of the commands.
* <p>
* Extending classes need to implement the initialize() and shutdown() methods.
*/
public abstract class AbstractMIControl extends AbstractDsfService
implements ICommandControl
{
final static String PROP_INSTANCE_ID = MIPlugin.PLUGIN_ID + ".miControlInstanceId"; //$NON-NLS-1$
/*
* Thread control variables for the transmit and receive threads.
*/
private TxThread fTxThread;
private RxThread fRxThread;
private int fCurrentStackLevel = -1;
private int fCurrentThreadId = -1;
private final BlockingQueue<CommandHandle> fTxCommands = new LinkedBlockingQueue<CommandHandle>();
private final Map<Integer, CommandHandle> fRxCommands = Collections.synchronizedMap(new HashMap<Integer, CommandHandle>());
/*
* Various listener control variables used to keep track of listeners who want to monitor
* what the control object is doing.
*/
private final List<ICommandListener> fCommandProcessors = new ArrayList<ICommandListener>();
private final List<IEventListener> fEventProcessors = new ArrayList<IEventListener>();
/**
* Current command which have not been handed off to the backend yet.
*/
private final List<CommandHandle> fCommandQueue = new ArrayList<CommandHandle>();
/**
* Flag indicating that the command control has stopped processing commands.
*/
private boolean fStoppedCommandProcessing = false;
/*
* Public constructor.
*/
public AbstractMIControl(DsfSession session) {
super(session);
}
/**
* Starts the threads that process the debugger input/output channels.
* To be invoked by the initialization routine of the extending class.
*
* @param inStream
* @param outStream
*/
protected void startCommandProcessing(InputStream inStream, OutputStream outStream) {
fTxThread = new TxThread(outStream);
fRxThread = new RxThread(inStream);
fTxThread.start();
fRxThread.start();
}
/**
* Stops the threads that process the debugger input/output channels, and notifies the
* results of the outstanding commands. To be invoked by the shutdown routine of the
* extending class.
*
* @param inStream
* @param outStream
*/
private Status genStatus(String str) {
return new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, str, null);
}
protected void stopCommandProcessing() {
fStoppedCommandProcessing = true;
/*
* First go through the commands which have been queueud and not yet sent to the backend.
*/
for (CommandHandle commandHandle : fCommandQueue) {
if (commandHandle.getRequestMonitor() == null) continue;
commandHandle.getRequestMonitor().setStatus(genStatus("Connection is shut down")); //$NON-NLS-1$
commandHandle.getRequestMonitor().done();
}
/*
* Now go through the commands which are outstanding in that they have been sent to the backend.
*/
synchronized(fRxCommands) {
for (CommandHandle commandHandle : fRxCommands.values()) {
if (commandHandle.getRequestMonitor() == null) continue;
commandHandle.getRequestMonitor().setStatus(genStatus( "Connection is shut down")); //$NON-NLS-1$
commandHandle.getRequestMonitor().done();
}
fRxCommands.clear();
}
/*
* Now handle any requests which have not been transmitted, but weconsider them handed off.
*/
List<CommandHandle> txCommands = new ArrayList<CommandHandle>();
fTxCommands.drainTo(txCommands);
for (CommandHandle commandHandle : txCommands) {
if (commandHandle.getRequestMonitor() == null) continue;
commandHandle.getRequestMonitor().setStatus(genStatus("Connection is shut down")); //$NON-NLS-1$
commandHandle.getRequestMonitor().done();
}
}
/**
* Queues the given MI command to be sent to the debugger back end.
*
* @param command Command to be executed. This parameter must be an
* instance of DsfMICommand, otherwise a ClassCastException will be
* thrown.
* @param rm Request completion monitor
*
* @see org.eclipse.dd.dsf.debug.service.command.ICommandControl#addCommand(org.eclipse.dd.dsf.debug.service.command.ICommand, org.eclipse.dd.dsf.concurrent.RequestMonitor)
*/
public <V extends ICommandResult> void queueCommand(ICommand<V> command, DataRequestMonitor<V> rm) {
// If the command control stopped processing commands, just return an error immediately.
if (fStoppedCommandProcessing) {
rm.setStatus(genStatus("Connection is shut down")); //$NON-NLS-1$
rm.done();
return;
}
// Cast the command to MI Command type. This will cause a cast exception to be
// thrown if the client did not give an MI command as an argument.
@SuppressWarnings("unchecked")
MICommand<MIInfo> miCommand = (MICommand<MIInfo>) command;
// Cast the return token to match the result type of MI Command. This is checking
// against an erased type so it should never throw any exceptions.
@SuppressWarnings("unchecked")
DataRequestMonitor<MIInfo> miDone = (DataRequestMonitor<MIInfo>)rm;
final CommandHandle handle = new CommandHandle(miCommand, miDone);
if ( fRxCommands.size() > 3 ) {
/*
* We only allow three outstanding commands to be on the wire to the backend
* at any one time. This allows for coalesence as well as allowing for canceling
* existing commands on a state change. So we add it to the waiting list and let
* the user know they can now work with this item if need be.
*/
fCommandQueue.add(handle);
processCommandQueued(handle);
} else {
/*
* We are putting this one on the wire. We need to add it to the waiting list so
* the user has the chance to cancel it when we tell them we are acknowleding it
* has been officially accepted. They could choose to cancel it before we go and
* send it. That is why we put it into the QUEUE and then check to see if it is
* still there.
*/
fCommandQueue.add(handle);
processCommandQueued(handle);
if ( fCommandQueue.remove(handle) ) {
processCommandSent(handle);
// Before the command is sent, Check the Thread Id and send it to
// the queue only if the id has been changed.
if( handle.getThreadId()!= null &&
handle.getThreadId().intValue() != fCurrentThreadId && handle.getThreadId().intValue() != 0)
{
// Re-set the level
fCurrentThreadId = handle.getThreadId().intValue();
CommandHandle cmdHandle = new CommandHandle(
new MIThreadSelect(handle.fCommand.getContext(), fCurrentThreadId), null);
fTxCommands.add(cmdHandle);
MIPlugin.debug(MIPlugin.getDebugTime() + " " + cmdHandle.getCommand()); //$NON-NLS-1$
}
// Before the command is sent, Check the Stack level and send it to
// the queue only if the level has been changed.
if( handle.getStackFrameId()!= null &&
handle.getStackFrameId().intValue() != fCurrentStackLevel)
{
// Re-set the level
fCurrentStackLevel = handle.getStackFrameId().intValue();
CommandHandle cmdHandle = new CommandHandle(
new MIStackSelectFrame(handle.fCommand.getContext(), fCurrentStackLevel), null);
fTxCommands.add(cmdHandle);
MIPlugin.debug(MIPlugin.getDebugTime() + " " + cmdHandle.getCommand()); //$NON-NLS-1$
}
fTxCommands.add(handle);
}
}
}
/*
* This is the command which allows the user to retract a previously issued command. The
* state of the command is that it is in the waiting queue and has not yet been handed
* to the backend yet.
*
* (non-Javadoc)
* @see org.eclipse.dd.mi.service.command.IDebuggerControl#removeCommand(org.eclipse.dd.mi.service.command.commands.ICommand)
*/
public void removeCommand(ICommand<? extends ICommandResult> command) {
synchronized(fCommandQueue) {
for ( CommandHandle handle : fCommandQueue ) {
if ( handle.getCommand().equals(command)) {
fCommandQueue.remove(handle);
final CommandHandle finalHandle = handle;
getExecutor().execute(new DsfRunnable() {
public void run() {
processCommandRemoved(finalHandle);
}
});
break;
}
}
}
}
/*
* This command allows the user to try and cancel commands which have been handed off to the
* backend. Some backends support this with extended GDB/MI commands. If the support is there
* then we will attempt it. Because of the bidirectional nature of the GDB/MI command stream
* there is no guarantee that this will work. The response to the command could be on its way
* back when the cancel command is being issued.
*
* (non-Javadoc)
* @see org.eclipse.dd.mi.service.command.IDebuggerControl#cancelCommand(org.eclipse.dd.mi.service.command.commands.ICommand)
*/
public void cancelCommand(ICommand<? extends ICommandResult> command) {}
/*
* Allows a user ( typically a cache manager ) to sign up a listener to monitor command queue
* activity.
*
* (non-Javadoc)
* @see org.eclipse.dd.mi.service.command.IDebuggerControl#addCommandListener(org.eclipse.dd.mi.service.command.IDebuggerControl.ICommandListener)
*/
public void addCommandListener(ICommandListener processor) { fCommandProcessors.add(processor); }
/*
* Allows a user ( typically a cache manager ) to remove a monitoring listener.
* (non-Javadoc)
* @see org.eclipse.dd.mi.service.command.IDebuggerControl#removeCommandListener(org.eclipse.dd.mi.service.command.IDebuggerControl.ICommandListener)
*/
public void removeCommandListener(ICommandListener processor) { fCommandProcessors.remove(processor); }
/*
* Allows a user to sign up to a listener which handles out of band messages ( events ).
*
* (non-Javadoc)
* @see org.eclipse.dd.mi.service.command.IDebuggerControl#addEventListener(org.eclipse.dd.mi.service.command.IDebuggerControl.IEventListener)
*/
public void addEventListener(IEventListener processor) { fEventProcessors.add(processor); }
/*
* Allows a user to remove a event monitoring listener.
*
* (non-Javadoc)
* @see org.eclipse.dd.mi.service.command.IDebuggerControl#removeEventListener(org.eclipse.dd.mi.service.command.IDebuggerControl.IEventListener)
*/
public void removeEventListener(IEventListener processor) { fEventProcessors.remove(processor); }
abstract public MIControlDMContext getControlDMContext();
/*
* These are the service routines which perform the various callouts back to the listeners.
*/
private void processCommandQueued(CommandHandle commandHandle) {
for (ICommandListener processor : fCommandProcessors) {
processor.commandQueued(commandHandle.getCommand());
}
}
private void processCommandRemoved(CommandHandle commandHandle) {
for (ICommandListener processor : fCommandProcessors) {
processor.commandRemoved(commandHandle.getCommand());
}
}
private void processCommandSent(CommandHandle commandHandle) {
MIPlugin.debug(MIPlugin.getDebugTime() + " " + commandHandle.getToken() + commandHandle.getCommand()); //$NON-NLS-1$
for (ICommandListener processor : fCommandProcessors) {
processor.commandSent(commandHandle.getCommand());
}
}
private void processCommandDone(CommandHandle commandHandle, ICommandResult result) {
/*
* Provide tracking for out processing.
*/
if ( result != null ) {
MIInfo cmdResult = (MIInfo) result ;
MIOutput output = cmdResult.getMIOutput();
MIPlugin.debug(MIPlugin.getDebugTime() + " " + output + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
}
else
{
MIPlugin.debug(MIPlugin.getDebugTime() + " result output not available\n"); //$NON-NLS-1$
}
/*
* Tell the listeners we have completed this one.
*/
for (ICommandListener processor : fCommandProcessors) {
processor.commandDone(commandHandle == null ? null : commandHandle.getCommand(), result);
}
}
private void processEvent(MIOutput output) {
MIPlugin.debug(MIPlugin.getDebugTime() + " " + output + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
for (IEventListener processor : fEventProcessors) {
processor.eventReceived(output);
}
}
/*
* A global counter for all command, the token will be use to identify uniquely a command.
* Unless the value wraps around which is unlikely.
*/
private static int globalCounter = 0 ;
private static synchronized int getUniqToken() {
int count = ++globalCounter;
// If we ever wrap around.
if (count <= 0) {
count = globalCounter = 1;
}
return count;
}
/*
* Support class which creates a convenient wrapper for holding all information about an
* individual request.
*/
public static class CommandHandle {
private MICommand<MIInfo> fCommand;
private DataRequestMonitor<MIInfo> fRequestMonitor;
private int fTokenId ;
CommandHandle(MICommand<MIInfo> c, DataRequestMonitor<MIInfo> d) {
fCommand = c;
fRequestMonitor = d;
fTokenId = getUniqToken() ;
}
public MICommand<MIInfo> getCommand() { return fCommand; }
public DataRequestMonitor<MIInfo> getRequestMonitor() { return fRequestMonitor; }
public Integer getToken() { return fTokenId; }
//public String getThreadId() { return null; }
public Integer getStackFrameId() {
IFrameDMContext frameCtx = DMContexts.getAncestorOfType(fCommand.getContext(), IFrameDMContext.class);
if(frameCtx != null)
return frameCtx.getLevel();
return null;
}
public Integer getThreadId() {
IMIExecutionDMContext execCtx = DMContexts.getAncestorOfType(fCommand.getContext(), IMIExecutionDMContext.class);
if(execCtx != null)
return execCtx.getThreadId();
return null;
}
}
/*
* This is the transmitter thread. When a command is given to this thread it has been
* considered to be sent, even if it has not actually been sent yet. This assumption
* makes it easier from state management. Whomever fill this pipeline handles all of
* the required state notofication ( callbacks ). This thread simply physically gives
* the message to the backend.
*/
private class TxThread extends Thread {
final private OutputStream fOutputStream;
public TxThread(OutputStream outStream) {
super("MI TX Thread"); //$NON-NLS-1$
fOutputStream = outStream;
}
@Override
public void run () {
while (true) {
CommandHandle commandHandle = null;
/*
* Note: Acquiring locks for both fRxCommands and fTxCommands collections.
*/
synchronized(fTxCommands) {
try {
commandHandle = fTxCommands.take();
} catch (InterruptedException e) {
break; // Shutting down.
}
if (commandHandle == null) {
break; // Null command is an indicator that we're shutting down.
}
/*
* We note that this is an outstanding request at this point.
*/
fRxCommands.put(commandHandle.getToken(), commandHandle);
}
/*
* Construct the new command and push this command out the pipeline.
*/
String str = commandHandle.getToken() + commandHandle.getCommand().constructCommand();
try {
if (fOutputStream != null) {
fOutputStream.write(str.getBytes());
fOutputStream.flush();
}
} catch (IOException e) {
// Shutdown thread in case of IO error.
break;
}
}
}
}
private class RxThread extends Thread {
private final InputStream fInputStream;
private final MIParser fMiParser = new MIParser();
/**
* List of out of band records since the last result record. Out of band records are
* required for processing the results of CLI commands.
*/
private final List<MIOOBRecord> fAccumulatedOOBRecords = new ArrayList<MIOOBRecord>();
public RxThread(InputStream inputStream) {
super("MI RX Thread"); //$NON-NLS-1$
fInputStream = inputStream;
}
@Override
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(fInputStream));
try {
String line;
while ((line = reader.readLine()) != null) {
if (line.length() != 0) {
processMIOutput(line);
}
}
} catch (IOException e) {
// Socket is shut down.
} catch (RejectedExecutionException e) {
// Dispatch thread is down.
}
}
private MIResult findResultRecord(MIResult[] results, String variable) {
for (int i = 0; i < results.length; i++) {
if (variable.equals(results[i].getVariable())) {
return results[i];
}
}
return null;
}
private String getStatusString(MICommand<MIInfo> origCommand, MIOutput response ) {
// Attempt to extract a message from the result record:
String message = null;
String[] parameters = null;
if (response != null && response.getMIResultRecord() != null) {
MIResult[] results = response.getMIResultRecord().getMIResults();
// Extract the parameters
MIResult paramsRes = findResultRecord(results, "parameters"); //$NON-NLS-1$
if (paramsRes != null && paramsRes.getMIValue() instanceof MIList) {
MIValue[] paramValues = ((MIList)paramsRes.getMIValue()).getMIValues();
parameters = new String[paramValues.length];
for (int i = 0; i < paramValues.length; i++) {
if (paramValues[i] instanceof MIConst) {
parameters[i] = ((MIConst)paramValues[i]).getString();
} else {
parameters[i] = ""; //$NON-NLS-1$
}
}
}
MIResult messageRes = findResultRecord(results, "message"); //$NON-NLS-1$
if (messageRes != null && messageRes.getMIValue() instanceof MIConst) {
message = ((MIConst)messageRes.getMIValue()).getString();
}
// FRCH: I believe that the actual string is "msg" ...
// FRCH: (at least for the version of gdb I'm using)
else {
messageRes = findResultRecord(results, "msg"); //$NON-NLS-1$
if (messageRes != null && messageRes.getMIValue() instanceof MIConst) {
message = ((MIConst)messageRes.getMIValue()).getString();
}
}
}
StringBuilder clientMsg = new StringBuilder();
clientMsg.append("Failed to execute MI command:\n"); //$NON-NLS-1$
clientMsg.append(origCommand.toString());
if (message != null) {
clientMsg.append("Error message from debugger back end:\n"); //$NON-NLS-1$
if (parameters != null) {
try {
clientMsg.append(MessageFormat.format(message, (Object[])parameters));
} catch(IllegalArgumentException e2) {
// Message format string invalid. Fallback to just appending the strings.
clientMsg.append(message);
clientMsg.append(parameters);
}
} else {
clientMsg.append(message);
}
}
return clientMsg.toString();
}
void processMIOutput(String line) {
MIParser.RecordType recordType = fMiParser.getRecordType(line);
if (recordType == MIParser.RecordType.ResultRecord) {
final MIResultRecord rr = fMiParser.parseMIResultRecord(line);
final MIOutput response = new MIOutput(rr,
fAccumulatedOOBRecords.toArray(new MIOOBRecord[fAccumulatedOOBRecords.size()]) );
fAccumulatedOOBRecords.clear();
/*
* Find the command in the current output list. If we cannot then this is
* some form of asynchronous notification. Or perhaps general IO.
*/
int id = rr.getToken();
final CommandHandle commandHandle = fRxCommands.remove(id);
if (commandHandle != null) {
MIInfo result = commandHandle.getCommand().getResult(response);
DataRequestMonitor<MIInfo> rm = commandHandle.getRequestMonitor();
/*
* Not all users want to get there results. They indicate so by not having
* a completion object.
*/
if ( rm != null ) {
rm.setData(result);
/*
* We need to indicate if this request had an error or not.
*/
String errorResult = rr.getResultClass();
if ( errorResult.equals(MIResultRecord.ERROR) ) {
String status = getStatusString(commandHandle.getCommand(),response);
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.REQUEST_FAILED, status, null));
}
/*
* We need to complete the command on the DSF thread for data security.
*/
final ICommandResult finalResult = result;
getExecutor().execute(new DsfRunnable() {
public void run() {
/*
* Complete the specific command.
*/
if (commandHandle.getRequestMonitor() != null) {
commandHandle.getRequestMonitor().done();
}
/*
* Now tell the generic listeners about it.
*/
processCommandDone(commandHandle, finalResult);
}
@Override
public String toString() {
return "MI command output received for: " + commandHandle.getCommand(); //$NON-NLS-1$
}
});
} else {
/*
* While the specific requestor did not care about the completion we
* need to call any listeners. This could have been a CLI command for
* example and the CommandDone listeners there handle the IO as part
* of the work.
*/
final ICommandResult finalResult = result;
getExecutor().execute(new DsfRunnable() {
public void run() {
processCommandDone(commandHandle, finalResult);
}
@Override
public String toString() {
return "MI command output received for: " + commandHandle.getCommand(); //$NON-NLS-1$
}
});
}
} else {
/*
* GDB apparently can sometimes send multiple responses to the same command. In those cases,
* the command handle is gone, so post the result as an event. Again this must be done on the
* DSF thread for integrity.
*/
getExecutor().execute(new DsfRunnable() {
public void run() {
processEvent(response);
}
@Override
public String toString() {
return "MI asynchronous output received: " + response; //$NON-NLS-1$
}
});
}
//} else {
} else if (recordType == MIParser.RecordType.OOBRecord) {
// Process OOBs
final MIOOBRecord oob = fMiParser.parseMIOOBRecord(line);
fAccumulatedOOBRecords.add(oob);
final MIOutput response = new MIOutput(oob);
/*
* OOBS are events. So we pass them to any event listeners who want to see them. Again this must
* be done on the DSF thread for integrity.
*/
getExecutor().execute(new DsfRunnable() {
public void run() {
processEvent(response);
}
@Override
public String toString() {
return "MI asynchronous output received: " + response; //$NON-NLS-1$
}
});
}
getExecutor().execute(new DsfRunnable() {
public void run() {
if ( fCommandQueue.size() > 0 ) {
CommandHandle comHandle = fCommandQueue.remove(0);
if ( comHandle != null ) {
processCommandQueued(comHandle);
processCommandSent(comHandle);
fTxCommands.add(comHandle);
}
}
}
});
}
}
public void resetCurrentThreadLevel(){
fCurrentThreadId = -1;
}
}

View file

@ -0,0 +1,353 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson AB - Additional handling of events
*******************************************************************************/
package org.eclipse.dd.mi.service.command;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.ISignals.ISignalsDMContext;
import org.eclipse.dd.dsf.debug.service.command.ICommand;
import org.eclipse.dd.dsf.debug.service.command.ICommandListener;
import org.eclipse.dd.dsf.debug.service.command.ICommandResult;
import org.eclipse.dd.dsf.debug.service.command.IEventListener;
import org.eclipse.dd.mi.service.command.commands.CLICommand;
import org.eclipse.dd.mi.service.command.commands.MIInterpreterExecConsole;
import org.eclipse.dd.mi.service.command.events.MIBreakpointChangedEvent;
import org.eclipse.dd.mi.service.command.events.MIDetachedEvent;
import org.eclipse.dd.mi.service.command.events.MIErrorEvent;
import org.eclipse.dd.mi.service.command.events.MIEvent;
import org.eclipse.dd.mi.service.command.events.MIRunningEvent;
import org.eclipse.dd.mi.service.command.events.MISignalChangedEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadCreatedEvent;
import org.eclipse.dd.mi.service.command.output.MIConsoleStreamOutput;
import org.eclipse.dd.mi.service.command.output.MIOOBRecord;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIResultRecord;
/**
* GDB debugger output listener.
*/
@ConfinedToDsfExecutor("fConnection#getExecutor")
public class CLIEventProcessor
implements ICommandListener, IEventListener
{
private final AbstractMIControl fCommandControl;
private final MIInferiorProcess fInferior;
private final IContainerDMContext fContainerDmc;
private final List<Object> fEventList = new LinkedList<Object>();
// Last Thread ID created
private static int fLastThreadId;
public CLIEventProcessor(AbstractMIControl connection, IContainerDMContext containerDmc, MIInferiorProcess inferior) {
fCommandControl = connection;
fInferior = inferior;
fContainerDmc = containerDmc;
connection.addCommandListener(this);
connection.addEventListener(this);
// Re-set the counter
fLastThreadId = 0;
}
public void dispose() {
fCommandControl.removeCommandListener(this);
fCommandControl.removeEventListener(this);
}
public void commandSent(ICommand<? extends ICommandResult> command) {
if (command instanceof CLICommand<?>) {
processStateChanges( (CLICommand<?>)command );
}
else if (command instanceof MIInterpreterExecConsole<?>) {
processStateChanges( (MIInterpreterExecConsole<?>)command );
}
}
public void commandDone(ICommand<? extends ICommandResult> command, ICommandResult result) {
if (command instanceof CLICommand<?>) {
processSettingChanges( (CLICommand<?>)command );
}
else if (command instanceof MIInterpreterExecConsole<?>) {
processSettingChanges( (MIInterpreterExecConsole<?>)command );
}
fEventList.clear();
}
public void commandQueued(ICommand<? extends ICommandResult> command) {
// No action
}
public void commandRemoved(ICommand<? extends ICommandResult> command) {
// No action
}
public void eventReceived(Object output) {
for (MIOOBRecord oobr : ((MIOutput)output).getMIOOBRecords()) {
fEventList.add(oobr);
if (oobr instanceof MIConsoleStreamOutput) {
// Process Events of type DsfMIConsoleStreamOutput here
MIConsoleStreamOutput exec = (MIConsoleStreamOutput) oobr;
// Look for events with Pattern ^[New Thread 1077300144 (LWP 7973)
Pattern pattern = Pattern.compile("(^\\[New Thread.*LWP\\s*)(\\d*)", Pattern.MULTILINE); //$NON-NLS-1$
Matcher matcher = pattern.matcher(exec.getCString());
if (matcher.find()) {
//fMapThreadIds.put(matcher.group(2), Integer.valueOf(++fLastThreadId));
//DsfMIEvent e = new DsfMIThreadCreatedEvent(Integer.valueOf(matcher.group(2)));
MIEvent<?> e = new MIThreadCreatedEvent(fContainerDmc, ++fLastThreadId);
// Dispatch DsfMIThreadCreatedEvent
fCommandControl.getSession().dispatchEvent(e, fCommandControl.getProperties());
}
// HACK - For GDB thread exit events, we won't use the events generated by GDB. This event is
// raised in GDBRunControl class by polling and comparing the ExecutionContexts returned by
// -thread-list-ids command. This is done as threads reported by exit event are still reported till
// they completely exit the system.
// Look for Thread Exited Event with Pattern [Thread 1077300144 (LWP 23832) exited]\n
// See bug 200615 for details.
// pattern = Pattern.compile("(^\\[Thread.*LWP\\s)(\\d*)(.*exited.*$)", Pattern.MULTILINE); //$NON-NLS-1$
// matcher = pattern.matcher(exec.getCString());
// if (matcher.find()) {
// DsfMIEvent e = new DsfMIThreadExitEvent(fMapThreadIds.get(matcher.group(2)).intValue());
// // Dispatch DsfMIThreadExitEvent
// fConnection.getSession().dispatchEvent(e, fConnection.getProperties());
// }
}
}
// GDB can send an error result following sending an OK result.
// In this case the error is routed as an event.
MIResultRecord rr = ((MIOutput)output).getMIResultRecord();
if (rr != null) {
// Check if the state changed.
String state = rr.getResultClass();
if (fInferior != null && "error".equals(state)) { //$NON-NLS-1$
if (fInferior.getState() == MIInferiorProcess.State.RUNNING) {
fInferior.setState(MIInferiorProcess.State.RUNNING);
fCommandControl.getSession().dispatchEvent(
MIErrorEvent.parse(fContainerDmc, rr.getToken(), rr.getMIResults(), null),
fCommandControl.getProperties());
}
}
}
}
private void processStateChanges(CLICommand<? extends ICommandResult> cmd) {
String operation = cmd.getOperation().trim();
// In refactoring we are no longer genwerating the token id as
// part of the command. It is passed here and stored away and
// then never really used. So it has just been changed to 0.
processStateChanges(0, operation);
}
private void processStateChanges(MIInterpreterExecConsole<? extends ICommandResult> exec) {
String[] operations = exec.getParameters();
if (operations != null && operations.length > 0) {
// In refactoring we are no longer genwerating the token id as
// part of the command. It is passed here and stored away and
// then never really used. So it has just been changed to 0.
processStateChanges(0, operations[0]);
}
}
private void processStateChanges(int token, String operation) {
// Get the command name.
int indx = operation.indexOf(' ');
if (indx != -1) {
operation = operation.substring(0, indx).trim();
} else {
operation = operation.trim();
}
// Check the type of command
int type = getSteppingOperationKind(operation);
if (type != -1) {
// if it was a step instruction set state running
MIEvent<?> event = new MIRunningEvent(fContainerDmc, token, type);
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
}
/**
* An attempt to discover the command type and
* fire an event if necessary.
*/
private void processSettingChanges(CLICommand<?> cmd) {
String operation = cmd.getOperation().trim();
// In refactoring we are no longer genwerating the token id as
// part of the command. It is passed here and stored away and
// then never really used. So it has just been changed to 0.
processSettingChanges(cmd.getContext(), 0, operation);
}
private void processSettingChanges(MIInterpreterExecConsole<?> exec) {
String[] operations = exec.getParameters();
if (operations != null && operations.length > 0) {
// In refactoring we are no longer genwerating the token id as
// part of the command. It is passed here and stored away and
// then never really used. So it has just been changed to 0.
processSettingChanges(exec.getContext(), 0, operations[0]);
}
}
private void processSettingChanges(IDMContext dmc, int token, String operation) {
// Get the command name.
int indx = operation.indexOf(' ');
if (indx != -1) {
operation = operation.substring(0, indx).trim();
} else {
operation = operation.trim();
}
// Check the type of command
if (isSettingBreakpoint(operation) ||
isSettingWatchpoint(operation) ||
isChangeBreakpoint(operation) ||
isDeletingBreakpoint(operation))
{
// We know something change, we just do not know what.
// So the easiest way is to let the top layer handle it.
MIEvent<?> event = new MIBreakpointChangedEvent(
DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class), 0);
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
} else if (isSettingSignal(operation)) {
// We do no know which signal let the upper layer find it.
MIEvent<?> event = new MISignalChangedEvent(
DMContexts.getAncestorOfType(dmc, ISignalsDMContext.class), ""); //$NON-NLS-1$
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
} else if (isDetach(operation)) {
// if it was a "detach" command change the state.
MIEvent<?> event = new MIDetachedEvent(DMContexts.getAncestorOfType(dmc, MIControlDMContext.class), token);
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
}
private static int getSteppingOperationKind(String operation) {
int type = -1;
/* execution commands: n, next, s, step, si, stepi, u, until, finish,
c, continue, fg */
if (operation.equals("n") || operation.equals("next")) { //$NON-NLS-1$ //$NON-NLS-2$
type = MIRunningEvent.NEXT;
} else if (operation.equals("ni") || operation.equals("nexti")) { //$NON-NLS-1$ //$NON-NLS-2$
type = MIRunningEvent.NEXTI;
} else if (operation.equals("s") || operation.equals("step")) { //$NON-NLS-1$ //$NON-NLS-2$
type = MIRunningEvent.STEP;
} else if (operation.equals("si") || operation.equals("stepi")) { //$NON-NLS-1$ //$NON-NLS-2$
type = MIRunningEvent.STEPI;
} else if (operation.equals("u") || //$NON-NLS-1$
(operation.startsWith("unt") && "until".indexOf(operation) != -1)) { //$NON-NLS-1$ //$NON-NLS-2$
type = MIRunningEvent.UNTIL;
} else if (operation.startsWith("fin") && "finish".indexOf(operation) != -1) { //$NON-NLS-1$ //$NON-NLS-2$
type = MIRunningEvent.FINISH;
} else if (operation.equals("c") || operation.equals("fg") || //$NON-NLS-1$ //$NON-NLS-2$
(operation.startsWith("cont") && "continue".indexOf(operation) != -1)) { //$NON-NLS-1$ //$NON-NLS-2$
type = MIRunningEvent.CONTINUE;
} else if (operation.startsWith("sig") && "signal".indexOf(operation) != -1) { //$NON-NLS-1$ //$NON-NLS-2$
type = MIRunningEvent.CONTINUE;
} else if (operation.startsWith("j") && "jump".indexOf(operation) != -1) { //$NON-NLS-1$ //$NON-NLS-2$
type = MIRunningEvent.CONTINUE;
} else if (operation.equals("r") || operation.equals("run")) { //$NON-NLS-1$ //$NON-NLS-2$
type = MIRunningEvent.CONTINUE;
}
return type;
}
/**
* Return true if the operation is a stepping operation.
*
* @param operation
* @return
*/
public static boolean isSteppingOperation(String operation) {
int type = getSteppingOperationKind(operation);
return type != -1;
}
private boolean isSettingBreakpoint(String operation) {
boolean isbreak = false;
/* breakpoints: b, break, hbreak, tbreak, rbreak, thbreak */
/* watchpoints: watch, rwatch, awatch, tbreak, rbreak, thbreak */
if ((operation.startsWith("b") && "break".indexOf(operation) != -1) || //$NON-NLS-1$ //$NON-NLS-2$
(operation.startsWith("tb") && "tbreak".indexOf(operation) != -1) || //$NON-NLS-1$ //$NON-NLS-2$
(operation.startsWith("hb") && "hbreak".indexOf(operation) != -1) || //$NON-NLS-1$ //$NON-NLS-2$
(operation.startsWith("thb") && "thbreak".indexOf(operation) != -1) || //$NON-NLS-1$ //$NON-NLS-2$
(operation.startsWith("rb") && "rbreak".indexOf(operation) != -1)) { //$NON-NLS-1$ //$NON-NLS-2$
isbreak = true;
}
return isbreak;
}
private boolean isSettingWatchpoint(String operation) {
boolean isWatch = false;
/* watchpoints: watch, rwatch, awatch, tbreak, rbreak, thbreak */
if ((operation.startsWith("wa") && "watch".indexOf(operation) != -1) || //$NON-NLS-1$ //$NON-NLS-2$
(operation.startsWith("rw") && "rwatch".indexOf(operation) != -1) || //$NON-NLS-1$ //$NON-NLS-2$
(operation.startsWith("aw") && "awatch".indexOf(operation) != -1)) { //$NON-NLS-1$ //$NON-NLS-2$
isWatch = true;
}
return isWatch;
}
private boolean isDeletingBreakpoint(String operation) {
boolean isDelete = false;
/* deleting breaks: clear, delete */
if ((operation.startsWith("cl") && "clear".indexOf(operation) != -1) || //$NON-NLS-1$ //$NON-NLS-2$
(operation.equals("d") || (operation.startsWith("del") && "delete".indexOf(operation) != -1))) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
isDelete = true;
}
return isDelete;
}
private boolean isChangeBreakpoint(String operation) {
boolean isChange = false;
/* changing breaks: enable, disable */
if ((operation.equals("dis") || operation.equals("disa") || //$NON-NLS-1$ //$NON-NLS-2$
(operation.startsWith("disa") && "disable".indexOf(operation) != -1)) || //$NON-NLS-1$ //$NON-NLS-2$
(operation.equals("en") || (operation.startsWith("en") && "enable".indexOf(operation) != -1)) || //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
(operation.startsWith("ig") && "ignore".indexOf(operation) != -1) || //$NON-NLS-1$ //$NON-NLS-2$
(operation.startsWith("cond") && "condition".indexOf(operation) != -1)) { //$NON-NLS-1$ //$NON-NLS-2$
isChange = true;
}
return isChange;
}
private boolean isSettingSignal(String operation) {
boolean isChange = false;
/* changing signal: handle, signal */
if (operation.startsWith("ha") && "handle".indexOf(operation) != -1) { //$NON-NLS-1$ //$NON-NLS-2$
isChange = true;
}
return isChange;
}
/**
* @param operation
* @return
*/
private boolean isDetach(String operation) {
return (operation.startsWith("det") && "detach".indexOf(operation) != -1); //$NON-NLS-1$ //$NON-NLS-2$
}
}

View file

@ -0,0 +1,62 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service.command;
import org.eclipse.dd.dsf.datamodel.AbstractDMContext;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.command.ICommandControl;
import org.eclipse.dd.dsf.service.IDsfService;
import org.osgi.framework.Constants;
/**
*
*/
public class MIControlDMContext extends AbstractDMContext {
private final String fCommandControlFilter;
private final String fCommandControlId;
public MIControlDMContext(String sessionId, String commandControlId) {
this(sessionId, DMContexts.EMPTY_CONTEXTS_ARRAY, commandControlId);
}
public MIControlDMContext(String sessionId, IDMContext[] parents, String commandControlId) {
super(sessionId, parents);
fCommandControlId = commandControlId;
fCommandControlFilter =
"(&" + //$NON-NLS-1$
"(" + Constants.OBJECTCLASS + "=" + ICommandControl.class.getName() + ")" + //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
"(" + IDsfService.PROP_SESSION_ID + "=" + sessionId + ")" + //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
"(" + AbstractMIControl.PROP_INSTANCE_ID + "=" + commandControlId + ")" + //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
")"; //$NON-NLS-1$
}
public String getCommandControlFilter() {
return fCommandControlFilter;
}
@Override
public boolean equals(Object obj) {
return baseEquals(obj) && fCommandControlFilter.equals(((MIControlDMContext)obj).fCommandControlFilter);
}
@Override
public int hashCode() {
return baseHashCode() + fCommandControlFilter.hashCode();
}
@Override
public String toString() {
return baseToString() + ".control(" + fCommandControlId + ")"; //$NON-NLS-1$//$NON-NLS-2$*/
}
}

View file

@ -0,0 +1,396 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Hewlett-Packard Development Company - fix for bug 109733
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.utils.pty.PTY;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.concurrent.ImmediateExecutor;
import org.eclipse.dd.dsf.concurrent.Query;
import org.eclipse.dd.dsf.debug.service.command.ICommand;
import org.eclipse.dd.dsf.debug.service.command.ICommandListener;
import org.eclipse.dd.dsf.debug.service.command.ICommandResult;
import org.eclipse.dd.dsf.debug.service.command.IEventListener;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.command.commands.CLIExecAbort;
import org.eclipse.dd.mi.service.command.commands.MIGDBShowExitCode;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIExecAsyncOutput;
import org.eclipse.dd.mi.service.command.output.MIGDBShowExitCodeInfo;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MIOOBRecord;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIResult;
import org.eclipse.dd.mi.service.command.output.MIResultRecord;
import org.eclipse.dd.mi.service.command.output.MITargetStreamOutput;
import org.eclipse.dd.mi.service.command.output.MIValue;
/**
* This Process implementation tracks the process that is being debugged
* by GDB. The process object is displayed in Debug view and is used to
* channel the STDIO of the interior process to the console view.
*
* @see org.eclipse.debug.core.model.IProcess
*/
public class MIInferiorProcess extends Process
implements IEventListener, ICommandListener
{
public enum State { RUNNING, STOPPED, TERMINATED }
private final OutputStream fOutputStream;
private final InputStream fInputStream;
private final PipedOutputStream fInputStreamPiped;
private final PipedInputStream fErrorStream;
private final PipedOutputStream fErrorStreamPiped;
private final DsfSession fSession;
private final PTY fPty;
private final AbstractMIControl fCommandControl;
@ConfinedToDsfExecutor("fSession#getExecutor")
private boolean fDisposed = false;
Integer fExitCode = null;
private State fState = State.RUNNING;
int inferiorPID;
@ConfinedToDsfExecutor("fSession#getExecutor")
public MIInferiorProcess(AbstractMIControl commandControl, OutputStream gdbOutputStream) {
this(commandControl, gdbOutputStream, null);
}
@ConfinedToDsfExecutor("fSession#getExecutor")
public MIInferiorProcess(AbstractMIControl commandControl, PTY p) {
this(commandControl, null, p);
}
@ConfinedToDsfExecutor("fSession#getExecutor")
private MIInferiorProcess(AbstractMIControl commandControl, final OutputStream gdbOutputStream, PTY p) {
fCommandControl = commandControl;
fSession = commandControl.getSession();
commandControl.addEventListener(this);
commandControl.addCommandListener(this);
fPty = p;
if (fPty != null) {
fOutputStream = fPty.getOutputStream();
fInputStream = fPty.getInputStream();
fInputStreamPiped = null;
} else {
fOutputStream = new OutputStream() {
@Override
public void write(int b) throws IOException {
// Have to re-dispatch to dispatch thread to check state
if (getState() != State.RUNNING) {
throw new IOException("Target is not running"); //$NON-NLS-1$
}
gdbOutputStream.write(b);
}
};
fInputStreamPiped = new PipedOutputStream();
PipedInputStream inputStream = null;
try {
inputStream = new PipedInputStream(fInputStreamPiped);
} catch (IOException e) {
}
fInputStream = inputStream;
}
// Note: We do not have any err stream from gdb/mi so this gdb
// err channel instead.
fErrorStreamPiped = new PipedOutputStream();
PipedInputStream errorStream = null;
try {
errorStream = new PipedInputStream(fErrorStreamPiped);
} catch (IOException e) {
}
fErrorStream = errorStream;
}
@ConfinedToDsfExecutor("fSession#getExecutor")
public void dispose() {
fCommandControl.removeEventListener(this);
fCommandControl.removeCommandListener(this);
closeIO();
setState(State.TERMINATED);
fDisposed = true;
}
protected DsfSession getSession() {
return fSession;
}
protected AbstractMIControl getCommandControl() { return fCommandControl; }
protected boolean isDisposed() { return fDisposed; }
@Override
public OutputStream getOutputStream() {
return fOutputStream;
}
@Override
public InputStream getInputStream() {
return fInputStream;
}
@Override
public InputStream getErrorStream() {
return fErrorStream;
}
public synchronized void waitForSync() throws InterruptedException {
while (getState() != State.TERMINATED) {
wait(100);
}
}
/**
* @see java.lang.Process#waitFor()
*/
@Override
public int waitFor() throws InterruptedException {
waitForSync();
return exitValue();
}
/**
* @see java.lang.Process#exitValue()
*/
@Override
public int exitValue() {
if (fExitCode != null) {
return fExitCode;
}
try {
Query<Integer> exitCodeQuery = new Query<Integer>() {
@Override
protected void execute(final DataRequestMonitor<Integer> rm) {
// Guard against session disposed.
if (!DsfSession.isSessionActive(fSession.getId())) {
cancel(false);
return;
}
if (isDisposed()) {
rm.setData(0);
rm.done();
} else if (getState() != State.TERMINATED) {
// This will cause ExecutionException to be thrown with a CoreException,
// which will in turn contain the IllegalThreadStateException.
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "GDB is still running.", new IllegalThreadStateException())); //$NON-NLS-1$
rm.done();
} else {
getCommandControl().queueCommand(
new MIGDBShowExitCode(getCommandControl().getControlDMContext()),
new DataRequestMonitor<MIGDBShowExitCodeInfo>(fSession.getExecutor(), rm) {
@Override
protected void handleOK() {
rm.setData(getData().getCode());
rm.done();
}
});
}
}
};
fSession.getExecutor().execute(exitCodeQuery);
fExitCode = exitCodeQuery.get();
return fExitCode;
} catch (RejectedExecutionException e) {
} catch (InterruptedException e) {
} catch (CancellationException e) {
} catch (ExecutionException e) {
// Che
if (e.getCause() instanceof CoreException &&
((CoreException)e.getCause()).getStatus().getException() instanceof RuntimeException )
{
throw (RuntimeException)((CoreException)e.getCause()).getStatus().getException();
}
}
return 0;
}
/**
* @see java.lang.Process#destroy()
*/
@Override
public void destroy() {
try {
fSession.getExecutor().execute(new DsfRunnable() {
public void run() {
doDestroy();
}
});
} catch (RejectedExecutionException e) {
// Session disposed.
}
closeIO();
}
private void closeIO() {
try {
fOutputStream.close();
} catch (IOException e) {}
try {
fInputStream.close();
} catch (IOException e) {}
try {
fInputStreamPiped.close();
} catch (IOException e) {}
try {
fErrorStream.close();
} catch (IOException e) {}
try {
fErrorStreamPiped.close();
} catch (IOException e) {}
}
@ConfinedToDsfExecutor("fSession#getExecutor")
private void doDestroy() {
if (isDisposed() || !fSession.isActive() || getState() == State.TERMINATED) return;
// To avoid a RejectedExecutionException, use an executor that
// immediately executes in the same dispatch cycle.
CLIExecAbort cmd = new CLIExecAbort(getCommandControl().getControlDMContext());
getCommandControl().queueCommand(
cmd,
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), null) {
@Override
protected void handleCompleted() {
setState(MIInferiorProcess.State.TERMINATED);
}
}
);
}
public State getState() {
return fState;
}
synchronized void setState(State state) {
if (fState == State.TERMINATED) return;
fState = state;
if (fState == State.TERMINATED) {
closeIO();
}
notifyAll();
}
public OutputStream getPipedOutputStream() {
return fInputStreamPiped;
}
public OutputStream getPipedErrorStream() {
return fErrorStreamPiped;
}
public PTY getPTY() {
return fPty;
}
public void eventReceived(Object output) {
for (MIOOBRecord oobr : ((MIOutput)output).getMIOOBRecords()) {
if (oobr instanceof MIExecAsyncOutput) {
MIExecAsyncOutput async = (MIExecAsyncOutput)oobr;
String state = async.getAsyncClass();
if ("stopped".equals(state)) { //$NON-NLS-1$
boolean handled = false;
MIResult[] results = async.getMIResults();
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
if (var.equals("reason")) { //$NON-NLS-1$
MIValue value = results[i].getMIValue();
if (value instanceof MIConst) {
String reason = ((MIConst) value).getString();
if ("exited-signalled".equals(reason) || "exited-normally".equals(reason) || "exited".equals(reason)) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
setState(State.TERMINATED);
} else {
setState(State.STOPPED);
}
handled = true;
}
}
}
if (!handled) {
setState(State.STOPPED);
}
}
} else if (oobr instanceof MITargetStreamOutput) {
MITargetStreamOutput tgtOut = (MITargetStreamOutput)oobr;
if (fInputStreamPiped != null && tgtOut.getString() != null) {
try {
fInputStreamPiped.write(tgtOut.getString().getBytes());
fInputStreamPiped.flush();
} catch (IOException e) {
}
}
}
}
}
public void commandQueued(ICommand<? extends ICommandResult> command) {
// No action
}
public void commandSent(ICommand<? extends ICommandResult> command) {
// No action
}
public void commandRemoved(ICommand<? extends ICommandResult> command) {
// No action
}
public void commandDone(ICommand<? extends ICommandResult> cmd, ICommandResult result) {
MIInfo cmdResult = (MIInfo) result ;
MIOutput output = cmdResult.getMIOutput();
MIResultRecord rr = output.getMIResultRecord();
// Check if the state changed.
String state = rr.getResultClass();
if ("running".equals(state)) { setState(State.RUNNING); }//$NON-NLS-1$
else if ("exit".equals(state)) { setState(State.TERMINATED); }//$NON-NLS-1$
else if ("error".equals(state)) { setState(State.STOPPED); }//$NON-NLS-1$
}
}

View file

@ -0,0 +1,225 @@
/*******************************************************************************
* 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
* Ericsson - Additional handling of events
*******************************************************************************/
package org.eclipse.dd.mi.service.command;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.command.ICommand;
import org.eclipse.dd.dsf.debug.service.command.ICommandListener;
import org.eclipse.dd.dsf.debug.service.command.ICommandResult;
import org.eclipse.dd.dsf.debug.service.command.IEventListener;
import org.eclipse.dd.dsf.service.DsfServicesTracker;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.command.commands.MIExecContinue;
import org.eclipse.dd.mi.service.command.commands.MIExecFinish;
import org.eclipse.dd.mi.service.command.commands.MIExecNext;
import org.eclipse.dd.mi.service.command.commands.MIExecNextInstruction;
import org.eclipse.dd.mi.service.command.commands.MIExecReturn;
import org.eclipse.dd.mi.service.command.commands.MIExecStep;
import org.eclipse.dd.mi.service.command.commands.MIExecStepInstruction;
import org.eclipse.dd.mi.service.command.commands.MIExecUntil;
import org.eclipse.dd.mi.service.command.events.MIBreakpointHitEvent;
import org.eclipse.dd.mi.service.command.events.MIEvent;
import org.eclipse.dd.mi.service.command.events.MIFunctionFinishedEvent;
import org.eclipse.dd.mi.service.command.events.MIInferiorExitEvent;
import org.eclipse.dd.mi.service.command.events.MIInferiorSignalExitEvent;
import org.eclipse.dd.mi.service.command.events.MILocationReachedEvent;
import org.eclipse.dd.mi.service.command.events.MIRunningEvent;
import org.eclipse.dd.mi.service.command.events.MISignalEvent;
import org.eclipse.dd.mi.service.command.events.MISteppingRangeEvent;
import org.eclipse.dd.mi.service.command.events.MIStoppedEvent;
import org.eclipse.dd.mi.service.command.events.MIWatchpointScopeEvent;
import org.eclipse.dd.mi.service.command.events.MIWatchpointTriggerEvent;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIExecAsyncOutput;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MINotifyAsyncOutput;
import org.eclipse.dd.mi.service.command.output.MIOOBRecord;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIResult;
import org.eclipse.dd.mi.service.command.output.MIResultRecord;
import org.eclipse.dd.mi.service.command.output.MIStatusAsyncOutput;
import org.eclipse.dd.mi.service.command.output.MIValue;
/**
* MI debugger output listener that listens for the parsed MI output, and
* generates corresponding MI events. The generated MI events are then
* received by other services and clients.
*/
public class MIRunControlEventProcessor
implements IEventListener, ICommandListener
{
/**
* The connection service that this event processor is registered with.
*/
private final AbstractMIControl fCommandControl;
/**
* Container context used as the context for the run control events generated
* by this processor.
*/
private final IContainerDMContext fContainerDmc;
/**
* Services tracker used to retrieve the MIRunControl service.
*/
private final DsfServicesTracker fServicesTracker;
/**
* Creates the event processor and registers it as listener with the debugger
* control.
* @param connection
* @param inferior
*/
public MIRunControlEventProcessor(AbstractMIControl connection, IContainerDMContext containerDmc) {
fCommandControl = connection;
fContainerDmc = containerDmc;
fServicesTracker = new DsfServicesTracker(MIPlugin.getBundleContext(), fCommandControl.getSession().getId());
connection.addEventListener(this);
connection.addCommandListener(this);
}
/**
* This processor must be disposed before the control service is un-registered.
*/
public void dispose() {
fCommandControl.removeEventListener(this);
fCommandControl.removeCommandListener(this);
fServicesTracker.dispose();
}
public void eventReceived(Object output) {
for (MIOOBRecord oobr : ((MIOutput)output).getMIOOBRecords()) {
if (oobr instanceof MIExecAsyncOutput) {
MIExecAsyncOutput exec = (MIExecAsyncOutput) oobr;
// Change of state.
String state = exec.getAsyncClass();
if ("stopped".equals(state)) { //$NON-NLS-1$
// Re-set the thread level to -1 when stopped event is recvd.
// This is to synchronize the state between GDB back-end and AbstractMIControl.
fCommandControl.resetCurrentThreadLevel();
List<MIEvent<?>> events = new LinkedList<MIEvent<?>>();
MIResult[] results = exec.getMIResults();
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue val = results[i].getMIValue();
if (var.equals("reason")) { //$NON-NLS-1$
if (val instanceof MIConst) {
String reason = ((MIConst) val).getString();
MIEvent<?> e = createEvent(reason, exec);
if (e != null) {
events.add(e);
continue;
}
}
}
}
// We were stopped for some unknown reason, for example
// GDB for temporary breakpoints will not send the
// "reason" ??? still fire a stopped event.
if (events.isEmpty()) {
MIEvent<?> e = MIStoppedEvent.parse(
fServicesTracker.getService(MIRunControl.class), fContainerDmc, exec.getToken(), exec.getMIResults());
events.add(e);
}
for (MIEvent<?> event : events) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
}
}
else if (oobr instanceof MIStatusAsyncOutput) {
// Nothing done .. but what about +download??
} else if (oobr instanceof MINotifyAsyncOutput) {
// Nothing
}
}
}
protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec) {
MIRunControl runControl = fServicesTracker.getService(MIRunControl.class);
MIEvent<?> event = null;
if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$
event = MIBreakpointHitEvent.parse(runControl, fContainerDmc, exec.getToken(), exec.getMIResults());
} else if (
"watchpoint-trigger".equals(reason) //$NON-NLS-1$
|| "read-watchpoint-trigger".equals(reason) //$NON-NLS-1$
|| "access-watchpoint-trigger".equals(reason)) { //$NON-NLS-1$
event = MIWatchpointTriggerEvent.parse(runControl, fContainerDmc, exec.getToken(), exec.getMIResults());
} else if ("watchpoint-scope".equals(reason)) { //$NON-NLS-1$
event = MIWatchpointScopeEvent.parse(runControl, fContainerDmc, exec.getToken(), exec.getMIResults());
} else if ("end-stepping-range".equals(reason)) { //$NON-NLS-1$
event = MISteppingRangeEvent.parse(runControl, fContainerDmc, exec.getToken(), exec.getMIResults());
} else if ("signal-received".equals(reason)) { //$NON-NLS-1$
event = MISignalEvent.parse(runControl, fContainerDmc, exec.getToken(), exec.getMIResults());
} else if ("location-reached".equals(reason)) { //$NON-NLS-1$
event = MILocationReachedEvent.parse(runControl, fContainerDmc, exec.getToken(), exec.getMIResults());
} else if ("function-finished".equals(reason)) { //$NON-NLS-1$
event = MIFunctionFinishedEvent.parse(runControl, fContainerDmc, exec.getToken(), exec.getMIResults());
} else if ("exited-normally".equals(reason) || "exited".equals(reason)) { //$NON-NLS-1$ //$NON-NLS-2$
event = MIInferiorExitEvent.parse(fCommandControl.getControlDMContext(), exec.getToken(), exec.getMIResults());
} else if ("exited-signalled".equals(reason)) { //$NON-NLS-1$
event = MIInferiorSignalExitEvent.parse(fCommandControl.getControlDMContext(), exec.getToken(), exec.getMIResults());
}
return event;
}
public void commandQueued(ICommand<?> command) {
// Do nothing.
}
public void commandSent(ICommand<?> command) {
// Do nothing.
}
public void commandRemoved(ICommand<?> command) {
// Do nothing.
}
public void commandDone(ICommand<?> cmd, ICommandResult result) {
MIInfo cmdResult = (MIInfo) result ;
MIOutput output = cmdResult.getMIOutput();
MIResultRecord rr = output.getMIResultRecord();
if (rr != null) {
int id = rr.getToken();
// Check if the state changed.
String state = rr.getResultClass();
if ("running".equals(state)) { //$NON-NLS-1$
int type = 0;
// Check the type of command
// if it was a step instruction set state stepping
if (cmd instanceof MIExecNext) { type = MIRunningEvent.NEXT; }
else if (cmd instanceof MIExecNextInstruction) { type = MIRunningEvent.NEXTI; }
else if (cmd instanceof MIExecStep) { type = MIRunningEvent.STEP; }
else if (cmd instanceof MIExecStepInstruction) { type = MIRunningEvent.STEPI; }
else if (cmd instanceof MIExecUntil) { type = MIRunningEvent.UNTIL; }
else if (cmd instanceof MIExecFinish) { type = MIRunningEvent.FINISH; }
else if (cmd instanceof MIExecReturn) { type = MIRunningEvent.RETURN; }
else if (cmd instanceof MIExecContinue) { type = MIRunningEvent.CONTINUE; }
else { type = MIRunningEvent.CONTINUE; }
fCommandControl.getSession().dispatchEvent(
new MIRunningEvent(fContainerDmc, id, type), fCommandControl.getProperties());
} else if ("exit".equals(state)) { //$NON-NLS-1$
// No need to do anything, terminate() will.
// Send exited?
} else if ("connected".equals(state)) { //$NON-NLS-1$
} else if ("error".equals(state)) { //$NON-NLS-1$
}
}
}
}

View file

@ -0,0 +1,26 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
* Represents a CLI command.
*/
public class CLICommand<V extends MIInfo> extends MICommand<V>
{
public CLICommand(IDMContext ctx, String oper) {
super(ctx, oper);
}
}

View file

@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.mi.service.command.MIControlDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* kill
*
* Terminates the user (MI inferior) process
*
*/
public class CLIExecAbort extends CLICommand<MIInfo>
{
public CLIExecAbort(MIControlDMContext ctx) {
super(ctx, "kill"); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright (c) 2000, 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
* Ericsson - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IModules.IModuleDMContext;
import org.eclipse.dd.dsf.debug.service.IModules.ISymbolDMContext;
import org.eclipse.dd.mi.service.command.output.CLIInfoSharedLibraryInfo;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
*
* info sharedlibrary
*
*/
public class CLIInfoSharedLibrary extends CLICommand<CLIInfoSharedLibraryInfo> {
public CLIInfoSharedLibrary(ISymbolDMContext ctx) {
super(ctx, "info sharedlibrary"); //$NON-NLS-1$
}
public CLIInfoSharedLibrary(IModuleDMContext ctx) {
super(ctx, "info sharedlibrary"); //$NON-NLS-1$
}
@Override
public CLIInfoSharedLibraryInfo getResult(MIOutput output) {
return (CLIInfoSharedLibraryInfo)getMIInfo(output);
}
public MIInfo getMIInfo(MIOutput out) {
MIInfo info = null;
if (out != null) {
info = new CLIInfoSharedLibraryInfo(out);
}
return info;
}
}

View file

@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Ericsson - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.mi.service.command.output.CLIInfoThreadsInfo;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
*
* info threads
*
*/
public class CLIInfoThreads extends CLICommand<CLIInfoThreadsInfo> {
public CLIInfoThreads(IContainerDMContext ctx) {
super(ctx, "info threads"); //$NON-NLS-1$
}
@Override
public CLIInfoThreadsInfo getResult(MIOutput output) {
return (CLIInfoThreadsInfo)getMIInfo(output);
}
public MIInfo getMIInfo(MIOutput out) {
MIInfo info = null;
if (out != null) {
info = new CLIInfoThreadsInfo(out);
}
return info;
}
}

View file

@ -0,0 +1,61 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.command.ICommand;
import org.eclipse.dd.dsf.debug.service.command.ICommandResult;
public class ExprMetaCommand<V extends ICommandResult> implements ICommand<V> {
private final IDMContext fCtx;
public ExprMetaCommand(IDMContext ctx) {
fCtx = ctx;
}
/*
* Takes the supplied command and coalesces it with this one.
* The result is a new third command which represent the two
* original command.
*/
public ICommand<? extends ICommandResult> coalesceWith( ICommand<? extends ICommandResult> command ) {
return null ;
}
public IDMContext getContext(){
return fCtx;
}
@Override
public boolean equals(Object other) {
if (other == null) return false;
if (!(other.getClass().equals(getClass()))) return false;
// Since other is the same class is this, we are sure it is of type DsfExprMetaCommand also
ExprMetaCommand<?> otherCmd = (ExprMetaCommand<?>)other;
return fCtx == null ? otherCmd.fCtx == null : fCtx.equals(otherCmd.fCtx);
}
@Override
public int hashCode() {
return fCtx == null ? getClass().hashCode() : getClass().hashCode() ^ fCtx.hashCode();
}
@Override
public String toString() {
return getClass().toString() + fCtx == null ? "null" : fCtx.toString(); //$NON-NLS-1$
}
public String getCommandControlFilter() {
return null;
}
}

View file

@ -0,0 +1,21 @@
/*******************************************************************************
* 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.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.mi.service.command.output.ExprMetaGetAttributesInfo;
public class ExprMetaGetAttributes extends ExprMetaCommand<ExprMetaGetAttributesInfo> {
public ExprMetaGetAttributes(IExpressionDMContext ctx) {
super(ctx);
}
}

View file

@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.mi.service.command.output.ExprMetaGetChildCountInfo;
public class ExprMetaGetChildCount extends ExprMetaCommand<ExprMetaGetChildCountInfo> {
public ExprMetaGetChildCount(IExpressionDMContext ctx) {
super(ctx);
}
}

View file

@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.mi.service.command.output.ExprMetaGetChildrenInfo;
public class ExprMetaGetChildren extends ExprMetaCommand<ExprMetaGetChildrenInfo> {
public ExprMetaGetChildren(IExpressionDMContext ctx) {
super(ctx);
}
}

View file

@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
import org.eclipse.dd.mi.service.command.output.ExprMetaGetValueInfo;
public class ExprMetaGetValue extends ExprMetaCommand<ExprMetaGetValueInfo> {
public ExprMetaGetValue(FormattedValueDMContext ctx) {
super(ctx);
}
}

View file

@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.mi.service.command.output.ExprMetaGetVarInfo;
public class ExprMetaGetVar extends ExprMetaCommand<ExprMetaGetVarInfo> {
public ExprMetaGetVar(IExpressionDMContext ctx) {
super(ctx);
}
}

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -break-after NUMBER COUNT
*
* The breakpoint number NUMBER is not in effect until it has been hit
* COUNT times. The count becomes part of the `-break-list' output
* (see the description of the DsfMIBreakList).
*/
public class MIBreakAfter extends MICommand<MIInfo>
{
public MIBreakAfter(IBreakpointsTargetDMContext ctx, int breakpoint, int ignoreCount) {
super(ctx, "-break-after"); //$NON-NLS-1$
setParameters(new String[] { Integer.toString(breakpoint), Integer.toString(ignoreCount) });
}
}

View file

@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -break-condition NUMBER EXPR
*
* Breakpoint NUMBER will stop the program only if the condition in
* EXPR is true. The condition becomes part of the `-break-list' output
* (see the description of the DsfMIBreakList).
*/
public class MIBreakCondition extends MICommand<MIInfo>
{
// In this particular case, because of a GDB peculiarity, setParameters() is
// not used and the whole command is formatted on the parent's constructor.
// See bug 213076 for more information.
public MIBreakCondition(IBreakpointsTargetDMContext ctx, int breakpoint, String condition) {
super(ctx, "-break-condition " + Integer.toString(breakpoint) + " " + condition); //$NON-NLS-1$ //$NON-NLS-2$
// setParameters(new String[] { Integer.toString(breakpoint), condition });
}
}

View file

@ -0,0 +1,42 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -break-delete ( BREAKPOINT )+
*
* Delete the breakpoint(s) whose number(s) are specified in the
* argument list. This is obviously reflected in the breakpoint list.
*
* Result:
* ^done
*
*/
public class MIBreakDelete extends MICommand<MIInfo>
{
public MIBreakDelete (IBreakpointsTargetDMContext ctx, int[] array) {
super(ctx, "-break-delete"); //$NON-NLS-1$
if (array != null && array.length > 0) {
String[] brkids = new String[array.length];
for (int i = 0; i < array.length; i++) {
brkids[i] = Integer.toString(array[i]);
}
setParameters(brkids);
}
}
}

View file

@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -break-disable ( BREAKPOINT )+
*
* Disable the named BREAKPOINT(s). The field `enabled' in the break
* list is now set to `n' for the named BREAKPOINT(s).
*
* Result:
* ^done
*/
public class MIBreakDisable extends MICommand<MIInfo>
{
public MIBreakDisable (IBreakpointsTargetDMContext ctx, int[] array) {
super(ctx, "-break-disable"); //$NON-NLS-1$
if (array != null && array.length > 0) {
String[] brkids = new String[array.length];
for (int i = 0; i < array.length; i++) {
brkids[i] = Integer.toString(array[i]);
}
setParameters(brkids);
}
}
}

View file

@ -0,0 +1,40 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -break-enable ( BREAKPOINT )+
*
* Enable (previously disabled) BREAKPOINT(s).
*
* Result:
* ^done
*/
public class MIBreakEnable extends MICommand<MIInfo>
{
public MIBreakEnable (IBreakpointsTargetDMContext ctx, int[] array) {
super(ctx, "-break-enable"); //$NON-NLS-1$
if (array != null && array.length > 0) {
String[] brkids = new String[array.length];
for (int i = 0; i < array.length; i++) {
brkids[i] = Integer.toString(array[i]);
}
setParameters(brkids);
}
}
}

View file

@ -0,0 +1,120 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.dd.mi.service.command.output.MIBreakInsertInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
* -break-insert [ -t ] [ -h ] [ -r ]
* [ -c CONDITION ] [ -i IGNORE-COUNT ]
* [ -p THREAD ] [ LINE | ADDR ]
*
* If specified, LINE, can be one of:
* * function
* * filename:linenum
* * filename:function
* * *address
*
* The possible optional parameters of this command are:
*
* '-t'
* Insert a temporary breakpoint.
*
* '-h'
* Insert a hardware breakpoint.
*
* '-r'
* Insert a regular breakpoint in all the functions whose names match
* the given regular expression. Other flags are not applicable to
* regular expression.
*
* '-c CONDITION'
* Make the breakpoint conditional on CONDITION.
*
* '-i IGNORE-COUNT'
* Initialize the IGNORE-COUNT (number of breakpoint hits before breaking).
*
* '-p THREAD'
* THREAD on which to apply the breakpoint
*/
public class MIBreakInsert extends MICommand<MIBreakInsertInfo>
{
public MIBreakInsert(IBreakpointsTargetDMContext ctx, String func) {
this(ctx, false, false, null, 0, func, 0);
}
public MIBreakInsert(IBreakpointsTargetDMContext ctx, boolean isTemporary, boolean isHardware,
String condition, int ignoreCount, String line, int tid) {
super(ctx, "-break-insert"); //$NON-NLS-1$
// Determine the number of optional parameters that are present
// and allocate a corresponding string array
int i = 0;
if (isTemporary) {
i++;
}
if (isHardware) {
i++;
}
if (condition != null && condition.length() > 0) {
i += 2;
}
if (ignoreCount > 0) {
i += 2;
}
if (tid > 0) {
i += 2;
}
String[] opts = new String[i];
// Fill in the optional parameters
i = 0;
if (isTemporary) {
opts[i] = "-t"; //$NON-NLS-1$
i++;
}
if (isHardware) {
opts[i] = "-h"; //$NON-NLS-1$
i++;
}
if (condition != null && condition.length() > 0) {
opts[i] = "-c"; //$NON-NLS-1$
i++;
opts[i] = condition;
i++;
}
if (ignoreCount > 0) {
opts[i] = "-i"; //$NON-NLS-1$
i++;
opts[i] = Integer.toString(ignoreCount);
i++;
}
if (tid > 0) {
opts[i] = "-p"; //$NON-NLS-1$
i++;
opts[i] = Integer.toString(tid);
}
if (opts.length > 0) {
setOptions(opts);
}
setParameters(new String[]{line});
}
@Override
public MIBreakInsertInfo getResult(MIOutput output) {
return new MIBreakInsertInfo(output);
}
}

View file

@ -0,0 +1,62 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.dd.mi.service.command.output.MIBreakListInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
*
* -break-list
*
* Displays the list of inserted breakpoints, showing the following
* fields:
*
* `Number'
* number of the breakpoint
*
* `Type'
* type of the breakpoint: `breakpoint' or `watchpoint'
*
* `Disposition'
* should the breakpoint be deleted or disabled when it is hit: `keep'
* or `nokeep'
*
* `Enabled'
* is the breakpoint enabled or no: `y' or `n'
*
* `Address'
* memory location at which the breakpoint is set
*
* `What'
* logical location of the breakpoint, expressed by function name,
*
* `Times'
* number of times the breakpoint has been hit
*
* If there are no breakpoints or watchpoints, the `BreakpointTable'
* `body' field is an empty list.
*
*/
public class MIBreakList extends MICommand<MIBreakListInfo>
{
public MIBreakList (IBreakpointsTargetDMContext ctx) {
super(ctx, "-break-list"); //$NON-NLS-1$
}
@Override
public MIBreakListInfo getResult(MIOutput output) {
return new MIBreakListInfo(output);
}
}

View file

@ -0,0 +1,55 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.dd.mi.service.command.output.MIBreakInsertInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
* -break-watch [ -a | -r ] LOCATION
*
* Create a watchpoint on LOCATION. Without either of the options, the watchpoint
* created is a regular watchpoint, i.e., a watchpoint that triggers when the
* memory LOCATION is accessed for writing.
* The possible optional parameters of this command are:
*
* '-a'
* Creates an access watchpoint i.e. a watchpoint that triggers either
* on a read from or on a write to the memory location.
*
* '-r'
* Creates a read watchpoint i.e. a watchpoint that triggers only when
* the memory location is accessed for reading.
*/
public class MIBreakWatch extends MICommand<MIBreakInsertInfo>
{
public MIBreakWatch(IBreakpointsTargetDMContext ctx, boolean isRead, boolean isWrite, String expression)
{
super(ctx, "-break-watch"); //$NON-NLS-1$
if (isRead) {
if (isWrite)
setOptions(new String[] { "-a" }); //$NON-NLS-1$
else
setOptions(new String[] { "-r" }); //$NON-NLS-1$
}
setParameters(new String[]{ expression });
}
@Override
public MIBreakInsertInfo getResult(MIOutput output) {
return new MIBreakInsertInfo(output);
}
}

View file

@ -0,0 +1,256 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for additional features in DSF Reference implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.command.ICommand;
import org.eclipse.dd.dsf.debug.service.command.ICommandResult;
import org.eclipse.dd.mi.service.command.MIControlDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
* Represents any MI command.
*/
public class MICommand<V extends MIInfo> implements ICommand<V> {
/*
* Variables.
*/
final static String[] empty = new String[0];
String[] fOptions = empty;
String[] fParameters = empty;
String fOperation = new String();
IDMContext fCtx;
/*
* Constructors.
*/
/*public DsfMICommand(String operation) {
this(operation, empty, empty);
}*/
public MICommand(IDMContext ctx, String operation) {
this(ctx, operation, empty, empty);
}
/*public DsfMICommand(String operation, String[] options) {
this(operation, options, empty);
}*/
public MICommand(IDMContext ctx, String operation, String[] options) {
this(ctx, operation, options, empty);
}
public MICommand(IDMContext ctx, String operation, String[] options, String[] params) {
assert(ctx != null && DMContexts.getAncestorOfType(ctx, MIControlDMContext.class) != null);
fCtx = ctx;
fOperation = operation;
fOptions = options;
fParameters = params;
}
public String getCommandControlFilter() {
MIControlDMContext controlDmc = DMContexts.getAncestorOfType(getContext(), MIControlDMContext.class);
return controlDmc.getCommandControlFilter();
}
/*
* Returns the operation of this command.
*/
public String getOperation() {
return fOperation;
}
/*
* Returns an array of command's options. An empty collection is
* returned if there are no options.
*/
public String[] getOptions() {
return fOptions;
}
public void setOptions(String[] options) {
fOptions = options;
}
/*
* Returns an array of command's parameters. An empty collection is
* returned if there are no parameters.
*/
public String[] getParameters() {
return fParameters;
}
public void setParameters(String[] params) {
fParameters = params;
}
/*
* Returns the constructed command.
*/
public String constructCommand() {
StringBuffer command = new StringBuffer(getOperation());
String opt = optionsToString();
if (opt.length() > 0) {
command.append(' ').append(opt);
}
String p = parametersToString();
if (p.length() > 0) {
command.append(' ').append(p);
}
command.append('\n');
return command.toString();
}
// /*
// * Checks to see if the current command can be coalesced with the
// * supplied command.
// */
// public boolean canCoalesce( ICommand<? extends ICommandResult> command ) {
// return false ;
// }
/*
* Takes the supplied command and coalesces it with this one.
* The result is a new third command which represent the two
* original command.
*/
public ICommand<? extends ICommandResult> coalesceWith( ICommand<? extends ICommandResult> command ) {
return null ;
}
public IDMContext getContext(){
return fCtx;
}
/**
* Produces the corresponding ICommandResult result for this
* command.
*
* @return result for this command
*/
public MIInfo getResult(MIOutput MIresult) {
return ( new MIInfo(MIresult) );
}
protected String optionsToString() {
String[] options = getOptions();
StringBuffer sb = new StringBuffer();
if (options != null && options.length > 0) {
for (int i = 0; i < options.length; i++) {
String option = options[i];
// If the option argument contains " or \ it must be escaped
if (option.indexOf('"') != -1 || option.indexOf('\\') != -1) {
StringBuffer buf = new StringBuffer();
for (int j = 0; j < option.length(); j++) {
char c = option.charAt(j);
if (c == '"' || c == '\\') {
buf.append('\\');
}
buf.append(c);
}
option = buf.toString();
}
// If the option contains a space according to
// GDB/MI spec we must surround it with double quotes.
if (option.indexOf('\t') != -1 || option.indexOf(' ') != -1) {
sb.append(' ').append('"').append(option).append('"');
} else {
sb.append(' ').append(option);
}
}
}
return sb.toString().trim();
}
protected String parametersToString() {
String[] parameters = getParameters();
String[] options = getOptions();
StringBuffer buffer = new StringBuffer();
if (parameters != null && parameters.length > 0) {
// According to GDB/MI spec
// Add a "--" separator if any parameters start with "-"
if (options != null && options.length > 0) {
for (int i = 0; i < parameters.length; i++) {
if (parameters[i].startsWith("-")) { //$NON-NLS-1$
buffer.append('-').append('-');
break;
}
}
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < parameters.length; i++) {
// We need to escape the double quotes and the backslash.
sb.setLength(0);
String param = parameters[i];
for (int j = 0; j < param.length(); j++) {
char c = param.charAt(j);
if (c == '"' || c == '\\') {
sb.append('\\');
}
sb.append(c);
}
// If the string contains spaces instead of escaping
// surround the parameter with double quotes.
if (containsWhitespace(param)) {
sb.insert(0, '"');
sb.append('"');
}
buffer.append(' ').append(sb);
}
}
return buffer.toString().trim();
}
protected boolean containsWhitespace(String s) {
for (int i = 0; i < s.length(); i++) {
if (Character.isWhitespace(s.charAt(i))) {
return true;
}
}
return false;
}
/**
* Compare commands based on the MI command string that they generate,
* without the token.
*/
@Override
public boolean equals(Object obj) {
if(obj instanceof MICommand<?>){
MICommand<?> otherCmd = (MICommand<?>)obj;
return ((fCtx == null && otherCmd.fCtx == null) || (fCtx != null && fCtx.equals(otherCmd.fCtx))) &&
constructCommand().equals(otherCmd.constructCommand());
}
return false;
}
@Override
public int hashCode() {
return constructCommand().hashCode();
}
@Override
public String toString() {
return constructCommand();
}
}

View file

@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.MIControlDMContext;
import org.eclipse.dd.mi.service.command.output.MIDataEvaluateExpressionInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
*
* -data-evaluate-expression EXPR
*
* Evaluate EXPR as an expression. The expression could contain an
*inferior function call. The function call will execute synchronously.
*If the expression contains spaces, it must be enclosed in double quotes.
*
*/
public class MIDataEvaluateExpression<V extends MIDataEvaluateExpressionInfo> extends MICommand<V>
{
public MIDataEvaluateExpression(MIControlDMContext ctx, String expr) {
super(ctx, "-data-evaluate-expression", new String[]{expr}); //$NON-NLS-1$
}
public MIDataEvaluateExpression(IMIExecutionDMContext execDmc, String expr) {
super(execDmc, "-data-evaluate-expression", new String[]{expr}); //$NON-NLS-1$
}
public MIDataEvaluateExpression(IFrameDMContext frameDmc, String expr) {
super(frameDmc, "-data-evaluate-expression", new String[]{expr}); //$NON-NLS-1$
}
public MIDataEvaluateExpression(IExpressionDMContext exprDmc) {
super(exprDmc, "-data-evaluate-expression", new String[]{exprDmc.getExpression()}); //$NON-NLS-1$
}
@Override
public MIDataEvaluateExpressionInfo getResult(MIOutput output) {
return new MIDataEvaluateExpressionInfo(output);
}
}

View file

@ -0,0 +1,52 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.mi.service.command.output.MIDataListRegisterNamesInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
*
* -data-list-register-names [ ( REGNO )+ ]
*
* Show a list of register names for the current target. If no
* arguments are given, it shows a list of the names of all the registers.
* If integer numbers are given as arguments, it will print a list of the
* names of the registers corresponding to the arguments. To ensure
* consistency between a register name and its number, the output list may
* include empty register names.
*
*/
public class MIDataListRegisterNames extends MICommand<MIDataListRegisterNamesInfo>
{
public MIDataListRegisterNames(IContainerDMContext ctx) {
super(ctx, "-data-list-register-names"); //$NON-NLS-1$
}
public MIDataListRegisterNames(IContainerDMContext ctx, int [] regnos) {
this(ctx);
if (regnos != null && regnos.length > 0) {
String[] array = new String[regnos.length];
for (int i = 0; i < regnos.length; i++) {
array[i] = Integer.toString(regnos[i]);
}
setParameters(array);
}
}
@Override
public MIDataListRegisterNamesInfo getResult(MIOutput output) {
return new MIDataListRegisterNamesInfo(output);
}
}

View file

@ -0,0 +1,145 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.command.ICommand;
import org.eclipse.dd.dsf.debug.service.command.ICommandResult;
import org.eclipse.dd.mi.service.MIFormat;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIDataListRegisterValuesInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
*
* -data-list-register-values FMT [ ( REGNO )*]
*
* Display the registers' contents. FMT is the format according to
* which the registers' contents are to be returned, followed by an
* optional list of numbers specifying the registers to display. A
* missing list of numbers indicates that the contents of all the
* registers must be returned.
*
*/
public class MIDataListRegisterValues extends MICommand<MIDataListRegisterValuesInfo> {
int[] regnums;
int fFmt;
public MIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt) {
this(ctx, fmt, null);
}
public MIDataListRegisterValues(IMIExecutionDMContext ctx, int fmt, int [] regnos) {
super(ctx, "-data-list-register-values"); //$NON-NLS-1$
regnums = regnos;
String format = "x"; //$NON-NLS-1$
switch (fmt) {
case MIFormat.NATURAL: format = "N"; break ; //$NON-NLS-1$
case MIFormat.RAW: format = "r"; break ; //$NON-NLS-1$
case MIFormat.DECIMAL: format = "d"; break ; //$NON-NLS-1$
case MIFormat.BINARY: format = "t"; break ; //$NON-NLS-1$
case MIFormat.OCTAL: format = "o"; break ; //$NON-NLS-1$
case MIFormat.HEXADECIMAL: format = "x"; break ; //$NON-NLS-1$
default: format = "x"; break ; //$NON-NLS-1$
}
fFmt = fmt;
setOptions(new String[]{format});
if (regnos != null && regnos.length > 0) {
String[] array = new String[regnos.length];
for (int i = 0; i < regnos.length; i++) {
array[i] = Integer.toString(regnos[i]);
}
setParameters(array);
}
}
public int[] getRegList() {
return regnums;
}
@Override
public MIDataListRegisterValuesInfo getResult(MIOutput output) {
return new MIDataListRegisterValuesInfo(output);
}
/*
* Takes the supplied command and coalesces it with this one.
* The result is a new third command which represent the two
* original command.
*/
@Override
public MIDataListRegisterValues coalesceWith(ICommand<? extends ICommandResult> command ) {
/*
* Can coalesce only with other DsfMIDataListRegisterValues commands.
*/
if (! (command instanceof MIDataListRegisterValues) ) return null;
MIDataListRegisterValues cmd = (MIDataListRegisterValues) command;
int[] newregnos = new int[ regnums.length + cmd.regnums.length];
/*
* We need to add the new register #'s to the list. If one is already there
* then do not add it twice. So copy the original list of this command.
*/
for ( int idx = 0 ; idx < regnums.length ; idx ++) {
newregnos[ idx ] = regnums[ idx ];
}
int curloc = regnums.length;
for ( int ndx = 0 ; ndx < cmd.regnums.length; ndx ++) {
int curnum = cmd.regnums[ ndx ] ;
int ldx;
/*
* Search the current list to see if this entry is in it.
*/
for ( ldx = 0 ; ldx < regnums.length; ldx ++ ) {
if ( newregnos[ ldx ] == curnum ) {
break ;
}
}
if ( ldx == regnums.length ) {
/*
* Since we did not find a match add it at the end of the list.
*/
newregnos[ curloc ] = curnum;
curloc ++;
}
}
/*
* Create a final proper array set of the new combined list.
*/
int[] finalregnums = new int[ curloc ] ;
for ( int fdx = 0 ; fdx < curloc ; fdx ++ ) {
finalregnums[ fdx ] = newregnos[ fdx ];
}
/*
* Now construct a new one. The format we will use is this command.
*/
return( new MIDataListRegisterValues((IMIExecutionDMContext)getContext(), fFmt, finalregnums));
}
}

View file

@ -0,0 +1,150 @@
/*******************************************************************************
* Copyright (c) 2000, 2006, 2007 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
* Ericsson AB - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.mi.service.MIFormat;
import org.eclipse.dd.mi.service.command.output.MIDataReadMemoryInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
* -data-read-memory [ -o BYTE-OFFSET ]
* ADDRESS WORD-FORMAT WORD-SIZE
* NR-ROWS NR-COLS [ ASCHAR ]
*
* where:
*
* 'ADDRESS'
* An expression specifying the address of the first memory word to be
* read. Complex expressions containing embedded white space should
* be quoted using the C convention.
*
* 'WORD-FORMAT'
* The format to be used to print the memory words. The notation is
* the same as for GDB's `print' command (*note Output formats:
* Output Formats.).
*
* 'WORD-SIZE'
* The size of each memory word in bytes.
*
* 'NR-ROWS'
* The number of rows in the output table.
*
* 'NR-COLS'
* The number of columns in the output table.
*
* 'ASCHAR'
* If present, indicates that each row should include an ASCII dump.
* The value of ASCHAR is used as a padding character when a byte is
* not a member of the printable ASCII character set (printable ASCII
* characters are those whose code is between 32 and 126,
* inclusively).
*
* 'BYTE-OFFSET'
* An offset to add to ADDRESS before fetching the memory.
*
*/
public class MIDataReadMemory extends MICommand<MIDataReadMemoryInfo> {
int fword_size;
public MIDataReadMemory(
IDMContext ctx,
long offset,
String address,
int word_format,
int word_size,
int rows,
int cols,
Character asChar)
{
super(ctx, "-data-read-memory"); //$NON-NLS-1$
// Save this for the result parser
fword_size = word_size;
if (offset != 0) {
setOptions(new String[] { "-o", Long.toString(offset * word_size)}); //$NON-NLS-1$
}
String format = "x"; //$NON-NLS-1$
switch (word_format) {
case MIFormat.UNSIGNED :
format = "u"; //$NON-NLS-1$
break;
case MIFormat.FLOAT :
format = "f"; //$NON-NLS-1$
break;
case MIFormat.ADDRESS :
format = "a"; //$NON-NLS-1$
break;
case MIFormat.INSTRUCTION :
format = "i"; //$NON-NLS-1$
break;
case MIFormat.CHAR :
format = "c"; //$NON-NLS-1$
break;
case MIFormat.STRING :
format = "s"; //$NON-NLS-1$
break;
case MIFormat.DECIMAL :
case MIFormat.NATURAL :
format = "d"; //$NON-NLS-1$
break;
case MIFormat.BINARY :
format = "t"; //$NON-NLS-1$
break;
case MIFormat.OCTAL :
format = "o"; //$NON-NLS-1$
break;
case MIFormat.HEXADECIMAL :
case MIFormat.RAW :
default :
format = "x"; //$NON-NLS-1$
break;
}
if (asChar == null) {
setParameters(
new String[] {
address,
format,
Integer.toString(1), // wordSize
Integer.toString(rows),
Integer.toString(cols * word_size)});
} else {
setParameters(
new String[] {
address,
format,
Integer.toString(1), // wordSize
Integer.toString(rows),
Integer.toString(cols * word_size),
asChar.toString()});
}
}
@Override
public MIDataReadMemoryInfo getResult(MIOutput out) {
return new MIDataReadMemoryInfo(out, fword_size);
}
}

View file

@ -0,0 +1,118 @@
/*******************************************************************************
* Copyright (c) 2000, 2006, 2007 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
* Ericsson Communication - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.mi.service.MIFormat;
import org.eclipse.dd.mi.service.command.output.MIDataWriteMemoryInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
* -data-write-memory [ -o COLUMN_OFFSET ]
* ADDRESS WORD-FORMAT WORD-SIZE VALUE
*
* where:
*
* 'COLUMN_OFFSET'
* The cell offset from the beginning of the memory grid row
*
* 'ADDRESS'
* Row address of the cell to be written
*
* 'WORD-FORMAT'
* The format to be used to print the memory words
*
* 'WORD-SIZE'
* The size of each memory word in bytes
*
* 'VALUE'
* The value to be written into the cell
*
* Writes VALUE into ADDRESS + (COLUMN_OFFSET * WORD_SIZE).
*
*/
public class MIDataWriteMemory extends MICommand<MIDataWriteMemoryInfo> {
public MIDataWriteMemory(
IDMContext ctx,
long offset,
String address,
int wordFormat,
int wordSize,
String value)
{
super(ctx, "-data-write-memory"); //$NON-NLS-1$
if (offset != 0) {
setOptions(new String[] { "-o", Long.toString(offset)}); //$NON-NLS-1$
}
String format = "x"; //$NON-NLS-1$
switch (wordFormat) {
case MIFormat.UNSIGNED :
format = "u"; //$NON-NLS-1$
break;
case MIFormat.FLOAT :
format = "f"; //$NON-NLS-1$
break;
case MIFormat.ADDRESS :
format = "a"; //$NON-NLS-1$
break;
case MIFormat.INSTRUCTION :
format = "i"; //$NON-NLS-1$
break;
case MIFormat.CHAR :
format = "c"; //$NON-NLS-1$
break;
case MIFormat.STRING :
format = "s"; //$NON-NLS-1$
break;
case MIFormat.DECIMAL :
case MIFormat.NATURAL :
format = "d"; //$NON-NLS-1$
break;
case MIFormat.BINARY :
format = "t"; //$NON-NLS-1$
break;
case MIFormat.OCTAL :
format = "o"; //$NON-NLS-1$
break;
case MIFormat.HEXADECIMAL :
case MIFormat.RAW :
default :
format = "x"; //$NON-NLS-1$
break;
}
setParameters(
new String[] {
address,
format,
Integer.toString(wordSize),
value});
}
@Override
public MIDataWriteMemoryInfo getResult(MIOutput out) {
return new MIDataWriteMemoryInfo(out);
}
}

View file

@ -0,0 +1,31 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-continue
*
* Asynchronous command. Resumes the execution of the inferior program
* until a breakpoint is encountered, or until the inferior exits.
*
*/
public class MIExecContinue extends MICommand<MIInfo>
{
public MIExecContinue(IExecutionDMContext dmc) {
super(dmc, "-exec-continue"); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,37 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for handling of execution contexts
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
* <code>-exec-finish</code>
* <p>
* Asynchronous command. Resumes the execution of the inferior program
* until the current function is exited. Displays the results returned by
* the function.
* </p>
* <p>
* The <code>-exec-finish</code> command operates on the selected stack
* frame. Therefore the constructor requires a stack frame context.
* </p>
*
*/
public class MIExecFinish extends MICommand<MIInfo>
{
public MIExecFinish(IFrameDMContext dmc) {
super(dmc, "-exec-finish"); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson AB - Modified for Execution Contexts
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-interrupt
*
* Asynchronous command. Interrupts the background execution of the
* target. Note how the token associated with the stop message is the one
* for the execution command that has been interrupted. The token for the
* interrupt itself only appears in the `^done' output. If the user is
* trying to interrupt a non-running program, an error message will be
* printed.
*
*/
public class MIExecInterrupt extends MICommand<MIInfo>
{
public MIExecInterrupt(IExecutionDMContext dmc) {
super(dmc, "-exec-interrupt"); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for handling of execution contexts
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-next
*
* Asynchronous command. Resumes execution of the inferior program,
* stopping when the beginning of the next source line is reached.
*
*/
public class MIExecNext extends MICommand<MIInfo>
{
public MIExecNext(IExecutionDMContext dmc) {
super(dmc, "-exec-next"); //$NON-NLS-1$
}
public MIExecNext(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-next", new String[] { Integer.toString(count) }); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,37 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-next-instruction
*
* Asynchronous command. Executes one machine instruction. If the
* instruction is a function call continues until the function returns. If
* the program stops at an instruction in the middle of a source line, the
* address will be printed as well.
*
*/
public class MIExecNextInstruction extends MICommand<MIInfo>
{
public MIExecNextInstruction(IExecutionDMContext dmc) {
super(dmc, "-exec-next-instruction"); //$NON-NLS-1$
}
public MIExecNextInstruction(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-next-instruction", new String[] { Integer.toString(count) }); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,42 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* <code>-exec-return</code>
*
* <p>
* Makes current function return immediately. Doesn't execute the
* inferior. Displays the new current frame.
* </p>
* <p>
* The <code>-exec-return</code> command operates on the selected stack
* frame. Therefore the constructor requires a stack frame context.
* </p>
*
*/
public class MIExecReturn extends MICommand<MIInfo>
{
public MIExecReturn(IFrameDMContext dmc) {
super(dmc, "-exec-return"); //$NON-NLS-1$
}
public MIExecReturn(IFrameDMContext dmc, String arg) {
super(dmc, "-exec-return", new String[] { arg }); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,37 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for handling of execution contexts
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-run
*
* Asynchronous command. Starts execution of the inferior from the
* beginning. The inferior executes until either a breakpoint is
* encountered or the program exits.
*
*/
public class MIExecRun extends MICommand<MIInfo>
{
public MIExecRun(IExecutionDMContext dmc) {
super(dmc, "-exec-run"); //$NON-NLS-1$
}
public MIExecRun(IExecutionDMContext dmc, String[] args) {
super(dmc, "-exec-run", args); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for handling of execution contexts
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-step
*
* Asynchronous command. Resumes execution of the inferior program,
* stopping when the beginning of the next source line is reached, if the
* next source line is not a function call. If it is, stop at the first
* instruction of the called function.
*
*/
public class MIExecStep extends MICommand<MIInfo>
{
public MIExecStep(IExecutionDMContext dmc) {
super(dmc, "-exec-step"); //$NON-NLS-1$
}
public MIExecStep(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-step", new String[] { Integer.toString(count) }); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-step-instruction
* Asynchronous command. Resumes the inferior which executes one
* machine instruction. The output, once GDB has stopped, will vary
* depending on whether we have stopped in the middle of a source line or
* not. In the former case, the address at which the program stopped will
* be printed as well.
*
*/
public class MIExecStepInstruction extends MICommand<MIInfo>
{
public MIExecStepInstruction(IExecutionDMContext dmc) {
super(dmc, "-exec-step-instruction"); //$NON-NLS-1$
}
public MIExecStepInstruction(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-step-instruction", new String[] { Integer.toString(count) }); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for handling of execution contexts
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-until [ LOCATION ]
*
* Asynchronous command. Executes the inferior until the LOCATION
* specified in the argument is reached. If there is no argument, the
* inferior executes until a source line greater than the current one is
* reached. The reason for stopping in this case will be
* `location-reached'.
*
*/
public class MIExecUntil extends MICommand<MIInfo>
{
public MIExecUntil(IExecutionDMContext dmc) {
super(dmc, "-exec-until"); //$NON-NLS-1$
}
public MIExecUntil(IExecutionDMContext dmc, String loc) {
super(dmc, "-exec-until", new String[]{loc}); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,30 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -gdb-exit
*
* Exit GDB immediately.
*
*/
public class MIGDBExit extends MICommand<MIInfo>
{
public MIGDBExit(IDMContext ctx) {
super(ctx, "-gdb-exit"); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,37 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.mi.service.command.MIControlDMContext;
import org.eclipse.dd.mi.service.command.output.MIGDBShowExitCodeInfo;
import org.eclipse.dd.mi.service.command.output.MIOutput;
/**
*
*-data-evaluate-expression $_exitcode
* ^done,value="10"
*
* Show the current value of a $_exitcode
*
*/
public class MIGDBShowExitCode extends MIDataEvaluateExpression<MIGDBShowExitCodeInfo> {
public MIGDBShowExitCode(MIControlDMContext ctx) {
super(ctx, "$_exitcode"); //$NON-NLS-1$
}
@Override
public MIGDBShowExitCodeInfo getResult(MIOutput output) {
return new MIGDBShowExitCodeInfo(output);
}
}

View file

@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for additional features in DSF Reference implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
* MIInterpreterExec
*
* -interpreter-exec
*
* -interpreter-exec interpreter command
*
* Execute the specified command in the given interpreter.
*
* -interpreter-exec console "break main"
* &"During symbol reading, couldn't parse type; debugger out of date?.\n"
* &"During symbol reading, bad structure-type format.\n"
* ~"Breakpoint 1 at 0x8074fc6: file ../../src/gdb/main.c, line 743.\n"
* ^done
*
*/
public class MIInterpreterExec<V extends MIInfo> extends MICommand<V> {
/**
* @param oper
*/
public MIInterpreterExec(IDMContext ctx, String interpreter, String cmd) {
super(ctx, "-interpreter-exec", new String[]{interpreter}, new String[] {cmd}); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for additional features in DSF Reference implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
* MIInterpreterExecConsole
*/
public class MIInterpreterExecConsole<V extends MIInfo> extends MIInterpreterExec<V> {
/**
* @param interpreter
* @param cmd
*/
public MIInterpreterExecConsole(IDMContext ctx, String cmd) {
super(ctx, "console", cmd); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2007 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 Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIStackInfoDepthInfo;
/**
*
* -stack-info-depth [maxDepth]
*
*
*/
public class MIStackInfoDepth extends MICommand<MIStackInfoDepthInfo>
{
public MIStackInfoDepth(IMIExecutionDMContext ctx) {
super(ctx, "-stack-info-depth"); //$NON-NLS-1$
}
public MIStackInfoDepth(IMIExecutionDMContext ctx, int maxDepth) {
super(ctx, "-stack-info-depth", new String[]{Integer.toString(maxDepth)}); //$NON-NLS-1$
}
@Override
public MIStackInfoDepthInfo getResult(MIOutput out) {
return new MIStackInfoDepthInfo(out);
}
}

View file

@ -0,0 +1,72 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for handling of execution contexts
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIStackListArgumentsInfo;
/**
*
* -stack-list-arguments SHOW-VALUES
* [ LOW-FRAME HIGH-FRAME ]
*
* Display a list of the arguments for the frames between LOW-FRAME and
* HIGH-FRAME (inclusive). If LOW-FRAME and HIGH-FRAME are not provided,
* list the arguments for the whole call stack.
*
* The SHOW-VALUES argument must have a value of 0 or 1. A value of 0
* means that only the names of the arguments are listed, a value of 1
* means that both names and values of the arguments are printed.
*
*/
public class MIStackListArguments extends MICommand<MIStackListArgumentsInfo>
{
public MIStackListArguments(IMIExecutionDMContext execDmc, boolean showValues) {
super(execDmc, "-stack-list-arguments"); //$NON-NLS-1$
if (showValues) {
setParameters(new String[]{"1"}); //$NON-NLS-1$
} else {
setParameters(new String[]{"0"}); //$NON-NLS-1$
}
}
public MIStackListArguments(IFrameDMContext frameDmc, boolean showValues) {
super(frameDmc, "-stack-list-arguments"); //$NON-NLS-1$
if (showValues) {
setParameters(new String[]{"1"}); //$NON-NLS-1$
} else {
setParameters(new String[]{"0"}); //$NON-NLS-1$
}
}
public MIStackListArguments(IMIExecutionDMContext execDmc, boolean showValues, int low, int high) {
super(execDmc, "-stack-list-arguments"); //$NON-NLS-1$
String[] params = new String[3];
if (showValues) {
params[0] = "1"; //$NON-NLS-1$
} else {
params[0] = "0"; //$NON-NLS-1$
}
params[1] = Integer.toString(low);
params[2] = Integer.toString(high);
setParameters(params);
}
@Override
public MIStackListArgumentsInfo getResult(MIOutput out) {
return new MIStackListArgumentsInfo(out);
}
}

View file

@ -0,0 +1,69 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for handling of Frame contexts
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIStackListFramesInfo;
/**
*
* -stack-list-frames [ LOW-FRAME HIGH-FRAME ]
*
* List the frames currently on the stack. For each frame it displays
* the following info:
*
* `LEVEL'
* The frame number, 0 being the topmost frame, i.e. the innermost
* function.
*
* `ADDR'
* The `$pc' value for that frame.
*
* `FUNC'
* Function name.
*
* `FILE'
* File name of the source file where the function lives.
*
* `FULLNAME'
* Absolute file name of the source file where the function lives.
* @since gdb 6.4
*
* `LINE'
* Line number corresponding to the `$pc'.
*
* If invoked without arguments, this command prints a backtrace for the
* whole stack. If given two integer arguments, it shows the frames whose
* levels are between the two arguments (inclusive). If the two arguments
* are equal, it shows the single frame at the corresponding level.
*
*/
public class MIStackListFrames extends MICommand<MIStackListFramesInfo>
{
public MIStackListFrames(IMIExecutionDMContext execDmc) {
super(execDmc, "-stack-list-frames"); //$NON-NLS-1$
}
public MIStackListFrames(IMIExecutionDMContext execDmc, int low, int high) {
super(execDmc, "-stack-list-frames", new String[]{Integer.toString(low), //$NON-NLS-1$
Integer.toString(high)});
}
@Override
public MIStackListFramesInfo getResult(MIOutput out) {
return new MIStackListFramesInfo(out);
}
}

View file

@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for additional features in DSF Reference implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIStackListLocalsInfo;
/**
*
* -stack-list-locals PRINT-VALUES
*
* Display the local variable names for the current frame. With an
* argument of 0 prints only the names of the variables, with argument of 1
* prints also their values.
*
*/
public class MIStackListLocals extends MICommand<MIStackListLocalsInfo>
{
public MIStackListLocals(IFrameDMContext frameCtx, boolean printValues) {
super(frameCtx, "-stack-list-locals"); //$NON-NLS-1$
if (printValues) {
setParameters(new String[]{"1"}); //$NON-NLS-1$
} else {
setParameters(new String[]{"0"}); //$NON-NLS-1$
}
}
@Override
public MIStackListLocalsInfo getResult(MIOutput out) {
return new MIStackListLocalsInfo(out);
}
}

View file

@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2000, 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
* Ericsson - Modified for additional features in DSF Reference implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -stack-select-frame FRAMENUM
*
* Change the current frame. Select a different frame FRAMENUM on the
* stack.
*
*/
public class MIStackSelectFrame extends MICommand<MIInfo> {
public MIStackSelectFrame(IDMContext ctx, int frameNum) {
super(ctx, "-stack-select-frame", new String[]{Integer.toString(frameNum)}, new String[0]); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,37 @@
/*******************************************************************************
* Copyright (c) 2000, 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
* Ericsson - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIThreadListIdsInfo;
/**
*
* -thread-list-ids
*
* Produces a list of the currently known GDB thread ids. At the end
* of the list it also prints the total number of such threads.
*
*/
public class MIThreadListIds extends MICommand<MIThreadListIdsInfo> {
public MIThreadListIds(IContainerDMContext contDmc) {
super(contDmc, "-thread-list-ids"); //$NON-NLS-1$
}
@Override
public MIThreadListIdsInfo getResult(MIOutput out) {
return new MIThreadListIdsInfo(out);
}
}

View file

@ -0,0 +1,35 @@
/*******************************************************************************
* Copyright (c) 2000, 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
* Ericsson AB - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -thread-select THREADNUM
*
* Make THREADNUM the current thread. It prints the number of the new
* current thread, and the topmost frame for that thread.
*
*/
public class MIThreadSelect extends MICommand<MIInfo>
{
public MIThreadSelect(IDMContext ctx, int threadNum) {
super(ctx, "-thread-select", new String[]{Integer.toString(threadNum)}); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2000, 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.mi.service.command.commands;
import org.eclipse.dd.mi.service.command.MIControlDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIVarAssignInfo;
/**
*
* -var-assign NAME EXPRESSION
*
* Assigns the value of EXPRESSION to the variable object specified by
* NAME. The object must be `editable'.
*
*/
public class MIVarAssign extends MICommand<MIVarAssignInfo>
{
public MIVarAssign(MIControlDMContext ctx, String name, String expression) {
super(ctx, "-var-assign", new String[]{name, expression}); //$NON-NLS-1$
}
@Override
public MIVarAssignInfo getResult(MIOutput out) {
return new MIVarAssignInfo(out);
}
}

View file

@ -0,0 +1,68 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for handling of contexts
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIVarCreateInfo;
/**
*
* -var-create {NAME | "-"}
* {FRAME-ADDR | "*"} EXPRESSION
*
* This operation creates a variable object, which allows the
* monitoring of a variable, the result of an expression, a memory cell or
* a CPU register.
*
* The NAME parameter is the string by which the object can be
* referenced. It must be unique. If `-' is specified, the varobj system
* will generate a string "varNNNNNN" automatically. It will be unique
* provided that one does not specify NAME on that format. The command
* fails if a duplicate name is found.
*
* The frame under which the expression should be evaluated can be
* specified by FRAME-ADDR. A `*' indicates that the current frame should
* be used.
*
* EXPRESSION is any expression valid on the current language set (must
* not begin with a `*'), or one of the following:
*
* * `*ADDR', where ADDR is the address of a memory cell
*
* * `*ADDR-ADDR' -- a memory address range (TBD)
*
* * `$REGNAME' -- a CPU register name
*
*/
public class MIVarCreate extends MICommand<MIVarCreateInfo>
{
public MIVarCreate(IExpressionDMContext dmc, String expression) {
this(dmc, "-", "*", expression); //$NON-NLS-1$ //$NON-NLS-2$
}
public MIVarCreate(IExpressionDMContext dmc,String name, String expression) {
this(dmc, name, "*", expression); //$NON-NLS-1$
}
public MIVarCreate(IExpressionDMContext dmc, String name, String frameAddr, String expression) {
super(dmc, "-var-create", new String[]{name, frameAddr, expression}); //$NON-NLS-1$
}
@Override
public MIVarCreateInfo getResult(MIOutput out) {
return new MIVarCreateInfo(out);
}
}

View file

@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.mi.service.command.MIControlDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIVarDeleteInfo;
/**
*
* -var-delete NAME
*
* Deletes a previously created variable object and all of its children.
*
* Returns an error if the object NAME is not found.
*
*/
public class MIVarDelete extends MICommand<MIVarDeleteInfo>
{
public MIVarDelete(MIControlDMContext dmc, String name) {
super(dmc, "-var-delete", new String[]{name}); //$NON-NLS-1$
}
@Override
public MIVarDeleteInfo getResult(MIOutput out) {
return new MIVarDeleteInfo(out);
}
}

View file

@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2000, 2007 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
* Wind River Systems - Modified for new DSF Reference Implementation
* Ericsson - Modified for handling of frame contexts
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.mi.service.command.MIControlDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIVarEvaluateExpressionInfo;
/**
*
* -var-evaluate-expression NAME
*
* Evaluates the expression that is represented by the specified
* variable object and returns its value as a string in the current format
* specified for the object:
*
* value=VALUE
*
*/
public class MIVarEvaluateExpression extends MICommand<MIVarEvaluateExpressionInfo> {
public MIVarEvaluateExpression(MIControlDMContext dmc, String name) {
super(dmc, "-var-evaluate-expression", new String[] { name }); //$NON-NLS-1$
}
@Override
public MIVarEvaluateExpressionInfo getResult(MIOutput out) {
return new MIVarEvaluateExpressionInfo(out);
}
}

View file

@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2000, 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.mi.service.command.commands;
import org.eclipse.dd.mi.service.command.MIControlDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIVarInfoExpressionInfo;
/**
*
* -var-info-expression NAME
*
* Returns what is represented by the variable object NAME:
*
* lang=LANG-SPEC,exp=EXPRESSION
*
* where LANG-SPEC is `{"C" | "C++" | "Java"}'.
*
*/
//MIVarInfoExpression.java
public class MIVarInfoExpression extends MICommand<MIVarInfoExpressionInfo>
{
public MIVarInfoExpression(MIControlDMContext ctx, String name) {
super(ctx, "-var-info-expression", new String[]{name}); //$NON-NLS-1$
}
@Override
public MIVarInfoExpressionInfo getResult(MIOutput out) {
return new MIVarInfoExpressionInfo(out);
}
}

View file

@ -0,0 +1,37 @@
/*******************************************************************************
* Copyright (c) 2000, 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.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIVarInfoNumChildrenInfo;
/**
*
* -var-info-num-children NAME
*
* Returns the number of children of a variable object NAME:
*
* numchild=N
*
*/
public class MIVarInfoNumChildren extends MICommand<MIVarInfoNumChildrenInfo>
{
public MIVarInfoNumChildren(IExpressionDMContext ctx, String name) {
super(ctx, "-var-info-num-children", new String[]{name}); //$NON-NLS-1$
}
@Override
public MIVarInfoNumChildrenInfo getResult(MIOutput out) {
return new MIVarInfoNumChildrenInfo(out);
}
}

Some files were not shown because too many files have changed in this diff Show more