1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Bug 284286: Trace Record visualization for DSF-GDB

This commit is contained in:
Marc Khouzam 2010-04-28 23:50:54 +00:00
parent 63207d9813
commit c8835a2f95
34 changed files with 1807 additions and 359 deletions

View file

@ -40,3 +40,9 @@ view.traceControl.name=Trace Control
toolbar.startTracing.name=Start Tracing
toolbar.stopTracing.name=Stop Tracing
toolbar.saveTracing.name=Save Trace Data
toolbar.nextTraceRecord.label=Next Trace Record
toolbar.prevTraceRecord.label=Previous Trace Record
command.nextTraceRecord.name=Next Trace Record
command.prevTraceRecord.name=Previous Trace Record
command.nextTraceRecord.description=Select Next Trace Record
command.prevTraceRecord.description=Select Previous Trace Record

View file

@ -353,6 +353,30 @@
</viewShortcut>
</perspectiveExtension>
</extension>
<extension
point="org.eclipse.ui.commands">
<command
description="%command.nextTraceRecord.description"
id="org.eclipse.cdt.dsf.gdb.ui.command.selectNextTraceRecord"
name="%command.nextTraceRecord.name">
</command>
<command
description="%command.prevTraceRecord.description"
id="org.eclipse.cdt.dsf.gdb.ui.command.selectPreviousTraceRecord"
name="%command.prevTraceRecord.name">
</command>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="org.eclipse.cdt.dsf.gdb.internal.ui.commands.SelectNextTraceRecordCommandHandler"
commandId="org.eclipse.cdt.dsf.gdb.ui.command.selectNextTraceRecord">
</handler>
<handler
class="org.eclipse.cdt.dsf.gdb.internal.ui.commands.SelectPrevTraceRecordCommandHandler"
commandId="org.eclipse.cdt.dsf.gdb.ui.command.selectPreviousTraceRecord">
</handler>
</extension>
<extension
point="org.eclipse.ui.menus">
<menuContribution
@ -369,6 +393,18 @@
label="%toolbar.stopTracing.name"
style="push">
</command>
<command
commandId="org.eclipse.cdt.dsf.gdb.ui.command.selectNextTraceRecord"
icon="icons/full/obj16/next_trace_record_nav.gif"
label="%toolbar.nextTraceRecord.label"
style="push">
</command>
<command
commandId="org.eclipse.cdt.dsf.gdb.ui.command.selectPreviousTraceRecord"
icon="icons/full/obj16/prev_trace_record_nav.gif"
label="%toolbar.prevTraceRecord.label"
style="push">
</command>
</menuContribution>
<menuContribution
locationURI="menu:org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view?after=additions">

View file

@ -40,6 +40,8 @@ import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.DefaultRefreshAllTarget;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.IRefreshAllTarget;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.DefaultDsfModelSelectionPolicyFactory;
import org.eclipse.cdt.dsf.gdb.actions.IConnect;
import org.eclipse.cdt.dsf.gdb.internal.commands.ISelectNextTraceRecordHandler;
import org.eclipse.cdt.dsf.gdb.internal.commands.ISelectPrevTraceRecordHandler;
import org.eclipse.cdt.dsf.gdb.internal.ui.actions.DsfTerminateCommand;
import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbConnectCommand;
import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbDisconnectCommand;
@ -51,6 +53,8 @@ import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseStepIntoCommand;
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseStepOverCommand;
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseToggleCommand;
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbSaveTraceDataCommand;
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbSelectNextTraceRecordCommand;
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbSelectPrevTraceRecordCommand;
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbStartTracingCommand;
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbStopTracingCommand;
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbUncallCommand;
@ -119,6 +123,8 @@ public class GdbAdapterFactory
final GdbStartTracingCommand fStartTracingTarget;
final GdbStopTracingCommand fStopTracingTarget;
final GdbSaveTraceDataCommand fSaveTraceDataTarget;
final GdbSelectNextTraceRecordCommand fSelectNextRecordTarget;
final GdbSelectPrevTraceRecordCommand fSelectPrevRecordTarget;
final GdbDebugTextHover fDebugTextHover;
SessionAdapterSet(GdbLaunch launch) {
@ -161,6 +167,8 @@ public class GdbAdapterFactory
fStartTracingTarget = new GdbStartTracingCommand(session);
fStopTracingTarget = new GdbStopTracingCommand(session);
fSaveTraceDataTarget = new GdbSaveTraceDataCommand(session);
fSelectNextRecordTarget = new GdbSelectNextTraceRecordCommand(session);
fSelectPrevRecordTarget = new GdbSelectPrevTraceRecordCommand(session);
session.registerModelAdapter(ISteppingModeTarget.class, fSteppingModeTarget);
session.registerModelAdapter(IStepIntoHandler.class, fStepIntoCommand);
@ -183,6 +191,8 @@ public class GdbAdapterFactory
session.registerModelAdapter(IStartTracingHandler.class, fStartTracingTarget);
session.registerModelAdapter(IStopTracingHandler.class, fStopTracingTarget);
session.registerModelAdapter(ISaveTraceDataHandler.class, fSaveTraceDataTarget);
session.registerModelAdapter(ISelectNextTraceRecordHandler.class, fSelectNextRecordTarget);
session.registerModelAdapter(ISelectPrevTraceRecordHandler.class, fSelectPrevRecordTarget);
fDebugModelProvider = new IDebugModelProvider() {
// @see org.eclipse.debug.core.model.IDebugModelProvider#getModelIdentifiers()
@ -238,7 +248,9 @@ public class GdbAdapterFactory
session.unregisterModelAdapter(IStartTracingHandler.class);
session.unregisterModelAdapter(IStopTracingHandler.class);
session.unregisterModelAdapter(ISaveTraceDataHandler.class);
session.unregisterModelAdapter(ISelectNextTraceRecordHandler.class);
session.unregisterModelAdapter(ISelectPrevTraceRecordHandler.class);
session.unregisterModelAdapter(ICEditorTextHover.class);
fSteppingModeTarget.dispose();
@ -261,6 +273,8 @@ public class GdbAdapterFactory
fStartTracingTarget.dispose();
fStopTracingTarget.dispose();
fSaveTraceDataTarget.dispose();
fSelectNextRecordTarget.dispose();
fSelectPrevRecordTarget.dispose();
}
}

View file

@ -0,0 +1,167 @@
/*******************************************************************************
* 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.commands;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.Query;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.gdb.internal.commands.ISelectNextTraceRecordHandler;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordDMContext;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.IRequest;
import org.eclipse.debug.core.commands.AbstractDebugCommand;
import org.eclipse.debug.core.commands.IDebugCommandRequest;
import org.eclipse.debug.core.commands.IEnabledStateRequest;
/**
* Command to select the next trace record
*
* @since 2.1
*/
public class GdbSelectNextTraceRecordCommand extends AbstractDebugCommand implements ISelectNextTraceRecordHandler {
private final DsfExecutor fExecutor;
private final DsfServicesTracker fTracker;
public GdbSelectNextTraceRecordCommand(DsfSession session) {
fExecutor = session.getExecutor();
fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
}
public void dispose() {
fTracker.dispose();
}
@Override
protected void doExecute(Object[] targets, IProgressMonitor monitor, IRequest request) throws CoreException {
if (targets.length != 1) {
return;
}
final ITraceTargetDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)targets[0]).getDMContext(), ITraceTargetDMContext.class);
if (dmc == null) {
return;
}
Query<Object> selectRecordQuery = new Query<Object>() {
@Override
public void execute(final DataRequestMonitor<Object> rm) {
final IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
if (traceControl != null) {
traceControl.getCurrentTraceRecordContext(
dmc,
new DataRequestMonitor<ITraceRecordDMContext>(fExecutor, rm) {
@Override
protected void handleSuccess() {
ITraceRecordDMContext nextDmc = traceControl.createNextRecordContext(getData());
traceControl.selectTraceRecord(nextDmc, rm);
};
});
} else {
rm.done();
}
}
};
try {
fExecutor.execute(selectRecordQuery);
selectRecordQuery.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} catch (RejectedExecutionException e) {
// Can be thrown if the session is shutdown
}
}
@Override
protected boolean isExecutable(Object[] targets, IProgressMonitor monitor, IEnabledStateRequest request)
throws CoreException
{
if (targets.length != 1) {
return false;
}
final ITraceTargetDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)targets[0]).getDMContext(), ITraceTargetDMContext.class);
if (dmc == null) {
return false;
}
Query<Boolean> canSelectRecordQuery = new Query<Boolean>() {
@Override
public void execute(final DataRequestMonitor<Boolean> rm) {
IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
if (traceControl != null) {
traceControl.getTraceStatus(dmc, new DataRequestMonitor<ITraceStatusDMData>(fExecutor, rm) {
@Override
protected void handleSuccess() {
if (getData().getNumberOfCollectedFrame() > 0) {
IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
if (traceControl != null) {
traceControl.isTracing(dmc, new DataRequestMonitor<Boolean>(fExecutor, rm) {
@Override
protected void handleSuccess() {
rm.setData(!getData());
rm.done();
};
});
} else {
rm.setData(false);
rm.done();
}
} else {
rm.setData(false);
rm.done();
}
};
});
} else {
rm.setData(false);
rm.done();
}
}
};
try {
fExecutor.execute(canSelectRecordQuery);
return canSelectRecordQuery.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} catch (RejectedExecutionException e) {
// Can be thrown if the session is shutdown
}
return false;
}
@Override
protected Object getTarget(Object element) {
if (element instanceof IDMVMContext) {
return element;
}
return null;
}
@Override
protected boolean isRemainEnabled(IDebugCommandRequest request) {
return true;
}
}

View file

