diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/CDIDebugModel.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/CDIDebugModel.java
index 43539805dc7..e02da67b6d6 100644
--- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/CDIDebugModel.java
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/CDIDebugModel.java
@@ -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:
+ *
+ *
Failure creating underlying marker. The exception's
+ * status contains the underlying exception responsible for the
+ * failure.
+ *
+ *
+ * @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 attributes = new HashMap(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 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
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/CDebugUtils.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/CDebugUtils.java
index ed986b883e7..f88761ee33a 100644
--- a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/CDebugUtils.java
+++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/CDebugUtils.java
@@ -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();
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ServicesLaunchSequence.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ServicesLaunchSequence.java
index ad15fc60642..02d071d3ded 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ServicesLaunchSequence.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ServicesLaunchSequence.java
@@ -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;
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBreakpoints_7_4.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBreakpoints_7_4.java
new file mode 100644
index 00000000000..c58005eb554
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBreakpoints_7_4.java
@@ -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());
+
+ 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 attributes, DataRequestMonitor 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 attributes, DataRequestMonitor 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 attributes, DataRequestMonitor 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);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
index 27501dff4ee..9b9e772cd0c 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
@@ -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);
+ }
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpoints.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpoints.java
index dcf41fb7361..55caaebfa8d 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpoints.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpoints.java
@@ -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(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(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 map = fBreakpoints.get(context);
+ if (map != null && map.keySet().contains(Integer.valueOf(reference))) {
+ return context;
+ }
+ }
+ return null;
+ }
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java
index 65b26f7d2c0..629014d30a6 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java
@@ -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 fBreakpointMarkerProblems =
new HashMap();
+ 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);
+ }
}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsSynchronizer.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsSynchronizer.java
new file mode 100644
index 00000000000..aa74559bdb4
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsSynchronizer.java
@@ -0,0 +1,1278 @@
+/*******************************************************************************
+ * 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.mi.service;
+
+import java.io.File;
+import java.math.BigInteger;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.cdt.core.IAddress;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.debug.core.CDIDebugModel;
+import org.eclipse.cdt.debug.core.breakpointactions.BreakpointActionManager;
+import org.eclipse.cdt.debug.core.model.ICAddressBreakpoint;
+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.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;
+import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
+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.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMData;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
+import org.eclipse.cdt.dsf.debug.service.IDsfBreakpointExtension;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+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.ISourceLookup;
+import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.CollectAction;
+import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.EvaluateAction;
+import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.ITracepointAction;
+import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.TracepointActionManager;
+import org.eclipse.cdt.dsf.gdb.internal.tracepointactions.WhileSteppingAction;
+import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.MIBreakpointDMContext;
+import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager.IMIBreakpointsTrackingListener;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
+import org.eclipse.cdt.dsf.service.AbstractDsfService;
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.utils.Addr64;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Provides synchronization between breakpoints set from outside of the Eclipse breakpoint
+ * framework (GDB console, trace files, etc.) and the Breakpoints view.
+ * @since 4.2
+ */
+public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMIBreakpointsTrackingListener {
+
+ // Catchpoint expressions
+ private static final String CE_EXCEPTION_CATCH = "exception catch"; //$NON-NLS-1$
+ private static final String CE_EXCEPTION_THROW = "exception throw"; //$NON-NLS-1$
+
+ // GDB tracepoint commands
+ private static final String TC_COLLECT = "collect "; //$NON-NLS-1$
+ private static final String TC_TEVAL = "teval "; //$NON-NLS-1$
+ private static final String TC_WHILE_STEPPING = "while-stepping "; //$NON-NLS-1$
+ private static final String TC_END = "end"; //$NON-NLS-1$
+
+ private IMICommandControl fConnection;
+ private MIBreakpoints fBreakpointsService;
+ private MIBreakpointsManager fBreakpointsManager;
+
+ /**
+ * Collection of the target contexts that are being tracked.
+ */
+ private Set fTrackedTargets;
+
+ /**
+ * Collection of breakpoints created from the GDB console or outside of Eclipse
+ */
+ private Map> fCreatedTargetBreakpoints;
+
+ /**
+ * Collection of breakpoints deleted from the GDB console or outside of Eclipse
+ */
+ private Map> fDeletedTargetBreakpoints;
+
+ /**
+ * Collection of pending breakpoint modifications
+ */
+ private Map> fPendingModifications;
+
+ public MIBreakpointsSynchronizer(DsfSession session) {
+ super(session);
+ fTrackedTargets = new HashSet();
+ fCreatedTargetBreakpoints = new HashMap>();
+ fDeletedTargetBreakpoints = new HashMap>();
+ fPendingModifications = new HashMap>();
+ }
+
+ @Override
+ protected BundleContext getBundleContext() {
+ return GdbPlugin.getBundleContext();
+ }
+
+ @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);
+ fBreakpointsService = getServicesTracker().getService(MIBreakpoints.class);
+ fBreakpointsManager = getServicesTracker().getService(MIBreakpointsManager.class);
+ if (fConnection == null || fBreakpointsService == null && fBreakpointsManager == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Service is not available")); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+ fBreakpointsManager.addBreakpointsTrackingListener(this);
+ getSession().addServiceEventListener(this, null);
+
+ // Register this service
+ register(new String[] {
+ MIBreakpointsSynchronizer.class.getName()
+ },
+ new Hashtable());
+
+ rm.done();
+ }
+
+ @Override
+ public void shutdown(RequestMonitor rm) {
+ fTrackedTargets.clear();
+ fCreatedTargetBreakpoints.clear();
+ fDeletedTargetBreakpoints.clear();
+ fPendingModifications.clear();
+ getSession().removeServiceEventListener(this);
+ MIBreakpointsManager bm = getBreakpointsManager();
+ if (bm != null) {
+ bm.removeBreakpointsTrackingListener(this);
+ }
+ unregister();
+ super.shutdown( rm );
+ }
+
+ @Override
+ public void breakpointTrackingStarted(IBreakpointsTargetDMContext bpTargetDMC) {
+ fTrackedTargets.add(bpTargetDMC);
+ }
+
+ @Override
+ public void breakpointTrackingStopped(IBreakpointsTargetDMContext bpTargetDMC) {
+ fTrackedTargets.remove(bpTargetDMC);
+ }
+
+ private IMICommandControl getCommandControl() {
+ return fConnection;
+ }
+
+ private MIBreakpoints getBreakpointsService() {
+ return fBreakpointsService;
+ }
+
+ private MIBreakpointsManager getBreakpointsManager() {
+ return fBreakpointsManager;
+ }
+
+ public void targetBreakpointCreated(final MIBreakpoint miBpt) {
+ if (isCatchpoint(miBpt))
+ return;
+ ICommandControlService commandControl = getCommandControl();
+ MIBreakpoints breakpointsService = getBreakpointsService();
+ final MIBreakpointsManager bm = getBreakpointsManager();
+ if (commandControl == null || breakpointsService == null || bm == null)
+ return;
+
+ final IBreakpointsTargetDMContext bpTargetDMC = getBreakpointsTargetContext(commandControl, miBpt);
+ if (bpTargetDMC == null)
+ return;
+
+ // Store the target breakpoint data
+ Map contextBreakpoints = breakpointsService.getBreakpointMap(bpTargetDMC);
+ if (contextBreakpoints == null) {
+ contextBreakpoints = breakpointsService.createNewBreakpointMap(bpTargetDMC);
+ }
+ contextBreakpoints.put(Integer.valueOf(miBpt.getNumber()), new MIBreakpointDMData(miBpt));
+
+ // Store the created target breakpoint to prevent setting it again on the target
+ // when addBreakpoint() is called.
+ Map targetMap = fCreatedTargetBreakpoints.get(bpTargetDMC);
+ if (targetMap == null) {
+ targetMap = new HashMap();
+ fCreatedTargetBreakpoints.put(bpTargetDMC, targetMap);
+ }
+ targetMap.put(Integer.valueOf(miBpt.getNumber()), miBpt);
+
+ // Convert the debug info file path into the file path in the local file system
+ String debuggerPath = getFileName(miBpt);
+ getSource(
+ bpTargetDMC,
+ debuggerPath,
+ new DataRequestMonitor(getExecutor(), null) {
+ @Override
+ @ConfinedToDsfExecutor( "fExecutor" )
+ protected void handleSuccess() {
+ String fileName = getData();
+ if (fileName == null)
+ fileName = getFileName(miBpt);
+ // Try to find matching platform breakpoint
+ ICBreakpoint plBpt = getPlatformBreakpoint(miBpt, fileName);
+ String threadId = miBpt.getThreadId();
+ boolean isThreadSpecific = threadId != null && !threadId.isEmpty() && !"0".equals(threadId); //$NON-NLS-1$
+ try {
+ if (plBpt == null) {
+ // If matching platform breakpoint doesn't exist create a new one
+ plBpt = createPlatformBreakpoint(fileName, miBpt);
+ // If the target breakpoint is thread specific, update thread filters
+ if (isThreadSpecific) {
+ setThreadSpecificBreakpoint(bpTargetDMC, plBpt, miBpt);
+ }
+ }
+ else {
+ // The corresponding platform breakpoint already exists.
+ // If the breakpoint tracking has already started we need
+ // to notify MIBreakpointsManager which will increment its
+ // install count.
+ // Otherwise the breakpoint will be processed as an initial
+ // breakpoint when the breakpoint tracking starts.
+ if (isBreakpointTargetTracked(bpTargetDMC)) {
+ // If the target breakpoint is thread specific, update thread filters
+ if (isThreadSpecific) {
+ setThreadSpecificBreakpoint(bpTargetDMC, plBpt, miBpt);
+ }
+ bm.breakpointAdded(plBpt);
+ }
+ }
+ // Make sure the platform breakpoint's parameters are synchronized
+ // with the target breakpoint.
+ Map map = fPendingModifications.get(bpTargetDMC);
+ if (map != null) {
+ MIBreakpoint mod = map.remove(Integer.valueOf(miBpt.getNumber()));
+ if (mod != null) {
+ targetBreakpointModified(bpTargetDMC, plBpt, mod);
+ }
+ }
+ else {
+ targetBreakpointModified(bpTargetDMC, plBpt, miBpt);
+ }
+ }
+ catch(CoreException e) {
+ GdbPlugin.log(getStatus());
+ }
+ super.handleSuccess();
+ }
+ });
+ }
+
+ public void targetBreakpointDeleted(final int id) {
+ MIBreakpoints breakpointsService = getBreakpointsService();
+ final MIBreakpointsManager bm = getBreakpointsManager();
+ if (breakpointsService == null || bm == null)
+ return;
+ final IBreakpointsTargetDMContext bpTargetDMC = breakpointsService.getBreakpointTargetContext(id);
+ final IContainerDMContext contDMC = DMContexts.getAncestorOfType(bpTargetDMC, IContainerDMContext.class);
+ if (contDMC == null)
+ return;
+ if (bpTargetDMC != null){
+ final MIBreakpointDMContext bpDMC =
+ new MIBreakpointDMContext(breakpointsService, new IDMContext[] { bpTargetDMC }, id);
+ breakpointsService.getBreakpointDMData(
+ bpDMC,
+ new DataRequestMonitor(getExecutor(), null) {
+ @Override
+ @ConfinedToDsfExecutor( "fExecutor" )
+ protected void handleSuccess() {
+ if (!(getData() instanceof MIBreakpointDMData))
+ return;
+ MIBreakpointDMData data = (MIBreakpointDMData)getData();
+ if (MIBreakpoints.CATCHPOINT.equals(data.getBreakpointType()))
+ return;
+
+ IBreakpoint plBpt = bm.findPlatformBreakpoint(bpDMC);
+ if (plBpt instanceof ICBreakpoint) {
+ Set set = fDeletedTargetBreakpoints.get(bpTargetDMC);
+ if (set == null) {
+ set = new HashSet();
+ fDeletedTargetBreakpoints.put(bpTargetDMC, set);
+ }
+ set.add(Integer.valueOf(id));
+
+ try {
+ int threadId = Integer.parseInt(data.getThreadId());
+ if (threadId > 0) {
+ IDsfBreakpointExtension bpExtension =
+ (IDsfBreakpointExtension)((ICBreakpoint)plBpt).getExtension(
+ MIBreakpointsManager.GDB_DEBUG_MODEL_ID, ICBreakpointExtension.class);
+ IExecutionDMContext[] execDMCs = bpExtension.getThreadFilters(contDMC);
+ List list = new ArrayList(execDMCs.length);
+ for (IExecutionDMContext c : execDMCs) {
+ if (c instanceof IMIExecutionDMContext
+ && ((IMIExecutionDMContext)c).getThreadId() != threadId)
+ list.add(c);
+ }
+ if (list.size() > 0) {
+ bpExtension.setThreadFilters(list.toArray(new IExecutionDMContext[list.size()]));
+ }
+ else {
+ bm.uninstallBreakpoint(bpTargetDMC, (ICBreakpoint)plBpt, new RequestMonitor(getExecutor(), null));
+ }
+ }
+ else {
+ bm.uninstallBreakpoint(bpTargetDMC, (ICBreakpoint)plBpt, new RequestMonitor(getExecutor(), null));
+ }
+ }
+ catch(CoreException e) {
+ GdbPlugin.log(e.getStatus());
+ }
+ catch(NumberFormatException e) {
+ GdbPlugin.log(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Invalid thread id")); //$NON-NLS-1$
+ }
+ }
+ }
+ });
+
+ }
+ }
+
+ public void targetBreakpointModified(final MIBreakpoint miBpt) {
+ if (isCatchpoint(miBpt))
+ return;
+ ICommandControlService commandControl = getCommandControl();
+ MIBreakpoints breakpointsService = getBreakpointsService();
+ final MIBreakpointsManager bm = getBreakpointsManager();
+ if (commandControl != null && breakpointsService != null && bm != null) {
+ final IBreakpointsTargetDMContext bpTargetDMC = getBreakpointsTargetContext(commandControl, miBpt);
+ if (bpTargetDMC == null)
+ return;
+ final Map contextBreakpoints = breakpointsService.getBreakpointMap(bpTargetDMC);
+ if (contextBreakpoints == null)
+ return;
+ IBreakpoint b = bm.findPlatformBreakpoint(
+ new MIBreakpointDMContext(breakpointsService, new IDMContext[] { bpTargetDMC }, miBpt.getNumber()));
+ if (!(b instanceof ICBreakpoint)) {
+ // Platform breakpoint hasn't been created yet. Store the latest
+ // modification data, it will be picked up later.
+ Map map = fPendingModifications.get(bpTargetDMC);
+ if (map == null) {
+ map = new HashMap();
+ fPendingModifications.put(bpTargetDMC, map);
+ }
+ map.put(Integer.valueOf(miBpt.getNumber()), miBpt);
+ }
+ else {
+ ICBreakpoint plBpt = (ICBreakpoint)b;
+ targetBreakpointModified(bpTargetDMC, plBpt, miBpt);
+ }
+ }
+ }
+
+ private void targetBreakpointModified(
+ IBreakpointsTargetDMContext bpTargetDMC,
+ ICBreakpoint plBpt,
+ MIBreakpoint miBpt) {
+ Map contextBreakpoints = getBreakpointsService().getBreakpointMap(bpTargetDMC);
+ MIBreakpointDMData oldData = contextBreakpoints.get(Integer.valueOf(miBpt.getNumber()));
+ contextBreakpoints.put(Integer.valueOf(miBpt.getNumber()), new MIBreakpointDMData(miBpt));
+ try {
+ if (plBpt.isEnabled() != miBpt.isEnabled()) {
+ plBpt.setEnabled(miBpt.isEnabled());
+ }
+ if (!plBpt.getCondition().equals(miBpt.getCondition())) {
+ plBpt.setCondition(miBpt.getCondition());
+ }
+ if (plBpt.getIgnoreCount() != miBpt.getIgnoreCount()) {
+ plBpt.setIgnoreCount(miBpt.getIgnoreCount());
+ }
+ if (oldData.isPending() != miBpt.isPending()) {
+ if (miBpt.isPending())
+ plBpt.decrementInstallCount();
+ else
+ plBpt.incrementInstallCount();
+ }
+ if (plBpt instanceof ICTracepoint && miBpt.isTracepoint()) {
+ ICTracepoint plTpt = (ICTracepoint)plBpt;
+ if (plTpt.getPassCount() != miBpt.getPassCount()) {
+ // GDB (up to 7.5) doesn't emit notification when the pass count is modified.
+ plTpt.setPassCount(miBpt.getPassCount());
+ }
+
+ if (!miBpt.getCommands().equals(plBpt.getMarker().getAttribute(BreakpointActionManager.BREAKPOINT_ACTION_ATTRIBUTE))) {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ String[] commands = miBpt.getCommands().split(TracepointActionManager.TRACEPOINT_ACTION_DELIMITER);
+ for (ITracepointAction action : getActionsFromCommands(commands)) {
+ if (first)
+ first = false;
+ else
+ sb.append(TracepointActionManager.TRACEPOINT_ACTION_DELIMITER);
+ sb.append(action.getName());
+ }
+ // Target breakpoints and platform breakpoints use the same format
+ // to store trace commands. This format is different than the format
+ // used by GDB. We need to switch to the platform format to avoid unnecessary
+ // modifications of target breakpoints.
+ miBpt.setCommands(sb.toString());
+ plBpt.getMarker().setAttribute(
+ BreakpointActionManager.BREAKPOINT_ACTION_ATTRIBUTE, sb.toString());
+ }
+ }
+ }
+ catch(CoreException e) {
+ contextBreakpoints.put(Integer.valueOf(miBpt.getNumber()), oldData);
+ GdbPlugin.log(e.getStatus());
+ }
+ }
+
+ private void setThreadSpecificBreakpoint(
+ IBreakpointsTargetDMContext bpTargetDMC,
+ final ICBreakpoint plBpt,
+ MIBreakpoint miBpt) {
+
+ try {
+ IContainerDMContext contDMC = DMContexts.getAncestorOfType(bpTargetDMC, IContainerDMContext.class);
+ if (contDMC == null) {
+ return;
+ }
+ IProcessDMContext procDmc =
+ DMContexts.getAncestorOfType(contDMC, IProcessDMContext.class);
+ if (procDmc == null) {
+ return;
+ }
+ IMIProcesses processes = getServicesTracker().getService(IMIProcesses.class);
+ if (processes == null) {
+ return;
+ }
+ IDsfBreakpointExtension bpExtension = (IDsfBreakpointExtension)plBpt.getExtension(
+ MIBreakpointsManager.GDB_DEBUG_MODEL_ID, ICBreakpointExtension.class);
+ IExecutionDMContext[] execDMCs = bpExtension.getThreadFilters(contDMC);
+ if (execDMCs == null) {
+ execDMCs = new IExecutionDMContext[0];
+ }
+ int threadId = Integer.parseInt(miBpt.getThreadId());
+ for (IExecutionDMContext execDMC : execDMCs) {
+ if (execDMC instanceof IMIExecutionDMContext
+ && ((IMIExecutionDMContext)execDMC).getThreadId() == threadId) {
+ // The platform breakpoint is already restricted to the given thread.
+ return;
+ }
+ }
+ IExecutionDMContext[] newExecDMCs = new IExecutionDMContext[execDMCs.length + 1];
+ System.arraycopy(execDMCs, 0, newExecDMCs, 0, execDMCs.length);
+ newExecDMCs[execDMCs.length] = processes.createExecutionContext(
+ contDMC,
+ processes.createThreadContext(procDmc, miBpt.getThreadId()),
+ miBpt.getThreadId());
+ bpExtension.setThreadFilters(newExecDMCs);
+ }
+ catch(NumberFormatException e) {
+ GdbPlugin.log(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Invalid thread id")); //$NON-NLS-1$
+ }
+ catch(CoreException e) {
+ GdbPlugin.log(e);
+ }
+ }
+
+ private ICBreakpoint getPlatformBreakpoint(MIBreakpoint miBpt, String fileName) {
+ for (IBreakpoint b : DebugPlugin.getDefault().getBreakpointManager().getBreakpoints()) {
+ if (b instanceof ICTracepoint
+ && miBpt.isTracepoint()
+ && isPlatformTracepoint((ICTracepoint)b, miBpt, fileName)) {
+ return (ICBreakpoint)b;
+ }
+ if (b instanceof ICWatchpoint
+ && miBpt.isWatchpoint()
+ && isPlatformWatchpoint((ICWatchpoint)b, miBpt)) {
+ return (ICBreakpoint)b;
+ }
+ if (b instanceof ICLineBreakpoint
+ && !miBpt.isWatchpoint()
+ && !isCatchpoint(miBpt)
+ && !miBpt.isTracepoint()
+ && isPlatformLineBreakpoint((ICLineBreakpoint)b, miBpt, fileName)) {
+ return (ICBreakpoint)b;
+ }
+ }
+ return null;
+ }
+
+ private ICBreakpoint createPlatformBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
+ if (miBpt.isWatchpoint()) {
+ return createPlatformWatchpoint(fileName, miBpt);
+ }
+ else if (miBpt.isTracepoint()) {
+ return createPlatformTracepoint(fileName, miBpt);
+ }
+ else {
+ return createPlatformLocationBreakpoint(fileName, miBpt);
+ }
+ }
+
+ private ICBreakpoint createPlatformLocationBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
+ if (isAddressBreakpoint(miBpt)) {
+ return createPlatformAddressBreakpoint(fileName, miBpt);
+ }
+ else if (isFunctionBreakpoint(miBpt)) {
+ return createPlatformFunctionBreakpoint(fileName, miBpt);
+ }
+ else {
+ return createPlatformLineBreakpoint(fileName, miBpt);
+ }
+ }
+
+ private ICBreakpoint createPlatformAddressBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
+ IResource resource = getResource(fileName);
+
+ int type = 0;
+ if (miBpt.isTemporary())
+ type |= ICBreakpointType.TEMPORARY;
+ if (miBpt.isHardware())
+ type |= ICBreakpointType.HARDWARE;
+
+ try {
+ return CDIDebugModel.createAddressBreakpoint(
+ null,
+ null,
+ resource,
+ type,
+ getPlatformAddress(miBpt.getAddress()),
+ miBpt.isEnabled(),
+ miBpt.getIgnoreCount(),
+ miBpt.getCondition(),
+ true);
+ }
+ catch(NumberFormatException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.getUniqueIdentifier(),
+ String.format("Invalid breakpoint addres: %s", miBpt.getAddress()))); //$NON-NLS-1$
+ }
+ }
+
+ private ICBreakpoint createPlatformFunctionTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
+ IResource resource = getResource(fileName);
+
+ int type = 0;
+ if (miBpt.isTemporary())
+ type |= ICBreakpointType.TEMPORARY;
+ if (miBpt.isHardware())
+ type |= ICBreakpointType.HARDWARE;
+
+ return CDIDebugModel.createFunctionTracepoint(
+ fileName,
+ resource,
+ type,
+ getFunctionName(miBpt),
+ -1,
+ -1,
+ getLineNumber(miBpt),
+ miBpt.isEnabled(),
+ miBpt.getIgnoreCount(),
+ miBpt.getCondition(),
+ true);
+ }
+
+ private ICBreakpoint createPlatformLineTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
+ IResource resource = getResource(fileName);
+
+ int type = 0;
+ if (miBpt.isTemporary())
+ type |= ICBreakpointType.TEMPORARY;
+ if (miBpt.isHardware())
+ type |= ICBreakpointType.HARDWARE;
+
+ return CDIDebugModel.createLineTracepoint(
+ fileName,
+ resource,
+ type,
+ getLineNumber(miBpt),
+ miBpt.isEnabled(),
+ miBpt.getIgnoreCount(),
+ miBpt.getCondition(),
+ true);
+ }
+
+ private ICBreakpoint createPlatformTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
+ if (isAddressBreakpoint(miBpt)) {
+ return createPlatformAddressTracepoint(fileName, miBpt);
+ }
+ else if (isFunctionBreakpoint(miBpt)) {
+ return createPlatformFunctionTracepoint(fileName, miBpt);
+ }
+ else {
+ return createPlatformLineTracepoint(fileName, miBpt);
+ }
+ }
+
+ private ICBreakpoint createPlatformAddressTracepoint(String fileName, MIBreakpoint miBpt) throws CoreException {
+ IResource resource = getResource(fileName);
+
+ int type = 0;
+ if (miBpt.isTemporary())
+ type |= ICBreakpointType.TEMPORARY;
+ if (miBpt.isHardware())
+ type |= ICBreakpointType.HARDWARE;
+
+ try {
+ return CDIDebugModel.createAddressTracepoint(
+ null,
+ null,
+ resource,
+ type,
+ getLineNumber(miBpt),
+ getPlatformAddress(miBpt.getAddress()),
+ miBpt.isEnabled(),
+ miBpt.getIgnoreCount(),
+ miBpt.getCondition(),
+ true);
+ }
+ catch(NumberFormatException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.getUniqueIdentifier(),
+ String.format("Invalid breakpoint addres: %s", miBpt.getAddress()))); //$NON-NLS-1$
+ }
+ }
+
+ private ICBreakpoint createPlatformFunctionBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
+ IResource resource = getResource(fileName);
+
+ int type = 0;
+ if (miBpt.isTemporary())
+ type |= ICBreakpointType.TEMPORARY;
+ if (miBpt.isHardware())
+ type |= ICBreakpointType.HARDWARE;
+
+ return CDIDebugModel.createFunctionBreakpoint(
+ fileName,
+ resource,
+ type,
+ getFunctionName(miBpt),
+ -1,
+ -1,
+ getLineNumber(miBpt),
+ miBpt.isEnabled(),
+ miBpt.getIgnoreCount(),
+ miBpt.getCondition(),
+ true);
+ }
+
+ private ICBreakpoint createPlatformLineBreakpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
+ IResource resource = getResource(fileName);
+
+ int type = 0;
+ if (miBpt.isTemporary())
+ type |= ICBreakpointType.TEMPORARY;
+ if (miBpt.isHardware())
+ type |= ICBreakpointType.HARDWARE;
+
+ return CDIDebugModel.createLineBreakpoint(
+ fileName,
+ resource,
+ type,
+ getLineNumber(miBpt),
+ miBpt.isEnabled(),
+ miBpt.getIgnoreCount(),
+ miBpt.getCondition(),
+ true);
+ }
+
+ private ICBreakpoint createPlatformWatchpoint(String fileName, MIBreakpoint miBpt) throws CoreException {
+ IResource resource = getResource(fileName);
+
+ int type = 0;
+ if (miBpt.isTemporary())
+ type |= ICBreakpointType.TEMPORARY;
+ if (miBpt.isHardware())
+ type |= ICBreakpointType.HARDWARE;
+
+ return CDIDebugModel.createWatchpoint(
+ fileName,
+ resource,
+ type,
+ miBpt.isAccessWatchpoint() || miBpt.isWriteWatchpoint(),
+ miBpt.isAccessWatchpoint() || miBpt.isReadWatchpoint(),
+ miBpt.getExpression(),
+ miBpt.isEnabled(),
+ miBpt.getIgnoreCount(),
+ miBpt.getCondition(),
+ true);
+ }
+
+ private IBreakpointsTargetDMContext getBreakpointsTargetContext(ICommandControlService commandControl, MIBreakpoint miBpt) {
+ IMIProcesses processes = getServicesTracker().getService(IMIProcesses.class);
+ if (processes == null) {
+ return null;
+ }
+ String threadId = (miBpt != null) ? miBpt.getThreadId() : null;
+ IContainerDMContext contContext = processes.createContainerContextFromThreadId(commandControl.getContext(), threadId);
+ if (contContext == null) {
+ return null;
+ }
+ return DMContexts.getAncestorOfType(contContext, IBreakpointsTargetDMContext.class);
+ }
+
+ public MIBreakpoint getTargetBreakpoint(IBreakpointsTargetDMContext context, Map attributes) {
+ Map map = fCreatedTargetBreakpoints.get(context);
+ if (map == null)
+ return null;
+ String type = (String)attributes.get(MIBreakpoints.BREAKPOINT_TYPE);
+ if (MIBreakpoints.BREAKPOINT.equals(type)) {
+ return getTargetLineBreakpoint(
+ map.values(),
+ (String)attributes.get(MIBreakpoints.FILE_NAME),
+ (Integer)attributes.get(MIBreakpoints.LINE_NUMBER),
+ (String)attributes.get(MIBreakpoints.FUNCTION),
+ (String)attributes.get(MIBreakpoints.ADDRESS),
+ (Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE),
+ (Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY));
+
+ }
+ else if (MIBreakpoints.TRACEPOINT.equals(type)) {
+ return getTargetTracepoint(
+ map.values(),
+ (String)attributes.get(MIBreakpoints.FILE_NAME),
+ (Integer)attributes.get(MIBreakpoints.LINE_NUMBER),
+ (String)attributes.get(MIBreakpoints.FUNCTION),
+ (String)attributes.get(MIBreakpoints.ADDRESS),
+ (Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE),
+ (Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY));
+ }
+ else if (MIBreakpoints.WATCHPOINT.equals(type)) {
+ return getTargetWatchpoint(
+ map.values(),
+ (String)attributes.get(MIBreakpoints.EXPRESSION),
+ (Boolean)attributes.get(MIBreakpoints.READ),
+ (Boolean)attributes.get(MIBreakpoints.WRITE),
+ (Boolean)attributes.get(MIBreakpointDMData.IS_HARDWARE),
+ (Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY));
+
+ }
+ return null;
+ }
+
+ private MIBreakpoint getTargetLineBreakpoint(
+ Collection targetBreakpoints,
+ String fileName,
+ Integer lineNumber,
+ String function,
+ String address,
+ Boolean isHardware,
+ Boolean isTemporary) {
+ for (MIBreakpoint miBpt : targetBreakpoints) {
+ if (!miBpt.isWatchpoint() && !isCatchpoint(miBpt) && !miBpt.isTracepoint()
+ && compareBreakpointAttributes(
+ miBpt, fileName, lineNumber, function, address, isHardware, isTemporary))
+ return miBpt;
+ }
+ return null;
+ }
+
+ private MIBreakpoint getTargetTracepoint(
+ Collection targetBreakpoints,
+ String fileName,
+ Integer lineNumber,
+ String function,
+ String address,
+ Boolean isHardware,
+ Boolean isTemporary) {
+ for (MIBreakpoint miBpt : targetBreakpoints) {
+ if (miBpt.isTracepoint()
+ && compareBreakpointAttributes(
+ miBpt, fileName, lineNumber, function, address, isHardware, isTemporary))
+ return miBpt;
+ }
+ return null;
+ }
+
+ private MIBreakpoint getTargetWatchpoint(
+ Collection targetBreakpoints,
+ String expression,
+ boolean readAccess,
+ boolean writeAccess,
+ Boolean isHardware,
+ Boolean isTemporary) {
+ for (MIBreakpoint miBpt : targetBreakpoints) {
+ if (!miBpt.isWatchpoint())
+ continue;
+ if (expression == null || !expression.equals(miBpt.getExpression()))
+ continue;
+ if (readAccess && writeAccess && !miBpt.isAccessWatchpoint())
+ continue;
+ if (readAccess && !writeAccess && !miBpt.isReadWatchpoint())
+ continue;
+ if (!readAccess && writeAccess && !miBpt.isWriteWatchpoint())
+ continue;
+ if (!compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary))
+ continue;
+ return miBpt;
+ }
+ return null;
+ }
+
+ private boolean compareBreakpointAttributes(
+ MIBreakpoint miBpt,
+ String fileName,
+ Integer lineNumber,
+ String function,
+ String address,
+ Boolean isHardware,
+ Boolean isTemporary) {
+ return compareBreakpointLocationAttributes(miBpt, fileName, lineNumber, function, address)
+ && compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary);
+ }
+
+ private boolean compareBreakpointLocationAttributes(
+ MIBreakpoint miBpt,
+ String fileName,
+ Integer lineNumber,
+ String function,
+ String address) {
+ if (isFunctionBreakpoint(miBpt) && (function == null || !function.equals(getFunctionName(miBpt))))
+ return false;
+ if (isAddressBreakpoint(miBpt)
+ && (address == null || !address.equals(getPlatformAddress(miBpt.getAddress()).toHexAddressString())))
+ return false;
+ if (isLineBreakpoint(miBpt)) {
+ if (fileName == null || !fileName.equals(getFileName(miBpt)))
+ return false;
+ if (lineNumber == null || lineNumber.intValue() != getLineNumber(miBpt))
+ return false;
+ }
+ return true;
+ }
+
+ private boolean compareBreakpointTypeAttributes(MIBreakpoint miBpt, Boolean isHardware, Boolean isTemporary) {
+ if ((isHardware == null && miBpt.isHardware())
+ || (isHardware != null && isHardware.booleanValue() != miBpt.isHardware()))
+ return false;
+ if ((isTemporary == null && miBpt.isTemporary())
+ || (isTemporary != null && isTemporary.booleanValue() != miBpt.isTemporary()))
+ return false;
+ return true;
+ }
+
+ public void removeCreatedTargetBreakpoint(IBreakpointsTargetDMContext context, MIBreakpoint miBpt) {
+ Map map = fCreatedTargetBreakpoints.get(context);
+ if (map != null) {
+ map.remove(Integer.valueOf(miBpt.getNumber()));
+ }
+ }
+
+ private boolean isPlatformLineBreakpoint(ICLineBreakpoint plBpt, MIBreakpoint miBpt, String fileName) {
+ if (plBpt instanceof ICAddressBreakpoint) {
+ return isAddressBreakpoint(miBpt) ?
+ isPlatformAddressBreakpoint((ICAddressBreakpoint)plBpt, miBpt) : false;
+ }
+ if (plBpt instanceof ICFunctionBreakpoint) {
+ return isFunctionBreakpoint(miBpt) ?
+ isPlatformFunctionBreakpoint((ICFunctionBreakpoint)plBpt, miBpt) : false;
+ }
+ try {
+ if (fileName == null || !fileName.equals(plBpt.getSourceHandle()))
+ return false;
+ if (plBpt.getLineNumber() != getLineNumber(miBpt))
+ return false;
+ return true;
+ }
+ catch(CoreException e) {
+ GdbPlugin.log(e.getStatus());
+ }
+ return false;
+ }
+
+ private boolean isPlatformFunctionBreakpoint(ICFunctionBreakpoint plBpt, MIBreakpoint miBpt) {
+ try {
+ return (plBpt.getFunction() != null && plBpt.getFunction().equals(getFunctionName(miBpt)));
+ }
+ catch(CoreException e) {
+ GdbPlugin.log(e.getStatus());
+ }
+ return false;
+ }
+
+ private boolean isPlatformAddressBreakpoint(ICAddressBreakpoint plBpt, MIBreakpoint miBpt) {
+ try {
+ return (plBpt.getAddress() != null
+ && plBpt.getAddress().equals(getPlatformAddress(miBpt.getAddress()).toHexAddressString()));
+ }
+ catch(CoreException e) {
+ GdbPlugin.log(e.getStatus());
+ }
+ return false;
+ }
+
+ private boolean isPlatformWatchpoint(ICWatchpoint plBpt, MIBreakpoint miBpt) {
+ try {
+ if (plBpt.getExpression() != null && plBpt.getExpression().equals(miBpt.getExpression()) ) {
+ if (miBpt.isAccessWatchpoint())
+ return plBpt.isWriteType() && plBpt.isReadType();
+ else if (miBpt.isReadWatchpoint())
+ return !plBpt.isWriteType() && plBpt.isReadType();
+ else if (miBpt.isWriteWatchpoint())
+ return plBpt.isWriteType() && !plBpt.isReadType();
+ }
+ }
+ catch(CoreException e) {
+ GdbPlugin.log(e.getStatus());
+ }
+ return false;
+ }
+
+ private boolean isPlatformTracepoint(ICTracepoint plBpt, MIBreakpoint miBpt, String fileName) {
+ return isPlatformLineBreakpoint(plBpt, miBpt, fileName);
+ }
+
+ public boolean isTargetBreakpointDeleted(IBreakpointsTargetDMContext context, int bpId, boolean remove) {
+ Set set = fDeletedTargetBreakpoints.get(context);
+ if (set != null )
+ return (remove) ? set.remove(Integer.valueOf(bpId)) : set.contains(Integer.valueOf(bpId));
+ return false;
+ }
+
+ /**
+ * Returns the list of tracepoint actions generated from the given command string.
+ * If the corresponding action for a command doesn't exist in TracepointActionManager
+ * the new action is created and added.
+ *
+ * @param commands list of gdb tracepoint commands separated by TracepointActionManager.TRACEPOINT_ACTION_DELIMITER
+ */
+ private ITracepointAction[] getActionsFromCommands(String[] commands) {
+ List list = new ArrayList();
+ TracepointActionManager tam = TracepointActionManager.getInstance();
+ WhileSteppingAction whileStepping = null;
+ List subActions = null;
+ for (String command : commands) {
+ // Check if an action for this command exists
+ boolean found = false;
+ for (ITracepointAction action :tam.getActions()) {
+ if (command.equals(action.getSummary())) {
+ if (whileStepping == null || subActions == null)
+ list.add(action);
+ else
+ subActions.add(action);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // Create a new action if an action for this command doesn't exists
+ ITracepointAction action = null;
+ if (command.startsWith(TC_COLLECT))
+ action = createCollectAction(command.substring(TC_COLLECT.length()));
+ else if (command.startsWith(TC_TEVAL))
+ action = createEvaluateAction(command.substring(TC_TEVAL.length()));
+ else if (command.startsWith(TC_WHILE_STEPPING)) {
+ whileStepping = createWhileSteppingAction(command.substring(TC_WHILE_STEPPING.length()));
+ if (whileStepping != null)
+ subActions = new ArrayList();
+ }
+ else if (command.equals(TC_END)) {
+ if (whileStepping == null || subActions == null)
+ continue;
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (ITracepointAction a : subActions) {
+ if (first)
+ first = false;
+ else
+ sb.append(',');
+ sb.append(a.getName());
+ }
+ whileStepping.setSubActionsNames(sb.toString());
+ whileStepping.setSubActionsContent(sb.toString());
+ action = whileStepping;
+ // Search for existing action for this 'while-stepping' command
+ for (ITracepointAction a :tam.getActions()) {
+ if (whileStepping.getSummary().equals(a.getSummary())) {
+ action = a;
+ found = true;
+ break;
+ }
+ }
+ whileStepping = null;
+ subActions.clear();
+ subActions = null;
+ }
+ if (action != null) {
+ if (!found)
+ TracepointActionManager.getInstance().addAction(action);
+ if (whileStepping == null || subActions == null) {
+ list.add(action);
+ }
+ else {
+ subActions.add(action);
+ }
+ }
+ }
+ TracepointActionManager.getInstance().saveActionData();
+ }
+ return list.toArray(new ITracepointAction[list.size()]);
+ }
+
+ private CollectAction createCollectAction(String collectStr) {
+ CollectAction action = new CollectAction();
+ action.setName(TracepointActionManager.getInstance().makeUniqueActionName(action.getDefaultName()));
+ action.setCollectString(collectStr);
+ return action;
+ }
+
+ private EvaluateAction createEvaluateAction(String evalStr) {
+ EvaluateAction action = new EvaluateAction();
+ action.setName(TracepointActionManager.getInstance().makeUniqueActionName(action.getDefaultName()));
+ action.setEvalString(evalStr);
+ return action;
+ }
+
+ private WhileSteppingAction createWhileSteppingAction(String str) {
+ WhileSteppingAction action = new WhileSteppingAction();
+ action.setName(TracepointActionManager.getInstance().makeUniqueActionName(action.getDefaultName()));
+ try {
+ action.setStepCount(Integer.parseInt(str.trim()));
+ }
+ catch(NumberFormatException e) {
+ return null;
+ }
+ return action;
+ }
+
+ protected void getSource(
+ IBreakpointsTargetDMContext bpTargetDMC,
+ final String debuggerPath,
+ final DataRequestMonitor rm) {
+
+ ISourceLookup sourceLookup = getServicesTracker().getService(ISourceLookup.class);
+ if (sourceLookup == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "Source lookup service is not available")); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ ISourceLookupDMContext srcDmc = DMContexts.getAncestorOfType(bpTargetDMC, ISourceLookupDMContext.class);
+ if (srcDmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, "No source lookup context")); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ if (debuggerPath == null || debuggerPath.isEmpty()) {
+ rm.done();
+ return;
+ }
+
+ sourceLookup.getSource(
+ srcDmc,
+ debuggerPath,
+ new DataRequestMonitor