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 index c58005eb554..4b871a9a251 100644 --- 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 @@ -14,6 +14,7 @@ package org.eclipse.cdt.dsf.gdb.service; import java.util.Hashtable; import java.util.Map; +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; @@ -169,72 +170,117 @@ public class GDBBreakpoints_7_4 extends GDBBreakpoints_7_2 implements IEventList } @Override - protected void addBreakpoint(IBreakpointsTargetDMContext context, Map attributes, DataRequestMonitor finalRm) { - MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class); + protected void addBreakpoint( + final IBreakpointsTargetDMContext context, + final Map attributes, + final DataRequestMonitor finalRm) { + final 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; - } + bs.getTargetBreakpoint( + context, + attributes, + new DataRequestMonitor(getExecutor(), finalRm) { + @Override + @ConfinedToDsfExecutor( "fExecutor" ) + protected void handleSuccess() { + MIBreakpoint miBpt = getData(); + if (miBpt != null) { + bs.removeCreatedTargetBreakpoint(context, miBpt); + MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt); + getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint); + IBreakpointDMContext dmc = + new MIBreakpointDMContext(GDBBreakpoints_7_4.this, new IDMContext[] { context }, newBreakpoint.getNumber()); + finalRm.setData(dmc); + getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties()); + finalRm.done(); + } + else { + GDBBreakpoints_7_4.super.addBreakpoint(context, attributes, finalRm); + } + } + }); + } + else { + super.addBreakpoint(context, attributes, finalRm); } - super.addBreakpoint(context, attributes, finalRm); } @Override - protected void addTracepoint(IBreakpointsTargetDMContext context, Map attributes, DataRequestMonitor drm) { - MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class); + protected void addTracepoint( + final IBreakpointsTargetDMContext context, + final Map attributes, + final DataRequestMonitor drm) { + final 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; - } + bs.getTargetBreakpoint( + context, + attributes, + new DataRequestMonitor(getExecutor(), drm) { + @Override + @ConfinedToDsfExecutor( "fExecutor" ) + protected void handleSuccess() { + MIBreakpoint miBpt = getData(); + if (miBpt != null) { + bs.removeCreatedTargetBreakpoint(context, miBpt); + MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt); + getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint); + IBreakpointDMContext dmc = + new MIBreakpointDMContext(GDBBreakpoints_7_4.this, new IDMContext[] { context }, newBreakpoint.getNumber()); + drm.setData(dmc); + getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties()); + drm.done(); + } + else { + GDBBreakpoints_7_4.super.addTracepoint(context, attributes, drm); + } + } + }); + } + else { + super.addTracepoint(context, attributes, drm); } - super.addTracepoint(context, attributes, drm); } @Override - protected void addWatchpoint(IBreakpointsTargetDMContext context, Map attributes, DataRequestMonitor drm) { - MIBreakpointsSynchronizer bs = getServicesTracker().getService(MIBreakpointsSynchronizer.class); + protected void addWatchpoint( + final IBreakpointsTargetDMContext context, + final Map attributes, + final DataRequestMonitor drm) { + final 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; - } + bs.getTargetBreakpoint( + context, + attributes, + new DataRequestMonitor(getExecutor(), drm) { + @Override + @ConfinedToDsfExecutor( "fExecutor" ) + protected void handleSuccess() { + MIBreakpoint miBpt = getData(); + if (miBpt != null) { + bs.removeCreatedTargetBreakpoint(context, miBpt); + MIBreakpointDMData newBreakpoint = new MIBreakpointDMData(miBpt); + getBreakpointMap(context).put(newBreakpoint.getNumber(), newBreakpoint); + IBreakpointDMContext dmc = + new MIBreakpointDMContext(GDBBreakpoints_7_4.this, new IDMContext[] { context }, newBreakpoint.getNumber()); + drm.setData(dmc); + getSession().dispatchEvent(new BreakpointAddedEvent(dmc), getProperties()); + drm.done(); + } + else { + GDBBreakpoints_7_4.super.addWatchpoint(context, attributes, drm); + } + } + }); + } + else { + super.addWatchpoint(context, attributes, drm); } - super.addWatchpoint(context, attributes, drm); } @Override 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 index aa74559bdb4..abf68c175f4 100644 --- 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 @@ -37,6 +37,7 @@ 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.ImmediateDataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.DMContexts; @@ -731,86 +732,126 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI return DMContexts.getAncestorOfType(contContext, IBreakpointsTargetDMContext.class); } - public MIBreakpoint getTargetBreakpoint(IBreakpointsTargetDMContext context, Map attributes) { + public void getTargetBreakpoint( + IBreakpointsTargetDMContext context, + Map attributes, + DataRequestMonitor rm) { Map map = fCreatedTargetBreakpoints.get(context); - if (map == null) - return null; + if (map == null) { + rm.done(); + return; + } String type = (String)attributes.get(MIBreakpoints.BREAKPOINT_TYPE); if (MIBreakpoints.BREAKPOINT.equals(type)) { - return getTargetLineBreakpoint( + getTargetLineBreakpoint( + context, 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)); + (Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY), + rm); } else if (MIBreakpoints.TRACEPOINT.equals(type)) { - return getTargetTracepoint( + getTargetTracepoint( + context, 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)); + (Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY), + rm); } else if (MIBreakpoints.WATCHPOINT.equals(type)) { - return getTargetWatchpoint( + getTargetWatchpoint( + context, 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)); + (Boolean)attributes.get(MIBreakpointDMData.IS_TEMPORARY), + rm); } - return null; + else { + rm.done(); + } } - private MIBreakpoint getTargetLineBreakpoint( + private void getTargetLineBreakpoint( + IBreakpointsTargetDMContext bpTargetDMC, Collection targetBreakpoints, String fileName, Integer lineNumber, String function, String address, Boolean isHardware, - Boolean isTemporary) { + Boolean isTemporary, + DataRequestMonitor drm) { + List candidates = new ArrayList(targetBreakpoints.size()); for (MIBreakpoint miBpt : targetBreakpoints) { - if (!miBpt.isWatchpoint() && !isCatchpoint(miBpt) && !miBpt.isTracepoint() - && compareBreakpointAttributes( - miBpt, fileName, lineNumber, function, address, isHardware, isTemporary)) - return miBpt; + if (!miBpt.isWatchpoint() && !isCatchpoint(miBpt) && !miBpt.isTracepoint()) { + // Filter out target breakpoints with different file names and line numbers + if (fileName == null + || (new File(fileName).getName().equals(new File(getFileName(miBpt)).getName()) + && getLineNumber(miBpt) == lineNumber)) { + candidates.add(miBpt); + } + } } - return null; + if (candidates.size() == 0) { + drm.done(); + return; + } + + findTargetLineBreakpoint(bpTargetDMC, candidates, + fileName, lineNumber, function, address, isHardware, isTemporary, drm); } - private MIBreakpoint getTargetTracepoint( + private void getTargetTracepoint( + IBreakpointsTargetDMContext bpTargetDMC, Collection targetBreakpoints, String fileName, Integer lineNumber, String function, String address, Boolean isHardware, - Boolean isTemporary) { + Boolean isTemporary, + DataRequestMonitor rm) { + List candidates = new ArrayList(targetBreakpoints.size()); for (MIBreakpoint miBpt : targetBreakpoints) { - if (miBpt.isTracepoint() - && compareBreakpointAttributes( - miBpt, fileName, lineNumber, function, address, isHardware, isTemporary)) - return miBpt; + if (miBpt.isTracepoint()) { + // Filter out target breakpoints with different file names and line numbers + if (new File(fileName).getName().equals(new File(getFileName(miBpt)).getName()) + && miBpt.getLine() == lineNumber) { + candidates.add(miBpt); + } + } } - return null; + if (candidates.size() == 0) { + rm.done(); + return; + } + + findTargetLineBreakpoint(bpTargetDMC, candidates, + fileName, lineNumber, function, address, isHardware, isTemporary, rm); } - private MIBreakpoint getTargetWatchpoint( + private void getTargetWatchpoint( + IBreakpointsTargetDMContext bpTargetDMC, Collection targetBreakpoints, String expression, boolean readAccess, boolean writeAccess, Boolean isHardware, - Boolean isTemporary) { + Boolean isTemporary, + DataRequestMonitor rm) { for (MIBreakpoint miBpt : targetBreakpoints) { if (!miBpt.isWatchpoint()) continue; @@ -824,25 +865,92 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI continue; if (!compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary)) continue; - return miBpt; + rm.setData(miBpt); + break; } - return null; + rm.done(); + } + + private void findTargetLineBreakpoint( + final IBreakpointsTargetDMContext bpTargetDMC, + final List candidates, + final String fileName, + final Integer lineNumber, + final String function, + final String address, + final Boolean isHardware, + final Boolean isTemporary, + final DataRequestMonitor drm) { + // We need to convert the debugger paths of the candidate target breakpoints + // before comparing them with the platform breakpoint's file name. + final List bpts = new ArrayList(candidates); + + class FindBreakpointRM extends ImmediateDataRequestMonitor { + + @Override + @ConfinedToDsfExecutor("fExecutor") + protected void handleCompleted() { + if (bpts.isEmpty()) { + drm.done(); + return; + } + + final MIBreakpoint bpt = bpts.remove(0); + final String debuggerPath = getFileName(bpt); + getSource( + bpTargetDMC, + debuggerPath, + new DataRequestMonitor(getExecutor(), drm) { + @Override + @ConfinedToDsfExecutor( "fExecutor" ) + protected void handleCompleted() { + // If an error occur performing source lookup + // log it and use the debugger path. + if (!isSuccess()) { + GdbPlugin.log(getStatus()); + } + if (compareBreakpointAttributes( + bpt, + isSuccess() ? getData() : debuggerPath, + fileName, + lineNumber, + function, + address, + isHardware, + isTemporary)) { + // The target breakpoint is found, we're done. + drm.setData(bpt); + drm.done(); + } + else { + // Try the next candidate + new FindBreakpointRM().done(); + } + } + }); + } + }; + + // Start the search. + new FindBreakpointRM().done(); } private boolean compareBreakpointAttributes( MIBreakpoint miBpt, + String miBptFileName, String fileName, Integer lineNumber, String function, String address, Boolean isHardware, Boolean isTemporary) { - return compareBreakpointLocationAttributes(miBpt, fileName, lineNumber, function, address) + return compareBreakpointLocationAttributes(miBpt, miBptFileName, fileName, lineNumber, function, address) && compareBreakpointTypeAttributes(miBpt, isHardware, isTemporary); } private boolean compareBreakpointLocationAttributes( MIBreakpoint miBpt, + String miBptFileName, String fileName, Integer lineNumber, String function, @@ -853,7 +961,7 @@ public class MIBreakpointsSynchronizer extends AbstractDsfService implements IMI && (address == null || !address.equals(getPlatformAddress(miBpt.getAddress()).toHexAddressString()))) return false; if (isLineBreakpoint(miBpt)) { - if (fileName == null || !fileName.equals(getFileName(miBpt))) + if (fileName == null || !fileName.equals(miBptFileName)) return false; if (lineNumber == null || lineNumber.intValue() != getLineNumber(miBpt)) return false;