@ -0,0 +1,167 @@
/*******************************************************************************
* 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.commands;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.Query;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.gdb.internal.commands.ISelectPrevTraceRecordHandler;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordDMContext;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.IRequest;
import org.eclipse.debug.core.commands.AbstractDebugCommand;
import org.eclipse.debug.core.commands.IDebugCommandRequest;
import org.eclipse.debug.core.commands.IEnabledStateRequest;
/**
* Command to select the previous trace record
*
* @since 2.1
*/
public class GdbSelectPrevTraceRecordCommand extends AbstractDebugCommand implements ISelectPrevTraceRecordHandler {
private final DsfExecutor fExecutor;
private final DsfServicesTracker fTracker;
public GdbSelectPrevTraceRecordCommand(DsfSession session) {
fExecutor = session.getExecutor();
fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
}
public void dispose() {
fTracker.dispose();
}
@Override
protected void doExecute(Object[] targets, IProgressMonitor monitor, IRequest request) throws CoreException {
if (targets.length != 1) {
return;
}
final ITraceTargetDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)targets[0]).getDMContext(), ITraceTargetDMContext.class);
if (dmc == null) {
return;
}
Query<Object> selectRecordQuery = new Query<Object>() {
@Override
public void execute(final DataRequestMonitor<Object> rm) {
final IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
if (traceControl != null) {
traceControl.getCurrentTraceRecordContext(
dmc,
new DataRequestMonitor<ITraceRecordDMContext>(fExecutor, rm) {
@Override
protected void handleSuccess() {
ITraceRecordDMContext prevDmc = traceControl.createPrevRecordContext(getData());
traceControl.selectTraceRecord(prevDmc, rm);
};
});
} else {
rm.done();
}
}
};
try {
fExecutor.execute(selectRecordQuery);
selectRecordQuery.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} catch (RejectedExecutionException e) {
// Can be thrown if the session is shutdown
}
}
@Override
protected boolean isExecutable(Object[] targets, IProgressMonitor monitor, IEnabledStateRequest request)
throws CoreException
{
if (targets.length != 1) {
return false;
}
final ITraceTargetDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)targets[0]).getDMContext(), ITraceTargetDMContext.class);
if (dmc == null) {
return false;
}
Query<Boolean> canSelectRecordQuery = new Query<Boolean>() {
@Override
public void execute(final DataRequestMonitor<Boolean> rm) {
IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
if (traceControl != null) {
traceControl.getTraceStatus(dmc, new DataRequestMonitor<ITraceStatusDMData>(fExecutor, rm) {
@Override
protected void handleSuccess() {
if (getData().getNumberOfCollectedFrame() > 0) {
IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
if (traceControl != null) {
traceControl.isTracing(dmc, new DataRequestMonitor<Boolean>(fExecutor, rm) {
@Override
protected void handleSuccess() {
rm.setData(!getData());
rm.done();
};
});
} else {
rm.setData(false);
rm.done();
}
} else {
rm.setData(false);
rm.done();
}
};
});
} else {
rm.setData(false);
rm.done();
}
}
};
try {
fExecutor.execute(canSelectRecordQuery);
return canSelectRecordQuery.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} catch (RejectedExecutionException e) {
// Can be thrown if the session is shutdown
}
return false;
}
@Override
protected Object getTarget(Object element) {
if (element instanceof IDMVMContext) {
return element;
}
return null;
}
@Override
protected boolean isRemainEnabled(IDebugCommandRequest request) {
return true;
}
}

View file

@ -0,0 +1,26 @@
/*******************************************************************************
* 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.commands;
import org.eclipse.cdt.dsf.gdb.internal.commands.ISelectNextTraceRecordHandler;
import org.eclipse.debug.ui.actions.DebugCommandHandler;
/**
* Command handler to select the next trace record
*
* @since 2.1
*/
public class SelectNextTraceRecordCommandHandler extends DebugCommandHandler {
@Override
protected Class<?> getCommandType() {
return ISelectNextTraceRecordHandler.class;
}
}

View file

@ -0,0 +1,26 @@
/*******************************************************************************
* 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.commands;
import org.eclipse.cdt.dsf.gdb.internal.commands.ISelectPrevTraceRecordHandler;
import org.eclipse.debug.ui.actions.DebugCommandHandler;
/**
* Command handler to select the previous trace record
*
* @since 2.1
*/
public class SelectPrevTraceRecordCommandHandler extends DebugCommandHandler {
@Override
protected Class<?> getCommandType() {
return ISelectPrevTraceRecordHandler.class;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008 QNX Software Systems and others.
* Copyright (c) 2008, 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
@ -8,6 +8,7 @@
* Contributors:
* QNX Software Systems - initial API and implementation
* Ken Ryall (Nokia) - bug 178731
* Ericsson - Support for tracepoint post-mortem debugging
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
@ -17,6 +18,7 @@ import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
import org.eclipse.cdt.launch.ui.CAbstractMainTab;
@ -39,11 +41,14 @@ import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.TwoPaneElementSelector;
@ -66,7 +71,18 @@ public class CMainTab extends CAbstractMainTab {
* @since 2.0
*/
public static final String TAB_ID = "org.eclipse.cdt.dsf.gdb.launch.mainTab"; //$NON-NLS-1$
private static final String CORE_FILE = LaunchMessages.getString("CMainTab.CoreFile_type"); //$NON-NLS-1$
private static final String TRACE_FILE = LaunchMessages.getString("CMainTab.TraceFile_type"); //$NON-NLS-1$
/**
* Combo box to select which type of post mortem file should be used.
* We currently support core files and trace files.
*
* @since 2.1
*/
protected Combo fCoreTypeCombo;
private final boolean fDontCheckProgram;
private final boolean fSpecifyCoreFile;
private final boolean fIncludeBuildSettings;
@ -151,7 +167,7 @@ public class CMainTab extends CAbstractMainTab {
browseForBinaryButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt) {
String text = handleBrowseButtonSelected();
String text = handleBrowseButtonSelected(LaunchMessages.getString("CMaintab.Application_Selection")); //$NON-NLS-1$
if (text != null) {
fProgText.setText(text);
}
@ -160,6 +176,92 @@ public class CMainTab extends CAbstractMainTab {
});
}
/*
* Overridden to add the possibility to choose a trace file as a post mortem debug file.
*/
/** @since 2.1 */
@Override
protected void createCoreFileGroup(Composite parent, int colSpan) {
Composite coreComp = new Composite(parent, SWT.NONE);
GridLayout coreLayout = new GridLayout();
coreLayout.numColumns = 3;
coreLayout.marginHeight = 0;
coreLayout.marginWidth = 0;
coreComp.setLayout(coreLayout);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = colSpan;
coreComp.setLayoutData(gd);
Label comboLabel = new Label(coreComp, SWT.NONE);
comboLabel.setText(LaunchMessages.getString("CMainTab.Post_mortem_file_type")); //$NON-NLS-1$
comboLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
fCoreTypeCombo = new Combo(coreComp, SWT.READ_ONLY | SWT.DROP_DOWN);
fCoreTypeCombo.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
fCoreTypeCombo.add(CORE_FILE);
fCoreTypeCombo.add(TRACE_FILE);
fCoreLabel = new Label(coreComp, SWT.NONE);
fCoreLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
fCoreText = new Text(coreComp, SWT.SINGLE | SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL);
fCoreText.setLayoutData(gd);
fCoreText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent evt) {
updateLaunchConfigurationDialog();
}
});
Button browseForCoreButton;
browseForCoreButton = createPushButton(coreComp, LaunchMessages.getString("Launch.common.Browse_2"), null); //$NON-NLS-1$
browseForCoreButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent evt) {
String text;
String coreType = getSelectedCoreType();
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
text = handleBrowseButtonSelected(LaunchMessages.getString("CMaintab.Core_Selection")); //$NON-NLS-1$
} else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
text = handleBrowseButtonSelected(LaunchMessages.getString("CMaintab.Trace_Selection")); //$NON-NLS-1$
} else {
assert false : "Unknown core file type"; //$NON-NLS-1$
text = handleBrowseButtonSelected(LaunchMessages.getString("CMaintab.Core_Selection")); //$NON-NLS-1$
}
if (text != null) {
fCoreText.setText(text);
}
updateLaunchConfigurationDialog();
}
});
fCoreTypeCombo.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
updateCoreFileLabel();
updateLaunchConfigurationDialog();
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
fCoreTypeCombo.select(0);
}
/**
* Show a dialog that lets the user select a file.
* This method allows to set the title of the dialog.
*
* @param title The title the dialog should show.
*
* @since 2.1
*/
protected String handleBrowseButtonSelected(String title) {
FileDialog fileDialog = new FileDialog(getShell(), SWT.NONE);
fileDialog.setText(title);
fileDialog.setFileName(fProgText.getText());
return fileDialog.open();
}
/*
* (non-Javadoc)
*
@ -177,12 +279,50 @@ public class CMainTab extends CAbstractMainTab {
protected void updateCoreFromConfig(ILaunchConfiguration config) {
if (fCoreText != null) {
String coreName = EMPTY_STRING;
String coreType = IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT;
try {
coreName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, EMPTY_STRING);
coreType = config.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE,
IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT);
} catch (CoreException ce) {
GdbUIPlugin.log(ce);
}
fCoreText.setText(coreName);
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
fCoreTypeCombo.setText(CORE_FILE);
} else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
fCoreTypeCombo.setText(TRACE_FILE);
} else {
assert false : "Unknown core file type"; //$NON-NLS-1$
fCoreTypeCombo.setText(CORE_FILE);
}
updateCoreFileLabel();
}
}
/** @since 2.1 */
protected String getSelectedCoreType() {
int selectedIndex = fCoreTypeCombo.getSelectionIndex();
if (fCoreTypeCombo.getItem(selectedIndex).equals(CORE_FILE)) {
return IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE;
} else if (fCoreTypeCombo.getItem(selectedIndex).equals(TRACE_FILE)) {
return IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE;
} else {
assert false : "Unknown post mortem file type"; //$NON-NLS-1$
return IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE;
}
}
/** @since 2.1 */
protected void updateCoreFileLabel() {
String coreType = getSelectedCoreType();
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
fCoreLabel.setText(LaunchMessages.getString("CMainTab.CoreFile_path")); //$NON-NLS-1$
} else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
fCoreLabel.setText(LaunchMessages.getString("CMainTab.TraceFile_path")); //$NON-NLS-1$
} else {
assert false : "Unknown post mortem file type"; //$NON-NLS-1$
fCoreLabel.setText(LaunchMessages.getString("CMainTab.CoreFile_path")); //$NON-NLS-1$
}
}
@ -206,6 +346,7 @@ public class CMainTab extends CAbstractMainTab {
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, fProgText.getText());
if (fCoreText != null) {
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, fCoreText.getText());
config.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE, getSelectedCoreType());
}
}
@ -350,12 +491,12 @@ public class CMainTab extends CAbstractMainTab {
// This allows to re-use the launch, with a different core file.
if (!coreName.equals(EMPTY_STRING)) {
if (coreName.equals(".") || coreName.equals("..")) { //$NON-NLS-1$ //$NON-NLS-2$
setErrorMessage(LaunchMessages.getString("CMainTab.Core_does_not_exist")); //$NON-NLS-1$
setErrorMessage(LaunchMessages.getString("CMainTab.File_does_not_exist")); //$NON-NLS-1$
return false;
}
IPath corePath = new Path(coreName);
if (!corePath.toFile().exists()) {
setErrorMessage(LaunchMessages.getString("CMainTab.Core_does_not_exist")); //$NON-NLS-1$
setErrorMessage(LaunchMessages.getString("CMainTab.File_does_not_exist")); //$NON-NLS-1$
return false;
}
}

View file

@ -20,6 +20,7 @@ Bundle-RequiredExecutionEnvironment: J2SE-1.5
Export-Package: org.eclipse.cdt.dsf.gdb,
org.eclipse.cdt.dsf.gdb.actions,
org.eclipse.cdt.dsf.gdb.breakpoints,
org.eclipse.cdt.dsf.gdb.internal.commands,
org.eclipse.cdt.dsf.gdb.launching,
org.eclipse.cdt.dsf.gdb.service,
org.eclipse.cdt.dsf.gdb.service.command,

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008 Ericsson and others.
* Copyright (c) 2008, 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
@ -90,6 +90,13 @@ public class IGDBLaunchConfigurationConstants {
*/
public static final String ATTR_DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND = GdbPlugin.PLUGIN_ID + ".UPDATE_THREADLIST_ON_SUSPEND"; //$NON-NLS-1$
/**
* Launch configuration attribute key. The value is a String specifying the type of post mortem launch.
* @since 3.0
*/
public static final String ATTR_DEBUGGER_POST_MORTEM_TYPE = GdbPlugin.PLUGIN_ID + ".POST_MORTEM_TYPE"; //$NON-NLS-1$
/**
* Launch configuration attribute value. The key is ATTR_DEBUG_NAME.
*/
@ -131,4 +138,26 @@ public class IGDBLaunchConfigurationConstants {
*/
public static final boolean DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND_DEFAULT = false;
/**
* Possible attribute value for the key is ATTR_DEBUGGER_POST_MORTEM_TYPE.
* Indicates a core file.
*
* @since 3.0
*/
public static final String DEBUGGER_POST_MORTEM_CORE_FILE = "CORE_FILE"; //$NON-NLS-1$
/**
* Possible attribute value for the key is ATTR_DEBUGGER_POST_MORTEM_TYPE.
* Indicates a trace data file.
*
* @since 3.0
*/
public static final String DEBUGGER_POST_MORTEM_TRACE_FILE = "TRACE_FILE"; //$NON-NLS-1$
/**
* Launch configuration attribute value. The key is ATTR_DEBUGGER_POST_MORTEM_TYPE.
* @since 3.0
*/
public static final String DEBUGGER_POST_MORTEM_TYPE_DEFAULT = DEBUGGER_POST_MORTEM_CORE_FILE;
}

View file

@ -0,0 +1,21 @@
/*******************************************************************************
* 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.commands;
import org.eclipse.debug.core.commands.IDebugCommandHandler;
/**
* Handler interface to select the next trace record.
*
* @since 3.0
*/
public interface ISelectNextTraceRecordHandler extends IDebugCommandHandler {
}

View file

@ -0,0 +1,21 @@
/*******************************************************************************
* 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.commands;
import org.eclipse.debug.core.commands.IDebugCommandHandler;
/**
* Handler interface to select the previous trace record.
*
* @since 3.0
*/
public interface ISelectPrevTraceRecordHandler extends IDebugCommandHandler {
}

View file

@ -0,0 +1,84 @@
/*******************************************************************************
* 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.service.command.events;
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.Immutable;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
import org.eclipse.cdt.dsf.mi.service.command.output.MIConst;
import org.eclipse.cdt.dsf.mi.service.command.output.MIFrame;
import org.eclipse.cdt.dsf.mi.service.command.output.MIResult;
import org.eclipse.cdt.dsf.mi.service.command.output.MIValue;
/**
* Conveys that gdb has selected a new tracepoint record. Although this
* is a response to an MI command, we trigger an MI event internally
* because it should cause the same behaviour as if we stopped at a
* breakpoint. The output record looks like this:
*
* <code>
* ^done,found="1",tracepoint="1",traceframe="0",frame={level="0",addr="0x08048900",func="foo",args=[{name="i",value="2"}],file="file.cpp",fullname="/home/marc/file.cpp",line="505"}
* </code>
* @since 3.0
*/
@Immutable
public class MITracepointSelectedEvent extends MIBreakpointHitEvent {
private int fRecNo;
protected MITracepointSelectedEvent(IExecutionDMContext ctx, int token, MIResult[] results, MIFrame frame, int trptno, int recordno) {
super(ctx, token, results, frame, trptno);
fRecNo = recordno;
}
/**
* Returns a text to display for the reason why we show the debug view as stopped.
*/
public String getReason() {
return Messages.Tracepoint + " " + getNumber() + //$NON-NLS-1$
", " + Messages.Record + " " + fRecNo; //$NON-NLS-1$ //$NON-NLS-2$
}
@ConfinedToDsfExecutor("")
public static MITracepointSelectedEvent parse(IExecutionDMContext dmc, int token, MIResult[] results) {
int trptno = -1;
int recordno = -1;
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue value = results[i].getMIValue();
String str = ""; //$NON-NLS-1$
if (value != null && value instanceof MIConst) {
str = ((MIConst)value).getString();
}
if (var.equals("tracepoint")) { //$NON-NLS-1$
try {
trptno = Integer.parseInt(str.trim());
} catch (NumberFormatException e) {
}
} else if (var.equals("traceframe")) { //$NON-NLS-1$
try {
recordno = Integer.parseInt(str.trim());
} catch (NumberFormatException e) {
}
}
}
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(dmc, token, results);
return new MITracepointSelectedEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame(), trptno, recordno);
}
}

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* 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.service.command.events;
import org.eclipse.osgi.util.NLS;
/**
* @noinstantiate This class is not intended to be instantiated by clients.
*/
public class Messages extends NLS {
private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.gdb.internal.service.command.events.messages"; //$NON-NLS-1$
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
private Messages() {
}
public static String Tracepoint;
public static String Record;
}

