1
0
Fork 0
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:
Alena Laskavaia 2016-03-11 11:06:43 -05:00 committed by Gerrit Code Review @ Eclipse.org
parent 76c4c117c4
commit bb0ba6fd91
10 changed files with 364 additions and 9 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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"

View file

@ -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);
}
}
});

View file

@ -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);
}
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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

View file

@ -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;
}

View file

@ -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<>());
}
});
}
}