blob: 8fff8ee4ee8719936f8df101e1c9bc84efc00a6f [file] [log] [blame]
/*
* Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger;
/** Common routines for data conversion */
public class DebuggerUtilities {
protected long addressSize;
protected boolean isBigEndian;
public DebuggerUtilities(long addressSize, boolean isBigEndian) {
this.addressSize = addressSize;
this.isBigEndian = isBigEndian;
}
public String addressValueToString(long address) {
StringBuffer buf = new StringBuffer();
buf.append("0x");
String val;
// Make negative addresses have the correct size
if (addressSize == 8) {
val = Long.toHexString(address);
} else {
val = Integer.toHexString((int) address);
}
for (int i = 0; i < ((2 * addressSize) - val.length()); i++) {
buf.append('0');
}
buf.append(val);
return buf.toString();
}
public void checkAlignment(long address, long alignment) {
if (address % alignment != 0) {
throw new UnalignedAddressException("Trying to read at address: " +
addressValueToString(address) +
" with alignment: " + alignment,
address);
}
}
public long scanAddress(String addrStr) throws NumberFormatException {
String s = addrStr.trim();
if (!s.startsWith("0x")) {
throw new NumberFormatException(addrStr);
}
long l = 0;
for (int i = 2; i < s.length(); ++i) {
int val = charToNibble(s.charAt(i));
l <<= 4;
l |= val;
}
return l;
}
public int charToNibble(char ascii) throws NumberFormatException {
if (ascii >= '0' && ascii <= '9') {
return ascii - '0';
} else if (ascii >= 'A' && ascii <= 'F') {
return 10 + ascii - 'A';
} else if (ascii >= 'a' && ascii <= 'f') {
return 10 + ascii - 'a';
}
throw new NumberFormatException(new Character(ascii).toString());
}
public boolean dataToJBoolean(byte[] data, long jbooleanSize) {
checkDataContents(data, jbooleanSize);
return (data[0] != 0);
}
public byte dataToJByte(byte[] data, long jbyteSize) {
checkDataContents(data, jbyteSize);
return data[0];
}
public char dataToJChar(byte[] data, long jcharSize) {
checkDataContents(data, jcharSize);
if (!isBigEndian) {
byteSwap(data);
}
return (char) (((data[0] & 0xFF) << 8) | (data[1] & 0xFF));
}
public double dataToJDouble(byte[] data, long jdoubleSize) {
long longBits = dataToJLong(data, jdoubleSize);
return Double.longBitsToDouble(longBits);
}
public float dataToJFloat(byte[] data, long jfloatSize) {
int intBits = dataToJInt(data, jfloatSize);
return Float.intBitsToFloat(intBits);
}
public int dataToJInt(byte[] data, long jintSize) {
checkDataContents(data, jintSize);
if (!isBigEndian) {
byteSwap(data);
}
return (((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16) | ((data[2] & 0xFF) << 8) | (data[3] & 0xFF));
}
public long dataToJLong(byte[] data, long jlongSize) {
checkDataContents(data, jlongSize);
if (!isBigEndian) {
byteSwap(data);
}
return rawDataToJLong(data);
}
public short dataToJShort(byte[] data, long jshortSize) {
checkDataContents(data, jshortSize);
if (!isBigEndian) {
byteSwap(data);
}
return (short) (((data[0] & 0xFF) << 8) | (data[1] & 0xFF));
}
public long dataToCInteger(byte[] data, boolean isUnsigned) {
checkDataContents(data, data.length);
if (!isBigEndian) {
byteSwap(data);
}
// By default we'll be zero-extending.
// Therefore we need to check to see whether isUnsigned is false and
// also the high bit of the data is set.
if ((data.length < 8) &&
(isUnsigned == false) &&
((data[0] & 0x80) != 0)) {
// Must sign-extend and right-align the data
byte[] newData = new byte[8];
for (int i = 0; i < 8; ++i) {
if ((7 - i) < data.length) {
newData[i] = data[i + data.length - 8];
} else {
newData[i] = (byte) 0xFF;
}
}
data = newData;
}
// Now just do the usual loop
return rawDataToJLong(data);
}
public long dataToAddressValue(byte[] data) {
checkDataContents(data, addressSize);
if (!isBigEndian) {
byteSwap(data);
}
return rawDataToJLong(data);
}
public byte[] jbooleanToData(boolean value) {
byte[] res = new byte[1];
res[0] = (byte) (value ? 1 : 0);
return res;
}
public byte[] jbyteToData(byte value) {
byte[] res = new byte[1];
res[0] = value;
return res;
}
public byte[] jcharToData(char value) {
byte[] res = new byte[2];
res[0] = (byte) ((value >> 8) & 0xFF);
res[1] = (byte) value;
if (!isBigEndian) {
byteSwap(res);
}
return res;
}
public byte[] jdoubleToData(double value) {
return jlongToData(Double.doubleToLongBits(value));
}
public byte[] jfloatToData(float value) {
return jintToData(Float.floatToIntBits(value));
}
public byte[] jintToData(int value) {
byte[] res = new byte[4];
for (int i = 0; i < 4; i++) {
res[3 - i] = (byte) (value & 0xFF);
value >>>= 8;
}
if (!isBigEndian) {
byteSwap(res);
}
return res;
}
public byte[] jlongToData(long value) {
byte[] res = new byte[8];
for (int i = 0; i < 8; i++) {
res[7 - i] = (byte) (value & 0xFF);
value >>>= 8;
}
if (!isBigEndian) {
byteSwap(res);
}
return res;
}
public byte[] jshortToData(short value) {
byte[] res = new byte[2];
res[0] = (byte) ((value >> 8) & 0xFF);
res[1] = (byte) value;
if (!isBigEndian) {
byteSwap(res);
}
return res;
}
public byte[] cIntegerToData(long longNumBytes, long value) {
int numBytes = (int) longNumBytes;
byte[] res = new byte[numBytes];
for (int i = 0; i < numBytes; i++) {
res[numBytes - i - 1] = (byte) (value & 0xFF);
value >>>= 8;
}
if (!isBigEndian) {
byteSwap(res);
}
return res;
}
//--------------------------------------------------------------------------------
// Internals only below this point
//
private void checkDataContents(byte[] data, long len) {
if (data.length != (int) len) {
throw new InternalError("Bug in Win32Debugger");
}
}
private void byteSwap(byte[] data) {
for (int i = 0; i < (data.length / 2); ++i) {
int altIndex = data.length - i - 1;
byte t = data[altIndex];
data[altIndex] = data[i];
data[i] = t;
}
}
private long rawDataToJLong(byte[] data) {
long addr = 0;
for (int i = 0; i < data.length; ++i) {
addr <<= 8;
addr |= data[i] & 0xFF;
}
return addr;
}
}