View file

@ -0,0 +1,13 @@
###############################################################################
# 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
###############################################################################
Tracepoint=Tracepoint
Record=Record

View file

@ -21,6 +21,7 @@ import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Sequence;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
@ -29,6 +30,8 @@ import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.gdb.actions.IConnect;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
import org.eclipse.cdt.dsf.gdb.service.SessionType;
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
@ -370,31 +373,60 @@ public class FinalLaunchSequence extends Sequence {
if (fSessionType == SessionType.CORE) {
try {
String coreFile = fLaunch.getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, ""); //$NON-NLS-1$
final String coreType = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE,
IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT);
if (coreFile.length() == 0) {
new PromptForCoreJob(
"Prompt for core file", //$NON-NLS-1$
"Prompt for post mortem file", //$NON-NLS-1$
new DataRequestMonitor<String>(getExecutor(), requestMonitor) {
@Override
protected void handleSuccess() {
String newCoreFile = getData();
if (newCoreFile == null || newCoreFile.length()== 0) {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get core file path", null)); //$NON-NLS-1$
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get post mortem file path", null)); //$NON-NLS-1$
requestMonitor.done();
} else {
fCommandControl.queueCommand(
fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), newCoreFile),
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
fCommandControl.queueCommand(
fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), newCoreFile),
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
} else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
if (traceControl != null) {
ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(fCommandControl.getContext(), ITraceTargetDMContext.class);
traceControl.loadTraceData(targetDmc, newCoreFile, requestMonitor);
} else {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null));
requestMonitor.done();
}
} else {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null));
requestMonitor.done();
}
}
}
}).schedule();
} else {
fCommandControl.queueCommand(
fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), coreFile),
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
fCommandControl.queueCommand(
fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), coreFile),
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
} else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
if (traceControl != null) {
ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(fCommandControl.getContext(), ITraceTargetDMContext.class);
traceControl.loadTraceData(targetDmc, coreFile, requestMonitor);
} else {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null));
requestMonitor.done();
}
} else {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null));
requestMonitor.done();
}
}
} catch (CoreException e) {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get core file path", e)); //$NON-NLS-1$
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get post mortem file path", e));
requestMonitor.done();
}
} else {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010 QNX Software Systems and others.
* Copyright (c) 2008, 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
@ -10,6 +10,7 @@
* Windriver and Ericsson - Updated for DSF
* IBM Corporation
* Ericsson - Added support for Mac OS
* Ericsson - Added support for post-mortem trace files
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.launching;
@ -57,7 +58,10 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
private final static String NON_STOP_FIRST_VERSION = "6.8.50"; //$NON-NLS-1$
private boolean isNonStopSession = false;
private final static String TRACING_FIRST_VERSION = "7.1.50"; //$NON-NLS-1$
private boolean fIsPostMortemTracingSession;
@Override
public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
org.eclipse.cdt.launch.LaunchUtils.enableActivity("org.eclipse.cdt.debug.dsfgdbActivity", true); //$NON-NLS-1$
@ -129,6 +133,10 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Non-stop mode is only supported starting with GDB " + NON_STOP_FIRST_VERSION, null)); //$NON-NLS-1$
}
if (fIsPostMortemTracingSession && !isPostMortemTracingSupported(gdbVersion)) {
throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Post-mortem tracing is only supported starting with GDB " + TRACING_FIRST_VERSION, null)); //$NON-NLS-1$
}
launch.setServiceFactory(newServiceFactory(gdbVersion));
// Create and invoke the launch sequence to create the debug control and services
@ -254,6 +262,18 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
return false;
}
private boolean isPostMortemTracingSession(ILaunchConfiguration config) {
SessionType sessionType = LaunchUtils.getSessionType(config);
if (sessionType == SessionType.CORE) {
try {
String coreType = config.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE,
IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT);
return coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE);
} catch (CoreException e) {
}
}
return false;
}
@Override
public boolean preLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) throws CoreException {
@ -271,6 +291,7 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
// the source lookup adapter.
isNonStopSession = isNonStopSession(configuration);
fIsPostMortemTracingSession = isPostMortemTracingSession(configuration);
GdbLaunch launch = new GdbLaunch(configuration, mode, null);
launch.initialize();
@ -300,7 +321,22 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
}
return false;
}
private boolean isPostMortemTracingSupported(String version) {
if (version.contains(LaunchUtils.MACOS_GDB_MARKER)) {
// Mac OS's GDB does not support post-mortem tracing
return false;
}
if (TRACING_FIRST_VERSION.compareTo(version) <= 0
// This feature will be available for GDB 7.2. But until that GDB is itself available
// there is a pre-release that has a version of 6.8.50.20090414
|| "6.8.50.20090414".equals(version)) {
return true;
}
return false;
}
// A subclass can override this method and provide its own ServiceFactory.
protected IDsfDebugServicesFactory newServiceFactory(String version) {

View file

@ -86,16 +86,23 @@ CMainTab.Project_not_specified=Project not specified
CMainTab.Program_not_specified=Program not specified
CMainTab.Project_must_be_opened=Project must be opened
CMainTab.Program_does_not_exist=Program does not exist
CMainTab.Core_does_not_exist=Core file does not exist
CMainTab.File_does_not_exist=File does not exist
CMainTab.Main=Main
CMainTab.&ProjectColon=&Project:
CMainTab.C/C++_Application=C/C++ Application:
CMainTab.CoreFile_type=Core file
CMainTab.TraceFile_type=Trace file
CMainTab.CoreFile_path=Core file (leave blank to trigger prompt):
CMainTab.TraceFile_path=Trace data file (leave blank to trigger prompt):
CMainTab.Search...=Searc&h Project...
CMainTab.Choose_program_to_run=Choose a &program to run:
CMainTab.Choose_program_to_run_from_NAME=Choose a program to run from {0}:
CMainTab.UseTerminal=Connect process input && output to a terminal.
CMainTab.Program_is_not_a_recongnized_executable=Program is not a recognized executable.
CMaintab.Application_Selection=Application Selection
CMaintab.Core_Selection=Core File Selection
CMaintab.Trace_Selection=Trace File Selection
CMainTab.Post_mortem_file_type=Post Mortem file type:
CDebuggerTab.Advanced_Options_Dialog_Title=Advanced Options
CDebuggerTab.Stop_at_main_on_startup=Stop on startup at:

View file

@ -782,6 +782,18 @@ public class GDBProcesses_7_0 extends AbstractDsfService
}
private IMIContainerDMContext[] makeContainerDMCs(ICommandControlDMContext controlDmc, IThreadGroupInfo[] groups) {
// This is a workaround for post-mortem tracing because the early GDB release
// does not report a process when we do -list-thread-group
// GDB 7.2 will properly report the process so this
// code can be removed when GDB 7.2 is released
// START OF WORKAROUND
if (groups.length == 0 && fBackend.getSessionType() == SessionType.CORE) {
String groupId = MIProcesses.UNIQUE_GROUP_ID;
IProcessDMContext processDmc = createProcessContext(controlDmc, groupId);
return new IMIContainerDMContext[] {createContainerContext(processDmc, groupId)};
}
// END OF WORKAROUND to be removed when GDB 7.2 is available
IMIContainerDMContext[] containerDmcs = new IMIContainerDMContext[groups.length];
for (int i = 0; i < groups.length; i++) {
String groupId = groups[i].getGroupId();

View file

@ -31,6 +31,7 @@ import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
@ -80,6 +81,14 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
private boolean fReverseSupported = true;
private boolean fReverseStepping = false;
private boolean fReverseModeEnabled = false;
/**
* This variable allows us to know if run control operation
* should be enabled or disabled. Run control operations are
* always enabled except when dealing with post-mortem debug
* session, or when visualizing tracepoints.
*/
private boolean fRunControlOperationsEnabled = true;
private RunToLineActiveOperation fRunToLineActiveOperation = null;
@ -105,6 +114,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
if (fGdb.getSessionType() == SessionType.CORE) {
// No execution for core files, so no support for reverse
fRunControlOperationsEnabled = false;
fReverseSupported = false;
}
@ -176,7 +186,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
*/
@Override
public void canResume(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
if (fGdb.getSessionType() == SessionType.CORE) {
if (fRunControlOperationsEnabled == false) {
rm.setData(false);
rm.done();
return;
@ -189,7 +199,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
*/
@Override
public void canSuspend(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
if (fGdb.getSessionType() == SessionType.CORE) {
if (fRunControlOperationsEnabled == false) {
rm.setData(false);
rm.done();
return;
@ -202,7 +212,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
*/
@Override
public void canStep(final IExecutionDMContext context, StepType stepType, final DataRequestMonitor<Boolean> rm) {
if (fGdb.getSessionType() == SessionType.CORE) {
if (fRunControlOperationsEnabled == false) {
rm.setData(false);
rm.done();
return;
@ -591,6 +601,16 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
super.eventDispatched(e);
}
/**
* @since 3.0
*/
@DsfServiceEventHandler
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
// We have started looking at trace records. We can no longer
// do run control operations.
fRunControlOperationsEnabled = false;
}
/** @since 2.0 */
public void setReverseModeEnabled(boolean enabled) {

View file

@ -43,6 +43,7 @@ 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.ICommandControlShutdownDMEvent;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.internal.service.command.events.MITracepointSelectedEvent;
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
@ -141,6 +142,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
public StateChangeReason getReason() {
if (getMIEvent() instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
return StateChangeReason.EVENT_BREAKPOINT;
} else if (getMIEvent() instanceof MITracepointSelectedEvent) { // must precede MIBreakpointHitEvent
return StateChangeReason.UNKNOWN; // Don't display anything here, the details will take care of it
} else if (getMIEvent() instanceof MIBreakpointHitEvent) {
return StateChangeReason.BREAKPOINT;
} else if (getMIEvent() instanceof MISteppingRangeEvent) {
@ -162,6 +165,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
MIStoppedEvent event = getMIEvent();
if (event instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
return ((MICatchpointHitEvent)event).getReason();
} else if (event instanceof MITracepointSelectedEvent) { // must precede MIBreakpointHitEvent
return ((MITracepointSelectedEvent)event).getReason();
} else if (event instanceof MISharedLibEvent) {
return ((MISharedLibEvent)event).getLibrary();
} else if (event instanceof MISignalEvent) {

View file

@ -13,20 +13,31 @@ package org.eclipse.cdt.dsf.gdb.service;
import java.util.Hashtable;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Immutable;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.ICachingService;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
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.ICommandControlDMContext;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.internal.service.command.events.MITracepointSelectedEvent;
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.events.MIEvent;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIResultRecord;
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceFindInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceListVariablesInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceListVariablesInfo.MITraceVariableInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStatusInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStopInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceListVariablesInfo.MITraceVariableInfo;
import org.eclipse.cdt.dsf.service.AbstractDsfService;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.IStatus;
@ -35,119 +46,104 @@ import org.eclipse.debug.core.ILaunchConfiguration;
import org.osgi.framework.BundleContext;
/**
* This class implements the ITraceControl interface which gives access
* This class implements the IGDBTraceControl interface which gives access
* to the debugger's tracing functionality.
*
* @since 3.0
*/
public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTraceControl, ICachingService {
public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTraceControl, ICachingService {
// @Immutable
// private static final class MITraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
//
// // The trace record reference
// private final int fReference;
//
// /**
// * @param session the DsfSession for this service
// * @param parents the parent contexts
// * @param reference the trace record reference
// */
// public MITraceRecordDMContext(DsfSession session, IDMContext[] parents, int reference) {
// super(session.getId(), parents);
// fReference = reference;
// }
//
// public int getReference() {
// return fReference;
// }
//
// /* (non-Javadoc)
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
// */
// @Override
// public boolean equals(Object obj) {
// return baseEquals(obj) && (fReference == ((MITraceRecordDMContext) obj).fReference);
// }
//
// /* (non-Javadoc)
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
// */
// @Override
// public int hashCode() {
// return baseHashCode() + fReference;
// }
//
// /* (non-Javadoc)
// * @see java.lang.Object#toString()
// */
// @Override
// public String toString() {
// return baseToString() + ".reference(" + fReference + ")"; //$NON-NLS-1$//$NON-NLS-2$
// }
// }
//
// /**
// * Trace record context used to indicate that there is no current trace record selected.
// */
// @Immutable
// private static final class InvalidTraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
//
// /**
// * @param session the DsfSession for this service
// * @param parents the parent contexts
// * @param reference the trace record reference
// */
// public InvalidTraceRecordDMContext(DsfSession session, IDMContext[] parents) {
// super(session.getId(), parents);
// }
//
//
// /* (non-Javadoc)
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
// */
// @Override
// public boolean equals(Object obj) {
// return baseEquals(obj);
// }
//
// /* (non-Javadoc)
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
// */
// @Override
// public int hashCode() {
// return baseHashCode();
// }
//
// /* (non-Javadoc)
// * @see java.lang.Object#toString()
// */
// @Override
// public String toString() {
// return baseToString() + ".noTraceRecord"; //$NON-NLS-1$
// }
// }
//
// @Immutable
// private static class MITraceRecordDMData implements ITraceRecordDMData {
// private final String fData;
//
// public MITraceRecordDMData(String data) {
// fData = data;
// }
//
// public String getData() { return fData; }
// }
@Immutable
protected static final class MITraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
// The trace record reference
private final int fReference;
/**
* @param session the DsfSession for this service
* @param parents the parent contexts
* @param reference the trace record reference
*/
public MITraceRecordDMContext(DsfSession session, ITraceTargetDMContext parent, int reference) {
super(session.getId(), new IDMContext[] { parent });
fReference = reference;
}
public int getReference() {
return fReference;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
return baseEquals(obj) && (fReference == ((MITraceRecordDMContext) obj).fReference);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
*/
@Override
public int hashCode() {
return baseHashCode() + fReference;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return baseToString() + ".reference(" + fReference + ")"; //$NON-NLS-1$//$NON-NLS-2$
}
}
/**
* Trace record context used to indicate that there is no current trace record selected.
*/
@Immutable
protected static final class InvalidTraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
/**
* @param session the DsfSession for this service
* @param parents the parent contexts
* @param reference the trace record reference
*/
public InvalidTraceRecordDMContext(DsfSession session, ITraceTargetDMContext parent) {
super(session.getId(), new IDMContext[] { parent });
}
/* (non-Javadoc)
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
return baseEquals(obj);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
*/
@Override
public int hashCode() {
return baseHashCode();
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return baseToString() + ".noTraceRecord"; //$NON-NLS-1$
}
}
private class TraceVariableDMData implements ITraceVariableDMData {
private String fName;
private String fValue;
private String fInitialValue;
public TraceVariableDMData(String name, String value) {
this(name, value, null);
}
public TraceVariableDMData(String name, String initial, String value) {
fName = name;
fInitialValue = initial;
@ -245,6 +241,20 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
return "\nTracing is not supported\n";
}
if (fBackend.getSessionType() == SessionType.CORE) {
str += "Off-line trace visualization\n";
} else {
str += "Tracing with live execution\n";
}
if (fCurrentRecordDmc instanceof MITraceRecordDMContext) {
str += "Looking at trace frame " +
((MITraceRecordDMContext)fCurrentRecordDmc).getReference() +
", tracepoint " + fTracepointIndexForTraceRecord + "\n\n";
} else {
str += "Not currently looking at any trace frame\n\n";
}
str += "Tracing is currently" + (!fTracingActive ? " not":"") + " active\n";
str += "Buffer contains " + fNumberOfCollectedFrames + " trace frame" +
(fNumberOfCollectedFrames>1?"s":"") + "\n";//" (out of ? created in total)\n";
@ -270,7 +280,10 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
} else {
str += " unknow reason";
}
str += "\n";
}
return str;
}
@ -304,25 +317,27 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
}
}
// private static class TraceRecordSelectedChangedEvent extends AbstractDMEvent<ITraceRecordDMContext>
// implements ITraceRecordSelectedChangedDMEvent {
// public TraceRecordSelectedChangedEvent(ITraceRecordDMContext context) {
// super(context);
// }
// }
public static class TraceRecordSelectedChangedEvent extends AbstractDMEvent<ITraceRecordDMContext>
implements ITraceRecordSelectedChangedDMEvent {
public TraceRecordSelectedChangedEvent(ITraceRecordDMContext context) {
super(context);
}
}
private CommandCache fTraceCache;
private ICommandControlService fConnection;
private CommandFactory fCommandFactory;
// private ITraceRecordDMContext fCurrentRecordDmc = null;
private boolean fIsTracingActive = false;
private boolean fIsTracingSupported = false;
private int fTraceRecordsStored = 0;
private IGDBBackend fBackend;
private ITraceRecordDMContext fCurrentRecordDmc;
private int fTracepointIndexForTraceRecord;
public GDBTraceControl_7_1(DsfSession session, ILaunchConfiguration config) {
private boolean fIsTracingActive;
private boolean fIsTracingCurrentlySupported;
private boolean fIsTracingFeatureAvailable = true;
private int fTraceRecordsStored;
public GDBTraceControl_7_2(DsfSession session, ILaunchConfiguration config) {
super(session);
}
@ -351,10 +366,6 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
* initialization is done.
*/
private void doInitialize(RequestMonitor requestMonitor) {
// Register to receive service events for this session.
// getSession().addServiceEventListener(this, null);
// Register this service.
register(new String[] {IGDBTraceControl.class.getName()},
new Hashtable<String, String>());
@ -364,6 +375,7 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
fTraceCache = new CommandCache(getSession(), fConnection);
fTraceCache.setContextAvailable(fConnection.getContext(), true);
fBackend = getServicesTracker().getService(IGDBBackend.class);
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
requestMonitor.done();
@ -379,7 +391,6 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
@Override
public void shutdown(RequestMonitor requestMonitor) {
unregister();
// getSession().removeServiceEventListener(this);
super.shutdown(requestMonitor);
}
@ -397,8 +408,27 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
rm.done();
return;
}
if (fIsTracingCurrentlySupported == false) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
rm.done();
return;
}
if (fBackend.getSessionType() == SessionType.CORE) {
rm.setData(false);
rm.done();
return;
}
if (fCurrentRecordDmc != null) {
// We are visualizing data, no more tracing possible.
rm.setData(false);
rm.done();
return;
}
rm.setData(fIsTracingSupported);
rm.setData(true);
rm.done();
}
@ -438,6 +468,25 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
rm.done();
return;
}
if (fIsTracingCurrentlySupported == false) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
rm.done();
return;
}
if (fBackend.getSessionType() == SessionType.CORE) {
rm.setData(false);
rm.done();
return;
}
if (fCurrentRecordDmc != null) {
// We are visualizing data, no more tracing possible.
rm.setData(false);
rm.done();
return;
}
isTracing(context, rm);
}
@ -488,11 +537,17 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
return;
}
if (fBackend.getSessionType() == SessionType.CORE) {
rm.setData(false);
rm.done();
return;
}
// Although tracing can be automatically stopped on the target, we
// don't go to the backend for this call, or we would make too many calls
// Instead, we can use our buffered state; we simply won't know about an
// automatic stop until a forced refresh. (Note that the MI notification
// about automatic stops, is not available until GDB 7.1 is released)
// about automatic stops, is not available until GDB 7.2 is released)
rm.setData(fIsTracingActive);
rm.done();
}
@ -503,21 +558,45 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
rm.done();
return;
}
if (fIsTracingCurrentlySupported == false) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
rm.done();
return;
}
if (fBackend.getSessionType() == SessionType.CORE) {
rm.setData(false);
rm.done();
return;
}
rm.setData(fTraceRecordsStored > 0);
rm.done();
}
public void saveTraceData(ITraceTargetDMContext context, String file, boolean remoteSave, RequestMonitor rm) {
public void saveTraceData(final ITraceTargetDMContext context, final String file,
final boolean remoteSave, final RequestMonitor rm) {
if (context == null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$
rm.done();
return;
}
fConnection.queueCommand(
fCommandFactory.createMITraceSave(context, file, remoteSave),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
canSaveTraceData(context, new DataRequestMonitor<Boolean>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
if (!getData()) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Cannot save trace data", null)); //$NON-NLS-1$
rm.done();
return;
}
fConnection.queueCommand(
fCommandFactory.createMITraceSave(context, file, remoteSave),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
}
});
}
public void canLoadTraceData(ITraceTargetDMContext context, DataRequestMonitor<Boolean> rm) {
@ -527,20 +606,44 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
return;
}
// If this service has been instantiated, it means we support loading trace data.
// Unlike the other operations, loading trace data does not require any GDB special state
// (like being connected to a target)
rm.setData(true);
rm.done();
}
public void loadTraceData(ITraceTargetDMContext context, String file, RequestMonitor rm) {
public void loadTraceData(final ITraceTargetDMContext context, final String file, final RequestMonitor rm) {
if (context == null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$
rm.done();
return;
}
fConnection.queueCommand(
fCommandFactory.createMITargetSelectTFile(context, file),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
canLoadTraceData(context, new DataRequestMonitor<Boolean>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
if (!getData()) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Cannot load trace data", null)); //$NON-NLS-1$
rm.done();
return;
}
fConnection.queueCommand(
fCommandFactory.createMITargetSelectTFile(context, file),
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
fIsTracingCurrentlySupported = true;
// Workaround for GDB pre-release where we don't get the details
// of the frame when we load a trace file.
// To get around this, we can force a select of record 0
ITraceRecordDMContext initialRecord = createTraceRecordContext(context, 0);
selectTraceRecord(initialRecord, rm);
}
});
}
});
}
public void getTraceStatus(final ITraceTargetDMContext context, final DataRequestMonitor<ITraceStatusDMData> rm) {
@ -550,19 +653,31 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
return;
}
if (fIsTracingFeatureAvailable == false) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
rm.done();
return;
}
fConnection.queueCommand(
fCommandFactory.createMITraceStatus(context),
new DataRequestMonitor<MITraceStatusInfo>(getExecutor(), rm) {
@Override
protected void handleError() {
// The MI command
fIsTracingFeatureAvailable = false;
super.handleError();
}
@Override
protected void handleSuccess() {
MITraceStatusInfo info = getData();
if (fIsTracingSupported != info.isTracingSupported()) {
fIsTracingSupported = info.isTracingSupported();
getSession().dispatchEvent(new TracingSupportedChangeEvent(context, fIsTracingSupported), getProperties());
if (fIsTracingCurrentlySupported != info.isTracingSupported()) {
fIsTracingCurrentlySupported = info.isTracingSupported();
getSession().dispatchEvent(new TracingSupportedChangeEvent(context, fIsTracingCurrentlySupported), getProperties());
}
if (fIsTracingSupported) {
if (fIsTracingCurrentlySupported) {
// Update the tracing state in case it was stopped by the backend
if (fIsTracingActive != info.isTracingActive()) {
fIsTracingActive = info.isTracingActive();
@ -609,6 +724,12 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
return;
}
if (fIsTracingCurrentlySupported == false) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
rm.done();
return;
}
if (varValue == null) {
fConnection.queueCommand(
fCommandFactory.createMITraceDefineVariable(context, varName),
@ -628,6 +749,12 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
return;
}
if (fIsTracingCurrentlySupported == false) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
rm.done();
return;
}
// It may be possible to cache this call, if we can figure out that all the cases
// where to data can change, to clear the cache in those cases
fConnection.queueCommand(
@ -648,125 +775,173 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
}
});
}
//
// /**
// * Create a trace record context
// */
// public ITraceRecordDMContext createTraceRecordContext(IDMContext ctx, int index) {
// return new MITraceRecordDMContext(getSession(), new IDMContext[] { ctx }, index);
// }
//
// public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx) {
// if (ctx instanceof InvalidTraceRecordDMContext) {
// // No specified context, so we return the first record context
// return new MITraceRecordDMContext(getSession(), new IDMContext[] { ctx }, 0);
// }
// if (ctx instanceof MITraceRecordDMContext) {
// return new MITraceRecordDMContext(getSession(),
// ctx.getParents(),
// ((MITraceRecordDMContext)ctx).getReference() + 1);
// }
// return null;
// }
//
// public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx) {
// if (ctx instanceof MITraceRecordDMContext) {
// return new MITraceRecordDMContext(getSession(),
// ctx.getParents(),
// ((MITraceRecordDMContext)ctx).getReference() - 1);
// }
// return null;
// }
//
//
// public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm) {
// if (fCurrentRecordDmc == null) {
// drm.setData(new InvalidTraceRecordDMContext(getSession(), new IDMContext[] { context }));
// } else {
// drm.setData(fCurrentRecordDmc);
// }
// drm.done();
// }
//
// public void selectTraceRecord(final ITraceRecordDMContext context, final RequestMonitor rm) {
// if (context instanceof MITraceRecordDMContext) {
// ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(context, ITraceTargetDMContext.class);
// fConnection.queueCommand(
// new MITraceFind(targetDmc, ((MITraceRecordDMContext)context).getReference()),
// new DataRequestMonitor<MITraceFindInfo>(getExecutor(), rm) {
// @Override
// protected void handleSuccess() {
// if (getData().isFound() == false) {
// rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Could not find trace record", null)); //$NON-NLS-1$
// } else {
// fCurrentRecordDmc = context;
// getSession().dispatchEvent(new TraceRecordSelectedChangedEvent(context), getProperties());
// }
// rm.done();
// }
// });
// } else {
// rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid trace record context.", null)); //$NON-NLS-1$
// rm.done();
// }
// }
//
// public void setDefaultCollect(ITraceTargetDMContext context, String[] expressions, RequestMonitor rm) {
// fConnection.queueCommand(
// new MIGDBSetDefaultCollect(context, expressions),
// new DataRequestMonitor<MIInfo>(getExecutor(), rm));
// }
//
// public void getDefaultCollect(ITraceTargetDMContext context, final DataRequestMonitor<String> rm) {
// // should use a cache and have it reset in setDefaultCommands
// fConnection.queueCommand(
// new MIGDBShowDefaultCollect(context),
// new DataRequestMonitor<MIGDBShowInfo>(getExecutor(), rm) {
// @Override
// protected void handleSuccess() {
// rm.setData(getData().getValue());
// rm.done();
// }
// });
// }
//
//
// public void getTraceRecordData(ITraceRecordDMContext context,
// DataRequestMonitor<ITraceRecordDMData> rm) {
// assert false;
// }
//
// public void saveTracepoints(ITraceTargetDMContext context,
// String file,
// RequestMonitor rm) {
// assert false;
// }
//
// public void loadTracepoints(ITraceTargetDMContext context,
// String file,
// RequestMonitor rm) {
// assert false;
// }
//
// public void saveTraceData(ITraceTargetDMContext context,
// String file,
// RequestMonitor rm) {
// assert false;
// }
//
// public void loadTraceData(ITraceTargetDMContext context,
// String file,
// RequestMonitor rm) {
// assert false;
// }
//
// public void createTraceVariable(IExecutionDMContext context,
// RequestMonitor rm) {
// assert false;
// }
/**
* Create a trace record context
*/
public ITraceRecordDMContext createTraceRecordContext(ITraceTargetDMContext ctx, int index) {
return new MITraceRecordDMContext(getSession(), ctx, index);
}
public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx) {
ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(ctx, ITraceTargetDMContext.class);
if (ctx instanceof InvalidTraceRecordDMContext) {
// No specified context, so we return the context for the first
return new MITraceRecordDMContext(getSession(), targetDmc, 0);
}
if (ctx instanceof MITraceRecordDMContext) {
int recordIndex = ((MITraceRecordDMContext)ctx).getReference();
recordIndex++;
if (recordIndex == fTraceRecordsStored) {
// Loop back to the front
recordIndex = 0;
}
return new MITraceRecordDMContext(getSession(),
targetDmc,
recordIndex);
}
return null;
}
public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx) {
if (ctx instanceof MITraceRecordDMContext) {
ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(ctx, ITraceTargetDMContext.class);
int recordIndex = ((MITraceRecordDMContext)ctx).getReference();
if (recordIndex == 0) {
// Loop back to the end
recordIndex = fTraceRecordsStored; // The last index of a trace record (zero-based)
}
recordIndex--;
return new MITraceRecordDMContext(getSession(),
targetDmc,
recordIndex);
}
return null;
}
public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm) {
if (fCurrentRecordDmc == null) {
drm.setData(new InvalidTraceRecordDMContext(getSession(), context));
} else {
drm.setData(fCurrentRecordDmc);
}
drm.done();
}
public void selectTraceRecord(final ITraceRecordDMContext context, final RequestMonitor rm) {
if (fIsTracingCurrentlySupported == false) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
rm.done();
return;
}
if (context instanceof MITraceRecordDMContext) {
ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(context, ITraceTargetDMContext.class);
fConnection.queueCommand(
fCommandFactory.createMITraceFind(targetDmc, ((MITraceRecordDMContext)context).getReference()),
new DataRequestMonitor<MITraceFindInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
if (getData().isFound() == false) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Could not find trace record", null)); //$NON-NLS-1$
rm.done();
return;
}
fCurrentRecordDmc = context;
fTracepointIndexForTraceRecord = getData().getTraceRecord().getTracepointId();
// This event will indicate to the other services that we are visualizing trace data.
getSession().dispatchEvent(new TraceRecordSelectedChangedEvent(context), getProperties());
// We could rely on the TraceRecordSelectedChangedEvent to update all the views, but this
// would require a lot of changes.
// Notice that looking at a new trace record should behave in the same manner
// as when the debugger suspends during normal execution; therefore we can simply
// trigger an MIStoppedEvent, as if reported by GDB. Note that we do this already for
// cases where GDB is missing such a event (like older versions of GDB when using a CLI command)
IMIProcesses procService = getServicesTracker().getService(IMIProcesses.class);
if (procService == null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
rm.done();
return;
}
final MIResultRecord rr = getData().getMIOutput().getMIResultRecord();
if (rr == null) {
assert false;
rm.done();
return;
}
// First find the process we are using.
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(context, ICommandControlDMContext.class);
procService.getProcessesBeingDebugged(
controlDmc,
new DataRequestMonitor<IDMContext[]>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
assert getData() != null;
assert getData().length == 1;
if (getData() == null || getData().length < 1) {
rm.done();
return;
}
// Choose the first process for now, until gdb can tell
// us which process the trace record is associated with.
// Or maybe GDB already tells us by only reporting a single
// process?
IContainerDMContext processContainerDmc = (IContainerDMContext)(getData()[0]);
// Now find the proper thread. We must do this hear because in post-mortem debugging
// we cannot rely on MIRunControl using 'thread', as it will fail
IMIProcesses procService = getServicesTracker().getService(IMIProcesses.class);
if (procService == null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
rm.done();
return;
}
procService.getProcessesBeingDebugged(
processContainerDmc,
new DataRequestMonitor<IDMContext[]>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
assert getData() != null;
assert getData().length == 1;
if (getData() == null || getData().length < 1) {
rm.done();
return;
}
IExecutionDMContext execDmc = (IExecutionDMContext)getData()[0];
MIEvent<?> event = MITracepointSelectedEvent.parse(execDmc, rr.getToken(), rr.getMIResults());
getSession().dispatchEvent(event, getProperties());
rm.done();
}
});
}
});
}
});
} else {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid trace record context.", null)); //$NON-NLS-1$
rm.done();
}
}
public void getTraceRecordData(ITraceRecordDMContext context, DataRequestMonitor<ITraceRecordDMData> rm) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$
rm.done();
}
public void flushCache(IDMContext context) {
fTraceCache.reset(context);
}
}

