mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 06:32:10 +02:00
Bug 489455 - Add new breakpoint action to run arbitrary debugger command
This is generic support for debugger commands though mi console bridge, should be not gdb specific (have a simple gdb implementation though) We add new breakpoint action called "Debugger Command" Interface allows to enter arbitrary string(s) This is interpreted by debugger as it see fit For gdb implementation these are cli commands Change-Id: I20ca0b8b094c724e1cf8b0691f4f6cab84a3737d
This commit is contained in:
parent
76c4c117c4
commit
bb0ba6fd91
10 changed files with 364 additions and 9 deletions
|
@ -0,0 +1,26 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) Mar 11, 2016 QNX Software Systems. All Rights Reserved.
|
||||
*
|
||||
* You must obtain a written license from and pay applicable license fees to QNX
|
||||
* Software Systems before you may reproduce, modify or distribute this software,
|
||||
* or any work that includes all or part of this software. Free development
|
||||
* licenses are available for evaluation and non-commercial purposes. For more
|
||||
* information visit [http://licensing.qnx.com] or email licensing@qnx.com.
|
||||
*
|
||||
* This file may contain contributions from others. Please review this entire
|
||||
* file for other proprietary rights or license notices, as well as the QNX
|
||||
* Development Suite License Guide at [http://licensing.qnx.com/license-guide/]
|
||||
* for other information.
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.core.breakpointactions;
|
||||
|
||||
/**
|
||||
* This interface intended to pass arbitrary debugger command to backend,
|
||||
* usually intended for command line debugger or scripting. Debugger can interpret this as it see fit
|
||||
* (including splitting this into multiple commands)
|
||||
*
|
||||
* @since 8.0
|
||||
*/
|
||||
public interface ICLIDebugActionEnabler {
|
||||
void execute(String command) throws Exception;
|
||||
}
|
|
@ -173,6 +173,7 @@ LogAction.name=Log Action
|
|||
ResumeAction.name=Resume Action
|
||||
ExternalToolAction.name=External Tool Action
|
||||
ReverseDebugAction.name=Reverse Debug Action
|
||||
CLICommandAction.name=Debugger Command Action
|
||||
|
||||
# Breakpoint Types
|
||||
breapointType.label=Type
|
||||
|
|
|
@ -1301,6 +1301,23 @@
|
|||
</actionPage>
|
||||
</extension>
|
||||
|
||||
<extension
|
||||
point="org.eclipse.cdt.debug.core.BreakpointActionType">
|
||||
<actionType
|
||||
class="org.eclipse.cdt.debug.ui.breakpointactions.CLICommandAction"
|
||||
id="org.eclipse.cdt.debug.ui.breakpointactions.CLICommandAction"
|
||||
name="%CLICommandAction.name">
|
||||
</actionType>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.cdt.debug.ui.BreakpointActionPage">
|
||||
<actionPage
|
||||
actionType="org.eclipse.cdt.debug.ui.breakpointactions.CLICommandAction"
|
||||
class="org.eclipse.cdt.debug.ui.breakpointactions.CLICommandActionPage"
|
||||
id="org.eclipse.cdt.debug.ui.breakpointactions.CLICommandActionPage">
|
||||
</actionPage>
|
||||
</extension>
|
||||
|
||||
<extension point="org.eclipse.debug.ui.detailPaneFactories">
|
||||
<detailFactories
|
||||
class="org.eclipse.cdt.debug.internal.ui.views.modules.ModuleDetailPaneFactory"
|
||||
|
|
|
@ -128,7 +128,8 @@ public class ActionDialog extends Dialog {
|
|||
public void widgetSelected(final SelectionEvent e) {
|
||||
try {
|
||||
showActionComposite();
|
||||
} catch (CoreException e1) {
|
||||
} catch (Exception ex) {
|
||||
CDebugUIPlugin.log(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Alena Laskavaia (QNX)- Initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.ui.breakpointactions;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.eclipse.cdt.debug.core.CDIDebugModel;
|
||||
import org.eclipse.cdt.debug.core.breakpointactions.AbstractBreakpointAction;
|
||||
import org.eclipse.cdt.debug.core.breakpointactions.ICLIDebugActionEnabler;
|
||||
import org.eclipse.cdt.debug.internal.core.ICDebugInternalConstants;
|
||||
import org.eclipse.cdt.debug.internal.ui.IInternalCDebugUIConstants;
|
||||
import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
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.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* This breakpoint action allows to pass arbitrary command line command to debugger backend.
|
||||
* For example in case of gdb it would be something like
|
||||
* p myGlobal
|
||||
* cont
|
||||
* @since 8.0
|
||||
*/
|
||||
public class CLICommandAction extends AbstractBreakpointAction {
|
||||
private static final String COMMAND_ATT = "command"; //$NON-NLS-1$
|
||||
private String command = ""; //$NON-NLS-1$
|
||||
|
||||
@Override
|
||||
public IStatus execute(IBreakpoint breakpoint, IAdaptable context, IProgressMonitor monitor) {
|
||||
ICLIDebugActionEnabler enabler = context.getAdapter(ICLIDebugActionEnabler.class);
|
||||
if (enabler != null) {
|
||||
try {
|
||||
enabler.execute(getCommand());
|
||||
} catch (Exception e) {
|
||||
return errorStatus(e);
|
||||
}
|
||||
} else
|
||||
return new Status(IStatus.ERROR, CDebugUIPlugin.getUniqueIdentifier(),
|
||||
IInternalCDebugUIConstants.INTERNAL_ERROR,
|
||||
Messages.getString("CLICommandAction.NoSupport"), null); //$NON-NLS-1$
|
||||
return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
|
||||
}
|
||||
|
||||
private IStatus errorStatus(Exception ex) {
|
||||
String errorMsg = MessageFormat.format(Messages.getString("CLICommandAction.error.0"), //$NON-NLS-1$
|
||||
new Object[] { getSummary() });
|
||||
return new Status(IStatus.ERROR, CDIDebugModel.getPluginIdentifier(),
|
||||
ICDebugInternalConstants.STATUS_CODE_ERROR, errorMsg, ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultName() {
|
||||
return Messages.getString("CLICommandAction.UntitledName"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return "org.eclipse.cdt.debug.ui.breakpointactions.CLICommandAction"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMemento() {
|
||||
try {
|
||||
Document doc = DebugPlugin.newDocument();
|
||||
Element rootElement = doc.createElement(COMMAND_ATT);
|
||||
rootElement.setAttribute(COMMAND_ATT, command);
|
||||
doc.appendChild(rootElement);
|
||||
return DebugPlugin.serializeDocument(doc);
|
||||
} catch (DOMException | CoreException e) {
|
||||
CDebugUIPlugin.log(e);
|
||||
|
||||
}
|
||||
return ""; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public void setCommand(String command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
String summary = getCommand();
|
||||
if (summary.length() > 32)
|
||||
summary = summary.substring(0, 32);
|
||||
return summary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTypeName() {
|
||||
return Messages.getString("CLICommandAction.TypeName"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeFromMemento(String data) {
|
||||
try {
|
||||
Element root = DebugPlugin.parseDocument(data);
|
||||
String value = root.getAttribute(COMMAND_ATT);
|
||||
if (value == null)
|
||||
value = ""; //$NON-NLS-1$
|
||||
command = value;
|
||||
} catch (Exception e) {
|
||||
CDebugUIPlugin.log(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Alena Laskavaia (QNX)- Initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.ui.breakpointactions;
|
||||
|
||||
import org.eclipse.jface.layout.GridDataFactory;
|
||||
import org.eclipse.jface.layout.GridLayoutFactory;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
/**
|
||||
* This composite show a little text field (multi-line) that allow to enter to enter debugger commands.
|
||||
* Interpretation of that depends on the backend
|
||||
*
|
||||
* @since 8.0
|
||||
*/
|
||||
public class CLICommandActionComposite extends Composite {
|
||||
private Text command;
|
||||
|
||||
public CLICommandActionComposite(Composite parent, int style, CLICommandActionPage commandActionPage) {
|
||||
super(parent, style);
|
||||
setLayout(GridLayoutFactory.fillDefaults().create());
|
||||
Label messageToLogLabel = new Label(this, SWT.NONE);
|
||||
messageToLogLabel.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create());
|
||||
messageToLogLabel.setText(Messages.getString("CLICommandActionComposite.0")); //$NON-NLS-1$
|
||||
command = new Text(this, SWT.BORDER | SWT.WRAP);
|
||||
command.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
|
||||
command.setText(commandActionPage.getCLICommandAction().getCommand());
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command.getText();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Alena Laskavaia (QNX)- Initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.ui.breakpointactions;
|
||||
|
||||
import org.eclipse.cdt.debug.core.breakpointactions.IBreakpointAction;
|
||||
import org.eclipse.cdt.debug.ui.breakpointactions.IBreakpointActionPage;
|
||||
import org.eclipse.core.runtime.PlatformObject;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
/**
|
||||
* @since 8.0
|
||||
*/
|
||||
public class CLICommandActionPage extends PlatformObject implements
|
||||
IBreakpointActionPage {
|
||||
private CLICommandAction cliCommandAction;
|
||||
private CLICommandActionComposite editor;
|
||||
|
||||
public CLICommandAction getCLICommandAction() {
|
||||
return cliCommandAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionDialogCanceled() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionDialogOK() {
|
||||
cliCommandAction.setCommand(editor.getCommand());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Composite createComposite(IBreakpointAction action, Composite composite, int style) {
|
||||
cliCommandAction = (CLICommandAction) action;
|
||||
editor = new CLICommandActionComposite(composite, style, this);
|
||||
return editor;
|
||||
}
|
||||
}
|
|
@ -71,3 +71,10 @@ ReverseDebugAction.error.1=Could not do reverse debug operation
|
|||
ReverseDebugAction.enable=Enable
|
||||
ReverseDebugAction.disable=Disable
|
||||
ReverseDebugAction.toggle=Toggle
|
||||
|
||||
CLICommandActionComposite.0=Debugger command(s) to run when the breakpoint is hit:
|
||||
CLICommandAction.ConsoleTitle=Debugger Command Action Messages
|
||||
CLICommandAction.UntitledName=Untitled Debugger Command Action
|
||||
CLICommandAction.TypeName=Debugger Command Action
|
||||
CLICommandAction.error.0=Could not execute debugger command action: "{0}".
|
||||
CLICommandAction.NoSupport=Your debugger integration does not support direct exectution of commands
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
package org.eclipse.cdt.dsf.mi.service.breakpoint.actions;
|
||||
|
||||
import org.eclipse.cdt.debug.core.breakpointactions.ICLIDebugActionEnabler;
|
||||
import org.eclipse.cdt.debug.core.breakpointactions.ILogActionEnabler;
|
||||
import org.eclipse.cdt.debug.core.breakpointactions.IResumeActionEnabler;
|
||||
import org.eclipse.cdt.debug.core.breakpointactions.IReverseDebugEnabler;
|
||||
|
@ -47,6 +48,9 @@ public class BreakpointActionAdapter implements IAdaptable {
|
|||
if (adapter.equals(IReverseDebugEnabler.class)) {
|
||||
return (T)new MIReverseDebugEnabler(fExecutor, fServiceTracker, fContext);
|
||||
}
|
||||
if (adapter.equals(ICLIDebugActionEnabler.class)) {
|
||||
return (T)new CLIDebugActionEnabler(fExecutor, fServiceTracker, fContext);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Alena Laskavaia (QNX)- Initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.mi.service.breakpoint.actions;
|
||||
|
||||
import org.eclipse.cdt.debug.core.breakpointactions.ICLIDebugActionEnabler;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CLIEventProcessor;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.CLICommand;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIInterpreterExecConsole;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
|
||||
/**
|
||||
*
|
||||
* This class permits to execute custom user debugger commands through cli/mi bridge
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public class CLIDebugActionEnabler implements ICLIDebugActionEnabler {
|
||||
private final DsfExecutor fExecutor;
|
||||
private final DsfServicesTracker fServiceTracker;
|
||||
private final ICommandControlDMContext fContext;
|
||||
private ICommandControlService fCommandControl;
|
||||
|
||||
/**
|
||||
* @param executor
|
||||
* @param serviceTracker
|
||||
* @param context
|
||||
*/
|
||||
public CLIDebugActionEnabler(DsfExecutor executor, DsfServicesTracker serviceTracker, IDMContext context) {
|
||||
fExecutor = executor;
|
||||
fServiceTracker = serviceTracker;
|
||||
fContext = DMContexts.getAncestorOfType(context, ICommandControlDMContext.class);
|
||||
fCommandControl = fServiceTracker.getService(ICommandControlService.class);
|
||||
assert fContext != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String commandmulti) throws Exception {
|
||||
String[] commands = commandmulti.split("\\r?\\n"); //$NON-NLS-1$
|
||||
for (int j = 0; j < commands.length; ++j) {
|
||||
String single = commands[j];
|
||||
executeSingleCommand(single);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMIOperation(String operation) {
|
||||
if (operation.startsWith("-")) { //$NON-NLS-1$
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void executeSingleCommand(String str) {
|
||||
// Do not use the interpreter-exec for stepping operation the UI will fall out of step.
|
||||
// Also, do not use "interpreter-exec console" for MI commands.
|
||||
ICommand<MIInfo> cmd;
|
||||
if (!isMIOperation(str) &&
|
||||
!CLIEventProcessor.isSteppingOperation(str)) {
|
||||
cmd = new MIInterpreterExecConsole<>(fContext, str);
|
||||
} else {
|
||||
cmd = new CLICommand<>(fContext, str);
|
||||
}
|
||||
fExecutor.execute(new DsfRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO: for print command would be nice to redirect to gdb console
|
||||
fCommandControl.queueCommand(cmd, new ImmediateDataRequestMonitor<>());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue