index
.
+ * Returns the signed LONG at index
.
* @param index the index where the LONG begins
* @return the LONG
* @exception IOException if an I/O error occurs
@@ -674,6 +669,34 @@ public class BinaryReader {
return converter.getLong(bytes);
}
+ /**
+ * Returns the signed value of the integer (of the specified length) at the specified offset.
+ *
+ * @param index offset the offset from the membuffers origin (the address that it is set at)
+ * @param len the number of bytes that the integer occupies. Valid values are 1 (byte), 2 (short),
+ * 4 (int), 8 (long)
+ * @return value of requested length, with sign bit extended, in a long
+ * @throws IOException
+ */
+ public long readValue(long index, int len) throws IOException {
+ byte[] bytes = provider.readBytes(index, len);
+ return converter.getSignedValue(bytes, len);
+ }
+
+ /**
+ * Returns the unsigned value of the integer (of the specified length) at the specified offset.
+ *
+ * @param index offset the offset from the membuffers origin (the address that it is set at)
+ * @param len the number of bytes that the integer occupies. Valid values are 1 (byte), 2 (short),
+ * 4 (int), 8 (long)
+ * @return unsigned value of requested length, in a long
+ * @throws IOException
+ */
+ public long readUnsignedValue(long index, int len) throws IOException {
+ byte[] bytes = provider.readBytes(index, len);
+ return converter.getValue(bytes, len);
+ }
+
/**
* Returns the BYTE array of nElements
* starting at index
.
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractClassicProcessor.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractClassicProcessor.java
index 1eef5e3272..ea7547f437 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractClassicProcessor.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractClassicProcessor.java
@@ -58,8 +58,7 @@ public abstract class AbstractClassicProcessor {
Address address = defaultAddressSpace.getAddress(addressValue);
- DataConverter converter =
- language.isBigEndian() ? new BigEndianDataConverter() : new LittleEndianDataConverter();
+ DataConverter converter = DataConverter.getInstance(language.isBigEndian());
Symbol symbol = getSymbol(nList);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractDyldInfoState.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractDyldInfoState.java
index 924f3bc94c..633a718779 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractDyldInfoState.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/macho/commands/dyld/AbstractDyldInfoState.java
@@ -58,8 +58,7 @@ abstract public class AbstractDyldInfoState {
long offset = symbol.getAddress().getOffset();
- DataConverter converter = program.getLanguage().isBigEndian() ? new BigEndianDataConverter()
- : new LittleEndianDataConverter();
+ DataConverter converter = DataConverter.getInstance(program.getLanguage().isBigEndian());
byte[] bytes = (program.getDefaultPointerSize() == 8) ? converter.getBytes(offset)
: converter.getBytes((int) offset);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImportDataDirectory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImportDataDirectory.java
index 2499be4385..5eb36e9e0e 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImportDataDirectory.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/ImportDataDirectory.java
@@ -40,7 +40,7 @@ public class ImportDataDirectory extends DataDirectory {
private ImportInfo[] imports;
ExportDataDirectory exportDirectory;
- DataConverter conv = new LittleEndianDataConverter();
+ DataConverter conv = LittleEndianDataConverter.INSTANCE;
static ImportDataDirectory createImportDataDirectory(NTHeader ntHeader,
FactoryBundledWithBinaryReader reader) throws IOException {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GUID.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GUID.java
index e31b9afae8..0d7d073536 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GUID.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GUID.java
@@ -167,10 +167,7 @@ public class GUID {
}
private DataConverter getDataConverter(MemBuffer buf) {
- if (buf.isBigEndian()) {
- return new BigEndianDataConverter();
- }
- return new LittleEndianDataConverter();
+ return DataConverter.getInstance(buf.isBigEndian());
}
@Override
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GuidDataType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GuidDataType.java
index b76cf818f4..45dc99d0dd 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GuidDataType.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GuidDataType.java
@@ -110,9 +110,7 @@ public class GuidDataType extends BuiltIn {
long[] data = new long[4];
boolean isBigEndian = ENDIAN.isBigEndian(settings, buf);
- DataConverter conv =
- isBigEndian ? (DataConverter) new BigEndianDataConverter()
- : (DataConverter) new LittleEndianDataConverter();
+ DataConverter conv = DataConverter.getInstance(isBigEndian);
if (buf.getBytes(bytes, 0) != bytes.length) {
if (guidName != null) {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GuidUtil.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GuidUtil.java
index 3f409c6f06..e4ca174231 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GuidUtil.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/datatype/microsoft/GuidUtil.java
@@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
- * REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -211,9 +210,7 @@ public class GuidUtil {
byte[] bytes = new byte[16];
long[] data = new long[4];
boolean isBigEndian = program.getMemory().isBigEndian();
- DataConverter conv =
- isBigEndian ? (DataConverter) new BigEndianDataConverter()
- : (DataConverter) new LittleEndianDataConverter();
+ DataConverter conv = DataConverter.getInstance(isBigEndian);
try {
program.getMemory().getBytes(address, bytes);
@@ -254,9 +251,7 @@ public class GuidUtil {
long[] data = new long[4];
int[] versionData = new int[2];
boolean isBigEndian = program.getMemory().isBigEndian();
- DataConverter conv =
- isBigEndian ? (DataConverter) new BigEndianDataConverter()
- : (DataConverter) new LittleEndianDataConverter();
+ DataConverter conv = DataConverter.getInstance(isBigEndian);
try {
program.getMemory().getBytes(address, bytes);
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java
index 5f24f6c3e2..c28e63056a 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoLoader.java
@@ -53,7 +53,7 @@ public class MachoLoader extends AbstractLibrarySupportLoader {
// Efficient check to fail fast
byte[] magicBytes = provider.readBytes(0, 4);
- if (!MachConstants.isMagic(new LittleEndianDataConverter().getInt(magicBytes))) {
+ if (!MachConstants.isMagic(LittleEndianDataConverter.INSTANCE.getInt(magicBytes))) {
return loadSpecs;
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java
index b7352b15e6..85e3398b8b 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MachoProgramBuilder.java
@@ -1385,8 +1385,7 @@ public class MachoProgramBuilder {
}
private DataConverter getDataConverter() {
- DataConverter dc = program.getLanguage().isBigEndian() ? new BigEndianDataConverter()
- : new LittleEndianDataConverter();
+ DataConverter dc = DataConverter.getInstance(program.getLanguage().isBigEndian());
return dc;
}
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MzLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MzLoader.java
index b7d1c29bcc..c0bbad1a86 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MzLoader.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MzLoader.java
@@ -52,7 +52,7 @@ public class MzLoader extends AbstractLibrarySupportLoader {
private final static byte MOVW_DS_OPCODE = (byte) 0xba;
private static final long MIN_BYTE_LENGTH = 4;
- private DataConverter converter = new LittleEndianDataConverter();
+ private DataConverter converter = LittleEndianDataConverter.INSTANCE;
@Override
public int getTierPriority() {
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/OmfLoader.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/OmfLoader.java
index 25ab45d399..1d2a0f7cc8 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/OmfLoader.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/OmfLoader.java
@@ -33,7 +33,7 @@ import ghidra.program.model.listing.*;
import ghidra.program.model.mem.*;
import ghidra.program.model.symbol.*;
import ghidra.program.model.util.CodeUnitInsertionException;
-import ghidra.util.*;
+import ghidra.util.DataConverter;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.task.TaskMonitor;
@@ -180,13 +180,7 @@ public class OmfLoader extends AbstractLibrarySupportLoader {
ArrayList* */ public interface DataConverter extends Serializable { + /** + * Returns the correct DataConverter static instance for the requested endian-ness. + * + * @param isBigEndian boolean flag, true means big endian + * @return static DataConverter instance + */ public static DataConverter getInstance(boolean isBigEndian) { return isBigEndian ? BigEndianDataConverter.INSTANCE : LittleEndianDataConverter.INSTANCE; } /** - * Get the short value from the given byte array. - * @param b array containing bytes - * @throws IndexOutOfBoundsException if byte array size is - * less than 2. + * Returns the endianess of this DataConverter instance. + * + * @return boolean flag, true means big-endian */ - public short getShort(byte[] b); + default boolean isBigEndian() { + return this instanceof BigEndianDataConverter; + } /** * Get the short value from the given byte array. * @param b array containing bytes + * @return signed short value from the beginning of the specified array + * @throws IndexOutOfBoundsException if byte array size is less than 2. + */ + default short getShort(byte[] b) { + return getShort(b, 0); + } + + /** + * Get the short value from the given byte array. + * + * @param b array containing bytes * @param offset offset into byte array for getting the short - * @throws IndexOutOfBoundsException if byte array size is - * less than offset+2. + * @return signed short value + * @throws IndexOutOfBoundsException if byte array size is less than offset+2 */ - public short getShort(byte[] b, int offset); + short getShort(byte[] b, int offset); /** * Get the int value from the given byte array. + * * @param b array containing bytes - * @throws IndexOutOfBoundsException if byte array size is - * less than 4. + * @return signed int value from the beginning of the specified array + * @throws IndexOutOfBoundsException if byte array size is less than 4 */ - public int getInt(byte[] b); + default int getInt(byte[] b) { + return getInt(b, 0); + } /** * Get the int value from the given byte array. + * * @param b array containing bytes * @param offset offset into byte array for getting the int - * @throws IndexOutOfBoundsException if byte array size is - * less than offset+4. + * @return signed int value + * @throws IndexOutOfBoundsException if byte array size is less than offset+4 */ - public int getInt(byte[] b, int offset); + int getInt(byte[] b, int offset); /** * Get the long value from the given byte array. + * * @param b array containing bytes - * @throws IndexOutOfBoundsException if byte array size is - * less than 8. + * @return signed long value from the beginning of the specified array + * @throws IndexOutOfBoundsException if byte array size is less than 8 */ - public long getLong(byte[] b); + default long getLong(byte[] b) { + return getLong(b, 0); + } /** * Get the long value from the given byte array. + * * @param b array containing bytes * @param offset offset into byte array for getting the long - * @throws IndexOutOfBoundsException if byte array size is - * less than offset+8. + * @return signed long value + * @throws IndexOutOfBoundsException if byte array size is less than offset+8 */ - public long getLong(byte[] b, int offset); + long getLong(byte[] b, int offset); + + /** + * Get the unsigned value from the given byte array using the specified + * integer size, returned as a long. + *
+ * Values with a size less than sizeof(long) will not have their sign bit + * extended and therefore will appear as an 'unsigned' value. + *
+ * Casting the 'unsigned' long value to the correctly sized smaller + * java primitive will cause the value to appear as a signed value. + *
+ * Values of size 8 (ie. longs) will be signed. + * + * @param b array containing bytes + * @param size number of bytes (1 - 8) to use from array at offset 0 + * @return unsigned value from the beginning of the specified array + * @throws IndexOutOfBoundsException if byte array size is less than specified size + */ + default long getValue(byte[] b, int size) { + return getValue(b, 0, size); + } + + /** + * Get the unsigned value from the given byte array using the specified + * integer size, returned as a long. + *
+ * Values with a size less than sizeof(long) will not have their sign bit + * extended and therefore will appear as an 'unsigned' value. + *
+ * Casting the 'unsigned' long value to the correctly sized smaller + * java primitive will cause the value to appear as a signed value. + *
+ * Values of size 8 (ie. longs) will be signed. + * + * @param b array containing bytes + * @param size number of bytes (1 - 8) to use from array + * @param offset offset into byte array for getting the long + * @return unsigned value + * @throws IndexOutOfBoundsException if byte array size is + * less than offset+size or size is greater than 8 (sizeof long) + */ + long getValue(byte[] b, int offset, int size); + + /** + * Get the signed value from the given byte array using the specified + * integer size, returned as a long. + *
+ * Values with a size less than sizeof(long) will have their sign bit + * extended. + * + * @param b array containing bytes + * @param size number of bytes (1 - 8) to use from array at offset 0 + * @return signed value from the beginning of the specified array + * @throws IndexOutOfBoundsException if byte array size is less than specified size + */ + default long getSignedValue(byte[] b, int size) { + return getSignedValue(b, 0, size); + } + + /** + * Get the signed value from the given byte array using the specified + * integer size, returned as a long. + *
+ * Values with a size less than sizeof(long) will have their sign bit + * extended. + * + * @param b array containing bytes + * @param size number of bytes (1 - 8) to use from array + * @param offset offset into byte array for getting the long + * @return signed value + * @throws IndexOutOfBoundsException if byte array size is + * less than offset+size or size is greater than 8 (sizeof long) + */ + default long getSignedValue(byte[] b, int offset, int size) { + long val = getValue(b, offset, size); + + int shiftBits = (8 /*sizeof(long)*/ - size) * 8; + + // this little bit of magic will sign-extend the value + val = val << shiftBits; + val = val >> shiftBits; + return val; + } /** * Get the value from the given byte array using the specified size. + * * @param b array containing bytes * @param size number of bytes to use from array at offset 0 + * @param signed boolean flag indicating the value is signed + * @return {@link BigInteger} with value * @throws IndexOutOfBoundsException if byte array size is - * less than size. + * less than size */ - public long getValue(byte[] b, int size); + default BigInteger getBigInteger(byte[] b, int size, boolean signed) { + return getBigInteger(b, 0, size, signed); + } /** * Get the value from the given byte array using the specified size. + * * @param b array containing bytes * @param size number of bytes to use from array * @param offset offset into byte array for getting the long + * @param signed boolean flag indicating the value is signed + * @return {@link BigInteger} with value * @throws IndexOutOfBoundsException if byte array size is - * less than offset+size or size is greater than 8 (sizeof long). + * less than offset+size */ - public long getValue(byte[] b, int offset, int size); + BigInteger getBigInteger(byte[] b, int offset, int size, boolean signed); + + //------------------------------------------------------------------------------- /** - * Get the value from the given byte array using the specified size. - * @param b array containing bytes - * @param size number of bytes to use from array at offset 0 - * @throws IndexOutOfBoundsException if byte array size is - * less than size. + * Converts the short value to an array of bytes. + * + * @param value short value to be converted + * @return array of bytes */ - public BigInteger getBigInteger(byte[] b, int size, boolean signed); + default byte[] getBytes(short value) { + byte[] bytes = new byte[2]; + getBytes(value, bytes); + return bytes; + } /** - * Get the value from the given byte array using the specified size. - * @param b array containing bytes - * @param size number of bytes to use from array - * @param offset offset into byte array for getting the long - * @throws IndexOutOfBoundsException if byte array size is - * less than offset+size. + * Converts the int value to an array of bytes. + * + * @param value int value to be converted + * @return array of bytes */ - public BigInteger getBigInteger(byte[] b, int offset, int size, boolean signed); + default byte[] getBytes(int value) { + byte[] bytes = new byte[4]; + getBytes(value, bytes); + return bytes; + } + + /** + * Converts the long value to an array of bytes. + * + * @param value long value to be converted + * @return array of bytes + */ + default byte[] getBytes(long value) { + byte[] bytes = new byte[8]; + getBytes(value, bytes); + return bytes; + } + + /** + * Converts the value to an array of bytes. + * + * @param value value to be converted + * @param size value size in bytes + * @return array of bytes + */ + default byte[] getBytes(BigInteger value, int size) { + byte[] bytes = new byte[size]; + putBigInteger(bytes, 0, size, value); + return bytes; + } + + //------------------------------------------------------------------------------- + + /** + * Writes a short value into a byte array. + * + * @param b array to contain the bytes + * @param value the short value + * @throws IndexOutOfBoundsException if byte array is too small to hold the value + */ + default void putShort(byte[] b, short value) { + putShort(b, 0, value); + } + + /** + * Writes a short value into the byte array at the given offset + * + * @param b array to contain the bytes + * @param offset the offset into the byte array to store the value + * @param value the short value + * @throws IndexOutOfBoundsException if offset is too large or byte array + * is too small to hold the value + */ + void putShort(byte[] b, int offset, short value); + + /** + * Writes a int value into a byte array. + *
+ * See {@link #getBytes(int, byte[])} + * + * @param b array to contain the bytes + * @param value the int value + * @throws IndexOutOfBoundsException if byte array is too small to hold the value + */ + default void putInt(byte[] b, int value) { + putInt(b, 0, value); + } + + /** + * Writes a int value into the byte array at the given offset. + *
+ * See {@link #getBytes(int, byte[], int)} + * + * @param b array to contain the bytes + * @param offset the offset into the byte array to store the value + * @param value the int value + * @throws IndexOutOfBoundsException if offset is too large or byte array + * is too small to hold the value + */ + void putInt(byte[] b, int offset, int value); + + /** + * Writes a long value into a byte array. + *
+ * See {@link #getBytes(long, byte[])} + * + * @param b array to contain the bytes + * @param value the long value + * @throws IndexOutOfBoundsException if byte array is too small to hold the value + */ + default void putLong(byte[] b, long value) { + putLong(b, 0, value); + } + + /** + * Writes a long value into the byte array at the given offset + *
+ * See {@link #getBytes(long, byte[], int)} + * + * @param b array to contain the bytes + * @param offset the offset into the byte array to store the value + * @param value the long value + * @throws IndexOutOfBoundsException if offset is too large or byte array + * is too small to hold the value + */ + default void putLong(byte[] b, int offset, long value) { + putValue(value, Long.BYTES, b, offset); + } + + /** + * Converts the given value to bytes using the number of least significant bytes + * specified by size. + *
+ * + * @param value value to convert to bytes + * @param size number of least significant bytes of value to be written to the byte array + * @param b byte array to store bytes + * @param offset offset into byte array to put the bytes + * @throws IndexOutOfBoundsException if (offset+size)>b.length + */ + void putValue(long value, int size, byte[] b, int offset); + + /** + * Writes a value of specified size into the byte array at the given offset. + *
+ * See {@link #getBytes(BigInteger, int, byte[], int)} + * + * @param b array to contain the bytes at offset 0 + * @param size number of bytes to be written + * @param value BigInteger value to convert + * @throws IndexOutOfBoundsException if byte array is less than specified size + */ + default void putBigInteger(byte[] b, int size, BigInteger value) { + putBigInteger(b, 0, size, value); + } + + /** + * Writes a value of specified size into the byte array at the given offset + *
+ * See {@link #getBytes(BigInteger, int, byte[], int)} + * + * @param b array to contain the bytes + * @param offset the offset into the byte array to store the value + * @param size number of bytes to be written + * @param value BigInteger value to convert + * @throws IndexOutOfBoundsException if (offset+size)>b.length + */ + public void putBigInteger(byte[] b, int offset, int size, BigInteger value); + + //-------------------------------------------------------------------------------- /** * Converts the given value to bytes. + * See {@link #putShort(byte[], short)} * @param value value to convert to bytes * @param b byte array to store bytes * @throws IndexOutOfBoundsException if b.length is not at least * 2. */ - public void getBytes(short value, byte[] b); + default void getBytes(short value, byte[] b) { + getBytes(value, b, 0); + } /** * Converts the given value to bytes. + *
+ * See {@link #putShort(byte[], int, short)} + * * @param value value to convert to bytes * @param b byte array to store bytes * @param offset offset into byte array to put the bytes * @throws IndexOutOfBoundsException if (offset+2)>b.length */ - public void getBytes(short value, byte[] b, int offset); + default void getBytes(short value, byte[] b, int offset) { + putShort(b, offset, value); + } /** * Converts the given value to bytes. + *
+ * See {@link #putInt(byte[], int)} + * * @param value value to convert to bytes * @param b byte array to store bytes * @throws IndexOutOfBoundsException if b.length is not at least * 4. */ - public void getBytes(int value, byte[] b); + default void getBytes(int value, byte[] b) { + getBytes(value, b, 0); + } /** * Converts the given value to bytes. + *
+ * See {@link #putInt(byte[], int)} + * * @param value value to convert to bytes * @param b byte array to store bytes * @param offset offset into byte array to put the bytes * @throws IndexOutOfBoundsException if (offset+4)>b.length */ - public void getBytes(int value, byte[] b, int offset); + default void getBytes(int value, byte[] b, int offset) { + putInt(b, offset, value); + } /** * Converts the given value to bytes. + *
+ * See {@link #putLong(byte[], long)} + * * @param value value to convert to bytes * @param b byte array to store bytes * @throws IndexOutOfBoundsException if b.length is not at least * 8. */ - public void getBytes(long value, byte[] b); + default void getBytes(long value, byte[] b) { + getBytes(value, b, 0); + } /** * Converts the given value to bytes. + *
+ * See {@link #putLong(byte[], long)} + * * @param value value to convert to bytes * @param b byte array to store bytes * @param offset offset into byte array to put the bytes * @throws IndexOutOfBoundsException if (offset+8)>b.length */ - public void getBytes(long value, byte[] b, int offset); + default void getBytes(long value, byte[] b, int offset) { + putLong(b, offset, value); + } /** * Converts the given value to bytes using the number of least significant bytes * specified by size. + *
+ * See {@link #putValue(long, int, byte[], int)} + * + * @param value value to convert to bytes + * @param size number of least significant bytes of value to be written to the byte array + * @param b byte array to store bytes + * @param offset offset into byte array to put the bytes + * @throws IndexOutOfBoundsException if (offset+size)>b.length + */ + default void getBytes(long value, int size, byte[] b, int offset) { + putValue(value, size, b, offset); + } + + /** + * Converts the given value to bytes using the number of least significant bytes + * specified by size. + *
+ * See {@link #putBigInteger(byte[], int, BigInteger)} + * * @param value value to convert to bytes * @param size number of least significant bytes of value to be written to the byte array * @param b byte array to store bytes * @param offset offset into byte array to put the bytes * @throws IndexOutOfBoundsException if (offset+size)>b.length. */ - public void getBytes(long value, int size, byte[] b, int offset); - - /** - * Converts the given value to bytes using the number of least significant bytes - * specified by size. - * @param value value to convert to bytes - * @param size number of least significant bytes of value to be written to the byte array - * @param b byte array to store bytes - * @param offset offset into byte array to put the bytes - * @throws IndexOutOfBoundsException if (offset+size)>b.length. - */ - public void getBytes(BigInteger value, int size, byte[] b, int offset); - - /** - * Converts the short value to an array of bytes. - * @param value short value to be converted - * @return array of bytes - */ - public byte[] getBytes(short value); - - /** - * Converts the int value to an array of bytes. - * @param value int value to be converted - * @return array of bytes - */ - public byte[] getBytes(int value); - - /** - * Converts the long value to an array of bytes. - * @param value long value to be converted - * @return array of bytes - */ - public byte[] getBytes(long value); - - /** - * Converts the value to an array of bytes. - * @param value value to be converted - * @param size value size in bytes - * @return array of bytes - */ - public byte[] getBytes(BigInteger value, int size); - - /** - * Writes a short value into a byte array. - * @param b array to contain the bytes; - * @param value the short value - */ - public void putShort(byte[] b, short value); - - /** - * Writes a short value into the byte array at the given offset - * @param b array to contain the bytes; - * @param offset the offset into the byte array to store the value. - * @param value the short value - */ - public void putShort(byte[] b, int offset, short value); - - /** - * Writes a int value into a byte array. - * @param b array to contain the bytes; - * @param value the int value - */ - public void putInt(byte[] b, int value); - - /** - * Writes a int value into the byte array at the given offset - * @param b array to contain the bytes; - * @param offset the offset into the byte array to store the value. - * @param value the int value - */ - public void putInt(byte[] b, int offset, int value); - - /** - * Writes a long value into a byte array. - * @param b array to contain the bytes; - * @param value the long value - */ - public void putLong(byte[] b, long value); - - /** - * Writes a long value into the byte array at the given offset - * @param b array to contain the bytes; - * @param offset the offset into the byte array to store the value. - * @param value the long value - */ - public void putLong(byte[] b, int offset, long value); - - /** - * Writes a value of specified size into the byte array at the given offset - * @param b array to contain the bytes at offset 0; - * @param size number of bytes to be written - * @param value - */ - public void putBigInteger(byte[] b, int size, BigInteger value); - - /** - * Writes a value of specified size into the byte array at the given offset - * @param b array to contain the bytes; - * @param offset the offset into the byte array to store the value. - * @param size number of bytes to be written - * @param value - */ - public void putBigInteger(byte[] b, int offset, int size, BigInteger value); + default void getBytes(BigInteger value, int size, byte[] b, int offset) { + putBigInteger(b, offset, size, value); + } /** * Swap the least-significant bytes (based upon size) - * @param val value whoose bytes are to be swapped + * @param val value whose bytes are to be swapped * @param size number of least significant bytes to be swapped * @return value with bytes swapped (any high-order bytes beyond size will be 0) */ diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/LittleEndianDataConverter.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/LittleEndianDataConverter.java index afe90fbe4b..bfe95173af 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/LittleEndianDataConverter.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/util/LittleEndianDataConverter.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +16,7 @@ package ghidra.util; import java.math.BigInteger; +import java.util.Objects; /** * @@ -25,43 +25,29 @@ import java.math.BigInteger; */ public class LittleEndianDataConverter implements DataConverter { - public static LittleEndianDataConverter INSTANCE = new LittleEndianDataConverter(); - /** - * - */ + public static final LittleEndianDataConverter INSTANCE = new LittleEndianDataConverter(); + private static final long serialVersionUID = 1L; /** - * Constructor for BigEndianDataConverter. + * Don't use this constructor to create new instances of this class. Use the static {@link #INSTANCE} instead + * or {@link DataConverter#getInstance(Endian)} */ public LittleEndianDataConverter() { + // empty } - /** - * @see DataConverter#getShort(byte[]) - */ - public final short getShort(byte[] b) { - return getShort(b, 0); - } - - /** - * @see DataConverter#getShort(byte[], int) - */ + @Override public short getShort(byte[] b, int offset) { + Objects.checkFromIndexSize(offset, Short.BYTES, b.length); + return (short) (((b[offset + 1] & 0xff) << 8) | (b[offset] & 0xff)); } - /** - * @see DataConverter#getInt(byte[]) - */ - public final int getInt(byte[] b) { - return getInt(b, 0); - } - - /** - * @see DataConverter#getInt(byte[], int) - */ + @Override public int getInt(byte[] b, int offset) { + Objects.checkFromIndexSize(offset, Integer.BYTES, b.length); + int v = b[offset + 3]; for (int i = 2; i >= 0; i--) { v = (v << 8) | (b[offset + i] & 0xff); @@ -69,17 +55,10 @@ public class LittleEndianDataConverter implements DataConverter { return v; } - /** - * @see DataConverter#getLong(byte[]) - */ - public final long getLong(byte[] b) { - return getLong(b, 0); - } - - /** - * @see DataConverter#getLong(byte[], int) - */ + @Override public long getLong(byte[] b, int offset) { + Objects.checkFromIndexSize(offset, Long.BYTES, b.length); + long v = b[offset + 7]; for (int i = 6; i >= 0; i--) { v = (v << 8) | (b[offset + i] & 0xff); @@ -87,20 +66,11 @@ public class LittleEndianDataConverter implements DataConverter { return v; } - /** - * @see ghidra.util.DataConverter#getValue(byte[], int) - */ - public long getValue(byte[] b, int size) { - return getValue(b, 0, size); - } - - /** - * @see ghidra.util.DataConverter#getValue(byte[], int, int) - */ + @Override public long getValue(byte[] b, int offset, int size) { - if (size > 8) { - throw new IndexOutOfBoundsException("size exceeds sizeof long: " + size); - } + Objects.checkFromIndexSize(offset, size, b.length); + Objects.checkIndex(size, Long.BYTES + 1); + long val = 0; for (int i = size - 1; i >= 0; i--) { val = (val << 8) | (b[offset + i] & 0xff); @@ -109,15 +79,9 @@ public class LittleEndianDataConverter implements DataConverter { } @Override - public final BigInteger getBigInteger(byte[] b, int size, boolean signed) { - return getBigInteger(b, 0, size, signed); - } + public BigInteger getBigInteger(byte[] b, int offset, int size, boolean signed) { + Objects.checkFromIndexSize(offset, size, b.length); - @Override - public final BigInteger getBigInteger(byte[] b, int offset, int size, boolean signed) { - if ((size + offset) > b.length) { - throw new IndexOutOfBoundsException("insufficient bytes"); - } int msbIndex = 0; if (!signed) { // prepend 0 byte @@ -132,32 +96,18 @@ public class LittleEndianDataConverter implements DataConverter { return new BigInteger(bytes); } - /** - * @see DataConverter#getBytes(short, byte[]) - */ - public final void getBytes(short value, byte[] b) { - getBytes(value, b, 0); - } + @Override + public void putShort(byte[] b, int offset, short value) { + Objects.checkFromIndexSize(offset, Short.BYTES, b.length); - /** - * @see DataConverter#getBytes(short, byte[], int) - */ - public void getBytes(short value, byte[] b, int offset) { b[offset + 1] = (byte) (value >> 8); b[offset] = (byte) (value & 0xff); } - /** - * @see DataConverter#getBytes(int, byte[]) - */ - public final void getBytes(int value, byte[] b) { - getBytes(value, b, 0); - } + @Override + public void putInt(byte[] b, int offset, int value) { + Objects.checkFromIndexSize(offset, Integer.BYTES, b.length); - /** - * @see DataConverter#getBytes(int, byte[], int) - */ - public void getBytes(int value, byte[] b, int offset) { b[offset] = (byte) (value); for (int i = 1; i < 4; i++) { value >>= 8; @@ -165,113 +115,20 @@ public class LittleEndianDataConverter implements DataConverter { } } - /** - * @see DataConverter#getBytes(long, byte[]) - */ - public final void getBytes(long value, byte[] b) { - getBytes(value, 8, b, 0); - } + @Override + public void putValue(long value, int size, byte[] b, int offset) { + Objects.checkFromIndexSize(offset, size, b.length); + Objects.checkIndex(size, Long.BYTES + 1); - /** - * @see DataConverter#getBytes(long, byte[], int) - */ - public void getBytes(long value, byte[] b, int offset) { - getBytes(value, 8, b, offset); - } - - /** - * @see ghidra.util.DataConverter#getBytes(long, int, byte[], int) - */ - public void getBytes(long value, int size, byte[] b, int offset) { for (int i = 0; i < size; i++) { b[offset + i] = (byte) value; value >>= 8; } } - /** - * @see ghidra.util.DataConverter#putInt(byte[], int, int) - */ - public final void putInt(byte[] b, int offset, int value) { - getBytes(value, b, offset); - } - - /** - * @see ghidra.util.DataConverter#putInt(byte[], int) - */ - public final void putInt(byte[] b, int value) { - getBytes(value, b); - } - - /** - * @see ghidra.util.DataConverter#putLong(byte[], int, long) - */ - public final void putLong(byte[] b, int offset, long value) { - getBytes(value, b, offset); - } - - /** - * @see ghidra.util.DataConverter#putLong(byte[], long) - */ - public final void putLong(byte[] b, long value) { - getBytes(value, b); - } - - /** - * @see ghidra.util.DataConverter#putShort(byte[], int, short) - */ - public final void putShort(byte[] b, int offset, short value) { - getBytes(value, b, offset); - } - - /** - * @see ghidra.util.DataConverter#putShort(byte[], short) - */ - public final void putShort(byte[] b, short value) { - getBytes(value, b); - } - - /** - * @see ghidra.util.DataConverter#getBytes(int) - */ - public byte[] getBytes(int value) { - byte[] bytes = new byte[4]; - getBytes(value, bytes); - return bytes; - } - - /** - * @see ghidra.util.DataConverter#getBytes(long) - */ - public byte[] getBytes(long value) { - byte[] bytes = new byte[8]; - getBytes(value, bytes); - return bytes; - } - - /** - * @see ghidra.util.DataConverter#getBytes(short) - */ - public byte[] getBytes(short value) { - byte[] bytes = new byte[2]; - getBytes(value, bytes); - return bytes; - } - - @Override - public byte[] getBytes(BigInteger value, int size) { - byte[] bytes = new byte[size]; - putBigInteger(bytes, 0, size, value); - return bytes; - } - - @Override - public void getBytes(BigInteger value, int size, byte[] b, int offset) { - putBigInteger(b, offset, size, value); - } - @Override public void putBigInteger(byte[] b, int offset, int size, BigInteger value) { + Objects.checkFromIndexSize(offset, size, b.length); int fillIndex = offset + size - 1; // start fill from MSB int srcIndex; @@ -292,9 +149,4 @@ public class LittleEndianDataConverter implements DataConverter { } } - @Override - public void putBigInteger(byte[] b, int size, BigInteger value) { - putBigInteger(b, 0, size, value); - } - } diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/NumericUtilities.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/NumericUtilities.java index e0de71c902..28442d9eb8 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/NumericUtilities.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/util/NumericUtilities.java @@ -29,6 +29,7 @@ import util.CollectionUtils; public final class NumericUtilities { public static final BigInteger MAX_UNSIGNED_LONG = new BigInteger("ffffffffffffffff", 16); public static final BigInteger MAX_SIGNED_LONG = new BigInteger("7fffffffffffffff", 16); + public static final long MAX_UNSIGNED_INT32_AS_LONG = 0xffffffffL; private final static String HEX_PREFIX_X = "0X"; private final static String HEX_PREFIX_x = "0x"; @@ -228,14 +229,26 @@ public final class NumericUtilities { return buf.toString(); } - public final static BigInteger unsignedLongToBigInteger(long value) { + /** + * Converts a unsigned long value, which is currently stored in a + * java signed long, into a {@link BigInteger}. + *
+ * In other words, the full 64 bits of the primitive java signed
+ * long is being used to store an unsigned value. This
+ * method converts this into a positive BigInteger value.
+ *
+ * @param value java unsigned long value stuffed into a
+ * java signed long
+ * @return new {@link BigInteger} with the positive value of the unsigned long value
+ */
+ public static BigInteger unsignedLongToBigInteger(long value) {
if (value >= 0) {
return BigInteger.valueOf(value);
}
return MAX_UNSIGNED_LONG.add(BigInteger.valueOf(value + 1));
}
- public final static long bigIntegerToUnsignedLong(BigInteger value) {
+ public static long bigIntegerToUnsignedLong(BigInteger value) {
if (value.compareTo(MAX_SIGNED_LONG) <= 0) {
return value.longValue();
}
diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/Emulator.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/Emulator.java
index a243e26581..70212d57e7 100644
--- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/Emulator.java
+++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/emulator/Emulator.java
@@ -172,8 +172,7 @@ public class Emulator {
* @param restore if true restore modified registers within the register space only
*/
private void initRegisters(boolean restore) {
- DataConverter conv =
- language.isBigEndian() ? new BigEndianDataConverter() : new LittleEndianDataConverter();
+ DataConverter conv = DataConverter.getInstance(language.isBigEndian());
Set