View file

@ -43,7 +43,8 @@ import org.eclipse.debug.core.ILaunchConfiguration;
public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
// This should eventually be "7.0" once GDB 7.0 is released
private static final String GDB_7_0_VERSION = "6.8.50.20090218"; //$NON-NLS-1$
private static final String GDB_7_0_VERSION = "6.8.50.20090218"; //$NON-NLS-1$
private static final String GDB_7_2_VERSION = "7.1.50"; //$NON-NLS-1$
private final String fVersion;
@ -163,12 +164,15 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
/** @since 3.0 */
protected IGDBTraceControl createTraceControlService(DsfSession session, ILaunchConfiguration config) {
// This service is available for GDB 7.1. But until that GDB is itself available
// This service is available for GDB 7.2. But until that GDB is itself available
// there is a pre-release that has a version of 6.8.50.20090414
if ("6.8.50.20090414".compareTo(fVersion) <= 0) {
return new GDBTraceControl_7_1(session, config);
if (GDB_7_2_VERSION.compareTo(fVersion) <= 0 || "6.8.50.20090414".equals(fVersion)) { //$NON-NLS-1$
return new GDBTraceControl_7_2(session, config);
}
// There is no implementation of the TraceControl service before GDB 7.1
// There is currently no implementation of the TraceControl service before GDB 7.2
// It could be done with restricted functionality for GDB 7.1 and maybe even 7.0
// but the service would have to be properly coded, as some MI commands don't exists
// in those older GDB versions. Also, gdbserver only supports tracing starting with 7.2
return null;
}
}

