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 int fLength;
|
||||
private int fWordSize;
|
||||
private MemoryByte[] fBlock;
|
||||
|
||||
private ArrayList<Object> fConnections = new ArrayList<Object>();
|
||||
|
@ -72,9 +73,10 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
|||
* @param modelId -
|
||||
* @param expression - the displayed expression in the UI
|
||||
* @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();
|
||||
fDebugTarget = retrieval.getDebugTarget();
|
||||
|
@ -85,6 +87,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
|||
|
||||
// Current block information
|
||||
fBlockAddress = address;
|
||||
fWordSize = word_size;
|
||||
fLength = (int) length;
|
||||
fBlock = null;
|
||||
|
||||
|
@ -413,7 +416,6 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
|||
|
||||
// For the IAddress interface
|
||||
final Addr64 address = new Addr64(bigAddress);
|
||||
final int word_size = 1;
|
||||
|
||||
// Use a Query to synchronize the downstream calls
|
||||
Query<MemoryByte[]> query = new Query<MemoryByte[]>() {
|
||||
|
@ -423,7 +425,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
|||
if (memoryService != null) {
|
||||
// Go for it
|
||||
memoryService.getMemory(
|
||||
fRetrieval.getContext(), address, 0, word_size, (int) length,
|
||||
fRetrieval.getContext(), address, 0, fWordSize, (int) length,
|
||||
new DataRequestMonitor<MemoryByte[]>(fRetrieval.getExecutor(), drm) {
|
||||
@Override
|
||||
protected void handleOK() {
|
||||
|
@ -460,9 +462,8 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
|||
|
||||
// For the IAddress interface
|
||||
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[]>() {
|
||||
@Override
|
||||
protected void execute(final DataRequestMonitor<MemoryByte[]> drm) {
|
||||
|
@ -470,7 +471,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
|
|||
if (memoryService != null) {
|
||||
// Go for it
|
||||
memoryService.setMemory(
|
||||
fRetrieval.getContext(), address, offset, word_size, bytes.length, bytes,
|
||||
fRetrieval.getContext(), address, offset, fWordSize, bytes.length, bytes,
|
||||
new RequestMonitor(fRetrieval.getExecutor(), null));
|
||||
}
|
||||
|
||||
|
|
|
@ -15,8 +15,11 @@
|
|||
package org.eclipse.dd.dsf.debug.model;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
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.DsfSession;
|
||||
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.DebugPlugin;
|
||||
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.IMemoryBlock;
|
||||
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.InvalidSyntaxException;
|
||||
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.
|
||||
|
@ -62,14 +73,23 @@ import org.osgi.util.tracker.ServiceTracker;
|
|||
* 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 DsfSession fSession;
|
||||
private final DsfExecutor fExecutor;
|
||||
private IMemoryDMContext fContext;
|
||||
private final ServiceTracker fMemoryServiceTracker;
|
||||
private final ServiceTracker fExpressionServiceTracker;
|
||||
private final String fModelId;
|
||||
private final DsfSession fSession;
|
||||
private final DsfExecutor fExecutor;
|
||||
private final IMemoryDMContext fContext;
|
||||
private final String fContextString;
|
||||
private final ServiceTracker fMemoryServiceTracker;
|
||||
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
|
||||
|
@ -78,11 +98,23 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
|||
* @param dmc
|
||||
* @throws DebugException
|
||||
*/
|
||||
public DsfMemoryBlockRetrieval(String modelId, IMemoryDMContext dmc) throws DebugException {
|
||||
public DsfMemoryBlockRetrieval(String modelId, ILaunchConfiguration config, IMemoryDMContext dmc) throws DebugException {
|
||||
|
||||
fModelId = modelId;
|
||||
fContext = dmc;
|
||||
fSession = DsfSession.getSession(fContext.getSessionId());
|
||||
// DSF stuff
|
||||
fModelId = modelId;
|
||||
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());
|
||||
if (fSession == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Session for context " + fContext + " is not active"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
@ -94,7 +126,7 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
|||
// amalgamated one because it is less error prone (and we are lazy).
|
||||
|
||||
// Create a tracker for the MemoryService
|
||||
String memoryServiceFilter = DsfServices.createServiceFilter( IMemory.class, dmc.getSessionId() );
|
||||
String memoryServiceFilter = DsfServices.createServiceFilter(IMemory.class, dmc.getSessionId());
|
||||
|
||||
try {
|
||||
fMemoryServiceTracker = new ServiceTracker(
|
||||
|
@ -124,11 +156,160 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
|||
"Error creating service filter.", e)); //$NON-NLS-1$
|
||||
}
|
||||
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
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public DsfSession getSession() {
|
||||
return fSession;
|
||||
|
@ -146,38 +327,37 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
|||
return fMemoryServiceTracker;
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Launch/Target specific information
|
||||
// To be completed
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public ILaunch getLaunch() {
|
||||
return null;
|
||||
return fLaunch;
|
||||
}
|
||||
|
||||
public IDebugTarget getDebugTarget() {
|
||||
return null;
|
||||
return fDebugTarget;
|
||||
}
|
||||
|
||||
public int getAddressSize() {
|
||||
return 4;
|
||||
return fAddressSize;
|
||||
}
|
||||
|
||||
public int getAddressableSize() {
|
||||
return 1;
|
||||
return fWordSize;
|
||||
}
|
||||
|
||||
public boolean supportsValueModification() {
|
||||
return true;
|
||||
return fSupportsValueModification;
|
||||
}
|
||||
|
||||
public boolean supportBaseAddressModification() {
|
||||
return false;
|
||||
return fSupportBaseAddressModification;
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IMemoryBlockRetrieval - obsoleted by IMemoryBlockRetrievalExtension
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* (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)
|
||||
// Put here for the sake of completeness (not used with IMemoryBlockExtension)
|
||||
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
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
|
@ -277,12 +457,12 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
|
|||
* 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
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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() ) {
|
||||
return;
|
||||
}
|
||||
|
@ -154,8 +154,9 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate
|
|||
GDBControl gdbControl = tracker.getService(GDBControl.class);
|
||||
if (gdbControl != null) {
|
||||
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);
|
||||
((DsfMemoryBlockRetrieval) memRetrieval).initialize();
|
||||
}
|
||||
tracker.dispose();
|
||||
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.MIBreakpoints;
|
||||
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.MIModules;
|
||||
import org.eclipse.dd.mi.service.MIRegisters;
|
||||
|
@ -121,6 +122,10 @@ public class LaunchSequence extends Sequence {
|
|||
public void execute(RequestMonitor 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.
|
||||
*/
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.eclipse.dd.mi.service.CSourceLookup;
|
|||
import org.eclipse.dd.mi.service.ExpressionService;
|
||||
import org.eclipse.dd.mi.service.MIBreakpoints;
|
||||
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.MIModules;
|
||||
import org.eclipse.dd.mi.service.MIRegisters;
|
||||
|
@ -63,6 +64,11 @@ public class ShutdownSequence extends Sequence {
|
|||
fTracker = null;
|
||||
requestMonitor.done();
|
||||
}
|
||||
}, new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor requestMonitor) {
|
||||
shutdownService(MIDisassembly.class, requestMonitor);
|
||||
}
|
||||
}, new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor requestMonitor) {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
package org.eclipse.dd.gdb.service.command;
|
||||
|
||||
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.IModules.ISymbolDMContext;
|
||||
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
|
||||
implements IContainerDMContext, ISymbolDMContext, IMemoryDMContext, IBreakpointsTargetDMContext, ISourceLookupDMContext,
|
||||
ISignalsDMContext
|
||||
ISignalsDMContext, IDisassemblyDMContext
|
||||
{
|
||||
|
||||
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.MIBreakpoints;
|
||||
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.MIRegisters;
|
||||
import org.eclipse.dd.mi.service.MIStack;
|
||||
|
@ -226,6 +227,10 @@ public class LaunchSequence extends Sequence {
|
|||
public void execute(RequestMonitor 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 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.MIBreakpoints;
|
||||
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.MIRegisters;
|
||||
import org.eclipse.dd.mi.service.MIStack;
|
||||
|
@ -59,6 +60,7 @@ public class ShutdownSequence extends Sequence {
|
|||
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() {
|
||||
// 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() ) {
|
||||
return;
|
||||
}
|
||||
|
@ -151,8 +151,9 @@ public class TestLaunchDelegate extends AbstractCLaunchDelegate
|
|||
GDBControl gdbControl = tracker.getService(GDBControl.class);
|
||||
if (gdbControl != null) {
|
||||
IMemoryBlockRetrieval memRetrieval = new DsfMemoryBlockRetrieval(
|
||||
GDB_DEBUG_MODEL_ID, gdbControl.getGDBDMContext());
|
||||
GDB_DEBUG_MODEL_ID, config, gdbControl.getGDBDMContext());
|
||||
launch.getSession().registerModelAdapter(IMemoryBlockRetrieval.class, memRetrieval);
|
||||
((DsfMemoryBlockRetrieval) memRetrieval).initialize();
|
||||
}
|
||||
tracker.dispose();
|
||||
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