From e49589af700c255f49e09d13395f53d7ed4e82cd Mon Sep 17 00:00:00 2001 From: Alvaro Sanchez-Leon Date: Tue, 28 Jan 2014 13:55:54 +0100 Subject: [PATCH] Bug 426730: [Memory] Support 16 bit addressable size Change-Id: I1fa5498eebe66cc6febbfaf72c4e433bdfab48ed Signed-off-by: Alvaro Sanchez-Leon Reviewed-on: https://git.eclipse.org/r/22118 Reviewed-by: Marc Khouzam IP-Clean: Marc Khouzam Tested-by: Marc Khouzam --- .../gdb/internal/memory/GdbMemoryBlock.java | 21 +- .../memory/GdbMemoryBlockRetrieval.java | 34 ++- .../cdt/dsf/gdb/service/GDBMemory.java | 172 +++++++---- .../cdt/dsf/gdb/service/GDBMemory_7_0.java | 12 +- .../cdt/dsf/gdb/service/GDBMemory_7_6.java | 7 +- .../cdt/dsf/gdb/service/IGDBMemory2.java | 26 ++ .../eclipse/cdt/dsf/mi/service/MIMemory.java | 282 +++++++++--------- .../mi/service/command/CommandFactory.java | 22 +- .../command/commands/CLIAddressableSize.java | 49 +++ .../commands/MIDataReadMemoryBytes.java | 30 +- .../output/CLIAddressableSizeInfo.java | 60 ++++ .../output/MIDataReadMemoryBytesInfo.java | 30 +- .../cdt/tests/dsf/gdb/tests/MIMemoryTest.java | 30 +- .../cdt/dsf/debug/model/DsfMemoryBlock.java | 55 +++- .../ui/memory/traditional/Rendering.java | 23 +- .../traditional/TraditionalRendering.java | 17 +- 16 files changed, 590 insertions(+), 280 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBMemory2.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIAddressableSize.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressableSizeInfo.java diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/memory/GdbMemoryBlock.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/memory/GdbMemoryBlock.java index 723839de9ad..181f0a374c9 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/memory/GdbMemoryBlock.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/memory/GdbMemoryBlock.java @@ -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(retrieval.getExecutor(), drm) { @Override @@ -206,6 +207,12 @@ public class GdbMemoryBlock extends DsfMemoryBlock implements IMemorySpaceAwareM protected void execute(final DataRequestMonitor 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) { diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/memory/GdbMemoryBlockRetrieval.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/memory/GdbMemoryBlockRetrieval.java index 8fa44d5a422..1071d7f0360 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/memory/GdbMemoryBlockRetrieval.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/memory/GdbMemoryBlockRetrieval.java @@ -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; + } + } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory.java index dce70724c1c..2039226e2a8 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory.java @@ -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 fAddressSizes = new HashMap(); + /** + * Cache of the addressable sizes for each memory context. + */ + private Map fAddressableSizes = new HashMap(); + /** * 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()); @@ -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 drm) { + long offset, int word_size, int word_count, final DataRequestMonitor drm) { super.readMemoryBlock( dmc, address, offset, word_size, - count, + word_count, new DataRequestMonitor(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 stepsList = new ArrayList(); - + 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(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(requestMonitor) { + new Step() { + // store original language + @Override + public void execute(final RequestMonitor requestMonitor) { + fCommandControl.queueCommand( + fCommandControl.getCommandFactory().createMIGDBShowLanguage(memContext), + new ImmediateDataRequestMonitor(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(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(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(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(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 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(ImmediateExecutor.getInstance(), drm) { + @Override + protected void handleSuccess() { + drm.setData(Integer.valueOf(getData().getAddressableSize())); + drm.done(); + } + }); + } + protected void readEndianness(IMemoryDMContext memContext, final DataRequestMonitor drm) { CommandFactory commandFactory = fCommandControl.getCommandFactory(); fCommandControl.queueCommand( diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory_7_0.java index 5193c4cd300..f7f544a02c3 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory_7_0.java @@ -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 drm) + int word_size, int word_count, DataRequestMonitor 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); } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory_7_6.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory_7_6.java index c4678490d64..4351c013dcd 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory_7_6.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory_7_6.java @@ -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() { diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBMemory2.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBMemory2.java new file mode 100644 index 00000000000..7e5fa5111bc --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBMemory2.java @@ -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); + +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIMemory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIMemory.java index be7fa3dc801..c25305290c8 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIMemory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIMemory.java @@ -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 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()); - // Create the memory requests cache fMemoryCaches = new HashMap(); - // 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 drm) + int word_size, int word_count, DataRequestMonitor 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 drm) + final int word_size, final int word_count, final DataRequestMonitor 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(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(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 getListOfMissingBlocks(IAddress reqBlockStart, int count) { + private LinkedList getListOfMissingBlocks(IAddress reqBlockStart, int word_count, int word_size) { + int octetCount = word_count * word_size; LinkedList list = new LinkedList(); ListIterator 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 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 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 drm) + final int word_count, final DataRequestMonitor drm) { // Determine the number of read requests to issue - LinkedList missingBlocks = getListOfMissingBlocks(address, count); + LinkedList 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(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(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 list = getListOfMissingBlocks(address, count); + LinkedList 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(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()); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java index 872dbc3f82e..6ccefadf562 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/CommandFactory.java @@ -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 createCLIAddressableSize(IMemoryDMContext ctx) { + return new CLIAddressableSize(ctx); + } + public ICommand 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 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 createMIDataWriteMemory(IDMContext ctx, long offset, String address, int wordFormat, int wordSize, String value) { return new MIDataWriteMemory(ctx, offset, address, wordFormat, wordSize, value); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIAddressableSize.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIAddressableSize.java new file mode 100644 index 00000000000..cf9ace03864 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/CLIAddressableSize.java @@ -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; + +/** + *

CLI command used to resolve the addressable size

+ * 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 + */ +public class CLIAddressableSize extends MIInterpreterExecConsole { + + 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); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataReadMemoryBytes.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataReadMemoryBytes.java index a5a4579cb97..e75f0bf5ac5 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataReadMemoryBytes.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataReadMemoryBytes.java @@ -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 { - 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); } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressableSizeInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressableSizeInfo.java new file mode 100644 index 00000000000..cf576d6cc49 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/CLIAddressableSizeInfo.java @@ -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 + *
"p/x (char)-1" + * + *

E.g. if the response to 'p/x (char)-1' is

+ * $n = 0xffff + * + *

Then we can easily resolve it to 2 octets (e.g. 2 hex characters per octet)

+ * @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; + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIDataReadMemoryBytesInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIDataReadMemoryBytesInfo.java index afe9f8c6234..c1e857d2f3f 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIDataReadMemoryBytesInfo.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MIDataReadMemoryBytesInfo.java @@ -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)); diff --git a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIMemoryTest.java b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIMemoryTest.java index 0b5b7505d69..86ce9de3a6b 100644 --- a/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIMemoryTest.java +++ b/dsf-gdb/org.eclipse.cdt.tests.dsf.gdb/src/org/eclipse/cdt/tests/dsf/gdb/tests/MIMemoryTest.java @@ -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); } diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/model/DsfMemoryBlock.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/model/DsfMemoryBlock.java index e21001d4718..e414647f8fc 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/model/DsfMemoryBlock.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/model/DsfMemoryBlock.java @@ -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(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))) { diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java index 1575693ac24..6ec88963edf 100755 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/Rendering.java @@ -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++) { diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java index 9022e5eb7d7..1f27497cb8b 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java @@ -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) {