From 954592bc6c319c4a0998ecd962a4ea4fe02176f9 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Sun, 19 Apr 2009 19:54:27 +0000 Subject: [PATCH] [272736] Add more checks to know if we ran to the right place. --- .../cdt/dsf/gdb/service/GDBRunControl.java | 47 +++++++++++----- .../dsf/gdb/service/GDBRunControl_7_0.java | 47 +++++++++++----- .../dsf/gdb/service/GDBRunControl_7_0_NS.java | 53 ++++++++++++------- 3 files changed, 101 insertions(+), 46 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl.java index b4705963f90..15b7b5f8e00 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl.java @@ -53,20 +53,23 @@ public class GDBRunControl extends MIRunControl { private static class RunToLineActiveOperation { private IMIExecutionDMContext fThreadContext; private int fBpId; - private String fLocation; + private String fFileLocation; + private String fAddrLocation; private boolean fSkipBreakpoints; public RunToLineActiveOperation(IMIExecutionDMContext threadContext, - int bpId, String location, boolean skipBreakpoints) { + int bpId, String fileLoc, String addr, boolean skipBreakpoints) { fThreadContext = threadContext; fBpId = bpId; - fLocation = location; + fFileLocation = fileLoc; + fAddrLocation = addr; fSkipBreakpoints = skipBreakpoints; } public IMIExecutionDMContext getThreadContext() { return fThreadContext; } public int getBreakointId() { return fBpId; } - public String getLocation() { return fLocation; } + public String getFileLocation() { return fFileLocation; } + public String getAddrLocation() { return fAddrLocation; } public boolean shouldSkipBreakpoints() { return fSkipBreakpoints; } } @@ -260,18 +263,19 @@ public class GDBRunControl extends MIRunControl { } if (doCanResume(context)) { - final String location = fileName + ":" + lineNo; //$NON-NLS-1$ + final String fileLocation = fileName + ":" + lineNo; //$NON-NLS-1$ IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class); getConnection().queueCommand( new MIBreakInsert(bpDmc, true, false, null, 0, - location, dmc.getThreadId()), + fileLocation, dmc.getThreadId()), new DataRequestMonitor(getExecutor(), rm) { @Override public void handleSuccess() { // We must set are RunToLineActiveOperation *before* we do the resume // or else we may get the stopped event, before we have set this variable. int bpId = getData().getMIBreakpoints()[0].getNumber(); - fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, location, skipBreakpoints); + String addr = getData().getMIBreakpoints()[0].getAddress(); + fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, fileLocation, addr, skipBreakpoints); resume(context, new RequestMonitor(getExecutor(), rm) { @Override @@ -320,12 +324,30 @@ public class GDBRunControl extends MIRunControl { @DsfServiceEventHandler public void eventDispatched(final MIStoppedEvent e) { if (fRunToLineActiveOperation != null) { - String location = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$ - if (location.equals(fRunToLineActiveOperation.getLocation())) { - // We stopped on our temporary breakpoint. All is well. + int bpId = 0; + if (e instanceof MIBreakpointHitEvent) { + bpId = ((MIBreakpointHitEvent)e).getNumber(); + } + String fileLocation = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$ + String addrLocation = e.getFrame().getAddress(); + // Here we check three different things to see if we are stopped at the right place + // 1- The actual location in the file. But this does not work for breakpoints that + // were set on non-executable lines + // 2- The address where the breakpoint was set. But this does not work for breakpoints + // that have multiple addresses (GDB returns .) I think that is for multi-process + // 3- The breakpoint id that was hit. But this does not work if another breakpoint + // was also set on the same line because GDB may return that breakpoint as being hit. + // + // So this works for the large majority of cases. The case that won't work is when the user + // does a runToLine to a line that is non-executable AND has another breakpoint AND + // has multiple addresses for the breakpoint. I'm mean, come on! + if (fileLocation.equals(fRunToLineActiveOperation.getFileLocation()) || + addrLocation.equals(fRunToLineActiveOperation.getAddrLocation()) || + bpId == fRunToLineActiveOperation.getBreakointId()) { + // We stopped at the right place. All is well. fRunToLineActiveOperation = null; } else { - // Didn't stop at the right line yet + // Didn't stop at the right place yet if (fRunToLineActiveOperation.shouldSkipBreakpoints() && e instanceof MIBreakpointHitEvent) { getConnection().queueCommand( new MIExecContinue(fRunToLineActiveOperation.getThreadContext()), @@ -338,9 +360,8 @@ public class GDBRunControl extends MIRunControl { // since we don't want it to hit later IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), IBreakpointsTargetDMContext.class); - int bpId = fRunToLineActiveOperation.getBreakointId(); - getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {fRunToLineActiveOperation.getBreakointId()}), new DataRequestMonitor(getExecutor(), null)); fRunToLineActiveOperation = null; } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java index cd443748e11..95a430f2dac 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java @@ -60,20 +60,23 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro private static class RunToLineActiveOperation { private IMIExecutionDMContext fThreadContext; private int fBpId; - private String fLocation; + private String fFileLocation; + private String fAddrLocation; private boolean fSkipBreakpoints; public RunToLineActiveOperation(IMIExecutionDMContext threadContext, - int bpId, String location, boolean skipBreakpoints) { + int bpId, String fileLoc, String addr, boolean skipBreakpoints) { fThreadContext = threadContext; fBpId = bpId; - fLocation = location; + fFileLocation = fileLoc; + fAddrLocation = addr; fSkipBreakpoints = skipBreakpoints; } public IMIExecutionDMContext getThreadContext() { return fThreadContext; } public int getBreakointId() { return fBpId; } - public String getLocation() { return fLocation; } + public String getFileLocation() { return fFileLocation; } + public String getAddrLocation() { return fAddrLocation; } public boolean shouldSkipBreakpoints() { return fSkipBreakpoints; } } @@ -450,18 +453,19 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro } if (doCanResume(context)) { - final String location = fileName + ":" + lineNo; //$NON-NLS-1$ + final String fileLocation = fileName + ":" + lineNo; //$NON-NLS-1$ IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class); getConnection().queueCommand( new MIBreakInsert(bpDmc, true, false, null, 0, - location, dmc.getThreadId()), + fileLocation, dmc.getThreadId()), new DataRequestMonitor(getExecutor(), rm) { @Override public void handleSuccess() { // We must set are RunToLineActiveOperation *before* we do the resume // or else we may get the stopped event, before we have set this variable. int bpId = getData().getMIBreakpoints()[0].getNumber(); - fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, location, skipBreakpoints); + String addr = getData().getMIBreakpoints()[0].getAddress(); + fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, fileLocation, addr, skipBreakpoints); resume(context, new RequestMonitor(getExecutor(), rm) { @Override @@ -510,12 +514,30 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro @DsfServiceEventHandler public void eventDispatched(final MIStoppedEvent e) { if (fRunToLineActiveOperation != null) { - String location = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$ - if (location.equals(fRunToLineActiveOperation.getLocation())) { - // We stopped on our temporary breakpoint. All is well. + int bpId = 0; + if (e instanceof MIBreakpointHitEvent) { + bpId = ((MIBreakpointHitEvent)e).getNumber(); + } + String fileLocation = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$ + String addrLocation = e.getFrame().getAddress(); + // Here we check three different things to see if we are stopped at the right place + // 1- The actual location in the file. But this does not work for breakpoints that + // were set on non-executable lines + // 2- The address where the breakpoint was set. But this does not work for breakpoints + // that have multiple addresses (GDB returns .) I think that is for multi-process + // 3- The breakpoint id that was hit. But this does not work if another breakpoint + // was also set on the same line because GDB may return that breakpoint as being hit. + // + // So this works for the large majority of cases. The case that won't work is when the user + // does a runToLine to a line that is non-executable AND has another breakpoint AND + // has multiple addresses for the breakpoint. I'm mean, come on! + if (fileLocation.equals(fRunToLineActiveOperation.getFileLocation()) || + addrLocation.equals(fRunToLineActiveOperation.getAddrLocation()) || + bpId == fRunToLineActiveOperation.getBreakointId()) { + // We stopped at the right place. All is well. fRunToLineActiveOperation = null; } else { - // Didn't stop at the right line yet + // Didn't stop at the right place yet if (fRunToLineActiveOperation.shouldSkipBreakpoints() && e instanceof MIBreakpointHitEvent) { getConnection().queueCommand( new MIExecContinue(fRunToLineActiveOperation.getThreadContext()), @@ -528,9 +550,8 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro // since we don't want it to hit later IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), IBreakpointsTargetDMContext.class); - int bpId = fRunToLineActiveOperation.getBreakointId(); - getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {fRunToLineActiveOperation.getBreakointId()}), new DataRequestMonitor(getExecutor(), null)); fRunToLineActiveOperation = null; } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java index 327bccbe6fa..d327108aa3d 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java @@ -200,20 +200,23 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo private static class RunToLineActiveOperation { private IMIExecutionDMContext fThreadContext; private int fBpId; - private String fLocation; + private String fFileLocation; + private String fAddrLocation; private boolean fSkipBreakpoints; public RunToLineActiveOperation(IMIExecutionDMContext threadContext, - int bpId, String location, boolean skipBreakpoints) { + int bpId, String fileLoc, String addr, boolean skipBreakpoints) { fThreadContext = threadContext; fBpId = bpId; - fLocation = location; + fFileLocation = fileLoc; + fAddrLocation = addr; fSkipBreakpoints = skipBreakpoints; } public IMIExecutionDMContext getThreadContext() { return fThreadContext; } public int getBreakointId() { return fBpId; } - public String getLocation() { return fLocation; } + public String getFileLocation() { return fFileLocation; } + public String getAddrLocation() { return fAddrLocation; } public boolean shouldSkipBreakpoints() { return fSkipBreakpoints; } } @@ -593,26 +596,19 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo return; } - final String location = fileName + ":" + lineNo; //$NON-NLS-1$ + final String fileLocation = fileName + ":" + lineNo; //$NON-NLS-1$ IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class); fConnection.queueCommand( new MIBreakInsert(bpDmc, true, false, null, 0, - location, dmc.getThreadId()), + fileLocation, dmc.getThreadId()), new DataRequestMonitor(getExecutor(), rm) { @Override public void handleSuccess() { // We must set are RunToLineActiveOperation *before* we do the resume // or else we may get the stopped event, before we have set this variable. int bpId = getData().getMIBreakpoints()[0].getNumber(); - - // It would have been nice to use the address returned by the break-insert as our location, - // but that does not always work because sometimes the address is - // - // Also, we could have used the breakpoint id to know if we hit the proper breakpoint, - // but that also doesn't always work because if there are many bp at that location, - // GDB will report hitting one of them but not all of them (although GDB does consider - // that all those bps did hit.) - fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, location, skipBreakpoints); + String addr = getData().getMIBreakpoints()[0].getAddress(); + fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, fileLocation, addr, skipBreakpoints); resume(dmc, new RequestMonitor(getExecutor(), rm) { @Override @@ -737,9 +733,27 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo // First check if it is the right thread that stopped IMIExecutionDMContext threadDmc = DMContexts.getAncestorOfType(e.getDMContext(), IMIExecutionDMContext.class); if (fRunToLineActiveOperation.getThreadContext().equals(threadDmc)) { - String location = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$ - if (location.equals(fRunToLineActiveOperation.getLocation())) { - // We stopped on our temporary breakpoint. All is well. + int bpId = 0; + if (e instanceof MIBreakpointHitEvent) { + bpId = ((MIBreakpointHitEvent)e).getNumber(); + } + String fileLocation = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$ + String addrLocation = e.getFrame().getAddress(); + // Here we check three different things to see if we are stopped at the right place + // 1- The actual location in the file. But this does not work for breakpoints that + // were set on non-executable lines + // 2- The address where the breakpoint was set. But this does not work for breakpoints + // that have multiple addresses (GDB returns .) I think that is for multi-process + // 3- The breakpoint id that was hit. But this does not work if another breakpoint + // was also set on the same line because GDB may return that breakpoint as being hit. + // + // So this works for the large majority of cases. The case that won't work is when the user + // does a runToLine to a line that is non-executable AND has another breakpoint AND + // has multiple addresses for the breakpoint. I'm mean, come on! + if (fileLocation.equals(fRunToLineActiveOperation.getFileLocation()) || + addrLocation.equals(fRunToLineActiveOperation.getAddrLocation()) || + bpId == fRunToLineActiveOperation.getBreakointId()) { + // We stopped at the right place. All is well. fRunToLineActiveOperation = null; } else { // The right thread stopped but not at the right place yet @@ -755,9 +769,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo // since we don't want it to hit later IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(), IBreakpointsTargetDMContext.class); - int bpId = fRunToLineActiveOperation.getBreakointId(); - fConnection.queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}), + fConnection.queueCommand(new MIBreakDelete(bpDmc, new int[] {fRunToLineActiveOperation.getBreakointId()}), new DataRequestMonitor(getExecutor(), null)); fRunToLineActiveOperation = null; }