mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GT-3512 cleanup DataConverter interface and BE/LE impls
This commit is contained in:
parent
283e148b26
commit
b6bea0fb39
33 changed files with 539 additions and 666 deletions
|
@ -93,12 +93,7 @@ public class BinaryReader {
|
||||||
* @param isLittleEndian true for little-endian and false for big-endian
|
* @param isLittleEndian true for little-endian and false for big-endian
|
||||||
*/
|
*/
|
||||||
public void setLittleEndian(boolean isLittleEndian) {
|
public void setLittleEndian(boolean isLittleEndian) {
|
||||||
if (isLittleEndian) {
|
converter = DataConverter.getInstance(!isLittleEndian);
|
||||||
converter = new LittleEndianDataConverter();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
converter = new BigEndianDataConverter();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -664,7 +659,7 @@ public class BinaryReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the LONG at <code>index</code>.
|
* Returns the signed LONG at <code>index</code>.
|
||||||
* @param index the index where the LONG begins
|
* @param index the index where the LONG begins
|
||||||
* @return the LONG
|
* @return the LONG
|
||||||
* @exception IOException if an I/O error occurs
|
* @exception IOException if an I/O error occurs
|
||||||
|
@ -674,6 +669,34 @@ public class BinaryReader {
|
||||||
return converter.getLong(bytes);
|
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 <code>nElements</code>
|
* Returns the BYTE array of <code>nElements</code>
|
||||||
* starting at <code>index</code>.
|
* starting at <code>index</code>.
|
||||||
|
|
|
@ -58,8 +58,7 @@ public abstract class AbstractClassicProcessor {
|
||||||
|
|
||||||
Address address = defaultAddressSpace.getAddress(addressValue);
|
Address address = defaultAddressSpace.getAddress(addressValue);
|
||||||
|
|
||||||
DataConverter converter =
|
DataConverter converter = DataConverter.getInstance(language.isBigEndian());
|
||||||
language.isBigEndian() ? new BigEndianDataConverter() : new LittleEndianDataConverter();
|
|
||||||
|
|
||||||
Symbol symbol = getSymbol(nList);
|
Symbol symbol = getSymbol(nList);
|
||||||
|
|
||||||
|
|
|
@ -58,8 +58,7 @@ abstract public class AbstractDyldInfoState {
|
||||||
|
|
||||||
long offset = symbol.getAddress().getOffset();
|
long offset = symbol.getAddress().getOffset();
|
||||||
|
|
||||||
DataConverter converter = program.getLanguage().isBigEndian() ? new BigEndianDataConverter()
|
DataConverter converter = DataConverter.getInstance(program.getLanguage().isBigEndian());
|
||||||
: new LittleEndianDataConverter();
|
|
||||||
|
|
||||||
byte[] bytes = (program.getDefaultPointerSize() == 8) ? converter.getBytes(offset)
|
byte[] bytes = (program.getDefaultPointerSize() == 8) ? converter.getBytes(offset)
|
||||||
: converter.getBytes((int) offset);
|
: converter.getBytes((int) offset);
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class ImportDataDirectory extends DataDirectory {
|
||||||
private ImportInfo[] imports;
|
private ImportInfo[] imports;
|
||||||
|
|
||||||
ExportDataDirectory exportDirectory;
|
ExportDataDirectory exportDirectory;
|
||||||
DataConverter conv = new LittleEndianDataConverter();
|
DataConverter conv = LittleEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
static ImportDataDirectory createImportDataDirectory(NTHeader ntHeader,
|
static ImportDataDirectory createImportDataDirectory(NTHeader ntHeader,
|
||||||
FactoryBundledWithBinaryReader reader) throws IOException {
|
FactoryBundledWithBinaryReader reader) throws IOException {
|
||||||
|
|
|
@ -167,10 +167,7 @@ public class GUID {
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataConverter getDataConverter(MemBuffer buf) {
|
private DataConverter getDataConverter(MemBuffer buf) {
|
||||||
if (buf.isBigEndian()) {
|
return DataConverter.getInstance(buf.isBigEndian());
|
||||||
return new BigEndianDataConverter();
|
|
||||||
}
|
|
||||||
return new LittleEndianDataConverter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -110,9 +110,7 @@ public class GuidDataType extends BuiltIn {
|
||||||
long[] data = new long[4];
|
long[] data = new long[4];
|
||||||
|
|
||||||
boolean isBigEndian = ENDIAN.isBigEndian(settings, buf);
|
boolean isBigEndian = ENDIAN.isBigEndian(settings, buf);
|
||||||
DataConverter conv =
|
DataConverter conv = DataConverter.getInstance(isBigEndian);
|
||||||
isBigEndian ? (DataConverter) new BigEndianDataConverter()
|
|
||||||
: (DataConverter) new LittleEndianDataConverter();
|
|
||||||
|
|
||||||
if (buf.getBytes(bytes, 0) != bytes.length) {
|
if (buf.getBytes(bytes, 0) != bytes.length) {
|
||||||
if (guidName != null) {
|
if (guidName != null) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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];
|
byte[] bytes = new byte[16];
|
||||||
long[] data = new long[4];
|
long[] data = new long[4];
|
||||||
boolean isBigEndian = program.getMemory().isBigEndian();
|
boolean isBigEndian = program.getMemory().isBigEndian();
|
||||||
DataConverter conv =
|
DataConverter conv = DataConverter.getInstance(isBigEndian);
|
||||||
isBigEndian ? (DataConverter) new BigEndianDataConverter()
|
|
||||||
: (DataConverter) new LittleEndianDataConverter();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
program.getMemory().getBytes(address, bytes);
|
program.getMemory().getBytes(address, bytes);
|
||||||
|
@ -254,9 +251,7 @@ public class GuidUtil {
|
||||||
long[] data = new long[4];
|
long[] data = new long[4];
|
||||||
int[] versionData = new int[2];
|
int[] versionData = new int[2];
|
||||||
boolean isBigEndian = program.getMemory().isBigEndian();
|
boolean isBigEndian = program.getMemory().isBigEndian();
|
||||||
DataConverter conv =
|
DataConverter conv = DataConverter.getInstance(isBigEndian);
|
||||||
isBigEndian ? (DataConverter) new BigEndianDataConverter()
|
|
||||||
: (DataConverter) new LittleEndianDataConverter();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
program.getMemory().getBytes(address, bytes);
|
program.getMemory().getBytes(address, bytes);
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class MachoLoader extends AbstractLibrarySupportLoader {
|
||||||
|
|
||||||
// Efficient check to fail fast
|
// Efficient check to fail fast
|
||||||
byte[] magicBytes = provider.readBytes(0, 4);
|
byte[] magicBytes = provider.readBytes(0, 4);
|
||||||
if (!MachConstants.isMagic(new LittleEndianDataConverter().getInt(magicBytes))) {
|
if (!MachConstants.isMagic(LittleEndianDataConverter.INSTANCE.getInt(magicBytes))) {
|
||||||
return loadSpecs;
|
return loadSpecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1385,8 +1385,7 @@ public class MachoProgramBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataConverter getDataConverter() {
|
private DataConverter getDataConverter() {
|
||||||
DataConverter dc = program.getLanguage().isBigEndian() ? new BigEndianDataConverter()
|
DataConverter dc = DataConverter.getInstance(program.getLanguage().isBigEndian());
|
||||||
: new LittleEndianDataConverter();
|
|
||||||
return dc;
|
return dc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class MzLoader extends AbstractLibrarySupportLoader {
|
||||||
private final static byte MOVW_DS_OPCODE = (byte) 0xba;
|
private final static byte MOVW_DS_OPCODE = (byte) 0xba;
|
||||||
private static final long MIN_BYTE_LENGTH = 4;
|
private static final long MIN_BYTE_LENGTH = 4;
|
||||||
|
|
||||||
private DataConverter converter = new LittleEndianDataConverter();
|
private DataConverter converter = LittleEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTierPriority() {
|
public int getTierPriority() {
|
||||||
|
|
|
@ -33,7 +33,7 @@ import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.*;
|
import ghidra.program.model.mem.*;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||||
import ghidra.util.*;
|
import ghidra.util.DataConverter;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
@ -180,13 +180,7 @@ public class OmfLoader extends AbstractLibrarySupportLoader {
|
||||||
ArrayList<OmfFixupRecord> fixups = header.getFixups();
|
ArrayList<OmfFixupRecord> fixups = header.getFixups();
|
||||||
OmfFixupRecord.FixupState state =
|
OmfFixupRecord.FixupState state =
|
||||||
new OmfFixupRecord.FixupState(header, externsyms, program.getLanguage());
|
new OmfFixupRecord.FixupState(header, externsyms, program.getLanguage());
|
||||||
DataConverter converter;
|
DataConverter converter = DataConverter.getInstance(!header.isLittleEndian());
|
||||||
if (header.isLittleEndian()) {
|
|
||||||
converter = new LittleEndianDataConverter();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
converter = new BigEndianDataConverter();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (OmfFixupRecord fixup : fixups) {
|
for (OmfFixupRecord fixup : fixups) {
|
||||||
state.currentFixupRecord = fixup;
|
state.currentFixupRecord = fixup;
|
||||||
|
|
|
@ -319,7 +319,7 @@ public class PeLoader extends AbstractPeDebugLoader {
|
||||||
space.getAddress(originalImageBase + brdd.getVirtualAddress() + brdd.getSize()));
|
space.getAddress(originalImageBase + brdd.getVirtualAddress() + brdd.getSize()));
|
||||||
AddressRange headerRange = new AddressRangeImpl(space.getAddress(originalImageBase),
|
AddressRange headerRange = new AddressRangeImpl(space.getAddress(originalImageBase),
|
||||||
space.getAddress(originalImageBase + optionalHeader.getSizeOfHeaders()));
|
space.getAddress(originalImageBase + optionalHeader.getSizeOfHeaders()));
|
||||||
DataConverter conv = new LittleEndianDataConverter();
|
DataConverter conv = LittleEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
for (BaseRelocation reloc : relocs) {
|
for (BaseRelocation reloc : relocs) {
|
||||||
if (monitor.isCancelled()) {
|
if (monitor.isCancelled()) {
|
||||||
|
|
|
@ -498,16 +498,9 @@ public class ProgramMemoryUtil {
|
||||||
|
|
||||||
int addrSize = toAddress.getSize();
|
int addrSize = toAddress.getSize();
|
||||||
|
|
||||||
DataConverter dataConverter;
|
DataConverter dataConverter = DataConverter.getInstance(memory.isBigEndian());
|
||||||
byte[] addressBytes = new byte[addrSize / 8];
|
byte[] addressBytes = new byte[addrSize / 8];
|
||||||
|
|
||||||
if (isBigEndian) {
|
|
||||||
dataConverter = new BigEndianDataConverter();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dataConverter = new LittleEndianDataConverter();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toAddress instanceof SegmentedAddress) {
|
if (toAddress instanceof SegmentedAddress) {
|
||||||
// Only search for offset (exclude segment)
|
// Only search for offset (exclude segment)
|
||||||
addressBytes = new byte[2];
|
addressBytes = new byte[2];
|
||||||
|
|
|
@ -195,9 +195,7 @@ public class FollowFlowProgramBuilder extends ProgramBuilder {
|
||||||
|
|
||||||
private void setupProgram() throws Exception {
|
private void setupProgram() throws Exception {
|
||||||
|
|
||||||
dataConverter =
|
dataConverter = DataConverter.getInstance(getProgram().getMemory().isBigEndian());
|
||||||
(getProgram().getMemory().isBigEndian()) ? new BigEndianDataConverter()
|
|
||||||
: new LittleEndianDataConverter();
|
|
||||||
|
|
||||||
createMemory(".text", "0x0", 0x1000);
|
createMemory(".text", "0x0", 0x1000);
|
||||||
createMemory(".data", "0x5000", 0x1000);
|
createMemory(".data", "0x5000", 0x1000);
|
||||||
|
|
|
@ -38,7 +38,7 @@ import ghidra.util.DataConverter;
|
||||||
*/
|
*/
|
||||||
public class BigEndianConverterTest extends AbstractGhidraHeadedIntegrationTest {
|
public class BigEndianConverterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
private byte[] b;
|
private byte[] b;
|
||||||
private DataConverter dc;
|
private DataConverter dc = BigEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for BigEndianConverterTest.
|
* Constructor for BigEndianConverterTest.
|
||||||
|
@ -54,7 +54,6 @@ public class BigEndianConverterTest extends AbstractGhidraHeadedIntegrationTest
|
||||||
for (int i = 0; i < b.length; i++) {
|
for (int i = 0; i < b.length; i++) {
|
||||||
b[i] = (byte) i;
|
b[i] = (byte) i;
|
||||||
}
|
}
|
||||||
dc = new BigEndianDataConverter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -36,7 +36,7 @@ import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
*/
|
*/
|
||||||
public class LittleEndianConverterTest extends AbstractGhidraHeadedIntegrationTest {
|
public class LittleEndianConverterTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
private byte[] b;
|
private byte[] b;
|
||||||
private DataConverter dc;
|
private DataConverter dc = LittleEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for BigEndianConverterTest.
|
* Constructor for BigEndianConverterTest.
|
||||||
|
@ -52,7 +52,6 @@ public class LittleEndianConverterTest extends AbstractGhidraHeadedIntegrationTe
|
||||||
for (int i = 0; i < b.length; i++) {
|
for (int i = 0; i < b.length; i++) {
|
||||||
b[i] = (byte) i;
|
b[i] = (byte) i;
|
||||||
}
|
}
|
||||||
dc = new LittleEndianDataConverter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -36,7 +35,7 @@ class FileByteBlock implements ByteBlock {
|
||||||
|
|
||||||
FileByteBlock(byte[] b) {
|
FileByteBlock(byte[] b) {
|
||||||
buf = b;
|
buf = b;
|
||||||
converter = new LittleEndianDataConverter();
|
converter = LittleEndianDataConverter.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
@ -153,12 +152,7 @@ class FileByteBlock implements ByteBlock {
|
||||||
public void setBigEndian(boolean bigEndian) {
|
public void setBigEndian(boolean bigEndian) {
|
||||||
if (this.bigEndian != bigEndian) {
|
if (this.bigEndian != bigEndian) {
|
||||||
this.bigEndian = bigEndian;
|
this.bigEndian = bigEndian;
|
||||||
if (bigEndian) {
|
converter = DataConverter.getInstance(bigEndian);
|
||||||
converter = new BigEndianDataConverter();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
converter = new LittleEndianDataConverter();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ public class FileByteBlockTest extends AbstractGenericTest {
|
||||||
@Test
|
@Test
|
||||||
public void testGetInt() throws Exception {
|
public void testGetInt() throws Exception {
|
||||||
block.setBigEndian(true);
|
block.setBigEndian(true);
|
||||||
DataConverter conv = new BigEndianDataConverter();
|
DataConverter conv = BigEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
byte[] b = new byte[4];
|
byte[] b = new byte[4];
|
||||||
|
@ -77,7 +77,7 @@ public class FileByteBlockTest extends AbstractGenericTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
block.setBigEndian(false);
|
block.setBigEndian(false);
|
||||||
conv = new LittleEndianDataConverter();
|
conv = LittleEndianDataConverter.INSTANCE;
|
||||||
for (int i = 0; i < 12; i++) {
|
for (int i = 0; i < 12; i++) {
|
||||||
byte[] b = new byte[4];
|
byte[] b = new byte[4];
|
||||||
System.arraycopy(buf, i + 4, b, 0, b.length);
|
System.arraycopy(buf, i + 4, b, 0, b.length);
|
||||||
|
@ -89,7 +89,7 @@ public class FileByteBlockTest extends AbstractGenericTest {
|
||||||
@Test
|
@Test
|
||||||
public void testGetLong() throws Exception {
|
public void testGetLong() throws Exception {
|
||||||
block.setBigEndian(true);
|
block.setBigEndian(true);
|
||||||
DataConverter conv = new BigEndianDataConverter();
|
DataConverter conv = BigEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
byte[] b = new byte[8];
|
byte[] b = new byte[8];
|
||||||
|
@ -104,7 +104,7 @@ public class FileByteBlockTest extends AbstractGenericTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
block.setBigEndian(false);
|
block.setBigEndian(false);
|
||||||
conv = new LittleEndianDataConverter();
|
conv = LittleEndianDataConverter.INSTANCE;
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
byte[] b = new byte[8];
|
byte[] b = new byte[8];
|
||||||
System.arraycopy(buf, i + 8, b, 0, b.length);
|
System.arraycopy(buf, i + 8, b, 0, b.length);
|
||||||
|
@ -141,7 +141,7 @@ public class FileByteBlockTest extends AbstractGenericTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSetInt() throws Exception {
|
public void testSetInt() throws Exception {
|
||||||
block.setBigEndian(true);
|
block.setBigEndian(true);
|
||||||
DataConverter conv = new BigEndianDataConverter();
|
DataConverter conv = BigEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
byte[] b = new byte[4];
|
byte[] b = new byte[4];
|
||||||
System.arraycopy(buf, 35, b, 0, b.length);
|
System.arraycopy(buf, 35, b, 0, b.length);
|
||||||
|
@ -158,7 +158,7 @@ public class FileByteBlockTest extends AbstractGenericTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
block.setBigEndian(false);
|
block.setBigEndian(false);
|
||||||
conv = new LittleEndianDataConverter();
|
conv = LittleEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
b = new byte[4];
|
b = new byte[4];
|
||||||
System.arraycopy(buf, 35, b, 0, b.length);
|
System.arraycopy(buf, 35, b, 0, b.length);
|
||||||
|
@ -179,7 +179,7 @@ public class FileByteBlockTest extends AbstractGenericTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSetLong() throws Exception {
|
public void testSetLong() throws Exception {
|
||||||
block.setBigEndian(true);
|
block.setBigEndian(true);
|
||||||
DataConverter conv = new BigEndianDataConverter();
|
DataConverter conv = BigEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
byte[] b = new byte[8];
|
byte[] b = new byte[8];
|
||||||
System.arraycopy(buf, 35, b, 0, b.length);
|
System.arraycopy(buf, 35, b, 0, b.length);
|
||||||
|
@ -196,7 +196,7 @@ public class FileByteBlockTest extends AbstractGenericTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
block.setBigEndian(false);
|
block.setBigEndian(false);
|
||||||
conv = new LittleEndianDataConverter();
|
conv = LittleEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
b = new byte[8];
|
b = new byte[8];
|
||||||
System.arraycopy(buf, 35, b, 0, b.length);
|
System.arraycopy(buf, 35, b, 0, b.length);
|
||||||
|
|
|
@ -395,9 +395,7 @@ public class MachoProcessBindScript extends GhidraScript {
|
||||||
|
|
||||||
long offset = symbol.getAddress().getOffset();
|
long offset = symbol.getAddress().getOffset();
|
||||||
|
|
||||||
DataConverter converter = currentProgram.getLanguage().isBigEndian() ?
|
DataConverter converter = DataConverter.getInstance(currentProgram.getLanguage().isBigEndian());
|
||||||
new BigEndianDataConverter() :
|
|
||||||
new LittleEndianDataConverter();
|
|
||||||
|
|
||||||
if ( currentProgram.getDefaultPointerSize() == 8 ) {
|
if ( currentProgram.getDefaultPointerSize() == 8 ) {
|
||||||
setBytes( getAddress(), converter.getBytes( offset ) );
|
setBytes( getAddress(), converter.getBytes( offset ) );
|
||||||
|
|
|
@ -32,7 +32,7 @@ public abstract class NSObject implements StructConverter {
|
||||||
/**
|
/**
|
||||||
* All data is stored BIG ENDIAN in a binary plist.
|
* All data is stored BIG ENDIAN in a binary plist.
|
||||||
*/
|
*/
|
||||||
protected DataConverter converter = new BigEndianDataConverter( );
|
protected DataConverter converter = BigEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
public abstract String getType();
|
public abstract String getType();
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ import ghidra.util.exception.DuplicateNameException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
public class FixupMacho32bitArmOffsets {
|
public class FixupMacho32bitArmOffsets {
|
||||||
private DataConverter converter = new LittleEndianDataConverter();
|
private DataConverter converter = LittleEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
public InputStream fix(GFile file, long offsetAdjustment, ByteProvider provider,
|
public InputStream fix(GFile file, long offsetAdjustment, ByteProvider provider,
|
||||||
TaskMonitor monitor) throws IOException, MachException {
|
TaskMonitor monitor) throws IOException, MachException {
|
||||||
|
|
|
@ -167,7 +167,7 @@ public class ItemSerializer {
|
||||||
inputStream.skip(MAGIC_NUMBER_POS);
|
inputStream.skip(MAGIC_NUMBER_POS);
|
||||||
byte[] magicBytes = new byte[MAGIC_NUMBER_SIZE];
|
byte[] magicBytes = new byte[MAGIC_NUMBER_SIZE];
|
||||||
inputStream.read(magicBytes);
|
inputStream.read(magicBytes);
|
||||||
BigEndianDataConverter dc = new BigEndianDataConverter();
|
BigEndianDataConverter dc = BigEndianDataConverter.INSTANCE;
|
||||||
long magic = dc.getLong(magicBytes);
|
long magic = dc.getLong(magicBytes);
|
||||||
return (magic == MAGIC_NUMBER);
|
return (magic == MAGIC_NUMBER);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package ghidra.util;
|
package ghidra.util;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to convert a byte array to Java primitives and primitives to a
|
* Helper class to convert a byte array to Java primitives and primitives to a
|
||||||
|
@ -27,42 +28,26 @@ import java.math.BigInteger;
|
||||||
public class BigEndianDataConverter implements DataConverter {
|
public class BigEndianDataConverter implements DataConverter {
|
||||||
public static final BigEndianDataConverter INSTANCE = new BigEndianDataConverter();
|
public static final BigEndianDataConverter INSTANCE = new BigEndianDataConverter();
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = 1L;
|
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.
|
||||||
*/
|
*/
|
||||||
public BigEndianDataConverter() {
|
public BigEndianDataConverter() {
|
||||||
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getShort(byte[])
|
|
||||||
*/
|
|
||||||
public final short getShort(byte[] b) {
|
|
||||||
return getShort(b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see DataConverter#getShort(byte[], int)
|
|
||||||
*/
|
|
||||||
public short getShort(byte[] b, int offset) {
|
public short getShort(byte[] b, int offset) {
|
||||||
|
Objects.checkFromIndexSize(offset, Short.BYTES, b.length);
|
||||||
|
|
||||||
return (short) (((b[offset] & 0xff) << 8) | (b[offset + 1] & 0xff));
|
return (short) (((b[offset] & 0xff) << 8) | (b[offset + 1] & 0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getInt(byte[])
|
|
||||||
*/
|
|
||||||
public final int getInt(byte[] b) {
|
|
||||||
return getInt(b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see DataConverter#getInt(byte[], int)
|
|
||||||
*/
|
|
||||||
public int getInt(byte[] b, int offset) {
|
public int getInt(byte[] b, int offset) {
|
||||||
|
Objects.checkFromIndexSize(offset, Integer.BYTES, b.length);
|
||||||
|
|
||||||
int v = b[offset];
|
int v = b[offset];
|
||||||
for (int i = 1; i < 4; i++) {
|
for (int i = 1; i < 4; i++) {
|
||||||
v = (v << 8) | (b[offset + i] & 0xff);
|
v = (v << 8) | (b[offset + i] & 0xff);
|
||||||
|
@ -70,17 +55,10 @@ public class BigEndianDataConverter implements DataConverter {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getLong(byte[])
|
|
||||||
*/
|
|
||||||
public final long getLong(byte[] b) {
|
|
||||||
return getLong(b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see DataConverter#getLong(byte[], int)
|
|
||||||
*/
|
|
||||||
public long getLong(byte[] b, int offset) {
|
public long getLong(byte[] b, int offset) {
|
||||||
|
Objects.checkFromIndexSize(offset, Long.BYTES, b.length);
|
||||||
|
|
||||||
long v = b[offset];
|
long v = b[offset];
|
||||||
for (int i = 1; i < 8; i++) {
|
for (int i = 1; i < 8; i++) {
|
||||||
v = (v << 8) | (b[offset + i] & 0xff);
|
v = (v << 8) | (b[offset + i] & 0xff);
|
||||||
|
@ -88,20 +66,11 @@ public class BigEndianDataConverter implements DataConverter {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @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)
|
|
||||||
*/
|
|
||||||
public long getValue(byte[] b, int offset, int size) {
|
public long getValue(byte[] b, int offset, int size) {
|
||||||
if (size > 8) {
|
Objects.checkFromIndexSize(offset, size, b.length);
|
||||||
throw new IndexOutOfBoundsException("size exceeds sizeof long: " + size);
|
Objects.checkIndex(size, Long.BYTES + 1);
|
||||||
}
|
|
||||||
long val = 0;
|
long val = 0;
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
val = (val << 8) | (b[offset + i] & 0xff);
|
val = (val << 8) | (b[offset + i] & 0xff);
|
||||||
|
@ -109,16 +78,10 @@ public class BigEndianDataConverter implements DataConverter {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public final BigInteger getBigInteger(byte[] b, int size, boolean signed) {
|
|
||||||
return getBigInteger(b, 0, size, signed);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final BigInteger getBigInteger(byte[] b, int offset, int size, boolean signed) {
|
public final BigInteger getBigInteger(byte[] b, int offset, int size, boolean signed) {
|
||||||
if ((size + offset) > b.length) {
|
Objects.checkFromIndexSize(offset, size, b.length);
|
||||||
throw new IndexOutOfBoundsException("insufficient bytes");
|
|
||||||
}
|
|
||||||
if (offset != 0 || size != b.length) {
|
if (offset != 0 || size != b.length) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
if (!signed && b[offset] < 0) {
|
if (!signed && b[offset] < 0) {
|
||||||
|
@ -132,39 +95,25 @@ public class BigEndianDataConverter implements DataConverter {
|
||||||
}
|
}
|
||||||
else if (!signed && b[0] < 0) {
|
else if (!signed && b[0] < 0) {
|
||||||
// keep unsigned - prepend 0 byte
|
// keep unsigned - prepend 0 byte
|
||||||
byte[] bytes = new byte[size+1];
|
byte[] bytes = new byte[size + 1];
|
||||||
System.arraycopy(b, 0, bytes, 1, size);
|
System.arraycopy(b, 0, bytes, 1, size);
|
||||||
b = bytes;
|
b = bytes;
|
||||||
}
|
}
|
||||||
return new BigInteger(b);
|
return new BigInteger(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getBytes(short, byte[])
|
public void putShort(byte[] b, int offset, short value) {
|
||||||
*/
|
Objects.checkFromIndexSize(offset, Short.BYTES, b.length);
|
||||||
public final void getBytes(short value, byte[] b) {
|
|
||||||
getBytes(value, b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see DataConverter#getBytes(short, byte[], int)
|
|
||||||
*/
|
|
||||||
public void getBytes(short value, byte[] b, int offset) {
|
|
||||||
b[offset] = (byte) (value >> 8);
|
b[offset] = (byte) (value >> 8);
|
||||||
b[offset + 1] = (byte) (value & 0xff);
|
b[offset + 1] = (byte) (value & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getBytes(int, byte[])
|
public void putInt(byte[] b, int offset, int value) {
|
||||||
*/
|
Objects.checkFromIndexSize(offset, Integer.BYTES, b.length);
|
||||||
public final void getBytes(int value, byte[] b) {
|
|
||||||
getBytes(value, b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see DataConverter#getBytes(int, byte[], int)
|
|
||||||
*/
|
|
||||||
public void getBytes(int value, byte[] b, int offset) {
|
|
||||||
b[offset + 3] = (byte) (value);
|
b[offset + 3] = (byte) (value);
|
||||||
for (int i = 2; i >= 0; i--) {
|
for (int i = 2; i >= 0; i--) {
|
||||||
value >>= 8;
|
value >>= 8;
|
||||||
|
@ -172,113 +121,20 @@ public class BigEndianDataConverter implements DataConverter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getBytes(long, byte[])
|
public void putValue(long value, int size, byte[] b, int offset) {
|
||||||
*/
|
Objects.checkFromIndexSize(offset, size, b.length);
|
||||||
public final void getBytes(long value, byte[] b) {
|
Objects.checkIndex(size, Long.BYTES + 1);
|
||||||
getBytes(value, 8, b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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 = size - 1; i >= 0; i--) {
|
for (int i = size - 1; i >= 0; i--) {
|
||||||
b[offset + i] = (byte) value;
|
b[offset + i] = (byte) value;
|
||||||
value >>= 8;
|
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
|
@Override
|
||||||
public void putBigInteger(byte[] b, int offset, int size, BigInteger value) {
|
public void putBigInteger(byte[] b, int offset, int size, BigInteger value) {
|
||||||
|
Objects.checkFromIndexSize(offset, size, b.length);
|
||||||
|
|
||||||
int fillIndex = offset; // start fill from MSB
|
int fillIndex = offset; // start fill from MSB
|
||||||
int srcIndex;
|
int srcIndex;
|
||||||
|
@ -300,9 +156,4 @@ public class BigEndianDataConverter implements DataConverter {
|
||||||
System.arraycopy(valBytes, srcIndex, b, fillIndex, fillCnt);
|
System.arraycopy(valBytes, srcIndex, b, fillIndex, fillCnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void putBigInteger(byte[] b, int size, BigInteger value) {
|
|
||||||
putBigInteger(b, 0, size, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ import java.math.BigInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Defines methods to convert byte arrays to a specific primitive Java types,
|
* Defines methods to convert Java numeric types to and from their
|
||||||
* and to populate byte arrays from primitive Java types.
|
* raw form in a byte array.
|
||||||
*
|
* <p>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface DataConverter extends Serializable {
|
public interface DataConverter extends Serializable {
|
||||||
|
@ -32,264 +32,466 @@ public interface DataConverter extends Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the short value from the given byte array.
|
* Returns the endianess of this DataConverter instance.
|
||||||
* @param b array containing bytes
|
*
|
||||||
* @throws IndexOutOfBoundsException if byte array size is
|
* @return boolean flag, true means big-endian
|
||||||
* less than 2.
|
|
||||||
*/
|
*/
|
||||||
public short getShort(byte[] b);
|
default boolean isBigEndian() {
|
||||||
|
return this instanceof BigEndianDataConverter;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the short value from the given byte array.
|
* Get the short value from the given byte array.
|
||||||
* @param b array containing bytes
|
* @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
|
* @param offset offset into byte array for getting the short
|
||||||
* @throws IndexOutOfBoundsException if byte array size is
|
* @return signed short value
|
||||||
* less than offset+2.
|
* @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.
|
* Get the int value from the given byte array.
|
||||||
|
*
|
||||||
* @param b array containing bytes
|
* @param b array containing bytes
|
||||||
* @throws IndexOutOfBoundsException if byte array size is
|
* @return signed int value from the beginning of the specified array
|
||||||
* less than 4.
|
* @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.
|
* Get the int value from the given byte array.
|
||||||
|
*
|
||||||
* @param b array containing bytes
|
* @param b array containing bytes
|
||||||
* @param offset offset into byte array for getting the int
|
* @param offset offset into byte array for getting the int
|
||||||
* @throws IndexOutOfBoundsException if byte array size is
|
* @return signed int value
|
||||||
* less than offset+4.
|
* @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.
|
* Get the long value from the given byte array.
|
||||||
|
*
|
||||||
* @param b array containing bytes
|
* @param b array containing bytes
|
||||||
* @throws IndexOutOfBoundsException if byte array size is
|
* @return signed long value from the beginning of the specified array
|
||||||
* less than 8.
|
* @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.
|
* Get the long value from the given byte array.
|
||||||
|
*
|
||||||
* @param b array containing bytes
|
* @param b array containing bytes
|
||||||
* @param offset offset into byte array for getting the long
|
* @param offset offset into byte array for getting the long
|
||||||
* @throws IndexOutOfBoundsException if byte array size is
|
* @return signed long value
|
||||||
* less than offset+8.
|
* @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 <b>unsigned</b> value from the given byte array using the specified
|
||||||
|
* integer size, returned as a long.
|
||||||
|
* <p>
|
||||||
|
* Values with a size less than sizeof(long) will <b>not</b> have their sign bit
|
||||||
|
* extended and therefore will appear as an 'unsigned' value.
|
||||||
|
* <p>
|
||||||
|
* Casting the 'unsigned' long value to the correctly sized smaller
|
||||||
|
* java primitive will cause the value to appear as a signed value.
|
||||||
|
* <p>
|
||||||
|
* 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 <b>unsigned</b> value from the given byte array using the specified
|
||||||
|
* integer size, returned as a long.
|
||||||
|
* <p>
|
||||||
|
* Values with a size less than sizeof(long) will <b>not</b> have their sign bit
|
||||||
|
* extended and therefore will appear as an 'unsigned' value.
|
||||||
|
* <p>
|
||||||
|
* Casting the 'unsigned' long value to the correctly sized smaller
|
||||||
|
* java primitive will cause the value to appear as a signed value.
|
||||||
|
* <p>
|
||||||
|
* 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 <b>signed</b> value from the given byte array using the specified
|
||||||
|
* integer size, returned as a long.
|
||||||
|
* <p>
|
||||||
|
* 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 <b>signed</b> value from the given byte array using the specified
|
||||||
|
* integer size, returned as a long.
|
||||||
|
* <p>
|
||||||
|
* 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.
|
* Get the value from the given byte array using the specified size.
|
||||||
|
*
|
||||||
* @param b array containing bytes
|
* @param b array containing bytes
|
||||||
* @param size number of bytes to use from array at offset 0
|
* @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
|
* @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.
|
* Get the value from the given byte array using the specified size.
|
||||||
|
*
|
||||||
* @param b array containing bytes
|
* @param b array containing bytes
|
||||||
* @param size number of bytes to use from array
|
* @param size number of bytes to use from array
|
||||||
* @param offset offset into byte array for getting the long
|
* @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
|
* @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.
|
* Converts the short value to an array of bytes.
|
||||||
* @param b array containing bytes
|
*
|
||||||
* @param size number of bytes to use from array at offset 0
|
* @param value short value to be converted
|
||||||
* @throws IndexOutOfBoundsException if byte array size is
|
* @return array of bytes
|
||||||
* less than size.
|
|
||||||
*/
|
*/
|
||||||
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.
|
* Converts the int value to an array of bytes.
|
||||||
* @param b array containing bytes
|
*
|
||||||
* @param size number of bytes to use from array
|
* @param value int value to be converted
|
||||||
* @param offset offset into byte array for getting the long
|
* @return array of bytes
|
||||||
* @throws IndexOutOfBoundsException if byte array size is
|
|
||||||
* less than offset+size.
|
|
||||||
*/
|
*/
|
||||||
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
default void putShort(byte[] b, int offset, short value) {
|
||||||
|
getBytes(value, b, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a int value into a byte array.
|
||||||
|
* <p>
|
||||||
|
* See {@link #getBytes(int, byte[])}
|
||||||
|
*
|
||||||
|
* @param b array to contain the bytes
|
||||||
|
* @param value the int value
|
||||||
|
*/
|
||||||
|
default void putInt(byte[] b, int value) {
|
||||||
|
putInt(b, 0, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a int value into the byte array at the given offset.
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void putInt(byte[] b, int offset, int value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a long value into a byte array.
|
||||||
|
* <p>
|
||||||
|
* See {@link #getBytes(long, byte[])}
|
||||||
|
*
|
||||||
|
* @param b array to contain the bytes
|
||||||
|
* @param value the long value
|
||||||
|
*/
|
||||||
|
default void putLong(byte[] b, long value) {
|
||||||
|
putLong(b, 0, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a long value into the byte array at the given offset
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* <p>
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public void putBigInteger(byte[] b, int offset, int size, BigInteger value);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given value to bytes.
|
* Converts the given value to bytes.
|
||||||
|
* See {@link #putShort(byte[], short)}
|
||||||
* @param value value to convert to bytes
|
* @param value value to convert to bytes
|
||||||
* @param b byte array to store bytes
|
* @param b byte array to store bytes
|
||||||
* @throws IndexOutOfBoundsException if b.length is not at least
|
* @throws IndexOutOfBoundsException if b.length is not at least
|
||||||
* 2.
|
* 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.
|
* Converts the given value to bytes.
|
||||||
|
* <p>
|
||||||
|
* See {@link #putShort(byte[], int, short)}
|
||||||
|
*
|
||||||
* @param value value to convert to bytes
|
* @param value value to convert to bytes
|
||||||
* @param b byte array to store bytes
|
* @param b byte array to store bytes
|
||||||
* @param offset offset into byte array to put the bytes
|
* @param offset offset into byte array to put the bytes
|
||||||
* @throws IndexOutOfBoundsException if (offset+2)>b.length
|
* @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.
|
* Converts the given value to bytes.
|
||||||
|
* <p>
|
||||||
|
* See {@link #putInt(byte[], int)}
|
||||||
|
*
|
||||||
* @param value value to convert to bytes
|
* @param value value to convert to bytes
|
||||||
* @param b byte array to store bytes
|
* @param b byte array to store bytes
|
||||||
* @throws IndexOutOfBoundsException if b.length is not at least
|
* @throws IndexOutOfBoundsException if b.length is not at least
|
||||||
* 4.
|
* 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.
|
* Converts the given value to bytes.
|
||||||
|
* <p>
|
||||||
|
* See {@link #putInt(byte[], int)}
|
||||||
|
*
|
||||||
* @param value value to convert to bytes
|
* @param value value to convert to bytes
|
||||||
* @param b byte array to store bytes
|
* @param b byte array to store bytes
|
||||||
* @param offset offset into byte array to put the bytes
|
* @param offset offset into byte array to put the bytes
|
||||||
* @throws IndexOutOfBoundsException if (offset+4)>b.length
|
* @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.
|
* Converts the given value to bytes.
|
||||||
|
* <p>
|
||||||
|
* See {@link #putLong(byte[], long)}
|
||||||
|
*
|
||||||
* @param value value to convert to bytes
|
* @param value value to convert to bytes
|
||||||
* @param b byte array to store bytes
|
* @param b byte array to store bytes
|
||||||
* @throws IndexOutOfBoundsException if b.length is not at least
|
* @throws IndexOutOfBoundsException if b.length is not at least
|
||||||
* 8.
|
* 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.
|
* Converts the given value to bytes.
|
||||||
|
* <p>
|
||||||
|
* See {@link #putLong(byte[], long)}
|
||||||
|
*
|
||||||
* @param value value to convert to bytes
|
* @param value value to convert to bytes
|
||||||
* @param b byte array to store bytes
|
* @param b byte array to store bytes
|
||||||
* @param offset offset into byte array to put the bytes
|
* @param offset offset into byte array to put the bytes
|
||||||
* @throws IndexOutOfBoundsException if (offset+8)>b.length
|
* @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
|
* Converts the given value to bytes using the number of least significant bytes
|
||||||
* specified by size.
|
* specified by size.
|
||||||
|
* <p>
|
||||||
|
* 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.
|
||||||
|
* <p>
|
||||||
|
* See {@link #putBigInteger(byte[], int, BigInteger)}
|
||||||
|
*
|
||||||
* @param value value to convert to bytes
|
* @param value value to convert to bytes
|
||||||
* @param size number of least significant bytes of value to be written to the byte array
|
* @param size number of least significant bytes of value to be written to the byte array
|
||||||
* @param b byte array to store bytes
|
* @param b byte array to store bytes
|
||||||
* @param offset offset into byte array to put the bytes
|
* @param offset offset into byte array to put the bytes
|
||||||
* @throws IndexOutOfBoundsException if (offset+size)>b.length.
|
* @throws IndexOutOfBoundsException if (offset+size)>b.length.
|
||||||
*/
|
*/
|
||||||
public void getBytes(long value, int size, byte[] b, int offset);
|
default void getBytes(BigInteger value, int size, byte[] b, int offset) {
|
||||||
|
putBigInteger(b, offset, size, value);
|
||||||
/**
|
}
|
||||||
* 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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swap the least-significant bytes (based upon size)
|
* 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
|
* @param size number of least significant bytes to be swapped
|
||||||
* @return value with bytes swapped (any high-order bytes beyond size will be 0)
|
* @return value with bytes swapped (any high-order bytes beyond size will be 0)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,6 +16,7 @@
|
||||||
package ghidra.util;
|
package ghidra.util;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -25,43 +25,29 @@ import java.math.BigInteger;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class LittleEndianDataConverter implements DataConverter {
|
public class LittleEndianDataConverter implements DataConverter {
|
||||||
public static LittleEndianDataConverter INSTANCE = new LittleEndianDataConverter();
|
public static final LittleEndianDataConverter INSTANCE = new LittleEndianDataConverter();
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = 1L;
|
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() {
|
public LittleEndianDataConverter() {
|
||||||
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getShort(byte[])
|
|
||||||
*/
|
|
||||||
public final short getShort(byte[] b) {
|
|
||||||
return getShort(b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see DataConverter#getShort(byte[], int)
|
|
||||||
*/
|
|
||||||
public short getShort(byte[] b, int offset) {
|
public short getShort(byte[] b, int offset) {
|
||||||
|
Objects.checkFromIndexSize(offset, Short.BYTES, b.length);
|
||||||
|
|
||||||
return (short) (((b[offset + 1] & 0xff) << 8) | (b[offset] & 0xff));
|
return (short) (((b[offset + 1] & 0xff) << 8) | (b[offset] & 0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getInt(byte[])
|
|
||||||
*/
|
|
||||||
public final int getInt(byte[] b) {
|
|
||||||
return getInt(b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see DataConverter#getInt(byte[], int)
|
|
||||||
*/
|
|
||||||
public int getInt(byte[] b, int offset) {
|
public int getInt(byte[] b, int offset) {
|
||||||
|
Objects.checkFromIndexSize(offset, Integer.BYTES, b.length);
|
||||||
|
|
||||||
int v = b[offset + 3];
|
int v = b[offset + 3];
|
||||||
for (int i = 2; i >= 0; i--) {
|
for (int i = 2; i >= 0; i--) {
|
||||||
v = (v << 8) | (b[offset + i] & 0xff);
|
v = (v << 8) | (b[offset + i] & 0xff);
|
||||||
|
@ -69,17 +55,10 @@ public class LittleEndianDataConverter implements DataConverter {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getLong(byte[])
|
|
||||||
*/
|
|
||||||
public final long getLong(byte[] b) {
|
|
||||||
return getLong(b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see DataConverter#getLong(byte[], int)
|
|
||||||
*/
|
|
||||||
public long getLong(byte[] b, int offset) {
|
public long getLong(byte[] b, int offset) {
|
||||||
|
Objects.checkFromIndexSize(offset, Long.BYTES, b.length);
|
||||||
|
|
||||||
long v = b[offset + 7];
|
long v = b[offset + 7];
|
||||||
for (int i = 6; i >= 0; i--) {
|
for (int i = 6; i >= 0; i--) {
|
||||||
v = (v << 8) | (b[offset + i] & 0xff);
|
v = (v << 8) | (b[offset + i] & 0xff);
|
||||||
|
@ -87,20 +66,11 @@ public class LittleEndianDataConverter implements DataConverter {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @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)
|
|
||||||
*/
|
|
||||||
public long getValue(byte[] b, int offset, int size) {
|
public long getValue(byte[] b, int offset, int size) {
|
||||||
if (size > 8) {
|
Objects.checkFromIndexSize(offset, size, b.length);
|
||||||
throw new IndexOutOfBoundsException("size exceeds sizeof long: " + size);
|
Objects.checkIndex(size, Long.BYTES + 1);
|
||||||
}
|
|
||||||
long val = 0;
|
long val = 0;
|
||||||
for (int i = size - 1; i >= 0; i--) {
|
for (int i = size - 1; i >= 0; i--) {
|
||||||
val = (val << 8) | (b[offset + i] & 0xff);
|
val = (val << 8) | (b[offset + i] & 0xff);
|
||||||
|
@ -109,15 +79,9 @@ public class LittleEndianDataConverter implements DataConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final BigInteger getBigInteger(byte[] b, int size, boolean signed) {
|
public BigInteger getBigInteger(byte[] b, int offset, int size, boolean signed) {
|
||||||
return getBigInteger(b, 0, size, 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;
|
int msbIndex = 0;
|
||||||
if (!signed) {
|
if (!signed) {
|
||||||
// prepend 0 byte
|
// prepend 0 byte
|
||||||
|
@ -132,32 +96,18 @@ public class LittleEndianDataConverter implements DataConverter {
|
||||||
return new BigInteger(bytes);
|
return new BigInteger(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getBytes(short, byte[])
|
public void putShort(byte[] b, int offset, short value) {
|
||||||
*/
|
Objects.checkFromIndexSize(offset, Short.BYTES, b.length);
|
||||||
public final void getBytes(short value, byte[] b) {
|
|
||||||
getBytes(value, b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see DataConverter#getBytes(short, byte[], int)
|
|
||||||
*/
|
|
||||||
public void getBytes(short value, byte[] b, int offset) {
|
|
||||||
b[offset + 1] = (byte) (value >> 8);
|
b[offset + 1] = (byte) (value >> 8);
|
||||||
b[offset] = (byte) (value & 0xff);
|
b[offset] = (byte) (value & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getBytes(int, byte[])
|
public void putInt(byte[] b, int offset, int value) {
|
||||||
*/
|
Objects.checkFromIndexSize(offset, Integer.BYTES, b.length);
|
||||||
public final void getBytes(int value, byte[] b) {
|
|
||||||
getBytes(value, b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see DataConverter#getBytes(int, byte[], int)
|
|
||||||
*/
|
|
||||||
public void getBytes(int value, byte[] b, int offset) {
|
|
||||||
b[offset] = (byte) (value);
|
b[offset] = (byte) (value);
|
||||||
for (int i = 1; i < 4; i++) {
|
for (int i = 1; i < 4; i++) {
|
||||||
value >>= 8;
|
value >>= 8;
|
||||||
|
@ -165,113 +115,20 @@ public class LittleEndianDataConverter implements DataConverter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* @see DataConverter#getBytes(long, byte[])
|
public void putValue(long value, int size, byte[] b, int offset) {
|
||||||
*/
|
Objects.checkFromIndexSize(offset, size, b.length);
|
||||||
public final void getBytes(long value, byte[] b) {
|
Objects.checkIndex(size, Long.BYTES + 1);
|
||||||
getBytes(value, 8, b, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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++) {
|
for (int i = 0; i < size; i++) {
|
||||||
b[offset + i] = (byte) value;
|
b[offset + i] = (byte) value;
|
||||||
value >>= 8;
|
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
|
@Override
|
||||||
public void putBigInteger(byte[] b, int offset, int size, BigInteger value) {
|
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 fillIndex = offset + size - 1; // start fill from MSB
|
||||||
int srcIndex;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import util.CollectionUtils;
|
||||||
public final class NumericUtilities {
|
public final class NumericUtilities {
|
||||||
public static final BigInteger MAX_UNSIGNED_LONG = new BigInteger("ffffffffffffffff", 16);
|
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 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";
|
||||||
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();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static BigInteger unsignedLongToBigInteger(long value) {
|
/**
|
||||||
|
* Converts a <strong>unsigned</strong> long value, which is currently stored in a
|
||||||
|
* java <strong>signed</strong> long, into a {@link BigInteger}.
|
||||||
|
* <p>
|
||||||
|
* In other words, the full 64 bits of the primitive java <strong>signed</strong>
|
||||||
|
* long is being used to store an <strong>unsigned</strong> value. This
|
||||||
|
* method converts this into a positive BigInteger value.
|
||||||
|
*
|
||||||
|
* @param value java <strong>unsigned</strong> long value stuffed into a
|
||||||
|
* java <strong>signed</strong> long
|
||||||
|
* @return new {@link BigInteger} with the positive value of the unsigned long value
|
||||||
|
*/
|
||||||
|
public static BigInteger unsignedLongToBigInteger(long value) {
|
||||||
if (value >= 0) {
|
if (value >= 0) {
|
||||||
return BigInteger.valueOf(value);
|
return BigInteger.valueOf(value);
|
||||||
}
|
}
|
||||||
return MAX_UNSIGNED_LONG.add(BigInteger.valueOf(value + 1));
|
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) {
|
if (value.compareTo(MAX_SIGNED_LONG) <= 0) {
|
||||||
return value.longValue();
|
return value.longValue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,8 +172,7 @@ public class Emulator {
|
||||||
* @param restore if true restore modified registers within the register space only
|
* @param restore if true restore modified registers within the register space only
|
||||||
*/
|
*/
|
||||||
private void initRegisters(boolean restore) {
|
private void initRegisters(boolean restore) {
|
||||||
DataConverter conv =
|
DataConverter conv = DataConverter.getInstance(language.isBigEndian());
|
||||||
language.isBigEndian() ? new BigEndianDataConverter() : new LittleEndianDataConverter();
|
|
||||||
Set<String> keys = mstate.getKeys();
|
Set<String> keys = mstate.getKeys();
|
||||||
for (String key : keys) {
|
for (String key : keys) {
|
||||||
List<byte[]> vals = mstate.getVals(key);
|
List<byte[]> vals = mstate.getVals(key);
|
||||||
|
|
|
@ -31,7 +31,7 @@ abstract class RefList extends DatabaseObject {
|
||||||
|
|
||||||
static volatile int BIG_REFLIST_THRESHOLD = 1700;
|
static volatile int BIG_REFLIST_THRESHOLD = 1700;
|
||||||
|
|
||||||
protected static DataConverter converter = new BigEndianDataConverter();
|
protected static DataConverter converter = BigEndianDataConverter.INSTANCE;
|
||||||
|
|
||||||
protected Address address;
|
protected Address address;
|
||||||
protected RecordAdapter adapter;
|
protected RecordAdapter adapter;
|
||||||
|
|
|
@ -327,7 +327,7 @@ public class GenericAddress implements Address {
|
||||||
public String toString(boolean showAddressSpace, int minNumDigits) {
|
public String toString(boolean showAddressSpace, int minNumDigits) {
|
||||||
|
|
||||||
boolean stackFormat = false;
|
boolean stackFormat = false;
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuilder buf = new StringBuilder();
|
||||||
if (addrSpace.isStackSpace()) {
|
if (addrSpace.isStackSpace()) {
|
||||||
stackFormat = true;
|
stackFormat = true;
|
||||||
buf.append("Stack[");
|
buf.append("Stack[");
|
||||||
|
|
|
@ -24,6 +24,7 @@ import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.mem.*;
|
import ghidra.program.model.mem.*;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
|
import ghidra.util.DataConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic implementation for a pointer dataType
|
* Basic implementation for a pointer dataType
|
||||||
|
@ -280,7 +281,7 @@ public class PointerDataType extends BuiltIn implements Pointer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
StringBuffer sbuf = new StringBuffer();
|
StringBuilder sbuf = new StringBuilder();
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
sbuf.append(Integer.toString(8 * length));
|
sbuf.append(Integer.toString(8 * length));
|
||||||
sbuf.append("-bit ");
|
sbuf.append("-bit ");
|
||||||
|
@ -355,21 +356,7 @@ public class PointerDataType extends BuiltIn implements Pointer {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isBigEndian = buf.isBigEndian(); // ENDIAN.isBigEndian(settings, buf);
|
long val = DataConverter.getInstance(buf.isBigEndian()).getValue(bytes, size);
|
||||||
|
|
||||||
if (!isBigEndian) {
|
|
||||||
byte[] flipped = new byte[size];
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
flipped[i] = bytes[size - i - 1];
|
|
||||||
}
|
|
||||||
bytes = flipped;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use long when possible
|
|
||||||
long val = 0;
|
|
||||||
for (byte b : bytes) {
|
|
||||||
val = (val << 8) + (b & 0x0ffL);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return targetSpace.getAddress(val, true);
|
return targetSpace.getAddress(val, true);
|
||||||
|
@ -387,15 +374,14 @@ public class PointerDataType extends BuiltIn implements Pointer {
|
||||||
try {
|
try {
|
||||||
switch (dataLen) {
|
switch (dataLen) {
|
||||||
case 1:
|
case 1:
|
||||||
offset = buf.getByte(0) & 0xff;
|
|
||||||
break;
|
|
||||||
case 2:
|
case 2:
|
||||||
offset = buf.getShort(0) & 0xffff;
|
offset = (int) buf.getVarLengthUnsignedInt(0, dataLen);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
case 8:
|
case 8:
|
||||||
segment = buf.getShort(0) & 0xffff;
|
segment = buf.getUnsignedShort(0);
|
||||||
offset = buf.getShort(2) & 0xffff;
|
offset = buf.getUnsignedShort(2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -20,6 +20,7 @@ import ghidra.docking.settings.SettingsDefinition;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.lang.ProcessorContext;
|
import ghidra.program.model.lang.ProcessorContext;
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
import ghidra.program.model.mem.MemBuffer;
|
||||||
|
import ghidra.util.DataConverter;
|
||||||
import ghidra.util.classfinder.ClassTranslator;
|
import ghidra.util.classfinder.ClassTranslator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,21 +106,7 @@ public class ShiftedAddressDataType extends BuiltIn {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isBigEndian = buf.isBigEndian(); // ENDIAN.isBigEndian(settings, buf);
|
long val = DataConverter.getInstance(buf.isBigEndian()).getValue(bytes, size);
|
||||||
|
|
||||||
if (!isBigEndian) {
|
|
||||||
byte[] flipped = new byte[size];
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
flipped[i] = bytes[size - i - 1];
|
|
||||||
}
|
|
||||||
bytes = flipped;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use long when possible
|
|
||||||
long val = 0;
|
|
||||||
for (byte b : bytes) {
|
|
||||||
val = (val << 8) + (b & 0x0ffL);
|
|
||||||
}
|
|
||||||
|
|
||||||
val = val << shift;
|
val = val << shift;
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,7 @@ package ghidra.program.model.mem;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.util.GhidraBigEndianDataConverter;
|
import ghidra.util.GhidraDataConverter;
|
||||||
import ghidra.util.GhidraLittleEndianDataConverter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple byte buffer implementation of the memBuffer. Since there is no
|
* Simple byte buffer implementation of the memBuffer. Since there is no
|
||||||
|
@ -29,9 +28,9 @@ import ghidra.util.GhidraLittleEndianDataConverter;
|
||||||
*/
|
*/
|
||||||
public class ByteMemBufferImpl implements MemBuffer {
|
public class ByteMemBufferImpl implements MemBuffer {
|
||||||
|
|
||||||
|
private final GhidraDataConverter converter;
|
||||||
private byte[] bytes;
|
private byte[] bytes;
|
||||||
private Address addr;
|
private Address addr;
|
||||||
private final boolean isBigEndian;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a ByteMemBufferImpl object
|
* Construct a ByteMemBufferImpl object
|
||||||
|
@ -42,7 +41,7 @@ public class ByteMemBufferImpl implements MemBuffer {
|
||||||
public ByteMemBufferImpl(Address addr, byte[] bytes, boolean isBigEndian) {
|
public ByteMemBufferImpl(Address addr, byte[] bytes, boolean isBigEndian) {
|
||||||
this.addr = addr;
|
this.addr = addr;
|
||||||
this.bytes = bytes;
|
this.bytes = bytes;
|
||||||
this.isBigEndian = isBigEndian;
|
this.converter = GhidraDataConverter.getInstance(isBigEndian);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,7 +53,7 @@ public class ByteMemBufferImpl implements MemBuffer {
|
||||||
*/
|
*/
|
||||||
public ByteMemBufferImpl(Address addr, boolean isBigEndian, int... byteValues) {
|
public ByteMemBufferImpl(Address addr, boolean isBigEndian, int... byteValues) {
|
||||||
this.addr = addr;
|
this.addr = addr;
|
||||||
this.isBigEndian = isBigEndian;
|
this.converter = GhidraDataConverter.getInstance(isBigEndian);
|
||||||
bytes = new byte[byteValues.length];
|
bytes = new byte[byteValues.length];
|
||||||
for (int i = 0; i < bytes.length; i++) {
|
for (int i = 0; i < bytes.length; i++) {
|
||||||
bytes[i] = (byte) byteValues[i];
|
bytes[i] = (byte) byteValues[i];
|
||||||
|
@ -96,42 +95,30 @@ public class ByteMemBufferImpl implements MemBuffer {
|
||||||
System.arraycopy(bytes, offset, b, 0, len);
|
System.arraycopy(bytes, offset, b, 0, len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isBigEndian() {
|
public boolean isBigEndian() {
|
||||||
return isBigEndian;
|
return converter.isBigEndian();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short getShort(int offset) throws MemoryAccessException {
|
public short getShort(int offset) throws MemoryAccessException {
|
||||||
if (isBigEndian) {
|
return converter.getShort(this, offset);
|
||||||
return GhidraBigEndianDataConverter.INSTANCE.getShort(this, offset);
|
|
||||||
}
|
|
||||||
return GhidraLittleEndianDataConverter.INSTANCE.getShort(this, offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getInt(int offset) throws MemoryAccessException {
|
public int getInt(int offset) throws MemoryAccessException {
|
||||||
if (isBigEndian) {
|
return converter.getInt(this, offset);
|
||||||
return GhidraBigEndianDataConverter.INSTANCE.getInt(this, offset);
|
|
||||||
}
|
|
||||||
return GhidraLittleEndianDataConverter.INSTANCE.getInt(this, offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getLong(int offset) throws MemoryAccessException {
|
public long getLong(int offset) throws MemoryAccessException {
|
||||||
if (isBigEndian) {
|
return converter.getLong(this, offset);
|
||||||
return GhidraBigEndianDataConverter.INSTANCE.getLong(this, offset);
|
|
||||||
}
|
|
||||||
return GhidraLittleEndianDataConverter.INSTANCE.getLong(this, offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigInteger getBigInteger(int offset, int size, boolean signed)
|
public BigInteger getBigInteger(int offset, int size, boolean signed)
|
||||||
throws MemoryAccessException {
|
throws MemoryAccessException {
|
||||||
if (isBigEndian) {
|
return converter.getBigInteger(this, offset, size, signed);
|
||||||
return GhidraBigEndianDataConverter.INSTANCE.getBigInteger(this, offset, size, signed);
|
|
||||||
}
|
|
||||||
return GhidraLittleEndianDataConverter.INSTANCE.getBigInteger(this, offset, size, signed);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,38 +22,49 @@ import ghidra.program.model.mem.MemoryAccessException;
|
||||||
|
|
||||||
public interface GhidraDataConverter extends DataConverter {
|
public interface GhidraDataConverter extends DataConverter {
|
||||||
|
|
||||||
|
public static GhidraDataConverter getInstance(boolean isBigEndian) {
|
||||||
|
return isBigEndian ? GhidraBigEndianDataConverter.INSTANCE
|
||||||
|
: GhidraLittleEndianDataConverter.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a little-endian short value by invoking buf.getBytes at the specified offset.
|
* Generate a short value by invoking buf.getBytes at the specified offset.
|
||||||
* @param buf
|
*
|
||||||
* @param offset
|
* @param buf MemBuffer source of bytes
|
||||||
* @return little-endian short value
|
* @param offset offset in mem buffer to read
|
||||||
|
* @return short value
|
||||||
* @throws MemoryAccessException if failed to read 2-bytes at the specified offset
|
* @throws MemoryAccessException if failed to read 2-bytes at the specified offset
|
||||||
*/
|
*/
|
||||||
public short getShort(MemBuffer buf, int offset) throws MemoryAccessException;
|
public short getShort(MemBuffer buf, int offset) throws MemoryAccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a little-endian int value by invoking buf.getBytes at the specified offset.
|
* Generate a int value by invoking buf.getBytes at the specified offset.
|
||||||
* @param buf
|
*
|
||||||
* @param offset
|
* @param buf MemBuffer source of bytes
|
||||||
* @return little-endian int value
|
* @param offset offset in mem buffer to read
|
||||||
|
* @return int value
|
||||||
* @throws MemoryAccessException if failed to read 4-bytes at the specified offset
|
* @throws MemoryAccessException if failed to read 4-bytes at the specified offset
|
||||||
*/
|
*/
|
||||||
public int getInt(MemBuffer buf, int offset) throws MemoryAccessException;
|
public int getInt(MemBuffer buf, int offset) throws MemoryAccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a little-endian long value by invoking buf.getBytes at the specified offset.
|
* Generate a long value by invoking buf.getBytes at the specified offset.
|
||||||
* @param buf
|
*
|
||||||
* @param offset
|
* @param buf MemBuffer source of bytes
|
||||||
* @return little-endian long value
|
* @param offset offset in mem buffer to read
|
||||||
|
* @return long value
|
||||||
* @throws MemoryAccessException if failed to read 8-bytes at the specified offset
|
* @throws MemoryAccessException if failed to read 8-bytes at the specified offset
|
||||||
*/
|
*/
|
||||||
public long getLong(MemBuffer buf, int offset) throws MemoryAccessException;
|
public long getLong(MemBuffer buf, int offset) throws MemoryAccessException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a little-endian BigInteger value by invoking buf.getBytes at the specified offset.
|
* Generate a BigInteger value by invoking buf.getBytes at the specified offset.
|
||||||
* @param buf
|
*
|
||||||
* @param offset
|
* @param buf MemBuffer source of bytes
|
||||||
* @return little-endian BigInteger value
|
* @param offset offset in mem buffer to read
|
||||||
|
* @param size number of bytes
|
||||||
|
* @param signed boolean flag
|
||||||
|
* @return BigInteger value
|
||||||
* @throws MemoryAccessException if failed to read specified number of bytes
|
* @throws MemoryAccessException if failed to read specified number of bytes
|
||||||
* at the specified offset
|
* at the specified offset
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue