mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
Bug 284286: Trace Record visualization for DSF-GDB
This commit is contained in:
parent
63207d9813
commit
c8835a2f95
34 changed files with 1807 additions and 359 deletions
|
@ -40,3 +40,9 @@ view.traceControl.name=Trace Control
|
||||||
toolbar.startTracing.name=Start Tracing
|
toolbar.startTracing.name=Start Tracing
|
||||||
toolbar.stopTracing.name=Stop Tracing
|
toolbar.stopTracing.name=Stop Tracing
|
||||||
toolbar.saveTracing.name=Save Trace Data
|
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
|
||||||
|
|
|
@ -353,6 +353,30 @@
|
||||||
</viewShortcut>
|
</viewShortcut>
|
||||||
</perspectiveExtension>
|
</perspectiveExtension>
|
||||||
</extension>
|
</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
|
<extension
|
||||||
point="org.eclipse.ui.menus">
|
point="org.eclipse.ui.menus">
|
||||||
<menuContribution
|
<menuContribution
|
||||||
|
@ -369,6 +393,18 @@
|
||||||
label="%toolbar.stopTracing.name"
|
label="%toolbar.stopTracing.name"
|
||||||
style="push">
|
style="push">
|
||||||
</command>
|
</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>
|
||||||
<menuContribution
|
<menuContribution
|
||||||
locationURI="menu:org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view?after=additions">
|
locationURI="menu:org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view?after=additions">
|
||||||
|
|
|
@ -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.actions.IRefreshAllTarget;
|
||||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.DefaultDsfModelSelectionPolicyFactory;
|
import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.DefaultDsfModelSelectionPolicyFactory;
|
||||||
import org.eclipse.cdt.dsf.gdb.actions.IConnect;
|
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.DsfTerminateCommand;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbConnectCommand;
|
import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbConnectCommand;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbDisconnectCommand;
|
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.GdbReverseStepOverCommand;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseToggleCommand;
|
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.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.GdbStartTracingCommand;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbStopTracingCommand;
|
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbStopTracingCommand;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbUncallCommand;
|
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbUncallCommand;
|
||||||
|
@ -119,6 +123,8 @@ public class GdbAdapterFactory
|
||||||
final GdbStartTracingCommand fStartTracingTarget;
|
final GdbStartTracingCommand fStartTracingTarget;
|
||||||
final GdbStopTracingCommand fStopTracingTarget;
|
final GdbStopTracingCommand fStopTracingTarget;
|
||||||
final GdbSaveTraceDataCommand fSaveTraceDataTarget;
|
final GdbSaveTraceDataCommand fSaveTraceDataTarget;
|
||||||
|
final GdbSelectNextTraceRecordCommand fSelectNextRecordTarget;
|
||||||
|
final GdbSelectPrevTraceRecordCommand fSelectPrevRecordTarget;
|
||||||
final GdbDebugTextHover fDebugTextHover;
|
final GdbDebugTextHover fDebugTextHover;
|
||||||
|
|
||||||
SessionAdapterSet(GdbLaunch launch) {
|
SessionAdapterSet(GdbLaunch launch) {
|
||||||
|
@ -161,6 +167,8 @@ public class GdbAdapterFactory
|
||||||
fStartTracingTarget = new GdbStartTracingCommand(session);
|
fStartTracingTarget = new GdbStartTracingCommand(session);
|
||||||
fStopTracingTarget = new GdbStopTracingCommand(session);
|
fStopTracingTarget = new GdbStopTracingCommand(session);
|
||||||
fSaveTraceDataTarget = new GdbSaveTraceDataCommand(session);
|
fSaveTraceDataTarget = new GdbSaveTraceDataCommand(session);
|
||||||
|
fSelectNextRecordTarget = new GdbSelectNextTraceRecordCommand(session);
|
||||||
|
fSelectPrevRecordTarget = new GdbSelectPrevTraceRecordCommand(session);
|
||||||
|
|
||||||
session.registerModelAdapter(ISteppingModeTarget.class, fSteppingModeTarget);
|
session.registerModelAdapter(ISteppingModeTarget.class, fSteppingModeTarget);
|
||||||
session.registerModelAdapter(IStepIntoHandler.class, fStepIntoCommand);
|
session.registerModelAdapter(IStepIntoHandler.class, fStepIntoCommand);
|
||||||
|
@ -183,6 +191,8 @@ public class GdbAdapterFactory
|
||||||
session.registerModelAdapter(IStartTracingHandler.class, fStartTracingTarget);
|
session.registerModelAdapter(IStartTracingHandler.class, fStartTracingTarget);
|
||||||
session.registerModelAdapter(IStopTracingHandler.class, fStopTracingTarget);
|
session.registerModelAdapter(IStopTracingHandler.class, fStopTracingTarget);
|
||||||
session.registerModelAdapter(ISaveTraceDataHandler.class, fSaveTraceDataTarget);
|
session.registerModelAdapter(ISaveTraceDataHandler.class, fSaveTraceDataTarget);
|
||||||
|
session.registerModelAdapter(ISelectNextTraceRecordHandler.class, fSelectNextRecordTarget);
|
||||||
|
session.registerModelAdapter(ISelectPrevTraceRecordHandler.class, fSelectPrevRecordTarget);
|
||||||
|
|
||||||
fDebugModelProvider = new IDebugModelProvider() {
|
fDebugModelProvider = new IDebugModelProvider() {
|
||||||
// @see org.eclipse.debug.core.model.IDebugModelProvider#getModelIdentifiers()
|
// @see org.eclipse.debug.core.model.IDebugModelProvider#getModelIdentifiers()
|
||||||
|
@ -238,7 +248,9 @@ public class GdbAdapterFactory
|
||||||
session.unregisterModelAdapter(IStartTracingHandler.class);
|
session.unregisterModelAdapter(IStartTracingHandler.class);
|
||||||
session.unregisterModelAdapter(IStopTracingHandler.class);
|
session.unregisterModelAdapter(IStopTracingHandler.class);
|
||||||
session.unregisterModelAdapter(ISaveTraceDataHandler.class);
|
session.unregisterModelAdapter(ISaveTraceDataHandler.class);
|
||||||
|
session.unregisterModelAdapter(ISelectNextTraceRecordHandler.class);
|
||||||
|
session.unregisterModelAdapter(ISelectPrevTraceRecordHandler.class);
|
||||||
|
|
||||||
session.unregisterModelAdapter(ICEditorTextHover.class);
|
session.unregisterModelAdapter(ICEditorTextHover.class);
|
||||||
|
|
||||||
fSteppingModeTarget.dispose();
|
fSteppingModeTarget.dispose();
|
||||||
|
@ -261,6 +273,8 @@ public class GdbAdapterFactory
|
||||||
fStartTracingTarget.dispose();
|
fStartTracingTarget.dispose();
|
||||||
fStopTracingTarget.dispose();
|
fStopTracingTarget.dispose();
|
||||||
fSaveTraceDataTarget.dispose();
|
fSaveTraceDataTarget.dispose();
|
||||||
|
fSelectNextRecordTarget.dispose();
|
||||||
|
fSelectPrevRecordTarget.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -8,6 +8,7 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* QNX Software Systems - initial API and implementation
|
* QNX Software Systems - initial API and implementation
|
||||||
* Ken Ryall (Nokia) - bug 178731
|
* Ken Ryall (Nokia) - bug 178731
|
||||||
|
* Ericsson - Support for tracepoint post-mortem debugging
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
|
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.model.ICProject;
|
||||||
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
|
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
|
||||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
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.internal.ui.GdbUIPlugin;
|
||||||
import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
|
import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
|
||||||
import org.eclipse.cdt.launch.ui.CAbstractMainTab;
|
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.ModifyListener;
|
||||||
import org.eclipse.swt.events.SelectionAdapter;
|
import org.eclipse.swt.events.SelectionAdapter;
|
||||||
import org.eclipse.swt.events.SelectionEvent;
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionListener;
|
||||||
import org.eclipse.swt.graphics.Image;
|
import org.eclipse.swt.graphics.Image;
|
||||||
import org.eclipse.swt.layout.GridData;
|
import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.layout.GridLayout;
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
import org.eclipse.swt.widgets.Button;
|
import org.eclipse.swt.widgets.Button;
|
||||||
|
import org.eclipse.swt.widgets.Combo;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.FileDialog;
|
||||||
import org.eclipse.swt.widgets.Label;
|
import org.eclipse.swt.widgets.Label;
|
||||||
import org.eclipse.swt.widgets.Text;
|
import org.eclipse.swt.widgets.Text;
|
||||||
import org.eclipse.ui.dialogs.TwoPaneElementSelector;
|
import org.eclipse.ui.dialogs.TwoPaneElementSelector;
|
||||||
|
@ -66,7 +71,18 @@ public class CMainTab extends CAbstractMainTab {
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public static final String TAB_ID = "org.eclipse.cdt.dsf.gdb.launch.mainTab"; //$NON-NLS-1$
|
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 fDontCheckProgram;
|
||||||
private final boolean fSpecifyCoreFile;
|
private final boolean fSpecifyCoreFile;
|
||||||
private final boolean fIncludeBuildSettings;
|
private final boolean fIncludeBuildSettings;
|
||||||
|
@ -151,7 +167,7 @@ public class CMainTab extends CAbstractMainTab {
|
||||||
browseForBinaryButton.addSelectionListener(new SelectionAdapter() {
|
browseForBinaryButton.addSelectionListener(new SelectionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void widgetSelected(SelectionEvent evt) {
|
public void widgetSelected(SelectionEvent evt) {
|
||||||
String text = handleBrowseButtonSelected();
|
String text = handleBrowseButtonSelected(LaunchMessages.getString("CMaintab.Application_Selection")); //$NON-NLS-1$
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
fProgText.setText(text);
|
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)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
|
@ -177,12 +279,50 @@ public class CMainTab extends CAbstractMainTab {
|
||||||
protected void updateCoreFromConfig(ILaunchConfiguration config) {
|
protected void updateCoreFromConfig(ILaunchConfiguration config) {
|
||||||
if (fCoreText != null) {
|
if (fCoreText != null) {
|
||||||
String coreName = EMPTY_STRING;
|
String coreName = EMPTY_STRING;
|
||||||
|
String coreType = IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT;
|
||||||
try {
|
try {
|
||||||
coreName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, EMPTY_STRING);
|
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) {
|
} catch (CoreException ce) {
|
||||||
GdbUIPlugin.log(ce);
|
GdbUIPlugin.log(ce);
|
||||||
}
|
}
|
||||||
fCoreText.setText(coreName);
|
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());
|
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, fProgText.getText());
|
||||||
if (fCoreText != null) {
|
if (fCoreText != null) {
|
||||||
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, fCoreText.getText());
|
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.
|
// This allows to re-use the launch, with a different core file.
|
||||||
if (!coreName.equals(EMPTY_STRING)) {
|
if (!coreName.equals(EMPTY_STRING)) {
|
||||||
if (coreName.equals(".") || coreName.equals("..")) { //$NON-NLS-1$ //$NON-NLS-2$
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
IPath corePath = new Path(coreName);
|
IPath corePath = new Path(coreName);
|
||||||
if (!corePath.toFile().exists()) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||||
Export-Package: org.eclipse.cdt.dsf.gdb,
|
Export-Package: org.eclipse.cdt.dsf.gdb,
|
||||||
org.eclipse.cdt.dsf.gdb.actions,
|
org.eclipse.cdt.dsf.gdb.actions,
|
||||||
org.eclipse.cdt.dsf.gdb.breakpoints,
|
org.eclipse.cdt.dsf.gdb.breakpoints,
|
||||||
|
org.eclipse.cdt.dsf.gdb.internal.commands,
|
||||||
org.eclipse.cdt.dsf.gdb.launching,
|
org.eclipse.cdt.dsf.gdb.launching,
|
||||||
org.eclipse.cdt.dsf.gdb.service,
|
org.eclipse.cdt.dsf.gdb.service,
|
||||||
org.eclipse.cdt.dsf.gdb.service.command,
|
org.eclipse.cdt.dsf.gdb.service.command,
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* 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$
|
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.
|
* 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;
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -21,6 +21,7 @@ import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
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.DataModelInitializedEvent;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||||
|
@ -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.actions.IConnect;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
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.SessionType;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
|
import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
|
||||||
|
@ -370,31 +373,60 @@ public class FinalLaunchSequence extends Sequence {
|
||||||
if (fSessionType == SessionType.CORE) {
|
if (fSessionType == SessionType.CORE) {
|
||||||
try {
|
try {
|
||||||
String coreFile = fLaunch.getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, ""); //$NON-NLS-1$
|
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) {
|
if (coreFile.length() == 0) {
|
||||||
new PromptForCoreJob(
|
new PromptForCoreJob(
|
||||||
"Prompt for core file", //$NON-NLS-1$
|
"Prompt for post mortem file", //$NON-NLS-1$
|
||||||
new DataRequestMonitor<String>(getExecutor(), requestMonitor) {
|
new DataRequestMonitor<String>(getExecutor(), requestMonitor) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
String newCoreFile = getData();
|
String newCoreFile = getData();
|
||||||
if (newCoreFile == null || newCoreFile.length()== 0) {
|
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();
|
requestMonitor.done();
|
||||||
} else {
|
} else {
|
||||||
fCommandControl.queueCommand(
|
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
|
||||||
fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), newCoreFile),
|
fCommandControl.queueCommand(
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
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();
|
}).schedule();
|
||||||
} else {
|
} else {
|
||||||
fCommandControl.queueCommand(
|
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
|
||||||
fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), coreFile),
|
fCommandControl.queueCommand(
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
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) {
|
} 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();
|
requestMonitor.done();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -10,6 +10,7 @@
|
||||||
* Windriver and Ericsson - Updated for DSF
|
* Windriver and Ericsson - Updated for DSF
|
||||||
* IBM Corporation
|
* IBM Corporation
|
||||||
* Ericsson - Added support for Mac OS
|
* Ericsson - Added support for Mac OS
|
||||||
|
* Ericsson - Added support for post-mortem trace files
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.dsf.gdb.launching;
|
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 final static String NON_STOP_FIRST_VERSION = "6.8.50"; //$NON-NLS-1$
|
||||||
private boolean isNonStopSession = false;
|
private boolean isNonStopSession = false;
|
||||||
|
|
||||||
|
private final static String TRACING_FIRST_VERSION = "7.1.50"; //$NON-NLS-1$
|
||||||
|
private boolean fIsPostMortemTracingSession;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
|
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$
|
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$
|
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));
|
launch.setServiceFactory(newServiceFactory(gdbVersion));
|
||||||
|
|
||||||
// Create and invoke the launch sequence to create the debug control and services
|
// Create and invoke the launch sequence to create the debug control and services
|
||||||
|
@ -254,6 +262,18 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
|
||||||
return false;
|
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
|
@Override
|
||||||
public boolean preLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) throws CoreException {
|
public boolean preLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) throws CoreException {
|
||||||
|
@ -271,6 +291,7 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
|
||||||
// the source lookup adapter.
|
// the source lookup adapter.
|
||||||
|
|
||||||
isNonStopSession = isNonStopSession(configuration);
|
isNonStopSession = isNonStopSession(configuration);
|
||||||
|
fIsPostMortemTracingSession = isPostMortemTracingSession(configuration);
|
||||||
|
|
||||||
GdbLaunch launch = new GdbLaunch(configuration, mode, null);
|
GdbLaunch launch = new GdbLaunch(configuration, mode, null);
|
||||||
launch.initialize();
|
launch.initialize();
|
||||||
|
@ -300,7 +321,22 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
|
||||||
}
|
}
|
||||||
return false;
|
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.
|
// A subclass can override this method and provide its own ServiceFactory.
|
||||||
protected IDsfDebugServicesFactory newServiceFactory(String version) {
|
protected IDsfDebugServicesFactory newServiceFactory(String version) {
|
||||||
|
|
||||||
|
|
|
@ -86,16 +86,23 @@ CMainTab.Project_not_specified=Project not specified
|
||||||
CMainTab.Program_not_specified=Program not specified
|
CMainTab.Program_not_specified=Program not specified
|
||||||
CMainTab.Project_must_be_opened=Project must be opened
|
CMainTab.Project_must_be_opened=Project must be opened
|
||||||
CMainTab.Program_does_not_exist=Program does not exist
|
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.Main=Main
|
||||||
CMainTab.&ProjectColon=&Project:
|
CMainTab.&ProjectColon=&Project:
|
||||||
CMainTab.C/C++_Application=C/C++ Application:
|
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.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.Search...=Searc&h Project...
|
||||||
CMainTab.Choose_program_to_run=Choose a &program to run:
|
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.Choose_program_to_run_from_NAME=Choose a program to run from {0}:
|
||||||
CMainTab.UseTerminal=Connect process input && output to a terminal.
|
CMainTab.UseTerminal=Connect process input && output to a terminal.
|
||||||
CMainTab.Program_is_not_a_recongnized_executable=Program is not a recognized executable.
|
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.Advanced_Options_Dialog_Title=Advanced Options
|
||||||
CDebuggerTab.Stop_at_main_on_startup=Stop on startup at:
|
CDebuggerTab.Stop_at_main_on_startup=Stop on startup at:
|
||||||
|
|
|
@ -782,6 +782,18 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
||||||
}
|
}
|
||||||
|
|
||||||
private IMIContainerDMContext[] makeContainerDMCs(ICommandControlDMContext controlDmc, IThreadGroupInfo[] groups) {
|
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];
|
IMIContainerDMContext[] containerDmcs = new IMIContainerDMContext[groups.length];
|
||||||
for (int i = 0; i < groups.length; i++) {
|
for (int i = 0; i < groups.length; i++) {
|
||||||
String groupId = groups[i].getGroupId();
|
String groupId = groups[i].getGroupId();
|
||||||
|
|
|
@ -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.ICommand;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
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.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.IMICommandControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
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 fReverseSupported = true;
|
||||||
private boolean fReverseStepping = false;
|
private boolean fReverseStepping = false;
|
||||||
private boolean fReverseModeEnabled = 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;
|
private RunToLineActiveOperation fRunToLineActiveOperation = null;
|
||||||
|
|
||||||
|
@ -105,6 +114,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
||||||
|
|
||||||
if (fGdb.getSessionType() == SessionType.CORE) {
|
if (fGdb.getSessionType() == SessionType.CORE) {
|
||||||
// No execution for core files, so no support for reverse
|
// No execution for core files, so no support for reverse
|
||||||
|
fRunControlOperationsEnabled = false;
|
||||||
fReverseSupported = false;
|
fReverseSupported = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +186,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void canResume(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
public void canResume(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
||||||
if (fGdb.getSessionType() == SessionType.CORE) {
|
if (fRunControlOperationsEnabled == false) {
|
||||||
rm.setData(false);
|
rm.setData(false);
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
return;
|
||||||
|
@ -189,7 +199,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void canSuspend(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
public void canSuspend(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
||||||
if (fGdb.getSessionType() == SessionType.CORE) {
|
if (fRunControlOperationsEnabled == false) {
|
||||||
rm.setData(false);
|
rm.setData(false);
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
return;
|
||||||
|
@ -202,7 +212,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void canStep(final IExecutionDMContext context, StepType stepType, final DataRequestMonitor<Boolean> rm) {
|
public void canStep(final IExecutionDMContext context, StepType stepType, final DataRequestMonitor<Boolean> rm) {
|
||||||
if (fGdb.getSessionType() == SessionType.CORE) {
|
if (fRunControlOperationsEnabled == false) {
|
||||||
rm.setData(false);
|
rm.setData(false);
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
return;
|
||||||
|
@ -591,6 +601,16 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
||||||
|
|
||||||
super.eventDispatched(e);
|
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 */
|
/** @since 2.0 */
|
||||||
public void setReverseModeEnabled(boolean enabled) {
|
public void setReverseModeEnabled(boolean enabled) {
|
||||||
|
|
|
@ -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;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
|
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.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.IMICommandControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
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() {
|
public StateChangeReason getReason() {
|
||||||
if (getMIEvent() instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
if (getMIEvent() instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
||||||
return StateChangeReason.EVENT_BREAKPOINT;
|
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) {
|
} else if (getMIEvent() instanceof MIBreakpointHitEvent) {
|
||||||
return StateChangeReason.BREAKPOINT;
|
return StateChangeReason.BREAKPOINT;
|
||||||
} else if (getMIEvent() instanceof MISteppingRangeEvent) {
|
} else if (getMIEvent() instanceof MISteppingRangeEvent) {
|
||||||
|
@ -162,6 +165,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
||||||
MIStoppedEvent event = getMIEvent();
|
MIStoppedEvent event = getMIEvent();
|
||||||
if (event instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
if (event instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
||||||
return ((MICatchpointHitEvent)event).getReason();
|
return ((MICatchpointHitEvent)event).getReason();
|
||||||
|
} else if (event instanceof MITracepointSelectedEvent) { // must precede MIBreakpointHitEvent
|
||||||
|
return ((MITracepointSelectedEvent)event).getReason();
|
||||||
} else if (event instanceof MISharedLibEvent) {
|
} else if (event instanceof MISharedLibEvent) {
|
||||||
return ((MISharedLibEvent)event).getLibrary();
|
return ((MISharedLibEvent)event).getLibrary();
|
||||||
} else if (event instanceof MISignalEvent) {
|
} else if (event instanceof MISignalEvent) {
|
||||||
|
|
|
@ -13,20 +13,31 @@ package org.eclipse.cdt.dsf.gdb.service;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
|
||||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
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.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
|
||||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
|
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.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
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.CommandCache;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
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.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.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.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.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;
|
||||||
|
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.MITraceStatusInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStopInfo;
|
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.AbstractDsfService;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
@ -35,119 +46,104 @@ import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
import org.osgi.framework.BundleContext;
|
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.
|
* to the debugger's tracing functionality.
|
||||||
*
|
*
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTraceControl, ICachingService {
|
public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTraceControl, ICachingService {
|
||||||
|
|
||||||
// @Immutable
|
@Immutable
|
||||||
// private static final class MITraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
|
protected static final class MITraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
|
||||||
//
|
|
||||||
// // The trace record reference
|
// The trace record reference
|
||||||
// private final int fReference;
|
private final int fReference;
|
||||||
//
|
|
||||||
// /**
|
/**
|
||||||
// * @param session the DsfSession for this service
|
* @param session the DsfSession for this service
|
||||||
// * @param parents the parent contexts
|
* @param parents the parent contexts
|
||||||
// * @param reference the trace record reference
|
* @param reference the trace record reference
|
||||||
// */
|
*/
|
||||||
// public MITraceRecordDMContext(DsfSession session, IDMContext[] parents, int reference) {
|
public MITraceRecordDMContext(DsfSession session, ITraceTargetDMContext parent, int reference) {
|
||||||
// super(session.getId(), parents);
|
super(session.getId(), new IDMContext[] { parent });
|
||||||
// fReference = reference;
|
fReference = reference;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// public int getReference() {
|
public int getReference() {
|
||||||
// return fReference;
|
return fReference;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// /* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
|
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
|
||||||
// */
|
*/
|
||||||
// @Override
|
@Override
|
||||||
// public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
// return baseEquals(obj) && (fReference == ((MITraceRecordDMContext) obj).fReference);
|
return baseEquals(obj) && (fReference == ((MITraceRecordDMContext) obj).fReference);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// /* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
|
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
|
||||||
// */
|
*/
|
||||||
// @Override
|
@Override
|
||||||
// public int hashCode() {
|
public int hashCode() {
|
||||||
// return baseHashCode() + fReference;
|
return baseHashCode() + fReference;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// /* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
// * @see java.lang.Object#toString()
|
* @see java.lang.Object#toString()
|
||||||
// */
|
*/
|
||||||
// @Override
|
@Override
|
||||||
// public String toString() {
|
public String toString() {
|
||||||
// return baseToString() + ".reference(" + fReference + ")"; //$NON-NLS-1$//$NON-NLS-2$
|
return baseToString() + ".reference(" + fReference + ")"; //$NON-NLS-1$//$NON-NLS-2$
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// /**
|
/**
|
||||||
// * Trace record context used to indicate that there is no current trace record selected.
|
* Trace record context used to indicate that there is no current trace record selected.
|
||||||
// */
|
*/
|
||||||
// @Immutable
|
@Immutable
|
||||||
// private static final class InvalidTraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
|
protected static final class InvalidTraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
|
||||||
//
|
|
||||||
// /**
|
/**
|
||||||
// * @param session the DsfSession for this service
|
* @param session the DsfSession for this service
|
||||||
// * @param parents the parent contexts
|
* @param parents the parent contexts
|
||||||
// * @param reference the trace record reference
|
* @param reference the trace record reference
|
||||||
// */
|
*/
|
||||||
// public InvalidTraceRecordDMContext(DsfSession session, IDMContext[] parents) {
|
public InvalidTraceRecordDMContext(DsfSession session, ITraceTargetDMContext parent) {
|
||||||
// super(session.getId(), parents);
|
super(session.getId(), new IDMContext[] { parent });
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
//
|
|
||||||
// /* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
|
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
|
||||||
// */
|
*/
|
||||||
// @Override
|
@Override
|
||||||
// public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
// return baseEquals(obj);
|
return baseEquals(obj);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// /* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
|
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
|
||||||
// */
|
*/
|
||||||
// @Override
|
@Override
|
||||||
// public int hashCode() {
|
public int hashCode() {
|
||||||
// return baseHashCode();
|
return baseHashCode();
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// /* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
// * @see java.lang.Object#toString()
|
* @see java.lang.Object#toString()
|
||||||
// */
|
*/
|
||||||
// @Override
|
@Override
|
||||||
// public String toString() {
|
public String toString() {
|
||||||
// return baseToString() + ".noTraceRecord"; //$NON-NLS-1$
|
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; }
|
|
||||||
// }
|
|
||||||
|
|
||||||
private class TraceVariableDMData implements ITraceVariableDMData {
|
private class TraceVariableDMData implements ITraceVariableDMData {
|
||||||
private String fName;
|
private String fName;
|
||||||
private String fValue;
|
private String fValue;
|
||||||
private String fInitialValue;
|
private String fInitialValue;
|
||||||
|
|
||||||
public TraceVariableDMData(String name, String value) {
|
|
||||||
this(name, value, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TraceVariableDMData(String name, String initial, String value) {
|
public TraceVariableDMData(String name, String initial, String value) {
|
||||||
fName = name;
|
fName = name;
|
||||||
fInitialValue = initial;
|
fInitialValue = initial;
|
||||||
|
@ -245,6 +241,20 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
return "\nTracing is not supported\n";
|
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 += "Tracing is currently" + (!fTracingActive ? " not":"") + " active\n";
|
||||||
str += "Buffer contains " + fNumberOfCollectedFrames + " trace frame" +
|
str += "Buffer contains " + fNumberOfCollectedFrames + " trace frame" +
|
||||||
(fNumberOfCollectedFrames>1?"s":"") + "\n";//" (out of ? created in total)\n";
|
(fNumberOfCollectedFrames>1?"s":"") + "\n";//" (out of ? created in total)\n";
|
||||||
|
@ -270,7 +280,10 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
} else {
|
} else {
|
||||||
str += " unknow reason";
|
str += " unknow reason";
|
||||||
}
|
}
|
||||||
|
str += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
@ -304,25 +317,27 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private static class TraceRecordSelectedChangedEvent extends AbstractDMEvent<ITraceRecordDMContext>
|
public static class TraceRecordSelectedChangedEvent extends AbstractDMEvent<ITraceRecordDMContext>
|
||||||
// implements ITraceRecordSelectedChangedDMEvent {
|
implements ITraceRecordSelectedChangedDMEvent {
|
||||||
// public TraceRecordSelectedChangedEvent(ITraceRecordDMContext context) {
|
public TraceRecordSelectedChangedEvent(ITraceRecordDMContext context) {
|
||||||
// super(context);
|
super(context);
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
private CommandCache fTraceCache;
|
private CommandCache fTraceCache;
|
||||||
private ICommandControlService fConnection;
|
private ICommandControlService fConnection;
|
||||||
private CommandFactory fCommandFactory;
|
private CommandFactory fCommandFactory;
|
||||||
|
private IGDBBackend fBackend;
|
||||||
// private ITraceRecordDMContext fCurrentRecordDmc = null;
|
|
||||||
|
|
||||||
private boolean fIsTracingActive = false;
|
|
||||||
private boolean fIsTracingSupported = false;
|
|
||||||
private int fTraceRecordsStored = 0;
|
|
||||||
|
|
||||||
|
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);
|
super(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,10 +366,6 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
* initialization is done.
|
* initialization is done.
|
||||||
*/
|
*/
|
||||||
private void doInitialize(RequestMonitor requestMonitor) {
|
private void doInitialize(RequestMonitor requestMonitor) {
|
||||||
|
|
||||||
// Register to receive service events for this session.
|
|
||||||
// getSession().addServiceEventListener(this, null);
|
|
||||||
|
|
||||||
// Register this service.
|
// Register this service.
|
||||||
register(new String[] {IGDBTraceControl.class.getName()},
|
register(new String[] {IGDBTraceControl.class.getName()},
|
||||||
new Hashtable<String, String>());
|
new Hashtable<String, String>());
|
||||||
|
@ -364,6 +375,7 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
fTraceCache = new CommandCache(getSession(), fConnection);
|
fTraceCache = new CommandCache(getSession(), fConnection);
|
||||||
fTraceCache.setContextAvailable(fConnection.getContext(), true);
|
fTraceCache.setContextAvailable(fConnection.getContext(), true);
|
||||||
|
|
||||||
|
fBackend = getServicesTracker().getService(IGDBBackend.class);
|
||||||
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
|
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
|
||||||
|
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
|
@ -379,7 +391,6 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
@Override
|
@Override
|
||||||
public void shutdown(RequestMonitor requestMonitor) {
|
public void shutdown(RequestMonitor requestMonitor) {
|
||||||
unregister();
|
unregister();
|
||||||
// getSession().removeServiceEventListener(this);
|
|
||||||
super.shutdown(requestMonitor);
|
super.shutdown(requestMonitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,8 +408,27 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
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();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,6 +468,25 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
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);
|
isTracing(context, rm);
|
||||||
}
|
}
|
||||||
|
@ -488,11 +537,17 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fBackend.getSessionType() == SessionType.CORE) {
|
||||||
|
rm.setData(false);
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Although tracing can be automatically stopped on the target, we
|
// 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
|
// 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
|
// 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
|
// 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.setData(fIsTracingActive);
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
@ -503,21 +558,45 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
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.setData(fTraceRecordsStored > 0);
|
||||||
rm.done();
|
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) {
|
if (context == null) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fConnection.queueCommand(
|
canSaveTraceData(context, new DataRequestMonitor<Boolean>(getExecutor(), rm) {
|
||||||
fCommandFactory.createMITraceSave(context, file, remoteSave),
|
@Override
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
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) {
|
public void canLoadTraceData(ITraceTargetDMContext context, DataRequestMonitor<Boolean> rm) {
|
||||||
|
@ -527,20 +606,44 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
return;
|
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.setData(true);
|
||||||
rm.done();
|
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) {
|
if (context == null) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fConnection.queueCommand(
|
canLoadTraceData(context, new DataRequestMonitor<Boolean>(getExecutor(), rm) {
|
||||||
fCommandFactory.createMITargetSelectTFile(context, file),
|
@Override
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
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) {
|
public void getTraceStatus(final ITraceTargetDMContext context, final DataRequestMonitor<ITraceStatusDMData> rm) {
|
||||||
|
@ -550,19 +653,31 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
return;
|
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(
|
fConnection.queueCommand(
|
||||||
fCommandFactory.createMITraceStatus(context),
|
fCommandFactory.createMITraceStatus(context),
|
||||||
new DataRequestMonitor<MITraceStatusInfo>(getExecutor(), rm) {
|
new DataRequestMonitor<MITraceStatusInfo>(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleError() {
|
||||||
|
// The MI command
|
||||||
|
fIsTracingFeatureAvailable = false;
|
||||||
|
super.handleError();
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
MITraceStatusInfo info = getData();
|
MITraceStatusInfo info = getData();
|
||||||
|
|
||||||
if (fIsTracingSupported != info.isTracingSupported()) {
|
if (fIsTracingCurrentlySupported != info.isTracingSupported()) {
|
||||||
fIsTracingSupported = info.isTracingSupported();
|
fIsTracingCurrentlySupported = info.isTracingSupported();
|
||||||
getSession().dispatchEvent(new TracingSupportedChangeEvent(context, fIsTracingSupported), getProperties());
|
getSession().dispatchEvent(new TracingSupportedChangeEvent(context, fIsTracingCurrentlySupported), getProperties());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fIsTracingSupported) {
|
if (fIsTracingCurrentlySupported) {
|
||||||
// Update the tracing state in case it was stopped by the backend
|
// Update the tracing state in case it was stopped by the backend
|
||||||
if (fIsTracingActive != info.isTracingActive()) {
|
if (fIsTracingActive != info.isTracingActive()) {
|
||||||
fIsTracingActive = info.isTracingActive();
|
fIsTracingActive = info.isTracingActive();
|
||||||
|
@ -609,6 +724,12 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
return;
|
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) {
|
if (varValue == null) {
|
||||||
fConnection.queueCommand(
|
fConnection.queueCommand(
|
||||||
fCommandFactory.createMITraceDefineVariable(context, varName),
|
fCommandFactory.createMITraceDefineVariable(context, varName),
|
||||||
|
@ -628,6 +749,12 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
return;
|
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
|
// 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
|
// where to data can change, to clear the cache in those cases
|
||||||
fConnection.queueCommand(
|
fConnection.queueCommand(
|
||||||
|
@ -648,125 +775,173 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// /**
|
/**
|
||||||
// * Create a trace record context
|
* Create a trace record context
|
||||||
// */
|
*/
|
||||||
// public ITraceRecordDMContext createTraceRecordContext(IDMContext ctx, int index) {
|
public ITraceRecordDMContext createTraceRecordContext(ITraceTargetDMContext ctx, int index) {
|
||||||
// return new MITraceRecordDMContext(getSession(), new IDMContext[] { ctx }, index);
|
return new MITraceRecordDMContext(getSession(), 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;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
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) {
|
public void flushCache(IDMContext context) {
|
||||||
fTraceCache.reset(context);
|
fTraceCache.reset(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -43,7 +43,8 @@ import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
||||||
|
|
||||||
// This should eventually be "7.0" once GDB 7.0 is released
|
// 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;
|
private final String fVersion;
|
||||||
|
|
||||||
|
@ -163,12 +164,15 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
||||||
|
|
||||||
/** @since 3.0 */
|
/** @since 3.0 */
|
||||||
protected IGDBTraceControl createTraceControlService(DsfSession session, ILaunchConfiguration config) {
|
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
|
// there is a pre-release that has a version of 6.8.50.20090414
|
||||||
if ("6.8.50.20090414".compareTo(fVersion) <= 0) {
|
if (GDB_7_2_VERSION.compareTo(fVersion) <= 0 || "6.8.50.20090414".equals(fVersion)) { //$NON-NLS-1$
|
||||||
return new GDBTraceControl_7_1(session, config);
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@ import org.eclipse.cdt.dsf.service.IDsfService;
|
||||||
* The TraceControl service provides access to the debugger Tracing functionality.
|
* The TraceControl service provides access to the debugger Tracing functionality.
|
||||||
* It is used to do such things as start and stop tracing.
|
* 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
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface IGDBTraceControl extends IDsfService {
|
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.
|
* {@link saveTraceData} should have the correct format to be loaded by this call.
|
||||||
*/
|
*/
|
||||||
public void loadTraceData(ITraceTargetDMContext context,
|
public void loadTraceData(ITraceTargetDMContext context,
|
||||||
String file,
|
String file,
|
||||||
RequestMonitor rm);
|
RequestMonitor rm);
|
||||||
|
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Request that the backend use the specified trace record.
|
* Request that the backend use the specified trace record.
|
||||||
// */
|
*/
|
||||||
// public void selectTraceRecord(ITraceRecordDMContext context, RequestMonitor rm);
|
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);
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
|
public void getTraceRecordData(ITraceRecordDMContext context, DataRequestMonitor<ITraceRecordDMData> rm);
|
||||||
|
|
||||||
/////////////////////////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
// GDB specific part
|
// GDB specific part
|
||||||
/////////////////////////////////////////////////
|
/////////////////////////////////////////////////
|
||||||
|
@ -179,12 +158,8 @@ public interface IGDBTraceControl extends IDsfService {
|
||||||
*/
|
*/
|
||||||
public void getTraceVariables(ITraceTargetDMContext context, DataRequestMonitor<ITraceVariableDMData[]> rm);
|
public void getTraceVariables(ITraceTargetDMContext context, DataRequestMonitor<ITraceVariableDMData[]> rm);
|
||||||
|
|
||||||
// public ITraceRecordDMContext createTraceRecordContext(IDMContext ctx, int index);
|
public ITraceRecordDMContext createTraceRecordContext(ITraceTargetDMContext ctx, int index);
|
||||||
// public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm);
|
public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm);
|
||||||
// public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx);
|
public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx);
|
||||||
// public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx);
|
public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx);
|
||||||
//
|
|
||||||
// public void setDefaultCollect(ITraceTargetDMContext context, String[] expressions, RequestMonitor rm);
|
|
||||||
// public void getDefaultCollect(ITraceTargetDMContext context, DataRequestMonitor<String> rm);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.launching.GdbLaunch;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.GDBRunControl_7_0;
|
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.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.IReverseRunControl;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.GDBProcesses_7_0.ContainerExitedDMEvent;
|
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 static class InitializationShutdownStep extends Sequence.Step {
|
||||||
public enum Direction { INITIALIZING, SHUTTING_DOWN }
|
public enum Direction { INITIALIZING, SHUTTING_DOWN }
|
||||||
|
|
||||||
|
|
|
@ -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.debug.service.command.ICommandControlService;
|
||||||
import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType;
|
import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
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.CommandFactory;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetAttributes;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetAttributes;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetChildCount;
|
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 MIVariableManager varManager;
|
||||||
private CommandFactory fCommandFactory;
|
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) {
|
public MIExpressions(DsfSession session) {
|
||||||
super(session);
|
super(session);
|
||||||
}
|
}
|
||||||
|
@ -754,6 +761,15 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I
|
||||||
rm.setData(new FormattedValueDMData(getData().getValue()));
|
rm.setData(new FormattedValueDMData(getData().getValue()));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
protected void handleError() {
|
||||||
|
if (fTraceVisualization) {
|
||||||
|
rm.setData(new FormattedValueDMData("")); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
} else {
|
||||||
|
super.handleError();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
fExpressionCache.execute(
|
fExpressionCache.execute(
|
||||||
|
@ -1004,6 +1020,14 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I
|
||||||
// MIVariableManager separately traps this event
|
// 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}
|
* {@inheritDoc}
|
||||||
* @since 1.1
|
* @since 1.1
|
||||||
|
|
|
@ -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;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
|
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.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.MIBreakpoints.MIBreakpointDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
|
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() {
|
public StateChangeReason getReason() {
|
||||||
if (getMIEvent() instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
if (getMIEvent() instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
||||||
return StateChangeReason.EVENT_BREAKPOINT;
|
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) {
|
} else if (getMIEvent() instanceof MIBreakpointHitEvent) {
|
||||||
return StateChangeReason.BREAKPOINT;
|
return StateChangeReason.BREAKPOINT;
|
||||||
} else if (getMIEvent() instanceof MISteppingRangeEvent) {
|
} else if (getMIEvent() instanceof MISteppingRangeEvent) {
|
||||||
|
@ -201,6 +204,8 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
||||||
MIStoppedEvent event = getMIEvent();
|
MIStoppedEvent event = getMIEvent();
|
||||||
if (event instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
if (event instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
||||||
return ((MICatchpointHitEvent)event).getReason();
|
return ((MICatchpointHitEvent)event).getReason();
|
||||||
|
} else if (event instanceof MITracepointSelectedEvent) { // must precede MIBreakpointHitEvent
|
||||||
|
return ((MITracepointSelectedEvent)event).getReason();
|
||||||
} else if (event instanceof MISharedLibEvent) {
|
} else if (event instanceof MISharedLibEvent) {
|
||||||
return ((MISharedLibEvent)event).getLibrary();
|
return ((MISharedLibEvent)event).getLibrary();
|
||||||
} else if (event instanceof MISignalEvent) {
|
} else if (event instanceof MISignalEvent) {
|
||||||
|
|
|
@ -26,16 +26,17 @@ import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
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.IExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
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.ISuspendedDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
|
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.BufferedCommandControl;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
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.ICommand;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
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.CommandFactory;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
||||||
|
@ -61,7 +62,6 @@ public class MIStack extends AbstractDsfService
|
||||||
implements IFrameDMContext
|
implements IFrameDMContext
|
||||||
{
|
{
|
||||||
private final int fLevel;
|
private final int fLevel;
|
||||||
// public MIFrameDMC(MIStack service, int level) {
|
|
||||||
public MIFrameDMC(String sessionId, IExecutionDMContext execDmc, int level) {
|
public MIFrameDMC(String sessionId, IExecutionDMContext execDmc, int level) {
|
||||||
super(sessionId, new IDMContext[] { execDmc });
|
super(sessionId, new IDMContext[] { execDmc });
|
||||||
fLevel = level;
|
fLevel = level;
|
||||||
|
@ -166,6 +166,12 @@ public class MIStack extends AbstractDsfService
|
||||||
private MIStoppedEvent fCachedStoppedEvent;
|
private MIStoppedEvent fCachedStoppedEvent;
|
||||||
private IRunControl fRunControl;
|
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)
|
public MIStack(DsfSession session)
|
||||||
{
|
{
|
||||||
super(session);
|
super(session);
|
||||||
|
@ -250,20 +256,19 @@ public class MIStack extends AbstractDsfService
|
||||||
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
|
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
|
||||||
|
|
||||||
if (execDmc == null) {
|
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.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context " + ctx, null)); //$NON-NLS-1$
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the thread is stopped
|
// Make sure the thread is stopped but only if we are not visualizing trace data
|
||||||
if (!fRunControl.isSuspended(execDmc)) {
|
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.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context is running: " + ctx, null)); //$NON-NLS-1$
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startIndex == 0 && endIndex == 0) {
|
if (fTraceVisualization || (startIndex == 0 && endIndex == 0)) {
|
||||||
// Try to retrieve the top stack frame from the cached stopped event.
|
// Try to retrieve the top stack frame from the cached stopped event.
|
||||||
if (fCachedStoppedEvent != null &&
|
if (fCachedStoppedEvent != null &&
|
||||||
fCachedStoppedEvent.getFrame() != 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) {
|
private IFrameDMContext[] getFrames(IMIExecutionDMContext execDmc, MIStackListFramesInfo info, int firstIndex, int lastIndex, int startIndex) {
|
||||||
int length = info.getMIFrames().length;
|
int length = info.getMIFrames().length;
|
||||||
if (lastIndex > 0) {
|
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
|
// Retrieve the top stack frame from the stopped event only if the selected thread is the one on which stopped event
|
||||||
// is raised
|
// is raised
|
||||||
if (fCachedStoppedEvent != null &&
|
if (fTraceVisualization || miFrameDmc.fLevel == 0) {
|
||||||
execDmc.equals(fCachedStoppedEvent.getDMContext()) &&
|
if (fCachedStoppedEvent != null && fCachedStoppedEvent.getFrame() != null &&
|
||||||
miFrameDmc.fLevel == 0 &&
|
(execDmc.equals(fCachedStoppedEvent.getDMContext()) || fTraceVisualization))
|
||||||
fCachedStoppedEvent.getFrame() != null)
|
{
|
||||||
{
|
rm.setData(new FrameDataFromStoppedEvent(fCachedStoppedEvent));
|
||||||
rm.setData(new FrameDataFromStoppedEvent(fCachedStoppedEvent));
|
rm.done();
|
||||||
rm.done();
|
return;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not, retrieve the full list of frame data.
|
// If not, retrieve the full list of frame data.
|
||||||
class FrameDataFromMIStackFrameListInfo extends FrameData {
|
class FrameDataFromMIStackFrameListInfo extends FrameData {
|
||||||
|
@ -475,13 +479,24 @@ public class MIStack extends AbstractDsfService
|
||||||
return;
|
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(
|
fMICommandCache.execute(
|
||||||
// We don't actually need to ask for the values in this case, but since
|
// 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
|
// 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
|
// so as to cache the result. If the command fails, then we will ask for
|
||||||
// the result without the values
|
// 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) {
|
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
|
@ -504,8 +519,8 @@ public class MIStack extends AbstractDsfService
|
||||||
@Override
|
@Override
|
||||||
protected void handleError() {
|
protected void handleError() {
|
||||||
// If the command fails it can be because we asked for values.
|
// If the command fails it can be because we asked for values.
|
||||||
// This can happen with uninitialized values and pretty printers (bug 307614)
|
// This can happen with uninitialized values and pretty printers (bug 307614).
|
||||||
// or when visualizing tracepoints. Since asking for values was simply an optimization
|
// Since asking for values was simply an optimization
|
||||||
// to store the command in the cache, let's retry the command without asking for values.
|
// to store the command in the cache, let's retry the command without asking for values.
|
||||||
fMICommandCache.execute(
|
fMICommandCache.execute(
|
||||||
fCommandFactory.createMIStackListArguments(execDmc, false),
|
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) {
|
public void getVariableData(IVariableDMContext variableDmc, final DataRequestMonitor<IVariableDMData> rm) {
|
||||||
if (!(variableDmc instanceof MIVariableDMC)) {
|
if (!(variableDmc instanceof MIVariableDMC)) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context type " + variableDmc, null)); //$NON-NLS-1$
|
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 (miVariableDmc.fType == MIVariableDMC.Type.ARGUMENT){
|
||||||
|
if (fTraceVisualization) {
|
||||||
|
getArgumentsDataForTraceVisualization(miVariableDmc, rm);
|
||||||
|
} else {
|
||||||
fMICommandCache.execute(
|
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) {
|
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
|
@ -610,8 +667,7 @@ public class MIStack extends AbstractDsfService
|
||||||
@Override
|
@Override
|
||||||
protected void handleError() {
|
protected void handleError() {
|
||||||
// Unable to get the values. This can happen with uninitialized values and pretty printers (bug 307614)
|
// 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,
|
// Let's try to ask for the arguments without their values, which is better than nothing
|
||||||
// which is better than nothing
|
|
||||||
fMICommandCache.execute(
|
fMICommandCache.execute(
|
||||||
fCommandFactory.createMIStackListArguments(execDmc, false),
|
fCommandFactory.createMIStackListArguments(execDmc, false),
|
||||||
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
|
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
|
||||||
|
@ -633,10 +689,13 @@ public class MIStack extends AbstractDsfService
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}//if
|
}//if
|
||||||
if (miVariableDmc.fType == MIVariableDMC.Type.LOCAL){
|
if (miVariableDmc.fType == MIVariableDMC.Type.LOCAL){
|
||||||
fMICommandCache.execute(
|
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) {
|
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
|
@ -652,9 +711,8 @@ public class MIStack extends AbstractDsfService
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void handleError() {
|
protected void handleError() {
|
||||||
// Unable to get the value. This can happen with uninitialized values and pretty printers (bug 307614)
|
// 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,
|
// Let's try to ask for the variables without their values, which is better than nothing
|
||||||
// which is better than nothing
|
|
||||||
fMICommandCache.execute(
|
fMICommandCache.execute(
|
||||||
fCommandFactory.createMIStackListLocals(frameDmc, false),
|
fCommandFactory.createMIStackListLocals(frameDmc, false),
|
||||||
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) {
|
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) {
|
private MIVariableDMC[] makeVariableDMCs(IFrameDMContext frame, MIVariableDMC.Type type, int count) {
|
||||||
MIVariableDMC[] variables = new MIVariableDMC[count];
|
MIVariableDMC[] variables = new MIVariableDMC[count];
|
||||||
for (int i = 0; i < count; i++) {
|
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
|
// 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
|
// so as to cache the result. If the command fails, then we will ask for
|
||||||
// the result without the values
|
// 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) {
|
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), countingRm) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
|
@ -734,8 +840,8 @@ public class MIStack extends AbstractDsfService
|
||||||
@Override
|
@Override
|
||||||
protected void handleError() {
|
protected void handleError() {
|
||||||
// If the command fails it can be because we asked for values.
|
// If the command fails it can be because we asked for values.
|
||||||
// This can happen with uninitialized values and pretty printers (bug 307614)
|
// This can happen with uninitialized values and pretty printers (bug 307614).
|
||||||
// or when visualizing tracepoints. Since asking for values was simply an optimization
|
// Since asking for values was simply an optimization
|
||||||
// to store the command in the cache, let's retry the command without asking for values.
|
// to store the command in the cache, let's retry the command without asking for values.
|
||||||
fMICommandCache.execute(
|
fMICommandCache.execute(
|
||||||
fCommandFactory.createMIStackListLocals(frameDmc, false),
|
fCommandFactory.createMIStackListLocals(frameDmc, false),
|
||||||
|
@ -755,7 +861,7 @@ public class MIStack extends AbstractDsfService
|
||||||
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class);
|
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class);
|
||||||
if (execDmc != null) {
|
if (execDmc != null) {
|
||||||
// Make sure the thread is stopped
|
// Make sure the thread is stopped
|
||||||
if (!fRunControl.isSuspended(execDmc)) {
|
if (!fTraceVisualization && !fRunControl.isSuspended(execDmc)) {
|
||||||
rm.setData(0);
|
rm.setData(0);
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
return;
|
||||||
|
@ -787,6 +893,25 @@ public class MIStack extends AbstractDsfService
|
||||||
rm.setData(getData().getDepth());
|
rm.setData(getData().getDepth());
|
||||||
rm.done();
|
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 {
|
} else {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
|
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}
|
* {@inheritDoc}
|
||||||
* @since 1.1
|
* @since 1.1
|
||||||
|
|
|
@ -15,6 +15,7 @@ package org.eclipse.cdt.dsf.mi.service;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
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.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IExpressions;
|
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.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.FormattedValueDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData;
|
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.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.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.IStack.IFrameDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
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.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.ICommandListener;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandResult;
|
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.ICommandToken;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
|
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;
|
||||||
import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType;
|
import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
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.ExpressionInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.MIExpressions.MIExpressionDMC;
|
import org.eclipse.cdt.dsf.mi.service.MIExpressions.MIExpressionDMC;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
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
|
// The variable object is out-of-scope and we
|
||||||
// should not use it.
|
// should not use it.
|
||||||
if (shouldCreateNew) {
|
if (shouldCreateNew) {
|
||||||
/**
|
/*
|
||||||
* It may happen that when accessing a varObject we find it to be
|
* 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
|
* 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
|
* 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
|
// The views will fully refresh on a MemoryChangedEvent
|
||||||
markAllOutOfDate();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ public abstract class AbstractMIControl extends AbstractDsfService
|
||||||
|
|
||||||
// MI did not always support the --thread/--frame options
|
// 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
|
// 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
|
// currentStackLevel and currentThreadId are only necessary when
|
||||||
// we must use -thread-select and -stack-select-frame
|
// we must use -thread-select and -stack-select-frame
|
||||||
private int fCurrentStackLevel = -1;
|
private int fCurrentStackLevel = -1;
|
||||||
|
@ -157,6 +157,13 @@ public abstract class AbstractMIControl extends AbstractDsfService
|
||||||
return fTracingStream;
|
return fTracingStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
protected void setUseThreadAndFrameOptions(boolean shouldUse) {
|
||||||
|
fUseThreadAndFrameOptions = shouldUse;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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.MIThreadListIds;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIThreadSelect;
|
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.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.MITraceListVariables;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceSave;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceSave;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceStart;
|
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.MIStackListLocalsInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIThreadInfoInfo;
|
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.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.MITraceListVariablesInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStatusInfo;
|
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.MITraceStopInfo;
|
||||||
|
@ -660,6 +662,10 @@ public class CommandFactory {
|
||||||
public ICommand<MIInfo> createMITraceDefineVariable(ITraceTargetDMContext ctx, String varName, String varValue) {
|
public ICommand<MIInfo> createMITraceDefineVariable(ITraceTargetDMContext ctx, String varName, String varValue) {
|
||||||
return new MITraceDefineVariable(ctx, varName, 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) {
|
public ICommand<MITraceListVariablesInfo> createMITraceListVariables(ITraceTargetDMContext ctx) {
|
||||||
return new MITraceListVariables(ctx);
|
return new MITraceListVariables(ctx);
|
||||||
|
|
|
@ -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 if 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue