mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 284286: Trace Record visualization for DSF-GDB
This commit is contained in:
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.stopTracing.name=Stop Tracing
|
||||
toolbar.saveTracing.name=Save Trace Data
|
||||
toolbar.nextTraceRecord.label=Next Trace Record
|
||||
toolbar.prevTraceRecord.label=Previous Trace Record
|
||||
command.nextTraceRecord.name=Next Trace Record
|
||||
command.prevTraceRecord.name=Previous Trace Record
|
||||
command.nextTraceRecord.description=Select Next Trace Record
|
||||
command.prevTraceRecord.description=Select Previous Trace Record
|
||||
|
|
|
@ -353,6 +353,30 @@
|
|||
</viewShortcut>
|
||||
</perspectiveExtension>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.commands">
|
||||
<command
|
||||
description="%command.nextTraceRecord.description"
|
||||
id="org.eclipse.cdt.dsf.gdb.ui.command.selectNextTraceRecord"
|
||||
name="%command.nextTraceRecord.name">
|
||||
</command>
|
||||
<command
|
||||
description="%command.prevTraceRecord.description"
|
||||
id="org.eclipse.cdt.dsf.gdb.ui.command.selectPreviousTraceRecord"
|
||||
name="%command.prevTraceRecord.name">
|
||||
</command>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.handlers">
|
||||
<handler
|
||||
class="org.eclipse.cdt.dsf.gdb.internal.ui.commands.SelectNextTraceRecordCommandHandler"
|
||||
commandId="org.eclipse.cdt.dsf.gdb.ui.command.selectNextTraceRecord">
|
||||
</handler>
|
||||
<handler
|
||||
class="org.eclipse.cdt.dsf.gdb.internal.ui.commands.SelectPrevTraceRecordCommandHandler"
|
||||
commandId="org.eclipse.cdt.dsf.gdb.ui.command.selectPreviousTraceRecord">
|
||||
</handler>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.menus">
|
||||
<menuContribution
|
||||
|
@ -369,6 +393,18 @@
|
|||
label="%toolbar.stopTracing.name"
|
||||
style="push">
|
||||
</command>
|
||||
<command
|
||||
commandId="org.eclipse.cdt.dsf.gdb.ui.command.selectNextTraceRecord"
|
||||
icon="icons/full/obj16/next_trace_record_nav.gif"
|
||||
label="%toolbar.nextTraceRecord.label"
|
||||
style="push">
|
||||
</command>
|
||||
<command
|
||||
commandId="org.eclipse.cdt.dsf.gdb.ui.command.selectPreviousTraceRecord"
|
||||
icon="icons/full/obj16/prev_trace_record_nav.gif"
|
||||
label="%toolbar.prevTraceRecord.label"
|
||||
style="push">
|
||||
</command>
|
||||
</menuContribution>
|
||||
<menuContribution
|
||||
locationURI="menu:org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view?after=additions">
|
||||
|
|
|
@ -40,6 +40,8 @@ import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.DefaultRefreshAllTarget;
|
|||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.IRefreshAllTarget;
|
||||
import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.DefaultDsfModelSelectionPolicyFactory;
|
||||
import org.eclipse.cdt.dsf.gdb.actions.IConnect;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.commands.ISelectNextTraceRecordHandler;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.commands.ISelectPrevTraceRecordHandler;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.actions.DsfTerminateCommand;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbConnectCommand;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbDisconnectCommand;
|
||||
|
@ -51,6 +53,8 @@ import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseStepIntoCommand;
|
|||
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseStepOverCommand;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseToggleCommand;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbSaveTraceDataCommand;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbSelectNextTraceRecordCommand;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbSelectPrevTraceRecordCommand;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbStartTracingCommand;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbStopTracingCommand;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbUncallCommand;
|
||||
|
@ -119,6 +123,8 @@ public class GdbAdapterFactory
|
|||
final GdbStartTracingCommand fStartTracingTarget;
|
||||
final GdbStopTracingCommand fStopTracingTarget;
|
||||
final GdbSaveTraceDataCommand fSaveTraceDataTarget;
|
||||
final GdbSelectNextTraceRecordCommand fSelectNextRecordTarget;
|
||||
final GdbSelectPrevTraceRecordCommand fSelectPrevRecordTarget;
|
||||
final GdbDebugTextHover fDebugTextHover;
|
||||
|
||||
SessionAdapterSet(GdbLaunch launch) {
|
||||
|
@ -161,6 +167,8 @@ public class GdbAdapterFactory
|
|||
fStartTracingTarget = new GdbStartTracingCommand(session);
|
||||
fStopTracingTarget = new GdbStopTracingCommand(session);
|
||||
fSaveTraceDataTarget = new GdbSaveTraceDataCommand(session);
|
||||
fSelectNextRecordTarget = new GdbSelectNextTraceRecordCommand(session);
|
||||
fSelectPrevRecordTarget = new GdbSelectPrevTraceRecordCommand(session);
|
||||
|
||||
session.registerModelAdapter(ISteppingModeTarget.class, fSteppingModeTarget);
|
||||
session.registerModelAdapter(IStepIntoHandler.class, fStepIntoCommand);
|
||||
|
@ -183,6 +191,8 @@ public class GdbAdapterFactory
|
|||
session.registerModelAdapter(IStartTracingHandler.class, fStartTracingTarget);
|
||||
session.registerModelAdapter(IStopTracingHandler.class, fStopTracingTarget);
|
||||
session.registerModelAdapter(ISaveTraceDataHandler.class, fSaveTraceDataTarget);
|
||||
session.registerModelAdapter(ISelectNextTraceRecordHandler.class, fSelectNextRecordTarget);
|
||||
session.registerModelAdapter(ISelectPrevTraceRecordHandler.class, fSelectPrevRecordTarget);
|
||||
|
||||
fDebugModelProvider = new IDebugModelProvider() {
|
||||
// @see org.eclipse.debug.core.model.IDebugModelProvider#getModelIdentifiers()
|
||||
|
@ -238,7 +248,9 @@ public class GdbAdapterFactory
|
|||
session.unregisterModelAdapter(IStartTracingHandler.class);
|
||||
session.unregisterModelAdapter(IStopTracingHandler.class);
|
||||
session.unregisterModelAdapter(ISaveTraceDataHandler.class);
|
||||
|
||||
session.unregisterModelAdapter(ISelectNextTraceRecordHandler.class);
|
||||
session.unregisterModelAdapter(ISelectPrevTraceRecordHandler.class);
|
||||
|
||||
session.unregisterModelAdapter(ICEditorTextHover.class);
|
||||
|
||||
fSteppingModeTarget.dispose();
|
||||
|
@ -261,6 +273,8 @@ public class GdbAdapterFactory
|
|||
fStartTracingTarget.dispose();
|
||||
fStopTracingTarget.dispose();
|
||||
fSaveTraceDataTarget.dispose();
|
||||
fSelectNextRecordTarget.dispose();
|
||||
fSelectPrevRecordTarget.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -8,6 +8,7 @@
|
|||
* Contributors:
|
||||
* QNX Software Systems - initial API and implementation
|
||||
* Ken Ryall (Nokia) - bug 178731
|
||||
* Ericsson - Support for tracepoint post-mortem debugging
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
|
||||
|
||||
|
@ -17,6 +18,7 @@ import org.eclipse.cdt.core.model.ICElement;
|
|||
import org.eclipse.cdt.core.model.ICProject;
|
||||
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
|
||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
|
||||
import org.eclipse.cdt.launch.ui.CAbstractMainTab;
|
||||
|
@ -39,11 +41,14 @@ import org.eclipse.swt.events.ModifyEvent;
|
|||
import org.eclipse.swt.events.ModifyListener;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.events.SelectionListener;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Combo;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.FileDialog;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.eclipse.ui.dialogs.TwoPaneElementSelector;
|
||||
|
@ -66,7 +71,18 @@ public class CMainTab extends CAbstractMainTab {
|
|||
* @since 2.0
|
||||
*/
|
||||
public static final String TAB_ID = "org.eclipse.cdt.dsf.gdb.launch.mainTab"; //$NON-NLS-1$
|
||||
|
||||
|
||||
private static final String CORE_FILE = LaunchMessages.getString("CMainTab.CoreFile_type"); //$NON-NLS-1$
|
||||
private static final String TRACE_FILE = LaunchMessages.getString("CMainTab.TraceFile_type"); //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Combo box to select which type of post mortem file should be used.
|
||||
* We currently support core files and trace files.
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
protected Combo fCoreTypeCombo;
|
||||
|
||||
private final boolean fDontCheckProgram;
|
||||
private final boolean fSpecifyCoreFile;
|
||||
private final boolean fIncludeBuildSettings;
|
||||
|
@ -151,7 +167,7 @@ public class CMainTab extends CAbstractMainTab {
|
|||
browseForBinaryButton.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent evt) {
|
||||
String text = handleBrowseButtonSelected();
|
||||
String text = handleBrowseButtonSelected(LaunchMessages.getString("CMaintab.Application_Selection")); //$NON-NLS-1$
|
||||
if (text != null) {
|
||||
fProgText.setText(text);
|
||||
}
|
||||
|
@ -160,6 +176,92 @@ public class CMainTab extends CAbstractMainTab {
|
|||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Overridden to add the possibility to choose a trace file as a post mortem debug file.
|
||||
*/
|
||||
/** @since 2.1 */
|
||||
@Override
|
||||
protected void createCoreFileGroup(Composite parent, int colSpan) {
|
||||
Composite coreComp = new Composite(parent, SWT.NONE);
|
||||
GridLayout coreLayout = new GridLayout();
|
||||
coreLayout.numColumns = 3;
|
||||
coreLayout.marginHeight = 0;
|
||||
coreLayout.marginWidth = 0;
|
||||
coreComp.setLayout(coreLayout);
|
||||
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
|
||||
gd.horizontalSpan = colSpan;
|
||||
coreComp.setLayoutData(gd);
|
||||
|
||||
Label comboLabel = new Label(coreComp, SWT.NONE);
|
||||
comboLabel.setText(LaunchMessages.getString("CMainTab.Post_mortem_file_type")); //$NON-NLS-1$
|
||||
comboLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
|
||||
|
||||
fCoreTypeCombo = new Combo(coreComp, SWT.READ_ONLY | SWT.DROP_DOWN);
|
||||
fCoreTypeCombo.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1));
|
||||
fCoreTypeCombo.add(CORE_FILE);
|
||||
fCoreTypeCombo.add(TRACE_FILE);
|
||||
|
||||
fCoreLabel = new Label(coreComp, SWT.NONE);
|
||||
fCoreLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
|
||||
fCoreText = new Text(coreComp, SWT.SINGLE | SWT.BORDER);
|
||||
gd = new GridData(GridData.FILL_HORIZONTAL);
|
||||
fCoreText.setLayoutData(gd);
|
||||
fCoreText.addModifyListener(new ModifyListener() {
|
||||
public void modifyText(ModifyEvent evt) {
|
||||
updateLaunchConfigurationDialog();
|
||||
}
|
||||
});
|
||||
|
||||
Button browseForCoreButton;
|
||||
browseForCoreButton = createPushButton(coreComp, LaunchMessages.getString("Launch.common.Browse_2"), null); //$NON-NLS-1$
|
||||
browseForCoreButton.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent evt) {
|
||||
String text;
|
||||
String coreType = getSelectedCoreType();
|
||||
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
|
||||
text = handleBrowseButtonSelected(LaunchMessages.getString("CMaintab.Core_Selection")); //$NON-NLS-1$
|
||||
} else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
|
||||
text = handleBrowseButtonSelected(LaunchMessages.getString("CMaintab.Trace_Selection")); //$NON-NLS-1$
|
||||
} else {
|
||||
assert false : "Unknown core file type"; //$NON-NLS-1$
|
||||
text = handleBrowseButtonSelected(LaunchMessages.getString("CMaintab.Core_Selection")); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (text != null) {
|
||||
fCoreText.setText(text);
|
||||
}
|
||||
updateLaunchConfigurationDialog();
|
||||
}
|
||||
});
|
||||
|
||||
fCoreTypeCombo.addSelectionListener(new SelectionListener() {
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
updateCoreFileLabel();
|
||||
updateLaunchConfigurationDialog();
|
||||
}
|
||||
|
||||
public void widgetDefaultSelected(SelectionEvent e) {
|
||||
}
|
||||
});
|
||||
fCoreTypeCombo.select(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a dialog that lets the user select a file.
|
||||
* This method allows to set the title of the dialog.
|
||||
*
|
||||
* @param title The title the dialog should show.
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
protected String handleBrowseButtonSelected(String title) {
|
||||
FileDialog fileDialog = new FileDialog(getShell(), SWT.NONE);
|
||||
fileDialog.setText(title);
|
||||
fileDialog.setFileName(fProgText.getText());
|
||||
return fileDialog.open();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
@ -177,12 +279,50 @@ public class CMainTab extends CAbstractMainTab {
|
|||
protected void updateCoreFromConfig(ILaunchConfiguration config) {
|
||||
if (fCoreText != null) {
|
||||
String coreName = EMPTY_STRING;
|
||||
String coreType = IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT;
|
||||
try {
|
||||
coreName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, EMPTY_STRING);
|
||||
coreType = config.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT);
|
||||
} catch (CoreException ce) {
|
||||
GdbUIPlugin.log(ce);
|
||||
}
|
||||
fCoreText.setText(coreName);
|
||||
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
|
||||
fCoreTypeCombo.setText(CORE_FILE);
|
||||
} else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
|
||||
fCoreTypeCombo.setText(TRACE_FILE);
|
||||
} else {
|
||||
assert false : "Unknown core file type"; //$NON-NLS-1$
|
||||
fCoreTypeCombo.setText(CORE_FILE);
|
||||
}
|
||||
updateCoreFileLabel();
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2.1 */
|
||||
protected String getSelectedCoreType() {
|
||||
int selectedIndex = fCoreTypeCombo.getSelectionIndex();
|
||||
if (fCoreTypeCombo.getItem(selectedIndex).equals(CORE_FILE)) {
|
||||
return IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE;
|
||||
} else if (fCoreTypeCombo.getItem(selectedIndex).equals(TRACE_FILE)) {
|
||||
return IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE;
|
||||
} else {
|
||||
assert false : "Unknown post mortem file type"; //$NON-NLS-1$
|
||||
return IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2.1 */
|
||||
protected void updateCoreFileLabel() {
|
||||
String coreType = getSelectedCoreType();
|
||||
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
|
||||
fCoreLabel.setText(LaunchMessages.getString("CMainTab.CoreFile_path")); //$NON-NLS-1$
|
||||
} else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
|
||||
fCoreLabel.setText(LaunchMessages.getString("CMainTab.TraceFile_path")); //$NON-NLS-1$
|
||||
} else {
|
||||
assert false : "Unknown post mortem file type"; //$NON-NLS-1$
|
||||
fCoreLabel.setText(LaunchMessages.getString("CMainTab.CoreFile_path")); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,6 +346,7 @@ public class CMainTab extends CAbstractMainTab {
|
|||
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, fProgText.getText());
|
||||
if (fCoreText != null) {
|
||||
config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, fCoreText.getText());
|
||||
config.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE, getSelectedCoreType());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,12 +491,12 @@ public class CMainTab extends CAbstractMainTab {
|
|||
// This allows to re-use the launch, with a different core file.
|
||||
if (!coreName.equals(EMPTY_STRING)) {
|
||||
if (coreName.equals(".") || coreName.equals("..")) { //$NON-NLS-1$ //$NON-NLS-2$
|
||||
setErrorMessage(LaunchMessages.getString("CMainTab.Core_does_not_exist")); //$NON-NLS-1$
|
||||
setErrorMessage(LaunchMessages.getString("CMainTab.File_does_not_exist")); //$NON-NLS-1$
|
||||
return false;
|
||||
}
|
||||
IPath corePath = new Path(coreName);
|
||||
if (!corePath.toFile().exists()) {
|
||||
setErrorMessage(LaunchMessages.getString("CMainTab.Core_does_not_exist")); //$NON-NLS-1$
|
||||
setErrorMessage(LaunchMessages.getString("CMainTab.File_does_not_exist")); //$NON-NLS-1$
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
|||
Export-Package: org.eclipse.cdt.dsf.gdb,
|
||||
org.eclipse.cdt.dsf.gdb.actions,
|
||||
org.eclipse.cdt.dsf.gdb.breakpoints,
|
||||
org.eclipse.cdt.dsf.gdb.internal.commands,
|
||||
org.eclipse.cdt.dsf.gdb.launching,
|
||||
org.eclipse.cdt.dsf.gdb.service,
|
||||
org.eclipse.cdt.dsf.gdb.service.command,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 Ericsson and others.
|
||||
* Copyright (c) 2008, 2010 Ericsson and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -90,6 +90,13 @@ public class IGDBLaunchConfigurationConstants {
|
|||
*/
|
||||
public static final String ATTR_DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND = GdbPlugin.PLUGIN_ID + ".UPDATE_THREADLIST_ON_SUSPEND"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Launch configuration attribute key. The value is a String specifying the type of post mortem launch.
|
||||
* @since 3.0
|
||||
*/
|
||||
public static final String ATTR_DEBUGGER_POST_MORTEM_TYPE = GdbPlugin.PLUGIN_ID + ".POST_MORTEM_TYPE"; //$NON-NLS-1$
|
||||
|
||||
|
||||
/**
|
||||
* Launch configuration attribute value. The key is ATTR_DEBUG_NAME.
|
||||
*/
|
||||
|
@ -131,4 +138,26 @@ public class IGDBLaunchConfigurationConstants {
|
|||
*/
|
||||
public static final boolean DEBUGGER_UPDATE_THREADLIST_ON_SUSPEND_DEFAULT = false;
|
||||
|
||||
/**
|
||||
* Possible attribute value for the key is ATTR_DEBUGGER_POST_MORTEM_TYPE.
|
||||
* Indicates a core file.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public static final String DEBUGGER_POST_MORTEM_CORE_FILE = "CORE_FILE"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Possible attribute value for the key is ATTR_DEBUGGER_POST_MORTEM_TYPE.
|
||||
* Indicates a trace data file.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public static final String DEBUGGER_POST_MORTEM_TRACE_FILE = "TRACE_FILE"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Launch configuration attribute value. The key is ATTR_DEBUGGER_POST_MORTEM_TYPE.
|
||||
* @since 3.0
|
||||
*/
|
||||
public static final String DEBUGGER_POST_MORTEM_TYPE_DEFAULT = DEBUGGER_POST_MORTEM_CORE_FILE;
|
||||
|
||||
}
|
||||
|
|
|
@ -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.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||
|
@ -29,6 +30,8 @@ import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
|||
import org.eclipse.cdt.dsf.gdb.actions.IConnect;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
|
||||
|
@ -370,31 +373,60 @@ public class FinalLaunchSequence extends Sequence {
|
|||
if (fSessionType == SessionType.CORE) {
|
||||
try {
|
||||
String coreFile = fLaunch.getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, ""); //$NON-NLS-1$
|
||||
|
||||
final String coreType = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT);
|
||||
if (coreFile.length() == 0) {
|
||||
new PromptForCoreJob(
|
||||
"Prompt for core file", //$NON-NLS-1$
|
||||
"Prompt for post mortem file", //$NON-NLS-1$
|
||||
new DataRequestMonitor<String>(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
String newCoreFile = getData();
|
||||
if (newCoreFile == null || newCoreFile.length()== 0) {
|
||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get core file path", null)); //$NON-NLS-1$
|
||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get post mortem file path", null)); //$NON-NLS-1$
|
||||
requestMonitor.done();
|
||||
} else {
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), newCoreFile),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
||||
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), newCoreFile),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
||||
} else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
|
||||
IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
|
||||
if (traceControl != null) {
|
||||
ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(fCommandControl.getContext(), ITraceTargetDMContext.class);
|
||||
traceControl.loadTraceData(targetDmc, newCoreFile, requestMonitor);
|
||||
} else {
|
||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null));
|
||||
requestMonitor.done();
|
||||
}
|
||||
} else {
|
||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null));
|
||||
requestMonitor.done();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).schedule();
|
||||
} else {
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), coreFile),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
||||
if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_CORE_FILE)) {
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMITargetSelectCore(fCommandControl.getContext(), coreFile),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
||||
} else if (coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE)) {
|
||||
IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class);
|
||||
if (traceControl != null) {
|
||||
ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(fCommandControl.getContext(), ITraceTargetDMContext.class);
|
||||
traceControl.loadTraceData(targetDmc, coreFile, requestMonitor);
|
||||
} else {
|
||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Tracing not supported", null));
|
||||
requestMonitor.done();
|
||||
}
|
||||
} else {
|
||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Invalid post-mortem type", null));
|
||||
requestMonitor.done();
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get core file path", e)); //$NON-NLS-1$
|
||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get post mortem file path", e));
|
||||
requestMonitor.done();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2010 QNX Software Systems and others.
|
||||
* Copyright (c) 2008, 2010 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -10,6 +10,7 @@
|
|||
* Windriver and Ericsson - Updated for DSF
|
||||
* IBM Corporation
|
||||
* Ericsson - Added support for Mac OS
|
||||
* Ericsson - Added support for post-mortem trace files
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.gdb.launching;
|
||||
|
||||
|
@ -57,7 +58,10 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
|
|||
|
||||
private final static String NON_STOP_FIRST_VERSION = "6.8.50"; //$NON-NLS-1$
|
||||
private boolean isNonStopSession = false;
|
||||
|
||||
|
||||
private final static String TRACING_FIRST_VERSION = "7.1.50"; //$NON-NLS-1$
|
||||
private boolean fIsPostMortemTracingSession;
|
||||
|
||||
@Override
|
||||
public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
|
||||
org.eclipse.cdt.launch.LaunchUtils.enableActivity("org.eclipse.cdt.debug.dsfgdbActivity", true); //$NON-NLS-1$
|
||||
|
@ -129,6 +133,10 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
|
|||
throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Non-stop mode is only supported starting with GDB " + NON_STOP_FIRST_VERSION, null)); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (fIsPostMortemTracingSession && !isPostMortemTracingSupported(gdbVersion)) {
|
||||
throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Post-mortem tracing is only supported starting with GDB " + TRACING_FIRST_VERSION, null)); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
launch.setServiceFactory(newServiceFactory(gdbVersion));
|
||||
|
||||
// Create and invoke the launch sequence to create the debug control and services
|
||||
|
@ -254,6 +262,18 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
|
|||
return false;
|
||||
}
|
||||
|
||||
private boolean isPostMortemTracingSession(ILaunchConfiguration config) {
|
||||
SessionType sessionType = LaunchUtils.getSessionType(config);
|
||||
if (sessionType == SessionType.CORE) {
|
||||
try {
|
||||
String coreType = config.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT);
|
||||
return coreType.equals(IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TRACE_FILE);
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) throws CoreException {
|
||||
|
@ -271,6 +291,7 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
|
|||
// the source lookup adapter.
|
||||
|
||||
isNonStopSession = isNonStopSession(configuration);
|
||||
fIsPostMortemTracingSession = isPostMortemTracingSession(configuration);
|
||||
|
||||
GdbLaunch launch = new GdbLaunch(configuration, mode, null);
|
||||
launch.initialize();
|
||||
|
@ -300,7 +321,22 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private boolean isPostMortemTracingSupported(String version) {
|
||||
if (version.contains(LaunchUtils.MACOS_GDB_MARKER)) {
|
||||
// Mac OS's GDB does not support post-mortem tracing
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TRACING_FIRST_VERSION.compareTo(version) <= 0
|
||||
// This feature will be available for GDB 7.2. But until that GDB is itself available
|
||||
// there is a pre-release that has a version of 6.8.50.20090414
|
||||
|| "6.8.50.20090414".equals(version)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// A subclass can override this method and provide its own ServiceFactory.
|
||||
protected IDsfDebugServicesFactory newServiceFactory(String version) {
|
||||
|
||||
|
|
|
@ -86,16 +86,23 @@ CMainTab.Project_not_specified=Project not specified
|
|||
CMainTab.Program_not_specified=Program not specified
|
||||
CMainTab.Project_must_be_opened=Project must be opened
|
||||
CMainTab.Program_does_not_exist=Program does not exist
|
||||
CMainTab.Core_does_not_exist=Core file does not exist
|
||||
CMainTab.File_does_not_exist=File does not exist
|
||||
CMainTab.Main=Main
|
||||
CMainTab.&ProjectColon=&Project:
|
||||
CMainTab.C/C++_Application=C/C++ Application:
|
||||
CMainTab.CoreFile_type=Core file
|
||||
CMainTab.TraceFile_type=Trace file
|
||||
CMainTab.CoreFile_path=Core file (leave blank to trigger prompt):
|
||||
CMainTab.TraceFile_path=Trace data file (leave blank to trigger prompt):
|
||||
CMainTab.Search...=Searc&h Project...
|
||||
CMainTab.Choose_program_to_run=Choose a &program to run:
|
||||
CMainTab.Choose_program_to_run_from_NAME=Choose a program to run from {0}:
|
||||
CMainTab.UseTerminal=Connect process input && output to a terminal.
|
||||
CMainTab.Program_is_not_a_recongnized_executable=Program is not a recognized executable.
|
||||
CMaintab.Application_Selection=Application Selection
|
||||
CMaintab.Core_Selection=Core File Selection
|
||||
CMaintab.Trace_Selection=Trace File Selection
|
||||
CMainTab.Post_mortem_file_type=Post Mortem file type:
|
||||
|
||||
CDebuggerTab.Advanced_Options_Dialog_Title=Advanced Options
|
||||
CDebuggerTab.Stop_at_main_on_startup=Stop on startup at:
|
||||
|
|
|
@ -782,6 +782,18 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
}
|
||||
|
||||
private IMIContainerDMContext[] makeContainerDMCs(ICommandControlDMContext controlDmc, IThreadGroupInfo[] groups) {
|
||||
// This is a workaround for post-mortem tracing because the early GDB release
|
||||
// does not report a process when we do -list-thread-group
|
||||
// GDB 7.2 will properly report the process so this
|
||||
// code can be removed when GDB 7.2 is released
|
||||
// START OF WORKAROUND
|
||||
if (groups.length == 0 && fBackend.getSessionType() == SessionType.CORE) {
|
||||
String groupId = MIProcesses.UNIQUE_GROUP_ID;
|
||||
IProcessDMContext processDmc = createProcessContext(controlDmc, groupId);
|
||||
return new IMIContainerDMContext[] {createContainerContext(processDmc, groupId)};
|
||||
}
|
||||
// END OF WORKAROUND to be removed when GDB 7.2 is available
|
||||
|
||||
IMIContainerDMContext[] containerDmcs = new IMIContainerDMContext[groups.length];
|
||||
for (int i = 0; i < groups.length; i++) {
|
||||
String groupId = groups[i].getGroupId();
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
|||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||
|
@ -80,6 +81,14 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
|||
private boolean fReverseSupported = true;
|
||||
private boolean fReverseStepping = false;
|
||||
private boolean fReverseModeEnabled = false;
|
||||
|
||||
/**
|
||||
* This variable allows us to know if run control operation
|
||||
* should be enabled or disabled. Run control operations are
|
||||
* always enabled except when dealing with post-mortem debug
|
||||
* session, or when visualizing tracepoints.
|
||||
*/
|
||||
private boolean fRunControlOperationsEnabled = true;
|
||||
|
||||
private RunToLineActiveOperation fRunToLineActiveOperation = null;
|
||||
|
||||
|
@ -105,6 +114,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
|||
|
||||
if (fGdb.getSessionType() == SessionType.CORE) {
|
||||
// No execution for core files, so no support for reverse
|
||||
fRunControlOperationsEnabled = false;
|
||||
fReverseSupported = false;
|
||||
}
|
||||
|
||||
|
@ -176,7 +186,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
|||
*/
|
||||
@Override
|
||||
public void canResume(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
||||
if (fGdb.getSessionType() == SessionType.CORE) {
|
||||
if (fRunControlOperationsEnabled == false) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
|
@ -189,7 +199,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
|||
*/
|
||||
@Override
|
||||
public void canSuspend(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
||||
if (fGdb.getSessionType() == SessionType.CORE) {
|
||||
if (fRunControlOperationsEnabled == false) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
|
@ -202,7 +212,7 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
|||
*/
|
||||
@Override
|
||||
public void canStep(final IExecutionDMContext context, StepType stepType, final DataRequestMonitor<Boolean> rm) {
|
||||
if (fGdb.getSessionType() == SessionType.CORE) {
|
||||
if (fRunControlOperationsEnabled == false) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
|
@ -591,6 +601,16 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
|||
|
||||
super.eventDispatched(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.0
|
||||
*/
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
|
||||
// We have started looking at trace records. We can no longer
|
||||
// do run control operations.
|
||||
fRunControlOperationsEnabled = false;
|
||||
}
|
||||
|
||||
/** @since 2.0 */
|
||||
public void setReverseModeEnabled(boolean enabled) {
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
|||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.service.command.events.MITracepointSelectedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||
|
@ -141,6 +142,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
|||
public StateChangeReason getReason() {
|
||||
if (getMIEvent() instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
||||
return StateChangeReason.EVENT_BREAKPOINT;
|
||||
} else if (getMIEvent() instanceof MITracepointSelectedEvent) { // must precede MIBreakpointHitEvent
|
||||
return StateChangeReason.UNKNOWN; // Don't display anything here, the details will take care of it
|
||||
} else if (getMIEvent() instanceof MIBreakpointHitEvent) {
|
||||
return StateChangeReason.BREAKPOINT;
|
||||
} else if (getMIEvent() instanceof MISteppingRangeEvent) {
|
||||
|
@ -162,6 +165,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo
|
|||
MIStoppedEvent event = getMIEvent();
|
||||
if (event instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
||||
return ((MICatchpointHitEvent)event).getReason();
|
||||
} else if (event instanceof MITracepointSelectedEvent) { // must precede MIBreakpointHitEvent
|
||||
return ((MITracepointSelectedEvent)event).getReason();
|
||||
} else if (event instanceof MISharedLibEvent) {
|
||||
return ((MISharedLibEvent)event).getLibrary();
|
||||
} else if (event instanceof MISignalEvent) {
|
||||
|
|
|
@ -13,20 +13,31 @@ package org.eclipse.cdt.dsf.gdb.service;
|
|||
import java.util.Hashtable;
|
||||
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Immutable;
|
||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
|
||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.service.command.events.MITracepointSelectedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIResultRecord;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceFindInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceListVariablesInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceListVariablesInfo.MITraceVariableInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStatusInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStopInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceListVariablesInfo.MITraceVariableInfo;
|
||||
import org.eclipse.cdt.dsf.service.AbstractDsfService;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
|
@ -35,119 +46,104 @@ import org.eclipse.debug.core.ILaunchConfiguration;
|
|||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
* This class implements the ITraceControl interface which gives access
|
||||
* This class implements the IGDBTraceControl interface which gives access
|
||||
* to the debugger's tracing functionality.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTraceControl, ICachingService {
|
||||
public class GDBTraceControl_7_2 extends AbstractDsfService implements IGDBTraceControl, ICachingService {
|
||||
|
||||
// @Immutable
|
||||
// private static final class MITraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
|
||||
//
|
||||
// // The trace record reference
|
||||
// private final int fReference;
|
||||
//
|
||||
// /**
|
||||
// * @param session the DsfSession for this service
|
||||
// * @param parents the parent contexts
|
||||
// * @param reference the trace record reference
|
||||
// */
|
||||
// public MITraceRecordDMContext(DsfSession session, IDMContext[] parents, int reference) {
|
||||
// super(session.getId(), parents);
|
||||
// fReference = reference;
|
||||
// }
|
||||
//
|
||||
// public int getReference() {
|
||||
// return fReference;
|
||||
// }
|
||||
//
|
||||
// /* (non-Javadoc)
|
||||
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
|
||||
// */
|
||||
// @Override
|
||||
// public boolean equals(Object obj) {
|
||||
// return baseEquals(obj) && (fReference == ((MITraceRecordDMContext) obj).fReference);
|
||||
// }
|
||||
//
|
||||
// /* (non-Javadoc)
|
||||
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
|
||||
// */
|
||||
// @Override
|
||||
// public int hashCode() {
|
||||
// return baseHashCode() + fReference;
|
||||
// }
|
||||
//
|
||||
// /* (non-Javadoc)
|
||||
// * @see java.lang.Object#toString()
|
||||
// */
|
||||
// @Override
|
||||
// public String toString() {
|
||||
// return baseToString() + ".reference(" + fReference + ")"; //$NON-NLS-1$//$NON-NLS-2$
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Trace record context used to indicate that there is no current trace record selected.
|
||||
// */
|
||||
// @Immutable
|
||||
// private static final class InvalidTraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
|
||||
//
|
||||
// /**
|
||||
// * @param session the DsfSession for this service
|
||||
// * @param parents the parent contexts
|
||||
// * @param reference the trace record reference
|
||||
// */
|
||||
// public InvalidTraceRecordDMContext(DsfSession session, IDMContext[] parents) {
|
||||
// super(session.getId(), parents);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /* (non-Javadoc)
|
||||
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
|
||||
// */
|
||||
// @Override
|
||||
// public boolean equals(Object obj) {
|
||||
// return baseEquals(obj);
|
||||
// }
|
||||
//
|
||||
// /* (non-Javadoc)
|
||||
// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
|
||||
// */
|
||||
// @Override
|
||||
// public int hashCode() {
|
||||
// return baseHashCode();
|
||||
// }
|
||||
//
|
||||
// /* (non-Javadoc)
|
||||
// * @see java.lang.Object#toString()
|
||||
// */
|
||||
// @Override
|
||||
// public String toString() {
|
||||
// return baseToString() + ".noTraceRecord"; //$NON-NLS-1$
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Immutable
|
||||
// private static class MITraceRecordDMData implements ITraceRecordDMData {
|
||||
// private final String fData;
|
||||
//
|
||||
// public MITraceRecordDMData(String data) {
|
||||
// fData = data;
|
||||
// }
|
||||
//
|
||||
// public String getData() { return fData; }
|
||||
// }
|
||||
@Immutable
|
||||
protected static final class MITraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
|
||||
|
||||
// The trace record reference
|
||||
private final int fReference;
|
||||
|
||||
/**
|
||||
* @param session the DsfSession for this service
|
||||
* @param parents the parent contexts
|
||||
* @param reference the trace record reference
|
||||
*/
|
||||
public MITraceRecordDMContext(DsfSession session, ITraceTargetDMContext parent, int reference) {
|
||||
super(session.getId(), new IDMContext[] { parent });
|
||||
fReference = reference;
|
||||
}
|
||||
|
||||
public int getReference() {
|
||||
return fReference;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return baseEquals(obj) && (fReference == ((MITraceRecordDMContext) obj).fReference);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return baseHashCode() + fReference;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return baseToString() + ".reference(" + fReference + ")"; //$NON-NLS-1$//$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trace record context used to indicate that there is no current trace record selected.
|
||||
*/
|
||||
@Immutable
|
||||
protected static final class InvalidTraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext {
|
||||
|
||||
/**
|
||||
* @param session the DsfSession for this service
|
||||
* @param parents the parent contexts
|
||||
* @param reference the trace record reference
|
||||
*/
|
||||
public InvalidTraceRecordDMContext(DsfSession session, ITraceTargetDMContext parent) {
|
||||
super(session.getId(), new IDMContext[] { parent });
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return baseEquals(obj);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return baseHashCode();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return baseToString() + ".noTraceRecord"; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
private class TraceVariableDMData implements ITraceVariableDMData {
|
||||
private String fName;
|
||||
private String fValue;
|
||||
private String fInitialValue;
|
||||
|
||||
public TraceVariableDMData(String name, String value) {
|
||||
this(name, value, null);
|
||||
}
|
||||
|
||||
public TraceVariableDMData(String name, String initial, String value) {
|
||||
fName = name;
|
||||
fInitialValue = initial;
|
||||
|
@ -245,6 +241,20 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
return "\nTracing is not supported\n";
|
||||
}
|
||||
|
||||
if (fBackend.getSessionType() == SessionType.CORE) {
|
||||
str += "Off-line trace visualization\n";
|
||||
} else {
|
||||
str += "Tracing with live execution\n";
|
||||
}
|
||||
|
||||
if (fCurrentRecordDmc instanceof MITraceRecordDMContext) {
|
||||
str += "Looking at trace frame " +
|
||||
((MITraceRecordDMContext)fCurrentRecordDmc).getReference() +
|
||||
", tracepoint " + fTracepointIndexForTraceRecord + "\n\n";
|
||||
} else {
|
||||
str += "Not currently looking at any trace frame\n\n";
|
||||
}
|
||||
|
||||
str += "Tracing is currently" + (!fTracingActive ? " not":"") + " active\n";
|
||||
str += "Buffer contains " + fNumberOfCollectedFrames + " trace frame" +
|
||||
(fNumberOfCollectedFrames>1?"s":"") + "\n";//" (out of ? created in total)\n";
|
||||
|
@ -270,7 +280,10 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
} else {
|
||||
str += " unknow reason";
|
||||
}
|
||||
str += "\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
return str;
|
||||
}
|
||||
|
@ -304,25 +317,27 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
}
|
||||
}
|
||||
|
||||
// private static class TraceRecordSelectedChangedEvent extends AbstractDMEvent<ITraceRecordDMContext>
|
||||
// implements ITraceRecordSelectedChangedDMEvent {
|
||||
// public TraceRecordSelectedChangedEvent(ITraceRecordDMContext context) {
|
||||
// super(context);
|
||||
// }
|
||||
// }
|
||||
public static class TraceRecordSelectedChangedEvent extends AbstractDMEvent<ITraceRecordDMContext>
|
||||
implements ITraceRecordSelectedChangedDMEvent {
|
||||
public TraceRecordSelectedChangedEvent(ITraceRecordDMContext context) {
|
||||
super(context);
|
||||
}
|
||||
}
|
||||
|
||||
private CommandCache fTraceCache;
|
||||
private ICommandControlService fConnection;
|
||||
private CommandFactory fCommandFactory;
|
||||
|
||||
// private ITraceRecordDMContext fCurrentRecordDmc = null;
|
||||
|
||||
private boolean fIsTracingActive = false;
|
||||
private boolean fIsTracingSupported = false;
|
||||
private int fTraceRecordsStored = 0;
|
||||
private IGDBBackend fBackend;
|
||||
|
||||
private ITraceRecordDMContext fCurrentRecordDmc;
|
||||
private int fTracepointIndexForTraceRecord;
|
||||
|
||||
public GDBTraceControl_7_1(DsfSession session, ILaunchConfiguration config) {
|
||||
private boolean fIsTracingActive;
|
||||
private boolean fIsTracingCurrentlySupported;
|
||||
private boolean fIsTracingFeatureAvailable = true;
|
||||
private int fTraceRecordsStored;
|
||||
|
||||
public GDBTraceControl_7_2(DsfSession session, ILaunchConfiguration config) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
|
@ -351,10 +366,6 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
* initialization is done.
|
||||
*/
|
||||
private void doInitialize(RequestMonitor requestMonitor) {
|
||||
|
||||
// Register to receive service events for this session.
|
||||
// getSession().addServiceEventListener(this, null);
|
||||
|
||||
// Register this service.
|
||||
register(new String[] {IGDBTraceControl.class.getName()},
|
||||
new Hashtable<String, String>());
|
||||
|
@ -364,6 +375,7 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
fTraceCache = new CommandCache(getSession(), fConnection);
|
||||
fTraceCache.setContextAvailable(fConnection.getContext(), true);
|
||||
|
||||
fBackend = getServicesTracker().getService(IGDBBackend.class);
|
||||
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
|
||||
|
||||
requestMonitor.done();
|
||||
|
@ -379,7 +391,6 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
@Override
|
||||
public void shutdown(RequestMonitor requestMonitor) {
|
||||
unregister();
|
||||
// getSession().removeServiceEventListener(this);
|
||||
super.shutdown(requestMonitor);
|
||||
}
|
||||
|
||||
|
@ -397,8 +408,27 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fIsTracingCurrentlySupported == false) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fBackend.getSessionType() == SessionType.CORE) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fCurrentRecordDmc != null) {
|
||||
// We are visualizing data, no more tracing possible.
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
rm.setData(fIsTracingSupported);
|
||||
rm.setData(true);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
|
@ -438,6 +468,25 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fIsTracingCurrentlySupported == false) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fBackend.getSessionType() == SessionType.CORE) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fCurrentRecordDmc != null) {
|
||||
// We are visualizing data, no more tracing possible.
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
isTracing(context, rm);
|
||||
}
|
||||
|
@ -488,11 +537,17 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
return;
|
||||
}
|
||||
|
||||
if (fBackend.getSessionType() == SessionType.CORE) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Although tracing can be automatically stopped on the target, we
|
||||
// don't go to the backend for this call, or we would make too many calls
|
||||
// Instead, we can use our buffered state; we simply won't know about an
|
||||
// automatic stop until a forced refresh. (Note that the MI notification
|
||||
// about automatic stops, is not available until GDB 7.1 is released)
|
||||
// about automatic stops, is not available until GDB 7.2 is released)
|
||||
rm.setData(fIsTracingActive);
|
||||
rm.done();
|
||||
}
|
||||
|
@ -503,21 +558,45 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fIsTracingCurrentlySupported == false) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fBackend.getSessionType() == SessionType.CORE) {
|
||||
rm.setData(false);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
rm.setData(fTraceRecordsStored > 0);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
public void saveTraceData(ITraceTargetDMContext context, String file, boolean remoteSave, RequestMonitor rm) {
|
||||
public void saveTraceData(final ITraceTargetDMContext context, final String file,
|
||||
final boolean remoteSave, final RequestMonitor rm) {
|
||||
if (context == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
fConnection.queueCommand(
|
||||
fCommandFactory.createMITraceSave(context, file, remoteSave),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||
canSaveTraceData(context, new DataRequestMonitor<Boolean>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
if (!getData()) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Cannot save trace data", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
fConnection.queueCommand(
|
||||
fCommandFactory.createMITraceSave(context, file, remoteSave),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void canLoadTraceData(ITraceTargetDMContext context, DataRequestMonitor<Boolean> rm) {
|
||||
|
@ -527,20 +606,44 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
return;
|
||||
}
|
||||
|
||||
// If this service has been instantiated, it means we support loading trace data.
|
||||
// Unlike the other operations, loading trace data does not require any GDB special state
|
||||
// (like being connected to a target)
|
||||
rm.setData(true);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
public void loadTraceData(ITraceTargetDMContext context, String file, RequestMonitor rm) {
|
||||
public void loadTraceData(final ITraceTargetDMContext context, final String file, final RequestMonitor rm) {
|
||||
if (context == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
fConnection.queueCommand(
|
||||
fCommandFactory.createMITargetSelectTFile(context, file),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||
canLoadTraceData(context, new DataRequestMonitor<Boolean>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
if (!getData()) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Cannot load trace data", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
fConnection.queueCommand(
|
||||
fCommandFactory.createMITargetSelectTFile(context, file),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
fIsTracingCurrentlySupported = true;
|
||||
// Workaround for GDB pre-release where we don't get the details
|
||||
// of the frame when we load a trace file.
|
||||
// To get around this, we can force a select of record 0
|
||||
ITraceRecordDMContext initialRecord = createTraceRecordContext(context, 0);
|
||||
selectTraceRecord(initialRecord, rm);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void getTraceStatus(final ITraceTargetDMContext context, final DataRequestMonitor<ITraceStatusDMData> rm) {
|
||||
|
@ -550,19 +653,31 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
return;
|
||||
}
|
||||
|
||||
if (fIsTracingFeatureAvailable == false) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
fConnection.queueCommand(
|
||||
fCommandFactory.createMITraceStatus(context),
|
||||
new DataRequestMonitor<MITraceStatusInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleError() {
|
||||
// The MI command
|
||||
fIsTracingFeatureAvailable = false;
|
||||
super.handleError();
|
||||
}
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
MITraceStatusInfo info = getData();
|
||||
|
||||
if (fIsTracingSupported != info.isTracingSupported()) {
|
||||
fIsTracingSupported = info.isTracingSupported();
|
||||
getSession().dispatchEvent(new TracingSupportedChangeEvent(context, fIsTracingSupported), getProperties());
|
||||
if (fIsTracingCurrentlySupported != info.isTracingSupported()) {
|
||||
fIsTracingCurrentlySupported = info.isTracingSupported();
|
||||
getSession().dispatchEvent(new TracingSupportedChangeEvent(context, fIsTracingCurrentlySupported), getProperties());
|
||||
}
|
||||
|
||||
if (fIsTracingSupported) {
|
||||
if (fIsTracingCurrentlySupported) {
|
||||
// Update the tracing state in case it was stopped by the backend
|
||||
if (fIsTracingActive != info.isTracingActive()) {
|
||||
fIsTracingActive = info.isTracingActive();
|
||||
|
@ -609,6 +724,12 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
return;
|
||||
}
|
||||
|
||||
if (fIsTracingCurrentlySupported == false) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (varValue == null) {
|
||||
fConnection.queueCommand(
|
||||
fCommandFactory.createMITraceDefineVariable(context, varName),
|
||||
|
@ -628,6 +749,12 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
return;
|
||||
}
|
||||
|
||||
if (fIsTracingCurrentlySupported == false) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// It may be possible to cache this call, if we can figure out that all the cases
|
||||
// where to data can change, to clear the cache in those cases
|
||||
fConnection.queueCommand(
|
||||
|
@ -648,125 +775,173 @@ public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTrace
|
|||
}
|
||||
});
|
||||
}
|
||||
//
|
||||
// /**
|
||||
// * Create a trace record context
|
||||
// */
|
||||
// public ITraceRecordDMContext createTraceRecordContext(IDMContext ctx, int index) {
|
||||
// return new MITraceRecordDMContext(getSession(), new IDMContext[] { ctx }, index);
|
||||
// }
|
||||
//
|
||||
// public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx) {
|
||||
// if (ctx instanceof InvalidTraceRecordDMContext) {
|
||||
// // No specified context, so we return the first record context
|
||||
// return new MITraceRecordDMContext(getSession(), new IDMContext[] { ctx }, 0);
|
||||
// }
|
||||
// if (ctx instanceof MITraceRecordDMContext) {
|
||||
// return new MITraceRecordDMContext(getSession(),
|
||||
// ctx.getParents(),
|
||||
// ((MITraceRecordDMContext)ctx).getReference() + 1);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx) {
|
||||
// if (ctx instanceof MITraceRecordDMContext) {
|
||||
// return new MITraceRecordDMContext(getSession(),
|
||||
// ctx.getParents(),
|
||||
// ((MITraceRecordDMContext)ctx).getReference() - 1);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm) {
|
||||
// if (fCurrentRecordDmc == null) {
|
||||
// drm.setData(new InvalidTraceRecordDMContext(getSession(), new IDMContext[] { context }));
|
||||
// } else {
|
||||
// drm.setData(fCurrentRecordDmc);
|
||||
// }
|
||||
// drm.done();
|
||||
// }
|
||||
//
|
||||
// public void selectTraceRecord(final ITraceRecordDMContext context, final RequestMonitor rm) {
|
||||
// if (context instanceof MITraceRecordDMContext) {
|
||||
// ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(context, ITraceTargetDMContext.class);
|
||||
// fConnection.queueCommand(
|
||||
// new MITraceFind(targetDmc, ((MITraceRecordDMContext)context).getReference()),
|
||||
// new DataRequestMonitor<MITraceFindInfo>(getExecutor(), rm) {
|
||||
// @Override
|
||||
// protected void handleSuccess() {
|
||||
// if (getData().isFound() == false) {
|
||||
// rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Could not find trace record", null)); //$NON-NLS-1$
|
||||
// } else {
|
||||
// fCurrentRecordDmc = context;
|
||||
// getSession().dispatchEvent(new TraceRecordSelectedChangedEvent(context), getProperties());
|
||||
// }
|
||||
// rm.done();
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid trace record context.", null)); //$NON-NLS-1$
|
||||
// rm.done();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void setDefaultCollect(ITraceTargetDMContext context, String[] expressions, RequestMonitor rm) {
|
||||
// fConnection.queueCommand(
|
||||
// new MIGDBSetDefaultCollect(context, expressions),
|
||||
// new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||
// }
|
||||
//
|
||||
// public void getDefaultCollect(ITraceTargetDMContext context, final DataRequestMonitor<String> rm) {
|
||||
// // should use a cache and have it reset in setDefaultCommands
|
||||
// fConnection.queueCommand(
|
||||
// new MIGDBShowDefaultCollect(context),
|
||||
// new DataRequestMonitor<MIGDBShowInfo>(getExecutor(), rm) {
|
||||
// @Override
|
||||
// protected void handleSuccess() {
|
||||
// rm.setData(getData().getValue());
|
||||
// rm.done();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public void getTraceRecordData(ITraceRecordDMContext context,
|
||||
// DataRequestMonitor<ITraceRecordDMData> rm) {
|
||||
// assert false;
|
||||
// }
|
||||
//
|
||||
// public void saveTracepoints(ITraceTargetDMContext context,
|
||||
// String file,
|
||||
// RequestMonitor rm) {
|
||||
// assert false;
|
||||
// }
|
||||
//
|
||||
// public void loadTracepoints(ITraceTargetDMContext context,
|
||||
// String file,
|
||||
// RequestMonitor rm) {
|
||||
// assert false;
|
||||
// }
|
||||
//
|
||||
// public void saveTraceData(ITraceTargetDMContext context,
|
||||
// String file,
|
||||
// RequestMonitor rm) {
|
||||
// assert false;
|
||||
// }
|
||||
//
|
||||
// public void loadTraceData(ITraceTargetDMContext context,
|
||||
// String file,
|
||||
// RequestMonitor rm) {
|
||||
// assert false;
|
||||
// }
|
||||
//
|
||||
// public void createTraceVariable(IExecutionDMContext context,
|
||||
// RequestMonitor rm) {
|
||||
// assert false;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Create a trace record context
|
||||
*/
|
||||
public ITraceRecordDMContext createTraceRecordContext(ITraceTargetDMContext ctx, int index) {
|
||||
return new MITraceRecordDMContext(getSession(), ctx, index);
|
||||
}
|
||||
|
||||
public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx) {
|
||||
ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(ctx, ITraceTargetDMContext.class);
|
||||
if (ctx instanceof InvalidTraceRecordDMContext) {
|
||||
// No specified context, so we return the context for the first
|
||||
return new MITraceRecordDMContext(getSession(), targetDmc, 0);
|
||||
}
|
||||
if (ctx instanceof MITraceRecordDMContext) {
|
||||
int recordIndex = ((MITraceRecordDMContext)ctx).getReference();
|
||||
recordIndex++;
|
||||
if (recordIndex == fTraceRecordsStored) {
|
||||
// Loop back to the front
|
||||
recordIndex = 0;
|
||||
}
|
||||
return new MITraceRecordDMContext(getSession(),
|
||||
targetDmc,
|
||||
recordIndex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx) {
|
||||
if (ctx instanceof MITraceRecordDMContext) {
|
||||
ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(ctx, ITraceTargetDMContext.class);
|
||||
int recordIndex = ((MITraceRecordDMContext)ctx).getReference();
|
||||
if (recordIndex == 0) {
|
||||
// Loop back to the end
|
||||
recordIndex = fTraceRecordsStored; // The last index of a trace record (zero-based)
|
||||
}
|
||||
recordIndex--;
|
||||
return new MITraceRecordDMContext(getSession(),
|
||||
targetDmc,
|
||||
recordIndex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm) {
|
||||
if (fCurrentRecordDmc == null) {
|
||||
drm.setData(new InvalidTraceRecordDMContext(getSession(), context));
|
||||
} else {
|
||||
drm.setData(fCurrentRecordDmc);
|
||||
}
|
||||
drm.done();
|
||||
}
|
||||
|
||||
public void selectTraceRecord(final ITraceRecordDMContext context, final RequestMonitor rm) {
|
||||
if (fIsTracingCurrentlySupported == false) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Tracing not supported", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (context instanceof MITraceRecordDMContext) {
|
||||
ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(context, ITraceTargetDMContext.class);
|
||||
fConnection.queueCommand(
|
||||
fCommandFactory.createMITraceFind(targetDmc, ((MITraceRecordDMContext)context).getReference()),
|
||||
new DataRequestMonitor<MITraceFindInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
if (getData().isFound() == false) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Could not find trace record", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
fCurrentRecordDmc = context;
|
||||
fTracepointIndexForTraceRecord = getData().getTraceRecord().getTracepointId();
|
||||
|
||||
// This event will indicate to the other services that we are visualizing trace data.
|
||||
getSession().dispatchEvent(new TraceRecordSelectedChangedEvent(context), getProperties());
|
||||
|
||||
// We could rely on the TraceRecordSelectedChangedEvent to update all the views, but this
|
||||
// would require a lot of changes.
|
||||
// Notice that looking at a new trace record should behave in the same manner
|
||||
// as when the debugger suspends during normal execution; therefore we can simply
|
||||
// trigger an MIStoppedEvent, as if reported by GDB. Note that we do this already for
|
||||
// cases where GDB is missing such a event (like older versions of GDB when using a CLI command)
|
||||
IMIProcesses procService = getServicesTracker().getService(IMIProcesses.class);
|
||||
if (procService == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
final MIResultRecord rr = getData().getMIOutput().getMIResultRecord();
|
||||
if (rr == null) {
|
||||
assert false;
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// First find the process we are using.
|
||||
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(context, ICommandControlDMContext.class);
|
||||
procService.getProcessesBeingDebugged(
|
||||
controlDmc,
|
||||
new DataRequestMonitor<IDMContext[]>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
assert getData() != null;
|
||||
assert getData().length == 1;
|
||||
|
||||
if (getData() == null || getData().length < 1) {
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Choose the first process for now, until gdb can tell
|
||||
// us which process the trace record is associated with.
|
||||
// Or maybe GDB already tells us by only reporting a single
|
||||
// process?
|
||||
IContainerDMContext processContainerDmc = (IContainerDMContext)(getData()[0]);
|
||||
|
||||
// Now find the proper thread. We must do this hear because in post-mortem debugging
|
||||
// we cannot rely on MIRunControl using 'thread', as it will fail
|
||||
IMIProcesses procService = getServicesTracker().getService(IMIProcesses.class);
|
||||
if (procService == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
procService.getProcessesBeingDebugged(
|
||||
processContainerDmc,
|
||||
new DataRequestMonitor<IDMContext[]>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
assert getData() != null;
|
||||
assert getData().length == 1;
|
||||
|
||||
if (getData() == null || getData().length < 1) {
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
IExecutionDMContext execDmc = (IExecutionDMContext)getData()[0];
|
||||
MIEvent<?> event = MITracepointSelectedEvent.parse(execDmc, rr.getToken(), rr.getMIResults());
|
||||
getSession().dispatchEvent(event, getProperties());
|
||||
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid trace record context.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void getTraceRecordData(ITraceRecordDMContext context, DataRequestMonitor<ITraceRecordDMData> rm) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Not implemented.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
}
|
||||
|
||||
public void flushCache(IDMContext context) {
|
||||
fTraceCache.reset(context);
|
||||
}
|
||||
|
||||
}
|
|
@ -43,7 +43,8 @@ import org.eclipse.debug.core.ILaunchConfiguration;
|
|||
public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
||||
|
||||
// This should eventually be "7.0" once GDB 7.0 is released
|
||||
private static final String GDB_7_0_VERSION = "6.8.50.20090218"; //$NON-NLS-1$
|
||||
private static final String GDB_7_0_VERSION = "6.8.50.20090218"; //$NON-NLS-1$
|
||||
private static final String GDB_7_2_VERSION = "7.1.50"; //$NON-NLS-1$
|
||||
|
||||
private final String fVersion;
|
||||
|
||||
|
@ -163,12 +164,15 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
|
|||
|
||||
/** @since 3.0 */
|
||||
protected IGDBTraceControl createTraceControlService(DsfSession session, ILaunchConfiguration config) {
|
||||
// This service is available for GDB 7.1. But until that GDB is itself available
|
||||
// This service is available for GDB 7.2. But until that GDB is itself available
|
||||
// there is a pre-release that has a version of 6.8.50.20090414
|
||||
if ("6.8.50.20090414".compareTo(fVersion) <= 0) {
|
||||
return new GDBTraceControl_7_1(session, config);
|
||||
if (GDB_7_2_VERSION.compareTo(fVersion) <= 0 || "6.8.50.20090414".equals(fVersion)) { //$NON-NLS-1$
|
||||
return new GDBTraceControl_7_2(session, config);
|
||||
}
|
||||
// There is no implementation of the TraceControl service before GDB 7.1
|
||||
// There is currently no implementation of the TraceControl service before GDB 7.2
|
||||
// It could be done with restricted functionality for GDB 7.1 and maybe even 7.0
|
||||
// but the service would have to be properly coded, as some MI commands don't exists
|
||||
// in those older GDB versions. Also, gdbserver only supports tracing starting with 7.2
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ import org.eclipse.cdt.dsf.service.IDsfService;
|
|||
* The TraceControl service provides access to the debugger Tracing functionality.
|
||||
* It is used to do such things as start and stop tracing.
|
||||
*
|
||||
* As this functionality is very new to GDB itself, this interface is likely
|
||||
* to change a little in the next release of CDT.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface IGDBTraceControl extends IDsfService {
|
||||
|
@ -98,41 +101,17 @@ public interface IGDBTraceControl extends IDsfService {
|
|||
* {@link saveTraceData} should have the correct format to be loaded by this call.
|
||||
*/
|
||||
public void loadTraceData(ITraceTargetDMContext context,
|
||||
String file,
|
||||
RequestMonitor rm);
|
||||
String file,
|
||||
RequestMonitor rm);
|
||||
|
||||
|
||||
// /**
|
||||
// * Request that the backend use the specified trace record.
|
||||
// */
|
||||
// public void selectTraceRecord(ITraceRecordDMContext context, RequestMonitor rm);
|
||||
// /**
|
||||
// * Returns the trace record data of the specified trace record.
|
||||
// */
|
||||
// public void getTraceRecordData(ITraceRecordDMContext context,
|
||||
// DataRequestMonitor<ITraceRecordDMData> rm);
|
||||
//
|
||||
// /**
|
||||
// * Save all tracepoint definitions to the specified file in a
|
||||
// * format suitable for {@link loadTracepoints}.
|
||||
// */
|
||||
// // This should probably be part of the GDB Breakpoints service
|
||||
// public void saveTracepoints(ITraceTargetDMContext context,
|
||||
// String file,
|
||||
// RequestMonitor rm);
|
||||
//
|
||||
// /**
|
||||
// * Load all tracepoint definitions from the specified file.
|
||||
// * A file created from a call to {@link saveTracepoints} should have
|
||||
// * the correct format to be loaded by this call.
|
||||
// */
|
||||
// // This should probably be part of the GDB Breakpoints service
|
||||
// public void loadTracepoints(ITraceTargetDMContext context,
|
||||
// String file,
|
||||
// RequestMonitor rm);
|
||||
//
|
||||
|
||||
/**
|
||||
* Request that the backend use the specified trace record.
|
||||
*/
|
||||
public void selectTraceRecord(ITraceRecordDMContext context, RequestMonitor rm);
|
||||
|
||||
public void getTraceRecordData(ITraceRecordDMContext context, DataRequestMonitor<ITraceRecordDMData> rm);
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// GDB specific part
|
||||
/////////////////////////////////////////////////
|
||||
|
@ -179,12 +158,8 @@ public interface IGDBTraceControl extends IDsfService {
|
|||
*/
|
||||
public void getTraceVariables(ITraceTargetDMContext context, DataRequestMonitor<ITraceVariableDMData[]> rm);
|
||||
|
||||
// public ITraceRecordDMContext createTraceRecordContext(IDMContext ctx, int index);
|
||||
// public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm);
|
||||
// public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx);
|
||||
// public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx);
|
||||
//
|
||||
// public void setDefaultCollect(ITraceTargetDMContext context, String[] expressions, RequestMonitor rm);
|
||||
// public void getDefaultCollect(ITraceTargetDMContext context, DataRequestMonitor<String> rm);
|
||||
|
||||
public ITraceRecordDMContext createTraceRecordContext(ITraceTargetDMContext ctx, int index);
|
||||
public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm);
|
||||
public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx);
|
||||
public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
|||
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
|
||||
import org.eclipse.cdt.dsf.gdb.service.GDBRunControl_7_0;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IReverseRunControl;
|
||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||
import org.eclipse.cdt.dsf.gdb.service.GDBProcesses_7_0.ContainerExitedDMEvent;
|
||||
|
@ -606,7 +607,18 @@ public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @since 3.0 */
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
|
||||
// Once we start looking at trace frames, we should not use
|
||||
// the --thread or --frame options because GDB does not handle
|
||||
// it well, there are no actual threads running.
|
||||
// We only need to do this once, but it won't hurt to do it
|
||||
// every time.
|
||||
setUseThreadAndFrameOptions(false);
|
||||
}
|
||||
|
||||
public static class InitializationShutdownStep extends Sequence.Step {
|
||||
public enum Direction { INITIALIZING, SHUTTING_DOWN }
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
|||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetAttributes;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetChildCount;
|
||||
|
@ -436,6 +437,12 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I
|
|||
private MIVariableManager varManager;
|
||||
private CommandFactory fCommandFactory;
|
||||
|
||||
/**
|
||||
* Indicates that we are currently visualizing trace data.
|
||||
* In this case, some errors should not be reported.
|
||||
*/
|
||||
private boolean fTraceVisualization;
|
||||
|
||||
public MIExpressions(DsfSession session) {
|
||||
super(session);
|
||||
}
|
||||
|
@ -754,6 +761,15 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I
|
|||
rm.setData(new FormattedValueDMData(getData().getValue()));
|
||||
rm.done();
|
||||
}
|
||||
@Override
|
||||
protected void handleError() {
|
||||
if (fTraceVisualization) {
|
||||
rm.setData(new FormattedValueDMData("")); //$NON-NLS-1$
|
||||
rm.done();
|
||||
} else {
|
||||
super.handleError();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
fExpressionCache.execute(
|
||||
|
@ -1004,6 +1020,14 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I
|
|||
// MIVariableManager separately traps this event
|
||||
}
|
||||
|
||||
/** @since 3.0 */
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
|
||||
// Once we start looking at a trace record, we remain in
|
||||
// trace visualization mode.
|
||||
fTraceVisualization = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.1
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
|||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.service.command.events.MITracepointSelectedEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.MIBreakpointDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
|
||||
|
@ -177,6 +178,8 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
public StateChangeReason getReason() {
|
||||
if (getMIEvent() instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
||||
return StateChangeReason.EVENT_BREAKPOINT;
|
||||
} else if (getMIEvent() instanceof MITracepointSelectedEvent) { // must precede MIBreakpointHitEvent
|
||||
return StateChangeReason.UNKNOWN; // Don't display anything here, the details will take care of it
|
||||
} else if (getMIEvent() instanceof MIBreakpointHitEvent) {
|
||||
return StateChangeReason.BREAKPOINT;
|
||||
} else if (getMIEvent() instanceof MISteppingRangeEvent) {
|
||||
|
@ -201,6 +204,8 @@ public class MIRunControl extends AbstractDsfService implements IMIRunControl, I
|
|||
MIStoppedEvent event = getMIEvent();
|
||||
if (event instanceof MICatchpointHitEvent) { // must precede MIBreakpointHitEvent
|
||||
return ((MICatchpointHitEvent)event).getReason();
|
||||
} else if (event instanceof MITracepointSelectedEvent) { // must precede MIBreakpointHitEvent
|
||||
return ((MITracepointSelectedEvent)event).getReason();
|
||||
} else if (event instanceof MISharedLibEvent) {
|
||||
return ((MISharedLibEvent)event).getLibrary();
|
||||
} else if (event instanceof MISignalEvent) {
|
||||
|
|
|
@ -26,16 +26,17 @@ import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
|||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
||||
|
@ -61,7 +62,6 @@ public class MIStack extends AbstractDsfService
|
|||
implements IFrameDMContext
|
||||
{
|
||||
private final int fLevel;
|
||||
// public MIFrameDMC(MIStack service, int level) {
|
||||
public MIFrameDMC(String sessionId, IExecutionDMContext execDmc, int level) {
|
||||
super(sessionId, new IDMContext[] { execDmc });
|
||||
fLevel = level;
|
||||
|
@ -166,6 +166,12 @@ public class MIStack extends AbstractDsfService
|
|||
private MIStoppedEvent fCachedStoppedEvent;
|
||||
private IRunControl fRunControl;
|
||||
|
||||
/**
|
||||
* Indicates that we are currently visualizing trace data.
|
||||
* In this case, some errors should not be reported.
|
||||
*/
|
||||
private boolean fTraceVisualization;
|
||||
|
||||
public MIStack(DsfSession session)
|
||||
{
|
||||
super(session);
|
||||
|
@ -250,20 +256,19 @@ public class MIStack extends AbstractDsfService
|
|||
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
|
||||
|
||||
if (execDmc == null) {
|
||||
//rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "No frame context found in " + ctx, null)); //$NON-NLS-1$
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context " + ctx, null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the thread is stopped
|
||||
if (!fRunControl.isSuspended(execDmc)) {
|
||||
// Make sure the thread is stopped but only if we are not visualizing trace data
|
||||
if (!fTraceVisualization && !fRunControl.isSuspended(execDmc)) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context is running: " + ctx, null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (startIndex == 0 && endIndex == 0) {
|
||||
if (fTraceVisualization || (startIndex == 0 && endIndex == 0)) {
|
||||
// Try to retrieve the top stack frame from the cached stopped event.
|
||||
if (fCachedStoppedEvent != null &&
|
||||
fCachedStoppedEvent.getFrame() != null &&
|
||||
|
@ -329,7 +334,6 @@ public class MIStack extends AbstractDsfService
|
|||
});
|
||||
}
|
||||
|
||||
//private MIFrameDMC[] getFrames(DsfMIStackListFramesInfo info) {
|
||||
private IFrameDMContext[] getFrames(IMIExecutionDMContext execDmc, MIStackListFramesInfo info, int firstIndex, int lastIndex, int startIndex) {
|
||||
int length = info.getMIFrames().length;
|
||||
if (lastIndex > 0) {
|
||||
|
@ -408,15 +412,15 @@ public class MIStack extends AbstractDsfService
|
|||
|
||||
// Retrieve the top stack frame from the stopped event only if the selected thread is the one on which stopped event
|
||||
// is raised
|
||||
if (fCachedStoppedEvent != null &&
|
||||
execDmc.equals(fCachedStoppedEvent.getDMContext()) &&
|
||||
miFrameDmc.fLevel == 0 &&
|
||||
fCachedStoppedEvent.getFrame() != null)
|
||||
{
|
||||
rm.setData(new FrameDataFromStoppedEvent(fCachedStoppedEvent));
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
if (fTraceVisualization || miFrameDmc.fLevel == 0) {
|
||||
if (fCachedStoppedEvent != null && fCachedStoppedEvent.getFrame() != null &&
|
||||
(execDmc.equals(fCachedStoppedEvent.getDMContext()) || fTraceVisualization))
|
||||
{
|
||||
rm.setData(new FrameDataFromStoppedEvent(fCachedStoppedEvent));
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If not, retrieve the full list of frame data.
|
||||
class FrameDataFromMIStackFrameListInfo extends FrameData {
|
||||
|
@ -475,13 +479,24 @@ public class MIStack extends AbstractDsfService
|
|||
return;
|
||||
}
|
||||
|
||||
// If not, retrieve the full list of frame data.
|
||||
if (fTraceVisualization) {
|
||||
// For the pre-release of GDB that supports tracepoints, we cannot ask
|
||||
// for the list of arguments for all stack frames, but only for available
|
||||
// ones. Again, I'm hoping that GDB 7.2 will be smarter than that.
|
||||
getArgumentsForTraceVisualization(frameDmc, rm);
|
||||
return;
|
||||
}
|
||||
|
||||
// If not, retrieve the full list of frame data. Although we only need one frame
|
||||
// for this call, it will be stored the cache and made available for other calls.
|
||||
fMICommandCache.execute(
|
||||
// We don't actually need to ask for the values in this case, but since
|
||||
// we will ask for them right after, it is more efficient to ask for them now
|
||||
// so as to cache the result. If the command fails, then we will ask for
|
||||
// the result without the values
|
||||
fCommandFactory.createMIStackListArguments(execDmc, true),
|
||||
// Don't ask for value when we are visualizing trace data, since some
|
||||
// data will not be there, and the command will fail
|
||||
fCommandFactory.createMIStackListArguments(execDmc, true),
|
||||
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
@ -504,8 +519,8 @@ public class MIStack extends AbstractDsfService
|
|||
@Override
|
||||
protected void handleError() {
|
||||
// If the command fails it can be because we asked for values.
|
||||
// This can happen with uninitialized values and pretty printers (bug 307614)
|
||||
// or when visualizing tracepoints. Since asking for values was simply an optimization
|
||||
// This can happen with uninitialized values and pretty printers (bug 307614).
|
||||
// Since asking for values was simply an optimization
|
||||
// to store the command in the cache, let's retry the command without asking for values.
|
||||
fMICommandCache.execute(
|
||||
fCommandFactory.createMIStackListArguments(execDmc, false),
|
||||
|
@ -533,6 +548,43 @@ public class MIStack extends AbstractDsfService
|
|||
});
|
||||
}
|
||||
|
||||
// For the pre-release of GDB that supports tracepoints, we cannot ask
|
||||
// for the list of arguments for all stack frames, but only for available
|
||||
// ones. Again, I'm hoping that GDB 7.2 will be smarter than that.
|
||||
private void getArgumentsForTraceVisualization(final IFrameDMContext frameDmc, final DataRequestMonitor<IVariableDMContext[]> rm) {
|
||||
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class);
|
||||
|
||||
getStackDepth(execDmc, 0, new DataRequestMonitor<Integer>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
int bottomFrame = getData() - 1;
|
||||
fMICommandCache.execute(
|
||||
// Don't ask for values for tracepoints
|
||||
fCommandFactory.createMIStackListArguments(execDmc, false, 0, bottomFrame),
|
||||
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// Find the index to the correct MI frame object.
|
||||
// Note: this is a short-cut, but it won't work once we implement retrieving
|
||||
// partial lists of stack frames.
|
||||
int idx = frameDmc.getLevel();
|
||||
if (idx == -1 || idx >= getData().getMIFrames().length) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid frame " + frameDmc, null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the variable array out of MIArg array.
|
||||
MIArg[] args = getData().getMIFrames()[idx].getArgs();
|
||||
if (args == null) args = new MIArg[0];
|
||||
rm.setData(makeVariableDMCs(frameDmc, MIVariableDMC.Type.ARGUMENT, args.length));
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void getVariableData(IVariableDMContext variableDmc, final DataRequestMonitor<IVariableDMData> rm) {
|
||||
if (!(variableDmc instanceof MIVariableDMC)) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context type " + variableDmc, null)); //$NON-NLS-1$
|
||||
|
@ -589,8 +641,13 @@ public class MIStack extends AbstractDsfService
|
|||
}
|
||||
|
||||
if (miVariableDmc.fType == MIVariableDMC.Type.ARGUMENT){
|
||||
if (fTraceVisualization) {
|
||||
getArgumentsDataForTraceVisualization(miVariableDmc, rm);
|
||||
} else {
|
||||
fMICommandCache.execute(
|
||||
fCommandFactory.createMIStackListArguments(execDmc, true),
|
||||
// Don't ask for value when we are visualizing trace data, since some
|
||||
// data will not be there, and the command will fail
|
||||
fCommandFactory.createMIStackListArguments(execDmc, true),
|
||||
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
@ -610,8 +667,7 @@ public class MIStack extends AbstractDsfService
|
|||
@Override
|
||||
protected void handleError() {
|
||||
// Unable to get the values. This can happen with uninitialized values and pretty printers (bug 307614)
|
||||
// or when visualizing tracepoints. Either way, we try to ask for the arguments without their values,
|
||||
// which is better than nothing
|
||||
// Let's try to ask for the arguments without their values, which is better than nothing
|
||||
fMICommandCache.execute(
|
||||
fCommandFactory.createMIStackListArguments(execDmc, false),
|
||||
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
|
||||
|
@ -633,10 +689,13 @@ public class MIStack extends AbstractDsfService
|
|||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}//if
|
||||
if (miVariableDmc.fType == MIVariableDMC.Type.LOCAL){
|
||||
fMICommandCache.execute(
|
||||
fCommandFactory.createMIStackListLocals(frameDmc, true),
|
||||
// Don't ask for value when we are visualizing trace data, since some
|
||||
// data will not be there, and the command will fail
|
||||
fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization),
|
||||
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
@ -652,9 +711,8 @@ public class MIStack extends AbstractDsfService
|
|||
}
|
||||
@Override
|
||||
protected void handleError() {
|
||||
// Unable to get the value. This can happen with uninitialized values and pretty printers (bug 307614)
|
||||
// or when visualizing tracepoints. Either way, we try to ask for the variables without their values,
|
||||
// which is better than nothing
|
||||
// Unable to get the value. This can happen with uninitialized values and pretty printers (bug 307614).
|
||||
// Let's try to ask for the variables without their values, which is better than nothing
|
||||
fMICommandCache.execute(
|
||||
fCommandFactory.createMIStackListLocals(frameDmc, false),
|
||||
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) {
|
||||
|
@ -677,6 +735,52 @@ public class MIStack extends AbstractDsfService
|
|||
|
||||
}
|
||||
|
||||
// For the pre-release of GDB that supports tracepoints, we cannot ask
|
||||
// for the list of arguments for all stack frames, but only for available
|
||||
// ones. Again, I'm hoping that GDB 7.2 will be smarter than that.
|
||||
private void getArgumentsDataForTraceVisualization(final MIVariableDMC miVariableDmc, final DataRequestMonitor<IVariableDMData> rm) {
|
||||
final MIFrameDMC frameDmc = DMContexts.getAncestorOfType(miVariableDmc, MIFrameDMC.class);
|
||||
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class);
|
||||
|
||||
class VariableData implements IVariableDMData {
|
||||
private MIArg dsfMIArg;
|
||||
VariableData(MIArg arg){
|
||||
dsfMIArg = arg;
|
||||
}
|
||||
public String getName() { return dsfMIArg.getName(); }
|
||||
public String getValue() { return dsfMIArg.getValue(); }
|
||||
@Override
|
||||
public String toString() { return dsfMIArg.toString(); }
|
||||
}
|
||||
|
||||
getStackDepth(execDmc, 0, new DataRequestMonitor<Integer>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
int bottomFrame = getData() - 1;
|
||||
fMICommandCache.execute(
|
||||
// Don't ask for values for tracepoints
|
||||
fCommandFactory.createMIStackListArguments(execDmc, false, 0, bottomFrame),
|
||||
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// Find the correct frame and argument
|
||||
if ( frameDmc.fLevel >= getData().getMIFrames().length ||
|
||||
miVariableDmc.fIndex >= getData().getMIFrames()[frameDmc.fLevel].getArgs().length )
|
||||
{
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the data object.
|
||||
rm.setData(new VariableData(getData().getMIFrames()[frameDmc.fLevel].getArgs()[miVariableDmc.fIndex]));
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private MIVariableDMC[] makeVariableDMCs(IFrameDMContext frame, MIVariableDMC.Type type, int count) {
|
||||
MIVariableDMC[] variables = new MIVariableDMC[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
@ -723,7 +827,9 @@ public class MIStack extends AbstractDsfService
|
|||
// we will ask for them right after, it is more efficient to ask for them now
|
||||
// so as to cache the result. If the command fails, then we will ask for
|
||||
// the result without the values
|
||||
fCommandFactory.createMIStackListLocals(frameDmc, true),
|
||||
// Don't ask for value when we are visualizing trace data, since some
|
||||
// data will not be there, and the command will fail
|
||||
fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization),
|
||||
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), countingRm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
@ -734,8 +840,8 @@ public class MIStack extends AbstractDsfService
|
|||
@Override
|
||||
protected void handleError() {
|
||||
// If the command fails it can be because we asked for values.
|
||||
// This can happen with uninitialized values and pretty printers (bug 307614)
|
||||
// or when visualizing tracepoints. Since asking for values was simply an optimization
|
||||
// This can happen with uninitialized values and pretty printers (bug 307614).
|
||||
// Since asking for values was simply an optimization
|
||||
// to store the command in the cache, let's retry the command without asking for values.
|
||||
fMICommandCache.execute(
|
||||
fCommandFactory.createMIStackListLocals(frameDmc, false),
|
||||
|
@ -755,7 +861,7 @@ public class MIStack extends AbstractDsfService
|
|||
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class);
|
||||
if (execDmc != null) {
|
||||
// Make sure the thread is stopped
|
||||
if (!fRunControl.isSuspended(execDmc)) {
|
||||
if (!fTraceVisualization && !fRunControl.isSuspended(execDmc)) {
|
||||
rm.setData(0);
|
||||
rm.done();
|
||||
return;
|
||||
|
@ -787,6 +893,25 @@ public class MIStack extends AbstractDsfService
|
|||
rm.setData(getData().getDepth());
|
||||
rm.done();
|
||||
}
|
||||
@Override
|
||||
protected void handleError() {
|
||||
if (fTraceVisualization) {
|
||||
// when visualizing trace data, the pre-release GDB, the command
|
||||
// -stack-info-depth will return an error if we ask for any level
|
||||
// that GDB does not know about. We would have to iteratively
|
||||
// try different depths until we found the deepest that succeeds.
|
||||
// That is too much of a hack for a pre-release. Let's hope
|
||||
// GDB 7.2 will properly answer -stack-info-depth when visualizing
|
||||
// trace data. Until then, we can safely say we have one stack
|
||||
// frame, which is going to be the case for 95% of the cases.
|
||||
// To have more stack frames, the user would have to have collected
|
||||
// the registers and enough stack memory for GDB to build another frame.
|
||||
rm.setData(1);
|
||||
rm.done();
|
||||
} else {
|
||||
super.handleError();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
|
||||
|
@ -833,6 +958,13 @@ public class MIStack extends AbstractDsfService
|
|||
}
|
||||
}
|
||||
|
||||
/** @since 3.0 */
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
|
||||
// Once we start looking at a trace record, we remain in
|
||||
// trace visualization mode.
|
||||
fTraceVisualization = true;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.1
|
||||
|
|
|
@ -15,6 +15,7 @@ package org.eclipse.cdt.dsf.mi.service;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -26,25 +27,26 @@ import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
|||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.debug.service.IExpressions;
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack;
|
||||
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData;
|
||||
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack;
|
||||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandListener;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandResult;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandToken;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.GDBTypeParser;
|
||||
import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIExpressions.ExpressionInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIExpressions.MIExpressionDMC;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
|
@ -1505,7 +1507,7 @@ public class MIVariableManager implements ICommandControl {
|
|||
// The variable object is out-of-scope and we
|
||||
// should not use it.
|
||||
if (shouldCreateNew) {
|
||||
/**
|
||||
/*
|
||||
* It may happen that when accessing a varObject we find it to be
|
||||
* out-of-scope. The expression for which we are trying to access a varObject
|
||||
* could still be valid, and therefore we should try to create a new varObject for
|
||||
|
@ -1850,4 +1852,22 @@ public class MIVariableManager implements ICommandControl {
|
|||
// The views will fully refresh on a MemoryChangedEvent
|
||||
markAllOutOfDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.0
|
||||
*/
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
|
||||
// We have a big limitation with tracepoints!
|
||||
// GDB usually only reports a depth of 1, for every trace record, no
|
||||
// matter where it occurred. This means that our naming scheme for VariableObjectId
|
||||
// fails miserably because all objects will have the same depth and we will confuse
|
||||
// them. Until we find a good solution, we have to clear our entire list of
|
||||
// of variable objects (and delete them in GDB to avoid having too many).
|
||||
Iterator<Map.Entry<VariableObjectId, MIVariableObject>> iterator = lruVariableList.entrySet().iterator();
|
||||
while (iterator.hasNext()){
|
||||
iterator.next();
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ public abstract class AbstractMIControl extends AbstractDsfService
|
|||
|
||||
// MI did not always support the --thread/--frame options
|
||||
// This boolean is used to know if we should use -thread-select and -stack-select-frame instead
|
||||
private final boolean fUseThreadAndFrameOptions;
|
||||
private boolean fUseThreadAndFrameOptions;
|
||||
// currentStackLevel and currentThreadId are only necessary when
|
||||
// we must use -thread-select and -stack-select-frame
|
||||
private int fCurrentStackLevel = -1;
|
||||
|
@ -157,6 +157,13 @@ public abstract class AbstractMIControl extends AbstractDsfService
|
|||
return fTracingStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.0
|
||||
*/
|
||||
protected void setUseThreadAndFrameOptions(boolean shouldUse) {
|
||||
fUseThreadAndFrameOptions = shouldUse;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.0
|
||||
*/
|
||||
|
|
|
@ -105,6 +105,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIThreadInfo;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIThreadListIds;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIThreadSelect;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceDefineVariable;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceFind;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceListVariables;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceSave;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceStart;
|
||||
|
@ -145,6 +146,7 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIStackListFramesInfo;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.output.MIStackListLocalsInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIThreadInfoInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIThreadListIdsInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceFindInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceListVariablesInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStatusInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStopInfo;
|
||||
|
@ -660,6 +662,10 @@ public class CommandFactory {
|
|||
public ICommand<MIInfo> createMITraceDefineVariable(ITraceTargetDMContext ctx, String varName, String varValue) {
|
||||
return new MITraceDefineVariable(ctx, varName, varValue);
|
||||
}
|
||||
|
||||
public ICommand<MITraceFindInfo> createMITraceFind(ITraceTargetDMContext ctx, int frameReference) {
|
||||
return new MITraceFind(ctx, frameReference);
|
||||
}
|
||||
|
||||
public ICommand<MITraceListVariablesInfo> createMITraceListVariables(ITraceTargetDMContext ctx) {
|
||||
return new MITraceListVariables(ctx);
|
||||
|
|
|
@ -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