From 3cbd8de918e6ca811526e9706980d2d518c02cd6 Mon Sep 17 00:00:00 2001 From: adamopolous Date: Wed, 27 Mar 2019 14:16:31 -0400 Subject: [PATCH 1/5] GT-2703: fixed intel hex export issue of dropping bytes on selection --- .../help/topics/ExporterPlugin/exporter.htm | 6 + .../images/Intel_Hex_Options.png | Bin 6240 -> 8014 bytes .../src/main/java/ghidra/app/util/Option.java | 9 + .../app/util/exporter/IntelHexExporter.java | 220 +++++++++++++++--- .../util/opinion/IntelHexRecordWriter.java | 23 +- 5 files changed, 225 insertions(+), 33 deletions(-) diff --git a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm index 27f1bb5d34..2166be79db 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm @@ -306,6 +306,12 @@
  • 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.
  • +
  • Force - 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 31e0df87d2f5b3292dece58a88777de556cd99ec..19ecef3db6d3da860dbce4b104958453a5478351 100644 GIT binary patch literal 8014 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 Tsxt7N{DHE(x?GKnW!V1$hx*SQ literal 6240 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 + * 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/IntelHexExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/IntelHexExporter.java index 29242fff3b..eaf04de5bc 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,10 +34,22 @@ 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 force a record size for every line + * of output, which will only print out lines that match the max record size; 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; /** * Constructs a new Intel Hex exporter. @@ -41,6 +58,13 @@ public class IntelHexExporter extends Exporter { this("Intel Hex", "hex", new HelpLocation("ExporterPlugin", "intel_hex")); } + /** + * 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 +79,150 @@ 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()); + + recordSizeOption = new RecordSizeOption("Record Size", Integer.class); + + optionsList.add(addressSpaceOption); + optionsList.add(recordSizeOption); - optionsList.add(option); return optionsList; } @Override public void setOptions(List

      + *
    • input: a {@link HintTextField} for entering numeric digits; these + * represent the record size for each line of output
    • + *
    • forceCb: a {@link JCheckBox} for specifying the force setting; this + * enforces that every line in the output matches the specified record size
    • + *
    + * + * Note: If the force option is set, any bytes that are left over after outputting + * all lines that match the record size will be dropped on the floor. + */ + private class RecordSizeComponent extends JPanel { + + private HintTextField input; + private JCheckBox forceCb; + + public RecordSizeComponent(int recordSize) { + setLayout(new BorderLayout()); + + input = new HintTextField(String.valueOf(recordSize), false, new BoundedIntegerVerifier()); + forceCb = new JCheckBox("force"); + + input.setText(String.valueOf(recordSize)); + + add(input, BorderLayout.CENTER); + add(forceCb, BorderLayout.EAST); + } + + public int getValue() { + String val = input.getText(); + if (!input.isFieldValid()) { + return 0x10; + } + + return Integer.valueOf(val); + } + + public boolean getForce() { + return forceCb.isSelected(); + } + } + + /** + * Verifier for a {@link HintTextField} that ensures input is a numeric value between + * 0 and 0xFF. + *

    + * Input may be specified in either decimal or hex. + */ + private class BoundedIntegerVerifier extends InputVerifier { + + @Override + public boolean verify(JComponent input) { + HintTextField field = (HintTextField) input; + String text = field.getText(); + + // Strip off any leading "0x" chars if the user has put them there - the + // parseInt method can't handle them. + if (text.startsWith("0x")) { + text = text.substring(2); + } + + // Now try and parse the input; first as hex, then as decimal. + Integer val; + try { + val = Integer.parseInt(text, 16); + } + catch (NumberFormatException e) { + try { + val = Integer.parseInt(text); + } + catch (NumberFormatException e1) { + return false; + } + } + + return val <= 0xFF && val >= 0; } } @@ -84,33 +242,31 @@ public class IntelHexExporter extends Exporter { return false; } - if (option == null) { + if (addressSpaceOption == null || recordSizeOption == null) { getOptions(() -> program); } - PrintWriter writer = new PrintWriter(new FileOutputStream(file)); + try (PrintWriter writer = new PrintWriter(new FileOutputStream(file))) { - Memory memory = program.getMemory(); + Memory memory = program.getMemory(); - if (addrSet == null) { - addrSet = memory; - } - - try { - List records = dumpMemory(program, memory, addrSet, monitor); - for (IntelHexRecord record : records) { - writer.println(record.format()); + if (addrSet == null) { + addrSet = memory; } - } - catch (MemoryAccessException e) { - throw new ExporterException(e); - } - finally { - // Close the PrintWriter - // - writer.close(); - option = null; + try { + List records = dumpMemory(program, memory, addrSet, monitor); + for (IntelHexRecord record : records) { + writer.println(record.format()); + } + } + catch (MemoryAccessException e) { + throw new ExporterException(e); + } + finally { + addressSpaceOption = null; + recordSizeOption = null; + } } return true; @@ -118,15 +274,19 @@ public class IntelHexExporter extends Exporter { protected List dumpMemory(Program program, Memory memory, AddressSetView addrSetView, TaskMonitor monitor) throws MemoryAccessException { - IntelHexRecordWriter writer = new IntelHexRecordWriter(MAX_BYTES_PER_LINE); + + int size = (int) recordSizeOption.getValue(); + boolean forceSize = recordSizeOption.getForce(); + + IntelHexRecordWriter writer = new IntelHexRecordWriter(size, forceSize); AddressSet set = new AddressSet(addrSetView); MemoryBlock[] blocks = memory.getBlocks(); - for (int i = 0; i < blocks.length; ++i) { - if (!blocks[i].isInitialized() || - blocks[i].getStart().getAddressSpace() != option.getValue()) { - set.delete(new AddressRangeImpl(blocks[i].getStart(), blocks[i].getEnd())); + for (MemoryBlock block : blocks) { + if (!block.isInitialized() || + block.getStart().getAddressSpace() != addressSpaceOption.getValue()) { + set.delete(new AddressRangeImpl(block.getStart(), block.getEnd())); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java index 623417a12a..471842790e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java @@ -20,21 +20,31 @@ import java.util.*; import ghidra.program.model.address.*; public class IntelHexRecordWriter { + private final int maxBytesPerLine; + private final boolean forceSize; private Address startAddress = null; private Long oldSegment = null; - private ArrayList bytes = new ArrayList(); + private ArrayList bytes = new ArrayList<>(); private Boolean isSegmented = null; - private ArrayList results = new ArrayList(); + private ArrayList results = new ArrayList<>(); private boolean done = false; - public IntelHexRecordWriter(int maxBytesPerLine) { + /** + * Constructor + * + * @param maxBytesPerLine the maximum number of bytes to write per line in the hex output + * @param forceSize if true, only lines matching {@link #maxBytesPerLine} will be output; + * remaining bytes will be left out + */ + public IntelHexRecordWriter(int maxBytesPerLine, boolean forceSize) { if (maxBytesPerLine > IntelHexRecord.MAX_RECORD_LENGTH) { throw new IllegalArgumentException("maxBytesPerLine > IntelHexRecord.MAX_RECORD_LENGTH"); } this.maxBytesPerLine = maxBytesPerLine; + this.forceSize = forceSize; } public void addByte(Address address, byte b) { @@ -117,6 +127,13 @@ public class IntelHexRecordWriter { } public List finish(Address entryPoint) { + + // Before finalizing things, write out any remaining bytes that haven't yet been written, if + // the user has specified to do so via the force option (false = write out everything). + if (bytes.size() > 0 && !forceSize) { + emitData(); + } + if (entryPoint != null && isSegmented != null) { final long offset = entryPoint.getOffset(); byte[] data = new byte[4]; From 6fad64426a5c9ec8b71c7c6d718859a24ff9e1a6 Mon Sep 17 00:00:00 2001 From: adamopolous Date: Thu, 28 Mar 2019 07:34:36 -0400 Subject: [PATCH 2/5] GT-2703: changed "force" option to "drop extra bytes" in intel hex options --- .../help/topics/ExporterPlugin/exporter.htm | 2 +- .../images/Intel_Hex_Options.png | Bin 8014 -> 8778 bytes .../app/util/exporter/IntelHexExporter.java | 34 +++++++++--------- .../util/opinion/IntelHexRecordWriter.java | 13 +++---- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm index 2166be79db..7cc81d3288 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm @@ -308,7 +308,7 @@ address space.

  • Record Size - Specifies the size (in bytes) of each record in the output file. The default 16.
  • -
  • Force - If checked, this will ensure that only records matching +
  • Drop Extra Bytes - 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 19ecef3db6d3da860dbce4b104958453a5478351..8d6087886acedf6d1c98098ddf1be9ed6fc490f3 100644 GIT binary patch literal 8778 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 Tsxt7N{DHE(x?GKnW!V1$hx*SQ 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 eaf04de5bc..7b86e60c4d 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 @@ -39,8 +39,8 @@ import ghidra.util.task.TaskMonitor; *

    * 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 force a record size for every line - * of output, which will only print out lines that match the max record size; any other + * 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 { @@ -100,8 +100,8 @@ public class IntelHexExporter extends Exporter { /** * Option for exporting Intel Hex records that allows users to specify a record size for the - * output. Users may also optionally specify a force option that will only output - * lines that match this maximum size. + * output. Users may also optionally select the Drop Extra Bytes option that + * will cause only those records that match the maximum size to be output to the file. * * @see RecordSizeComponent */ @@ -140,8 +140,8 @@ public class IntelHexExporter extends Exporter { return Integer.class; } - public boolean getForce() { - return comp.getForce(); + public boolean dropExtraBytes() { + return comp.dropExtraBytes(); } } @@ -151,28 +151,28 @@ public class IntelHexExporter extends Exporter { *

      *
    • input: a {@link HintTextField} for entering numeric digits; these * represent the record size for each line of output
    • - *
    • forceCb: a {@link JCheckBox} for specifying the force setting; this - * enforces that every line in the output matches the specified record size
    • + *
    • dropCb: a {@link JCheckBox} for specifying a setting that enforces that every line in + * the output matches the specified record size
    • *
    * - * Note: If the force option is set, any bytes that are left over after outputting - * all lines that match the record size will be dropped on the floor. + * Note: If the Drop Extra Bytes option is set, any bytes that are left over + * after outputting all lines that match the record size will be omitted from the output. */ private class RecordSizeComponent extends JPanel { private HintTextField input; - private JCheckBox forceCb; + private JCheckBox dropCb; public RecordSizeComponent(int recordSize) { setLayout(new BorderLayout()); input = new HintTextField(String.valueOf(recordSize), false, new BoundedIntegerVerifier()); - forceCb = new JCheckBox("force"); + dropCb = new JCheckBox("Drop Extra Bytes"); input.setText(String.valueOf(recordSize)); add(input, BorderLayout.CENTER); - add(forceCb, BorderLayout.EAST); + add(dropCb, BorderLayout.EAST); } public int getValue() { @@ -184,8 +184,8 @@ public class IntelHexExporter extends Exporter { return Integer.valueOf(val); } - public boolean getForce() { - return forceCb.isSelected(); + public boolean dropExtraBytes() { + return dropCb.isSelected(); } } @@ -276,9 +276,9 @@ public class IntelHexExporter extends Exporter { AddressSetView addrSetView, TaskMonitor monitor) throws MemoryAccessException { int size = (int) recordSizeOption.getValue(); - boolean forceSize = recordSizeOption.getForce(); + boolean dropBytes = recordSizeOption.dropExtraBytes(); - IntelHexRecordWriter writer = new IntelHexRecordWriter(size, forceSize); + IntelHexRecordWriter writer = new IntelHexRecordWriter(size, dropBytes); AddressSet set = new AddressSet(addrSetView); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java index 471842790e..16d21698c1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/IntelHexRecordWriter.java @@ -22,7 +22,7 @@ import ghidra.program.model.address.*; public class IntelHexRecordWriter { private final int maxBytesPerLine; - private final boolean forceSize; + private final boolean dropExtraBytes; private Address startAddress = null; private Long oldSegment = null; @@ -36,15 +36,15 @@ public class IntelHexRecordWriter { * Constructor * * @param maxBytesPerLine the maximum number of bytes to write per line in the hex output - * @param forceSize if true, only lines matching {@link #maxBytesPerLine} will be output; + * @param dropExtraBytes if true, only lines matching {@link #maxBytesPerLine} will be output; * remaining bytes will be left out */ - public IntelHexRecordWriter(int maxBytesPerLine, boolean forceSize) { + public IntelHexRecordWriter(int maxBytesPerLine, boolean dropExtraBytes) { if (maxBytesPerLine > IntelHexRecord.MAX_RECORD_LENGTH) { throw new IllegalArgumentException("maxBytesPerLine > IntelHexRecord.MAX_RECORD_LENGTH"); } this.maxBytesPerLine = maxBytesPerLine; - this.forceSize = forceSize; + this.dropExtraBytes = dropExtraBytes; } public void addByte(Address address, byte b) { @@ -129,8 +129,9 @@ public class IntelHexRecordWriter { public List finish(Address entryPoint) { // Before finalizing things, write out any remaining bytes that haven't yet been written, if - // the user has specified to do so via the force option (false = write out everything). - if (bytes.size() > 0 && !forceSize) { + // the user has specified to do so via the drop extra bytes option (false = + // write out everything). + if (bytes.size() > 0 && !dropExtraBytes) { emitData(); } From 7caa7e369bf77df272a92a74a559167bb70a46db Mon Sep 17 00:00:00 2001 From: adamopolous Date: Thu, 28 Mar 2019 14:46:21 -0400 Subject: [PATCH 3/5] GT-2703: fixes from code review --- .../ghidra/app/util/exporter/Compare.java | 9 +- .../app/util/exporter/IntelHexExporter.java | 248 ++++++++++-------- 2 files changed, 140 insertions(+), 117 deletions(-) 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 7b86e60c4d..5418555a92 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 @@ -50,14 +50,32 @@ public class IntelHexExporter extends Exporter { /** 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 * @@ -82,7 +100,9 @@ public class IntelHexExporter extends Exporter { addressSpaceOption = new Option("Address Space", program.getAddressFactory().getDefaultAddressSpace()); - recordSizeOption = new RecordSizeOption("Record Size", Integer.class); + if (recordSizeOption == null) { + recordSizeOption = new RecordSizeOption("Record Size", Integer.class); + } optionsList.add(addressSpaceOption); optionsList.add(recordSizeOption); @@ -97,98 +117,7 @@ public class IntelHexExporter extends Exporter { recordSizeOption = (RecordSizeOption) options.get(1); } } - - /** - * Option for exporting Intel Hex records that allows users to specify a record size for the - * output. Users may also optionally select the Drop Extra Bytes option that - * will cause only those records that match the maximum size to be output to the file. - * - * @see RecordSizeComponent - */ - private class RecordSizeOption extends Option { - - // Initialize the record size to 16 bytes when showing the option. - private final RecordSizeComponent comp = new RecordSizeComponent(16); - - public RecordSizeOption(String name, Class valueClass) { - super(name, valueClass); - } - - public RecordSizeOption(String name, Class valueClass, Object value, String arg, - String group) { - super(name, valueClass, value, arg, group); - } - - @Override - public Component getCustomEditorComponent() { - return comp; - } - - @Override - public Option copy() { - return new RecordSizeOption(getName(), getValueClass(), getValue(), getArg(), - getGroup()); - } - - @Override - public Object getValue() { - return comp.getValue(); - } - - @Override - public Class getValueClass() { - return Integer.class; - } - - public boolean dropExtraBytes() { - return comp.dropExtraBytes(); - } - } - - /** - * Component that displays two widgets for setting export options: - * - *
      - *
    • input: a {@link HintTextField} for entering numeric digits; these - * represent the record size for each line of output
    • - *
    • dropCb: a {@link JCheckBox} for specifying a setting that enforces that every line in - * the output matches the specified record size
    • - *
    - * - * Note: If the Drop Extra Bytes option is set, any bytes that are left over - * after outputting all lines that match the record size will be omitted from the output. - */ - private class RecordSizeComponent extends JPanel { - - private HintTextField input; - private JCheckBox dropCb; - - public RecordSizeComponent(int recordSize) { - setLayout(new BorderLayout()); - - input = new HintTextField(String.valueOf(recordSize), false, new BoundedIntegerVerifier()); - dropCb = new JCheckBox("Drop Extra Bytes"); - - input.setText(String.valueOf(recordSize)); - - add(input, BorderLayout.CENTER); - add(dropCb, BorderLayout.EAST); - } - - public int getValue() { - String val = input.getText(); - if (!input.isFieldValid()) { - return 0x10; - } - - return Integer.valueOf(val); - } - - public boolean dropExtraBytes() { - return dropCb.isSelected(); - } - } - + /** * Verifier for a {@link HintTextField} that ensures input is a numeric value between * 0 and 0xFF. @@ -202,24 +131,12 @@ public class IntelHexExporter extends Exporter { HintTextField field = (HintTextField) input; String text = field.getText(); - // Strip off any leading "0x" chars if the user has put them there - the - // parseInt method can't handle them. - if (text.startsWith("0x")) { - text = text.substring(2); - } - - // Now try and parse the input; first as hex, then as decimal. - Integer val; + int val; try { - val = Integer.parseInt(text, 16); + val = Integer.decode(text); } catch (NumberFormatException e) { - try { - val = Integer.parseInt(text); - } - catch (NumberFormatException e1) { - return false; - } + return false; } return val <= 0xFF && val >= 0; @@ -308,4 +225,113 @@ public class IntelHexExporter extends Exporter { } return writer.finish(entryPoint); } + + /** + * Option for exporting Intel Hex records that allows users to specify a record size for the + * output. Users may also optionally select the Drop Extra Bytes option that + * will cause only those records that match the maximum size to be output to the file. + * + * @see RecordSizeComponent + */ + private class RecordSizeOption extends Option { + + private final RecordSizeComponent comp = new RecordSizeComponent(DEFAULT_RECORD_SIZE); + + public RecordSizeOption(String name, Class valueClass) { + super(name, valueClass); + } + + public RecordSizeOption(String name, Class valueClass, Object value, String arg, + String group) { + super(name, valueClass, value, arg, group); + } + + @Override + public Component getCustomEditorComponent() { + return comp; + } + + @Override + public Option copy() { + return new RecordSizeOption(getName(), getValueClass(), getValue(), getArg(), + getGroup()); + } + + @Override + public Object getValue() { + return comp.getValue(); + } + + @Override + public Class getValueClass() { + return Integer.class; + } + + public boolean dropExtraBytes() { + return comp.dropExtraBytes(); + } + + public void setRecordSize(int recordSize) { + comp.setRecordSize(recordSize); + } + + public void setDropBytes(boolean dropBytes) { + comp.setDropBytes(dropBytes); + } + } + + /** + * Component that displays two widgets for setting export options: + * + *
      + *
    • input: a {@link HintTextField} for entering numeric digits; these + * represent the record size for each line of output
    • + *
    • dropCb: a {@link JCheckBox} for specifying a setting that enforces that every line in + * the output matches the specified record size
    • + *
    + * + * Note: If the Drop Extra Bytes option is set, any bytes that are left over + * after outputting all lines that match the record size will be omitted from the output. + */ + private class RecordSizeComponent extends JPanel { + + private HintTextField input; + private JCheckBox dropCb; + + public RecordSizeComponent(int recordSize) { + setLayout(new BorderLayout()); + + input = new HintTextField(Integer.toString(recordSize), false, new BoundedIntegerVerifier()); + dropCb = new JCheckBox("Drop Extra Bytes"); + + input.setText(Integer.toString(recordSize)); + + add(input, BorderLayout.CENTER); + add(dropCb, BorderLayout.EAST); + } + + public int getValue() { + String val = input.getText(); + if (!input.isFieldValid()) { + + // If the user clears the input field, revert to the default + // record size (16). + return DEFAULT_RECORD_SIZE; + } + + return Integer.valueOf(val); + } + + public boolean dropExtraBytes() { + return dropCb.isSelected(); + } + + public void setRecordSize(int recordSize) { + input.setText(Integer.toString(recordSize)); + } + + public void setDropBytes(boolean dropBytes) { + dropCb.setSelected(dropBytes); + } + } } From a3121e19a442250f40692a2bf12d62b005d2c37b Mon Sep 17 00:00:00 2001 From: adamopolous Date: Tue, 2 Apr 2019 10:40:08 -0400 Subject: [PATCH 4/5] GT-2703: changed label on intel hex option to be intelligible --- .../Base/src/main/help/help/topics/ExporterPlugin/exporter.htm | 2 +- .../main/java/ghidra/app/util/exporter/IntelHexExporter.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm index 7cc81d3288..3c35967519 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/ExporterPlugin/exporter.htm @@ -308,7 +308,7 @@ address space.
  • Record Size - Specifies the size (in bytes) of each record in the output file. The default 16.
  • -
  • Drop Extra Bytes - If checked, this will ensure that only records matching +
  • 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/java/ghidra/app/util/exporter/IntelHexExporter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/exporter/IntelHexExporter.java index 5418555a92..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 @@ -302,7 +302,7 @@ public class IntelHexExporter extends Exporter { setLayout(new BorderLayout()); input = new HintTextField(Integer.toString(recordSize), false, new BoundedIntegerVerifier()); - dropCb = new JCheckBox("Drop Extra Bytes"); + dropCb = new JCheckBox("Align To Record Size"); input.setText(Integer.toString(recordSize)); From b874111ae730f9f78566f222a945399dcd5997eb Mon Sep 17 00:00:00 2001 From: adamopolous Date: Tue, 2 Apr 2019 11:13:27 -0400 Subject: [PATCH 5/5] GT-2703: added new help image for intel hex options dialog --- .../images/Intel_Hex_Options.png | Bin 8778 -> 7427 bytes 1 file changed, 0 insertions(+), 0 deletions(-) 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 8d6087886acedf6d1c98098ddf1be9ed6fc490f3..614e2f37d3b9ae85cf56a7b66cac79c00fc84373 100644 GIT binary patch literal 7427 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 literal 8778 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