Bug 426730: [Memory] Support 16 bit addressable size

Change-Id: I1fa5498eebe66cc6febbfaf72c4e433bdfab48ed
Signed-off-by: Alvaro Sanchez-Leon <alvsan09@gmail.com>
Reviewed-on: https://git.eclipse.org/r/22118
Reviewed-by: Marc Khouzam <marc.khouzam@ericsson.com>
IP-Clean: Marc Khouzam <marc.khouzam@ericsson.com>
Tested-by: Marc Khouzam <marc.khouzam@ericsson.com>
This commit is contained in:
Alvaro Sanchez-Leon 2014-01-28 13:55:54 +01:00 committed by Marc Khouzam
parent 0b2adb5223
commit e49589af70
16 changed files with 590 additions and 280 deletions

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010, Texas Instruments, Freescale Semiconductor and others.
* Copyright (c) 2010, 2014 Texas Instruments, Freescale Semiconductor 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
@ -7,6 +7,7 @@
*
* Contributors:
* Texas Instruments, Freescale Semiconductor - initial API and implementation
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.memory;
@ -117,12 +118,12 @@ public class GdbMemoryBlock extends DsfMemoryBlock implements IMemorySpaceAwareM
* asynchronous calls to complete before returning.
*
* @param bigAddress
* @param length
* @return MemoryByte[]
* @param count - The number of addressable units for this block
* @return MemoryByte[]
* @throws DebugException
*/
@Override
protected MemoryByte[] fetchMemoryBlock(BigInteger bigAddress, final long length) throws DebugException {
protected MemoryByte[] fetchMemoryBlock(BigInteger bigAddress, final long count) throws DebugException {
// For the IAddress interface
final Addr64 address = new Addr64(bigAddress);
@ -159,7 +160,7 @@ public class GdbMemoryBlock extends DsfMemoryBlock implements IMemorySpaceAwareM
if (memoryService != null) {
// Go for it
memoryService.getMemory(
context, address, 0, addressableSize, (int) length,
context, address, 0, addressableSize, (int) count,
//getContext(), address, 0, addressableSize, (int) length,
new DataRequestMonitor<MemoryByte[]>(retrieval.getExecutor(), drm) {
@Override
@ -206,6 +207,12 @@ public class GdbMemoryBlock extends DsfMemoryBlock implements IMemorySpaceAwareM
protected void execute(final DataRequestMonitor<MemoryByte[]> drm) {
GdbMemoryBlockRetrieval retrieval = (GdbMemoryBlockRetrieval)getMemoryBlockRetrieval();
int addressableSize = 1;
try {
addressableSize = getAddressableSize();
} catch (DebugException e) {}
int addressableUnits = bytes.length/addressableSize;
// If this block was created with a memory space qualification,
// we need to create an enhanced context
IMemoryDMContext context = null;
@ -227,7 +234,7 @@ public class GdbMemoryBlock extends DsfMemoryBlock implements IMemorySpaceAwareM
if (memoryService != null) {
// Go for it
memoryService.setMemory(
context, address, offset, addressableSize, bytes.length, bytes,
context, address, offset, addressableSize, addressableUnits, bytes,
new RequestMonitor(retrieval.getExecutor(), drm));
}
else {
@ -293,7 +300,7 @@ public class GdbMemoryBlock extends DsfMemoryBlock implements IMemorySpaceAwareM
throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, Messages.Err_MemoryServiceNotAvailable, null));
}
@Override
@DsfServiceEventHandler
public void eventDispatched(ISuspendedDMEvent e) {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010, 2013 Texas Instruments, Freescale Semiconductor and others.
* Copyright (c) 2010, 2014 Texas Instruments, Freescale Semiconductor and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -8,6 +8,7 @@
* Contributors:
* Texas Instruments, Freescale Semiconductor - initial API and implementation
* Alvaro Sanchez-Leon (Ericsson AB) - Each memory context needs a different MemoryRetrieval (Bug 250323)
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.memory;
@ -26,6 +27,8 @@ import org.eclipse.cdt.dsf.debug.model.DsfMemoryBlockRetrieval;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.cdt.dsf.debug.service.IMemorySpaces;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.internal.memory.GdbMemoryBlock.MemorySpaceDMContext;
import org.eclipse.cdt.dsf.gdb.service.IGDBMemory2;
import org.eclipse.cdt.dsf.service.DsfServices;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.CoreException;
@ -181,7 +184,7 @@ public class GdbMemoryBlockRetrieval extends DsfMemoryBlockRetrieval implements
* same memory block, a trip to the target could result. However,
* the memory request cache should save the day.
*/
return new GdbMemoryBlock(this, memoryDmc, getModelId(), expression, blockAddress, getAddressableSize(), 0, memorySpaceID);
return new GdbMemoryBlock(this, memoryDmc, getModelId(), expression, blockAddress, getAddressableSize(memoryDmc, memorySpaceID), 0, memorySpaceID);
}
/*
@ -363,7 +366,7 @@ public class GdbMemoryBlockRetrieval extends DsfMemoryBlockRetrieval implements
}
BigInteger blockAddress = new BigInteger(address);
DsfMemoryBlock block = new GdbMemoryBlock(this, memoryCtx, getModelId(), label, blockAddress, getAddressableSize(), 0, memorySpaceID);
DsfMemoryBlock block = new GdbMemoryBlock(this, memoryCtx, getModelId(), label, blockAddress, getAddressableSize(memoryCtx, memorySpaceID), 0, memorySpaceID);
blocks.add(block);
}
}
@ -383,4 +386,29 @@ public class GdbMemoryBlockRetrieval extends DsfMemoryBlockRetrieval implements
}
return false;
}
private int getAddressableSize(IMemoryDMContext aContext, String memorySpaceID) {
IGDBMemory2 memoryService = (IGDBMemory2) getServiceTracker()
.getService();
if (memoryService != null && aContext != null) {
IMemoryDMContext context = resolveMemSpaceContext(aContext, memorySpaceID);
return memoryService.getAddressableSize(context);
}
return super.getAddressableSize();
}
private IMemoryDMContext resolveMemSpaceContext(IMemoryDMContext aContext, String aMemorySpaceID) {
IMemoryDMContext context = aContext;
if (aMemorySpaceID != null && aMemorySpaceID.length() > 0) {
IMemorySpaces memorySpacesService = (IMemorySpaces) getMemorySpaceServiceTracker().getService();
if (memorySpacesService != null) {
context = new MemorySpaceDMContext(memorySpacesService.getSession().getId(), aMemorySpaceID, aContext);
}
}
return context;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2013 Mentor Graphics and others.
* Copyright (c) 2013, 2014 Mentor Graphics 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
@ -9,6 +9,7 @@
* Mentor Graphics - Initial API and implementation
* John Dallaway - Add methods to get the endianness and address size (Bug 225609)
* Philippe Gil (AdaCore) - Switch to c language when getting sizeof(void *) when required (Bug 421541)
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
@ -35,6 +36,7 @@ import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
import org.eclipse.cdt.dsf.mi.service.MIMemory;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressableSizeInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIShowEndianInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataEvaluateExpressionInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIGDBShowLanguageInfo;
@ -48,7 +50,7 @@ import org.eclipse.debug.core.model.MemoryByte;
/**
* @since 4.2
*/
public class GDBMemory extends MIMemory implements IGDBMemory {
public class GDBMemory extends MIMemory implements IGDBMemory2 {
private IGDBControl fCommandControl;
@ -57,6 +59,11 @@ public class GDBMemory extends MIMemory implements IGDBMemory {
*/
private Map<IMemoryDMContext, Integer> fAddressSizes = new HashMap<IMemoryDMContext, Integer>();
/**
* Cache of the addressable sizes for each memory context.
*/
private Map<IMemoryDMContext, Integer> fAddressableSizes = new HashMap<IMemoryDMContext, Integer>();
/**
* We assume the endianness is the same for all processes because GDB supports only one target.
*/
@ -84,6 +91,7 @@ public class GDBMemory extends MIMemory implements IGDBMemory {
IMemory.class.getName(),
MIMemory.class.getName(),
IGDBMemory.class.getName(),
IGDBMemory2.class.getName(),
GDBMemory.class.getName(),
},
new Hashtable<String, String>());
@ -94,19 +102,20 @@ public class GDBMemory extends MIMemory implements IGDBMemory {
public void shutdown(RequestMonitor requestMonitor) {
unregister();
getSession().removeServiceEventListener(this);
fAddressableSizes.clear();
fAddressSizes.clear();
super.shutdown(requestMonitor);
}
@Override
protected void readMemoryBlock(final IDMContext dmc, IAddress address,
long offset, int word_size, int count, final DataRequestMonitor<MemoryByte[]> drm) {
long offset, int word_size, int word_count, final DataRequestMonitor<MemoryByte[]> drm) {
super.readMemoryBlock(
dmc,
address,
offset,
word_size,
count,
word_count,
new DataRequestMonitor<MemoryByte[]>(ImmediateExecutor.getInstance(), drm) {
@Override
protected void handleSuccess() {
@ -134,78 +143,88 @@ public class GDBMemory extends MIMemory implements IGDBMemory {
// Need a global here as getSteps() can be called more than once.
private Step[] steps = null;
private void determineSteps()
{
ArrayList<Step> stepsList = new ArrayList<Step>();
if (fAddressSizes.get(memContext) == null) {
stepsList.add(
new Step() {
// store original language
@Override
public void execute(final RequestMonitor requestMonitor) {
fCommandControl.queueCommand(
fCommandControl.getCommandFactory().createMIGDBShowLanguage(memContext),
new ImmediateDataRequestMonitor<MIGDBShowLanguageInfo>(requestMonitor) {
@Override
protected void handleCompleted() {
if (isSuccess()) {
originalLanguage = getData().getLanguage();
} else {
abortLanguageSteps = true;
}
requestMonitor.done();
}
});
}
});
stepsList.add(
new Step() {
// switch to c language
@Override
public void execute(final RequestMonitor requestMonitor) {
if (abortLanguageSteps) {
requestMonitor.done();
return;
}
fCommandControl.queueCommand(
fCommandControl.getCommandFactory().createMIGDBSetLanguage(memContext, MIGDBShowLanguageInfo.C),
new ImmediateDataRequestMonitor<MIInfo>(requestMonitor) {
new Step() {
// store original language
@Override
public void execute(final RequestMonitor requestMonitor) {
fCommandControl.queueCommand(
fCommandControl.getCommandFactory().createMIGDBShowLanguage(memContext),
new ImmediateDataRequestMonitor<MIGDBShowLanguageInfo>(requestMonitor) {
@Override
protected void handleCompleted() {
if (!isSuccess()) {
if (isSuccess()) {
originalLanguage = getData().getLanguage();
} else {
abortLanguageSteps = true;
}
// Accept failure
requestMonitor.done();
}
});
}
});
}
});
stepsList.add(
new Step() {
// read address size
@Override
public void execute(final RequestMonitor requestMonitor) {
// Run this step even if the language commands where aborted, but accept failures.
readAddressSize(
memContext,
new ImmediateDataRequestMonitor<Integer>(requestMonitor) {
new Step() {
// switch to c language
@Override
public void execute(final RequestMonitor requestMonitor) {
if (abortLanguageSteps) {
requestMonitor.done();
return;
}
fCommandControl.queueCommand(
fCommandControl.getCommandFactory().createMIGDBSetLanguage(memContext, MIGDBShowLanguageInfo.C),
new ImmediateDataRequestMonitor<MIInfo>(requestMonitor) {
@Override
protected void handleCompleted() {
if (!isSuccess()) {
abortLanguageSteps = true;
}
// Accept failure
requestMonitor.done();
}
});
}
});
stepsList.add(new Step() {
// Run this step even if the language commands where aborted, but accept failures.
// Resolve Addressable and Address size
@Override
public void execute(final RequestMonitor requestMonitor) {
//Read Minimum addressable memory size and actual address size
readAddressableSize(memContext, new ImmediateDataRequestMonitor<Integer>(requestMonitor) {
@Override
protected void handleCompleted() {
if (isSuccess()) {
final Integer minAddressableInOctets = getData();
//Preserve the addressable size per context
fAddressableSizes.put(memContext, minAddressableInOctets);
}
readAddressSize(memContext, new ImmediateDataRequestMonitor<Integer>(requestMonitor) {
@Override
protected void handleCompleted() {
if (isSuccess()) {
//Preserve the address size per context
fAddressSizes.put(memContext, getData());
}
// Accept failure
// Accept failures
requestMonitor.done();
}
});
}
});
}
});
}
});
stepsList.add(
new Step() {
// restore original language
@ -250,8 +269,8 @@ public class GDBMemory extends MIMemory implements IGDBMemory {
});
}
});
}
}
if (fIsBigEndian == null) {
stepsList.add(
@ -283,7 +302,7 @@ public class GDBMemory extends MIMemory implements IGDBMemory {
if (steps == null) {
determineSteps();
}
return steps;
}
});
@ -295,6 +314,7 @@ public class GDBMemory extends MIMemory implements IGDBMemory {
IMemoryDMContext context = DMContexts.getAncestorOfType(event.getDMContext(), IMemoryDMContext.class);
if (context != null) {
fAddressSizes.remove(context);
fAddressableSizes.remove(context);
}
}
}
@ -305,6 +325,15 @@ public class GDBMemory extends MIMemory implements IGDBMemory {
return (addressSize != null) ? addressSize.intValue() : 8;
}
/**
* @since 4.4
*/
@Override
public int getAddressableSize(IMemoryDMContext context) {
Integer addressableSize = fAddressableSizes.get(context);
return (addressableSize != null) ? addressableSize.intValue() : 1;
}
@Override
public boolean isBigEndian(IMemoryDMContext context) {
assert fIsBigEndian != null;
@ -335,6 +364,33 @@ public class GDBMemory extends MIMemory implements IGDBMemory {
});
}
/**
* The minimum addressable size is determined by the space used to store a "char" on a target system
* This is then resolved by retrieving a hex representation of -1 casted to the size of a "char"
* e.g. from GDB command line
* > p/x (char)-1
* > $7 = 0xffff
*
* Since two hex characters are representing one octet, for the above example this method should return 2
* @since 4.4
*
*/
protected void readAddressableSize(IMemoryDMContext memContext, final DataRequestMonitor<Integer> drm) {
//We use a CLI command here instead of the expression services, since the target may not be available
//e.g. when using a remote launch.
// Using MI directly is a possibility although there is no way to specify the required output format to hex.
CommandFactory commandFactory = fCommandControl.getCommandFactory();
fCommandControl.queueCommand(
commandFactory.createCLIAddressableSize(memContext),
new DataRequestMonitor<CLIAddressableSizeInfo>(ImmediateExecutor.getInstance(), drm) {
@Override
protected void handleSuccess() {
drm.setData(Integer.valueOf(getData().getAddressableSize()));
drm.done();
}
});
}
protected void readEndianness(IMemoryDMContext memContext, final DataRequestMonitor<Boolean> drm) {
CommandFactory commandFactory = fCommandControl.getCommandFactory();
fCommandControl.queueCommand(

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2010 Ericsson and others.
* Copyright (c) 2008, 2014 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
@ -7,6 +7,7 @@
*
* Contributors:
* Ericsson - initial API and implementation
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
@ -50,6 +51,7 @@ public class GDBMemory_7_0 extends GDBMemory {
MIMemory.class.getName(),
IMemory.class.getName(),
IGDBMemory.class.getName(),
IGDBMemory2.class.getName(),
GDBMemory.class.getName(),
GDBMemory_7_0.class.getName()
},
@ -66,7 +68,7 @@ public class GDBMemory_7_0 extends GDBMemory {
@Override
protected void readMemoryBlock(IDMContext dmc, IAddress address, long offset,
int word_size, int count, DataRequestMonitor<MemoryByte[]> drm)
int word_size, int word_count, DataRequestMonitor<MemoryByte[]> drm)
{
IDMContext threadOrMemoryDmc = dmc;
@ -103,12 +105,12 @@ public class GDBMemory_7_0 extends GDBMemory {
}
}
super.readMemoryBlock(threadOrMemoryDmc, address, offset, word_size, count, drm);
super.readMemoryBlock(threadOrMemoryDmc, address, offset, word_size, word_count, drm);
}
@Override
protected void writeMemoryBlock(IDMContext dmc, IAddress address, long offset,
int word_size, int count, byte[] buffer, RequestMonitor rm)
int word_size, int word_count, byte[] buffer, RequestMonitor rm)
{
IDMContext threadOrMemoryDmc = dmc;
@ -145,6 +147,6 @@ public class GDBMemory_7_0 extends GDBMemory {
}
}
super.writeMemoryBlock(threadOrMemoryDmc, address, offset, word_size, count, buffer, rm);
super.writeMemoryBlock(threadOrMemoryDmc, address, offset, word_size, word_count, buffer, rm);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2013 Ericsson and others.
* Copyright (c) 2013, 2014 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
@ -7,6 +7,7 @@
*
* Contributors:
* Marc Khouzam (Ericsson) - initial API and implementation
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
@ -62,6 +63,7 @@ public class GDBMemory_7_6 extends GDBMemory_7_0 implements IEventListener {
register(new String[] { MIMemory.class.getName(),
IMemory.class.getName(),
IGDBMemory.class.getName(),
IGDBMemory2.class.getName(),
GDBMemory.class.getName(),
GDBMemory_7_0.class.getName(),
GDBMemory_7_6.class.getName()},
@ -140,8 +142,9 @@ public class GDBMemory_7_6 extends GDBMemory_7_0 implements IEventListener {
// Now refresh our memory cache, it case it contained this address. Don't have
// it send the potential IMemoryChangedEvent as we will send it ourselves (see below).
final IMemoryDMContext memoryDMC = DMContexts.getAncestorOfType(containerDmc, IMemoryDMContext.class);
final IAddress address = new Addr64(addr);
getMemoryCache(memoryDMC).refreshMemory(memoryDMC, address, 0, 1, count, false,
getMemoryCache(memoryDMC).refreshMemory(memoryDMC, address, 0, getAddressableSize(memoryDMC), count, false,
new RequestMonitor(getExecutor(), null) {
@Override
protected void handleCompleted() {

View file

@ -0,0 +1,26 @@
/*******************************************************************************
* Copyright (c) 2014 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:
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;
/**
* Extension interface to provide access to the addressable size of a memory context
*
* @since 4.4
*/
public interface IGDBMemory2 extends IGDBMemory {
/**
* Returns the addressable size (in octets) of the memory specified by the given context
*/
public int getAddressableSize(IMemoryDMContext context);
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2010 Wind River Systems and others.
* Copyright (c) 2007, 2014 Wind River 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
@ -13,6 +13,7 @@
* Vladimir Prus (CodeSourcery) - support for -data-read-memory-bytes (bug 322658)
* John Dallaway - support for -data-write-memory-bytes (bug 387793)
* John Dallaway - memory cache update fix (bug 387688)
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
@ -68,6 +69,8 @@ import org.osgi.framework.BundleContext;
public class MIMemory extends AbstractDsfService implements IMemory, ICachingService {
private static final String READ_MEMORY_BYTES_FEATURE = "data-read-memory-bytes"; //$NON-NLS-1$
//data-read-memory write is deprecated, its description could be ambiguous for e.g. 16 bit addressable systems
private static final String DATA_WRITE_MEMORY_16_NOT_SUPPORTED = "data-write-memory with word-size != 1 not supported"; //$NON-NLS-1$
public class MemoryChangedEvent extends AbstractDMEvent<IMemoryDMContext>
implements IMemoryChangedEvent
@ -120,9 +123,6 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
/* (non-Javadoc)
* @see org.eclipse.cdt.dsf.service.AbstractDsfService#initialize(org.eclipse.cdt.dsf.concurrent.RequestMonitor)
*
* This function is called during the launch sequence (where the service is
* instantiated). See LaunchSequence.java.
*/
@Override
public void initialize(final RequestMonitor requestMonitor) {
@ -134,16 +134,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
});
}
/*
* Initialization function:
* - Register the service
* - Create the command cache
* - Register self to service events
*
* @param requestMonitor
*/
private void doInitialize(final RequestMonitor requestMonitor) {
// Create the command cache
IGDBControl commandControl = getServicesTracker().getService(IGDBControl.class);
BufferedCommandControl bufferedCommandControl = new BufferedCommandControl(commandControl, getExecutor(), 2);
@ -162,16 +153,12 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
fCommandCache = new CommandCache(getSession(), bufferedCommandControl);
fCommandCache.setContextAvailable(commandControl.getContext(), true);
// Register this service
register(new String[] { MIMemory.class.getName(), IMemory.class.getName() }, new Hashtable<String, String>());
// Create the memory requests cache
fMemoryCaches = new HashMap<IMemoryDMContext, MIMemoryCache>();
// Register as service event listener
getSession().addServiceEventListener(this, null);
// Done
requestMonitor.done();
}
@ -181,13 +168,10 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
@Override
public void shutdown(final RequestMonitor requestMonitor) {
// Unregister this service
unregister();
// Remove event listener
getSession().removeServiceEventListener(this);
// Complete the shutdown
super.shutdown(requestMonitor);
}
@ -208,32 +192,27 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
*/
@Override
public void getMemory(IMemoryDMContext memoryDMC, IAddress address, long offset,
int word_size, int count, DataRequestMonitor<MemoryByte[]> drm)
int word_size, int word_count, DataRequestMonitor<MemoryByte[]> drm)
{
// Validate the context
if (memoryDMC == null) {
drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
drm.done();
return;
}
// Validate the word size
// NOTE: We only accept 1 byte words for this implementation
if (word_size != 1) {
drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (!= 1)", null)); //$NON-NLS-1$
if (word_size < 1) {
drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (< 1)", null)); //$NON-NLS-1$
drm.done();
return;
}
// Validate the byte count
if (count < 0) {
if (word_count < 0) {
drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Invalid word count (< 0)", null)); //$NON-NLS-1$
drm.done();
return;
}
// All is clear: go for it
getMemoryCache(memoryDMC).getMemory(memoryDMC, address.add(offset), word_size, count, drm);
getMemoryCache(memoryDMC).getMemory(memoryDMC, address.add(offset), word_size, word_count, drm);
}
/* (non-Javadoc)
@ -241,39 +220,33 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
*/
@Override
public void setMemory(IMemoryDMContext memoryDMC, IAddress address, long offset,
int word_size, int count, byte[] buffer, RequestMonitor rm)
int word_size, int word_count, byte[] buffer, RequestMonitor rm)
{
// Validate the context
if (memoryDMC == null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
rm.done();
return;
}
// Validate the word size
// NOTE: We only accept 1 byte words for this implementation
if (word_size != 1) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (!= 1)", null)); //$NON-NLS-1$
if (word_size < 1) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (< 1)", null)); //$NON-NLS-1$
rm.done();
return;
}
// Validate the byte count
if (count < 0) {
if (word_count < 0) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Invalid word count (< 0)", null)); //$NON-NLS-1$
rm.done();
return;
}
// Validate the buffer size
if (buffer.length < count) {
if (buffer.length < word_count * word_size) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Buffer too short", null)); //$NON-NLS-1$
rm.done();
return;
}
// All is clear: go for it
getMemoryCache(memoryDMC).setMemory(memoryDMC, address, offset, word_size, count, buffer, rm);
getMemoryCache(memoryDMC).setMemory(memoryDMC, address, offset, word_size, word_count, buffer, rm);
}
/* (non-Javadoc)
@ -283,29 +256,24 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
public void fillMemory(IMemoryDMContext memoryDMC, IAddress address, long offset,
int word_size, int count, byte[] pattern, RequestMonitor rm)
{
// Validate the context
if (memoryDMC == null) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown context type", null)); //$NON-NLS-1$);
rm.done();
return;
}
// Validate the word size
// NOTE: We only accept 1 byte words for this implementation
if (word_size != 1) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (!= 1)", null)); //$NON-NLS-1$
if (word_size < 1) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Word size not supported (< 1)", null)); //$NON-NLS-1$
rm.done();
return;
}
// Validate the repeat count
if (count < 0) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Invalid repeat count (< 0)", null)); //$NON-NLS-1$
rm.done();
return;
}
// Validate the pattern
if (pattern.length < 1) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Empty pattern", null)); //$NON-NLS-1$
rm.done();
@ -319,8 +287,13 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
System.arraycopy(pattern, 0, buffer, i * length, length);
}
int word_count = buffer.length / word_size;
if (buffer.length % word_size != 0) {
word_count ++;
}
// All is clear: go for it
getMemoryCache(memoryDMC).setMemory(memoryDMC, address, offset, word_size, count * length, buffer, rm);
getMemoryCache(memoryDMC).setMemory(memoryDMC, address, offset, word_size, word_count, buffer, rm);
}
///////////////////////////////////////////////////////////////////////
@ -332,17 +305,17 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
* @param address
* @param offset
* @param word_size
* @param count
* @param word_count in addressable units
* @param drm
*
* @since 1.1
*/
protected void readMemoryBlock(IDMContext dmc, IAddress address, final long offset,
final int word_size, final int count, final DataRequestMonitor<MemoryByte[]> drm)
final int word_size, final int word_count, final DataRequestMonitor<MemoryByte[]> drm)
{
if (fDataReadMemoryBytes) {
fCommandCache.execute(
fCommandFactory.createMIDataReadMemoryBytes(dmc, address.toString(), offset*word_size, count*word_size),
fCommandFactory.createMIDataReadMemoryBytes(dmc, address.toString(), offset, word_count, word_size),
new DataRequestMonitor<MIDataReadMemoryBytesInfo>(getExecutor(), drm) {
@Override
protected void handleSuccess() {
@ -352,17 +325,27 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
}
@Override
protected void handleFailure() {
drm.setData(createInvalidBlock(word_size * count));
drm.setData(createInvalidBlock(word_size * word_count));
drm.done();
}
});
} else {
if (word_size != 1) {
//The word-size is specified within the resulting command data-read-memory
//The word-size is defined in bytes although in the MI interface it's not clear if the meaning is
//octets or system dependent bytes (minimum addressable memory).
//As this command is deprecated there is no good reason to augment the support for word sizes != 1
drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, DATA_WRITE_MEMORY_16_NOT_SUPPORTED, null));
drm.done();
return;
}
/* To simplify the parsing of the MI result, we request the output to
* be on 1 row of [count] columns, no char interpretation.
*/
int mode = MIFormat.HEXADECIMAL;
int nb_rows = 1;
int nb_cols = count;
int nb_cols = word_count;
Character asChar = null;
fCommandCache.execute(
@ -376,7 +359,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
}
@Override
protected void handleFailure() {
drm.setData(createInvalidBlock(word_size * count));
drm.setData(createInvalidBlock(word_size * word_count));
drm.done();
}
}
@ -397,34 +380,44 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
* @param address
* @param offset
* @param word_size
* @param count
* @param word_count in addressable units
* @param buffer
* @param rm
*
* @since 1.1
*/
protected void writeMemoryBlock(final IDMContext dmc, final IAddress address, final long offset,
final int word_size, final int count, final byte[] buffer, final RequestMonitor rm)
final int word_size, final int word_count, final byte[] buffer, final RequestMonitor rm)
{
if (fDataReadMemoryBytes) {
// Use -data-write-memory-bytes for performance
// Use -data-write-memory-bytes for performance,
fCommandCache.execute(
fCommandFactory.createMIDataWriteMemoryBytes(dmc, address.add(offset).toString(),
(buffer.length == count) ? buffer : Arrays.copyOf(buffer, count)),
(buffer.length == word_count*word_size) ? buffer : Arrays.copyOf(buffer, word_count*word_size)),
new DataRequestMonitor<MIInfo>(getExecutor(), rm)
);
} else {
if (word_size != 1) {
//The word-size is specified within the resulting command data-write-memory
//The word-size is defined in bytes although in the MI interface it's not clear if the meaning is
//octets or system dependent bytes (minimum addressable memory).
//As this command is deprecated there is no good reason to augment the support for word sizes != 1
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, DATA_WRITE_MEMORY_16_NOT_SUPPORTED, null));
rm.done();
return;
}
// Each byte is written individually (GDB power...)
// so we need to keep track of the count
final CountingRequestMonitor countingRM = new CountingRequestMonitor(getExecutor(), rm);
countingRM.setDoneCount(count);
countingRM.setDoneCount(word_count);
// We will format the individual bytes in decimal
int format = MIFormat.DECIMAL;
String baseAddress = address.toString();
// Issue an MI request for each byte to write
for (int i = 0; i < count; i++) {
for (int i = 0; i < word_count; i++) {
String value = new Byte(buffer[i]).toString();
fCommandCache.execute(
fCommandFactory.createMIDataWriteMemory(dmc, offset + i, baseAddress, format, word_size, value),
@ -528,7 +521,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
address = new Addr64(expAddress.getValue());
final IMemoryDMContext memoryDMC = DMContexts.getAncestorOfType(context, IMemoryDMContext.class);
getMemoryCache(memoryDMC).refreshMemory(memoryDMC, address, 0, 1, count, true,
getMemoryCache(memoryDMC).refreshMemory(memoryDMC, address, 0, getAddressableSize(memoryDMC), count, true,
new RequestMonitor(getExecutor(), null));
}
}
@ -536,6 +529,14 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
}
}
/**
* The default addressable size is set to 1 octet, to be overridden by sub-classes supporting different values
* @since 4.4
*/
protected int getAddressableSize(IMemoryDMContext context) {
return 1;
}
///////////////////////////////////////////////////////////////////////////
// SortedLinkedlist
///////////////////////////////////////////////////////////////////////////
@ -544,11 +545,16 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
// For simplicity, everything is public.
private class MemoryBlock {
public IAddress fAddress;
public long fLength;
public long fLengthInAddressableUnits;
public long fLengthInOctets;
public MemoryByte[] fBlock;
public MemoryBlock(IAddress address, long length, MemoryByte[] block) {
public MemoryBlock(IAddress address, long lengthInOctets, long lengthInAddressableUnits, MemoryByte[] block) {
// A memory block is expected to be populated with the contents of a defined range of addresses
// therefore the number of octets shall be divisible by the number of addresses
assert (lengthInOctets % lengthInAddressableUnits == 0);
fAddress = address;
fLength = length;
fLengthInAddressableUnits = lengthInAddressableUnits;
fLengthInOctets = lengthInOctets;
fBlock = block;
}
}
@ -601,14 +607,15 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
// Case where the block is to be merged with the previous block
if (index > 0) {
MemoryBlock prevBlock = get(index - 1);
IAddress endOfPreviousBlock = prevBlock.fAddress.add(prevBlock.fLength);
IAddress endOfPreviousBlock = prevBlock.fAddress.add(prevBlock.fLengthInAddressableUnits);
if (endOfPreviousBlock.distanceTo(newBlock.fAddress).longValue() == 0) {
long newLength = prevBlock.fLength + newBlock.fLength;
if (newLength <= Integer.MAX_VALUE) {
MemoryByte[] block = new MemoryByte[(int) newLength] ;
System.arraycopy(prevBlock.fBlock, 0, block, 0, (int) prevBlock.fLength);
System.arraycopy(newBlock.fBlock, 0, block, (int) prevBlock.fLength, (int) newBlock.fLength);
newBlock = new MemoryBlock(prevBlock.fAddress, newLength, block);
long newLengthInOctets = prevBlock.fLengthInOctets + newBlock.fLengthInOctets;
long newLengthInAddressableUnits = prevBlock.fLengthInAddressableUnits + newBlock.fLengthInAddressableUnits;
if (newLengthInOctets <= Integer.MAX_VALUE) {
MemoryByte[] block = new MemoryByte[(int) newLengthInOctets] ;
System.arraycopy(prevBlock.fBlock, 0, block, 0, (int) prevBlock.fLengthInOctets);
System.arraycopy(newBlock.fBlock, 0, block, (int) prevBlock.fLengthInOctets, (int) newBlock.fLengthInOctets);
newBlock = new MemoryBlock(prevBlock.fAddress, newLengthInOctets, newLengthInAddressableUnits, block);
remove(index);
index -= 1;
set(index, newBlock);
@ -620,14 +627,15 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
int lastIndex = size() - 1;
if (index < lastIndex) {
MemoryBlock nextBlock = get(index + 1);
IAddress endOfNewBlock = newBlock.fAddress.add(newBlock.fLength);
IAddress endOfNewBlock = newBlock.fAddress.add(newBlock.fLengthInAddressableUnits);
if (endOfNewBlock.distanceTo(nextBlock.fAddress).longValue() == 0) {
long newLength = newBlock.fLength + nextBlock.fLength;
long newLength = newBlock.fLengthInOctets + nextBlock.fLengthInOctets;
long newAddressesLength = newBlock.fLengthInAddressableUnits + nextBlock.fLengthInAddressableUnits;
if (newLength <= Integer.MAX_VALUE) {
MemoryByte[] block = new MemoryByte[(int) newLength] ;
System.arraycopy(newBlock.fBlock, 0, block, 0, (int) newBlock.fLength);
System.arraycopy(nextBlock.fBlock, 0, block, (int) newBlock.fLength, (int) nextBlock.fLength);
newBlock = new MemoryBlock(newBlock.fAddress, newLength, block);
System.arraycopy(newBlock.fBlock, 0, block, 0, (int) newBlock.fLengthInOctets);
System.arraycopy(nextBlock.fBlock, 0, block, (int) newBlock.fLengthInOctets, (int) nextBlock.fLengthInOctets);
newBlock = new MemoryBlock(newBlock.fAddress, newLength, newAddressesLength, block);
set(index, newBlock);
remove(index + 1);
}
@ -712,28 +720,30 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
* @return A list of the sub-blocks to fetch in order to fill enough gaps in the memory cache
* to service the request
*/
private LinkedList<MemoryBlock> getListOfMissingBlocks(IAddress reqBlockStart, int count) {
private LinkedList<MemoryBlock> getListOfMissingBlocks(IAddress reqBlockStart, int word_count, int word_size) {
int octetCount = word_count * word_size;
LinkedList<MemoryBlock> list = new LinkedList<MemoryBlock>();
ListIterator<MemoryBlock> it = fMemoryBlockList.listIterator();
// Look for holes in the list of memory blocks
while (it.hasNext() && count > 0) {
while (it.hasNext() && octetCount > 0) {
MemoryBlock cachedBlock = it.next();
IAddress cachedBlockStart = cachedBlock.fAddress;
IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLength);
IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLengthInAddressableUnits);
// Case where we miss a block before the cached block
if (reqBlockStart.distanceTo(cachedBlockStart).longValue() >= 0) {
int length = (int) Math.min(reqBlockStart.distanceTo(cachedBlockStart).longValue(), count);
int lengthInOctets = (int) Math.min(reqBlockStart.distanceTo(cachedBlockStart).longValue()*word_size, octetCount);
// If both blocks start at the same location, no need to create a new cached block
if (length > 0) {
MemoryBlock newBlock = new MemoryBlock(reqBlockStart, length, new MemoryByte[0]);
if (lengthInOctets > 0) {
int lengthInAddressableUnits = lengthInOctets / word_size;
MemoryBlock newBlock = new MemoryBlock(reqBlockStart, lengthInOctets, lengthInAddressableUnits, new MemoryByte[0]);
list.add(newBlock);
}
// Adjust request block start and length for the next iteration
reqBlockStart = cachedBlockEnd;
count -= length + cachedBlock.fLength;
octetCount -= lengthInOctets + cachedBlock.fLengthInOctets;
}
// Case where the requested block starts somewhere in the cached block
@ -742,14 +752,15 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
{
// Start of the requested block already in cache
// Adjust request block start and length for the next iteration
count -= reqBlockStart.distanceTo(cachedBlockEnd).longValue();
octetCount -= reqBlockStart.distanceTo(cachedBlockEnd).longValue()*word_size;
reqBlockStart = cachedBlockEnd;
}
}
// Case where we miss a block at the end of the cache
if (count > 0) {
MemoryBlock newBlock = new MemoryBlock(reqBlockStart, count, new MemoryByte[0]);
if (octetCount > 0) {
int addressesLength = octetCount / word_size;
MemoryBlock newBlock = new MemoryBlock(reqBlockStart, octetCount, addressesLength, new MemoryByte[0]);
list.add(newBlock);
}
@ -782,22 +793,23 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
* @param count Its length
* @return The cached memory content
*/
private MemoryByte[] getMemoryBlockFromCache(IAddress reqBlockStart, int count) {
IAddress reqBlockEnd = reqBlockStart.add(count);
private MemoryByte[] getMemoryBlockFromCache(IAddress reqBlockStart, int word_count, int word_size) {
int count = word_count * word_size;
IAddress reqBlockEnd = reqBlockStart.add(word_count);
MemoryByte[] resultBlock = new MemoryByte[count];
ListIterator<MemoryBlock> iter = fMemoryBlockList.listIterator();
while (iter.hasNext()) {
MemoryBlock cachedBlock = iter.next();
IAddress cachedBlockStart = cachedBlock.fAddress;
IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLength);
IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLengthInAddressableUnits);
// Case where the cached block overlaps completely the requested memory block
if (cachedBlockStart.distanceTo(reqBlockStart).longValue() >= 0
&& reqBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0)
{
int pos = (int) cachedBlockStart.distanceTo(reqBlockStart).longValue();
int pos = (int) cachedBlockStart.distanceTo(reqBlockStart).longValue() * word_size;
System.arraycopy(cachedBlock.fBlock, pos, resultBlock, 0, count);
}
@ -805,8 +817,8 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
else if (reqBlockStart.distanceTo(cachedBlockStart).longValue() >= 0
&& cachedBlockStart.distanceTo(reqBlockEnd).longValue() > 0)
{
int pos = (int) reqBlockStart.distanceTo(cachedBlockStart).longValue();
int length = (int) Math.min(cachedBlock.fLength, count - pos);
int pos = (int) reqBlockStart.distanceTo(cachedBlockStart).longValue() * word_size;
int length = (int) Math.min(cachedBlock.fLengthInOctets, count - pos);
System.arraycopy(cachedBlock.fBlock, 0, resultBlock, pos, length);
}
@ -814,8 +826,8 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
else if (cachedBlockStart.distanceTo(reqBlockStart).longValue() >= 0
&& reqBlockStart.distanceTo(cachedBlockEnd).longValue() > 0)
{
int pos = (int) cachedBlockStart.distanceTo(reqBlockStart).longValue();
int length = (int) Math.min(cachedBlock.fLength - pos, count);
int pos = (int) cachedBlockStart.distanceTo(reqBlockStart).longValue() * word_size;
int length = (int) Math.min(cachedBlock.fLengthInOctets - pos, count);
System.arraycopy(cachedBlock.fBlock, pos, resultBlock, 0, length);
}
}
@ -827,18 +839,19 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
* the content with the actual memory just read from the target.
*
* @param modBlockStart
* @param count
* @param word_count - Number of addressable units
* @param modBlock
* @param word_size - Number of octets per addressable unit
*/
private void updateMemoryCache(IAddress modBlockStart, int count, MemoryByte[] modBlock) {
IAddress modBlockEnd = modBlockStart.add(count);
private void updateMemoryCache(IAddress modBlockStart, int word_count, MemoryByte[] modBlock, int word_size) {
IAddress modBlockEnd = modBlockStart.add(word_count);
ListIterator<MemoryBlock> iter = fMemoryBlockList.listIterator();
int count = word_count * word_size;
while (iter.hasNext()) {
MemoryBlock cachedBlock = iter.next();
IAddress cachedBlockStart = cachedBlock.fAddress;
IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLength);
IAddress cachedBlockEnd = cachedBlock.fAddress.add(cachedBlock.fLengthInAddressableUnits);
// For now, we only bother to update bytes already cached.
// Note: In a better implementation (v1.1), we would augment
@ -850,7 +863,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
if (cachedBlockStart.distanceTo(modBlockStart).longValue() >= 0
&& modBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0)
{
int pos = (int) cachedBlockStart.distanceTo(modBlockStart).longValue();
int pos = (int) cachedBlockStart.distanceTo(modBlockStart).longValue() * word_size;
System.arraycopy(modBlock, 0, cachedBlock.fBlock, pos, count);
}
@ -858,16 +871,16 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
else if (modBlockStart.distanceTo(cachedBlockStart).longValue() >= 0
&& cachedBlockEnd.distanceTo(modBlockEnd).longValue() >= 0)
{
int pos = (int) modBlockStart.distanceTo(cachedBlockStart).longValue();
System.arraycopy(modBlock, pos, cachedBlock.fBlock, 0, (int) cachedBlock.fLength);
int pos = (int) modBlockStart.distanceTo(cachedBlockStart).longValue() * word_size;
System.arraycopy(modBlock, pos, cachedBlock.fBlock, 0, (int) cachedBlock.fLengthInOctets);
}
// Case where the beginning of the modified block is within the cached block
else if (cachedBlockStart.distanceTo(modBlockStart).longValue() >= 0
&& modBlockStart.distanceTo(cachedBlockEnd).longValue() > 0)
{
int pos = (int) cachedBlockStart.distanceTo(modBlockStart).longValue();
int length = (int) modBlockStart.distanceTo(cachedBlockEnd).longValue();
int pos = (int) cachedBlockStart.distanceTo(modBlockStart).longValue() * word_size;
int length = (int) modBlockStart.distanceTo(cachedBlockEnd).longValue() * word_size;
System.arraycopy(modBlock, 0, cachedBlock.fBlock, pos, length);
}
@ -875,8 +888,8 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
else if (cachedBlockStart.distanceTo(modBlockEnd).longValue() > 0
&& modBlockEnd.distanceTo(cachedBlockEnd).longValue() >= 0)
{
int pos = (int) modBlockStart.distanceTo(cachedBlockStart).longValue();
int length = (int) cachedBlockStart.distanceTo(modBlockEnd).longValue();
int pos = (int) modBlockStart.distanceTo(cachedBlockStart).longValue() * word_size;
int length = (int) cachedBlockStart.distanceTo(modBlockEnd).longValue() * word_size;
System.arraycopy(modBlock, pos, cachedBlock.fBlock, 0, length);
}
}
@ -887,14 +900,14 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
* @param memoryDMC
* @param address the memory block address (on the target)
* @param word_size the size, in bytes, of an addressable item
* @param count the number of bytes to read
* @param word_count the number of addressable units to read
* @param drm the asynchronous data request monitor
*/
public void getMemory(IMemoryDMContext memoryDMC, final IAddress address, final int word_size,
final int count, final DataRequestMonitor<MemoryByte[]> drm)
final int word_count, final DataRequestMonitor<MemoryByte[]> drm)
{
// Determine the number of read requests to issue
LinkedList<MemoryBlock> missingBlocks = getListOfMissingBlocks(address, count);
LinkedList<MemoryBlock> missingBlocks = getListOfMissingBlocks(address, word_count, word_size);
int numberOfRequests = missingBlocks.size();
// A read request will be issued for each block needed
@ -904,7 +917,7 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
@Override
protected void handleSuccess() {
// We received everything so read the result from the memory cache
drm.setData(getMemoryBlockFromCache(address, count));
drm.setData(getMemoryBlockFromCache(address, word_count, word_size));
drm.done();
}
};
@ -914,14 +927,14 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
for (int i = 0; i < numberOfRequests; i++) {
MemoryBlock block = missingBlocks.get(i);
final IAddress startAddress = block.fAddress;
final int length = (int) block.fLength;
final int length = (int) block.fLengthInAddressableUnits;
readMemoryBlock(memoryDMC, startAddress, 0, word_size, length,
new DataRequestMonitor<MemoryByte[]>(getSession().getExecutor(), drm) {
@Override
protected void handleSuccess() {
MemoryByte[] block = new MemoryByte[count];
block = getData();
MemoryBlock memoryBlock = new MemoryBlock(startAddress, length, block);
MemoryByte[] block = getData();
int lenghtInaddressableUnits = block.length / word_size;
MemoryBlock memoryBlock = new MemoryBlock(startAddress, block.length, lenghtInaddressableUnits, block);
fMemoryBlockList.add(memoryBlock);
countingRM.done();
}
@ -934,16 +947,16 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
* @param address the memory block address (on the target)
* @param offset the offset from the start address
* @param word_size the size, in bytes, of an addressable item
* @param count the number of bytes to write
* @param word_count the number of addressable units to write
* @param buffer the source buffer
* @param rm the asynchronous request monitor
*/
public void setMemory(final IMemoryDMContext memoryDMC, final IAddress address,
final long offset, final int word_size, final int count, final byte[] buffer,
final long offset, final int word_size, final int word_count, final byte[] buffer,
final RequestMonitor rm)
{
writeMemoryBlock(
memoryDMC, address, offset, word_size, count, buffer,
memoryDMC, address, offset, word_size, word_count, buffer,
new RequestMonitor(getSession().getExecutor(), rm) {
@Override
protected void handleSuccess() {
@ -952,18 +965,17 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
fCommandCache.reset();
// Re-read the modified memory block to asynchronously update of the memory cache
readMemoryBlock(memoryDMC, address, offset, word_size, count,
readMemoryBlock(memoryDMC, address, offset, word_size, word_count,
new DataRequestMonitor<MemoryByte[]>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
updateMemoryCache(address.add(offset), count, getData());
updateMemoryCache(address.add(offset), word_count, getData(), word_size);
// Send the MemoryChangedEvent
IAddress[] addresses = new IAddress[count];
for (int i = 0; i < count; i++) {
IAddress[] addresses = new IAddress[word_count];
for (int i = 0; i < word_count; i++) {
addresses[i] = address.add(offset + i);
}
getSession().dispatchEvent(new MemoryChangedEvent(memoryDMC, addresses), getProperties());
// Finally...
rm.done();
}
});
@ -976,35 +988,35 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
* @param address
* @param offset
* @param word_size
* @param count
* @param word_count
* @param sendMemoryEvent Indicates if a IMemoryChangedEvent should be sent if the memory cache has changed.
* @param rm
*/
public void refreshMemory(final IMemoryDMContext memoryDMC, final IAddress address,
final long offset, final int word_size, final int count, final boolean sendMemoryEvent,
final long offset, final int word_size, final int word_count, final boolean sendMemoryEvent,
final RequestMonitor rm)
{
// Check if we already cache part of this memory area (which means it
// is used by a memory service client that will have to be updated)
LinkedList<MemoryBlock> list = getListOfMissingBlocks(address, count);
LinkedList<MemoryBlock> list = getListOfMissingBlocks(address, word_count, word_size);
int sizeToRead = 0;
for (MemoryBlock block : list) {
sizeToRead += block.fLength;
sizeToRead += block.fLengthInAddressableUnits;
}
// If none of the requested memory is in cache, just get out
if (sizeToRead == count) {
if (sizeToRead == word_count) {
rm.done();
return;
}
// Read the corresponding memory block
fCommandCache.reset();
readMemoryBlock(memoryDMC, address, offset, word_size, count,
readMemoryBlock(memoryDMC, address, offset, word_size, word_count,
new DataRequestMonitor<MemoryByte[]>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
MemoryByte[] oldBlock = getMemoryBlockFromCache(address, count);
MemoryByte[] oldBlock = getMemoryBlockFromCache(address, word_count, word_size);
MemoryByte[] newBlock = getData();
boolean blocksDiffer = false;
for (int i = 0; i < oldBlock.length; i++) {
@ -1014,11 +1026,11 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer
}
}
if (blocksDiffer) {
updateMemoryCache(address.add(offset), count, newBlock);
updateMemoryCache(address.add(offset), word_count, newBlock, word_size);
if (sendMemoryEvent) {
// Send the MemoryChangedEvent
final IAddress[] addresses = new IAddress[count];
for (int i = 0; i < count; i++) {
final IAddress[] addresses = new IAddress[word_count];
for (int i = 0; i < word_count; i++) {
addresses[i] = address.add(offset + i);
}
getSession().dispatchEvent(new MemoryChangedEvent(memoryDMC, addresses), getProperties());

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2013 QNX Software Systems and others.
* Copyright (c) 2000, 2014 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
@ -23,6 +23,7 @@
* Alvaro Sanchez-Leon (Ericsson) - Make Registers View specific to a frame (Bug (323552)
* Philippe Gil (AdaCore) - Add show/set language CLI commands (Bug 421541)
* Dmitry Kozlov (Mentor Graphics) - New trace-related methods (Bug 390827)
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command;
@ -43,6 +44,7 @@ import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordDMContext;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAddressableSize;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIAttach;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLICatch;
import org.eclipse.cdt.dsf.mi.service.command.commands.CLIDetach;
@ -178,6 +180,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarSetUpdateRange;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowAttributes;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarShowFormat;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIVarUpdate;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressableSizeInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLICatchInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoBreakInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIInfoProgramInfo;
@ -198,11 +201,11 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIDataReadMemoryBytesInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataReadMemoryInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataWriteMemoryInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIGDBShowExitCodeInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIGDBShowLanguageInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfoOsInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIListFeaturesInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIGDBShowLanguageInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIStackInfoDepthInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIStackListArgumentsInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIStackListFramesInfo;
@ -236,6 +239,13 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIVarUpdateInfo;
*/
public class CommandFactory {
/**
* @since 4.4
*/
public ICommand<CLIAddressableSizeInfo> createCLIAddressableSize(IMemoryDMContext ctx) {
return new CLIAddressableSize(ctx);
}
public ICommand<MIInfo> createCLIAttach(IDMContext ctx, int pid) {
return new CLIAttach(ctx, pid);
}
@ -475,6 +485,14 @@ public class CommandFactory {
return new MIDataReadMemoryBytes(ctx, address, offset, num_bytes);
}
/**
* @since 4.4
*/
public ICommand<MIDataReadMemoryBytesInfo> createMIDataReadMemoryBytes(IDMContext ctx, String address,
long offset, int word_count, int word_size) {
return new MIDataReadMemoryBytes(ctx, address, offset, word_count, word_size);
}
public ICommand<MIDataWriteMemoryInfo> createMIDataWriteMemory(IDMContext ctx, long offset, String address,
int wordFormat, int wordSize, String value) {
return new MIDataWriteMemory(ctx, offset, address, wordFormat, wordSize, value);

View file

@ -0,0 +1,49 @@
/*******************************************************************************
* Copyright (c) 2014 Ericsson AB 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:
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.commands;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.cdt.dsf.mi.service.command.output.CLIAddressableSizeInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
/**
* <p>CLI command used to resolve the addressable size </p>
* The minimum addressable size
* is determined by the space used to store a "char" on a target system
* <br>
* This is
* then resolved by retrieving a hex representation of -1 casted to the size of
* a "char"
* <br>
* <br>E.g. from GDB command line
* <br>
* > p/x (char)-1 <br>
* > $7 = 0xffff <br>
*
* <p>Since two hex characters are representing one octet, for the above example
* this method should return 2</p>
*
* @since 4.4
*/
public class CLIAddressableSize extends MIInterpreterExecConsole<CLIAddressableSizeInfo> {
private static final String hexOfBitsContainedInChar = "p/x (char)-1"; //$NON-NLS-1$
public CLIAddressableSize(IMemoryDMContext ctx) {
super(ctx, hexOfBitsContainedInChar);
}
@Override
public CLIAddressableSizeInfo getResult(MIOutput miResult) {
return new CLIAddressableSizeInfo(miResult);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010 CodeSourcery and others.
* Copyright (c) 2010, 2014 CodeSourcery 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
@ -7,6 +7,7 @@
*
* Contributors:
* Vladimir Prus (CodeSourcery) - Initial API and implementation
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.commands;
@ -26,10 +27,10 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
* be quoted using the C convention.
*
* `COUNT'
* The number of bytes to read. This should be an integer literal.
* The number of addressable units to read. This should be an integer literal.
*
* `BYTE-OFFSET'
* The offsets in bytes relative to ADDRESS at which to start
* The offset in addressable units relative to ADDRESS at which to start
* reading. This should be an integer literal. This option is
* provided so that a frontend is not required to first evaluate
* address and then perform address arithmetics itself.
@ -37,23 +38,36 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
*/
public class MIDataReadMemoryBytes extends MICommand<MIDataReadMemoryBytesInfo> {
private int fSize;
private static final int DEFAULT_ADDRESSABLE_SIZE = 1;
private int fCount;
private int fword_size;
public MIDataReadMemoryBytes(IDMContext ctx, String address, long offset,
int num_bytes) {
int count) {
this(ctx, address, offset, count, DEFAULT_ADDRESSABLE_SIZE);
}
/**
* @param count - The number of addressable units to read from memory
* @since 4.4
*/
public MIDataReadMemoryBytes(IDMContext ctx, String address, long offset,
int count, int word_size) {
super(ctx, "-data-read-memory-bytes"); //$NON-NLS-1$
fSize = num_bytes;
fCount = count;
fword_size = word_size;
if (offset != 0) {
setOptions(new String[] { "-o", Long.toString(offset) }); //$NON-NLS-1$
}
setParameters(new String[] { address, Integer.toString(num_bytes) });
setParameters(new String[] { address, Integer.toString(count) });
}
@Override
public MIDataReadMemoryBytesInfo getResult(MIOutput out) {
return new MIDataReadMemoryBytesInfo(out, fSize);
return new MIDataReadMemoryBytesInfo(out, fCount, fword_size);
}
}

View file

@ -0,0 +1,60 @@
/*******************************************************************************
* Copyright (c) 2014 Ericsson AB 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:
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.output;
/**
* This class takes care of parsing and providing the result of the CLI command
* <br>"p/x (char)-1"
*
* <p>E.g. if the response to 'p/x (char)-1' is</p>
* $n = 0xffff
*
* <p>Then we can easily resolve it to 2 octets (e.g. 2 hex characters per octet)</p>
* @since 4.4
*/
public class CLIAddressableSizeInfo extends MIInfo {
private int fAddressableSize = 1;
public CLIAddressableSizeInfo(MIOutput record) {
super(record);
parse();
}
protected void parse() {
if (isDone()) {
MIOutput out = getMIOutput();
for (MIOOBRecord oob : out.getMIOOBRecords()) {
if (oob instanceof MIConsoleStreamOutput) {
String line = ((MIConsoleStreamOutput)oob).getString().trim();
fAddressableSize = hexToOctetCount(line);
}
}
}
}
public int getAddressableSize() {
return fAddressableSize;
}
private int hexToOctetCount(String hexString) {
//Receiving format is expected in hex form e.g. "$n = 0xffff" or "$n = 0xff"
//which shall result in 2 and 1 octets respectively
int starts = hexString.indexOf("x"); //$NON-NLS-1$
assert(starts > 0);
String hexDigits = hexString.substring(starts+1);
assert hexDigits.length() > 1;
int octets = hexDigits.length()/2;
return octets;
}
}

View file

@ -1,12 +1,13 @@
/*******************************************************************************
* Copyright (c) 2010 CodeSourcery and others.
* Copyright (c) 2010, 2014 CodeSourcery 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:
* Vladimir Prus (CodeSourcery) - Initial API and implementation
* Vladimir Prus (CodeSourcery) - Initial API and implementation
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command.output;
@ -25,12 +26,25 @@ import org.eclipse.debug.core.model.MemoryByte;
*/
public class MIDataReadMemoryBytesInfo extends MIInfo {
/**
* Default Addressable size in octets
*/
private static final int DEFAULT_WORD_SIZE = 1;
/* The cached memory block. */
private MemoryByte[] fBlock = null;
public MIDataReadMemoryBytesInfo(MIOutput output, int size) {
this(output, size, DEFAULT_WORD_SIZE);
}
/**
* @param count - Number of Addressable units
* @param word_size - Addressable size in octets
* @since 4.4
*/
public MIDataReadMemoryBytesInfo(MIOutput output, int count, int word_size) {
super(output);
parse(size);
parse(count, word_size);
}
/**
@ -40,11 +54,11 @@ public class MIDataReadMemoryBytesInfo extends MIInfo {
return fBlock;
}
private void parse(int size)
private void parse(int count, int word_size)
{
fBlock = new MemoryByte[size];
fBlock = new MemoryByte[count*word_size];
// Fill the block with invalid bytes, initially.
for (int i = 0; i < size; i++)
for (int i = 0; i < fBlock.length; i++)
fBlock[i] = new MemoryByte((byte) 0, (byte) 0);
MIResult[] results = getMIOutput().getMIResultRecord().getMIResults();
@ -72,9 +86,9 @@ public class MIDataReadMemoryBytesInfo extends MIInfo {
}
}
if (offset + contents.length()/2 <= size)
if (offset*word_size + contents.length()/2 <= count*word_size)
for (int k = 0; k < contents.length() / 2; ++k) {
fBlock[offset + k] = new MemoryByte(
fBlock[offset*word_size + k] = new MemoryByte(
(byte) Integer.parseInt(
contents.substring(k * 2, k * 2 + 2),
16));

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2010 Ericsson and others.
* Copyright (c) 2007, 2014 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
@ -7,6 +7,7 @@
*
* Contributors:
* Ericsson AB - Initial Implementation
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.tests.dsf.gdb.tests;
@ -530,7 +531,7 @@ public class MIMemoryTest extends BaseTestCase {
fBaseAddress = evaluateExpression(frameDmc, "&charBlock");
// Perform the test
String expected = "Word size not supported (!= 1)";
String expected = "Word size not supported (< 1)";
fWait.waitReset();
readMemory(fMemoryDmc, fBaseAddress, offset, 0, count);
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
@ -538,13 +539,6 @@ public class MIMemoryTest extends BaseTestCase {
assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
fWait.getMessage().contains(expected));
fWait.waitReset();
readMemory(fMemoryDmc, fBaseAddress, offset, 2, count);
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
assertFalse(fWait.getMessage(), fWait.isOK());
assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
fWait.getMessage().contains(expected));
// Ensure no MemoryChangedEvent event was received
assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0);
}
@ -823,7 +817,7 @@ public class MIMemoryTest extends BaseTestCase {
fBaseAddress = evaluateExpression(frameDmc, "&charBlock");
// Perform the test
String expected = "Word size not supported (!= 1)";
String expected = "Word size not supported (< 1)";
fWait.waitReset();
writeMemory(fMemoryDmc, fBaseAddress, offset, 0, count, buffer);
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
@ -831,13 +825,6 @@ public class MIMemoryTest extends BaseTestCase {
assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
fWait.getMessage().contains(expected));
fWait.waitReset();
writeMemory(fMemoryDmc, fBaseAddress, offset, 2, count, buffer);
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
assertFalse(fWait.getMessage(), fWait.isOK());
assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
fWait.getMessage().contains(expected));
// Ensure no MemoryChangedEvent event was received
assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0);
}
@ -1184,7 +1171,7 @@ public class MIMemoryTest extends BaseTestCase {
fBaseAddress = evaluateExpression(frameDmc, "&charBlock");
// Perform the test
String expected = "Word size not supported (!= 1)";
String expected = "Word size not supported (< 1)";
fWait.waitReset();
fillMemory(fMemoryDmc, fBaseAddress, offset, 0, count, pattern);
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
@ -1192,13 +1179,6 @@ public class MIMemoryTest extends BaseTestCase {
assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
fWait.getMessage().contains(expected));
fWait.waitReset();
fillMemory(fMemoryDmc, fBaseAddress, offset, 2, count, pattern);
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
assertFalse(fWait.getMessage(), fWait.isOK());
assertTrue("Wrong error message: expected '" + expected + "', received '" + fWait.getMessage() + "'",
fWait.getMessage().contains(expected));
// Ensure no MemoryChangedEvent event was received
assertTrue("MemoryChangedEvent problem: expected " + 0 + ", received " + getEventCount(), getEventCount() == 0);
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2010 Wind River Systems and others.
* Copyright (c) 2007, 2014 Wind River 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
@ -11,6 +11,7 @@
* Ericsson Communication - added support for 64 bit processors
* Ericsson Communication - added support for changed bytes
* Ericsson Communication - better management of exceptions
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.model;
@ -325,7 +326,12 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
@Override
public MemoryByte[] getBytesFromAddress(BigInteger address, long units) throws DebugException {
if (isUseCacheData() && fBlockAddress.compareTo(address) == 0 && units * getAddressableSize() <= fBlock.length)
int addressableSize = 1;
try {
addressableSize = getAddressableSize();
} catch (DebugException e) {}
if (isUseCacheData() && fBlockAddress.compareTo(address) == 0 && units * addressableSize <= fBlock.length)
return fBlock;
MemoryByte[] newBlock = fetchMemoryBlock(address, units);
@ -378,7 +384,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
// Determine the distance between the cached and the requested block addresses
// If the distance does not exceed the length of the cached block, then there
// is some overlap between the blocks and we have to mark the changed bytes.
BigInteger bigDistance = address.subtract(fBlockAddress);
BigInteger bigDistance = address.subtract(fBlockAddress).multiply(BigInteger.valueOf(addressableSize));
if (bigDistance.compareTo(BigInteger.valueOf(fLength)) == -1) {
// Calculate the length of the data we are going to examine/update
int distance = bigDistance.intValue();
@ -464,7 +470,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
// If the distance does not exceed the length of the new block, then there
// is some overlap between the blocks and we have to update the blanks and
// possibly note they are changed.
BigInteger bigDistance = fBlockAddress.subtract(address);
BigInteger bigDistance = fBlockAddress.subtract(address).multiply(BigInteger.valueOf(addressableSize));
if (bigDistance.compareTo(BigInteger.valueOf(newLength)) == -1) {
// Calculate the length of the data we are going to examine/update
int distance = bigDistance.intValue();
@ -580,7 +586,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
*/
@Override
public int getAddressableSize() throws DebugException {
return fRetrieval.getAddressableSize();
return fWordSize;
}
///////////////////////////////////////////////////////////////////////////
@ -593,13 +599,21 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* asynchronous calls to complete before returning.
*
* @param bigAddress
* @param length
* @param count - Number of addressable units for this memory block
* @return MemoryByte[]
* @throws DebugException
* @since 2.1
*/
protected MemoryByte[] fetchMemoryBlock(BigInteger bigAddress, final long length) throws DebugException {
protected MemoryByte[] fetchMemoryBlock(BigInteger bigAddress, final long count) throws DebugException {
//resolve the addressable size
int aSize;
try {
aSize = getAddressableSize();
} catch (DebugException e) {
aSize = 1;
}
final int addressableSize = aSize;
// For the IAddress interface
final Addr64 address = new Addr64(bigAddress);
@ -611,7 +625,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
if (memoryService != null) {
// Go for it
memoryService.getMemory(
fContext, address, 0, fWordSize, (int) length,
fContext, address, 0, addressableSize, (int) count,
new DataRequestMonitor<MemoryByte[]>(fRetrieval.getExecutor(), drm) {
@Override
protected void handleSuccess() {
@ -645,7 +659,17 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @since 2.1
*/
protected void writeMemoryBlock(final long offset, final byte[] bytes) throws DebugException {
//resolve the addressable size
int aSize;
try {
aSize = getAddressableSize();
} catch (DebugException e) {
aSize = 1;
}
final int addressableSize = aSize;
final int addressableUnits = bytes.length/addressableSize;
// For the IAddress interface
final Addr64 address = new Addr64(fBaseAddress);
@ -657,7 +681,7 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
if (memoryService != null) {
// Go for it
memoryService.setMemory(
fContext, address, offset, fWordSize, bytes.length, bytes,
fContext, address, offset, addressableSize, addressableUnits, bytes,
new RequestMonitor(fRetrieval.getExecutor(), drm));
}
else {
@ -711,9 +735,16 @@ public class DsfMemoryBlock extends PlatformObject implements IMemoryBlockExtens
* @param length
*/
public void handleMemoryChange(BigInteger address) {
int addressableSize;
try {
addressableSize = getAddressableSize();
} catch (DebugException e) {
addressableSize = 1;
}
int addressesLength = fLength/addressableSize;
// Check if the change affects this particular block (0 is universal)
BigInteger fEndAddress = fBlockAddress.add(BigInteger.valueOf(fLength));
BigInteger fEndAddress = fBlockAddress.add(BigInteger.valueOf(addressesLength));
if (address.equals(BigInteger.ZERO) ||
((fBlockAddress.compareTo(address) != 1) && (fEndAddress.compareTo(address) == 1)))
{

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2014 Wind River Systems, Inc. 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
@ -7,6 +7,7 @@
*
* Contributors:
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.debug.ui.memory.traditional;
@ -917,8 +918,8 @@ public class Rendering extends Composite implements IDebugEventSetListener
{
IMemoryBlockExtension memoryBlock = getMemoryBlock();
BigInteger lengthInBytes = endAddress.subtract(startAddress);
BigInteger addressableSize = BigInteger.valueOf(getAddressableSize());
final BigInteger addressableSize = BigInteger.valueOf(getAddressableSize());
BigInteger lengthInBytes = endAddress.subtract(startAddress).multiply(addressableSize);
long units = lengthInBytes.divide(addressableSize).add(
lengthInBytes.mod(addressableSize).compareTo(BigInteger.ZERO) > 0
@ -984,15 +985,15 @@ public class Rendering extends Composite implements IDebugEventSetListener
BigInteger.valueOf(1));
BigInteger overlapLength = minEnd
.subtract(maxStart);
.subtract(maxStart).multiply(addressableSize);
if(overlapLength.compareTo(BigInteger.valueOf(0)) > 0)
{
// there is overlap
int offsetIntoOld = maxStart.subtract(
fHistoryCache[historyIndex].start).intValue();
int offsetIntoOld = (maxStart.subtract(
fHistoryCache[historyIndex].start).multiply(addressableSize)).intValue();
int offsetIntoNew = maxStart.subtract(
startAddress).intValue();
startAddress).multiply(addressableSize).intValue();
for(int i = overlapLength.intValue(); i >= 0; i--)
{
@ -1035,6 +1036,10 @@ public class Rendering extends Composite implements IDebugEventSetListener
Display.getDefault().getThread()) : TraditionalRenderingMessages
.getString("TraditionalRendering.CALLED_ON_NON_DISPATCH_THREAD"); //$NON-NLS-1$
//calculate the number of units needed for the number of requested bytes
int rem = (bytesRequested % getAddressableSize()) > 0 ? 1 : 0;
int units = bytesRequested / getAddressableSize() + rem;
if(containsEditedCell(address)) // cell size cannot be switched during an edit
return getEditedMemory(address);
@ -1042,7 +1047,7 @@ public class Rendering extends Composite implements IDebugEventSetListener
if(fCache != null && fCache.start != null)
{
// see if all of the data requested is in the cache
BigInteger dataEnd = address.add(BigInteger.valueOf(bytesRequested));
BigInteger dataEnd = address.add(BigInteger.valueOf(units));
if(fCache.start.compareTo(address) <= 0
&& fCache.end.compareTo(dataEnd) >= 0
@ -1052,7 +1057,7 @@ public class Rendering extends Composite implements IDebugEventSetListener
if(contains)
{
int offset = address.subtract(fCache.start).intValue();
int offset = address.subtract(fCache.start).multiply(BigInteger.valueOf(getAddressableSize())).intValue();
TraditionalMemoryByte bytes[] = new TraditionalMemoryByte[bytesRequested];
for(int i = 0; i < bytes.length; i++)
{

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2014 Wind River Systems, Inc. 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
@ -7,6 +7,7 @@
*
* Contributors:
* Ted R Williams (Wind River Systems, Inc.) - initial implementation
* Alvaro Sanchez-Leon (Ericsson AB) - [Memory] Support 16 bit addressable size (Bug 426730)
*******************************************************************************/
package org.eclipse.cdt.debug.ui.memory.traditional;
@ -1616,8 +1617,12 @@ abstract class CopyAction extends Action
// : 0);
final int columns = fRendering.getColumnCount();
BigInteger lengthToRead = end.subtract(start);
int addressableSize = fRendering.getAddressableSize();
assert(addressableSize != 0);
int addressesPerColumn = bytesPerColumn/addressableSize;
BigInteger lengthToRead = end.subtract(start).multiply(BigInteger.valueOf(addressableSize));
int rows = lengthToRead.divide(
BigInteger.valueOf(columns * bytesPerColumn)).intValue();
@ -1630,7 +1635,7 @@ abstract class CopyAction extends Action
for(int row = 0; row < rows; row++)
{
BigInteger rowAddress = start.add(BigInteger.valueOf(row
* columns * bytesPerColumn));
* columns * addressesPerColumn));
if(copyAddress)
{
@ -1643,7 +1648,7 @@ abstract class CopyAction extends Action
for(int col = 0; col < columns; col++)
{
BigInteger cellAddress = rowAddress.add(BigInteger
.valueOf(col * bytesPerColumn));
.valueOf(col * addressesPerColumn));
if(cellAddress.compareTo(end) < 0)
{
@ -1685,7 +1690,7 @@ abstract class CopyAction extends Action
for(int col = 0; col < columns; col++)
{
BigInteger cellAddress = rowAddress.add(BigInteger
.valueOf(col * fRendering.getBytesPerColumn()));
.valueOf(col * addressesPerColumn));
if(cellAddress.compareTo(end) < 0)
{