mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-09-10 12:03:16 +02:00
[228703] - [breakpoints] Add a breakpoint hit event to IBreakpoints service.
This commit is contained in:
parent
e23f43553a
commit
7bdb38f1b0
6 changed files with 250 additions and 15 deletions
|
@ -35,6 +35,7 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
|||
import org.eclipse.cdt.dsf.debug.service.IRunControl2;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension.IBreakpointHitDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||
|
@ -51,6 +52,7 @@ import org.eclipse.cdt.dsf.mi.service.MIBreakpointDMData;
|
|||
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIRunControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIStack;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.MIBreakpointDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
|
||||
|
@ -150,6 +152,27 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the given thread has been suspended on a breakpoint.
|
||||
* @since 3.0
|
||||
*/
|
||||
@Immutable
|
||||
private static class BreakpointHitEvent extends SuspendedEvent
|
||||
implements IBreakpointHitDMEvent
|
||||
{
|
||||
final private MIBreakpointDMContext[] fBreakpoints;
|
||||
|
||||
BreakpointHitEvent(IExecutionDMContext ctx, MIStoppedEvent miInfo, MIBreakpointDMContext bpCtx) {
|
||||
super(ctx, miInfo);
|
||||
|
||||
fBreakpoints = new MIBreakpointDMContext[] { bpCtx };
|
||||
}
|
||||
|
||||
public IBreakpointDMContext[] getBreakpoints() {
|
||||
return fBreakpoints;
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
private static class ResumedEvent extends RunControlEvent<IExecutionDMContext, MIRunningEvent>
|
||||
implements IResumedDMEvent
|
||||
|
@ -1026,7 +1049,23 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
|||
// Don't broadcast the stopped event
|
||||
return;
|
||||
}
|
||||
getSession().dispatchEvent(new SuspendedEvent(e.getDMContext(), e), getProperties());
|
||||
|
||||
MIBreakpointDMContext bp = null;
|
||||
if (e instanceof MIBreakpointHitEvent) {
|
||||
int bpId = ((MIBreakpointHitEvent)e).getNumber();
|
||||
IBreakpointsTargetDMContext bpsTarget = DMContexts.getAncestorOfType(e.getDMContext(), IBreakpointsTargetDMContext.class);
|
||||
if (bpsTarget != null && bpId >= 0) {
|
||||
bp = new MIBreakpointDMContext(getSession().getId(), new IDMContext[] {bpsTarget}, bpId);
|
||||
}
|
||||
}
|
||||
|
||||
IDMEvent<?> event = null;
|
||||
if (bp != null) {
|
||||
event = new BreakpointHitEvent(e.getDMContext(), e, bp);
|
||||
} else {
|
||||
event = new SuspendedEvent(e.getDMContext(), e);
|
||||
}
|
||||
getSession().dispatchEvent(event, getProperties());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ package org.eclipse.cdt.dsf.mi.service;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||
|
@ -26,10 +27,15 @@ import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
|
|||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerResumedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
|
@ -50,7 +56,7 @@ import org.osgi.framework.BundleContext;
|
|||
* Initial breakpoint service implementation.
|
||||
* Implements the IBreakpoints interface.
|
||||
*/
|
||||
public class MIBreakpoints extends AbstractDsfService implements IBreakpoints
|
||||
public class MIBreakpoints extends AbstractDsfService implements IBreakpoints, IBreakpointsExtension
|
||||
{
|
||||
/**
|
||||
* Breakpoint attributes markers used in the map parameters of insert/updateBreakpoint().
|
||||
|
@ -96,6 +102,13 @@ public class MIBreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
private Map<IBreakpointsTargetDMContext, Map<Integer, MIBreakpointDMData>> fBreakpoints =
|
||||
new HashMap<IBreakpointsTargetDMContext, Map<Integer, MIBreakpointDMData>>();
|
||||
|
||||
/**
|
||||
* Map tracking which threads are currently suspended on a breakpoint.
|
||||
* @since 3.0
|
||||
*/
|
||||
private Map<IExecutionDMContext, IBreakpointDMContext[]> fBreakpointHitMap =
|
||||
new HashMap<IExecutionDMContext, IBreakpointDMContext[]>();
|
||||
|
||||
/**
|
||||
* Returns a map of existing breakpoints for the specified context
|
||||
*
|
||||
|
@ -192,7 +205,18 @@ public class MIBreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
* @param reference the DsfMIBreakpoint reference
|
||||
*/
|
||||
public MIBreakpointDMContext(MIBreakpoints service, IDMContext[] parents, int reference) {
|
||||
super(service.getSession().getId(), parents);
|
||||
this(service.getSession().getId(), parents, reference);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sessionId session ID
|
||||
* @param parents the parent contexts
|
||||
* @param reference the DsfMIBreakpoint reference
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public MIBreakpointDMContext(String sessionId, IDMContext[] parents, int reference) {
|
||||
super(sessionId, parents);
|
||||
fReference = reference;
|
||||
}
|
||||
|
||||
|
@ -269,7 +293,7 @@ public class MIBreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
getSession().addServiceEventListener(this, null);
|
||||
|
||||
// Register this service
|
||||
register(new String[] { IBreakpoints.class.getName(), MIBreakpoints.class.getName() },
|
||||
register(new String[] { IBreakpoints.class.getName(), IBreakpointsExtension.class.getName(), MIBreakpoints.class.getName() },
|
||||
new Hashtable<String, String>());
|
||||
|
||||
rm.done();
|
||||
|
@ -471,6 +495,15 @@ public class MIBreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.0
|
||||
*/
|
||||
public void getExecutionContextBreakpoints(IExecutionDMContext ctx, DataRequestMonitor<IBreakpointDMContext[]> rm) {
|
||||
IBreakpointDMContext[] bps = fBreakpointHitMap.get(ctx);
|
||||
rm.setData(bps != null ? bps : new IBreakpointDMContext[0]);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param map
|
||||
* @param key
|
||||
|
@ -1237,4 +1270,57 @@ public class MIBreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @nooverride This method is not intended to be re-implemented or extended by clients.
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(IBreakpointHitDMEvent e) {
|
||||
if (e instanceof IContainerSuspendedDMEvent) {
|
||||
IExecutionDMContext[] triggeringContexts = ((IContainerSuspendedDMEvent)e).getTriggeringContexts();
|
||||
for (IExecutionDMContext ctx : triggeringContexts) {
|
||||
fBreakpointHitMap.put(ctx, e.getBreakpoints());
|
||||
|
||||
}
|
||||
} else {
|
||||
fBreakpointHitMap.put(e.getDMContext(), e.getBreakpoints());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @nooverride This method is not intended to be re-implemented or extended by clients.
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(IResumedDMEvent e) {
|
||||
if (e instanceof IContainerResumedDMEvent) {
|
||||
clearBreakpointHitForContainer(((IContainerResumedDMEvent)e).getDMContext());
|
||||
} else {
|
||||
fBreakpointHitMap.remove(e.getDMContext());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler when a thread is destroyed
|
||||
* @nooverride This method is not intended to be re-implemented or extended by clients.
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(IExitedDMEvent e) {
|
||||
if (e.getDMContext() instanceof IContainerDMContext) {
|
||||
clearBreakpointHitForContainer(e.getDMContext());
|
||||
} else {
|
||||
fBreakpointHitMap.remove(e.getDMContext());
|
||||
}
|
||||
}
|
||||
|
||||
private void clearBreakpointHitForContainer(IDMContext container) {
|
||||
for (Iterator<Map.Entry<IExecutionDMContext, IBreakpointDMContext[]>> itr = fBreakpointHitMap.entrySet().iterator(); itr.hasNext();) {
|
||||
if (DMContexts.isAncestorOf(itr.next().getKey(), container)) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1277,6 +1277,18 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a platform breakpoint corresponding to a given target breakpoint.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public IBreakpoint findPlatformBreakpoint(IBreakpointDMContext bpContext) {
|
||||
if (bpContext instanceof MIBreakpointDMContext) {
|
||||
return findPlatformBreakpoint(((MIBreakpointDMContext)bpContext).getReference());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Session exit
|
||||
//-------------------------------------------------------------------------
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
|||
import org.eclipse.cdt.dsf.debug.service.IProcesses;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpointsExtension.IBreakpointHitDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
||||
|
@ -39,6 +40,7 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
|||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.MIBreakpointDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
|
||||
|
@ -187,6 +189,28 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the given thread has been suspended on a breakpoint.
|
||||
* @since 3.0
|
||||
*/
|
||||
@Immutable
|
||||
protected static class BreakpointHitEvent extends SuspendedEvent
|
||||
implements IBreakpointHitDMEvent
|
||||
{
|
||||
final private MIBreakpointDMContext[] fBreakpoints;
|
||||
|
||||
BreakpointHitEvent(IExecutionDMContext ctx, MIStoppedEvent miInfo, MIBreakpointDMContext bpCtx) {
|
||||
super(ctx, miInfo);
|
||||
|
||||
fBreakpoints = new MIBreakpointDMContext[] { bpCtx };
|
||||
}
|
||||
|
||||
public IBreakpointDMContext[] getBreakpoints() {
|
||||
return fBreakpoints;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Immutable
|
||||
protected static class ContainerSuspendedEvent extends SuspendedEvent
|
||||
implements IContainerSuspendedDMEvent
|
||||
|
@ -203,6 +227,27 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the given container has been suspended on a breakpoint.
|
||||
* @since 3.0
|
||||
*/
|
||||
@Immutable
|
||||
protected static class ContainerBreakpointHitEvent extends ContainerSuspendedEvent
|
||||
implements IBreakpointHitDMEvent
|
||||
{
|
||||
final private MIBreakpointDMContext[] fBreakpoints;
|
||||
|
||||
ContainerBreakpointHitEvent(IContainerDMContext containerDmc, MIStoppedEvent miInfo, IExecutionDMContext triggeringDmc, MIBreakpointDMContext bpCtx) {
|
||||
super(containerDmc, miInfo, triggeringDmc);
|
||||
|
||||
fBreakpoints = new MIBreakpointDMContext[] { bpCtx };
|
||||
}
|
||||
|
||||
public IBreakpointDMContext[] getBreakpoints() {
|
||||
return fBreakpoints;
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
protected static class ResumedEvent extends RunControlEvent<IExecutionDMContext, MIRunningEvent>
|
||||
implements IResumedDMEvent
|
||||
|
@ -382,6 +427,15 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
return;
|
||||
}
|
||||
|
||||
MIBreakpointDMContext bp = null;
|
||||
if (e instanceof MIBreakpointHitEvent) {
|
||||
int bpId = ((MIBreakpointHitEvent)e).getNumber();
|
||||
IBreakpointsTargetDMContext bpsTarget = DMContexts.getAncestorOfType(e.getDMContext(), IBreakpointsTargetDMContext.class);
|
||||
if (bpsTarget != null && bpId >= 0) {
|
||||
bp = new MIBreakpointDMContext(getSession().getId(), new IDMContext[] {bpsTarget}, bpId);
|
||||
}
|
||||
}
|
||||
|
||||
IDMEvent<?> event = null;
|
||||
// Find the container context, which is used in multi-threaded debugging.
|
||||
final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(e.getDMContext(), IContainerDMContext.class);
|
||||
|
@ -407,9 +461,17 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
});
|
||||
return;
|
||||
}
|
||||
event = new ContainerSuspendedEvent(containerDmc, e, triggeringCtx);
|
||||
if (bp != null) {
|
||||
event = new ContainerBreakpointHitEvent(containerDmc, e, triggeringCtx, bp);
|
||||
} else {
|
||||
event = new ContainerSuspendedEvent(containerDmc, e, triggeringCtx);
|
||||
}
|
||||
} else {
|
||||
event = new SuspendedEvent(e.getDMContext(), e);
|
||||
if (bp != null) {
|
||||
event = new BreakpointHitEvent(e.getDMContext(), e, bp);
|
||||
} else {
|
||||
event = new SuspendedEvent(e.getDMContext(), e);
|
||||
}
|
||||
}
|
||||
getSession().dispatchEvent(event, getProperties());
|
||||
}
|
||||
|
|
|
@ -732,15 +732,6 @@ public class MIStack extends AbstractDsfService
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is left for API compatibility only.
|
||||
* @nooverride This method is not intended to be re-implemented or extended by clients.
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(MIRunControl.ContainerSuspendedEvent e) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.1
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 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.cdt.dsf.debug.service;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||
|
||||
/**
|
||||
* Extension to the Breakpoints service which adds support for corollating
|
||||
* breakpoints and execution contexts.
|
||||
* @since 2.1
|
||||
*/
|
||||
public interface IBreakpointsExtension extends IBreakpoints {
|
||||
|
||||
/**
|
||||
* Event indicating that a given thread or container was suspended
|
||||
* by the given breakpoint(s).
|
||||
*/
|
||||
public interface IBreakpointHitDMEvent extends ISuspendedDMEvent {
|
||||
|
||||
/**
|
||||
* Returs the breakpoints that suspended the thread.
|
||||
*/
|
||||
IBreakpointDMContext[] getBreakpoints();
|
||||
}
|
||||
|
||||
/**
|
||||
* If a given execution context was suspended due hitting a breakpoint,
|
||||
* this method should return the breakpoints which caused the thread or
|
||||
* container to suspend.
|
||||
*
|
||||
* @param ctx Thread or container to get breakpoints for.
|
||||
* @param rm Breakpoints that the thread suspended on.
|
||||
*/
|
||||
public void getExecutionContextBreakpoints(IExecutionDMContext ctx, DataRequestMonitor<IBreakpointDMContext[]> rm);
|
||||
}
|
Loading…
Add table
Reference in a new issue