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

Bug 239028

This change adds support for multli-process debugging although we are still using the single-process GDB.
With this fix, our debug session will now be in a multi-process situation, with only one process being debugged.  At this point, there should be no visible changes in the debugging experience.
This commit is contained in:
Marc Khouzam 2008-07-23 17:49:01 +00:00
parent 593106d158
commit c1f6612245
16 changed files with 936 additions and 439 deletions

View file

@ -20,16 +20,17 @@ import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.datamodel.IDMEvent;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.AbstractContainerVMNode;
import org.eclipse.dd.dsf.debug.service.IProcesses;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IProcesses.IProcessDMContext;
import org.eclipse.dd.dsf.debug.service.IProcesses.IThreadDMData;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.ui.concurrent.ViewerDataRequestMonitor;
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl;
import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl.IGDBProcessData;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControlDMContext;
import org.eclipse.dd.mi.service.command.MIInferiorProcess;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider;
@ -55,53 +56,72 @@ public class ContainerVMNode extends AbstractContainerVMNode
}
@Override
protected void updateElementsInSessionThread(IChildrenUpdate update) {
GDBControl controlService = getServicesTracker().getService(GDBControl.class);
if ( controlService == null ) {
handleFailedUpdate(update);
return;
}
MIInferiorProcess inferiorProcess = controlService.getInferiorProcess();
if (inferiorProcess != null && inferiorProcess.getState() != MIInferiorProcess.State.TERMINATED) {
update.setChild(createVMContext(inferiorProcess.getExecutionContext()), 0);
}
update.done();
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
IProcesses processService = getServicesTracker().getService(IProcesses.class);
GDBControl controlService = getServicesTracker().getService(GDBControl.class);
if (processService == null || controlService == null) {
handleFailedUpdate(update);
return;
}
processService.getProcessesBeingDebugged(
controlService.getGDBDMContext(),
new ViewerDataRequestMonitor<IDMContext[]>(getExecutor(), update) {
@Override
public void handleCompleted() {
if (!isSuccess()) {
handleFailedUpdate(update);
return;
}
fillUpdateWithVMCs(update, getData());
update.done();
}
});
}
@Override
@Override
protected void updateLabelInSessionThread(final ILabelUpdate update) {
final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl == null ) {
handleFailedUpdate(update);
return;
}
final GDBControlDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), GDBControlDMContext.class);
IProcesses processService = getServicesTracker().getService(IProcesses.class);
IRunControl runControl = getServicesTracker().getService(IRunControl.class);
if (processService == null) {
handleFailedUpdate(update);
return;
}
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 ViewerDataRequestMonitor<IGDBProcessData>(getExecutor(), update) {
@Override
public void handleCompleted() {
if (!isSuccess()) {
update.done();
return;
}
update.setLabel(getData().getName(), 0);
update.done();
}
});
}
final IProcessDMContext procDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IProcessDMContext.class);
final IContainerDMContext contDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IContainerDMContext.class);
String imageKey = null;
if (runControl.isSuspended(contDmc)) {
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED;
} else {
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING;
}
update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0);
processService.getExecutionData(
procDmc,
new ViewerDataRequestMonitor<IThreadDMData>(getExecutor(), update) {
@Override
public void handleCompleted() {
if (!isSuccess()) {
update.setLabel("<unavailable>", 0); //$NON-NLS-1$
update.done();
return;
}
// Create Labels of type Name[PID] if the pid is available
final StringBuilder builder = new StringBuilder();
builder.append(getData().getName());
if (getData().getId() != null && getData().getId().length() > 0) {
builder.append("[" + getData().getId()+ "]"); //$NON-NLS-1$//$NON-NLS-2$
}
update.setLabel(builder.toString(), 0);
update.done();
}
});
}
@Override
public int getDeltaFlags(Object e) {
@ -133,53 +153,55 @@ public class ContainerVMNode extends AbstractContainerVMNode
private final String MEMENTO_NAME = "CONTAINER_MEMENTO_NAME"; //$NON-NLS-1$
public void compareElements(IElementCompareRequest[] requests) {
for ( final IElementCompareRequest request : requests ) {
Object element = request.getElement();
final IMemento memento = request.getMemento();
final String mementoName = memento.getString(MEMENTO_NAME);
if (mementoName != null) {
if (element instanceof IDMVMContext) {
IDMContext dmc = ((IDMVMContext)element).getDMContext();
if ( dmc instanceof GDBControlDMContext )
{
final GDBControlDMContext procDmc = (GDBControlDMContext) dmc;
try {
getSession().getExecutor().execute(new DsfRunnable() {
public void run() {
final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl != null ) {
runControl.getProcessData(
procDmc,
new ViewerDataRequestMonitor<IGDBProcessData>(runControl.getExecutor(), request) {
@Override
protected void handleCompleted() {
if ( getStatus().isOK() ) {
request.setEqual( mementoName.equals( "Container." + getData().getName() ) ); //$NON-NLS-1$
}
request.done();
}
});
}
else {
request.done();
}
}
});
} catch (RejectedExecutionException e) {
request.done();
}
for (final IElementCompareRequest request : requests) {
continue;
}
}
}
request.done();
}
Object element = request.getElement();
final IMemento memento = request.getMemento();
final String mementoName = memento.getString(MEMENTO_NAME);
if (mementoName != null) {
if (element instanceof IDMVMContext) {
IDMContext dmc = ((IDMVMContext)element).getDMContext();
if (dmc instanceof IContainerDMContext)
{
final IProcessDMContext procDmc = findDmcInPath(request.getViewerInput(), request.getElementPath(), IProcessDMContext.class);
if (procDmc != null) {
try {
getSession().getExecutor().execute(new DsfRunnable() {
public void run() {
final IProcesses processService = getServicesTracker().getService(IProcesses.class);
if (processService != null) {
processService.getExecutionData(
procDmc,
new ViewerDataRequestMonitor<IThreadDMData>(processService.getExecutor(), request) {
@Override
protected void handleCompleted() {
if ( getStatus().isOK() ) {
memento.putString(MEMENTO_NAME, "Container." + getData().getName() + getData().getId()); //$NON-NLS-1$
}
request.done();
}
});
}
else {
request.done();
}
}
});
} catch (RejectedExecutionException e) {
request.done();
}
continue;
}
}
}
}
request.done();
}
}
/*
@ -187,49 +209,50 @@ public class ContainerVMNode extends AbstractContainerVMNode
* @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#encodeElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest[])
*/
public void encodeElements(IElementMementoRequest[] requests) {
for ( final IElementMementoRequest request : requests ) {
Object element = request.getElement();
final IMemento memento = request.getMemento();
if (element instanceof IDMVMContext) {
IDMContext dmc = ((IDMVMContext)element).getDMContext();
if ( dmc instanceof GDBControlDMContext )
{
final GDBControlDMContext procDmc = (GDBControlDMContext) dmc;
try {
getSession().getExecutor().execute(new DsfRunnable() {
public void run() {
final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl != null ) {
runControl.getProcessData(
procDmc,
new ViewerDataRequestMonitor<IGDBProcessData>(runControl.getExecutor(), request) {
@Override
protected void handleCompleted() {
if ( getStatus().isOK() ) {
memento.putString(MEMENTO_NAME, "Container." + getData().getName()); //$NON-NLS-1$
}
request.done();
}
});
}
else {
request.done();
}
}
});
} catch (RejectedExecutionException e) {
request.done();
}
for (final IElementMementoRequest request : requests) {
continue;
}
}
request.done();
}
Object element = request.getElement();
final IMemento memento = request.getMemento();
if (element instanceof IDMVMContext) {
IDMContext dmc = ((IDMVMContext)element).getDMContext();
if (dmc instanceof IContainerDMContext)
{
final IProcessDMContext procDmc = findDmcInPath(request.getViewerInput(), request.getElementPath(), IProcessDMContext.class);
if (procDmc != null) {
try {
getSession().getExecutor().execute(new DsfRunnable() {
public void run() {
final IProcesses processService = getServicesTracker().getService(IProcesses.class);
if (processService != null) {
processService.getExecutionData(
procDmc,
new ViewerDataRequestMonitor<IThreadDMData>(processService.getExecutor(), request) {
@Override
protected void handleCompleted() {
if ( getStatus().isOK() ) {
memento.putString(MEMENTO_NAME, "Container." + getData().getName() + getData().getId()); //$NON-NLS-1$
}
request.done();
}
});
} else {
request.done();
}
}
});
} catch (RejectedExecutionException e) {
request.done();
}
continue;
}
}
}
request.done();
}
}
}

