mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Committing patches for bugs 159946 (disassembly) and 214546 (memory monitor persistence).
This commit is contained in:
parent
90f4dc4c71
commit
8868398cc9
25 changed files with 1708 additions and 43 deletions
|
@ -58,6 +58,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
|
|
||||||
private BigInteger fBlockAddress;
|
private BigInteger fBlockAddress;
|
||||||
private int fLength;
|
private int fLength;
|
||||||
|
private int fWordSize;
|
||||||
private MemoryByte[] fBlock;
|
private MemoryByte[] fBlock;
|
||||||
|
|
||||||
private ArrayList<Object> fConnections = new ArrayList<Object>();
|
private ArrayList<Object> fConnections = new ArrayList<Object>();
|
||||||
|
@ -72,9 +73,10 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
* @param modelId -
|
* @param modelId -
|
||||||
* @param expression - the displayed expression in the UI
|
* @param expression - the displayed expression in the UI
|
||||||
* @param address - the actual memory block start address
|
* @param address - the actual memory block start address
|
||||||
* @param length - the memory block length (could be 0)
|
* @param word_size - the number of bytes per address
|
||||||
|
* @param length - the requested block length (could be 0)
|
||||||
*/
|
*/
|
||||||
DsfMemoryBlock(DsfMemoryBlockRetrieval retrieval, String modelId, String expression, BigInteger address, long length) {
|
DsfMemoryBlock(DsfMemoryBlockRetrieval retrieval, String modelId, String expression, BigInteger address, int word_size, long length) {
|
||||||
|
|
||||||
fLaunch = retrieval.getLaunch();
|
fLaunch = retrieval.getLaunch();
|
||||||
fDebugTarget = retrieval.getDebugTarget();
|
fDebugTarget = retrieval.getDebugTarget();
|
||||||
|
@ -85,6 +87,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
|
|
||||||
// Current block information
|
// Current block information
|
||||||
fBlockAddress = address;
|
fBlockAddress = address;
|
||||||
|
fWordSize = word_size;
|
||||||
fLength = (int) length;
|
fLength = (int) length;
|
||||||
fBlock = null;
|
fBlock = null;
|
||||||
|
|
||||||
|
@ -413,7 +416,6 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
|
|
||||||
// For the IAddress interface
|
// For the IAddress interface
|
||||||
final Addr64 address = new Addr64(bigAddress);
|
final Addr64 address = new Addr64(bigAddress);
|
||||||
final int word_size = 1;
|
|
||||||
|
|
||||||
// Use a Query to synchronize the downstream calls
|
// Use a Query to synchronize the downstream calls
|
||||||
Query<MemoryByte[]> query = new Query<MemoryByte[]>() {
|
Query<MemoryByte[]> query = new Query<MemoryByte[]>() {
|
||||||
|
@ -423,7 +425,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
if (memoryService != null) {
|
if (memoryService != null) {
|
||||||
// Go for it
|
// Go for it
|
||||||
memoryService.getMemory(
|
memoryService.getMemory(
|
||||||
fRetrieval.getContext(), address, 0, word_size, (int) length,
|
fRetrieval.getContext(), address, 0, fWordSize, (int) length,
|
||||||
new DataRequestMonitor<MemoryByte[]>(fRetrieval.getExecutor(), drm) {
|
new DataRequestMonitor<MemoryByte[]>(fRetrieval.getExecutor(), drm) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleOK() {
|
protected void handleOK() {
|
||||||
|
@ -460,9 +462,8 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
|
|
||||||
// For the IAddress interface
|
// For the IAddress interface
|
||||||
final Addr64 address = new Addr64(fBaseAddress);
|
final Addr64 address = new Addr64(fBaseAddress);
|
||||||
final int word_size = 1;
|
|
||||||
|
|
||||||
// Use a Query to synchronise the downstream calls
|
// Use a Query to synchronize the downstream calls
|
||||||
Query<MemoryByte[]> query = new Query<MemoryByte[]>() {
|
Query<MemoryByte[]> query = new Query<MemoryByte[]>() {
|
||||||
@Override
|
@Override
|
||||||
protected void execute(final DataRequestMonitor<MemoryByte[]> drm) {
|
protected void execute(final DataRequestMonitor<MemoryByte[]> drm) {
|
||||||
|
@ -470,7 +471,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
||||||
if (memoryService != null) {
|
if (memoryService != null) {
|
||||||
// Go for it
|
// Go for it
|
||||||
memoryService.setMemory(
|
memoryService.setMemory(
|
||||||
fRetrieval.getContext(), address, offset, word_size, bytes.length, bytes,
|
fRetrieval.getContext(), address, offset, fWordSize, bytes.length, bytes,
|
||||||
new RequestMonitor(fRetrieval.getExecutor(), null));
|
new RequestMonitor(fRetrieval.getExecutor(), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,11 @@
|
||||||
package org.eclipse.dd.dsf.debug.model;
|
package org.eclipse.dd.dsf.debug.model;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IAdaptable;
|
import org.eclipse.core.runtime.IAdaptable;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.PlatformObject;
|
import org.eclipse.core.runtime.PlatformObject;
|
||||||
|
@ -36,8 +39,12 @@ import org.eclipse.dd.dsf.debug.service.IMemory.IMemoryDMContext;
|
||||||
import org.eclipse.dd.dsf.service.DsfServices;
|
import org.eclipse.dd.dsf.service.DsfServices;
|
||||||
import org.eclipse.dd.dsf.service.DsfSession;
|
import org.eclipse.dd.dsf.service.DsfSession;
|
||||||
import org.eclipse.dd.dsf.service.IDsfService;
|
import org.eclipse.dd.dsf.service.IDsfService;
|
||||||
|
import org.eclipse.dd.dsf.service.DsfSession.SessionEndedListener;
|
||||||
import org.eclipse.debug.core.DebugException;
|
import org.eclipse.debug.core.DebugException;
|
||||||
|
import org.eclipse.debug.core.DebugPlugin;
|
||||||
import org.eclipse.debug.core.ILaunch;
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||||
|
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
|
||||||
import org.eclipse.debug.core.model.IDebugTarget;
|
import org.eclipse.debug.core.model.IDebugTarget;
|
||||||
import org.eclipse.debug.core.model.IMemoryBlock;
|
import org.eclipse.debug.core.model.IMemoryBlock;
|
||||||
import org.eclipse.debug.core.model.IMemoryBlockExtension;
|
import org.eclipse.debug.core.model.IMemoryBlockExtension;
|
||||||
|
@ -45,6 +52,10 @@ import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension;
|
||||||
import org.osgi.framework.BundleContext;
|
import org.osgi.framework.BundleContext;
|
||||||
import org.osgi.framework.InvalidSyntaxException;
|
import org.osgi.framework.InvalidSyntaxException;
|
||||||
import org.osgi.util.tracker.ServiceTracker;
|
import org.osgi.util.tracker.ServiceTracker;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of memory access API of the Eclipse standard debug model.
|
* Implementation of memory access API of the Eclipse standard debug model.
|
||||||
|
@ -62,15 +73,24 @@ import org.osgi.util.tracker.ServiceTracker;
|
||||||
* code will still be functional after some trivial adjustments.
|
* code will still be functional after some trivial adjustments.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBlockRetrievalExtension
|
public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBlockRetrievalExtension, SessionEndedListener
|
||||||
{
|
{
|
||||||
private final String fModelId;
|
private final String fModelId;
|
||||||
private final DsfSession fSession;
|
private final DsfSession fSession;
|
||||||
private final DsfExecutor fExecutor;
|
private final DsfExecutor fExecutor;
|
||||||
private IMemoryDMContext fContext;
|
private final IMemoryDMContext fContext;
|
||||||
|
private final String fContextString;
|
||||||
private final ServiceTracker fMemoryServiceTracker;
|
private final ServiceTracker fMemoryServiceTracker;
|
||||||
private final ServiceTracker fExpressionServiceTracker;
|
private final ServiceTracker fExpressionServiceTracker;
|
||||||
|
|
||||||
|
private final ILaunchConfiguration fLaunchConfig;
|
||||||
|
private final ILaunch fLaunch;
|
||||||
|
private final IDebugTarget fDebugTarget;
|
||||||
|
private final boolean fSupportsValueModification;
|
||||||
|
private final boolean fSupportBaseAddressModification;
|
||||||
|
private final int fAddressSize;
|
||||||
|
private final int fWordSize; // Number of bytes per address
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
|
@ -78,10 +98,22 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
||||||
* @param dmc
|
* @param dmc
|
||||||
* @throws DebugException
|
* @throws DebugException
|
||||||
*/
|
*/
|
||||||
public DsfMemoryBlockRetrieval(String modelId, IMemoryDMContext dmc) throws DebugException {
|
public DsfMemoryBlockRetrieval(String modelId, ILaunchConfiguration config, IMemoryDMContext dmc) throws DebugException {
|
||||||
|
|
||||||
|
// DSF stuff
|
||||||
fModelId = modelId;
|
fModelId = modelId;
|
||||||
fContext = dmc;
|
fContext = dmc;
|
||||||
|
|
||||||
|
// FIXME: Currently memory contexts are differentiated by sessionID
|
||||||
|
// so there is no way to guarantee the memory blocks will be reinstated
|
||||||
|
// in the correct memory space.
|
||||||
|
// Need a way to create deterministically the context ID from a unique
|
||||||
|
// target, ideally from the launch configuration (or derived from it).
|
||||||
|
// For the time being, just put some constant. This will work until we
|
||||||
|
// support multiple targets in the same launch.
|
||||||
|
// fContextString = fContext.toString();
|
||||||
|
fContextString = "Context string"; //$NON-NLS-1$
|
||||||
|
|
||||||
fSession = DsfSession.getSession(fContext.getSessionId());
|
fSession = DsfSession.getSession(fContext.getSessionId());
|
||||||
if (fSession == null) {
|
if (fSession == null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
@ -124,11 +156,160 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
||||||
"Error creating service filter.", e)); //$NON-NLS-1$
|
"Error creating service filter.", e)); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
fExpressionServiceTracker.open();
|
fExpressionServiceTracker.open();
|
||||||
|
|
||||||
|
// Launch configuration information
|
||||||
|
fLaunchConfig = config;
|
||||||
|
fLaunch = null;
|
||||||
|
fDebugTarget = null;
|
||||||
|
fAddressSize = 4; // Get this from the launch configuration
|
||||||
|
fWordSize = 1; // Get this from the launch configuration
|
||||||
|
fSupportsValueModification = true; // Get this from the launch configuration
|
||||||
|
fSupportBaseAddressModification = false; // Get this from the launch configuration
|
||||||
|
|
||||||
|
// So we are notified on exit and can save the memory blocks
|
||||||
|
DsfSession.addSessionEndedListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Memory monitors persistence
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In the launch configuration file, the memory block entry is structured
|
||||||
|
* as follows (note: this differs from CDI):
|
||||||
|
*
|
||||||
|
* <stringAttribute
|
||||||
|
* key="org.eclipse.dsf.launch.MEMORY_BLOCKS"
|
||||||
|
* value="<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
* <memoryBlockExpressionList context=[memory context ID]>
|
||||||
|
* <memoryBlockExpression label=[monitor label] address=[base address]/>
|
||||||
|
* <memoryBlockExpression ...>
|
||||||
|
* ...
|
||||||
|
* </memoryBlockExpressionList>
|
||||||
|
* ...
|
||||||
|
* <memoryBlockExpressionList context=...>
|
||||||
|
* ...
|
||||||
|
* </memoryBlockExpressionList>"
|
||||||
|
* />
|
||||||
|
*/
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Memory blocks memento tags
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// These 2 really belong in the DSF launch configuration class...
|
||||||
|
private static final String DSF_LAUNCH_ID = "org.eclipse.dsf.launch"; //$NON-NLS-1$
|
||||||
|
private static final String ATTR_DEBUGGER_MEMORY_BLOCKS = DSF_LAUNCH_ID + ".MEMORY_BLOCKS"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private static final String MEMORY_BLOCK_EXPRESSION_LIST = "memoryBlockExpressionList"; //$NON-NLS-1$
|
||||||
|
private static final String ATTR_EXPRESSION_LIST_CONTEXT = "context"; //$NON-NLS-1$
|
||||||
|
private static final String MEMORY_BLOCK_EXPRESSION = "memoryBlockExpression"; //$NON-NLS-1$
|
||||||
|
private static final String ATTR_MEMORY_BLOCK_EXPR_LABEL = "label"; //$NON-NLS-1$
|
||||||
|
private static final String ATTR_MEMORY_BLOCK_EXPR_ADDRESS = "address"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Install persisted memory monitors
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the memory monitors from the memento in the launch configuration
|
||||||
|
*/
|
||||||
|
public void initialize() {
|
||||||
|
try {
|
||||||
|
final String memento = fLaunchConfig.getAttribute(ATTR_DEBUGGER_MEMORY_BLOCKS, ""); //$NON-NLS-1$
|
||||||
|
if (memento != null && memento.trim().length() != 0) {
|
||||||
|
// Submit the runnable to install the monitors on dispatch thread.
|
||||||
|
getExecutor().submit(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
createBlocksFromConfiguration(memento);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
DsfDebugPlugin.getDefault().getLog().log(e.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (CoreException e) {
|
||||||
|
DsfDebugPlugin.getDefault().getLog().log(e.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createBlocksFromConfiguration(String memento) throws CoreException {
|
||||||
|
|
||||||
|
// Parse the memento and validate its type
|
||||||
|
Element root = DebugPlugin.parseDocument(memento);
|
||||||
|
if (!root.getNodeName().equalsIgnoreCase(MEMORY_BLOCK_EXPRESSION_LIST)) {
|
||||||
|
IStatus status = new Status(IStatus.ERROR, DsfDebugPlugin.PLUGIN_ID, DebugPlugin.INTERNAL_ERROR,
|
||||||
|
"Memory monitor initialization: invalid memento", null);//$NON-NLS-1$
|
||||||
|
throw new CoreException(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the block list specific to this memory context
|
||||||
|
// FIXME: We only process the first entry...
|
||||||
|
if (root.getAttribute(ATTR_EXPRESSION_LIST_CONTEXT).equals(fContextString)) {
|
||||||
|
List<IMemoryBlock> blocks = new ArrayList<IMemoryBlock>();
|
||||||
|
NodeList expressionList = root.getChildNodes();
|
||||||
|
int length = expressionList.getLength();
|
||||||
|
for (int i = 0; i < length; ++i) {
|
||||||
|
Node node = expressionList.item(i);
|
||||||
|
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
|
Element entry = (Element) node;
|
||||||
|
if (entry.getNodeName().equalsIgnoreCase(MEMORY_BLOCK_EXPRESSION)) {
|
||||||
|
String label = entry.getAttribute(ATTR_MEMORY_BLOCK_EXPR_LABEL);
|
||||||
|
String address = entry.getAttribute(ATTR_MEMORY_BLOCK_EXPR_ADDRESS);
|
||||||
|
BigInteger blockAddress = new BigInteger(address);
|
||||||
|
DsfMemoryBlock block = new DsfMemoryBlock(this, fModelId, label, blockAddress, fWordSize, 0);
|
||||||
|
blocks.add(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DebugPlugin.getDefault().getMemoryBlockManager().addMemoryBlocks( blocks.toArray(new IMemoryBlock[blocks.size()]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On session exit, save the memory blocks in the launch configuration
|
||||||
|
*/
|
||||||
|
public void sessionEnded(DsfSession session) {
|
||||||
|
DsfSession.removeSessionEndedListener(this);
|
||||||
|
saveMemoryBlocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Each retrieval overwrites the previous one :-(
|
||||||
|
// FIXME: Racing condition :-( - synchronize on launch config enough?
|
||||||
|
// FIXME: Make it a Job?
|
||||||
|
public void saveMemoryBlocks() {
|
||||||
|
try {
|
||||||
|
ILaunchConfigurationWorkingCopy wc = fLaunchConfig.getWorkingCopy();
|
||||||
|
wc.setAttribute(ATTR_DEBUGGER_MEMORY_BLOCKS, getMemento());
|
||||||
|
wc.doSave();
|
||||||
|
}
|
||||||
|
catch( CoreException e ) {
|
||||||
|
DsfDebugPlugin.getDefault().getLog().log(e.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMemento() throws CoreException {
|
||||||
|
IMemoryBlock[] blocks = DebugPlugin.getDefault().getMemoryBlockManager().getMemoryBlocks(this);
|
||||||
|
Document document = DebugPlugin.newDocument();
|
||||||
|
Element expressionList = document.createElement(MEMORY_BLOCK_EXPRESSION_LIST);
|
||||||
|
expressionList.setAttribute(ATTR_EXPRESSION_LIST_CONTEXT, fContextString);
|
||||||
|
for (IMemoryBlock block : blocks) {
|
||||||
|
if (block instanceof IMemoryBlockExtension) {
|
||||||
|
IMemoryBlockExtension memoryBlock = (IMemoryBlockExtension) block;
|
||||||
|
Element expression = document.createElement(MEMORY_BLOCK_EXPRESSION);
|
||||||
|
expression.setAttribute(ATTR_MEMORY_BLOCK_EXPR_LABEL, memoryBlock.getExpression());
|
||||||
|
expression.setAttribute(ATTR_MEMORY_BLOCK_EXPR_ADDRESS, memoryBlock.getBigBaseAddress().toString());
|
||||||
|
expressionList.appendChild(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.appendChild(expressionList);
|
||||||
|
return DebugPlugin.serializeDocument(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Accessors
|
// Accessors
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public DsfSession getSession() {
|
public DsfSession getSession() {
|
||||||
return fSession;
|
return fSession;
|
||||||
|
@ -146,38 +327,37 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
||||||
return fMemoryServiceTracker;
|
return fMemoryServiceTracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Launch/Target specific information
|
// Launch/Target specific information
|
||||||
// To be completed
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
public ILaunch getLaunch() {
|
public ILaunch getLaunch() {
|
||||||
return null;
|
return fLaunch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDebugTarget getDebugTarget() {
|
public IDebugTarget getDebugTarget() {
|
||||||
return null;
|
return fDebugTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAddressSize() {
|
public int getAddressSize() {
|
||||||
return 4;
|
return fAddressSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAddressableSize() {
|
public int getAddressableSize() {
|
||||||
return 1;
|
return fWordSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean supportsValueModification() {
|
public boolean supportsValueModification() {
|
||||||
return true;
|
return fSupportsValueModification;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean supportBaseAddressModification() {
|
public boolean supportBaseAddressModification() {
|
||||||
return false;
|
return fSupportBaseAddressModification;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// IMemoryBlockRetrieval - obsoleted by IMemoryBlockRetrievalExtension
|
// IMemoryBlockRetrieval - obsoleted by IMemoryBlockRetrievalExtension
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
|
@ -198,12 +378,12 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
||||||
// The expression to display in the rendering tab (in hex by convention)
|
// The expression to display in the rendering tab (in hex by convention)
|
||||||
// Put here for the sake of completeness (not used with IMemoryBlockExtension)
|
// Put here for the sake of completeness (not used with IMemoryBlockExtension)
|
||||||
String expression = "0x" + Long.toHexString(startAddress); //$NON-NLS-1$
|
String expression = "0x" + Long.toHexString(startAddress); //$NON-NLS-1$
|
||||||
return new DsfMemoryBlock(this, fModelId, expression, BigInteger.valueOf(startAddress), length);
|
return new DsfMemoryBlock(this, fModelId, expression, BigInteger.valueOf(startAddress), fWordSize, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// IMemoryBlockRetrievalExtension
|
// IMemoryBlockRetrievalExtension
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
|
@ -277,12 +457,12 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
||||||
* the memory request cache should save the day.
|
* the memory request cache should save the day.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return new DsfMemoryBlock(this, fModelId, expression, blockAddress, 0);
|
return new DsfMemoryBlock(this, fModelId, expression, blockAddress, fWordSize, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Helper functions
|
// Helper functions
|
||||||
// ////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private BigInteger resolveMemoryAddress(final IDMContext idmContext, final String expression) throws DebugException {
|
private BigInteger resolveMemoryAddress(final IDMContext idmContext, final String expression) throws DebugException {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 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.dd.dsf.debug.service;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||||
|
import org.eclipse.dd.dsf.service.IDsfService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disassembly service interface
|
||||||
|
*/
|
||||||
|
public interface IDisassembly extends IDsfService {
|
||||||
|
|
||||||
|
public interface IDisassemblyDMContext extends IDMContext {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the disassembled code from an address range.
|
||||||
|
* If [startAddress] == null, disassemble from the instruction pointer.
|
||||||
|
*
|
||||||
|
* @param context Context of the disassembly code
|
||||||
|
* @param startAddress Beginning address
|
||||||
|
* @param endAddress End address
|
||||||
|
* @param drm Disassembled code
|
||||||
|
*/
|
||||||
|
public void getInstructions(
|
||||||
|
IDisassemblyDMContext context,
|
||||||
|
BigInteger startAddress,
|
||||||
|
BigInteger endAddress,
|
||||||
|
DataRequestMonitor<IInstruction[]> drm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the disassembled code from a file location.
|
||||||
|
* If [lines] == -1, the whole function is disassembled.
|
||||||
|
*
|
||||||
|
* @param context Context of the disassembly code
|
||||||
|
* @param filename File to disassemble
|
||||||
|
* @param linenum Line number within the file
|
||||||
|
* @param lines Number of lines of disassembled code to produce
|
||||||
|
* @param drm Disassembled code
|
||||||
|
*/
|
||||||
|
public void getInstructions(
|
||||||
|
IDisassemblyDMContext context,
|
||||||
|
String filename,
|
||||||
|
int linenum,
|
||||||
|
int lines,
|
||||||
|
DataRequestMonitor<IInstruction[]> drm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the mixed disassembled code from an address range.
|
||||||
|
* If [startAddress] == null, disassemble from the instruction pointer.
|
||||||
|
*
|
||||||
|
* @param context Context of the disassembly code
|
||||||
|
* @param startAddress Beginning address
|
||||||
|
* @param endAddress End address
|
||||||
|
* @param drm Disassembled code
|
||||||
|
*/
|
||||||
|
public void getMixedInstructions(
|
||||||
|
IDisassemblyDMContext context,
|
||||||
|
BigInteger startAddress,
|
||||||
|
BigInteger endAddress,
|
||||||
|
DataRequestMonitor<IMixedInstruction[]> drm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the mixed disassembled code from a file location.
|
||||||
|
* If [lines] == -1, the whole function is disassembled.
|
||||||
|
*
|
||||||
|
* @param context Context of the disassembly code
|
||||||
|
* @param filename File to disassemble
|
||||||
|
* @param linenum Line number within the file
|
||||||
|
* @param lines Number of lines of disassembled code to produce
|
||||||
|
* @param drm Disassembled code
|
||||||
|
*/
|
||||||
|
public void getMixedInstructions(
|
||||||
|
IDisassemblyDMContext context,
|
||||||
|
String filename,
|
||||||
|
int linenum,
|
||||||
|
int lines,
|
||||||
|
DataRequestMonitor<IMixedInstruction[]> drm);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 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.dd.dsf.debug.service;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an assembly instruction
|
||||||
|
*/
|
||||||
|
public interface IInstruction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the instruction address.
|
||||||
|
*/
|
||||||
|
BigInteger getAdress();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the function name.
|
||||||
|
*/
|
||||||
|
String getFuntionName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the offset of this machine instruction
|
||||||
|
*/
|
||||||
|
long getOffset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the instruction.
|
||||||
|
*/
|
||||||
|
String getInstruction();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the opcode
|
||||||
|
*/
|
||||||
|
String getOpcode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return any arguments to the instruction
|
||||||
|
*/
|
||||||
|
String getArgs();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 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.dd.dsf.debug.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the assembly instruction(s) corresponding to a source line
|
||||||
|
*/
|
||||||
|
public interface IMixedInstruction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the file name
|
||||||
|
*/
|
||||||
|
String getFileName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the line Number.
|
||||||
|
*/
|
||||||
|
int getLineNumber();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the array of instruction.
|
||||||
|
*/
|
||||||
|
IInstruction[] getInstructions();
|
||||||
|
|
||||||
|
}
|
|
@ -88,7 +88,7 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void launchLocalDebugSession( ILaunchConfiguration config, ILaunch l, IProgressMonitor monitor ) throws CoreException {
|
private void launchLocalDebugSession( final ILaunchConfiguration config, ILaunch l, IProgressMonitor monitor ) throws CoreException {
|
||||||
if ( monitor.isCanceled() ) {
|
if ( monitor.isCanceled() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -154,8 +154,9 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate
|
||||||
GDBControl gdbControl = tracker.getService(GDBControl.class);
|
GDBControl gdbControl = tracker.getService(GDBControl.class);
|
||||||
if (gdbControl != null) {
|
if (gdbControl != null) {
|
||||||
IMemoryBlockRetrieval memRetrieval = new DsfMemoryBlockRetrieval(
|
IMemoryBlockRetrieval memRetrieval = new DsfMemoryBlockRetrieval(
|
||||||
GDB_DEBUG_MODEL_ID, (IMemoryDMContext)gdbControl.getControlDMContext());
|
GDB_DEBUG_MODEL_ID, config, (IMemoryDMContext)gdbControl.getControlDMContext());
|
||||||
launch.getSession().registerModelAdapter(IMemoryBlockRetrieval.class, memRetrieval);
|
launch.getSession().registerModelAdapter(IMemoryBlockRetrieval.class, memRetrieval);
|
||||||
|
((DsfMemoryBlockRetrieval) memRetrieval).initialize();
|
||||||
}
|
}
|
||||||
tracker.dispose();
|
tracker.dispose();
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.eclipse.dd.mi.service.CSourceLookup;
|
||||||
import org.eclipse.dd.mi.service.ExpressionService;
|
import org.eclipse.dd.mi.service.ExpressionService;
|
||||||
import org.eclipse.dd.mi.service.MIBreakpoints;
|
import org.eclipse.dd.mi.service.MIBreakpoints;
|
||||||
import org.eclipse.dd.mi.service.MIBreakpointsManager;
|
import org.eclipse.dd.mi.service.MIBreakpointsManager;
|
||||||
|
import org.eclipse.dd.mi.service.MIDisassembly;
|
||||||
import org.eclipse.dd.mi.service.MIMemory;
|
import org.eclipse.dd.mi.service.MIMemory;
|
||||||
import org.eclipse.dd.mi.service.MIModules;
|
import org.eclipse.dd.mi.service.MIModules;
|
||||||
import org.eclipse.dd.mi.service.MIRegisters;
|
import org.eclipse.dd.mi.service.MIRegisters;
|
||||||
|
@ -121,6 +122,10 @@ public class LaunchSequence extends Sequence {
|
||||||
public void execute(RequestMonitor requestMonitor) {
|
public void execute(RequestMonitor requestMonitor) {
|
||||||
new MIRegisters(fSession).initialize(requestMonitor);
|
new MIRegisters(fSession).initialize(requestMonitor);
|
||||||
}},
|
}},
|
||||||
|
new Step() { @Override
|
||||||
|
public void execute(RequestMonitor requestMonitor) {
|
||||||
|
new MIDisassembly(fSession).initialize(requestMonitor);
|
||||||
|
}},
|
||||||
/*
|
/*
|
||||||
* If needed, insert breakpoint at main and run to it.
|
* If needed, insert breakpoint at main and run to it.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.eclipse.dd.mi.service.CSourceLookup;
|
||||||
import org.eclipse.dd.mi.service.ExpressionService;
|
import org.eclipse.dd.mi.service.ExpressionService;
|
||||||
import org.eclipse.dd.mi.service.MIBreakpoints;
|
import org.eclipse.dd.mi.service.MIBreakpoints;
|
||||||
import org.eclipse.dd.mi.service.MIBreakpointsManager;
|
import org.eclipse.dd.mi.service.MIBreakpointsManager;
|
||||||
|
import org.eclipse.dd.mi.service.MIDisassembly;
|
||||||
import org.eclipse.dd.mi.service.MIMemory;
|
import org.eclipse.dd.mi.service.MIMemory;
|
||||||
import org.eclipse.dd.mi.service.MIModules;
|
import org.eclipse.dd.mi.service.MIModules;
|
||||||
import org.eclipse.dd.mi.service.MIRegisters;
|
import org.eclipse.dd.mi.service.MIRegisters;
|
||||||
|
@ -63,6 +64,11 @@ public class ShutdownSequence extends Sequence {
|
||||||
fTracker = null;
|
fTracker = null;
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
}
|
}
|
||||||
|
}, new Step() {
|
||||||
|
@Override
|
||||||
|
public void execute(RequestMonitor requestMonitor) {
|
||||||
|
shutdownService(MIDisassembly.class, requestMonitor);
|
||||||
|
}
|
||||||
}, new Step() {
|
}, new Step() {
|
||||||
@Override
|
@Override
|
||||||
public void execute(RequestMonitor requestMonitor) {
|
public void execute(RequestMonitor requestMonitor) {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
package org.eclipse.dd.gdb.service.command;
|
package org.eclipse.dd.gdb.service.command;
|
||||||
|
|
||||||
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IDisassembly.IDisassemblyDMContext;
|
||||||
import org.eclipse.dd.dsf.debug.service.IMemory.IMemoryDMContext;
|
import org.eclipse.dd.dsf.debug.service.IMemory.IMemoryDMContext;
|
||||||
import org.eclipse.dd.dsf.debug.service.IModules.ISymbolDMContext;
|
import org.eclipse.dd.dsf.debug.service.IModules.ISymbolDMContext;
|
||||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
|
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
|
@ -23,7 +24,7 @@ import org.eclipse.dd.mi.service.command.MIControlDMContext;
|
||||||
*/
|
*/
|
||||||
public class GDBControlDMContext extends MIControlDMContext
|
public class GDBControlDMContext extends MIControlDMContext
|
||||||
implements IContainerDMContext, ISymbolDMContext, IMemoryDMContext, IBreakpointsTargetDMContext, ISourceLookupDMContext,
|
implements IContainerDMContext, ISymbolDMContext, IMemoryDMContext, IBreakpointsTargetDMContext, ISourceLookupDMContext,
|
||||||
ISignalsDMContext
|
ISignalsDMContext, IDisassemblyDMContext
|
||||||
{
|
{
|
||||||
|
|
||||||
public GDBControlDMContext(String sessionId, String commandControlId) {
|
public GDBControlDMContext(String sessionId, String commandControlId) {
|
||||||
|
|
|
@ -0,0 +1,200 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 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.dd.mi.service;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IDisassembly;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IInstruction;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IMixedInstruction;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.command.ICommandControl;
|
||||||
|
import org.eclipse.dd.dsf.service.AbstractDsfService;
|
||||||
|
import org.eclipse.dd.dsf.service.DsfSession;
|
||||||
|
import org.eclipse.dd.mi.internal.MIPlugin;
|
||||||
|
import org.eclipse.dd.mi.service.command.commands.MIDataDisassemble;
|
||||||
|
import org.eclipse.dd.mi.service.command.output.MIDataDisassembleInfo;
|
||||||
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
|
public class MIDisassembly extends AbstractDsfService implements IDisassembly {
|
||||||
|
|
||||||
|
// Services
|
||||||
|
ICommandControl fConnection;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// AbstractDsfService
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service constructor
|
||||||
|
*
|
||||||
|
* @param session The debugging session
|
||||||
|
*/
|
||||||
|
public MIDisassembly(DsfSession session) {
|
||||||
|
super(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.dd.dsf.service.AbstractDsfService#initialize(org.eclipse.dd.dsf.concurrent.RequestMonitor)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void initialize(final RequestMonitor rm) {
|
||||||
|
super.initialize(new RequestMonitor(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleOK() {
|
||||||
|
doInitialize(rm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doInitialize(final RequestMonitor rm) {
|
||||||
|
fConnection = getServicesTracker().getService(ICommandControl.class);
|
||||||
|
// getSession().addServiceEventListener(this, null);
|
||||||
|
register(new String[] { IDisassembly.class.getName(), MIDisassembly.class.getName() },
|
||||||
|
new Hashtable<String, String>());
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.dd.dsf.service.AbstractDsfService#shutdown(org.eclipse.dd.dsf.concurrent.RequestMonitor)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void shutdown(RequestMonitor rm) {
|
||||||
|
unregister();
|
||||||
|
// getSession().removeServiceEventListener(this);
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.dd.dsf.service.AbstractDsfService#getBundleContext()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected BundleContext getBundleContext() {
|
||||||
|
return MIPlugin.getBundleContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// IDisassembly
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.dd.dsf.debug.service.IDisassembly#getInstructions(org.eclipse.dd.dsf.debug.service.IDisassembly.IDisassemblyDMContext, java.math.BigInteger, java.math.BigInteger, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
|
||||||
|
*/
|
||||||
|
public void getInstructions(IDisassemblyDMContext context,
|
||||||
|
BigInteger startAddress, BigInteger endAddress,
|
||||||
|
final DataRequestMonitor<IInstruction[]> drm)
|
||||||
|
{
|
||||||
|
// Validate the context
|
||||||
|
if (context == null) {
|
||||||
|
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
|
||||||
|
drm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go for it
|
||||||
|
String start = (startAddress != null) ? startAddress.toString() : "$pc"; //$NON-NLS-1$
|
||||||
|
String end = (endAddress != null) ? endAddress.toString() : "$pc + 100"; //$NON-NLS-1$
|
||||||
|
fConnection.queueCommand(new MIDataDisassemble(context, start, end, false),
|
||||||
|
new DataRequestMonitor<MIDataDisassembleInfo>(getExecutor(), drm) {
|
||||||
|
@Override
|
||||||
|
protected void handleOK() {
|
||||||
|
IInstruction[] result = getData().getMIAssemblyCode();
|
||||||
|
drm.setData(result);
|
||||||
|
drm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.dd.dsf.debug.service.IDisassembly#getInstructions(org.eclipse.dd.dsf.debug.service.IDisassembly.IDisassemblyDMContext, java.lang.String, int, int, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
|
||||||
|
*/
|
||||||
|
public void getInstructions(IDisassemblyDMContext context, String filename,
|
||||||
|
int linenum, int lines, final DataRequestMonitor<IInstruction[]> drm)
|
||||||
|
{
|
||||||
|
// Validate the context
|
||||||
|
if (context == null) {
|
||||||
|
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
|
||||||
|
drm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go for it
|
||||||
|
fConnection.queueCommand(new MIDataDisassemble(context, filename, linenum, lines, false),
|
||||||
|
new DataRequestMonitor<MIDataDisassembleInfo>(getExecutor(), drm) {
|
||||||
|
@Override
|
||||||
|
protected void handleOK() {
|
||||||
|
IInstruction[] result = getData().getMIAssemblyCode();
|
||||||
|
drm.setData(result);
|
||||||
|
drm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.dd.dsf.debug.service.IDisassembly#getMixedInstructions(org.eclipse.dd.dsf.debug.service.IDisassembly.IDisassemblyDMContext, java.math.BigInteger, java.math.BigInteger, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
|
||||||
|
*/
|
||||||
|
public void getMixedInstructions(IDisassemblyDMContext context,
|
||||||
|
BigInteger startAddress, BigInteger endAddress,
|
||||||
|
final DataRequestMonitor<IMixedInstruction[]> drm)
|
||||||
|
{
|
||||||
|
// Validate the context
|
||||||
|
if (context == null) {
|
||||||
|
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
|
||||||
|
drm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go for it
|
||||||
|
String start = (startAddress != null) ? startAddress.toString() : "$pc"; //$NON-NLS-1$
|
||||||
|
String end = (endAddress != null) ? endAddress.toString() : "$pc + 100"; //$NON-NLS-1$
|
||||||
|
fConnection.queueCommand(new MIDataDisassemble(context, start, end, true),
|
||||||
|
new DataRequestMonitor<MIDataDisassembleInfo>(getExecutor(), drm) {
|
||||||
|
@Override
|
||||||
|
protected void handleOK() {
|
||||||
|
IMixedInstruction[] result = getData().getMIMixedCode();
|
||||||
|
drm.setData(result);
|
||||||
|
drm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.eclipse.dd.dsf.debug.service.IDisassembly#getMixedInstructions(org.eclipse.dd.dsf.debug.service.IDisassembly.IDisassemblyDMContext, java.lang.String, int, int, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
|
||||||
|
*/
|
||||||
|
public void getMixedInstructions(IDisassemblyDMContext context,
|
||||||
|
String filename, int linenum, int lines,
|
||||||
|
final DataRequestMonitor<IMixedInstruction[]> drm)
|
||||||
|
{
|
||||||
|
// Validate the context
|
||||||
|
if (context == null) {
|
||||||
|
drm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
|
||||||
|
drm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go for it
|
||||||
|
fConnection.queueCommand(new MIDataDisassemble(context, filename, linenum, lines, true),
|
||||||
|
new DataRequestMonitor<MIDataDisassembleInfo>(getExecutor(), drm) {
|
||||||
|
@Override
|
||||||
|
protected void handleOK() {
|
||||||
|
IMixedInstruction[] result = getData().getMIMixedCode();
|
||||||
|
drm.setData(result);
|
||||||
|
drm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2008 QNX Software Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* QNX Software Systems - Initial API and implementation
|
||||||
|
* Ericsson - Modified for DSF Reference Implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.dd.mi.service.command.commands;
|
||||||
|
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IDisassembly.IDisassemblyDMContext;
|
||||||
|
import org.eclipse.dd.mi.service.command.output.MIDataDisassembleInfo;
|
||||||
|
import org.eclipse.dd.mi.service.command.output.MIOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* -data-disassemble
|
||||||
|
* [ -s START-ADDR -e END-ADDR ]
|
||||||
|
* | [ -f FILENAME -l LINENUM [ -n LINES ] ]
|
||||||
|
* -- MODE
|
||||||
|
*
|
||||||
|
* Where:
|
||||||
|
*
|
||||||
|
* '-s START-ADDR'
|
||||||
|
* is the beginning address (or '$pc')
|
||||||
|
*
|
||||||
|
* '-e END-ADDR'
|
||||||
|
* is the end address
|
||||||
|
*
|
||||||
|
* '-f FILENAME'
|
||||||
|
* is the name of the file to disassemble
|
||||||
|
*
|
||||||
|
* '-l LINENUM'
|
||||||
|
* is the line number to disassemble around
|
||||||
|
*
|
||||||
|
* -n LINES'
|
||||||
|
* is the the number of disassembly lines to be produced. If it is
|
||||||
|
* -1, the whole function will be disassembled, in case no END-ADDR is
|
||||||
|
* specified. If END-ADDR is specified as a non-zero value, and
|
||||||
|
* LINES is lower than the number of disassembly lines between
|
||||||
|
* START-ADDR and END-ADDR, only LINES lines are displayed; if LINES
|
||||||
|
* is higher than the number of lines between START-ADDR and
|
||||||
|
* END-ADDR, only the lines up to END-ADDR are displayed.
|
||||||
|
*
|
||||||
|
* '-- MODE'
|
||||||
|
* is either 0 (meaning only disassembly) or 1 (meaning mixed source
|
||||||
|
* and disassembly).
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MIDataDisassemble extends MICommand<MIDataDisassembleInfo> {
|
||||||
|
|
||||||
|
public MIDataDisassemble(IDisassemblyDMContext ctx, String start, String end, boolean mode) {
|
||||||
|
super(ctx, "-data-disassemble"); //$NON-NLS-1$
|
||||||
|
setOptions(new String[]{"-s", start, "-e", end}); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
String mixed = "0"; //$NON-NLS-1$
|
||||||
|
if (mode) {
|
||||||
|
mixed = "1"; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
setParameters(new String[]{mixed});
|
||||||
|
}
|
||||||
|
|
||||||
|
public MIDataDisassemble(IDisassemblyDMContext ctx, String file, int linenum, int lines, boolean mode) {
|
||||||
|
super(ctx, "-data-disassemble"); //$NON-NLS-1$
|
||||||
|
setOptions(new String[]{"-f", file, "-l", //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
Integer.toString(linenum), "-n", Integer.toString(lines)}); //$NON-NLS-1$
|
||||||
|
String mixed = "0"; //$NON-NLS-1$
|
||||||
|
if (mode) {
|
||||||
|
mixed = "1"; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
setParameters(new String[]{mixed});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GDB the -data-disassemble uses "--" as a separator wit only the MODE
|
||||||
|
* So override the MICommand
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String parametersToString() {
|
||||||
|
String[] parameters = getParameters();
|
||||||
|
if (parameters != null && parameters.length > 0) {
|
||||||
|
return "-- " + parameters[0]; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
return new String();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MIDataDisassembleInfo getResult(MIOutput output) {
|
||||||
|
return new MIDataDisassembleInfo(output);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2008 QNX Software Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* QNX Software Systems - Initial API and implementation
|
||||||
|
* Ericsson - Modified for DSF Reference Implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.dd.mi.service.command.output;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parsed output of the data-disassemble command. The output format is
|
||||||
|
* determined by the mode field on the request.
|
||||||
|
*
|
||||||
|
* -data-disassemble -s $pc -e "$pc + 20" -- 0
|
||||||
|
* ^done,asm_insns=[
|
||||||
|
* {address="0x000107c0",func-name="main",offset="4",inst="mov 2, %o0"},
|
||||||
|
* {address="0x000107c4",func-name="main",offset="8",inst="sethi %hi(0x11800), %o2"},
|
||||||
|
* {address="0x000107c8",func-name="main",offset="12",inst="or %o2, 0x140, %o1\t! 0x11940 <_lib_version+8>"},
|
||||||
|
* {address="0x000107cc",func-name="main",offset="16",inst="sethi %hi(0x11800), %o2"},
|
||||||
|
* {address="0x000107d0",func-name="main",offset="20",inst="or %o2, 0x168, %o4\t! 0x11968 <_lib_version+48>"}]
|
||||||
|
*
|
||||||
|
* -data-disassemble -f basics.c -l 32 -- 0
|
||||||
|
* ^done,asm_insns=[
|
||||||
|
* {address="0x000107bc",func-name="main",offset="0",inst="save %sp, -112, %sp"},
|
||||||
|
* {address="0x000107c0",func-name="main",offset="4",inst="mov 2, %o0"},
|
||||||
|
* {address="0x000107c4",func-name="main",offset="8",inst="sethi %hi(0x11800), %o2"},
|
||||||
|
* [...]
|
||||||
|
* {address="0x0001081c",func-name="main",offset="96",inst="ret "},
|
||||||
|
* {address="0x00010820",func-name="main",offset="100",inst="restore "}]
|
||||||
|
*
|
||||||
|
* -data-disassemble -f basics.c -l 32 -n 3 -- 1
|
||||||
|
* ^done,asm_insns=[
|
||||||
|
* src_and_asm_line={line="31",file="/dir1/dir2/basics.c",line_asm_insn=[
|
||||||
|
* {address="0x000107bc",func-name="main",offset="0",inst="save %sp, -112, %sp"}]},
|
||||||
|
* src_and_asm_line={line="32",file="/dir1/dir2/basics.c",line_asm_insn=[
|
||||||
|
* {address="0x000107c0",func-name="main",offset="4",inst="mov 2, %o0"},
|
||||||
|
* {address="0x000107c4",func-name="main",offset="8",inst="sethi %hi(0x11800), %o2"}]}]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MIDataDisassembleInfo extends MIInfo {
|
||||||
|
|
||||||
|
// The parsed information
|
||||||
|
private boolean mixed;
|
||||||
|
private MIMixedInstruction[] mixedCode;
|
||||||
|
private MIInstruction[] assemblyCode;
|
||||||
|
|
||||||
|
public MIDataDisassembleInfo(MIOutput record) {
|
||||||
|
super(record);
|
||||||
|
mixed = false;
|
||||||
|
parse();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMixed() {
|
||||||
|
return mixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MIInstruction[] getMIAssemblyCode() {
|
||||||
|
return assemblyCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MIMixedInstruction[] getMIMixedCode() {
|
||||||
|
return mixedCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the relevant tag in the output record ("asm_insns") and then
|
||||||
|
* parse its value.
|
||||||
|
*/
|
||||||
|
private void parse() {
|
||||||
|
List<MIInstruction> asmList = new ArrayList<MIInstruction>();
|
||||||
|
List<MIMixedInstruction> srcList = new ArrayList<MIMixedInstruction>();
|
||||||
|
|
||||||
|
if (isDone()) {
|
||||||
|
MIOutput out = getMIOutput();
|
||||||
|
MIResultRecord rr = out.getMIResultRecord();
|
||||||
|
if (rr != null) {
|
||||||
|
MIResult[] results = rr.getMIResults();
|
||||||
|
// Technically, there should be only one field (asm_insns), but just in case...
|
||||||
|
for (int i = 0; i < results.length; i++) {
|
||||||
|
String var = results[i].getVariable();
|
||||||
|
if (var.equals("asm_insns")) { //$NON-NLS-1$
|
||||||
|
MIValue value = results[i].getMIValue();
|
||||||
|
if (value instanceof MIList) {
|
||||||
|
parseResult((MIList) value, srcList, asmList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assemblyCode = asmList.toArray(new MIInstruction[asmList.size()]);
|
||||||
|
mixedCode = srcList.toArray(new MIMixedInstruction[srcList.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the back-end result. Depending on the requested mode
|
||||||
|
* ("-- 0" or "-- 1" on the request), the result has one of the
|
||||||
|
* following forms:
|
||||||
|
*
|
||||||
|
* [1] Mode == 0 (assembly instructions only)
|
||||||
|
* {address="0x000107c0",func-name="main",offset="4",inst="mov 2, %o0"},
|
||||||
|
* {address="0x000107c4",func-name="main",offset="8",inst="sethi %hi(0x11800), %o2"},
|
||||||
|
* ...,
|
||||||
|
* {address="0x00010820",func-name="main",offset="100",inst="restore "}
|
||||||
|
*
|
||||||
|
* [2] Mode == 1 (Mixed source and assembly code)
|
||||||
|
* src_and_asm_line={
|
||||||
|
* line="31",file="/dir1/dir2/basics.c",
|
||||||
|
* line_asm_insn=[
|
||||||
|
* {address="0x000107c0",func-name="main",offset="4",inst="mov 2, %o0"},
|
||||||
|
* {address="0x000107c4",func-name="main",offset="8",inst="sethi %hi(0x11800), %o2"},
|
||||||
|
* ...,
|
||||||
|
* {address="0x00010820",func-name="main",offset="100",inst="restore "}
|
||||||
|
* ]
|
||||||
|
* },
|
||||||
|
* ...,
|
||||||
|
* src_and_asm_line={
|
||||||
|
* line="31",file="/dir1/dir2/basics.c",
|
||||||
|
* line_asm_insn=[
|
||||||
|
* ...,
|
||||||
|
* ]
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
private void parseResult(MIList list,
|
||||||
|
List<MIMixedInstruction> srcList, List<MIInstruction> asmList) {
|
||||||
|
|
||||||
|
// Mixed mode (with source)
|
||||||
|
MIResult[] results = list.getMIResults();
|
||||||
|
if (results != null && results.length > 0) {
|
||||||
|
for (int i = 0; i < results.length; i++) {
|
||||||
|
String var = results[i].getVariable();
|
||||||
|
if (var.equals("src_and_asm_line")) { //$NON-NLS-1$
|
||||||
|
MIValue value = results[i].getMIValue();
|
||||||
|
if (value instanceof MITuple) {
|
||||||
|
srcList.add(new MIMixedInstruction((MITuple) value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mixed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-mixed mode
|
||||||
|
MIValue[] values = list.getMIValues();
|
||||||
|
if (values != null && values.length > 0) {
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
if (values[i] instanceof MITuple) {
|
||||||
|
asmList.add(new MIInstruction((MITuple) values[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mixed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 QNX Software Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* QNX Software Systems - Initial API and implementation
|
||||||
|
* Ericsson - Adapted for DSF
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.dd.mi.service.command.output;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IInstruction;
|
||||||
|
|
||||||
|
public class MIInstruction implements IInstruction {
|
||||||
|
|
||||||
|
// The parsed information
|
||||||
|
BigInteger address;
|
||||||
|
String function = ""; //$NON-NLS-1$
|
||||||
|
long offset;
|
||||||
|
String opcode = ""; //$NON-NLS-1$
|
||||||
|
String args = ""; //$NON-NLS-1$
|
||||||
|
|
||||||
|
public MIInstruction(MITuple tuple) {
|
||||||
|
parse(tuple);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BigInteger getAdress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFuntionName() {
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getOffset() {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstruction() {
|
||||||
|
return opcode + " " + args; //$NON-NLS-1$;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOpcode() {
|
||||||
|
return opcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getArgs() {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the assembly instruction result. Each instruction has the following
|
||||||
|
* fields:
|
||||||
|
* - Address
|
||||||
|
* - Function name
|
||||||
|
* - Offset
|
||||||
|
* - Instruction
|
||||||
|
*
|
||||||
|
* {address="0x000107c0",func-name="main",offset="4",inst="mov 2, %o0"},
|
||||||
|
* {address="0x000107c4",func-name="main",offset="8",inst="sethi %hi(0x11800), %o2"},
|
||||||
|
* ...,
|
||||||
|
* {address="0x00010820",func-name="main",offset="100",inst="restore "}
|
||||||
|
*
|
||||||
|
* In addition, the opcode and arguments are extracted form the assembly instruction.
|
||||||
|
*/
|
||||||
|
private void parse(MITuple tuple) {
|
||||||
|
MIResult[] results = tuple.getMIResults();
|
||||||
|
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).getCString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var.equals("address")) { //$NON-NLS-1$
|
||||||
|
try {
|
||||||
|
address = new BigInteger(str.trim(), 16);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var.equals("func-name")) { //$NON-NLS-1$
|
||||||
|
function = str;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var.equals("offset")) { //$NON-NLS-1$
|
||||||
|
try {
|
||||||
|
offset = Long.decode(str.trim()).longValue();
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var.equals("inst")) { //$NON-NLS-1$
|
||||||
|
/* for the instruction, we do not want the C string but the
|
||||||
|
translated string since the only thing we are doing is
|
||||||
|
displaying it. */
|
||||||
|
str = ((MIConst) value).getString();
|
||||||
|
|
||||||
|
char chars[] = str.toCharArray();
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
// count the non-whitespace characters.
|
||||||
|
while( (index < chars.length) && (chars[index] > '\u0020'))
|
||||||
|
index++;
|
||||||
|
|
||||||
|
opcode = str.substring( 0, index );
|
||||||
|
|
||||||
|
// skip any whitespace characters
|
||||||
|
while( index < chars.length && chars[index] >= '\u0000' && chars[index] <= '\u0020')
|
||||||
|
index++;
|
||||||
|
|
||||||
|
// guard no argument
|
||||||
|
if( index < chars.length )
|
||||||
|
args = str.substring( index );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 QNX Software Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* QNX Software Systems - Initial API and implementation
|
||||||
|
* Ericsson - Adapted for DSF
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.dd.mi.service.command.output;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IInstruction;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IMixedInstruction;
|
||||||
|
|
||||||
|
public class MIMixedInstruction implements IMixedInstruction {
|
||||||
|
|
||||||
|
// The parsed information
|
||||||
|
private String fileName = ""; //$NON-NLS-1$
|
||||||
|
private int lineNumber = 0;
|
||||||
|
private MIInstruction[] assemblyCode;
|
||||||
|
|
||||||
|
public MIMixedInstruction(MITuple tuple) {
|
||||||
|
parse(tuple);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileName() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLineNumber() {
|
||||||
|
return lineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IInstruction[] getInstructions() {
|
||||||
|
return assemblyCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the mixed instruction result. It has the following 3 fields:
|
||||||
|
*
|
||||||
|
* line="31",
|
||||||
|
* file="/dir1/dir2/basics.c",
|
||||||
|
* line_asm_insn=[
|
||||||
|
* {address="0x000107c0",func-name="main",offset="4",inst="mov 2, %o0"},
|
||||||
|
* {address="0x000107c4",func-name="main",offset="8",inst="sethi %hi(0x11800), %o2"},
|
||||||
|
* ...,
|
||||||
|
* {address="0x00010820",func-name="main",offset="100",inst="restore "}
|
||||||
|
* ]
|
||||||
|
*/
|
||||||
|
private void parse(MITuple tuple) {
|
||||||
|
List<MIInstruction> instructions = new ArrayList<MIInstruction>();
|
||||||
|
MIResult[] results = tuple.getMIResults();
|
||||||
|
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).getCString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var.equals("line")) { //$NON-NLS-1$
|
||||||
|
try {
|
||||||
|
lineNumber = Integer.parseInt(str.trim());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var.equals("file")) { //$NON-NLS-1$
|
||||||
|
fileName = str;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var.equals("line_asm_insn")) { //$NON-NLS-1$
|
||||||
|
if (value instanceof MIList) {
|
||||||
|
MIList list = (MIList) value;
|
||||||
|
MIValue[] values = list.getMIValues();
|
||||||
|
for (int j = 0; j < values.length; j++) {
|
||||||
|
if (values[j] instanceof MITuple) {
|
||||||
|
instructions.add(new MIInstruction((MITuple) values[j]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assemblyCode = instructions.toArray(new MIInstruction[instructions.size()]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/BreakpointTestApp.exe
Executable file
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/BreakpointTestApp.exe
Executable file
Binary file not shown.
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/ExpressionTestApp.exe
Executable file
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/ExpressionTestApp.exe
Executable file
Binary file not shown.
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/GDBMIGenericTestApp.exe
Executable file
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/GDBMIGenericTestApp.exe
Executable file
Binary file not shown.
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/MemoryTestApp.exe
Executable file
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/MemoryTestApp.exe
Executable file
Binary file not shown.
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/MultiThread.exe
Executable file
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/MultiThread.exe
Executable file
Binary file not shown.
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/SpecialTestApp.exe
Executable file
BIN
plugins/org.eclipse.dd.tests.gdb/data/launch/bin/SpecialTestApp.exe
Executable file
Binary file not shown.
|
@ -0,0 +1,592 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 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 Implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.dd.tests.gdb;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.IAddress;
|
||||||
|
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||||
|
import org.eclipse.cdt.utils.Addr64;
|
||||||
|
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IExpressions;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IFormattedValues;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IInstruction;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IMixedInstruction;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IDisassembly.IDisassemblyDMContext;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
|
||||||
|
import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMData;
|
||||||
|
import org.eclipse.dd.dsf.service.DsfServicesTracker;
|
||||||
|
import org.eclipse.dd.dsf.service.DsfSession;
|
||||||
|
import org.eclipse.dd.gdb.service.command.GDBControl;
|
||||||
|
import org.eclipse.dd.gdb.service.command.GDBControlDMContext;
|
||||||
|
import org.eclipse.dd.mi.service.MIDisassembly;
|
||||||
|
import org.eclipse.dd.tests.gdb.framework.AsyncCompletionWaitor;
|
||||||
|
import org.eclipse.dd.tests.gdb.framework.BackgroundRunner;
|
||||||
|
import org.eclipse.dd.tests.gdb.framework.BaseTestCase;
|
||||||
|
import org.eclipse.dd.tests.gdb.framework.SyncUtil;
|
||||||
|
import org.eclipse.dd.tests.gdb.launching.TestsPlugin;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the Disassembly Service test suite.
|
||||||
|
*
|
||||||
|
* It is meant to be a regression suite to be executed automatically against
|
||||||
|
* the DSF nightly builds.
|
||||||
|
*
|
||||||
|
* It is also meant to be augmented with a proper test case(s) every time a
|
||||||
|
* feature is added or in the event (unlikely :-) that a bug is found in the
|
||||||
|
* Disassembly Service.
|
||||||
|
*
|
||||||
|
* Refer to the JUnit4 documentation for an explanation of the annotations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@RunWith(BackgroundRunner.class)
|
||||||
|
public class MIDisassemblyTest extends BaseTestCase {
|
||||||
|
|
||||||
|
private static final String FILE_NAME = "MemoryTestApp.cc";
|
||||||
|
private static final int LINE_NUMBER = 35;
|
||||||
|
private static final String INVALID_FILE_NAME = "invalid_filename";
|
||||||
|
|
||||||
|
private final AsyncCompletionWaitor fWait = new AsyncCompletionWaitor();
|
||||||
|
private DsfSession fSession;
|
||||||
|
private DsfServicesTracker fServicesTracker;
|
||||||
|
private GDBControlDMContext fGdbControlDmc;
|
||||||
|
private MIDisassembly fDisassembly;
|
||||||
|
private IExpressions fExpressionService;
|
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Housekeeping stuff
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void testSuiteInitialization() {
|
||||||
|
// Select the binary to run the tests against
|
||||||
|
setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, "data/launch/bin/MemoryTestApp.exe");
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void testSuiteCleanup() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void testCaseInitialization() {
|
||||||
|
fSession = getGDBLaunch().getSession();
|
||||||
|
|
||||||
|
// Get a reference to the memory service
|
||||||
|
fServicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), fSession.getId());
|
||||||
|
assert(fServicesTracker != null);
|
||||||
|
|
||||||
|
GDBControl gdbControl = fServicesTracker.getService(GDBControl.class);
|
||||||
|
fGdbControlDmc = gdbControl.getGDBDMContext();
|
||||||
|
assert(fGdbControlDmc != null);
|
||||||
|
|
||||||
|
fDisassembly = fServicesTracker.getService(MIDisassembly.class);
|
||||||
|
assert(fDisassembly != null);
|
||||||
|
|
||||||
|
fExpressionService = fServicesTracker.getService(IExpressions.class);
|
||||||
|
assert(fExpressionService != null);
|
||||||
|
|
||||||
|
// fSession.addServiceEventListener(MIDisassemblyTest.this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void testCaseCleanup() {
|
||||||
|
// Clear the references (not strictly necessary)
|
||||||
|
// fSession.removeServiceEventListener(MIDisassemblyTest.this);
|
||||||
|
fExpressionService = null;
|
||||||
|
fDisassembly = null;
|
||||||
|
fServicesTracker.dispose();
|
||||||
|
fServicesTracker = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Helper Functions
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------
|
||||||
|
* evaluateExpression
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Invokes the ExpressionService to evaluate an expression. In theory, we
|
||||||
|
* shouldn't rely on another service to test this one but we need a way to
|
||||||
|
* access a variable from the test application in order verify that the
|
||||||
|
* memory operations (read/write) are working properly.
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* @param expression Expression to resolve
|
||||||
|
* @return Resolved expression
|
||||||
|
* @throws InterruptedException
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
private IAddress evaluateExpression(String expression) throws Throwable
|
||||||
|
{
|
||||||
|
// Create the expression and format contexts
|
||||||
|
final IExpressionDMContext expressionDMC = SyncUtil.SyncCreateExpression(fGdbControlDmc, expression);
|
||||||
|
final FormattedValueDMContext formattedValueDMC = SyncUtil.SyncGetFormattedValue(fExpressionService, expressionDMC, IFormattedValues.HEX_FORMAT);
|
||||||
|
|
||||||
|
// Create the DataRequestMonitor which will store the operation result in the wait object
|
||||||
|
final DataRequestMonitor<FormattedValueDMData> drm =
|
||||||
|
new DataRequestMonitor<FormattedValueDMData>(fSession.getExecutor(), null) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
if (getStatus().isOK()) {
|
||||||
|
fWait.setReturnInfo(getData());
|
||||||
|
}
|
||||||
|
fWait.waitFinished(getStatus());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Evaluate the expression (asynchronously)
|
||||||
|
fSession.getExecutor().submit(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
fExpressionService.getFormattedExpressionValue(formattedValueDMC, drm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for completion
|
||||||
|
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
assertTrue(fWait.getMessage(), fWait.isOK());
|
||||||
|
|
||||||
|
// Return the string formatted by the back-end
|
||||||
|
String result = "";
|
||||||
|
Object returnInfo = fWait.getReturnInfo();
|
||||||
|
if (returnInfo instanceof FormattedValueDMData)
|
||||||
|
result = ((FormattedValueDMData) returnInfo).getFormattedValue();
|
||||||
|
return new Addr64(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------
|
||||||
|
* getInstruction
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Issues a disassembly request. The result is stored in fWait.
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Typical usage:
|
||||||
|
* getInstruction(dmc, start, end);
|
||||||
|
* fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
* assertTrue(fWait.getMessage(), fWait.isOK());
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* @param dmc the data model context
|
||||||
|
* @param start the start address (null == $pc)
|
||||||
|
* @param end the end address
|
||||||
|
* @throws InterruptedException
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
private void getInstruction(final IDisassemblyDMContext dmc,
|
||||||
|
final BigInteger startAddress, final BigInteger endAddress)
|
||||||
|
throws InterruptedException
|
||||||
|
{
|
||||||
|
// Set the Data Request Monitor
|
||||||
|
final DataRequestMonitor<IInstruction[]> drm =
|
||||||
|
new DataRequestMonitor<IInstruction[]>(fSession.getExecutor(), null) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
if (getStatus().isOK()) {
|
||||||
|
fWait.setReturnInfo(getData());
|
||||||
|
}
|
||||||
|
fWait.waitFinished(getStatus());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Issue the get memory request
|
||||||
|
fSession.getExecutor().submit(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
fDisassembly.getInstructions(dmc, startAddress, endAddress, drm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------
|
||||||
|
* getInstruction
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Issues a disassembly request. The result is stored in fWait.
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Typical usage:
|
||||||
|
* getInstruction(dmc, start, end);
|
||||||
|
* fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
* assertTrue(fWait.getMessage(), fWait.isOK());
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* @param dmc the data model context
|
||||||
|
* @param fucntion the function
|
||||||
|
* @param linenum the line
|
||||||
|
* @param count the instruction count
|
||||||
|
* @throws InterruptedException
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
private void getInstruction(final IDisassemblyDMContext dmc,
|
||||||
|
final String function, final int linenum, final int count)
|
||||||
|
throws InterruptedException
|
||||||
|
{
|
||||||
|
// Set the Data Request Monitor
|
||||||
|
final DataRequestMonitor<IInstruction[]> drm =
|
||||||
|
new DataRequestMonitor<IInstruction[]>(fSession.getExecutor(), null) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
if (getStatus().isOK()) {
|
||||||
|
fWait.setReturnInfo(getData());
|
||||||
|
}
|
||||||
|
fWait.waitFinished(getStatus());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Issue the get memory request
|
||||||
|
fSession.getExecutor().submit(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
fDisassembly.getInstructions(dmc, function, linenum, count, drm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------
|
||||||
|
* getMixedInstruction
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Issues a disassembly request. The result is stored in fWait.
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Typical usage:
|
||||||
|
* getInstruction(dmc, start, end);
|
||||||
|
* fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
* assertTrue(fWait.getMessage(), fWait.isOK());
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* @param dmc the data model context
|
||||||
|
* @param start the start address (null == $pc)
|
||||||
|
* @param end the end address
|
||||||
|
* @throws InterruptedException
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
private void getMixedInstruction(final IDisassemblyDMContext dmc,
|
||||||
|
final BigInteger startAddress, final BigInteger endAddress)
|
||||||
|
throws InterruptedException
|
||||||
|
{
|
||||||
|
// Set the Data Request Monitor
|
||||||
|
final DataRequestMonitor<IMixedInstruction[]> drm =
|
||||||
|
new DataRequestMonitor<IMixedInstruction[]>(fSession.getExecutor(), null) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
if (getStatus().isOK()) {
|
||||||
|
fWait.setReturnInfo(getData());
|
||||||
|
}
|
||||||
|
fWait.waitFinished(getStatus());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Issue the get memory request
|
||||||
|
fSession.getExecutor().submit(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
fDisassembly.getMixedInstructions(dmc, startAddress, endAddress, drm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------
|
||||||
|
* getMixedInstruction
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Issues a disassembly request. The result is stored in fWait.
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* Typical usage:
|
||||||
|
* getInstruction(dmc, start, end);
|
||||||
|
* fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
* assertTrue(fWait.getMessage(), fWait.isOK());
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
* @param dmc the data model context
|
||||||
|
* @param start the start address (null == $pc)
|
||||||
|
* @param end the end address
|
||||||
|
* @throws InterruptedException
|
||||||
|
* ------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
private void getMixedInstruction(final IDisassemblyDMContext dmc,
|
||||||
|
final String function, final int linenum, final int count)
|
||||||
|
throws InterruptedException
|
||||||
|
{
|
||||||
|
// Set the Data Request Monitor
|
||||||
|
final DataRequestMonitor<IMixedInstruction[]> drm =
|
||||||
|
new DataRequestMonitor<IMixedInstruction[]>(fSession.getExecutor(), null) {
|
||||||
|
@Override
|
||||||
|
protected void handleCompleted() {
|
||||||
|
if (getStatus().isOK()) {
|
||||||
|
fWait.setReturnInfo(getData());
|
||||||
|
}
|
||||||
|
fWait.waitFinished(getStatus());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Issue the get memory request
|
||||||
|
fSession.getExecutor().submit(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
fDisassembly.getMixedInstructions(dmc, function, linenum, count, drm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================================================
|
||||||
|
// Test Cases
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Templates:
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// @ Test
|
||||||
|
// public void basicTest() {
|
||||||
|
// // First test to run
|
||||||
|
// assertTrue("", true);
|
||||||
|
// }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// @ Test(timeout=5000)
|
||||||
|
// public void timeoutTest() {
|
||||||
|
// // Second test to run, which will timeout if not finished on time
|
||||||
|
// assertTrue("", true);
|
||||||
|
// }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// @ Test(expected=FileNotFoundException.class)
|
||||||
|
// public void exceptionTest() throws FileNotFoundException {
|
||||||
|
// // Third test to run which expects an exception
|
||||||
|
// throw new FileNotFoundException("Just testing");
|
||||||
|
// }
|
||||||
|
// ========================================================================
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// getMemory tests
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// readWithNullContext
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
@Test(timeout=20000)
|
||||||
|
public void readWithNullContext() throws Throwable {
|
||||||
|
|
||||||
|
// Setup call parameters
|
||||||
|
BigInteger startAddress = null;
|
||||||
|
BigInteger endAddress = null;
|
||||||
|
|
||||||
|
// Perform the test
|
||||||
|
fWait.waitReset();
|
||||||
|
getInstruction(null, startAddress, endAddress);
|
||||||
|
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
String expected = "Unknown context type";
|
||||||
|
assertFalse(fWait.getMessage(), fWait.isOK());
|
||||||
|
assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
|
||||||
|
fWait.getMessage().contains(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// readWithInvalidAddress
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
@Test(timeout=20000)
|
||||||
|
public void readWithInvalidAddress() throws Throwable {
|
||||||
|
|
||||||
|
// Setup call parameters
|
||||||
|
BigInteger startAddress = BigInteger.ZERO;
|
||||||
|
BigInteger endAddress = null;
|
||||||
|
|
||||||
|
// Perform the test
|
||||||
|
fWait.waitReset();
|
||||||
|
getInstruction(fGdbControlDmc, startAddress, endAddress);
|
||||||
|
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
String expected = "Cannot access memory at address";
|
||||||
|
assertFalse(fWait.getMessage(), fWait.isOK());
|
||||||
|
assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
|
||||||
|
fWait.getMessage().contains(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// readWithNullAddress
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
@Test(timeout=20000)
|
||||||
|
public void readWithNullAddress() throws Throwable {
|
||||||
|
|
||||||
|
// Setup call parameters
|
||||||
|
BigInteger startAddress = null;
|
||||||
|
BigInteger endAddress = null;
|
||||||
|
|
||||||
|
// Perform the test
|
||||||
|
fWait.waitReset();
|
||||||
|
getInstruction(fGdbControlDmc, startAddress, endAddress);
|
||||||
|
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
assertTrue(fWait.getMessage(), fWait.isOK());
|
||||||
|
IInstruction[] result = (IInstruction[]) fWait.getReturnInfo();
|
||||||
|
assertTrue("No instruction retrieved", result.length != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// readWithValidAddress
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
@Test(timeout=20000)
|
||||||
|
public void readWithValidAddress() throws Throwable {
|
||||||
|
|
||||||
|
// Setup call parameters
|
||||||
|
Addr64 main = (Addr64) evaluateExpression("&main");
|
||||||
|
BigInteger startAddress = main.getValue();
|
||||||
|
BigInteger endAddress = null;
|
||||||
|
|
||||||
|
// Perform the test
|
||||||
|
fWait.waitReset();
|
||||||
|
getInstruction(fGdbControlDmc, startAddress, endAddress);
|
||||||
|
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
assertTrue(fWait.getMessage(), fWait.isOK());
|
||||||
|
IInstruction[] result = (IInstruction[]) fWait.getReturnInfo();
|
||||||
|
assertTrue("No instruction retrieved", result.length != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// readWithInvalidFilename
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
@Test(timeout=20000)
|
||||||
|
public void readWithValidFunction() throws Throwable {
|
||||||
|
|
||||||
|
// Setup call parameters
|
||||||
|
String filename = INVALID_FILE_NAME;
|
||||||
|
int linenum = 1;
|
||||||
|
int count = -1;
|
||||||
|
|
||||||
|
// Perform the test
|
||||||
|
fWait.waitReset();
|
||||||
|
getInstruction(fGdbControlDmc, filename, linenum, count);
|
||||||
|
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
String expected = "Invalid filename";
|
||||||
|
assertFalse(fWait.getMessage(), fWait.isOK());
|
||||||
|
assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
|
||||||
|
fWait.getMessage().contains(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// readWithInvalidLineNumber
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
@Test(timeout=20000)
|
||||||
|
public void readWithInvalidLineNumber() throws Throwable {
|
||||||
|
|
||||||
|
// Setup call parameters
|
||||||
|
String filename = FILE_NAME;
|
||||||
|
int linenum = -1;
|
||||||
|
int count = -1;
|
||||||
|
|
||||||
|
// Perform the test
|
||||||
|
fWait.waitReset();
|
||||||
|
getInstruction(fGdbControlDmc, filename, linenum, count);
|
||||||
|
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
String expected = "Invalid line number";
|
||||||
|
assertFalse(fWait.getMessage(), fWait.isOK());
|
||||||
|
assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
|
||||||
|
fWait.getMessage().contains(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// readWithValidFilename
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
@Test(timeout=20000)
|
||||||
|
public void readWithValidFilename() throws Throwable {
|
||||||
|
|
||||||
|
// Setup call parameters
|
||||||
|
String filename = FILE_NAME;
|
||||||
|
int linenum = LINE_NUMBER;
|
||||||
|
int count = -1;
|
||||||
|
|
||||||
|
// Perform the test
|
||||||
|
fWait.waitReset();
|
||||||
|
getInstruction(fGdbControlDmc, filename, linenum, count);
|
||||||
|
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
assertTrue(fWait.getMessage(), fWait.isOK());
|
||||||
|
IInstruction[] result = (IInstruction[]) fWait.getReturnInfo();
|
||||||
|
assertTrue("No instruction retrieved", result.length != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// readWithLineCount
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
@Test(timeout=20000)
|
||||||
|
public void readWithLineCount() throws Throwable {
|
||||||
|
|
||||||
|
// Setup call parameters
|
||||||
|
String filename = FILE_NAME;
|
||||||
|
int linenum = LINE_NUMBER;
|
||||||
|
int count = 5;
|
||||||
|
|
||||||
|
// Perform the test
|
||||||
|
fWait.waitReset();
|
||||||
|
getInstruction(fGdbControlDmc, filename, linenum, count);
|
||||||
|
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
assertTrue(fWait.getMessage(), fWait.isOK());
|
||||||
|
IInstruction[] result = (IInstruction[]) fWait.getReturnInfo();
|
||||||
|
assertTrue("Wrong number of instructions retrieved, expected " + count + ", got " + result.length,
|
||||||
|
result.length == count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// readMixedWithValidAddress
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
@Test(timeout=20000)
|
||||||
|
public void readMixedWithValidAddress() throws Throwable {
|
||||||
|
|
||||||
|
// Setup call parameters
|
||||||
|
Addr64 main = (Addr64) evaluateExpression("&main");
|
||||||
|
BigInteger startAddress = main.getValue();
|
||||||
|
BigInteger endAddress = null;
|
||||||
|
|
||||||
|
// Perform the test
|
||||||
|
fWait.waitReset();
|
||||||
|
getMixedInstruction(fGdbControlDmc, startAddress, endAddress);
|
||||||
|
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
assertTrue(fWait.getMessage(), fWait.isOK());
|
||||||
|
IMixedInstruction[] result = (IMixedInstruction[]) fWait.getReturnInfo();
|
||||||
|
assertTrue("No instruction retrieved", result.length != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// readMixedWithLineCount
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
@Test(timeout=20000)
|
||||||
|
public void readMixedWithLineCount() throws Throwable {
|
||||||
|
|
||||||
|
// Setup call parameters
|
||||||
|
String filename = FILE_NAME;
|
||||||
|
int linenum = LINE_NUMBER;
|
||||||
|
int count = 5;
|
||||||
|
|
||||||
|
// Perform the test
|
||||||
|
fWait.waitReset();
|
||||||
|
getMixedInstruction(fGdbControlDmc, filename, linenum, count);
|
||||||
|
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
|
||||||
|
|
||||||
|
// Verify the result
|
||||||
|
assertTrue(fWait.getMessage(), fWait.isOK());
|
||||||
|
IMixedInstruction[] result = (IMixedInstruction[]) fWait.getReturnInfo();
|
||||||
|
int total = 0;
|
||||||
|
for (IMixedInstruction mixed : result) {
|
||||||
|
IInstruction[] inst = mixed.getInstructions();
|
||||||
|
total += inst.length;
|
||||||
|
}
|
||||||
|
assertTrue("Wrong number of instructions retrieved, expected " + count + ", got " + result.length,
|
||||||
|
total == count);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ import org.eclipse.dd.mi.service.CSourceLookup;
|
||||||
import org.eclipse.dd.mi.service.ExpressionService;
|
import org.eclipse.dd.mi.service.ExpressionService;
|
||||||
import org.eclipse.dd.mi.service.MIBreakpoints;
|
import org.eclipse.dd.mi.service.MIBreakpoints;
|
||||||
import org.eclipse.dd.mi.service.MIBreakpointsManager;
|
import org.eclipse.dd.mi.service.MIBreakpointsManager;
|
||||||
|
import org.eclipse.dd.mi.service.MIDisassembly;
|
||||||
import org.eclipse.dd.mi.service.MIMemory;
|
import org.eclipse.dd.mi.service.MIMemory;
|
||||||
import org.eclipse.dd.mi.service.MIRegisters;
|
import org.eclipse.dd.mi.service.MIRegisters;
|
||||||
import org.eclipse.dd.mi.service.MIStack;
|
import org.eclipse.dd.mi.service.MIStack;
|
||||||
|
@ -226,6 +227,10 @@ public class LaunchSequence extends Sequence {
|
||||||
public void execute(RequestMonitor requestMonitor) {
|
public void execute(RequestMonitor requestMonitor) {
|
||||||
new MIRegisters(fSession).initialize(requestMonitor);
|
new MIRegisters(fSession).initialize(requestMonitor);
|
||||||
}},
|
}},
|
||||||
|
new Step() { @Override
|
||||||
|
public void execute(RequestMonitor requestMonitor) {
|
||||||
|
new MIDisassembly(fSession).initialize(requestMonitor);
|
||||||
|
}},
|
||||||
/*new Step() { public void execute(RequestMonitor requestMonitor) {
|
/*new Step() { public void execute(RequestMonitor requestMonitor) {
|
||||||
new GDBVariables(fSession).initialize(requestMonitor);
|
new GDBVariables(fSession).initialize(requestMonitor);
|
||||||
}},*/
|
}},*/
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.eclipse.dd.mi.service.CSourceLookup;
|
||||||
import org.eclipse.dd.mi.service.ExpressionService;
|
import org.eclipse.dd.mi.service.ExpressionService;
|
||||||
import org.eclipse.dd.mi.service.MIBreakpoints;
|
import org.eclipse.dd.mi.service.MIBreakpoints;
|
||||||
import org.eclipse.dd.mi.service.MIBreakpointsManager;
|
import org.eclipse.dd.mi.service.MIBreakpointsManager;
|
||||||
|
import org.eclipse.dd.mi.service.MIDisassembly;
|
||||||
import org.eclipse.dd.mi.service.MIMemory;
|
import org.eclipse.dd.mi.service.MIMemory;
|
||||||
import org.eclipse.dd.mi.service.MIRegisters;
|
import org.eclipse.dd.mi.service.MIRegisters;
|
||||||
import org.eclipse.dd.mi.service.MIStack;
|
import org.eclipse.dd.mi.service.MIStack;
|
||||||
|
@ -59,6 +60,7 @@ public class ShutdownSequence extends Sequence {
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(MIDisassembly.class, requestMonitor); }},
|
||||||
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(MIRegisters.class, requestMonitor); }},
|
new Step() { @Override public void execute(RequestMonitor requestMonitor) { shutdownService(MIRegisters.class, requestMonitor); }},
|
||||||
new Step() {
|
new Step() {
|
||||||
// Uninstall the breakpoints before the service is shut down.
|
// Uninstall the breakpoints before the service is shut down.
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class TestLaunchDelegate extends AbstractCLaunchDelegate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void launchLocalDebugSession( ILaunchConfiguration config, ILaunch l, IProgressMonitor monitor ) throws CoreException {
|
private void launchLocalDebugSession( final ILaunchConfiguration config, ILaunch l, IProgressMonitor monitor ) throws CoreException {
|
||||||
if ( monitor.isCanceled() ) {
|
if ( monitor.isCanceled() ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -151,8 +151,9 @@ public class TestLaunchDelegate extends AbstractCLaunchDelegate
|
||||||
GDBControl gdbControl = tracker.getService(GDBControl.class);
|
GDBControl gdbControl = tracker.getService(GDBControl.class);
|
||||||
if (gdbControl != null) {
|
if (gdbControl != null) {
|
||||||
IMemoryBlockRetrieval memRetrieval = new DsfMemoryBlockRetrieval(
|
IMemoryBlockRetrieval memRetrieval = new DsfMemoryBlockRetrieval(
|
||||||
GDB_DEBUG_MODEL_ID, gdbControl.getGDBDMContext());
|
GDB_DEBUG_MODEL_ID, config, gdbControl.getGDBDMContext());
|
||||||
launch.getSession().registerModelAdapter(IMemoryBlockRetrieval.class, memRetrieval);
|
launch.getSession().registerModelAdapter(IMemoryBlockRetrieval.class, memRetrieval);
|
||||||
|
((DsfMemoryBlockRetrieval) memRetrieval).initialize();
|
||||||
}
|
}
|
||||||
tracker.dispose();
|
tracker.dispose();
|
||||||
return null;
|
return null;
|
||||||
|
|
11
tests/.project
Normal file
11
tests/.project
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>tests</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
Loading…
Add table
Reference in a new issue