From faae34208e1286b8ae81fe1262a9973e951f9859 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Thu, 11 Feb 2010 16:27:03 +0000 Subject: [PATCH] [249162] Added MoveToLine support for both the Editor and the DSF Disassembly view. Currently this only works for GDB 7.0. Bug 302597 must be fixed to have this work with older GDBs --- .../ui/actions/MoveToLineAdapter.java | 47 +++-- dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml | 2 +- ...va => GdbSuspendResumeAdapterFactory.java} | 144 +++++++------- .../actions/DisassemblyMoveToLineAdapter.java | 97 +++++++++ .../actions/DisassemblyRunToLineAdapter.java | 20 +- .../internal/ui/actions/GdbMoveToLine.java | 187 ++++++++++++++++++ .../gdb/internal/ui/actions/GdbRunToLine.java | 4 +- .../RetargettableActionAdapterFactory.java | 6 +- .../dsf/gdb/service/GDBRunControl_7_0_NS.java | 43 ++++ .../cdt/dsf/mi/service/IMIRunControl.java | 10 + .../cdt/dsf/mi/service/MIRunControl.java | 33 ++++ .../mi/service/command/commands/CLIJump.java | 28 +++ 12 files changed, 510 insertions(+), 111 deletions(-) rename dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/{GdbRunToLineAdapterFactory.java => GdbSuspendResumeAdapterFactory.java} (77%) create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DisassemblyMoveToLineAdapter.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbMoveToLine.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIJump.java diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/MoveToLineAdapter.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/MoveToLineAdapter.java index 7f534c1bfad..60d20566284 100644 --- a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/MoveToLineAdapter.java +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/actions/MoveToLineAdapter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 QNX Software Systems and others. + * Copyright (c) 2004, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * QNX Software Systems - Initial API and implementation + * Ericsson - Update to support DSF-GDB retargetting MoveToLine *******************************************************************************/ package org.eclipse.cdt.debug.internal.ui.actions; @@ -67,31 +68,30 @@ public class MoveToLineAdapter implements IMoveToLineTarget { else { final String fileName = getFileName( input ); IDebugTarget debugTarget = null; - if (target instanceof CDebugElement) { // should always be, but just in case + if (target instanceof CDebugElement) { debugTarget = ((CDebugElement)target).getDebugTarget(); } - if (debugTarget != null) { - ITextSelection textSelection = (ITextSelection)selection; - final int lineNumber = textSelection.getStartLine() + 1; - if ( target instanceof IAdaptable ) { - final IPath path = convertPath( fileName, debugTarget ); - final IMoveToLine moveToLine = (IMoveToLine)((IAdaptable)target).getAdapter( IMoveToLine.class ); - if ( moveToLine != null && moveToLine.canMoveToLine( path.toPortableString(), lineNumber ) ) { - Runnable r = new Runnable() { - public void run() { - try { - moveToLine.moveToLine(path.toPortableString(), lineNumber ); - } - catch( DebugException e ) { - failed( e ); - } + + ITextSelection textSelection = (ITextSelection)selection; + final int lineNumber = textSelection.getStartLine() + 1; + if ( target instanceof IAdaptable ) { + final IPath path = convertPath( fileName, debugTarget ); + final IMoveToLine moveToLine = (IMoveToLine)((IAdaptable)target).getAdapter( IMoveToLine.class ); + if ( moveToLine != null && moveToLine.canMoveToLine( path.toPortableString(), lineNumber ) ) { + Runnable r = new Runnable() { + public void run() { + try { + moveToLine.moveToLine(path.toPortableString(), lineNumber ); } - }; - runInBackground( r ); - } + catch( DebugException e ) { + failed( e ); + } + } + }; + runInBackground( r ); } - return; } + return; } } } @@ -163,12 +163,9 @@ public class MoveToLineAdapter implements IMoveToLineTarget { } IDebugTarget debugTarget = null; - if (target instanceof CDebugElement) { // should always be, but just in case + if (target instanceof CDebugElement) { debugTarget = ((CDebugElement)target).getDebugTarget(); } - if (debugTarget == null) { - return false; - } final IPath path = convertPath( fileName, debugTarget ); ITextSelection textSelection = (ITextSelection)selection; diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml index 9d26c5623fc..7da9aefff36 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml @@ -163,7 +163,7 @@ diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbRunToLineAdapterFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbSuspendResumeAdapterFactory.java similarity index 77% rename from dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbRunToLineAdapterFactory.java rename to dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbSuspendResumeAdapterFactory.java index 577fe1927fe..359fee67f8e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbRunToLineAdapterFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbSuspendResumeAdapterFactory.java @@ -1,68 +1,78 @@ -/******************************************************************************* - * Copyright (c) 2009 Wind River Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Wind River Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.dsf.gdb.internal.ui; - -import org.eclipse.cdt.dsf.datamodel.DMContexts; -import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; -import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; -import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbRunToLine; -import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.core.runtime.IAdapterFactory; -import org.eclipse.debug.core.DebugException; -import org.eclipse.debug.core.model.ISuspendResume; - -/** - * @since 2.0 - */ -public class GdbRunToLineAdapterFactory implements IAdapterFactory { - - static class GdbSuspendResume implements ISuspendResume, IAdaptable { - - private final GdbRunToLine fRunToLine; - - GdbSuspendResume(IExecutionDMContext execCtx) { - fRunToLine = new GdbRunToLine(execCtx); - } - - public Object getAdapter(Class adapter) { - if (adapter.isInstance(fRunToLine)) { - return fRunToLine; - } - return null; - } - - public boolean canResume() { return false; } - public boolean canSuspend() { return false; } - public boolean isSuspended() { return false; } - public void resume() throws DebugException {} - public void suspend() throws DebugException {} - } - - public Object getAdapter(Object adaptableObject, Class adapterType) { - if (ISuspendResume.class.equals(adapterType)) { - if (adaptableObject instanceof IDMVMContext) { - IExecutionDMContext execDmc = DMContexts.getAncestorOfType( - ((IDMVMContext)adaptableObject).getDMContext(), - IExecutionDMContext.class); - // It only makes sense to RunToLine if we are dealing with a thread, not a container - if (execDmc != null && !(execDmc instanceof IContainerDMContext)) { - return new GdbSuspendResume(execDmc); - } - } - } - return null; - } - - public Class[] getAdapterList() { - return new Class[] { ISuspendResume.class }; - } +/******************************************************************************* + * Copyright (c) 2009, 2010 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + * Ericsson - Updated to support Move-To-Line + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui; + +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbMoveToLine; +import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbRunToLine; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.ISuspendResume; + +/** + * Adapter factory for Run-To-Line and Move-To-Line + * + * @since 3.0 + */ +public class GdbSuspendResumeAdapterFactory implements IAdapterFactory { + + static class GdbSuspendResume implements ISuspendResume, IAdaptable { + + private final GdbRunToLine fRunToLine; + private final GdbMoveToLine fMoveToLine; + + GdbSuspendResume(IExecutionDMContext execCtx) { + fRunToLine = new GdbRunToLine(execCtx); + fMoveToLine = new GdbMoveToLine(execCtx); + } + + public Object getAdapter(Class adapter) { + if (adapter.isInstance(fRunToLine)) { + return fRunToLine; + } + if (adapter.isInstance(fMoveToLine)) { + return fMoveToLine; + } + return null; + } + + public boolean canResume() { return false; } + public boolean canSuspend() { return false; } + public boolean isSuspended() { return false; } + public void resume() throws DebugException {} + public void suspend() throws DebugException {} + } + + public Object getAdapter(Object adaptableObject, Class adapterType) { + if (ISuspendResume.class.equals(adapterType)) { + if (adaptableObject instanceof IDMVMContext) { + IExecutionDMContext execDmc = DMContexts.getAncestorOfType( + ((IDMVMContext)adaptableObject).getDMContext(), + IExecutionDMContext.class); + // It only makes sense to RunToLine or MoveToLine + // if we are dealing with a thread, not a container + if (execDmc != null && !(execDmc instanceof IContainerDMContext)) { + return new GdbSuspendResume(execDmc); + } + } + } + return null; + } + + public Class[] getAdapterList() { + return new Class[] { ISuspendResume.class }; + } } \ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DisassemblyMoveToLineAdapter.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DisassemblyMoveToLineAdapter.java new file mode 100644 index 00000000000..f6ac646e5ec --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DisassemblyMoveToLineAdapter.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson 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: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.actions; + +import java.math.BigInteger; + +import org.eclipse.cdt.core.IAddress; +import org.eclipse.cdt.debug.core.CDIDebugModel; +import org.eclipse.cdt.debug.core.model.IMoveToAddress; +import org.eclipse.cdt.debug.internal.ui.actions.IMoveToLineTarget; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.debug.internal.ui.disassembly.provisional.DisassemblySelection; +import org.eclipse.cdt.dsf.debug.internal.ui.disassembly.provisional.IDisassemblyPart; +import org.eclipse.cdt.dsf.debug.internal.ui.disassembly.provisional.IDisassemblySelection; +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.utils.Addr64; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.ISuspendResume; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchPart; + +/** + * Move to line target adapter for the DSF Disassembly view + * + * @since 2.1 + */ +public class DisassemblyMoveToLineAdapter implements IMoveToLineTarget { + + public void moveToLine(IWorkbenchPart part, ISelection selection, ISuspendResume target) throws CoreException { + if (part instanceof IDisassemblyPart && selection instanceof ITextSelection) { + if (!(selection instanceof IDisassemblySelection)) { + selection = new DisassemblySelection((ITextSelection)selection, (IDisassemblyPart)part); + } + IDisassemblySelection disassemblySelection = (IDisassemblySelection)selection; + BigInteger rawAddress = disassemblySelection.getStartAddress(); + if (rawAddress == null) { + return; + } + + final IAddress address = new Addr64(rawAddress); + if (address != null && target instanceof IAdaptable) { + final IMoveToAddress runToAddress = (IMoveToAddress)((IAdaptable)target).getAdapter(IMoveToAddress.class); + if (runToAddress != null && runToAddress.canMoveToAddress(address)) { + try { + runToAddress.moveToAddress(address); + } + catch(DebugException e) { + failed(e); + } + } + } + } + } + + public boolean canMoveToLine(IWorkbenchPart part, ISelection selection, ISuspendResume target) { + if (target instanceof IAdaptable && part instanceof IDisassemblyPart && selection instanceof ITextSelection) { + IMoveToAddress runToAddress = (IMoveToAddress)((IAdaptable)target).getAdapter(IMoveToAddress.class); + if (runToAddress == null) { + return false; + } + + if (!(selection instanceof IDisassemblySelection)) { + selection = new DisassemblySelection((ITextSelection)selection, (IDisassemblyPart)part); + } + IDisassemblySelection disassemblySelection = (IDisassemblySelection)selection; + BigInteger rawAddress = disassemblySelection.getStartAddress(); + if (rawAddress == null) { + return false; + } + + final IAddress address = new Addr64(rawAddress); + return runToAddress.canMoveToAddress(address); + } + + return false; + } + + protected void failed( Throwable e ) { + MultiStatus ms = new MultiStatus(CDIDebugModel.getPluginIdentifier(), IDsfStatusConstants.REQUEST_FAILED, "MoveToLine failed", null); //$NON-NLS-1$ + ms.add( new Status(IStatus.ERROR, CDIDebugModel.getPluginIdentifier(), IDsfStatusConstants.REQUEST_FAILED, e.getMessage(), e)); + GdbUIPlugin.log(ms); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DisassemblyRunToLineAdapter.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DisassemblyRunToLineAdapter.java index d71dc11f2aa..8d52e698cf3 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DisassemblyRunToLineAdapter.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DisassemblyRunToLineAdapter.java @@ -60,18 +60,13 @@ public class DisassemblyRunToLineAdapter implements IRunToLineTarget { if (address != null && target instanceof IAdaptable) { final IRunToAddress runToAddress = (IRunToAddress)((IAdaptable)target).getAdapter(IRunToAddress.class); if (runToAddress != null && runToAddress.canRunToAddress(address)) { -// Runnable r = new Runnable() { -// public void run() { - try { - boolean skipBreakpoints = DebugUITools.getPreferenceStore().getBoolean(IDebugUIConstants.PREF_SKIP_BREAKPOINTS_DURING_RUN_TO_LINE); - runToAddress.runToAddress(address, skipBreakpoints); - } - catch( DebugException e ) { - failed( e ); - } -// } -// }; -// DebugPlugin.getDefault().asyncExec(r); + try { + boolean skipBreakpoints = DebugUITools.getPreferenceStore().getBoolean(IDebugUIConstants.PREF_SKIP_BREAKPOINTS_DURING_RUN_TO_LINE); + runToAddress.runToAddress(address, skipBreakpoints); + } + catch(DebugException e) { + failed(e); + } } } } @@ -108,5 +103,4 @@ public class DisassemblyRunToLineAdapter implements IRunToLineTarget { ms.add( new Status( IStatus.ERROR, CDIDebugModel.getPluginIdentifier(), IDsfStatusConstants.REQUEST_FAILED, e.getMessage(), e ) ); GdbUIPlugin.log(ms); } - } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbMoveToLine.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbMoveToLine.java new file mode 100644 index 00000000000..4e951dce759 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbMoveToLine.java @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson 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: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.actions; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.RejectedExecutionException; + +import org.eclipse.cdt.core.IAddress; +import org.eclipse.cdt.debug.core.model.IMoveToAddress; +import org.eclipse.cdt.debug.core.model.IMoveToLine; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.concurrent.Query; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.debug.service.IBreakpoints; +import org.eclipse.cdt.dsf.debug.service.IRunControl; +import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext; +import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; +import org.eclipse.cdt.dsf.mi.service.IMIRunControl; +import org.eclipse.cdt.dsf.mi.service.MIBreakpointDMData; +import org.eclipse.cdt.dsf.mi.service.MIBreakpoints; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; + +/** + * Implements the CDT's move to line interface. + * + * @since 3.0 + */ +public class GdbMoveToLine implements IMoveToLine, IMoveToAddress { + + private final IExecutionDMContext fContext; + + public GdbMoveToLine(IExecutionDMContext context) { + fContext = context; + } + + public boolean canMoveToLine(String fileName, int lineNumber) { + return canMoveToLocation(); + } + + public void moveToLine(String fileName, int lineNumber) throws DebugException { + IMIExecutionDMContext threadExecDmc = DMContexts.getAncestorOfType(fContext, IMIExecutionDMContext.class); + if (threadExecDmc == null) { + throw new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Invalid thread context", null)); //$NON-NLS-1$ + } + + // Create the breakpoint attributes + Map attr = new HashMap(); + attr.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT); + attr.put(MIBreakpoints.FILE_NAME, fileName); + attr.put(MIBreakpoints.LINE_NUMBER, lineNumber); + attr.put(MIBreakpointDMData.IS_TEMPORARY, true); + attr.put(MIBreakpointDMData.THREAD_ID, Integer.toString(threadExecDmc.getThreadId())); + + // Now do the operation + moveToLocation(fileName + ":" + lineNumber, attr); //$NON-NLS-1$ + } + + public boolean canMoveToAddress(IAddress address) { + return canMoveToLocation(); + } + + public void moveToAddress(IAddress address) throws DebugException { + IMIExecutionDMContext threadExecDmc = DMContexts.getAncestorOfType(fContext, IMIExecutionDMContext.class); + if (threadExecDmc == null) { + throw new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Invalid thread context", null)); //$NON-NLS-1$ + } + + // Create the breakpoint attributes + Map attr = new HashMap(); + attr.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT); + attr.put(MIBreakpoints.ADDRESS, "0x" + address.toString(16)); //$NON-NLS-1$ + attr.put(MIBreakpointDMData.IS_TEMPORARY, true); + attr.put(MIBreakpointDMData.THREAD_ID, Integer.toString(threadExecDmc.getThreadId())); + + // Now do the operation + moveToLocation("*0x" + address.toString(16), attr); //$NON-NLS-1$ + } + + private boolean canMoveToLocation() { + DsfSession session = DsfSession.getSession(fContext.getSessionId()); + if (session != null && session.isActive()) { + try { + Query query = new Query() { + @Override + protected void execute(DataRequestMonitor rm) { + DsfServicesTracker tracker = + new DsfServicesTracker(GdbUIPlugin.getBundleContext(), fContext.getSessionId()); + + IRunControl runControl = tracker.getService(IRunControl.class); + if (runControl != null) { + runControl.canResume(fContext, rm); + } else { + rm.setData(false); + rm.done(); + } + tracker.dispose(); + } + }; + session.getExecutor().execute(query); + return query.get(); + } catch (RejectedExecutionException e) { + } catch (InterruptedException e) { + } catch (ExecutionException e) { + } + } + return false; + } + + + private void moveToLocation(final String location, final Map bpAttributes) throws DebugException { + final DsfSession session = DsfSession.getSession(fContext.getSessionId()); + if (session != null && session.isActive()) { + Throwable exception = null; + try { + Query query = new Query() { + @Override + protected void execute(final DataRequestMonitor rm) { + // first create a temporary breakpoint to stop the execution at + // the location we are about to jump to + final DsfServicesTracker tracker = + new DsfServicesTracker(GdbUIPlugin.getBundleContext(), fContext.getSessionId()); + IBreakpoints bpService = tracker.getService(IBreakpoints.class); + IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fContext, IBreakpointsTargetDMContext.class); + if (bpService != null && bpDmc != null) { + bpService.insertBreakpoint( + bpDmc, bpAttributes, + new DataRequestMonitor(session.getExecutor(), rm) { + @Override + protected void handleSuccess() { + // Now resume at the proper location + IMIRunControl miRunControl = tracker.getService(IMIRunControl.class); + tracker.dispose(); + if (miRunControl != null) { + miRunControl.resumeAtLocation(fContext, location, rm); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "MIRunControl service not available", null)); //$NON-NLS-1$ + rm.done(); + } + }; + @Override + protected void handleFailure() { + tracker.dispose(); + super.handleFailure(); + }; + }); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Unable to set breakpoint", null)); //$NON-NLS-1$ + rm.done(); + tracker.dispose(); + } + } + }; + session.getExecutor().execute(query); + query.get(); + } catch (RejectedExecutionException e) { + exception = e; + } catch (InterruptedException e) { + exception = e; + } catch (ExecutionException e) { + exception = e; + } + if (exception != null) { + throw new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Faild executing move to line", exception)); //$NON-NLS-1$ + } + } else { + throw new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Debug session is not active", null)); //$NON-NLS-1$ + } + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbRunToLine.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbRunToLine.java index d2b24caf26b..bac32feb781 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbRunToLine.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbRunToLine.java @@ -137,10 +137,10 @@ public class GdbRunToLine implements IRunToLine, IRunToAddress { exception = e; } if (exception != null) { - new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Faild executing run to line", exception)); //$NON-NLS-1$ + throw new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Faild executing run to line", exception)); //$NON-NLS-1$ } } else { - new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Debug session is not active", null)); //$NON-NLS-1$ + throw new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Debug session is not active", null)); //$NON-NLS-1$ } } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/RetargettableActionAdapterFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/RetargettableActionAdapterFactory.java index 4f2936dbd56..f9cc74eb0d9 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/RetargettableActionAdapterFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/RetargettableActionAdapterFactory.java @@ -32,9 +32,9 @@ public class RetargettableActionAdapterFactory implements IAdapterFactory { // if (adapterType == IResumeAtLineTarget.class) { // return new DisassemblyResumeAtLineAdapter(); // } -// if (adapterType == IMoveToLineTarget.class) { -// return new DisassemblyMoveToLineAdapter(); -// } + if (adapterType == IMoveToLineTarget.class) { + return new DisassemblyMoveToLineAdapter(); + } return 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 67120104903..28bc6eac504 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 @@ -38,6 +38,7 @@ import org.eclipse.cdt.dsf.mi.service.IMIProcesses; import org.eclipse.cdt.dsf.mi.service.IMIRunControl; import org.eclipse.cdt.dsf.mi.service.MIRunControl; import org.eclipse.cdt.dsf.mi.service.MIStack; +import org.eclipse.cdt.dsf.mi.service.command.commands.CLIJump; import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDelete; import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert; import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand; @@ -668,6 +669,48 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo } + // ------------------------------------------------------------------------ + // Resume at location + // ------------------------------------------------------------------------ + + /** @since 3.0 */ + public void resumeAtLocation(IExecutionDMContext context, String location, RequestMonitor rm) { + assert context != null; + + final IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); + if (dmc == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, + "Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$ + rm.done(); + return; + } + + if (!doCanResume(dmc)) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, + "Cannot resume context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + final MIThreadRunState threadState = fThreadRunStates.get(dmc); + if (threadState == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, + "Given context: " + dmc + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$ + rm.done(); + return; + } + + threadState.fResumePending = true; + fConnection.queueCommand( + new CLIJump(dmc, location), + new DataRequestMonitor(getExecutor(), rm) { + @Override + protected void handleFailure() { + threadState.fResumePending = false; + super.handleFailure(); + } + }); + } // ------------------------------------------------------------------------ // Support functions // ------------------------------------------------------------------------ diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/IMIRunControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/IMIRunControl.java index 3b896aec08a..7ebc54cc971 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/IMIRunControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/IMIRunControl.java @@ -30,5 +30,15 @@ public interface IMIRunControl extends IRunControl * @since 3.0 */ void runToLocation(IExecutionDMContext context, String location, boolean skipBreakpoints, RequestMonitor rm); + + /** + * Request to resume the program starting at the specified location. + * The specified location can be anywhere in the program, but proper + * program behavior is not guaranteed after this operation. + * + * @since 3.0 + */ + void resumeAtLocation(IExecutionDMContext context, String location, RequestMonitor rm); + } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java index ab9dd0eec78..bfaec9a9556 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java @@ -26,6 +26,7 @@ import org.eclipse.cdt.dsf.debug.service.command.CommandCache; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.mi.service.command.commands.CLIJump; import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue; import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecFinish; @@ -706,6 +707,38 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I } } + /** @since 3.0 */ + public void resumeAtLocation(IExecutionDMContext context, String location, RequestMonitor rm) { + assert context != null; + + final IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class); + if (dmc == null){ + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Given context: " + context + " is not an thread execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$ + rm.done(); + return; + } + + if (doCanResume(dmc)) { + fResumePending = true; + fMICommandCache.setContextAvailable(dmc, false); + fConnection.queueCommand( + new CLIJump(dmc, location), + new DataRequestMonitor(getExecutor(), rm) { + @Override + protected void handleFailure() { + fResumePending = false; + fMICommandCache.setContextAvailable(dmc, true); + + super.handleFailure(); + } + }); + } else { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, + "Cannot resume given DMC.", null)); //$NON-NLS-1$ + rm.done(); + } + } + /** * {@inheritDoc} * @since 1.1 diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIJump.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIJump.java new file mode 100644 index 00000000000..c6c02a7c310 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIJump.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson 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: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; + +/** + * jump LINESPEC + * jump LOCATION + * Resume execution at line LINESPEC or at address given by LOCATION. + * + * @since 3.0 + */ +public class CLIJump extends CLICommand { + + public CLIJump(IExecutionDMContext ctx, String location) { + super(ctx, "jump " + location); //$NON-NLS-1$ + } +}