View file

@ -22,6 +22,9 @@ import org.eclipse.cdt.dsf.service.IDsfService;
* The TraceControl service provides access to the debugger Tracing functionality.
* It is used to do such things as start and stop tracing.
*
* As this functionality is very new to GDB itself, this interface is likely
* to change a little in the next release of CDT.
*
* @since 3.0
*/
public interface IGDBTraceControl extends IDsfService {
@ -98,41 +101,17 @@ public interface IGDBTraceControl extends IDsfService {
* {@link saveTraceData} should have the correct format to be loaded by this call.
*/
public void loadTraceData(ITraceTargetDMContext context,
String file,
RequestMonitor rm);
String file,
RequestMonitor rm);
// /**
// * Request that the backend use the specified trace record.
// */
// public void selectTraceRecord(ITraceRecordDMContext context, RequestMonitor rm);
// /**
// * Returns the trace record data of the specified trace record.
// */
// public void getTraceRecordData(ITraceRecordDMContext context,
// DataRequestMonitor<ITraceRecordDMData> rm);
//
// /**
// * Save all tracepoint definitions to the specified file in a
// * format suitable for {@link loadTracepoints}.
// */
// // This should probably be part of the GDB Breakpoints service
// public void saveTracepoints(ITraceTargetDMContext context,
// String file,
// RequestMonitor rm);
//
// /**
// * Load all tracepoint definitions from the specified file.
// * A file created from a call to {@link saveTracepoints} should have
// * the correct format to be loaded by this call.
// */
// // This should probably be part of the GDB Breakpoints service
// public void loadTracepoints(ITraceTargetDMContext context,
// String file,
// RequestMonitor rm);
//
/**
* Request that the backend use the specified trace record.
*/
public void selectTraceRecord(ITraceRecordDMContext context, RequestMonitor rm);
public void getTraceRecordData(ITraceRecordDMContext context, DataRequestMonitor<ITraceRecordDMData> rm);
/////////////////////////////////////////////////
// GDB specific part
/////////////////////////////////////////////////
@ -179,12 +158,8 @@ public interface IGDBTraceControl extends IDsfService {
*/
public void getTraceVariables(ITraceTargetDMContext context, DataRequestMonitor<ITraceVariableDMData[]> rm);
// public ITraceRecordDMContext createTraceRecordContext(IDMContext ctx, int index);
// public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm);
// public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx);
// public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx);
//
// public void setDefaultCollect(ITraceTargetDMContext context, String[] expressions, RequestMonitor rm);
// public void getDefaultCollect(ITraceTargetDMContext context, DataRequestMonitor<String> rm);
public ITraceRecordDMContext createTraceRecordContext(ITraceTargetDMContext ctx, int index);
public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm);
public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx);
public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx);
}

View file

@ -40,6 +40,7 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
import org.eclipse.cdt.dsf.gdb.service.GDBRunControl_7_0;
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
import org.eclipse.cdt.dsf.gdb.service.IReverseRunControl;
import org.eclipse.cdt.dsf.gdb.service.SessionType;
import org.eclipse.cdt.dsf.gdb.service.GDBProcesses_7_0.ContainerExitedDMEvent;
@ -606,7 +607,18 @@ public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
}
}
}
/** @since 3.0 */
@DsfServiceEventHandler
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
// Once we start looking at trace frames, we should not use
// the --thread or --frame options because GDB does not handle
// it well, there are no actual threads running.
// We only need to do this once, but it won't hurt to do it
// every time.
setUseThreadAndFrameOptions(false);
}
public static class InitializationShutdownStep extends Sequence.Step {
public enum Direction { INITIALIZING, SHUTTING_DOWN }

View file

@ -35,6 +35,7 @@ import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetAttributes;
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetChildCount;
@ -436,6 +437,12 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I
private MIVariableManager varManager;
private CommandFactory fCommandFactory;
/**
* Indicates that we are currently visualizing trace data.
* In this case, some errors should not be reported.
*/
private boolean fTraceVisualization;
public MIExpressions(DsfSession session) {
super(session);
}
@ -754,6 +761,15 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I
rm.setData(new FormattedValueDMData(getData().getValue()));
rm.done();
}
@Override
protected void handleError() {
if (fTraceVisualization) {
rm.setData(new FormattedValueDMData("")); //$NON-NLS-1$
rm.done();
} else {
super.handleError();
}
}
});
} else {
fExpressionCache.execute(
@ -1004,6 +1020,14 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I
// MIVariableManager separately traps this event
}
/** @since 3.0 */
@DsfServiceEventHandler
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
// Once we start looking at a trace record, we remain in
// trace visualization mode.
fTraceVisualization = true;
}
/**
* {@inheritDoc}
* @since 1.1

View file

@ -40,6 +40,7 @@ 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.ICommandControlShutdownDMEvent;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.internal.service.command.events.MITracepointSelectedEvent;
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.MIBreakpointDMContext;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
@ -177,6 +178,8 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
public StateChangeReason getReason() {
if (getMIEvent() instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
return StateChangeReason.EVENT_BREAKPOINT;
} else if (getMIEvent() instanceof MITracepointSelectedEvent) { // must precede MIBreakpointHitEvent
return StateChangeReason.UNKNOWN; // Don't display anything here, the details will take care of it
} else if (getMIEvent() instanceof MIBreakpointHitEvent) {
return StateChangeReason.BREAKPOINT;
} else if (getMIEvent() instanceof MISteppingRangeEvent) {
@ -201,6 +204,8 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
MIStoppedEvent event = getMIEvent();
if (event instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
return ((MICatchpointHitEvent)event).getReason();
} else if (event instanceof MITracepointSelectedEvent) { // must precede MIBreakpointHitEvent
return ((MITracepointSelectedEvent)event).getReason();
} else if (event instanceof MISharedLibEvent) {
return ((MISharedLibEvent)event).getLibrary();
} else if (event instanceof MISignalEvent) {

View file

@ -26,16 +26,17 @@ import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.ICachingService;
import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
@ -61,7 +62,6 @@ public class MIStack extends AbstractDsfService
implements IFrameDMContext
{
private final int fLevel;
// public MIFrameDMC(MIStack service, int level) {
public MIFrameDMC(String sessionId, IExecutionDMContext execDmc, int level) {
super(sessionId, new IDMContext[] { execDmc });
fLevel = level;
@ -166,6 +166,12 @@ public class MIStack extends AbstractDsfService
private MIStoppedEvent fCachedStoppedEvent;
private IRunControl fRunControl;
/**
* Indicates that we are currently visualizing trace data.
* In this case, some errors should not be reported.
*/
private boolean fTraceVisualization;
public MIStack(DsfSession session)
{
super(session);
@ -250,20 +256,19 @@ public class MIStack extends AbstractDsfService
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
if (execDmc == null) {
//rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "No frame context found in " + ctx, null)); //$NON-NLS-1$
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context " + ctx, null)); //$NON-NLS-1$
rm.done();
return;
}
// Make sure the thread is stopped
if (!fRunControl.isSuspended(execDmc)) {
// Make sure the thread is stopped but only if we are not visualizing trace data
if (!fTraceVisualization && !fRunControl.isSuspended(execDmc)) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context is running: " + ctx, null)); //$NON-NLS-1$
rm.done();
return;
}
if (startIndex == 0 && endIndex == 0) {
if (fTraceVisualization || (startIndex == 0 && endIndex == 0)) {
// Try to retrieve the top stack frame from the cached stopped event.
if (fCachedStoppedEvent != null &&
fCachedStoppedEvent.getFrame() != null &&
@ -329,7 +334,6 @@ public class MIStack extends AbstractDsfService
});
}
//private MIFrameDMC[] getFrames(DsfMIStackListFramesInfo info) {
private IFrameDMContext[] getFrames(IMIExecutionDMContext execDmc, MIStackListFramesInfo info, int firstIndex, int lastIndex, int startIndex) {
int length = info.getMIFrames().length;
if (lastIndex > 0) {
@ -408,15 +412,15 @@ public class MIStack extends AbstractDsfService
// Retrieve the top stack frame from the stopped event only if the selected thread is the one on which stopped event
// is raised
if (fCachedStoppedEvent != null &&
execDmc.equals(fCachedStoppedEvent.getDMContext()) &&
miFrameDmc.fLevel == 0 &&
fCachedStoppedEvent.getFrame() != null)
{
rm.setData(new FrameDataFromStoppedEvent(fCachedStoppedEvent));
rm.done();
return;
}
if (fTraceVisualization || miFrameDmc.fLevel == 0) {
if (fCachedStoppedEvent != null && fCachedStoppedEvent.getFrame() != null &&
(execDmc.equals(fCachedStoppedEvent.getDMContext()) || fTraceVisualization))
{
rm.setData(new FrameDataFromStoppedEvent(fCachedStoppedEvent));
rm.done();
return;
}
}
// If not, retrieve the full list of frame data.
class FrameDataFromMIStackFrameListInfo extends FrameData {
@ -475,13 +479,24 @@ public class MIStack extends AbstractDsfService
return;
}
// If not, retrieve the full list of frame data.
if (fTraceVisualization) {
// For the pre-release of GDB that supports tracepoints, we cannot ask
// for the list of arguments for all stack frames, but only for available
// ones. Again, I'm hoping that GDB 7.2 will be smarter than that.
getArgumentsForTraceVisualization(frameDmc, rm);
return;
}
// If not, retrieve the full list of frame data. Although we only need one frame
// for this call, it will be stored the cache and made available for other calls.
fMICommandCache.execute(
// We don't actually need to ask for the values in this case, but since
// we will ask for them right after, it is more efficient to ask for them now
// so as to cache the result. If the command fails, then we will ask for
// the result without the values
fCommandFactory.createMIStackListArguments(execDmc, true),
// Don't ask for value when we are visualizing trace data, since some
// data will not be there, and the command will fail
fCommandFactory.createMIStackListArguments(execDmc, true),
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
@ -504,8 +519,8 @@ public class MIStack extends AbstractDsfService
@Override
protected void handleError() {
// If the command fails it can be because we asked for values.
// This can happen with uninitialized values and pretty printers (bug 307614)
// or when visualizing tracepoints. Since asking for values was simply an optimization
// This can happen with uninitialized values and pretty printers (bug 307614).
// Since asking for values was simply an optimization
// to store the command in the cache, let's retry the command without asking for values.
fMICommandCache.execute(
fCommandFactory.createMIStackListArguments(execDmc, false),
@ -533,6 +548,43 @@ public class MIStack extends AbstractDsfService
});
}
// For the pre-release of GDB that supports tracepoints, we cannot ask
// for the list of arguments for all stack frames, but only for available
// ones. Again, I'm hoping that GDB 7.2 will be smarter than that.
private void getArgumentsForTraceVisualization(final IFrameDMContext frameDmc, final DataRequestMonitor<IVariableDMContext[]> rm) {
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class);
getStackDepth(execDmc, 0, new DataRequestMonitor<Integer>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
int bottomFrame = getData() - 1;
fMICommandCache.execute(
// Don't ask for values for tracepoints
fCommandFactory.createMIStackListArguments(execDmc, false, 0, bottomFrame),
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// Find the index to the correct MI frame object.
// Note: this is a short-cut, but it won't work once we implement retrieving
// partial lists of stack frames.
int idx = frameDmc.getLevel();
if (idx == -1 || idx >= getData().getMIFrames().length) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid frame " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
// Create the variable array out of MIArg array.
MIArg[] args = getData().getMIFrames()[idx].getArgs();
if (args == null) args = new MIArg[0];
rm.setData(makeVariableDMCs(frameDmc, MIVariableDMC.Type.ARGUMENT, args.length));
rm.done();
}
});
}
});
}
public void getVariableData(IVariableDMContext variableDmc, final DataRequestMonitor<IVariableDMData> rm) {
if (!(variableDmc instanceof MIVariableDMC)) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context type " + variableDmc, null)); //$NON-NLS-1$
@ -589,8 +641,13 @@ public class MIStack extends AbstractDsfService
}
if (miVariableDmc.fType == MIVariableDMC.Type.ARGUMENT){
if (fTraceVisualization) {
getArgumentsDataForTraceVisualization(miVariableDmc, rm);
} else {
fMICommandCache.execute(
fCommandFactory.createMIStackListArguments(execDmc, true),
// Don't ask for value when we are visualizing trace data, since some
// data will not be there, and the command will fail
fCommandFactory.createMIStackListArguments(execDmc, true),
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
@ -610,8 +667,7 @@ public class MIStack extends AbstractDsfService
@Override
protected void handleError() {
// Unable to get the values. This can happen with uninitialized values and pretty printers (bug 307614)
// or when visualizing tracepoints. Either way, we try to ask for the arguments without their values,
// which is better than nothing
// Let's try to ask for the arguments without their values, which is better than nothing
fMICommandCache.execute(
fCommandFactory.createMIStackListArguments(execDmc, false),
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
@ -633,10 +689,13 @@ public class MIStack extends AbstractDsfService
});
}
});
}
}//if
if (miVariableDmc.fType == MIVariableDMC.Type.LOCAL){
fMICommandCache.execute(
fCommandFactory.createMIStackListLocals(frameDmc, true),
// Don't ask for value when we are visualizing trace data, since some
// data will not be there, and the command will fail
fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization),
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
@ -652,9 +711,8 @@ public class MIStack extends AbstractDsfService
}
@Override
protected void handleError() {
// Unable to get the value. This can happen with uninitialized values and pretty printers (bug 307614)
// or when visualizing tracepoints. Either way, we try to ask for the variables without their values,
// which is better than nothing
// Unable to get the value. This can happen with uninitialized values and pretty printers (bug 307614).
// Let's try to ask for the variables without their values, which is better than nothing
fMICommandCache.execute(
fCommandFactory.createMIStackListLocals(frameDmc, false),
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) {
@ -677,6 +735,52 @@ public class MIStack extends AbstractDsfService
}
// For the pre-release of GDB that supports tracepoints, we cannot ask
// for the list of arguments for all stack frames, but only for available
// ones. Again, I'm hoping that GDB 7.2 will be smarter than that.
private void getArgumentsDataForTraceVisualization(final MIVariableDMC miVariableDmc, final DataRequestMonitor<IVariableDMData> rm) {
final MIFrameDMC frameDmc = DMContexts.getAncestorOfType(miVariableDmc, MIFrameDMC.class);
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class);
class VariableData implements IVariableDMData {
private MIArg dsfMIArg;
VariableData(MIArg arg){
dsfMIArg = arg;
}
public String getName() { return dsfMIArg.getName(); }
public String getValue() { return dsfMIArg.getValue(); }
@Override
public String toString() { return dsfMIArg.toString(); }
}
getStackDepth(execDmc, 0, new DataRequestMonitor<Integer>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
int bottomFrame = getData() - 1;
fMICommandCache.execute(
// Don't ask for values for tracepoints
fCommandFactory.createMIStackListArguments(execDmc, false, 0, bottomFrame),
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// Find the correct frame and argument
if ( frameDmc.fLevel >= getData().getMIFrames().length ||
miVariableDmc.fIndex >= getData().getMIFrames()[frameDmc.fLevel].getArgs().length )
{
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
// Create the data object.
rm.setData(new VariableData(getData().getMIFrames()[frameDmc.fLevel].getArgs()[miVariableDmc.fIndex]));
rm.done();
}
});
}
});
}
private MIVariableDMC[] makeVariableDMCs(IFrameDMContext frame, MIVariableDMC.Type type, int count) {
MIVariableDMC[] variables = new MIVariableDMC[count];
for (int i = 0; i < count; i++) {
@ -723,7 +827,9 @@ public class MIStack extends AbstractDsfService
// we will ask for them right after, it is more efficient to ask for them now
// so as to cache the result. If the command fails, then we will ask for
// the result without the values
fCommandFactory.createMIStackListLocals(frameDmc, true),
// Don't ask for value when we are visualizing trace data, since some
// data will not be there, and the command will fail
fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization),
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), countingRm) {
@Override
protected void handleSuccess() {
@ -734,8 +840,8 @@ public class MIStack extends AbstractDsfService
@Override
protected void handleError() {
// If the command fails it can be because we asked for values.
// This can happen with uninitialized values and pretty printers (bug 307614)
// or when visualizing tracepoints. Since asking for values was simply an optimization
// This can happen with uninitialized values and pretty printers (bug 307614).
// Since asking for values was simply an optimization
// to store the command in the cache, let's retry the command without asking for values.
fMICommandCache.execute(
fCommandFactory.createMIStackListLocals(frameDmc, false),
@ -755,7 +861,7 @@ public class MIStack extends AbstractDsfService
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class);
if (execDmc != null) {
// Make sure the thread is stopped
if (!fRunControl.isSuspended(execDmc)) {
if (!fTraceVisualization && !fRunControl.isSuspended(execDmc)) {
rm.setData(0);
rm.done();
return;
@ -787,6 +893,25 @@ public class MIStack extends AbstractDsfService
rm.setData(getData().getDepth());
rm.done();
}
@Override
protected void handleError() {
if (fTraceVisualization) {
// when visualizing trace data, the pre-release GDB, the command
// -stack-info-depth will return an error if we ask for any level
// that GDB does not know about. We would have to iteratively
// try different depths until we found the deepest that succeeds.
// That is too much of a hack for a pre-release. Let's hope
// GDB 7.2 will properly answer -stack-info-depth when visualizing
// trace data. Until then, we can safely say we have one stack
// frame, which is going to be the case for 95% of the cases.
// To have more stack frames, the user would have to have collected
// the registers and enough stack memory for GDB to build another frame.
rm.setData(1);
rm.done();
} else {
super.handleError();
}
}
});
} else {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
@ -833,6 +958,13 @@ public class MIStack extends AbstractDsfService
}
}
/** @since 3.0 */
@DsfServiceEventHandler
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
// Once we start looking at a trace record, we remain in
// trace visualization mode.
fTraceVisualization = true;
}
/**
* {@inheritDoc}
* @since 1.1

View file

@ -15,6 +15,7 @@ package org.eclipse.cdt.dsf.mi.service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
@ -26,25 +27,26 @@ import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.debug.service.IExpressions;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommandListener;
import org.eclipse.cdt.dsf.debug.service.command.ICommandResult;
import org.eclipse.cdt.dsf.debug.service.command.ICommandToken;
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.cdt.dsf.gdb.GDBTypeParser;
import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
import org.eclipse.cdt.dsf.mi.service.MIExpressions.ExpressionInfo;
import org.eclipse.cdt.dsf.mi.service.MIExpressions.MIExpressionDMC;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
@ -1505,7 +1507,7 @@ public class MIVariableManager implements ICommandControl {
// The variable object is out-of-scope and we
// should not use it.
if (shouldCreateNew) {
/**
/*
* It may happen that when accessing a varObject we find it to be
* out-of-scope. The expression for which we are trying to access a varObject
* could still be valid, and therefore we should try to create a new varObject for
@ -1850,4 +1852,22 @@ public class MIVariableManager implements ICommandControl {
// The views will fully refresh on a MemoryChangedEvent
markAllOutOfDate();
}
/**
* @since 3.0
*/
@DsfServiceEventHandler
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
// We have a big limitation with tracepoints!
// GDB usually only reports a depth of 1, for every trace record, no
// matter where it occurred. This means that our naming scheme for VariableObjectId
// fails miserably because all objects will have the same depth and we will confuse
// them. Until we find a good solution, we have to clear our entire list of
// of variable objects (and delete them in GDB to avoid having too many).
Iterator<Map.Entry<VariableObjectId, MIVariableObject>> iterator = lruVariableList.entrySet().iterator();
while (iterator.hasNext()){
iterator.next();
iterator.remove();
}
}
}

