mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 09:25:31 +02:00
Bug 392512 - Support GDB breakpoint notifications
Change-Id: I244ba995392806a56a52852e0d0d9ea72f87edfa Reviewed-on: https://git.eclipse.org/r/8327 Reviewed-by: Marc Khouzam <marc.khouzam@ericsson.com> IP-Clean: Marc Khouzam <marc.khouzam@ericsson.com> Tested-by: Marc Khouzam <marc.khouzam@ericsson.com> Reviewed-by: Mikhail Khodjaiants <mikhailkhod@googlemail.com> IP-Clean: Mikhail Khodjaiants <mikhailkhod@googlemail.com> Tested-by: Mikhail Khodjaiants <mikhailkhod@googlemail.com>
This commit is contained in:
parent
db3fa6a01f
commit
12de79d9b0
9 changed files with 1760 additions and 36 deletions
|
@ -696,6 +696,52 @@ public class CDIDebugModel {
|
|||
return new CWatchpoint(resource, attributes, register);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a watchpoint for the source defined by the given
|
||||
* source handle, at the given expression. The marker associated with the
|
||||
* watchpoint will be created on the specified resource.
|
||||
*
|
||||
* @param sourceHandle
|
||||
* the handle to the watchpoint source
|
||||
* @param resource
|
||||
* the resource on which to create the associated watchpoint
|
||||
* marker
|
||||
* @param type
|
||||
* a type constant from ICBreakpointType
|
||||
* @param writeAccess
|
||||
* whether this is write watchpoint
|
||||
* @param readAccess
|
||||
* whether this is read watchpoint
|
||||
* @param expression
|
||||
* the expression on which the watchpoint is set
|
||||
* @param enabled
|
||||
* whether to enable or disable this breakpoint
|
||||
* @param ignoreCount
|
||||
* the number of times this breakpoint will be ignored
|
||||
* @param condition
|
||||
* the breakpoint condition
|
||||
* @param register
|
||||
* whether to add this breakpoint to the breakpoint manager
|
||||
* @return a watchpoint
|
||||
* @throws CoreException
|
||||
* if this method fails. Reasons include:
|
||||
* <ul>
|
||||
* <li>Failure creating underlying marker. The exception's
|
||||
* status contains the underlying exception responsible for the
|
||||
* failure.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @since 7.3
|
||||
*/
|
||||
public static ICWatchpoint createWatchpoint(String sourceHandle, IResource resource, int type, boolean writeAccess,
|
||||
boolean readAccess, String expression, boolean enabled, int ignoreCount, String condition, boolean register)
|
||||
throws CoreException {
|
||||
HashMap<String, Object> attributes = new HashMap<String, Object>(10);
|
||||
setWatchPointAttributes(attributes, sourceHandle, resource, type, writeAccess, readAccess, expression, "", //$NON-NLS-1$
|
||||
BigInteger.ZERO, enabled, ignoreCount, condition);
|
||||
return new CWatchpoint(resource, attributes, register);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a watchpoint for the source defined by the given
|
||||
* source handle, at the given expression. The marker associated with the
|
||||
|
@ -850,6 +896,47 @@ public class CDIDebugModel {
|
|||
attributes.put(ICWatchpoint.WRITE, Boolean.valueOf(writeAccess));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for setting common watchpoint attributes.
|
||||
*
|
||||
* @param attributes
|
||||
* Map to write the attributes into.
|
||||
* @param sourceHandle
|
||||
* the handle to the watchpoint source
|
||||
* @param resource
|
||||
* the resource on which to create the associated watchpoint
|
||||
* marker
|
||||
* @param type
|
||||
* a type constant from ICBreakpointType
|
||||
* @param writeAccess
|
||||
* whether this is write watchpoint
|
||||
* @param readAccess
|
||||
* whether this is read watchpoint
|
||||
* @param expression
|
||||
* the expression on which the watchpoint is set
|
||||
* @param memorySpace
|
||||
* the memory space in which the watchpoint is set
|
||||
* @param range
|
||||
* the range of the watchpoint in addressable units
|
||||
* @param enabled
|
||||
* whether to enable or disable this breakpoint
|
||||
* @param ignoreCount
|
||||
* the number of times this breakpoint will be ignored
|
||||
* @param condition
|
||||
* the breakpoint condition
|
||||
* @param register
|
||||
* whether to add this breakpoint to the breakpoint manager
|
||||
*
|
||||
* @since 7.3
|
||||
*/
|
||||
public static void setWatchPointAttributes(Map<String, Object> attributes, String sourceHandle, IResource resource,
|
||||
int type, boolean writeAccess, boolean readAccess, String expression, String memorySpace, BigInteger range,
|
||||
boolean enabled, int ignoreCount, String condition) {
|
||||
setWatchPointAttributes(attributes, sourceHandle, resource,
|
||||
writeAccess, readAccess, expression, memorySpace, range, enabled, ignoreCount, condition);
|
||||
attributes.put(ICBreakpointType.TYPE, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a breakpoint for the function defined by the given
|
||||
* name. The marker associated with the breakpoint will be created on the
|
||||
|
|
|
@ -357,6 +357,7 @@ public class CDebugUtils {
|
|||
appendWatchMemorySpace(wp2, label);
|
||||
appendWatchRange(wp2, label);
|
||||
}
|
||||
appendBreakpointType(watchpoint, label);
|
||||
appendIgnoreCount(watchpoint, label);
|
||||
appendCondition(watchpoint, label);
|
||||
return label.toString();
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
|
|||
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsSynchronizer;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
|
||||
|
@ -130,6 +131,11 @@ public class ServicesLaunchSequence extends Sequence {
|
|||
requestMonitor.done();
|
||||
}
|
||||
}},
|
||||
new Step() { @Override
|
||||
public void execute(final RequestMonitor requestMonitor) {
|
||||
// Create breakpoint synchronization service.
|
||||
fLaunch.getServiceFactory().createService(MIBreakpointsSynchronizer.class, fSession).initialize(requestMonitor);
|
||||
}},
|
||||
};
|
||||
|
||||
DsfSession fSession;
|
||||
|
|
|
@ -0,0 +1,252 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012 Mentor Graphics 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:
|
||||
* Mentor Graphics - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.dsf.gdb.service;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
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.command.ICommandControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpointDMData;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsSynchronizer;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIConst;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MINotifyAsyncOutput;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIOOBRecord;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIResult;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITuple;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIValue;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
||||
/**
|
||||
* Breakpoints service for GDB 7.4.
|
||||
* Using breakpoint notifications introduced in 7.4 supports synchronization between the breakpoints
|
||||
* set from the GDB console and the Breakpoints view as well as the tracepoints reported form trace files.
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public class GDBBreakpoints_7_4 extends GDBBreakpoints_7_2 implements IEventListener {
|
||||
|
||||
// Breakpoint notifications
|
||||
private static final String BREAKPOINT_PREFIX = "breakpoint-"; //$NON-NLS-1$
|
||||
private static final String BREAKPOINT_CREATED = BREAKPOINT_PREFIX + "created"; //$NON-NLS-1$
|
||||
private static final String BREAKPOINT_MODIFIED = BREAKPOINT_PREFIX + "modified"; //$NON-NLS-1$
|
||||
private static final String BREAKPOINT_DELETED = BREAKPOINT_PREFIX + "deleted"; //$NON-NLS-1$
|
||||
|
||||
private IMICommandControl fConnection;
|
||||
|
||||
public GDBBreakpoints_7_4(DsfSession session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(final RequestMonitor rm) {
|
||||
super.initialize(new ImmediateRequestMonitor(rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
doInitialize(rm);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doInitialize(final RequestMonitor rm) {
|
||||
fConnection = getServicesTracker().getService(IMICommandControl.class);
|
||||
if (fConnection == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Service is not available")); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
fConnection.addEventListener(this);
|
||||
|
||||
// Register this service
|
||||
register(new String[] { IBreakpoints.class.getName(),
|
||||
IBreakpointsExtension.class.getName(),
|
||||
MIBreakpoints.class.getName(),
|
||||
GDBBreakpoints_7_0.class.getName(),
|
||||
GDBBreakpoints_7_2.class.getName(),
|
||||
GDBBreakpoints_7_4.class.getName() },
|
||||
new Hashtable<String, String>());
|
||||
|
||||
rm.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown(RequestMonitor requestMonitor) {
|
||||
ICommandControl control = getCommandControl();
|
||||
if (control != null) {
|
||||
control.removeEventListener(this);
|
||||
}
|
||||
unregister();
|
||||
super.shutdown(requestMonitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventReceived(Object output) {
|
||||
if (output instanceof MIOutput) {
|
||||
MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class);
|
||||
if (bs != null) {
|
||||
MIOOBRecord[] records = ((MIOutput)output).getMIOOBRecords();
|
||||
for(MIOOBRecord r : records) {
|
||||
if (r instanceof MINotifyAsyncOutput) {
|
||||
MINotifyAsyncOutput notifyOutput = (MINotifyAsyncOutput)r;
|
||||
String asyncClass = notifyOutput.getAsyncClass();
|
||||
if (BREAKPOINT_CREATED.equals(asyncClass)) {
|
||||
MIBreakpoint bpt = getMIBreakpointFromOutput(notifyOutput);
|
||||
if (bpt != null)
|
||||
bs.targetBreakpointCreated(bpt);
|
||||
}
|
||||
else if (BREAKPOINT_DELETED.equals(asyncClass)) {
|
||||
int id = getMIBreakpointIdFromOutput(notifyOutput);
|
||||
if (id != 0)
|
||||
bs.targetBreakpointDeleted(id);
|
||||
}
|
||||
else if (BREAKPOINT_MODIFIED.equals(asyncClass)) {
|
||||
MIBreakpoint bpt = getMIBreakpointFromOutput(notifyOutput);
|
||||
if (bpt != null)
|
||||
bs.targetBreakpointModified(bpt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IMICommandControl getCommandControl() {
|
||||
return fConnection;
|
||||
}
|
||||
|
||||
private MIBreakpoint getMIBreakpointFromOutput(MINotifyAsyncOutput notifyOutput) {
|
||||
MIBreakpoint bpt = null;
|
||||
MIResult[] results = notifyOutput.getMIResults();
|
||||
for(int i = 0; i < results.length; i++) {
|
||||
String var = results[i].getVariable();
|
||||
MIValue val = results[i].getMIValue();
|
||||
if (var.equals("bkpt")) { //$NON-NLS-1$
|
||||
if (val instanceof MITuple) {
|
||||
bpt = new MIBreakpoint((MITuple)val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bpt;
|
||||
}
|
||||
|
||||
private int getMIBreakpointIdFromOutput(MINotifyAsyncOutput notifyOutput) {
|
||||
MIResult[] results = notifyOutput.getMIResults();
|
||||
for(int i = 0; i < results.length; i++) {
|
||||
String var = results[i].getVariable();
|
||||
MIValue val = results[i].getMIValue();
|
||||
if (var.equals("id") && val instanceof MIConst) { //$NON-NLS-1$
|
||||
try {
|
||||
return Integer.parseInt(((MIConst)val).getCString().trim());
|
||||
}
|
||||
catch(NumberFormatException e) {
|
||||
GdbPlugin.log(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Invalid breakpoint id")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addBreakpoint(IBreakpointsTargetDMContext context, Map<String, Object> attributes, DataRequestMonitor<IBreakpointDMContext> finalRm) {
|
||||
MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class);
|
||||
if (bs != null) {
|
||||
// Skip the breakpoints set from the console or from outside of Eclipse
|
||||
// because they are already installed on the target.
|
||||
MIBreakpoint miBpt = bs.getTargetBreakpoint(context, attributes);
|
||||
if (miBpt != null) {
|
||||
bs.removeCreatedTargetBreakpoint(context, miBpt);
|
||||
MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt);
|
||||
getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint);
|
||||
IBreakpointDMContext dmc = new MIBreakpointDMContext(this, new IDMContext[] { context }, newBreakpoint.getNumber());
|
||||
finalRm.setData(dmc);
|
||||
|
||||
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
|
||||
|
||||
finalRm.done();
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.addBreakpoint(context, attributes, finalRm);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addTracepoint(IBreakpointsTargetDMContext context, Map<String, Object> attributes, DataRequestMonitor<IBreakpointDMContext> drm) {
|
||||
MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class);
|
||||
if (bs != null) {
|
||||
// Skip the breakpoints set from the console or from outside of Eclipse
|
||||
// because they are already installed on the target.
|
||||
MIBreakpoint miBpt = bs.getTargetBreakpoint(context, attributes);
|
||||
if (miBpt != null) {
|
||||
bs.removeCreatedTargetBreakpoint(context, miBpt);
|
||||
MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt);
|
||||
getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint);
|
||||
IBreakpointDMContext dmc = new MIBreakpointDMContext(this, new IDMContext[] { context }, newBreakpoint.getNumber());
|
||||
drm.setData(dmc);
|
||||
|
||||
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
|
||||
|
||||
drm.done();
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.addTracepoint(context, attributes, drm);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addWatchpoint(IBreakpointsTargetDMContext context, Map<String, Object> attributes, DataRequestMonitor<IBreakpointDMContext> drm) {
|
||||
MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class);
|
||||
if (bs != null) {
|
||||
// Skip the breakpoints set from the console or from outside of Eclipse
|
||||
// because they are already installed on the target.
|
||||
MIBreakpoint miBpt = bs.getTargetBreakpoint(context, attributes);
|
||||
if (miBpt != null) {
|
||||
bs.removeCreatedTargetBreakpoint(context, miBpt);
|
||||
MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt);
|
||||
getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint);
|
||||
IBreakpointDMContext dmc = new MIBreakpointDMContext(this, new IDMContext[] { context }, newBreakpoint.getNumber());
|
||||
drm.setData(dmc);
|
||||
|
||||
getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties());
|
||||
|
||||
drm.done();
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.addWatchpoint(context, attributes, drm);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deleteBreakpointFromTarget(IBreakpointsTargetDMContext context, int reference, RequestMonitor finalRm) {
|
||||
MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class);
|
||||
if (bs != null) {
|
||||
// Do nothing if the breakpoint is deleted from the console.
|
||||
if (bs.isTargetBreakpointDeleted(context, reference, true)) {
|
||||
finalRm.done();
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.deleteBreakpointFromTarget(context, reference, finalRm);
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@ import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
|
|||
import org.eclipse.cdt.dsf.mi.service.IMIBackend;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsSynchronizer;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIDisassembly;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIExpressions;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIMemory;
|
||||
|
@ -106,6 +107,9 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (MIBreakpointsSynchronizer.class.isAssignableFrom(clazz)) {
|
||||
return (V)createBreakpointsSynchronizerService(session);
|
||||
}
|
||||
|
||||
return super.createService(clazz, session);
|
||||
}
|
||||
|
@ -116,6 +120,9 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
|||
|
||||
@Override
|
||||
protected IBreakpoints createBreakpointService(DsfSession session) {
|
||||
if (GDB_7_4_VERSION.compareTo(fVersion) <= 0) {
|
||||
return new GDBBreakpoints_7_4(session);
|
||||
}
|
||||
// This service is available for GDB 7.2 but there is a pre-release of GDB that
|
||||
// supports the same features and has version of 6.8.50.20090414
|
||||
if (GDB_7_2_VERSION.compareTo(fVersion) <= 0 || "6.8.50.20090414".equals(fVersion)) { //$NON-NLS-1$
|
||||
|
@ -237,4 +244,11 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
|||
}
|
||||
return new GDBHardwareAndOS(session);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.2
|
||||
*/
|
||||
protected MIBreakpointsSynchronizer createBreakpointsSynchronizerService(DsfSession session) {
|
||||
return new MIBreakpointsSynchronizer(session);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Map;
|
|||
|
||||
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Immutable;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
|
@ -913,26 +914,16 @@ public class MIBreakpoints extends AbstractDsfService implements IBreakpoints, I
|
|||
return;
|
||||
}
|
||||
|
||||
final Step deleteBreakpointStep = new Step() {
|
||||
@Override
|
||||
public void execute(final RequestMonitor rm) {
|
||||
// Queue the command
|
||||
fConnection.queueCommand(
|
||||
fCommandFactory.createMIBreakDelete(context, new int[] { reference }),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isSuccess()) {
|
||||
getSession().dispatchEvent(new BreakpointRemovedEvent(dmc), getProperties());
|
||||
contextBreakpoints.remove(reference);
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
fRunControl.executeWithTargetAvailable(context, new Step[] { deleteBreakpointStep }, finalRm);
|
||||
deleteBreakpointFromTarget(context, reference, new RequestMonitor(ImmediateExecutor.getInstance(), finalRm) {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isSuccess()) {
|
||||
getSession().dispatchEvent(new BreakpointRemovedEvent(dmc), getProperties());
|
||||
contextBreakpoints.remove(reference);
|
||||
}
|
||||
finalRm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
@ -1279,6 +1270,24 @@ public class MIBreakpoints extends AbstractDsfService implements IBreakpoints, I
|
|||
fRunControl.executeWithTargetAvailable(context, new Step[] { disableBreakpointStep }, finalRm);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deletes the target breakpoint with the given reference number.
|
||||
* @since 4.2
|
||||
*/
|
||||
protected void deleteBreakpointFromTarget(final IBreakpointsTargetDMContext context, final int reference, RequestMonitor finalRm) {
|
||||
final Step deleteBreakpointStep = new Step() {
|
||||
@Override
|
||||
public void execute(final RequestMonitor rm) {
|
||||
// Queue the command
|
||||
fConnection.queueCommand(
|
||||
fCommandFactory.createMIBreakDelete(context, new int[] { reference }),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||
}
|
||||
};
|
||||
|
||||
fRunControl.executeWithTargetAvailable(context, new Step[] { deleteBreakpointStep }, finalRm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
|
@ -1334,5 +1343,18 @@ public class MIBreakpoints extends AbstractDsfService implements IBreakpoints, I
|
|||
}
|
||||
fBreakpointHitMap.remove(container);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a breakpoint target context for given breakpoint number.
|
||||
* @since 4.2
|
||||
*/
|
||||
protected IBreakpointsTargetDMContext getBreakpointTargetContext(int reference) {
|
||||
for (IBreakpointsTargetDMContext context : fBreakpoints.keySet()) {
|
||||
Map<Integer, MIBreakpointDMData> map = fBreakpoints.get(context);
|
||||
if (map != null && map.keySet().contains(Integer.valueOf(reference))) {
|
||||
return context;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.eclipse.cdt.debug.core.model.ICBreakpoint;
|
|||
import org.eclipse.cdt.debug.core.model.ICBreakpointExtension;
|
||||
import org.eclipse.cdt.debug.core.model.ICBreakpointType;
|
||||
import org.eclipse.cdt.debug.core.model.ICEventBreakpoint;
|
||||
import org.eclipse.cdt.debug.core.model.ICFunctionBreakpoint;
|
||||
import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
|
||||
import org.eclipse.cdt.debug.core.model.ICTracepoint;
|
||||
import org.eclipse.cdt.debug.core.model.ICWatchpoint;
|
||||
|
@ -41,6 +42,7 @@ import org.eclipse.cdt.debug.internal.core.breakpoints.BreakpointProblems;
|
|||
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
|
||||
|
@ -82,6 +84,7 @@ import org.eclipse.core.resources.ResourcesPlugin;
|
|||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.ListenerList;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.ISchedulingRule;
|
||||
|
@ -104,7 +107,19 @@ import com.ibm.icu.text.MessageFormat;
|
|||
*/
|
||||
public class MIBreakpointsManager extends AbstractDsfService implements IBreakpointManagerListener, IBreakpointListener
|
||||
{
|
||||
// Note: Find a way to import this (careful of circular dependencies)
|
||||
/**
|
||||
* A listener is notified by {@link MIBreakpointsManager} when
|
||||
* the breakpoints tracking starts or stops.
|
||||
* @since 4.2
|
||||
*/
|
||||
public interface IMIBreakpointsTrackingListener {
|
||||
|
||||
public void breakpointTrackingStarted(IBreakpointsTargetDMContext bpTargetDMC);
|
||||
|
||||
public void breakpointTrackingStopped(IBreakpointsTargetDMContext bpTargetDMC);
|
||||
}
|
||||
|
||||
// Note: Find a way to import this (careful of circular dependencies)
|
||||
public final static String GDB_DEBUG_MODEL_ID = "org.eclipse.cdt.dsf.gdb"; //$NON-NLS-1$
|
||||
|
||||
// Extra breakpoint attributes
|
||||
|
@ -177,6 +192,8 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
|
|||
private Map<ICBreakpoint, IMarker> fBreakpointMarkerProblems =
|
||||
new HashMap<ICBreakpoint, IMarker>();
|
||||
|
||||
private ListenerList fTrackingListeners = new ListenerList();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// String constants
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -284,6 +301,7 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
|
|||
getSession().removeServiceEventListener(this);
|
||||
fBreakpointManager.removeBreakpointListener(this);
|
||||
fBreakpointManager.removeBreakpointManagerListener(this);
|
||||
fTrackingListeners.clear();
|
||||
|
||||
// Cleanup the breakpoints that are still installed by the service.
|
||||
// Use a counting monitor which will call mom to complete the shutdown
|
||||
|
@ -369,7 +387,16 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
|
|||
getExecutor().submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
installInitialBreakpoints(dmc, rm);
|
||||
installInitialBreakpoints(dmc, new RequestMonitor(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// Notify breakpoints tracking listeners that the tracking is started.
|
||||
for (Object o : fTrackingListeners.getListeners()) {
|
||||
((IMIBreakpointsTrackingListener)o).breakpointTrackingStarted(dmc);
|
||||
}
|
||||
rm.done();
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -491,6 +518,10 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
|
|||
fBreakpointIDs.remove(dmc);
|
||||
fTargetBPs.remove(dmc);
|
||||
fBreakpointThreads.remove(dmc);
|
||||
// Notify breakpoints tracking listeners that the tracking is stopped.
|
||||
for (Object o : fTrackingListeners.getListeners()) {
|
||||
((IMIBreakpointsTrackingListener)o).breakpointTrackingStopped(dmc);
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
};
|
||||
|
@ -549,7 +580,9 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
|
|||
}
|
||||
|
||||
// Ensure the breakpoint has a valid debugger source path
|
||||
if (breakpoint instanceof ICLineBreakpoint && !(breakpoint instanceof ICAddressBreakpoint)) {
|
||||
if (breakpoint instanceof ICLineBreakpoint
|
||||
&& !(breakpoint instanceof ICAddressBreakpoint)
|
||||
&& !(breakpoint instanceof ICFunctionBreakpoint)) {
|
||||
String debuggerPath = (String) attributes.get(ATTR_DEBUGGER_PATH);
|
||||
if (debuggerPath == null || debuggerPath == NULL_STRING) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, NO_DEBUGGER_PATH, null));
|
||||
|
@ -719,8 +752,10 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
|
|||
* @param dmc
|
||||
* @param breakpoint
|
||||
* @param rm
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
private void uninstallBreakpoint(final IBreakpointsTargetDMContext dmc,
|
||||
public void uninstallBreakpoint(final IBreakpointsTargetDMContext dmc,
|
||||
final ICBreakpoint breakpoint, final RequestMonitor rm)
|
||||
{
|
||||
// Retrieve the breakpoint maps
|
||||
|
@ -1809,16 +1844,6 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
|
|||
properties.put(MIBreakpoints.PASS_COUNT, attributes.get(ICTracepoint.PASS_COUNT));
|
||||
}
|
||||
|
||||
// checks for the breakpoint type, and adds the hardware/temporary flags
|
||||
Object breakpointType = attributes.get(ICBreakpointType.TYPE);
|
||||
if(breakpointType != null) {
|
||||
if(breakpointType instanceof Integer) {
|
||||
boolean isHardware = ((Integer) breakpointType & ICBreakpointType.HARDWARE) == ICBreakpointType.HARDWARE;
|
||||
boolean isTemporary = ((Integer) breakpointType & ICBreakpointType.TEMPORARY) == ICBreakpointType.TEMPORARY;
|
||||
properties.put(MIBreakpointDMData.IS_HARDWARE, isHardware);
|
||||
properties.put(MIBreakpointDMData.IS_TEMPORARY, isTemporary);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (breakpoint instanceof ICEventBreakpoint) {
|
||||
properties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.CATCHPOINT);
|
||||
|
@ -1845,6 +1870,17 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
|
|||
properties.put(MIBreakpoints.IS_ENABLED, attributes.get(ICBreakpoint.ENABLED));
|
||||
properties.put(MIBreakpointDMData.THREAD_ID, attributes.get(ATTR_THREAD_ID));
|
||||
|
||||
// checks for the breakpoint type, and adds the hardware/temporary flags
|
||||
Object breakpointType = attributes.get(ICBreakpointType.TYPE);
|
||||
if(breakpointType != null) {
|
||||
if(breakpointType instanceof Integer) {
|
||||
boolean isHardware = ((Integer) breakpointType & ICBreakpointType.HARDWARE) == ICBreakpointType.HARDWARE;
|
||||
boolean isTemporary = ((Integer) breakpointType & ICBreakpointType.TEMPORARY) == ICBreakpointType.TEMPORARY;
|
||||
properties.put(MIBreakpointDMData.IS_HARDWARE, isHardware);
|
||||
properties.put(MIBreakpointDMData.IS_TEMPORARY, isTemporary);
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust for "skip-all"
|
||||
// Tracepoints are not affected by "skip-all"
|
||||
if (!(breakpoint instanceof ICTracepoint ) && !fBreakpointManager.isEnabled()) {
|
||||
|
@ -1928,4 +1964,18 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.2
|
||||
*/
|
||||
public void addBreakpointsTrackingListener(IMIBreakpointsTrackingListener listener) {
|
||||
fTrackingListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.2
|
||||
*/
|
||||
public void removeBreakpointsTrackingListener(IMIBreakpointsTrackingListener listener) {
|
||||
fTrackingListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -81,7 +81,8 @@ public class MIBreakpoint {
|
|||
String threadId = "0"; //$NON-NLS-1$
|
||||
int ignore = 0;
|
||||
String commands = ""; //$NON-NLS-1$
|
||||
|
||||
String originalLocation = ""; //$NON-NLS-1$
|
||||
|
||||
// For tracepoints
|
||||
int passcount = 0;
|
||||
|
||||
|
@ -145,6 +146,7 @@ public class MIBreakpoint {
|
|||
isCatchpoint = other.isCatchpoint;
|
||||
catchpointType = other.catchpointType;
|
||||
pending = other.pending;
|
||||
originalLocation = other.originalLocation;
|
||||
if (other.groupIds != null) {
|
||||
groupIds = Arrays.copyOf(other.groupIds, other.groupIds.length);
|
||||
}
|
||||
|
@ -292,6 +294,13 @@ public class MIBreakpoint {
|
|||
return exp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.2
|
||||
*/
|
||||
public String getOriginalLocation() {
|
||||
return originalLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* If isCatchpoint is true, then this indicates the type of catchpoint
|
||||
* (event), as reported by gdb in its response to the CLI catch command.
|
||||
|
@ -487,6 +496,9 @@ public class MIBreakpoint {
|
|||
type.startsWith("fast tracepoint")) { //$NON-NLS-1$
|
||||
isTpt = true;
|
||||
}
|
||||
if (type.startsWith("catchpoint")) { //$NON-NLS-1$
|
||||
isCatchpoint = true;
|
||||
}
|
||||
// type="breakpoint"
|
||||
// default ok.
|
||||
} else if (var.equals("disp")) { //$NON-NLS-1$
|
||||
|
@ -541,6 +553,8 @@ public class MIBreakpoint {
|
|||
if (value instanceof MIList) {
|
||||
parseGroups((MIList)value);
|
||||
}
|
||||
} else if (var.equals("original-location")) { //$NON-NLS-1$
|
||||
originalLocation = str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue