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 4aa41ceff4a..93ae25b1b5a 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 @@ -11,9 +11,11 @@ * Ericsson AB - added support for event handling * Ericsson AB - added memory cache * Vladimir Prus (CodeSourcery) - support for -data-read-memory-bytes (bug 322658) + * John Dallaway - support for -data-write-memory-bytes (bug 387793) *******************************************************************************/ package org.eclipse.cdt.dsf.mi.service; +import java.util.Arrays; import java.util.HashMap; import java.util.Hashtable; import java.util.LinkedList; @@ -48,6 +50,7 @@ import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; 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.MIInfo; import org.eclipse.cdt.dsf.service.AbstractDsfService; import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; import org.eclipse.cdt.dsf.service.DsfSession; @@ -400,22 +403,31 @@ public class MIMemory extends AbstractDsfService implements IMemory, ICachingSer 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) { - // 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); - - // 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++) { - String value = new Byte(buffer[i]).toString(); + if (fDataReadMemoryBytes) { + // Use -data-write-memory-bytes for performance fCommandCache.execute( - fCommandFactory.createMIDataWriteMemory(dmc, offset + i, baseAddress, format, word_size, value), - new DataRequestMonitor(getExecutor(), countingRM) + fCommandFactory.createMIDataWriteMemoryBytes(dmc, address.add(offset).toString(), + (buffer.length == count) ? buffer : Arrays.copyOf(buffer, count)), + new DataRequestMonitor(getExecutor(), rm) ); + } else { + // 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); + + // 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++) { + String value = new Byte(buffer[i]).toString(); + fCommandCache.execute( + fCommandFactory.createMIDataWriteMemory(dmc, offset + i, baseAddress, format, word_size, value), + new DataRequestMonitor(getExecutor(), countingRM) + ); + } } } 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 f62b44c1882..c10c43b7581 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 @@ -19,6 +19,7 @@ * Mathias Kunter - New methods for handling different charsets (Bug 370462) * Anton Gorenkov - A preference to use RTTI for variable types determination (Bug 377536) * Vladimir Prus (Mentor Graphics) - Support for -info-os (Bug 360314) + * John Dallaway - Support for -data-write-memory-bytes (Bug 387793) *******************************************************************************/ package org.eclipse.cdt.dsf.mi.service.command; @@ -73,6 +74,7 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIDataListRegisterValues; import org.eclipse.cdt.dsf.mi.service.command.commands.MIDataReadMemory; import org.eclipse.cdt.dsf.mi.service.command.commands.MIDataReadMemoryBytes; import org.eclipse.cdt.dsf.mi.service.command.commands.MIDataWriteMemory; +import org.eclipse.cdt.dsf.mi.service.command.commands.MIDataWriteMemoryBytes; import org.eclipse.cdt.dsf.mi.service.command.commands.MIEnablePrettyPrinting; import org.eclipse.cdt.dsf.mi.service.command.commands.MIEnvironmentCD; import org.eclipse.cdt.dsf.mi.service.command.commands.MIEnvironmentDirectory; @@ -430,6 +432,11 @@ public class CommandFactory { return new MIDataWriteMemory(ctx, offset, address, wordFormat, wordSize, value); } + /** @since 4.2 */ + public ICommand createMIDataWriteMemoryBytes(IDMContext ctx, String address, byte[] contents) { + return new MIDataWriteMemoryBytes(ctx, address, contents); + } + /** @since 4.0 */ public ICommand createMIEnablePrettyPrinting(ICommandControlDMContext ctx) { return new MIEnablePrettyPrinting(ctx); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataWriteMemoryBytes.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataWriteMemoryBytes.java new file mode 100644 index 00000000000..99d34c6d73c --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MIDataWriteMemoryBytes.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2012 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * John Dallaway - MIDataWriteMemoryBytes based on MIDataWriteMemory (bug 387793) + *******************************************************************************/ + +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; + +/** + * -data-write-memory-bytes ADDRESS CONTENTS + * + * where: + * + * 'ADDRESS' + * An expression specifying the address of the first memory word to be + * written. Complex expressions containing embedded white space should + * be quoted using the C convention. + * + * 'CONTENTS' + * The hex-encoded bytes to write. + * @since 4.2 + */ +public class MIDataWriteMemoryBytes extends MICommand { + + public MIDataWriteMemoryBytes( + IDMContext ctx, + String address, + byte[] contents) + { + super(ctx, "-data-write-memory-bytes"); //$NON-NLS-1$ + + // performance-oriented conversion of byte[] to hex string + final char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + char[] hex = new char[contents.length * 2]; + for (int n = 0; n < contents.length; n++) { + final int val = contents[n] & 0xFF; + hex[n*2] = digits[val >>> 4]; + hex[n*2 + 1] = digits[val & 0x0F]; + } + setParameters( + new String[] { + address, + new String(hex)}); + } +}