blob: 7b6d129eaf0083e7ad4924655b9fa7b3ec507c8a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2010 Nokia and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nokia - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.debug.edc;
import java.math.BigInteger;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.symbols.IBasicType;
import org.eclipse.cdt.debug.edc.internal.symbols.ICPPBasicType;
import org.eclipse.cdt.debug.edc.internal.symbols.IPointerType;
import org.eclipse.cdt.debug.edc.symbols.IEnumerator;
import org.eclipse.cdt.debug.edc.symbols.IType;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.model.MemoryByte;
public class MemoryUtils {
public static final int LITTLE_ENDIAN = 0;
public static final int BIG_ENDIAN = 1;
public static final int ENDIANESS_UNKNOWN = 2;
/**
* Pad byte array with 0's or 1's when the byte array's length is shorter
* than what's expected by the conversion functions.
*
* @param array
* @param size
* @param endianess
* @param isSigned
* @return an array of bytes
*/
protected static byte[] fillArray(byte[] array, int size, int endianess, boolean isSigned) {
byte[] temp = new byte[size];
// either 0 fill or sign extend
byte fillByte = 0;
if (isSigned && ((array[array.length - 1] & 0x80) != 0))
fillByte = (byte) 0xff;
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
for (int i = 0; i < array.length; i++) {
temp[i] = array[i];
}
// fill up the rest of the array
for (int i = array.length; i < size; i++) {
temp[i] = fillByte;
}
array = temp;
return array;
}
for (int i = 0; i < size - array.length; i++) {
temp[i] = fillByte;
}
int j = 0;
// fill up the rest of the array
for (int i = size - array.length; i < size; i++) {
temp[i] = array[j];
j++;
}
array = temp;
return array;
}
/**
* Convert byte array to unsigned long.
*
* @param data
* @param endianess
* @return result of the conversion in long
*/
static public BigInteger convertByteArrayToUnsignedLong(MemoryByte[] data, int endianess) {
byte[] array = new byte[data.length];
for (int i = 0; i < array.length; i++) {
array[i] = data[i].getValue();
}
if (array.length < 8) {
array = fillArray(array, 8, endianess, false);
}
BigInteger value = new BigInteger("0"); //$NON-NLS-1$
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
for (int i = 0; i < 8; i++) {
byte[] temp = new byte[1];
temp[0] = array[i];
BigInteger b = new BigInteger(temp);
b = b.and(new BigInteger("ff", 16)); //$NON-NLS-1$
b = b.shiftLeft(i * 8);
value = value.or(b);
}
} else {
for (int i = 0; i < 8; i++) {
byte[] temp = new byte[1];
temp[0] = array[i];
BigInteger b = new BigInteger(temp);
b = b.and(new BigInteger("ff", 16)); //$NON-NLS-1$
b = b.shiftLeft((7 - i) * 8);
value = value.or(b);
}
}
return value;
}
/**
* Convert byte array to signed long.
*
* @param data
* @param endianess
* @return result of the conversion in long
*/
static public long convertByteArrayToLong(MemoryByte[] data, int endianess) {
byte[] array = new byte[data.length];
for (int i = 0; i < array.length; i++) {
array[i] = data[i].getValue();
}
if (array.length < 8) {
array = fillArray(array, 8, endianess, true);
}
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
long value = 0;
for (int i = 0; i < 8; i++) {
long b = array[i];
b &= 0xff;
value |= (b << (i * 8));
}
return value;
}
long value = 0;
for (int i = 0; i < 8; i++) {
long b = array[i];
b &= 0xff;
value |= (b << ((7 - i) * 8));
}
return value;
}
static public BigInteger convertByteArrayToSignedBigInt(byte[] array, int endianess) {
if (array.length < 16) {
array = fillArray(array, 16, endianess, false);
}
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
// reverse bytes
byte[] holder = new byte[16];
int j = 15;
for (int i = 0; i < 16; i++, j--) {
holder[i] = array[j];
}
// create BigInteger
BigInteger value = new BigInteger(holder);
return value;
}
BigInteger value = new BigInteger(array);
return value;
}
static public BigInteger convertByteArrayToSignedBigInt(byte[] array, int endianess, int arraySize) {
if (array.length < arraySize) {
array = fillArray(array, arraySize, endianess, true);
}
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
// reverse bytes
byte[] holder = new byte[arraySize];
int j = arraySize - 1;
for (int i = 0; i < arraySize; i++, j--) {
holder[i] = array[j];
}
// create BigInteger
BigInteger value = new BigInteger(holder);
return value;
}
BigInteger value = new BigInteger(array);
return value;
}
static public BigInteger convertByteArrayToUnsignedBigInt(byte[] array, int endianess) {
if (array.length < 16) {
array = fillArray(array, 16, endianess, false);
}
BigInteger value = new BigInteger("0"); //$NON-NLS-1$
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
for (int i = 0; i < 16; i++) {
byte[] temp = new byte[1];
temp[0] = array[i];
BigInteger b = new BigInteger(temp);
b = b.and(new BigInteger("ff", 16)); //$NON-NLS-1$
b = b.shiftLeft(i * 8);
value = value.or(b);
}
} else {
for (int i = 0; i < 16; i++) {
byte[] temp = new byte[1];
temp[0] = array[i];
BigInteger b = new BigInteger(temp);
b = b.and(new BigInteger("ff", 16)); //$NON-NLS-1$
b = b.shiftLeft((15 - i) * 8);
value = value.or(b);
}
}
return value;
}
static public BigInteger convertByteArrayToUnsignedBigInt(byte[] array, int endianess, int arraySize) {
if (array.length < arraySize) {
array = fillArray(array, arraySize, endianess, false);
}
BigInteger value = new BigInteger("0"); //$NON-NLS-1$
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
for (int i = 0; i < arraySize; i++) {
byte[] temp = new byte[1];
temp[0] = array[i];
BigInteger b = new BigInteger(temp);
b = b.and(new BigInteger("ff", 16)); //$NON-NLS-1$
b = b.shiftLeft(i * 8);
value = value.or(b);
}
} else {
for (int i = 0; i < arraySize; i++) {
byte[] temp = new byte[1];
temp[0] = array[i];
BigInteger b = new BigInteger(temp);
b = b.and(new BigInteger("ff", 16)); //$NON-NLS-1$
b = b.shiftLeft((arraySize - 1 - i) * 8);
value = value.or(b);
}
}
return value;
}
/**
* Convert byte array to integer.
*
* @param array
* @param endianess
* @return result of the conversion in int
*/
static public int convertByteArrayToInt(MemoryByte[] data, int endianess) {
byte[] array = new byte[data.length];
for (int i = 0; i < array.length; i++) {
array[i] = data[i].getValue();
}
if (array.length < 4) {
array = fillArray(array, 4, endianess, true);
}
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
int value = 0;
for (int i = 0; i < 4; i++) {
int b = array[i];
b &= 0xff;
value |= (b << (i * 8));
}
return value;
}
int value = 0;
for (int i = 0; i < 4; i++) {
int b = array[i];
b &= 0xff;
value |= (b << ((3 - i) * 8));
}
return value;
}
/**
* Convert byte array to short.
*
* @param array
* @param endianess
* @return result of teh conversion in short
*/
static public short convertByteArrayToShort(MemoryByte[] data, int endianess) {
byte[] array = new byte[data.length];
for (int i = 0; i < array.length; i++) {
array[i] = data[i].getValue();
}
if (array.length < 2) {
array = fillArray(array, 2, endianess, true);
}
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
short value = 0;
for (int i = 0; i < 2; i++) {
short b = array[i];
b &= 0xff;
value |= (b << (i * 8));
}
return value;
}
short value = 0;
for (int i = 0; i < 2; i++) {
short b = array[i];
b &= 0xff;
value |= (b << ((1 - i) * 8));
}
return value;
}
/**
* Convert big integer to byte array.
*
* @param i
* @param endianess
* @return result of the conversion in raw byte array
*/
static public byte[] convertBigIntegerToByteArray(BigInteger i, int endianess) {
byte buf[] = new byte[16];
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
for (int j = 0; j < 16; j++) {
BigInteger x = i.shiftRight(j * 8);
buf[j] = x.byteValue();
}
return buf;
}
for (int j = 15; j >= 0; j--) {
BigInteger x = i.shiftRight((15 - j) * 8);
buf[j] = x.byteValue();
}
return buf;
}
static public byte[] convertSignedBigIntToByteArray(BigInteger i, int endianess, int arraySize) {
byte buf[] = new byte[arraySize];
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
for (int j = 0; j < arraySize; j++) {
BigInteger x = i.shiftRight(j * 8);
buf[j] = x.byteValue();
}
return buf;
}
for (int j = arraySize - 1; j >= 0; j--) {
BigInteger x = i.shiftRight((arraySize - 1 - j) * 8);
buf[j] = x.byteValue();
}
return buf;
}
/**
* Convert big integer to byte array.
*
* @param i
* @param endianess
* @return result of the conversion in raw byte array
*/
static public byte[] convertUnsignedBigIntegerToByteArray(BigInteger i, int endianess) {
byte buf[] = new byte[32];
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
for (int j = 0; j < 32; j++) {
BigInteger x = i.shiftRight(j * 8);
buf[j] = x.byteValue();
}
return buf;
}
for (int j = 31; j >= 0; j--) {
BigInteger x = i.shiftRight((31 - j) * 8);
buf[j] = x.byteValue();
}
return buf;
}
static public byte[] convertUnsignedBigIntToByteArray(BigInteger i, int endianess, int arraySize) {
byte buf[] = new byte[arraySize * 2];
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
for (int j = 0; j < arraySize * 2; j++) {
BigInteger x = i.shiftRight(j * 8);
buf[j] = x.byteValue();
}
return buf;
}
for (int j = (arraySize * 2) - 1; j >= 0; j--) {
BigInteger x = i.shiftRight(((arraySize * 2) - 1 - j) * 8);
buf[j] = x.byteValue();
}
return buf;
}
/**
* Convert long to byte array.
*
* @param i
* @param endianess
* @return result of the conversion in raw byte array
*/
static public byte[] convertLongToByteArray(long i, int endianess) {
byte buf[] = new byte[8];
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
for (int j = 0; j < 8; j++) {
buf[j] = new Long(i >> j * 8).byteValue();
}
return buf;
}
for (int j = 7; j >= 0; j--) {
buf[j] = new Long(i >> (7 - j) * 8).byteValue();
}
return buf;
}
/**
* Convert integer to byte array.
*
* @param i
* @param endianess
* @return result of the conversion in raw byte array
*/
static public byte[] convertIntToByteArray(int i, int endianess) {
byte buf[] = new byte[4];
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
for (int j = 0; j < 4; j++) {
buf[j] = new Integer(i >> j * 8).byteValue();
}
return buf;
}
for (int j = 3; j >= 0; j--) {
buf[j] = new Integer(i >> (3 - j) * 8).byteValue();
}
return buf;
}
/**
* Convert short to byte array.
*
* @param i
* @param endianess
* @return result of the conversion in raw byte array
*/
static public byte[] convertShortToByteArray(short i, int endianess) {
byte buf[] = new byte[2];
if (endianess == MemoryUtils.LITTLE_ENDIAN) {
for (short j = 0; j < 2; j++) {
buf[j] = new Integer(i >> j * 8).byteValue();
}
return buf;
}
for (short j = 1; j >= 0; j--) {
buf[j] = new Integer(i >> (1 - j) * 8).byteValue();
}
return buf;
}
/**
* byte array to Hex string helper replaces the Integer.toHexString() which
* can't convert byte values properly (always pads with FFFFFF)
*/
static public String convertByteArrayToHexString(byte[] byteArray) {
StringBuffer strBuffer = new StringBuffer();
char charArray[];
for (byte element : byteArray) {
charArray = MemoryUtils.convertByteToCharArray(element);
strBuffer.append(charArray);
}
return strBuffer.toString();
}
static public char[] convertByteToCharArray(byte aByte) {
char charArray[] = new char[2];
int val = aByte;
if (val < 0)
val += 256;
charArray[0] = Character.forDigit(val / 16, 16);
charArray[1] = Character.forDigit(val % 16, 16);
return charArray;
}
/**
* Convert raw memory data to byte array
*
* @param str
* @param numBytes
* @param numCharsPerByte
* - number of characters per byte of data
* @return an array of byte, converted from a hex string
* @throws NumberFormatException
*/
public static byte[] convertHexStringToByteArray(String str, int numBytes, int numCharsPerByte)
throws NumberFormatException {
if (str.length() == 0)
return null;
StringBuffer buf = new StringBuffer(str);
// pad string with zeros
int requiredPadding = numBytes * numCharsPerByte - str.length();
while (requiredPadding > 0) {
buf.insert(0, "0"); //$NON-NLS-1$
requiredPadding--;
}
byte[] bytes = new byte[numBytes];
str = buf.toString();
// set data in memory
for (int i = 0; i < bytes.length; i++) {
// convert string to byte
String oneByte = str.substring(i * 2, i * 2 + 2);
Integer number = Integer.valueOf(oneByte, 16);
if (number.compareTo(Integer.valueOf(Byte.toString(Byte.MAX_VALUE))) > 0) {
int temp = number.intValue();
temp = temp - 256;
String tempStr = Integer.toString(temp);
Byte myByte = Byte.valueOf(tempStr);
bytes[i] = myByte.byteValue();
} else {
Byte myByte = Byte.valueOf(oneByte, 16);
bytes[i] = myByte.byteValue();
}
}
return bytes;
}
public static String convertMemoryBytesToHexString(MemoryByte[] bytes) {
StringBuffer strBuffer = new StringBuffer();
char charArray[];
for (MemoryByte b : bytes) {
charArray = MemoryUtils.convertByteToCharArray(b.getValue());
strBuffer.append(charArray);
}
return strBuffer.toString();
}
/**
* Convert raw memory data to byte array
*
* @param str
* @param numBytes
* @param numCharsPerByte
* - number of characters per byte of data
* @return an array of byte, converted from a hex string
* @throws NumberFormatException
*/
public static MemoryByte[] convertHexStringToMemoryBytes(String str, int numBytes, int numCharsPerByte)
throws NumberFormatException {
if (str.length() == 0)
return null;
StringBuffer buf = new StringBuffer(str);
// pad string with zeros
int requiredPadding = numBytes * numCharsPerByte - str.length();
while (requiredPadding > 0) {
buf.insert(0, "0"); //$NON-NLS-1$
requiredPadding--;
}
MemoryByte[] bytes = new MemoryByte[numBytes];
str = buf.toString();
// set data in memory
for (int i = 0; i < bytes.length; i++) {
// convert string to byte
String oneByte = str.substring(i * 2, i * 2 + 2);
Integer number = Integer.valueOf(oneByte, 16);
if (number.compareTo(Integer.valueOf(Byte.toString(Byte.MAX_VALUE))) > 0) {
int temp = number.intValue();
temp = temp - 256;
String tempStr = Integer.toString(temp);
Byte myByte = Byte.valueOf(tempStr);
bytes[i] = new MemoryByte(myByte.byteValue());
} else {
Byte myByte = Byte.valueOf(oneByte, 16);
bytes[i] = new MemoryByte(myByte.byteValue());
}
}
return bytes;
}
public static class TypeCharacteristics {
public int basicType = IBasicType.t_unspecified;
public boolean isSigned = false;
public boolean isShort = false;
public boolean isLong = false;
public boolean isLongLong = false;
public boolean isComplex = false;
public TypeCharacteristics(IType varType) {
if (varType instanceof IBasicType) {
IBasicType type = (IBasicType) varType;
basicType = type.getBaseType();
isSigned = type.isSigned();
isShort = type.isShort();
isLong = type.isLong();
if (varType instanceof ICPPBasicType) {
ICPPBasicType cppType = (ICPPBasicType) varType;
isLongLong = cppType.isLongLong();
isComplex = cppType.isComplex();
}
} else if (varType instanceof IPointerType) {
// treat pointer as an unsigned int
basicType = IBasicType.t_int;
} else if (varType instanceof IEnumerator){
// treat enumerator as a signed int
basicType = IBasicType.t_int;
isSigned = true;
} else {
// treat unknown type as an unsigned int
basicType = IBasicType.t_int;
}
}
}
public static BigInteger convertValueToMemory(IType varType, Number value) throws CoreException {
BigInteger result = null;
int varSize = varType.getByteSize();
if (varSize <= 0)
throw EDCDebugger.newCoreException("Type has no size");
TypeCharacteristics characteristics = new TypeCharacteristics(varType);
// all other locations
switch (characteristics.basicType) {
case IBasicType.t_float:
case IBasicType.t_double:
if (varSize == 4) {
result = BigInteger.valueOf(Float.floatToIntBits(value.floatValue()));
} else if (varSize == 8) {
result = BigInteger.valueOf(Double.doubleToLongBits(value.doubleValue()));
}
break;
case ICPPBasicType.t_bool:
case ICPPBasicType.t_wchar_t:
case IBasicType.t_char:
case IBasicType.t_int:
case IBasicType.t_void:
if (characteristics.isSigned) {
// as needed, mask the value and sign-extend
if (varSize == 4) {
result = BigInteger.valueOf(value.intValue());
} else if (varSize == 2) {
int intResult = value.intValue() & 0xffff;
if ((intResult & 0x00008000) != 0)
intResult |= 0xffff0000;
result = BigInteger.valueOf(intResult);
} else if (varSize == 1) {
int intResult = value.intValue() & 0xff;
if ((intResult & 0x00000080) != 0)
intResult |= 0xffffff00;
result = BigInteger.valueOf(intResult);
} else {
// assume an 8-byte long is the default
result = BigInteger.valueOf(value.longValue());
}
} else {
if (varSize == 4) {
result = BigInteger.valueOf(value.longValue() & 0xffffffffL); // keep it unsigned
} else if (varSize == 2) {
result = BigInteger.valueOf(value.intValue() & 0xffff);
} else if (varSize == 1) {
result = BigInteger.valueOf(value.intValue() & 0xff);
} else {
// assume an 8-byte long is the default
result = BigInteger.valueOf(value.longValue());
}
}
break;
case IBasicType.t_unspecified:
default:
assert false;
throw EDCDebugger.newCoreException("Unhandled type");
}
return result;
}
}