View file

@ -80,7 +80,7 @@ public abstract class AbstractMIControl extends AbstractDsfService
// MI did not always support the --thread/--frame options
// This boolean is used to know if we should use -thread-select and -stack-select-frame instead
private final boolean fUseThreadAndFrameOptions;
private boolean fUseThreadAndFrameOptions;
// currentStackLevel and currentThreadId are only necessary when
// we must use -thread-select and -stack-select-frame
private int fCurrentStackLevel = -1;
@ -157,6 +157,13 @@ public abstract class AbstractMIControl extends AbstractDsfService
return fTracingStream;
}
/**
* @since 3.0
*/
protected void setUseThreadAndFrameOptions(boolean shouldUse) {
fUseThreadAndFrameOptions = shouldUse;
}
/**
* @since 3.0
*/

View file

@ -105,6 +105,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIThreadInfo;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIThreadListIds;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIThreadSelect;
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceDefineVariable;
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceFind;
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceListVariables;
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceSave;
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceStart;
@ -145,6 +146,7 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIStackListFramesInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIStackListLocalsInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIThreadInfoInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIThreadListIdsInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceFindInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceListVariablesInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStatusInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStopInfo;
@ -660,6 +662,10 @@ public class CommandFactory {
public ICommand<MIInfo> createMITraceDefineVariable(ITraceTargetDMContext ctx, String varName, String varValue) {
return new MITraceDefineVariable(ctx, varName, varValue);
}
public ICommand<MITraceFindInfo> createMITraceFind(ITraceTargetDMContext ctx, int frameReference) {
return new MITraceFind(ctx, frameReference);
}
public ICommand<MITraceListVariablesInfo> createMITraceListVariables(ITraceTargetDMContext ctx) {
return new MITraceListVariables(ctx);

View file

@ -0,0 +1,62 @@
/*******************************************************************************
* 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.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceFindInfo;
/**
* -trace-find MODE [PARAMS...]
*
* Find a trace frame using criteria defined by MODE and PARAMS. The following
* lists permissible modes and their parameters.
*
* none - No parameters are required. Stops examining trace frames.
* frame-number - An integer is required as parameter. Selects tracepoint frame
* with that index.
* tracepoint-number - An integer is required as parameter. Finds next trace
* frame that corresponds to tracepoint with the specified number.
* pc - An integer address is required as parameter. Finds next trace
* frame that corresponds to any tracepoint at the specified address.
* pc-inside-range - Two integer addresses are required as parameters. Finds next
* trace frame that corresponds to a tracepoint at an address inside
* the specified range.
* pc-outside-range - Two integer addresses are required as parameters. Finds next
* trace frame that corresponds to a tracepoint at an address outside
* the specified range.
* line - Line specification is required as parameter.
* Finds next trace frame that corresponds to a tracepoint at the
* specified location.
*
* If the 'none' was passed as mode, the response does not have fields. Otherwise, the
* response may have the following fields:
*
* found - This field has either 0 or 1 as the value, depending on whether a matching
* tracepoint was found.
* traceframe - The index of the found traceframe. This field is present i f the 'found'
* field has value of 1.
* tracepoint - The index of the found tracepoint. This field is present if the 'found'
* field has value of 1.
* frame - The stack frame when the traceframe was collected
*
* @since 3.0
*/
public class MITraceFind extends MICommand<MITraceFindInfo> {
public MITraceFind(ITraceTargetDMContext ctx, int frameReference) {
super(ctx, "-trace-find", null, new String[] { "frame-number", Integer.toString(frameReference) }); //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public MITraceFindInfo getResult(MIOutput out) {
return new MITraceFindInfo(out);
}
}

View file

@ -0,0 +1,57 @@
/*******************************************************************************
* 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.output;
/**
* -trace-find result.
* @since 3.0
*/
public class MITraceFindInfo extends MIInfo {
private boolean fFound;
private MITraceRecord fTraceRecord;
public MITraceFindInfo(MIOutput out) {
super(out);
parse();
}
public boolean isFound() {
return fFound;
}
public MITraceRecord getTraceRecord() {
return fTraceRecord;
}
private void parse() {
if (isDone()) {
MIOutput out = getMIOutput();
MIResultRecord rr = out.getMIResultRecord();
if (rr != null) {
MIResult[] results = rr.getMIResults();
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
if (var.equals("found")) { //$NON-NLS-1$
MIValue val = results[i].getMIValue();
if (val instanceof MIConst) {
fFound = ((MIConst)val).getString().equals("0") ? false : true; //$NON-NLS-1$
if (fFound) {
fTraceRecord = new MITraceRecord(getMIOutput());
}
}
}
}
}
}
}
}

View file

@ -0,0 +1,73 @@
/*******************************************************************************
* 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.output;
/**
* -trace-find result.
* @since 3.0
*/
public class MITraceRecord extends MIInfo {
private MIFrame fStackFrame = null;
private Integer fTracepoint = null;
private Integer fRecordIndex = null;
public MITraceRecord(MIOutput out) {
super(out);
parse();
}
public MIFrame getStackFrame() {
return fStackFrame;
}
public Integer getTracepointId() {
return fTracepoint;
}
public Integer getRecordIndex() {
return fRecordIndex;
}
private void parse() {
if (isDone()) {
MIOutput out = getMIOutput();
MIResultRecord rr = out.getMIResultRecord();
if (rr != null) {
MIResult[] results = rr.getMIResults();
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
if (var.equals("traceframe")) { //$NON-NLS-1$
MIValue val = results[i].getMIValue();
if (val instanceof MIConst) {
try {
fRecordIndex = Integer.parseInt(((MIConst)val).getString());
} catch (NumberFormatException e) {}
}
} else if (var.equals("tracepoint")) { //$NON-NLS-1$
MIValue val = results[i].getMIValue();
if (val instanceof MIConst) {
try {
fTracepoint = Integer.parseInt(((MIConst)val).getString());
} catch (NumberFormatException e) {}
}
} else if (var.equals("frame")) { //$NON-NLS-1$
MIValue value = results[i].getMIValue();
if (value instanceof MITuple) {
fStackFrame = new MIFrame((MITuple)value);
}
}
}
}
}
}
}