View file

@ -21,120 +21,22 @@ 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.Immutable;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.AbstractDMContext;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IProcesses;
import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.gdb.internal.GdbPlugin;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.SessionType;
import org.eclipse.dd.mi.service.IMIProcessDMContext;
import org.eclipse.dd.mi.service.command.commands.CLIAttach;
import org.eclipse.dd.mi.service.MIProcesses;
import org.eclipse.dd.mi.service.command.commands.CLIMonitorListProcesses;
import org.eclipse.dd.mi.service.command.output.CLIMonitorListProcessesInfo;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.osgi.framework.BundleContext;
public class GDBProcesses extends AbstractDsfService implements IProcesses {
@Immutable
protected class GdbThreadDMC extends AbstractDMContext
implements IThreadDMContext
{
/**
* ID given by the OS.
*/
private final String fOSId;
/**
* Constructor for the context. It should not be called directly by clients.
* Instead clients should call {@link GDBProcesses#createThreadContext}
* to create instances of this context based on the thread ID.
* <p/>
*
* @param sessionId Session that this context belongs to.
* @param processDmc The process that this thread belongs to.
* @param id thread identifier.
*/
protected GdbThreadDMC(String sessionId, IProcessDMContext processDmc, String id) {
super(sessionId, processDmc != null ? new IDMContext[] { processDmc } : new IDMContext[0]);
fOSId = id;
}
/**
* Returns the thread identifier of this context.
* @return
*/
public String getId(){ return fOSId; }
@Override
public String toString() { return baseToString() + ".thread[" + fOSId + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
@Override
public boolean equals(Object obj) {
return super.baseEquals(obj) && ((GdbThreadDMC)obj).fOSId == fOSId;
}
@Override
public int hashCode() { return super.baseHashCode() ^ fOSId.hashCode(); }
}
@Immutable
protected class GdbProcessDMC extends GdbThreadDMC
implements IMIProcessDMContext
{
/**
* Constructor for the context. It should not be called directly by clients.
* Instead clients should call {@link GDBProcesses#createProcessContext}
* to create instances of this context based on the PID.
* <p/>
*
* @param sessionId Session that this context belongs to.
* @param id process identifier.
*/
protected GdbProcessDMC(String sessionId, String id) {
super(sessionId, null, id);
}
public String getProcId() { return getId(); }
@Override
public String toString() { return baseToString() + ".proc[" + getId() + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public int hashCode() { return super.hashCode(); }
}
/*
* The data of a corresponding thread or process.
*/
@Immutable
private static class GdbThreadDMData implements IThreadDMData {
final String fName;
final String fId;
GdbThreadDMData(String name, String id) {
fName = name;
fId = id;
}
public String getId() { return fId; }
public String getName() { return fName; }
public boolean isDebuggerAttached() {
return true;
}
}
public class GDBProcesses extends MIProcesses {
private GDBControl fCommandControl;
private GDBControl fGdb;
// A map of pid to names. It is filled when we get all the
// processes that are running
@ -144,12 +46,6 @@ public class GDBProcesses extends AbstractDsfService implements IProcesses {
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) {
@ -170,23 +66,17 @@ public class GDBProcesses extends AbstractDsfService implements IProcesses {
*/
private void doInitialize(RequestMonitor requestMonitor) {
fGdb = getServicesTracker().getService(GDBControl.class);
// Register this service.
register(new String[] { IProcesses.class.getName(),
MIProcesses.class.getName(),
GDBProcesses.class.getName() },
new Hashtable<String, String>());
fCommandControl = getServicesTracker().getService(GDBControl.class);
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();
@ -201,51 +91,13 @@ public class GDBProcesses extends AbstractDsfService implements IProcesses {
return GdbPlugin.getBundleContext();
}
/**
* Create a thread context.
*
* @param process The parent process context
* @param threadId The OS Id of the thread
*/
public IThreadDMContext createThreadContext(IProcessDMContext process, String threadId) {
return new GdbThreadDMC(getSession().getId(), process, threadId);
}
/**
* Create a process context.
*
* @param pid The OS Id of the process
*/
public IProcessDMContext createProcessContext(String pid) {
return new GdbProcessDMC(getSession().getId(), pid);
}
/**
* This method obtains the model data for a given GdbThreadDMC object
* which can represent a thread or a process.
*
* @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 IThreadDMContext) {
getExecutionData((IThreadDMContext) dmc,
(DataRequestMonitor<IThreadDMData>) rm);
} else {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
}
}
@Override
public void getExecutionData(IThreadDMContext dmc, DataRequestMonitor<IThreadDMData> rm) {
// We must first check for GdbProcessDMC because it is also a GdbThreadDMC
if (dmc instanceof GdbProcessDMC) {
String pidStr = ((GdbProcessDMC)dmc).getId();
int pid = 0;
if (dmc instanceof MIProcessDMC) {
String pidStr = ((MIProcessDMC)dmc).getId();
int pid = -1;
try {
pid = Integer.parseInt(pidStr);
} catch (NumberFormatException e) {
@ -253,85 +105,17 @@ public class GDBProcesses extends AbstractDsfService implements IProcesses {
String name = fProcessNames.get(pid);
// If we don't find the name in our list, return the default name of our program
if (name == null) name = fCommandControl.getExecutablePath().lastSegment();
rm.setData(new GdbThreadDMData(name, pidStr));
rm.done();
} else if (dmc instanceof GdbThreadDMC) {
rm.setData(new GdbThreadDMData("", ((GdbThreadDMC)dmc).getId())); //$NON-NLS-1$
if (name == null) name = fGdb.getExecutablePath().lastSegment();
rm.setData(new MIThreadDMData(name, pidStr));
rm.done();
} else {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
super.getExecutionData(dmc, rm);
}
}
public void getDebuggingContext(IThreadDMContext dmc, DataRequestMonitor<IDMContext> rm) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
public void attachDebuggerToProcess(IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> rm) {
if (procCtx instanceof IMIProcessDMContext) {
fCommandControl.queueCommand(
new CLIAttach((IMIProcessDMContext)procCtx),
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(fCommandControl.getGDBDMContext());
rm.done();
}
});
} else {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
rm.done();
}
}
public void detachDebuggerFromProcess(IProcessDMContext procCtx, final RequestMonitor rm) {
// if (procCtx instanceof GdbProcessDMC) {
// int pid;
// try {
// pid = Integer.parseInt(((GdbProcessDMC)procCtx).getId());
// } catch (NumberFormatException e) {
// rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid process id.", null)); //$NON-NLS-1$
// rm.done();
// return;
// }
//
// fCommandControl.queueCommand(
// new CLIDetach(procCtx, pid),
// new DataRequestMonitor<MIInfo>(getExecutor(), rm));
// } else {
// rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
// rm.done();
// }
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
public void canTerminate(IThreadDMContext thread, DataRequestMonitor<Boolean> rm) {
rm.setData(true);
rm.done();
}
public void debugNewProcess(String file, DataRequestMonitor<IProcessDMContext> rm) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
public void getProcessesBeingDebugged(IDMContext dmc, DataRequestMonitor<IDMContext[]> rm) {
// use -list-thread-groups
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
@Override
public void getRunningProcesses(IDMContext dmc, final DataRequestMonitor<IProcessDMContext[]> rm) {
if (fCommandControl.getSessionType() == SessionType.LOCAL) {
if (fGdb.getSessionType() == SessionType.LOCAL) {
IProcessList list = null;
try {
list = CCorePlugin.getDefault().getProcessList();
@ -352,7 +136,7 @@ public class GDBProcesses extends AbstractDsfService implements IProcesses {
rm.done();
} else {
// monitor list processes is only for remote session
fCommandControl.queueCommand(
fGdb.queueCommand(
new CLIMonitorListProcesses(dmc),
new DataRequestMonitor<CLIMonitorListProcessesInfo>(getExecutor(), rm) {
@Override
@ -376,23 +160,17 @@ public class GDBProcesses extends AbstractDsfService implements IProcesses {
}
private IProcessDMContext[] makeProcessDMCs(IProcessInfo[] processes) {
IProcessDMContext[] procDmcs = new GdbProcessDMC[processes.length];
IProcessDMContext[] procDmcs = new MIProcessDMC[processes.length];
for (int i=0; i<procDmcs.length; i++) {
procDmcs[i] = createProcessContext(Integer.toString(processes[i].getPid()));
}
return procDmcs;
}
public void runNewProcess(String file, DataRequestMonitor<IProcessDMContext> rm) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
public void terminate(IThreadDMContext thread, RequestMonitor rm) {
if (thread instanceof GdbProcessDMC) {
fCommandControl.terminate(rm);
@Override
public void terminate(IThreadDMContext thread, RequestMonitor rm) {
if (thread instanceof MIProcessDMC) {
fGdb.terminate(rm);
} else {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
rm.done();

View file

@ -0,0 +1,395 @@
/*******************************************************************************
* 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;
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.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IProcesses;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
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.CLIAttach;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.osgi.framework.BundleContext;
public class MIProcesses extends AbstractDsfService implements IProcesses {
/*
* Context representing a thread group of GDB/MI.
*/
@Immutable
protected class MIExecutionGroupDMC extends AbstractDMContext
implements IMIExecutionGroupDMContext
{
/**
* String ID that is used to identify the thread group in the GDB/MI protocol.
*/
private final String fId;
/**
* Constructor for the context. It should not be called directly by clients.
* Instead clients should call {@link MIRunControl#createMIExecutionGroupContext
* to create instances of this context based on the group name.
*
* @param sessionId Session that this context belongs to.
* @param containerDmc The container that this context belongs to.
* @param processDmc The process dmc that also is the parent of this context.
* @param groupId GDB/MI thread group identifier.
*/
protected MIExecutionGroupDMC(String sessionId, IContainerDMContext containerDmc,
IProcessDMContext processDmc, String groupId) {
super(sessionId, containerDmc == null && processDmc == null ? new IDMContext[0] :
containerDmc == null ? new IDMContext[] { processDmc } :
processDmc == null ? new IDMContext[] { containerDmc } :
new IDMContext[] { processDmc, containerDmc });
fId = groupId;
}
/**
* Returns the GDB/MI thread group identifier of this context.
*/
public String getGroupId(){ return fId; }
@Override
public String toString() { return baseToString() + ".threadGroup[" + fId + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
@Override
public boolean equals(Object obj) {
return super.baseEquals(obj) && ((MIExecutionGroupDMC)obj).fId == fId;
}
@Override
public int hashCode() { return super.baseHashCode() + fId.hashCode(); }
}
@Immutable
protected class MIThreadDMC extends AbstractDMContext
implements IThreadDMContext
{
/**
* ID given by the OS.
*/
private final String fOSId;
/**
* Constructor for the context. It should not be called directly by clients.
* Instead clients should call {@link MIProcesses#createThreadContext}
* to create instances of this context based on the thread ID.
* <p/>
*
* @param sessionId Session that this context belongs to.
* @param processDmc The process that this thread belongs to.
* @param id thread identifier.
*/
protected MIThreadDMC(String sessionId, IProcessDMContext processDmc, String id) {
super(sessionId, processDmc != null ? new IDMContext[] { processDmc } : new IDMContext[0]);
fOSId = id;
}
/**
* Returns the thread identifier of this context.
* @return
*/
public String getId(){ return fOSId; }
@Override
public String toString() { return baseToString() + ".thread[" + fOSId + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
@Override
public boolean equals(Object obj) {
return super.baseEquals(obj) && ((MIThreadDMC)obj).fOSId == fOSId;
}
@Override
public int hashCode() { return super.baseHashCode() ^ (fOSId == null ? 0 : fOSId.hashCode()); }
}
@Immutable
protected class MIProcessDMC extends MIThreadDMC
implements IMIProcessDMContext
{
/**
* Constructor for the context. It should not be called directly by clients.
* Instead clients should call {@link MIProcesses#createProcessContext}
* to create instances of this context based on the PID.
* <p/>
*
* @param sessionId Session that this context belongs to.
* @param id process identifier.
*/
protected MIProcessDMC(String sessionId, String id) {
super(sessionId, null, id);
}
public String getProcId() { return getId(); }
@Override
public String toString() { return baseToString() + ".proc[" + getId() + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public int hashCode() { return super.hashCode(); }
}
/*
* The data of a corresponding thread or process.
*/
@Immutable
protected static class MIThreadDMData implements IThreadDMData {
final String fName;
final String fId;
public MIThreadDMData(String name, String id) {
fName = name;
fId = id;
}
public String getId() { return fId; }
public String getName() { return fName; }
public boolean isDebuggerAttached() {
return true;
}
}
private ICommandControl fCommandControl;
public MIProcesses(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 handleSuccess() {
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 this service.
// register(new String[] { IProcesses.class.getName(),
// MIProcesses.class.getName() },
// new Hashtable<String, String>());
fCommandControl = getServicesTracker().getService(ICommandControl.class);
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();
super.shutdown(requestMonitor);
}
/**
* @return The bundle context of the plug-in to which this service belongs.
*/
@Override
protected BundleContext getBundleContext() {
return MIPlugin.getBundleContext();
}
/**
* Create a thread context.
*
* @param processDmc The parent process context
* @param threadId The OS Id of the thread
*/
public IThreadDMContext createThreadContext(IProcessDMContext processDmc, String threadId) {
return new MIThreadDMC(getSession().getId(), processDmc, threadId);
}
/**
* Create a process context.
*
* @param pid The OS Id of the process
*/
public IProcessDMContext createProcessContext(String pid) {
return new MIProcessDMC(getSession().getId(), pid);
}
/**
* Create a executionGroup context.
*
* @param containerDmc The parent container context of this context
* @param processDmc The parent process context of this context
* @param groupId The thread group id of the process
*/
public IMIExecutionGroupDMContext createExecutionGroupContext(IContainerDMContext containerDmc,
IProcessDMContext processDmc,
String groupId) {
return new MIExecutionGroupDMC(getSession().getId(), containerDmc, processDmc, groupId);
}
public IMIExecutionGroupDMContext createExecutionGroupContext(IContainerDMContext containerDmc, String groupId) {
return createExecutionGroupContext(containerDmc, createProcessContext(""), groupId); //$NON-NLS-1$
}
/**
* This method obtains the model data for a given GdbThreadDMC object
* which can represent a thread or a process.
*
* @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 IThreadDMContext) {
getExecutionData((IThreadDMContext) dmc,
(DataRequestMonitor<IThreadDMData>) rm);
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
}
}
public void getExecutionData(IThreadDMContext dmc, DataRequestMonitor<IThreadDMData> rm) {
// We must first do the if check for MIProcessDMC because it is also a GMIThreadDMC
if (dmc instanceof MIProcessDMC) {
rm.setData(new MIThreadDMData("", ((MIProcessDMC)dmc).getId())); //$NON-NLS-1$
rm.done();
} else if (dmc instanceof MIThreadDMC) {
rm.setData(new MIThreadDMData("", ((MIThreadDMC)dmc).getId())); //$NON-NLS-1$
rm.done();
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
}
}
public void getDebuggingContext(IThreadDMContext dmc, DataRequestMonitor<IDMContext> rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
public void attachDebuggerToProcess(IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> rm) {
if (procCtx instanceof IMIProcessDMContext) {
fCommandControl.queueCommand(
new CLIAttach((IMIProcessDMContext)procCtx),
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(null);
rm.done();
}
});
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
rm.done();
}
}
public void detachDebuggerFromProcess(IProcessDMContext procCtx, final RequestMonitor rm) {
// if (procCtx instanceof MIProcessDMC) {
// int pid;
// try {
// pid = Integer.parseInt(((MIProcessDMC)procCtx).getId());
// } catch (NumberFormatException e) {
// rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid process id.", null)); //$NON-NLS-1$
// rm.done();
// return;
// }
//
// // The service version cannot use -target-detach because it didn't exist
// // in versions of GDB up to and including GDB 6.8
// fCommandControl.queueCommand(
// new CLIDetach(procCtx, pid),
// new DataRequestMonitor<MIInfo>(getExecutor(), rm));
// } else {
// rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
// rm.done();
// }
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
public void canTerminate(IThreadDMContext thread, DataRequestMonitor<Boolean> rm) {
rm.setData(true);
rm.done();
}
public void debugNewProcess(String file, DataRequestMonitor<IProcessDMContext> rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
public void getProcessesBeingDebugged(IDMContext dmc, DataRequestMonitor<IDMContext[]> rm) {
// This service version only handles a single process to debug, therefore, we can simply
// create the context describing this process ourselves. This context's content is not
// used since it is the only context of its kind (only one process to debug) and can be recognized that way.
IContainerDMContext parentDmc = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class);
IContainerDMContext containerDmc = createExecutionGroupContext(parentDmc, createProcessContext(""), "");//$NON-NLS-1$//$NON-NLS-2$
rm.setData(new IContainerDMContext[] {containerDmc});
rm.done();
}
public void getRunningProcesses(IDMContext dmc, final DataRequestMonitor<IProcessDMContext[]> rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
public void runNewProcess(String file, DataRequestMonitor<IProcessDMContext> rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
public void terminate(IThreadDMContext thread, RequestMonitor rm) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
}

View file

@ -28,6 +28,9 @@ 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.ICommandToken;
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.MIProcesses;
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;
@ -57,10 +60,13 @@ public class CLIEventProcessor
// Last Thread ID created
private static int fLastThreadId;
private final DsfServicesTracker fServicesTracker;
public CLIEventProcessor(AbstractMIControl connection, IContainerDMContext containerDmc, MIInferiorProcess inferior) {
fCommandControl = connection;
fInferior = inferior;
fContainerDmc = containerDmc;
fServicesTracker = new DsfServicesTracker(MIPlugin.getBundleContext(), fCommandControl.getSession().getId());
connection.addCommandListener(this);
connection.addEventListener(this);
// Re-set the counter
@ -69,7 +75,8 @@ public class CLIEventProcessor
public void dispose() {
fCommandControl.removeCommandListener(this);
fCommandControl.removeEventListener(this);
fCommandControl.removeEventListener(this);
fServicesTracker.dispose();
}
public void resetInferior(MIInferiorProcess inferior) {
@ -115,9 +122,16 @@ public class CLIEventProcessor
Pattern pattern = Pattern.compile("(^\\[New Thread.*LWP\\s*)(\\d*)", Pattern.MULTILINE); //$NON-NLS-1$
Matcher matcher = pattern.matcher(exec.getCString());
if (matcher.find()) {
MIEvent<?> e = new MIThreadCreatedEvent(fContainerDmc, ++fLastThreadId);
MIProcesses procService = fServicesTracker.getService(MIProcesses.class);
IContainerDMContext processContainerDmc = procService.createExecutionGroupContext(fContainerDmc, ""); //$NON-NLS-1$
MIEvent<?> e = new MIThreadCreatedEvent(processContainerDmc, ++fLastThreadId);
fCommandControl.getSession().dispatchEvent(e, fCommandControl.getProperties());
}
// 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.
}
}
@ -130,8 +144,10 @@ public class CLIEventProcessor
if (fInferior != null && "error".equals(state)) { //$NON-NLS-1$
if (fInferior.getState() == MIInferiorProcess.State.RUNNING) {
fInferior.setState(MIInferiorProcess.State.STOPPED);
MIProcesses procService = fServicesTracker.getService(MIProcesses.class);
IContainerDMContext processContainerDmc = procService.createExecutionGroupContext(fContainerDmc, ""); //$NON-NLS-1$
fCommandControl.getSession().dispatchEvent(
MIErrorEvent.parse(fContainerDmc, rr.getToken(), rr.getMIResults(), null),
MIErrorEvent.parse(processContainerDmc, rr.getToken(), rr.getMIResults(), null),
fCommandControl.getProperties());
}
}
@ -171,7 +187,9 @@ public class CLIEventProcessor
int type = getSteppingOperationKind(operation);
if (type != -1) {
// if it was a step instruction set state running
MIEvent<?> event = new MIRunningEvent(fContainerDmc, token, type);
MIProcesses procService = fServicesTracker.getService(MIProcesses.class);
IContainerDMContext processContainerDmc = procService.createExecutionGroupContext(fContainerDmc, ""); //$NON-NLS-1$
MIEvent<?> event = new MIRunningEvent(processContainerDmc, token, type);
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
}

View file

@ -15,6 +15,7 @@ import java.util.LinkedList;
import java.util.List;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
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;
@ -22,8 +23,8 @@ import org.eclipse.dd.dsf.debug.service.command.ICommandToken;
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.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.MIProcesses;
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;
@ -64,7 +65,10 @@ import org.eclipse.dd.mi.service.command.output.MIValue;
public class MIRunControlEventProcessor
implements IEventListener, ICommandListener
{
/**
private static final String STOPPED_REASON = "stopped"; //$NON-NLS-1$
private static final String RUNNING_REASON = "running"; //$NON-NLS-1$
/**
* The connection service that this event processor is registered with.
*/
private final AbstractMIControl fCommandControl;
@ -75,9 +79,6 @@ public class MIRunControlEventProcessor
*/
private final IContainerDMContext fContainerDmc;
/**
* Services tracker used to retrieve the MIRunControl service.
*/
private final DsfServicesTracker fServicesTracker;
/**
@ -105,7 +106,6 @@ public class MIRunControlEventProcessor
public void eventReceived(Object output) {
for (MIOOBRecord oobr : ((MIOutput)output).getMIOOBRecords()) {
List<MIEvent<?>> events = new LinkedList<MIEvent<?>>();
if (oobr instanceof MIExecAsyncOutput) {
MIExecAsyncOutput exec = (MIExecAsyncOutput) oobr;
// Change of state.
@ -116,73 +116,103 @@ public class MIRunControlEventProcessor
fCommandControl.resetCurrentThreadLevel();
fCommandControl.resetCurrentStackLevel();
String threadId = null;
// For now, since GDB does not support thread-groups, fake an empty one
String groupId = "";//null; //$NON-NLS-1$
// I'm putting support for multiple reasons because it was
// there before, but I'm not sure this can actually happen
List<String> reasons = new LinkedList<String>();
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;
}
reasons.add(((MIConst) val).getString());
}
} else if (var.equals("thread-id")) { //$NON-NLS-1$
if (val instanceof MIConst) {
threadId = ((MIConst)val).getString();
}
} else if (var.equals("group-id")) { //$NON-NLS-1$
if (val instanceof MIConst) {
groupId = ((MIConst)val).getString();
}
}
}
// 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(IMIRunControl.class), fContainerDmc, exec.getToken(), exec.getMIResults());
events.add(e);
}
for (MIEvent<?> event : events) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
// We were stopped for some unknown reason, for example
// GDB for temporary breakpoints will not send the
// "reason" ??? still fire a stopped event.
if (reasons.isEmpty()) {
reasons.add(STOPPED_REASON);
}
for (String reason : reasons) {
MIEvent<?> event = createEvent(reason, exec, threadId, groupId);
if (event != null) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
}
}
else if ("running".equals(state)) { //$NON-NLS-1$
int token = exec.getToken();
String threadId = null;
// For now, since GDB does not support thread-groups, fake an empty one
String groupId = "";//null; //$NON-NLS-1$
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("thread-id")) { //$NON-NLS-1$
if (val instanceof MIConst) {
String thread = ((MIConst) val).getString();
MIEvent<?> evt = null;
int threadId = 0;
try {
threadId = Integer.parseInt(thread);
IMIExecutionDMContext context = fServicesTracker.getService(IMIRunControl.class).createMIExecutionContext(fContainerDmc, threadId);
evt = new MIRunningEvent(context, token, MIRunningEvent.CONTINUE);
}
catch (NumberFormatException e) {
evt = new MIRunningEvent(fContainerDmc, token, MIRunningEvent.CONTINUE);
}
fCommandControl.getSession().dispatchEvent(evt, fCommandControl.getProperties());
threadId = ((MIConst) val).getString();
}
} else if (var.equals("group-id")) { //$NON-NLS-1$
if (val instanceof MIConst) {
groupId = ((MIConst)val).getString();
}
}
}
}
}
else if (oobr instanceof MINotifyAsyncOutput) {
MIEvent<?> event = createEvent(RUNNING_REASON, exec, threadId, groupId);
if (event != null) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
}
} else if (oobr instanceof MINotifyAsyncOutput) {
// Parse the string and dispatch the corresponding event
MINotifyAsyncOutput exec = (MINotifyAsyncOutput) oobr;
String miEvent = exec.getAsyncClass();
if ("thread-created".equals(miEvent)) { //$NON-NLS-1$
MIEvent<?> event = MIThreadCreatedEvent.parse(fContainerDmc, exec.getToken(), exec.getMIResults());
if (event != null) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
if ("thread-created".equals(miEvent) || "thread-exited".equals(miEvent)) { //$NON-NLS-1$ //$NON-NLS-2$
// For now, since GDB does not support thread-groups, fake an empty one
String groupId = "";//null; //$NON-NLS-1$
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("group-id")) { //$NON-NLS-1$
if (val instanceof MIConst) {
groupId = ((MIConst) val).getString();
}
}
}
}
else if ("thread-exited".equals(miEvent)) { //$NON-NLS-1$
MIEvent<?> event = MIThreadExitEvent.parse(fContainerDmc, exec.getToken(), exec.getMIResults());
MIProcesses procService = fServicesTracker.getService(MIProcesses.class);
IContainerDMContext processContainerDmc = fContainerDmc;
if (procService != null && groupId != null) {
processContainerDmc = procService.createExecutionGroupContext(fContainerDmc, groupId);
}
MIEvent<?> event = null;
if ("thread-created".equals(miEvent)) { //$NON-NLS-1$
event = MIThreadCreatedEvent.parse(processContainerDmc, exec.getToken(), exec.getMIResults());
} else if ("thread-exited".equals(miEvent)) { //$NON-NLS-1$
event = MIThreadExitEvent.parse(processContainerDmc, exec.getToken(), exec.getMIResults());
}
if (event != null) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
@ -191,6 +221,7 @@ public class MIRunControlEventProcessor
}
}
@Deprecated
protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec) {
IMIRunControl runControl = fServicesTracker.getService(IMIRunControl.class);
MIEvent<?> event = null;
@ -218,6 +249,58 @@ public class MIRunControlEventProcessor
}
return event;
}
protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec, String threadId, String groupId) {
IMIRunControl runControl = fServicesTracker.getService(IMIRunControl.class);
MIProcesses procService = fServicesTracker.getService(MIProcesses.class);
IExecutionDMContext execDmc = fContainerDmc;
if (procService != null && groupId != null) {
IContainerDMContext processContainerDmc = procService.createExecutionGroupContext(fContainerDmc, groupId);
execDmc = processContainerDmc;
if (runControl != null && threadId != null) {
int threadIdInt = -1;
try {
threadIdInt = Integer.parseInt(threadId);
} catch (NumberFormatException e) {
}
if (threadIdInt != -1) {
execDmc = runControl.createMIExecutionContext(processContainerDmc, threadIdInt);
}
}
}
MIEvent<?> event = null;
if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$
event = MIBreakpointHitEvent.parse(execDmc, 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(execDmc, exec.getToken(), exec.getMIResults());
} else if ("watchpoint-scope".equals(reason)) { //$NON-NLS-1$
event = MIWatchpointScopeEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
} else if ("end-stepping-range".equals(reason)) { //$NON-NLS-1$
event = MISteppingRangeEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
} else if ("signal-received".equals(reason)) { //$NON-NLS-1$
event = MISignalEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
} else if ("location-reached".equals(reason)) { //$NON-NLS-1$
event = MILocationReachedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
} else if ("function-finished".equals(reason)) { //$NON-NLS-1$
event = MIFunctionFinishedEvent.parse(execDmc, 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());
} else if (STOPPED_REASON.equals(reason)) {
event = MIStoppedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
} else if (RUNNING_REASON.equals(reason)) {
event = new MIRunningEvent(execDmc, exec.getToken(), MIRunningEvent.CONTINUE);
}
return event;
}
public void commandQueued(ICommandToken token) {
// Do nothing.
@ -254,9 +337,12 @@ public class MIRunControlEventProcessor
else if (cmd instanceof MIExecReturn) { type = MIRunningEvent.RETURN; }
else if (cmd instanceof MIExecContinue) { type = MIRunningEvent.CONTINUE; }
else { type = MIRunningEvent.CONTINUE; }
MIProcesses procService = fServicesTracker.getService(MIProcesses.class);
IContainerDMContext processContainerDmc = procService.createExecutionGroupContext(fContainerDmc, ""); //$NON-NLS-1$
fCommandControl.getSession().dispatchEvent(
new MIRunningEvent(fContainerDmc, id, type), fCommandControl.getProperties());
new MIRunningEvent(processContainerDmc, id, type), fCommandControl.getProperties());
} else if ("exit".equals(state)) { //$NON-NLS-1$
// No need to do anything, terminate() will.
// Send exited?

View file

@ -1,13 +1,12 @@
/*******************************************************************************
* Copyright (c) 2000, 2006 QNX Software Systems and others.
* 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:
* QNX Software Systems - Initial API and implementation
* Ericsson - Modified for new DSF Reference Implementation
* Ericsson - Initial API and implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;

View file

@ -39,6 +39,7 @@ public class MIBreakpointHitEvent extends MIStoppedEvent {
return bkptno;
}
@Deprecated
public static MIBreakpointHitEvent parse(
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
@ -62,4 +63,27 @@ public class MIBreakpointHitEvent extends MIStoppedEvent {
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MIBreakpointHitEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), bkptno);
}
public static MIBreakpointHitEvent parse(IExecutionDMContext dmc, int token, MIResult[] results)
{
int bkptno = -1;
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue value = results[i].getMIValue();
String str = ""; //$NON-NLS-1$
if (value != null && value instanceof MIConst) {
str = ((MIConst)value).getString();
}
if (var.equals("bkptno")) { //$NON-NLS-1$
try {
bkptno = Integer.parseInt(str.trim());
} catch (NumberFormatException e) {
}
}
}
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
return new MIBreakpointHitEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), bkptno);
}
}

View file

@ -53,6 +53,7 @@ public class MIFunctionFinishedEvent extends MIStoppedEvent {
return returnType;
}
@Deprecated
public static MIFunctionFinishedEvent parse(
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
@ -80,4 +81,31 @@ public class MIFunctionFinishedEvent extends MIStoppedEvent {
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MIFunctionFinishedEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), gdbResult, returnValue, returnType);
}
public static MIFunctionFinishedEvent parse(IExecutionDMContext dmc, int token, MIResult[] results)
{
String gdbResult = ""; //$NON-NLS-1$
String returnValue = ""; //$NON-NLS-1$
String returnType = ""; //$NON-NLS-1$
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue value = results[i].getMIValue();
String str = ""; //$NON-NLS-1$
if (value instanceof MIConst) {
str = ((MIConst)value).getString();
}
if (var.equals("gdb-result-var")) { //$NON-NLS-1$
gdbResult = str;
} else if (var.equals("return-value")) { //$NON-NLS-1$
returnValue = str;
} else if (var.equals("return-type")) { //$NON-NLS-1$
returnType = str;
}
}
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
return new MIFunctionFinishedEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), gdbResult, returnValue, returnType);
}
}

View file

@ -28,11 +28,18 @@ public class MILocationReachedEvent extends MIStoppedEvent {
protected MILocationReachedEvent(IExecutionDMContext ctx, int token, MIResult[] results, MIFrame frame) {
super(ctx, token, results, frame);
}
@Deprecated
public static MILocationReachedEvent parse(
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MILocationReachedEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame());
}
public static MILocationReachedEvent parse(IExecutionDMContext dmc, int token, MIResult[] results)
{
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
return new MILocationReachedEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame());
}
}

View file

@ -29,6 +29,7 @@ public class MISharedLibEvent extends MIStoppedEvent {
super(ctx, token, results, frame);
}
@Deprecated
public static MIStoppedEvent parse(
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
@ -36,4 +37,10 @@ public class MISharedLibEvent extends MIStoppedEvent {
return new MISharedLibEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame());
}
public static MIStoppedEvent parse(IExecutionDMContext dmc, int token, MIResult[] results)
{
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
return new MISharedLibEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame());
}
}

View file

@ -48,6 +48,8 @@ public class MISignalEvent extends MIStoppedEvent {
return sigMeaning;
}
@Deprecated
public static MISignalEvent parse(
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
@ -72,4 +74,28 @@ public class MISignalEvent extends MIStoppedEvent {
return new MISignalEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), sigName, sigMeaning);
}
public static MISignalEvent parse(IExecutionDMContext dmc, int token, MIResult[] results)
{
String sigName = ""; //$NON-NLS-1$
String sigMeaning = ""; //$NON-NLS-1$
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue value = results[i].getMIValue();
String str = ""; //$NON-NLS-1$
if (value instanceof MIConst) {
str = ((MIConst)value).getString();
}
if (var.equals("signal-name")) { //$NON-NLS-1$
sigName = str;
} else if (var.equals("signal-meaning")) { //$NON-NLS-1$
sigMeaning = str;
}
}
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
return new MISignalEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), sigName, sigMeaning);
}
}

View file

@ -30,10 +30,17 @@ public class MISteppingRangeEvent extends MIStoppedEvent {
super(ctx, token, results, frame);
}
@Deprecated
public static MISteppingRangeEvent parse(
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MISteppingRangeEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame());
}
public static MISteppingRangeEvent parse(IExecutionDMContext dmc, int token, MIResult[] results)
{
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
return new MISteppingRangeEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame());
}
}

View file

@ -40,6 +40,7 @@ public class MIStoppedEvent extends MIEvent<IExecutionDMContext> {
return frame;
}
@Deprecated
public static MIStoppedEvent parse(
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
@ -70,4 +71,21 @@ public class MIStoppedEvent extends MIEvent<IExecutionDMContext> {
}
return new MIStoppedEvent(execDmc, token, results, frame);
}
public static MIStoppedEvent parse(IExecutionDMContext dmc, int token, MIResult[] results)
{
MIFrame frame = null;
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue value = results[i].getMIValue();
if (var.equals("frame")) { //$NON-NLS-1$
if (value instanceof MITuple) {
frame = new MIFrame((MITuple)value);
}
}
}
return new MIStoppedEvent(dmc, token, results, frame);
}
}

View file

@ -41,6 +41,7 @@ public class MIWatchpointScopeEvent extends MIStoppedEvent {
return number;
}
@Deprecated
public static MIWatchpointScopeEvent parse(
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
@ -63,4 +64,26 @@ public class MIWatchpointScopeEvent extends MIStoppedEvent {
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MIWatchpointScopeEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), number);
}
public static MIWatchpointScopeEvent parse(IExecutionDMContext dmc, int token, MIResult[] results)
{
int number = 0;
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue value = results[i].getMIValue();
if (var.equals("wpnum")) { //$NON-NLS-1$
if (value instanceof MIConst) {
String str = ((MIConst) value).getString();
try {
number = Integer.parseInt(str.trim());
} catch (NumberFormatException e) {
}
}
}
}
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
return new MIWatchpointScopeEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), number);
}
}

View file

@ -61,6 +61,7 @@ public class MIWatchpointTriggerEvent extends MIStoppedEvent {
return newValue;
}
@Deprecated
public static MIWatchpointTriggerEvent parse(
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
@ -119,4 +120,62 @@ public class MIWatchpointTriggerEvent extends MIStoppedEvent {
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MIWatchpointTriggerEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), number, exp, oldValue, newValue);
}
public static MIWatchpointTriggerEvent parse(IExecutionDMContext dmc, int token, MIResult[] results)
{
int number = 0;
String exp = ""; //$NON-NLS-1$
String oldValue = ""; //$NON-NLS-1$
String newValue = ""; //$NON-NLS-1$
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue value = results[i].getMIValue();
if (var.equals("wpt") || var.equals("hw-awpt") || var.equals("hw-rwpt")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (value instanceof MITuple) {
for (MIResult wptResult : ((MITuple) value).getMIResults()) {
String wptVar = wptResult.getVariable();
MIValue wptValue = wptResult.getMIValue();
if (wptVar.equals("number")) { //$NON-NLS-1$
if (wptValue instanceof MIConst) {
String str = ((MIConst) wptValue).getString();
try {
number = Integer.parseInt(str);
} catch (NumberFormatException e) {
}
}
} else if (wptVar.equals("exp")) { //$NON-NLS-1$
if (wptValue instanceof MIConst) {
exp = ((MIConst) wptValue).getString();
}
}
}
}
} else if (var.equals("value")) { //$NON-NLS-1$
if (value instanceof MITuple) {
for (MIResult valueResult : ((MITuple)value).getMIResults()) {
String valueVar = valueResult.getVariable();
MIValue valueValue = valueResult.getMIValue();
String str = ""; //$NON-NLS-1$
if (valueValue instanceof MIConst) {
str = ((MIConst) valueValue).getString();
}
if (valueVar.equals("old")) { //$NON-NLS-1$
oldValue = str;
} else if (valueVar.equals("new")) { //$NON-NLS-1$
newValue = str;
} else if (valueVar.equals("value")) { //$NON-NLS-1$
oldValue = newValue = str;
}
}
}
}
}
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
return new MIWatchpointTriggerEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), number, exp, oldValue, newValue);
}
}

View file

@ -1,13 +1,12 @@
/*******************************************************************************
* Copyright (c) 2000, 2006 QNX Software Systems and others.
* 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:
* QNX Software Systems - Initial API and implementation
* Ericsson AB - Modified for DSF Reference Implementation
* Ericsson - Initial API and implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.output;