Address Space - Specifies which address space to export as Intel Hex format
only supports one address space. This option will be intialized to the "default"
address space.
+
Record Size - Specifies the size (in bytes) of each record in the
+ output file. The default 16.
+
Align To Record Size - If checked, this will ensure that only records matching
+ the record size will be output. eg: if you set the record size to 16 but there are
+ 18 bytes selected, you will see only one line of 16 bytes in the output; the remaining
+ 2 bytes will be dropped.
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/images/Intel_Hex_Options.png b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/images/Intel_Hex_Options.png
index 31e0df87d2..614e2f37d3 100644
Binary files a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/images/Intel_Hex_Options.png and b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/images/Intel_Hex_Options.png differ
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/Option.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/Option.java
index afe63dcd5f..e5262f5181 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/Option.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/Option.java
@@ -96,6 +96,15 @@ public class Option {
this.listener = listener;
}
+ /**
+ * Override if you want to provide a custom widget for selecting your
+ * options.
+ *
+ * Important! If you override this you MUST also override the {@link #copy()}
+ * method so it returns a new instance of your custom editor.
+ *
+ * @return the custom editor
+ */
public Component getCustomEditorComponent() {
return null;
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Compare.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Compare.java
index 58ba286399..4b2fb28cb5 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Compare.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/Compare.java
@@ -25,17 +25,17 @@ import ghidra.util.Msg;
public class Compare {
public static void compare(ArrayList expectedList, File actualFile) throws Exception {
int index = 0;
- BufferedReader reader = new BufferedReader(new FileReader(actualFile));
-
+
boolean hasFailure = false;
- try {
+ try (BufferedReader reader = new BufferedReader(new FileReader(actualFile))) {
int excess = 0;
while (true) {
String actualLine = reader.readLine();
if (actualLine == null) {
break;
}
+
if (index >= expectedList.size()) {
++excess;
continue;
@@ -73,8 +73,5 @@ public class Compare {
Assert.fail("One or more failures--see output for data");
}
}
- finally {
- reader.close();
- }
}
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/IntelHexExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/IntelHexExporter.java
index 29242fff3b..47ba38d9ef 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/IntelHexExporter.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/IntelHexExporter.java
@@ -15,10 +15,15 @@
*/
package ghidra.app.util.exporter;
+import java.awt.BorderLayout;
+import java.awt.Component;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
+import javax.swing.*;
+
+import docking.widgets.textfield.HintTextField;
import ghidra.app.util.*;
import ghidra.app.util.opinion.IntelHexRecord;
import ghidra.app.util.opinion.IntelHexRecordWriter;
@@ -29,18 +34,55 @@ import ghidra.program.model.mem.*;
import ghidra.util.HelpLocation;
import ghidra.util.task.TaskMonitor;
+/**
+ * Exports the current program (or program selection) as bytes in Intel Hex format.
+ *
+ * The output defaults to lines of 16-bytes but this is configurable using the
+ * {@link #recordSizeOption} attribute. This allows users to select any record size
+ * up to the max of 0xFF. Users may also choose to Drop Extra Bytes, which will
+ * cause only lines that match the max record size to be printed; any other
+ * bytes will be dropped. If this option is not set, every byte will be represented in the output.
+ */
public class IntelHexExporter extends Exporter {
- protected final static int MAX_BYTES_PER_LINE = 0x00000010;
-
- protected Option option;
+ /** Option allowing the user to select the address space */
+ protected Option addressSpaceOption;
+
+ /** Option allowing the user to select the number of bytes in each line of output */
+ protected RecordSizeOption recordSizeOption;
+
+ private static final int DEFAULT_RECORD_SIZE = 0x10;
+
/**
- * Constructs a new Intel Hex exporter.
+ * Constructs a new Intel Hex exporter. This will use a record size of 16 (the default)
+ * and will export ALL bytes in the program or selection (even if the total length
+ * is not a multiple of 16.
*/
public IntelHexExporter() {
this("Intel Hex", "hex", new HelpLocation("ExporterPlugin", "intel_hex"));
}
-
+
+ /**
+ * Constructs a new Intel Hex exporter with a custom record size.
+ *
+ * @param recordSize the record size to use when writing to the output file
+ * @param dropBytes if true, bytes at the end of the file that don't match the specified
+ * record size will be dropped
+ */
+ public IntelHexExporter(int recordSize, boolean dropBytes) {
+ this("Intel Hex", "hex", new HelpLocation("ExporterPlugin", "intel_hex"));
+ recordSizeOption = new RecordSizeOption("Record Size", Integer.class);
+ recordSizeOption.setRecordSize(recordSize);
+ recordSizeOption.setDropBytes(dropBytes);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name the name of the exporter
+ * @param extension the extension to use for the output file
+ * @param help location of Ghidra help
+ */
protected IntelHexExporter(String name, String extension, HelpLocation help) {
super(name, extension, help);
}
@@ -55,16 +97,49 @@ public class IntelHexExporter extends Exporter {
}
Program program = (Program) domainObject;
- option = new Option("Address Space", program.getAddressFactory().getDefaultAddressSpace());
+ addressSpaceOption =
+ new Option("Address Space", program.getAddressFactory().getDefaultAddressSpace());
+
+ if (recordSizeOption == null) {
+ recordSizeOption = new RecordSizeOption("Record Size", Integer.class);
+ }
+
+ optionsList.add(addressSpaceOption);
+ optionsList.add(recordSizeOption);
- optionsList.add(option);
return optionsList;
}
@Override
public void setOptions(List