mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 08:55:25 +02:00
Bug 498782 - add synchronize of process selection between the DV and GDB
This patch synchronizes the GDB focus when the user selects a process node in the DV. When the user selects a new process (inferior) from the GDB console, we are already synchronizing the DV to the thread/frame that GDB selects from that process. Change-Id: I11dfd175d51ec49e969f4d07288f80f7ea72a3e1
This commit is contained in:
parent
c2b4f18943
commit
e8480ca0f8
4 changed files with 98 additions and 6 deletions
|
@ -12,6 +12,7 @@ import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.service.IGDBFocusSynchronizer;
|
import org.eclipse.cdt.dsf.gdb.internal.service.IGDBFocusSynchronizer;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
|
@ -46,8 +47,10 @@ public class GdbDebugContextSyncManager implements IDebugContextListener {
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
final IDMContext dmc = context.getAdapter(IDMContext.class);
|
final IDMContext dmc = context.getAdapter(IDMContext.class);
|
||||||
|
|
||||||
if (dmc instanceof IMIExecutionDMContext || dmc instanceof IFrameDMContext) {
|
if (dmc instanceof IMIContainerDMContext ||
|
||||||
// A thread or stack frame was selected. In either case, have GDB switch to the new
|
dmc instanceof IMIExecutionDMContext ||
|
||||||
|
dmc instanceof IFrameDMContext) {
|
||||||
|
// A process, thread or stack frame was selected. In each case, have GDB switch to the new
|
||||||
// corresponding thread, if required.
|
// corresponding thread, if required.
|
||||||
|
|
||||||
// Resolve the debug session
|
// Resolve the debug session
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
|
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIConst;
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIConst;
|
||||||
|
@ -70,7 +71,7 @@ import org.osgi.framework.BundleContext;
|
||||||
public class GDBFocusSynchronizer extends AbstractDsfService implements IGDBFocusSynchronizer, IEventListener
|
public class GDBFocusSynchronizer extends AbstractDsfService implements IGDBFocusSynchronizer, IEventListener
|
||||||
{
|
{
|
||||||
/** This service's opinion of what is the current GDB focus - it can be
|
/** This service's opinion of what is the current GDB focus - it can be
|
||||||
* a thread or stack frame context */
|
* a process, thread or stack frame context */
|
||||||
private IDMContext fCurrentGDBFocus;
|
private IDMContext fCurrentGDBFocus;
|
||||||
|
|
||||||
private IStack fStackService;
|
private IStack fStackService;
|
||||||
|
@ -170,6 +171,10 @@ public class GDBFocusSynchronizer extends AbstractDsfService implements IGDBFocu
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// new selection is a process?
|
||||||
|
else if (elem instanceof IMIContainerDMContext) {
|
||||||
|
setProcessFocus((IMIContainerDMContext)elem, rm);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
assert false;
|
assert false;
|
||||||
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
||||||
|
@ -178,6 +183,58 @@ public class GDBFocusSynchronizer extends AbstractDsfService implements IGDBFocu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setProcessFocus(IMIContainerDMContext newProc, RequestMonitor rm) {
|
||||||
|
if (newProc == null) {
|
||||||
|
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
||||||
|
INVALID_HANDLE, "GdbFocusSynchronizer unable to resolve process context for the selected element", null)); //$NON-NLS-1$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// There is no MI command to set the inferior. We could use the CLI 'inferior' command, but it would then
|
||||||
|
// generate a =thread-selected event, which would cause us to change the selection in the Debug view and
|
||||||
|
// select the stack frame of the first thread, or the first thread itself if it is running.
|
||||||
|
// That would prevent the user from being able to leave the selection to a process node.
|
||||||
|
// What we can do instead, is tell GDB to select the first thread of that inferior, which is what
|
||||||
|
// GDB would do anyway, but since we have an MI -thread-select command it will prevent GDB from
|
||||||
|
// issuing a =thread-selected event.
|
||||||
|
fProcesses.getProcessesBeingDebugged(newProc, new ImmediateDataRequestMonitor<IDMContext[]>(rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
if (getData().length > 0) {
|
||||||
|
IDMContext finalThread = getData()[0];
|
||||||
|
if (finalThread instanceof IMIExecutionDMContext) {
|
||||||
|
setThreadFocus((IMIExecutionDMContext)(finalThread), new ImmediateRequestMonitor(rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
// update the current focus, to match new GDB focus
|
||||||
|
fCurrentGDBFocus = finalThread;
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rm.done();
|
||||||
|
} else {
|
||||||
|
// If there are no threads, it probably implies the inferior is not running
|
||||||
|
// e.g., an exited process. In this case, we cannot set the thread, but it
|
||||||
|
// then becomes safe to set the inferior using the CLI command since
|
||||||
|
// there is no thread for that inferior and therefore no =thread-selected event
|
||||||
|
String miInferiorId = newProc.getGroupId();
|
||||||
|
// Remove the 'i' prefix
|
||||||
|
String cliInferiorId = miInferiorId.substring(1, miInferiorId.length());
|
||||||
|
ICommand<MIInfo> command = fCommandFactory.createCLIInferior(fGdbcontrol.getContext(), cliInferiorId);
|
||||||
|
fGdbcontrol.queueCommand(command, new ImmediateDataRequestMonitor<MIInfo> (rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
// update the current focus, to match new GDB focus
|
||||||
|
fCurrentGDBFocus = newProc;
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
protected void setThreadFocus(IMIExecutionDMContext newThread, RequestMonitor rm) {
|
protected void setThreadFocus(IMIExecutionDMContext newThread, RequestMonitor rm) {
|
||||||
if (newThread == null) {
|
if (newThread == null) {
|
||||||
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
package org.eclipse.cdt.dsf.mi.service.command;
|
package org.eclipse.cdt.dsf.mi.service.command;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.debug.core.model.IChangeReverseMethodHandler.ReverseDebugMethod;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext;
|
||||||
|
@ -53,6 +54,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAttach;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLICatch;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.CLICatch;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIDetach;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIDetach;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIExecAbort;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIExecAbort;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInferior;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoBreak;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoBreak;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoProgram;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoProgram;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoRecord;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIInfoRecord;
|
||||||
|
@ -195,6 +197,7 @@ import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressableSizeInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLICatchInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.CLICatchInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoBreakInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoBreakInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoProgramInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoProgramInfo;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoRecordInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoSharedLibraryInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoSharedLibraryInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoThreadsInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoThreadsInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIShowEndianInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.CLIShowEndianInfo;
|
||||||
|
@ -242,8 +245,6 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIVarSetFormatInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarShowAttributesInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarShowAttributesInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarShowFormatInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarShowFormatInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarUpdateInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarUpdateInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoRecordInfo;
|
|
||||||
import org.eclipse.cdt.debug.core.model.IChangeReverseMethodHandler.ReverseDebugMethod;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory to create MI/CLI commands.
|
* Factory to create MI/CLI commands.
|
||||||
|
@ -279,6 +280,11 @@ public class CommandFactory {
|
||||||
return new CLIExecAbort(ctx);
|
return new CLIExecAbort(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 5.2 */
|
||||||
|
public ICommand<MIInfo> createCLIInferior(ICommandControlDMContext ctx, String inferiorId) {
|
||||||
|
return new CLIInferior(ctx, inferiorId);
|
||||||
|
}
|
||||||
|
|
||||||
/** @since 4.2 */
|
/** @since 4.2 */
|
||||||
public ICommand<CLIInfoBreakInfo> createCLIInfoBreak(IDMContext ctx) {
|
public ICommand<CLIInfoBreakInfo> createCLIInfoBreak(IDMContext ctx) {
|
||||||
return new CLIInfoBreak(ctx);
|
return new CLIInfoBreak(ctx);
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2016 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
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.dsf.mi.service.command.commands;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the specified inferior in GDB.
|
||||||
|
*
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
public class CLIInferior extends MIInterpreterExecConsole<MIInfo> {
|
||||||
|
|
||||||
|
private static final String INFERIOR = "inferior "; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public CLIInferior(ICommandControlDMContext ctx, String inferiorId) {
|
||||||
|
super(ctx, INFERIOR + inferiorId);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue