From a92105a031b62ee80f27c8048f99757f06a5b662 Mon Sep 17 00:00:00 2001 From: Alexander Fedorov Date: Thu, 16 Apr 2020 21:28:56 +0300 Subject: [PATCH] Bug 562164 - Add JUnit tests for IMemoryImporter implementations The following changes are done to make the implementation headless and testable: * Reworked FileImport to implement base flow * Added ImportRequest to aggregate operation configuration * Extracted PlainTextImport extends FileImport * Extracted RawBinaryImport extends FileImport * Extracted SRecordImport extends FileImport * Extracted FileImportJob * Added ScrollMemory to interact with UI * Added WriteMemoryBlock to isolate from UI class BufferedMemoryWriter * Reworked related i18n Change-Id: Ibd68c0e345e9455f5f8a2e1be673ddac5eb9a9b1 Signed-off-by: Alexander Fedorov --- .../debug.product | 1 + .../META-INF/MANIFEST.MF | 8 +- .../core/memory/transport/FileImport.java | 108 +++++++++ .../core/memory/transport/ImportRequest.java | 60 +++++ .../{MemoryImport.java => WriteMemory.java} | 27 ++- .../core/memory/transport/FileImportJob.java | 46 ++++ .../core/memory/transport/Messages.java | 37 ++++ .../memory/transport/PlainTextImport.java | 81 +++++++ .../memory/transport/RAWBinaryImport.java | 61 +++++ .../core/memory/transport/SRecordImport.java | 148 +++++++++++++ .../core/memory/transport/messages.properties | 24 ++ .../META-INF/MANIFEST.MF | 6 +- .../ui/memory/transport/ScrollMemory.java | 42 ++++ .../ui/memory/transport/WriteMemoryBlock.java | 47 ++++ .../memory/transport/PlainTextImporter.java | 137 +++--------- .../memory/transport/RAWBinaryImporter.java | 120 +++------- .../ui/memory/transport/SRecordImporter.java | 209 +++--------------- .../ui/memory/transport/messages.properties | 12 +- 18 files changed, 767 insertions(+), 407 deletions(-) create mode 100644 memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/FileImport.java create mode 100644 memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/ImportRequest.java rename memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/{MemoryImport.java => WriteMemory.java} (53%) create mode 100644 memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/FileImportJob.java create mode 100644 memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/Messages.java create mode 100644 memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/PlainTextImport.java create mode 100644 memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/RAWBinaryImport.java create mode 100644 memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/SRecordImport.java create mode 100644 memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/messages.properties create mode 100644 memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/internal/ui/memory/transport/ScrollMemory.java create mode 100644 memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/internal/ui/memory/transport/WriteMemoryBlock.java diff --git a/debug/org.eclipse.cdt.debug.application.product/debug.product b/debug/org.eclipse.cdt.debug.application.product/debug.product index fba11943ea1..5ae6a7e823a 100644 --- a/debug/org.eclipse.cdt.debug.application.product/debug.product +++ b/debug/org.eclipse.cdt.debug.application.product/debug.product @@ -210,6 +210,7 @@ Java and all Java-based trademarks are trademarks of Oracle Corporation in the U + diff --git a/memory/org.eclipse.cdt.debug.core.memory/META-INF/MANIFEST.MF b/memory/org.eclipse.cdt.debug.core.memory/META-INF/MANIFEST.MF index cbf7857f082..806e40b48f9 100644 --- a/memory/org.eclipse.cdt.debug.core.memory/META-INF/MANIFEST.MF +++ b/memory/org.eclipse.cdt.debug.core.memory/META-INF/MANIFEST.MF @@ -6,6 +6,8 @@ Bundle-Version: 0.1.0.qualifier Bundle-Name: %Bundle-Name Bundle-Vendor: %Bundle-Vendor Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: org.eclipse.cdt.debug.core;bundle-version="8.4.100", - org.eclipse.core.runtime;bundle-version="3.17.200" -Export-Package: org.eclipse.cdt.debug.core.memory.transport;x-friends:="org.eclipse.cdt.debug.ui.memory.transport" +Require-Bundle: org.eclipse.core.runtime;bundle-version="3.17.0", + org.eclipse.debug.core;bundle-version="3.15.0", + org.eclipse.equinox.common;bundle-version="3.11.0" +Export-Package: org.eclipse.cdt.debug.core.memory.transport;x-friends:="org.eclipse.cdt.debug.ui.memory.transport", + org.eclipse.cdt.debug.internal.core.memory.transport;x-friends:="org.eclipse.cdt.debug.ui.memory.transport" diff --git a/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/FileImport.java b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/FileImport.java new file mode 100644 index 00000000000..d0a0f295902 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/FileImport.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2020 ArSysOp and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Alexander Fedorov (ArSysOp) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.memory.transport; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.math.BigInteger; +import java.util.function.Consumer; + +import org.eclipse.cdt.debug.internal.core.memory.transport.Messages; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.ICoreRunnable; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; +import org.osgi.framework.FrameworkUtil; + +/** + * Imports memory information from a given file + * + * @since 0.1 + */ +public abstract class FileImport implements ICoreRunnable { + + protected final BigInteger base; + protected final BigInteger start; + protected final WriteMemory write; + protected final Consumer scroll; + + private final File inputFile; + + protected FileImport(File input, ImportRequest request, Consumer scroll) { + this.inputFile = input; + this.base = request.base(); + this.start = request.start(); + this.write = request.write(); + this.scroll = scroll; + } + + @Override + public void run(IProgressMonitor monitor) throws CoreException { + try (I reader = input(inputFile)) { + BigInteger jobs = BigInteger.valueOf(inputFile.length()); + BigInteger factor = BigInteger.ONE; + if (jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) { + factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF)); + jobs = jobs.divide(factor); + } + monitor.beginTask(Messages.FileImport_task_transferring, jobs.intValue()); + transfer(monitor, reader, factor); + if (!monitor.isCanceled()) { + write.flush(); + } + } catch (IOException ex) { + requestFailed(Messages.FileImport_e_read_from_file, ex); + } catch (DebugException ex) { + requestFailed(Messages.FileImport_e_write_to_target, ex); + } catch (CoreException ex) { + failed(ex); + } catch (Exception ex) { + internalError(Messages.FileImport_e_import_from_file, ex); + } finally { + monitor.done(); + } + } + + protected abstract I input(File file) throws FileNotFoundException; + + protected abstract void transfer(IProgressMonitor monitor, I input, BigInteger factor) + throws IOException, CoreException, DebugException; + + protected void requestFailed(String message, Throwable exception) throws CoreException { + failed(DebugException.REQUEST_FAILED, message, exception); + } + + protected void internalError(String message, Throwable exception) throws CoreException { + failed(DebugException.INTERNAL_ERROR, message, exception); + } + + protected void failed(int code, String message, Throwable exception) throws CoreException { + Status status = new Status(// + IStatus.ERROR, // + FrameworkUtil.getBundle(getClass()).getSymbolicName(), // + code, // + message, // + exception); + failed(new CoreException(status)); + } + + protected void failed(CoreException exception) throws CoreException { + Platform.getLog(FrameworkUtil.getBundle(getClass())).log(exception.getStatus()); + throw exception; + } +} diff --git a/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/ImportRequest.java b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/ImportRequest.java new file mode 100644 index 00000000000..2085e966040 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/ImportRequest.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2020 ArSysOp and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Alexander Fedorov (ArSysOp) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.memory.transport; + +import java.math.BigInteger; + +/** + * + * Aggregates memory import configuration + * + * @since 0.1 + * + */ +public class ImportRequest { + + private final BigInteger base; + private final BigInteger start; + private final WriteMemory write; + + public ImportRequest(BigInteger base, BigInteger start, WriteMemory write) { + this.base = base; + this.start = start; + this.write = write; + } + + /** + * + * @return base memory address + */ + public BigInteger base() { + return base; + } + + /** + * + * @return starting offset + */ + public BigInteger start() { + return start; + } + + /** + * + * @return writer + */ + public WriteMemory write() { + return write; + } +} diff --git a/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/MemoryImport.java b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/WriteMemory.java similarity index 53% rename from memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/MemoryImport.java rename to memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/WriteMemory.java index cd21c343d24..1f058c1715d 100644 --- a/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/MemoryImport.java +++ b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/core/memory/transport/WriteMemory.java @@ -13,15 +13,30 @@ *******************************************************************************/ package org.eclipse.cdt.debug.core.memory.transport; -import org.eclipse.core.runtime.ICoreRunnable; +import java.math.BigInteger; + +import org.eclipse.debug.core.DebugException; /** - * Imports memory information from a given source + * Writes an array of bytes using the given offset * * @since 0.1 */ -public abstract class MemoryImport implements ICoreRunnable { - /* WIP: here we will place basic logic to read the data and notify consumer interactively - private final Consumer scroll; - */ +public interface WriteMemory { + + /** + * Writes the given data to a memory starting from the given offset. Actual write may be delayed until the nearest {@link WriteMemory#flush()} call + * + * @param offset + * @param data + * @throws DebugException + */ + void to(BigInteger offset, byte[] data) throws DebugException; + + /** + * Forces data write to a memory. + * + * @throws DebugException + */ + void flush() throws DebugException; } diff --git a/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/FileImportJob.java b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/FileImportJob.java new file mode 100644 index 00000000000..efc3e7517dc --- /dev/null +++ b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/FileImportJob.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2020 ArSysOp and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Alexander Fedorov (ArSysOp) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.core.memory.transport; + +import org.eclipse.cdt.debug.core.memory.transport.FileImport; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; + +/** + * Runs {@link FileImport} operation as a {@link Job} + * + */ +public final class FileImportJob extends Job { + + private final FileImport fileImport; + + public FileImportJob(String name, FileImport fileImport) { + super(name); + this.fileImport = fileImport; + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + fileImport.run(monitor); + } catch (CoreException e) { + return e.getStatus(); + } + return Status.OK_STATUS; + } + +} diff --git a/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/Messages.java b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/Messages.java new file mode 100644 index 00000000000..ab23d0f8008 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/Messages.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2020 ArSysOp and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Alexander Fedorov (ArSysOp) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.core.memory.transport; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.debug.internal.core.memory.transport.messages"; //$NON-NLS-1$ + public static String FileImport_e_import_from_file; + public static String FileImport_e_read_from_file; + public static String FileImport_e_write_to_target; + public static String FileImport_task_transferring; + public static String PlainTextImport_e_invalid_format; + public static String SRecordImport_e_checksum_failure; + public static String SRecordImport_e_invalid_address; + public static String SRecordImport_e_invalid_checksum_format; + public static String SRecordImport_e_invalid_data; + public static String SRecordImport_e_invalid_line_length; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/PlainTextImport.java b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/PlainTextImport.java new file mode 100644 index 00000000000..caa32984fa3 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/PlainTextImport.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2006, 2020 Wind River Systems, Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + * Alexander Fedorov (ArSysOp) - headless part extraction + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.core.memory.transport; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.math.BigInteger; +import java.util.StringTokenizer; +import java.util.function.Consumer; + +import org.eclipse.cdt.debug.core.memory.transport.FileImport; +import org.eclipse.cdt.debug.core.memory.transport.ImportRequest; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; +import org.osgi.framework.FrameworkUtil; + +public final class PlainTextImport extends FileImport { + + public PlainTextImport(File input, ImportRequest request, Consumer scroll) { + super(input, request, scroll); + } + + @Override + protected BufferedReader input(File file) throws FileNotFoundException { + return new BufferedReader(new InputStreamReader(new FileInputStream(file))); + } + + @Override + protected void transfer(IProgressMonitor monitor, BufferedReader reader, BigInteger factor) + throws IOException, CoreException, DebugException { + BigInteger recordAddress = start; + String line = reader.readLine(); + int lineNo = 1; // line error reporting + while (line != null && !monitor.isCanceled()) { + StringTokenizer st = new StringTokenizer(line, " "); //$NON-NLS-1$ + int bytesRead = 0; + while (st.hasMoreElements()) { + String valueString = (String) st.nextElement(); + int position = 0; + byte data[] = new byte[valueString.length() / 2]; + for (int i = 0; i < data.length; i++) { + try { + data[i] = new BigInteger(valueString.substring(position++, position++ + 1), 16).byteValue(); + } catch (NumberFormatException ex) { + throw new CoreException(new Status(IStatus.ERROR, + FrameworkUtil.getBundle(getClass()).getSymbolicName(), DebugException.REQUEST_FAILED, + String.format(Messages.PlainTextImport_e_invalid_format, lineNo), ex)); + } + } + BigInteger writeAddress = recordAddress.subtract(base).add(BigInteger.valueOf(bytesRead)); + write.to(writeAddress, data); + bytesRead += data.length; + } + recordAddress = recordAddress.add(BigInteger.valueOf(bytesRead)); + scroll.accept(recordAddress); + BigInteger jobCount = BigInteger.valueOf(bytesRead).divide(factor); + monitor.worked(jobCount.intValue()); + line = reader.readLine(); + lineNo++; + } + } +} \ No newline at end of file diff --git a/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/RAWBinaryImport.java b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/RAWBinaryImport.java new file mode 100644 index 00000000000..725b63a8ade --- /dev/null +++ b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/RAWBinaryImport.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2006, 2020 Wind River Systems, Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + * Alexander Fedorov (ArSysOp) - headless part extraction + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.core.memory.transport; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.math.BigInteger; +import java.util.function.Consumer; + +import org.eclipse.cdt.debug.core.memory.transport.FileImport; +import org.eclipse.cdt.debug.core.memory.transport.ImportRequest; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.debug.core.DebugException; + +public final class RAWBinaryImport extends FileImport { + + public RAWBinaryImport(File input, ImportRequest request, Consumer scroll) { + super(input, request, scroll); + } + + @Override + protected FileInputStream input(File file) throws FileNotFoundException { + return new FileInputStream(file); + } + + @Override + protected void transfer(IProgressMonitor monitor, FileInputStream input, BigInteger factor) + throws IOException, CoreException, DebugException { + byte[] byteValues = new byte[1024]; + int actualByteCount = input.read(byteValues); + BigInteger recordAddress = start; + while (actualByteCount != -1 && !monitor.isCanceled()) { + byte data[] = new byte[actualByteCount]; + for (int i = 0; i < data.length; i++) { + data[i] = byteValues[i]; + } + write.to(recordAddress.subtract(base), data); + BigInteger jobCount = BigInteger.valueOf(actualByteCount).divide(factor); + monitor.worked(jobCount.intValue()); + recordAddress = recordAddress.add(BigInteger.valueOf(actualByteCount)); + scroll.accept(recordAddress); + actualByteCount = input.read(byteValues); + } + } + +} \ No newline at end of file diff --git a/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/SRecordImport.java b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/SRecordImport.java new file mode 100644 index 00000000000..dc34d122590 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/SRecordImport.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright (c) 2006, 2020 Wind River Systems, Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Ted R Williams (Wind River Systems, Inc.) - initial implementation + * Alexander Fedorov (ArSysOp) - headless part extraction + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.core.memory.transport; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.math.BigInteger; +import java.util.function.Consumer; + +import org.eclipse.cdt.debug.core.memory.transport.FileImport; +import org.eclipse.cdt.debug.core.memory.transport.ImportRequest; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; +import org.osgi.framework.FrameworkUtil; + +public class SRecordImport extends FileImport { + + private final boolean transfer; + + public SRecordImport(File input, ImportRequest request, Consumer scroll, boolean transfer) { + super(input, request, scroll); + this.transfer = transfer; + } + + @Override + protected BufferedReader input(File file) throws FileNotFoundException { + return new BufferedReader(new InputStreamReader(new FileInputStream(file))); + } + + @Override + protected void transfer(IProgressMonitor monitor, BufferedReader reader, BigInteger factor) + throws IOException, CoreException, DebugException { + // FIXME 4 byte default + final int CHECKSUM_LENGTH = 1; + BigInteger offset = null; + if (!transfer) { + offset = BigInteger.ZERO; + } + String line = reader.readLine(); + int lineNo = 1; // line error reporting + while (line != null && !monitor.isCanceled()) { + String recordType = line.substring(0, 2); + int recordCount = 0; + try { + recordCount = Integer.parseInt(line.substring(2, 4), 16); + } catch (NumberFormatException ex) { + throw new CoreException(new Status(IStatus.ERROR, FrameworkUtil.getBundle(getClass()).getSymbolicName(), + DebugException.REQUEST_FAILED, + String.format(Messages.SRecordImport_e_invalid_line_length, lineNo), ex)); + } + int bytesRead = 4 + recordCount; + int position = 4; + int addressSize = 0; + BigInteger recordAddress = null; + if ("S3".equals(recordType)) //$NON-NLS-1$ + addressSize = 4; + else if ("S1".equals(recordType)) //$NON-NLS-1$ + addressSize = 2; + else if ("S2".equals(recordType)) //$NON-NLS-1$ + addressSize = 3; + else if ("S0".equals(recordType) || "S5".equals(recordType) || "S7".equals(recordType) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + || "S8".equals(recordType) || "S9".equals(recordType)) //$NON-NLS-1$ //$NON-NLS-2$ + { // ignore S0, S5, S7, S8 and S9 records + line = reader.readLine(); + lineNo++; + continue; + } + try { + recordAddress = new BigInteger(line.substring(position, position + addressSize * 2), 16); + } catch (NumberFormatException ex) { + throw new CoreException(new Status(IStatus.ERROR, FrameworkUtil.getBundle(getClass()).getSymbolicName(), + DebugException.REQUEST_FAILED, String.format(Messages.SRecordImport_e_invalid_address, lineNo), + ex)); + } + recordCount -= addressSize; + position += addressSize * 2; + if (offset == null) { + offset = start.subtract(recordAddress); + } + recordAddress = recordAddress.add(offset); + byte data[] = new byte[recordCount - CHECKSUM_LENGTH]; + for (int i = 0; i < data.length; i++) { + try { + data[i] = new BigInteger(line.substring(position++, position++ + 1), 16).byteValue(); + } catch (NumberFormatException ex) { + throw new CoreException(new Status(IStatus.ERROR, + FrameworkUtil.getBundle(getClass()).getSymbolicName(), DebugException.REQUEST_FAILED, + String.format(Messages.SRecordImport_e_invalid_data, lineNo), ex)); + } + } + /* + * The least significant byte of the one's complement of the sum of the values + * represented by the pairs of characters making up the records length, address, + * and the code/data fields. + */ + StringBuilder buf = new StringBuilder(line.substring(2)); + byte checksum = 0; + for (int i = 0; i < buf.length(); i += 2) { + BigInteger value = null; + try { + value = new BigInteger(buf.substring(i, i + 2), 16); + } catch (NumberFormatException ex) { + throw new CoreException(new Status(IStatus.ERROR, + FrameworkUtil.getBundle(getClass()).getSymbolicName(), DebugException.REQUEST_FAILED, + String.format(Messages.SRecordImport_e_invalid_checksum_format, lineNo), ex)); + } + checksum += value.byteValue(); + } + /* + * Since we included the checksum in the checksum calculation the checksum + * ( if correct ) will always be 0xFF which is -1 using the signed byte size + * calculation here. + */ + if (checksum != (byte) -1) { + monitor.done(); + throw new CoreException(new Status(IStatus.ERROR, FrameworkUtil.getBundle(getClass()).getSymbolicName(), + String.format(Messages.SRecordImport_e_checksum_failure, line))); + } + scroll.accept(recordAddress); + // FIXME error on incorrect checksum + write.to(recordAddress.subtract(base), data); + BigInteger jobCount = BigInteger.valueOf(bytesRead).divide(factor); + monitor.worked(jobCount.intValue()); + line = reader.readLine(); + lineNo++; + } + } + +} \ No newline at end of file diff --git a/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/messages.properties b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/messages.properties new file mode 100644 index 00000000000..7917646f5aa --- /dev/null +++ b/memory/org.eclipse.cdt.debug.core.memory/src/org/eclipse/cdt/debug/internal/core/memory/transport/messages.properties @@ -0,0 +1,24 @@ +############################################################################### +# Copyright (c) 2020 ArSysOp and others. +# +# This program and the accompanying materials +# are made available under the terms of the Eclipse Public License 2.0 +# which accompanies this distribution, and is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Alexander Fedorov (ArSysOp) - initial API and implementation +############################################################################### + +FileImport_e_import_from_file=Failure importing from file +FileImport_e_read_from_file=Could not read from file. +FileImport_e_write_to_target=Could not write to target. +FileImport_task_transferring=Transferring Data +PlainTextImport_e_invalid_format=Invalid file format. Expected integer at line %d +SRecordImport_e_checksum_failure=Checksum failure of line = %d +SRecordImport_e_invalid_address=Invalid file format. Invalid address at line %d +SRecordImport_e_invalid_checksum_format=Invalid file format. Invalid checksum format at line %d +SRecordImport_e_invalid_data=Invalid file format. Invalid data at line %d +SRecordImport_e_invalid_line_length=Invalid file format. Invalid line length at line %d diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/META-INF/MANIFEST.MF b/memory/org.eclipse.cdt.debug.ui.memory.transport/META-INF/MANIFEST.MF index 8d3a4901987..41df79fdf42 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.transport/META-INF/MANIFEST.MF +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/META-INF/MANIFEST.MF @@ -5,7 +5,8 @@ Bundle-SymbolicName: org.eclipse.cdt.debug.ui.memory.transport;singleton:=true Bundle-Version: 2.1.200.qualifier Bundle-Localization: plugin Bundle-Vendor: %providerName -Require-Bundle: org.eclipse.debug.core, +Require-Bundle: org.eclipse.cdt.debug.core.memory;bundle-version="0.1.0", + org.eclipse.debug.core, org.eclipse.debug.ui, org.eclipse.core.runtime, org.eclipse.swt, @@ -14,7 +15,8 @@ Require-Bundle: org.eclipse.debug.core, Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Bundle-Activator: org.eclipse.cdt.debug.ui.memory.transport.MemoryTransportPlugin -Export-Package: org.eclipse.cdt.debug.ui.memory.transport, +Export-Package: org.eclipse.cdt.debug.internal.ui.memory.transport;x-internal:=true, + org.eclipse.cdt.debug.ui.memory.transport, org.eclipse.cdt.debug.ui.memory.transport.actions, org.eclipse.cdt.debug.ui.memory.transport.model Automatic-Module-Name: org.eclipse.cdt.debug.ui.memory.transport diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/internal/ui/memory/transport/ScrollMemory.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/internal/ui/memory/transport/ScrollMemory.java new file mode 100644 index 00000000000..58a24a2bfaf --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/internal/ui/memory/transport/ScrollMemory.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2020 ArSysOp and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Alexander Fedorov (ArSysOp) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.ui.memory.transport; + +import java.math.BigInteger; +import java.util.function.Consumer; + +import org.eclipse.cdt.debug.ui.memory.transport.ImportMemoryDialog; + +public final class ScrollMemory implements Consumer { + + private final ImportMemoryDialog dialog; + + public ScrollMemory(ImportMemoryDialog dialog) { + this.dialog = dialog; + } + + @Override + public void accept(BigInteger address) { + dialog.scrollRenderings(address); + } + + public static class Ignore implements Consumer { + + @Override + public void accept(BigInteger t) { + //ignore + } + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/internal/ui/memory/transport/WriteMemoryBlock.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/internal/ui/memory/transport/WriteMemoryBlock.java new file mode 100644 index 00000000000..eff285e7f96 --- /dev/null +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/internal/ui/memory/transport/WriteMemoryBlock.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2020 ArSysOp and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Alexander Fedorov (ArSysOp) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.ui.memory.transport; + +import java.math.BigInteger; + +import org.eclipse.cdt.debug.core.memory.transport.WriteMemory; +import org.eclipse.cdt.debug.ui.memory.transport.BufferedMemoryWriter; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlockExtension; + +/** + * Writes to a given {@link IMemoryBlockExtension} using {@link BufferedMemoryWriter} + * + * + */ +public final class WriteMemoryBlock implements WriteMemory { + + private final BufferedMemoryWriter writer; + private final int capacity = 64 * 1024; + + public WriteMemoryBlock(IMemoryBlockExtension block) { + this.writer = new BufferedMemoryWriter(block, capacity); + } + + @Override + public void to(BigInteger offset, byte[] data) throws DebugException { + writer.write(offset, data); + } + + @Override + public void flush() throws DebugException { + writer.flush(); + } + +} diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/PlainTextImporter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/PlainTextImporter.java index fd3b36b42dc..03a53c4f630 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/PlainTextImporter.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/PlainTextImporter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2013 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2020 Wind River Systems, Inc. and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,26 +10,25 @@ * * Contributors: * Ted R Williams (Wind River Systems, Inc.) - initial implementation + * Alexander Fedorov (ArSysOp) - headless part extraction *******************************************************************************/ package org.eclipse.cdt.debug.ui.memory.transport; -import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; import java.math.BigInteger; -import java.util.StringTokenizer; +import java.util.function.Consumer; +import org.eclipse.cdt.debug.core.memory.transport.ImportRequest; +import org.eclipse.cdt.debug.internal.core.memory.transport.FileImportJob; +import org.eclipse.cdt.debug.internal.core.memory.transport.PlainTextImport; +import org.eclipse.cdt.debug.internal.ui.memory.transport.ScrollMemory; +import org.eclipse.cdt.debug.internal.ui.memory.transport.WriteMemoryBlock; import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryImporter; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; @@ -64,8 +63,6 @@ public class PlainTextImporter implements IMemoryImporter { private IDialogSettings fProperties; - private static final int BUFFER_LENGTH = 64 * 1024; - @Override public Control createControl(final Composite parent, IMemoryBlock memBlock, IDialogSettings properties, ImportMemoryDialog parentDialog) { @@ -267,104 +264,22 @@ public class PlainTextImporter implements IMemoryImporter { @Override public void importMemory() { - Job job = new Job("Memory Import from Plain Text File") { //$NON-NLS-1$ - - @Override - public IStatus run(IProgressMonitor monitor) { - try { - BufferedMemoryWriter memoryWriter = new BufferedMemoryWriter((IMemoryBlockExtension) fMemoryBlock, - BUFFER_LENGTH); - - BigInteger scrollToAddress = null; - - BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fInputFile))); - - BigInteger jobs = BigInteger.valueOf(fInputFile.length()); - BigInteger factor = BigInteger.ONE; - if (jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) { - factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF)); - jobs = jobs.divide(factor); - } - - monitor.beginTask(Messages.getString("Importer.ProgressTitle"), jobs.intValue()); //$NON-NLS-1$ - - BigInteger recordAddress = fStartAddress; - String line = reader.readLine(); - int lineNo = 1; // line error reporting - while (line != null && !monitor.isCanceled()) { - StringTokenizer st = new StringTokenizer(line, " "); //$NON-NLS-1$ - int bytesRead = 0; - while (st.hasMoreElements()) { - String valueString = (String) st.nextElement(); - int position = 0; - byte data[] = new byte[valueString.length() / 2]; - for (int i = 0; i < data.length; i++) { - try { - data[i] = new BigInteger(valueString.substring(position++, position++ + 1), 16) - .byteValue(); - } catch (NumberFormatException ex) { - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, - String.format(Messages.getString("PlainTextImporter.ErrInvalidFormat"), //$NON-NLS-1$ - lineNo), - ex); - } - } - - if (scrollToAddress == null) - scrollToAddress = recordAddress; - - BigInteger writeAddress = - - recordAddress.subtract(((IMemoryBlockExtension) fMemoryBlock).getBigBaseAddress()) - .add(BigInteger.valueOf(bytesRead)); - - memoryWriter.write(writeAddress, data); - - bytesRead += data.length; - } - - recordAddress = recordAddress.add(BigInteger.valueOf(bytesRead)); - - BigInteger jobCount = BigInteger.valueOf(bytesRead).divide(factor); - monitor.worked(jobCount.intValue()); - - line = reader.readLine(); - lineNo++; - } - - if (!monitor.isCanceled()) - memoryWriter.flush(); - - reader.close(); - monitor.done(); - - if (fScrollToStart) - fParentDialog.scrollRenderings(scrollToAddress); - } catch (IOException ex) { - MemoryTransportPlugin.getDefault().getLog() - .log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrReadFile"), ex)); //$NON-NLS-1$ - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrReadFile"), ex); //$NON-NLS-1$ - - } catch (DebugException ex) { - MemoryTransportPlugin.getDefault().getLog() - .log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrWriteTarget"), ex)); //$NON-NLS-1$ - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrWriteTarget"), ex); //$NON-NLS-1$ - } catch (Exception ex) { - MemoryTransportPlugin.getDefault().getLog() - .log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.INTERNAL_ERROR, Messages.getString("Importer.FalureImporting"), ex)); //$NON-NLS-1$ - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.INTERNAL_ERROR, Messages.getString("Importer.FalureImporting"), ex); //$NON-NLS-1$ - } - return Status.OK_STATUS; - } - }; - job.setUser(true); - job.schedule(); + try { + Consumer scroll = fScrollToStart ? new ScrollMemory(fParentDialog) : new ScrollMemory.Ignore(); + IMemoryBlockExtension block = (IMemoryBlockExtension) fMemoryBlock; + ImportRequest request = new ImportRequest(block.getBigBaseAddress(), fStartAddress, + new WriteMemoryBlock(block)); + PlainTextImport memoryImport = new PlainTextImport(fInputFile, request, scroll); + FileImportJob job = new FileImportJob(// + "Memory Import from Plain Text File", memoryImport); + job.setUser(true); + job.schedule(); + } catch (DebugException e) { + //FIXME: unreachable with current implementation, to be i18n after UI rework + ErrorDialog.openError(fParentDialog.getShell(), // + "Import Failure", // + "Failed to retrieve base memory address", // + e.getStatus()); + } } } diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/RAWBinaryImporter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/RAWBinaryImporter.java index f9f12b05d7e..9eee1f1d233 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/RAWBinaryImporter.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/RAWBinaryImporter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2013 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2020 Wind River Systems, Inc. and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,23 +10,25 @@ * * Contributors: * Ted R Williams (Wind River Systems, Inc.) - initial implementation + * Alexander Fedorov (ArSysOp) - headless part extraction *******************************************************************************/ package org.eclipse.cdt.debug.ui.memory.transport; import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; import java.math.BigInteger; +import java.util.function.Consumer; +import org.eclipse.cdt.debug.core.memory.transport.ImportRequest; +import org.eclipse.cdt.debug.internal.core.memory.transport.FileImportJob; +import org.eclipse.cdt.debug.internal.core.memory.transport.RAWBinaryImport; +import org.eclipse.cdt.debug.internal.ui.memory.transport.ScrollMemory; +import org.eclipse.cdt.debug.internal.ui.memory.transport.WriteMemoryBlock; import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryImporter; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; @@ -61,8 +63,6 @@ public class RAWBinaryImporter implements IMemoryImporter { private IDialogSettings fProperties; - private static final int BUFFER_LENGTH = 64 * 1024; - @Override public Control createControl(final Composite parent, IMemoryBlock memBlock, IDialogSettings properties, ImportMemoryDialog parentDialog) { @@ -247,89 +247,23 @@ public class RAWBinaryImporter implements IMemoryImporter { @Override public void importMemory() { - Job job = new Job("Memory Import from RAW Binary File") { //$NON-NLS-1$ - - @Override - public IStatus run(IProgressMonitor monitor) { - try { - BufferedMemoryWriter memoryWriter = new BufferedMemoryWriter((IMemoryBlockExtension) fMemoryBlock, - BUFFER_LENGTH); - - BigInteger scrollToAddress = null; - - FileInputStream reader = new FileInputStream(fInputFile); - - BigInteger jobs = BigInteger.valueOf(fInputFile.length()); - BigInteger factor = BigInteger.ONE; - if (jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) { - factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF)); - jobs = jobs.divide(factor); - } - - byte[] byteValues = new byte[1024]; - - monitor.beginTask(Messages.getString("Importer.ProgressTitle"), jobs.intValue()); //$NON-NLS-1$ - - int actualByteCount = reader.read(byteValues); - BigInteger recordAddress = fStartAddress; - - while (actualByteCount != -1 && !monitor.isCanceled()) { - byte data[] = new byte[actualByteCount]; - for (int i = 0; i < data.length; i++) { - data[i] = byteValues[i]; - } - - if (scrollToAddress == null) - scrollToAddress = recordAddress; - - BigInteger baseAddress = null; - if (fMemoryBlock instanceof IMemoryBlockExtension) - baseAddress = ((IMemoryBlockExtension) fMemoryBlock).getBigBaseAddress(); - else - baseAddress = BigInteger.valueOf(fMemoryBlock.getStartAddress()); - - memoryWriter.write(recordAddress.subtract(baseAddress), data); - - BigInteger jobCount = BigInteger.valueOf(actualByteCount).divide(factor); - monitor.worked(jobCount.intValue()); - - recordAddress = recordAddress.add(BigInteger.valueOf(actualByteCount)); - actualByteCount = reader.read(byteValues); - } - - if (!monitor.isCanceled()) - memoryWriter.flush(); - - reader.close(); - monitor.done(); - - if (fScrollToStart) - fParentDialog.scrollRenderings(scrollToAddress); - - } catch (IOException ex) { - MemoryTransportPlugin.getDefault().getLog() - .log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrReadFile"), ex)); //$NON-NLS-1$ - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrReadFile"), ex); //$NON-NLS-1$ - - } catch (DebugException ex) { - MemoryTransportPlugin.getDefault().getLog() - .log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrWriteTarget"), ex)); //$NON-NLS-1$ - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrWriteTarget"), ex); //$NON-NLS-1$ - } catch (Exception ex) { - MemoryTransportPlugin.getDefault().getLog() - .log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.INTERNAL_ERROR, Messages.getString("Importer.FalureImporting"), ex)); //$NON-NLS-1$ - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.INTERNAL_ERROR, Messages.getString("Importer.FalureImporting"), ex); //$NON-NLS-1$ - } - return Status.OK_STATUS; - } - }; - job.setUser(true); - job.schedule(); + try { + Consumer scroll = fScrollToStart ? new ScrollMemory(fParentDialog) : new ScrollMemory.Ignore(); + IMemoryBlockExtension block = (IMemoryBlockExtension) fMemoryBlock; + ImportRequest request = new ImportRequest(block.getBigBaseAddress(), fStartAddress, + new WriteMemoryBlock(block)); + RAWBinaryImport memoryImport = new RAWBinaryImport(fInputFile, request, scroll); + FileImportJob job = new FileImportJob(// + "Memory Import from RAW Binary File", memoryImport); + job.setUser(true); + job.schedule(); + } catch (DebugException e) { + //FIXME: unreachable with current implementation, to be i18n after UI rework + ErrorDialog.openError(fParentDialog.getShell(), // + "Import Failure", // + "Failed to retrieve base memory address", // + e.getStatus()); + } } + } diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/SRecordImporter.java b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/SRecordImporter.java index 318ca6dc6e6..8e5988583b1 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/SRecordImporter.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/SRecordImporter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2016 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2020 Wind River Systems, Inc. and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -10,25 +10,25 @@ * * Contributors: * Ted R Williams (Wind River Systems, Inc.) - initial implementation + * Alexander Fedorov (ArSysOp) - headless part extraction *******************************************************************************/ package org.eclipse.cdt.debug.ui.memory.transport; -import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; import java.math.BigInteger; +import java.util.function.Consumer; +import org.eclipse.cdt.debug.core.memory.transport.ImportRequest; +import org.eclipse.cdt.debug.internal.core.memory.transport.FileImportJob; +import org.eclipse.cdt.debug.internal.core.memory.transport.SRecordImport; +import org.eclipse.cdt.debug.internal.ui.memory.transport.ScrollMemory; +import org.eclipse.cdt.debug.internal.ui.memory.transport.WriteMemoryBlock; import org.eclipse.cdt.debug.ui.memory.transport.model.IMemoryImporter; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IMemoryBlockExtension; +import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; @@ -68,8 +68,6 @@ public class SRecordImporter implements IMemoryImporter { private IDialogSettings fProperties; - private static final int BUFFER_LENGTH = 64 * 1024; - @Override public Control createControl(final Composite parent, IMemoryBlock memBlock, IDialogSettings properties, ImportMemoryDialog parentDialog) { @@ -337,176 +335,23 @@ public class SRecordImporter implements IMemoryImporter { @Override public void importMemory() { - Job job = new Job("Memory Import from S-Record File") { //$NON-NLS-1$ - - @Override - public IStatus run(IProgressMonitor monitor) { - - try { - BufferedMemoryWriter memoryWriter = new BufferedMemoryWriter((IMemoryBlockExtension) fMemoryBlock, - BUFFER_LENGTH); - - // FIXME 4 byte default - - final int CHECKSUM_LENGTH = 1; - - BigInteger scrollToAddress = null; - - BigInteger offset = null; - if (!fProperties.getBoolean(TRANSFER_CUSTOM_START_ADDRESS)) - offset = BigInteger.ZERO; - - BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fInputFile))); - - BigInteger jobs = BigInteger.valueOf(fInputFile.length()); - BigInteger factor = BigInteger.ONE; - if (jobs.compareTo(BigInteger.valueOf(0x7FFFFFFF)) > 0) { - factor = jobs.divide(BigInteger.valueOf(0x7FFFFFFF)); - jobs = jobs.divide(factor); - } - - monitor.beginTask(Messages.getString("Importer.ProgressTitle"), jobs.intValue()); //$NON-NLS-1$ - - String line = reader.readLine(); - int lineNo = 1; // line error reporting - while (line != null && !monitor.isCanceled()) { - String recordType = line.substring(0, 2); - int recordCount = 0; - try { - recordCount = Integer.parseInt(line.substring(2, 4), 16); - } catch (NumberFormatException ex) { - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, - String.format(Messages.getString("SRecordImporter.InvalidLineLength"), lineNo), ex); //$NON-NLS-1$ - } - - int bytesRead = 4 + recordCount; - int position = 4; - int addressSize = 0; - - BigInteger recordAddress = null; - - if ("S3".equals(recordType)) //$NON-NLS-1$ - addressSize = 4; - else if ("S1".equals(recordType)) //$NON-NLS-1$ - addressSize = 2; - else if ("S2".equals(recordType)) //$NON-NLS-1$ - addressSize = 3; - else if ("S0".equals(recordType) || "S5".equals(recordType) || "S7".equals(recordType) - || "S8".equals(recordType) || "S9".equals(recordType)) //$NON-NLS-1$ - { // ignore S0, S5, S7, S8 and S9 records - line = reader.readLine(); - lineNo++; - continue; - } - try { - recordAddress = new BigInteger(line.substring(position, position + addressSize * 2), 16); - } catch (NumberFormatException ex) { - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, - String.format(Messages.getString("SRecordImporter.InvalidAddress"), lineNo), ex); //$NON-NLS-1$ - } - recordCount -= addressSize; - position += addressSize * 2; - - if (offset == null) - offset = fStartAddress.subtract(recordAddress); - - recordAddress = recordAddress.add(offset); - - byte data[] = new byte[recordCount - CHECKSUM_LENGTH]; - for (int i = 0; i < data.length; i++) { - try { - data[i] = new BigInteger(line.substring(position++, position++ + 1), 16).byteValue(); - } catch (NumberFormatException ex) { - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, - String.format(Messages.getString("SRecordImporter.InvalidData"), lineNo), ex); //$NON-NLS-1$ - } - } - - /* - * The least significant byte of the one's complement of the sum of the values - * represented by the pairs of characters making up the records length, address, - * and the code/data fields. - */ - StringBuilder buf = new StringBuilder(line.substring(2)); - byte checksum = 0; - - for (int i = 0; i < buf.length(); i += 2) { - BigInteger value = null; - try { - value = new BigInteger(buf.substring(i, i + 2), 16); - } catch (NumberFormatException ex) { - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, - String.format(Messages.getString("SRecordImporter.InvalidChecksum"), lineNo), //$NON-NLS-1$ - ex); - } - checksum += value.byteValue(); - } - - /* - * Since we included the checksum in the checksum calculation the checksum - * ( if correct ) will always be 0xFF which is -1 using the signed byte size - * calculation here. - */ - if (checksum != (byte) -1) { - reader.close(); - monitor.done(); - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - Messages.getString("SRecordImporter.ChecksumFalure") + line); //$NON-NLS-1$ - } - - if (scrollToAddress == null) - scrollToAddress = recordAddress; - - // FIXME error on incorrect checksum - - memoryWriter.write( - recordAddress.subtract(((IMemoryBlockExtension) fMemoryBlock).getBigBaseAddress()), - data); - - BigInteger jobCount = BigInteger.valueOf(bytesRead).divide(factor); - monitor.worked(jobCount.intValue()); - - line = reader.readLine(); - lineNo++; - } - - if (!monitor.isCanceled()) - memoryWriter.flush(); - - reader.close(); - monitor.done(); - - if (fScrollToStart) - fParentDialog.scrollRenderings(scrollToAddress); - - } catch (IOException ex) { - MemoryTransportPlugin.getDefault().getLog() - .log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrReadFile"), ex)); //$NON-NLS-1$ - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrReadFile"), ex); //$NON-NLS-1$ - - } catch (DebugException ex) { - MemoryTransportPlugin.getDefault().getLog() - .log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrWriteTarget"), ex)); //$NON-NLS-1$ - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.REQUEST_FAILED, Messages.getString("Importer.ErrWriteTarget"), ex); //$NON-NLS-1$ - } catch (Exception ex) { - MemoryTransportPlugin.getDefault().getLog() - .log(new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.INTERNAL_ERROR, Messages.getString("Importer.FalureImporting"), ex)); //$NON-NLS-1$ - return new Status(IStatus.ERROR, MemoryTransportPlugin.getUniqueIdentifier(), - DebugException.INTERNAL_ERROR, Messages.getString("Importer.FalureImporting"), ex); //$NON-NLS-1$ - } - return Status.OK_STATUS; - } - }; - job.setUser(true); - job.schedule(); + try { + Consumer scroll = fScrollToStart ? new ScrollMemory(fParentDialog) : new ScrollMemory.Ignore(); + IMemoryBlockExtension block = (IMemoryBlockExtension) fMemoryBlock; + ImportRequest request = new ImportRequest(block.getBigBaseAddress(), fStartAddress, + new WriteMemoryBlock(block)); + SRecordImport memoryImport = new SRecordImport(fInputFile, request, scroll, + fProperties.getBoolean(TRANSFER_CUSTOM_START_ADDRESS)); + FileImportJob job = new FileImportJob(// + "Memory Import from S-Record File", memoryImport); + job.setUser(true); + job.schedule(); + } catch (DebugException e) { + //FIXME: unreachable with current implementation, to be i18n after UI rework + ErrorDialog.openError(fParentDialog.getShell(), // + "Import Failure", // + "Failed to retrieve base memory address", // + e.getStatus()); + } } } diff --git a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/messages.properties b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/messages.properties index dd3a4a22e37..bdfc8f870b7 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/messages.properties +++ b/memory/org.eclipse.cdt.debug.ui.memory.transport/src/org/eclipse/cdt/debug/ui/memory/transport/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2009, 2010 Wind River Systems and others. +# Copyright (c) 2009, 2020 Wind River Systems and others. # # This program and the accompanying materials # are made available under the terms of the Eclipse Public License 2.0 @@ -11,6 +11,7 @@ # Contributors: # Ted R Williams (Wind River) - initial API and implementation # Teodor Madan (Freescale) - +# Alexander Fedorov (ArSysOp) - headless part extraction ############################################################################### ExportMemoryDialog.Format=Format:\u0020 @@ -31,11 +32,8 @@ Exporter.ProgressTitle=Transferring Data Importer.AllFiles=All Files Importer.Browse=Browse... -Importer.ErrReadFile=Could not read from file. -Importer.ErrWriteTarget=Could not write to target. Importer.FalureImporting=Failure importing from file Importer.File=File name:\u0020 -Importer.ProgressTitle=Transferring Data PlainTextExporter.ChooseFile=Choose memory export file PlainTextExporter.EndAddress=End address:\u0020 @@ -44,7 +42,6 @@ PlainTextExporter.Name=Plain Text PlainTextExporter.StartAddress=Start address:\u0020 PlainTextImporter.ChooseFile=Choose memory import file -PlainTextImporter.ErrInvalidFormat=Invalid file format. Expected integer at line %d PlainTextImporter.Name=Plain Text PlainTextImporter.RestoreAddress=Restore to address:\u0020 PlainTextImporter.ScrollToStart=Scroll to restore address @@ -56,14 +53,9 @@ SRecordExporter.Name=SRecord SRecordExporter.StartAddress=Start address:\u0020 SRecordExporter.32BitLimitationMessage=SRecord format only supports 32-bit address spaces. -SRecordImporter.ChecksumFalure=Checksum failure of line =\u0020 SRecordImporter.ChooseFile=Choose memory import file SRecordImporter.CustomAddressRestore=Restore to this address:\u0020 SRecordImporter.FileAddressRestore=Restore to address specified in the file -SRecordImporter.InvalidAddress=Invalid file format. Invalid address at line %d -SRecordImporter.InvalidChecksum=Invalid file format. Invalid checksum format at line %d -SRecordImporter.InvalidData=Invalid file format. Invalid data at line %d -SRecordImporter.InvalidLineLength=Invalid file format. Invalid line length at line %d SRecordImporter.Name=SRecord SRecordImporter.ScrollToStart=Scroll to restore address SRecordImporter.32BitLimitationMessage=SRecord format only supports 32-bit address spaces.