diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/ConvertToCharAction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/ConvertToCharAction.java index cd48969e34..fe446a1a1c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/ConvertToCharAction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/ConvertToCharAction.java @@ -48,8 +48,6 @@ public class ConvertToCharAction extends AbstractConvertAction { @Override protected String convertToString(Program program, Scalar scalar, boolean isData) { byte[] bytes = scalar.byteArrayValue(); - - return StringDataInstance.getCharRepresentation(ByteDataType.dataType, bytes, null, - program.getMemory().isBigEndian()); + return StringDataInstance.getCharRepresentation(ByteDataType.dataType, bytes, null); } } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/data/DataAction4Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/data/DataAction4Test.java index 2ea75aed19..058a6264a9 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/data/DataAction4Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/data/DataAction4Test.java @@ -818,7 +818,7 @@ public class DataAction4Test extends AbstractDataActionTest { d = getContextData(); assertEquals("ChooseFontW\0\u0015\0ReplaceTextW\0\0\u0004", d.getValue()); - assertEquals("\"ChooseFontW\\0\",15,\"\\0ReplaceTextW\\0\\0\",04", + assertEquals("\"ChooseFontW\\0\",15h,\"\\0ReplaceTextW\\0\\0\",04h", d.getDefaultValueRepresentation()); } @@ -851,7 +851,7 @@ public class DataAction4Test extends AbstractDataActionTest { assertEquals("\"ChooseFontW\"", d.getDefaultValueRepresentation()); d = checkNextData(dit, TerminatedStringDataType.class, 0x01006a0e, 2); - assertEquals("15", d.getDefaultValueRepresentation()); + assertEquals("15h", d.getDefaultValueRepresentation()); d = checkNextData(dit, TerminatedStringDataType.class, 0x01006a10, 13); assertEquals("ReplaceTextW", d.getValue()); @@ -862,7 +862,7 @@ public class DataAction4Test extends AbstractDataActionTest { assertEquals("\"\"", d.getDefaultValueRepresentation()); d = checkNextData(dit, TerminatedStringDataType.class, 0x01006a1e, 2); - assertEquals("04", d.getDefaultValueRepresentation()); + assertEquals("04h", d.getDefaultValueRepresentation()); } @Test @@ -890,7 +890,7 @@ public class DataAction4Test extends AbstractDataActionTest { checkOnDefined(null, UnicodeDataType.class); d = getContextData(); - assertEquals("01,00,\"\\0Sample\"", d.getDefaultValueRepresentation()); + assertEquals("01h,00h,\"\\0Sample\"", d.getDefaultValueRepresentation()); assertEquals("\1\0Sample", d.getValue()); } @@ -925,7 +925,7 @@ public class DataAction4Test extends AbstractDataActionTest { // check for wchar16[2] garbage string d = checkNextData(dit, TerminatedUnicodeDataType.class, 0x01008014, 4); assertEquals(d.getLength(), 4); - assertEquals("01,00", d.getDefaultValueRepresentation()); + assertEquals("01h,00h", d.getDefaultValueRepresentation()); assertEquals("\1", d.getValue()); // check for "Sample" string diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquatePlugin1Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquatePlugin1Test.java index 340ad37bc5..ed7d244862 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquatePlugin1Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/equate/EquatePlugin1Test.java @@ -1175,7 +1175,7 @@ public class EquatePlugin1Test extends AbstractEquatePluginTest { performAction("Convert To Char"); ListingTextField tf = (ListingTextField) cb.getCurrentField(); - assertEquals("'\\x02'", tf.getFieldElement(0, 11).getText()); + assertEquals("02h", tf.getFieldElement(0, 11).getText()); undo(program); tf = (ListingTextField) cb.getCurrentField(); @@ -1184,7 +1184,7 @@ public class EquatePlugin1Test extends AbstractEquatePluginTest { redo(program); tf = (ListingTextField) cb.getCurrentField(); - assertEquals("'\\x02'", tf.getFieldElement(0, 11).getText()); + assertEquals("02h", tf.getFieldElement(0, 11).getText()); } @Test diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractIntegerDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractIntegerDataType.java index b8457fe14e..f2b22e519c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractIntegerDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractIntegerDataType.java @@ -173,14 +173,8 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt return null; } - boolean isBigEndian = ENDIAN.isBigEndian(settings, buf); - - if (!isBigEndian) { - byte[] flipped = new byte[size]; - for (int i = 0; i < size; i++) { - flipped[i] = bytes[size - i - 1]; - } - bytes = flipped; + if (!ENDIAN.isBigEndian(settings, buf)) { + bytes = ArrayUtilities.reverse(bytes); } if (size > 8) { @@ -225,16 +219,17 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt return "??"; } - boolean isLE = !ENDIAN.isBigEndian(settings, buf); - if (isLE) { + if (!ENDIAN.isBigEndian(settings, buf)) { bytes = ArrayUtilities.reverse(bytes); } + BigInteger value = new BigInteger(bytes); + if (getFormatSettingsDefinition().getFormat(settings) == FormatSettingsDefinition.CHAR) { - return StringDataInstance.getCharRepresentation(this, bytes, settings, !isLE); + return StringDataInstance.getCharRepresentation(this, bytes, settings); } - return getRepresentation(new BigInteger(bytes), settings, 8 * length); + return getRepresentation(value, settings, 8 * length); } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldDataType.java index 756f9dcc73..387ca34473 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldDataType.java @@ -366,11 +366,21 @@ public class BitFieldDataType extends AbstractDataType { return big; } - public BigInteger getBigIntegerValue(MemBuffer buf, Settings settings) { + private BigInteger getBigIntegerValue(MemBuffer buf, Settings settings) { if (effectiveBitSize == 0) { return BigInteger.ZERO; } try { + + byte[] bytes = new byte[storageSize]; + if (buf.getBytes(bytes, 0) != storageSize) { + return null; + } + + if (!EndianSettingsDefinition.ENDIAN.isBigEndian(settings, buf)) { + bytes = ArrayUtilities.reverse(bytes); + } + BigInteger big = buf.getBigInteger(0, storageSize, false); BigInteger pow = BigInteger.valueOf(2).pow(effectiveBitSize); BigInteger mask = pow.subtract(BigInteger.ONE); @@ -415,12 +425,8 @@ public class BitFieldDataType extends AbstractDataType { } int bytesLen = BitFieldDataType.getMinimumStorageSize(bitSize); byte[] bytes = DataConverter.getInstance(buf.isBigEndian()).getBytes(big, bytesLen); - if (!EndianSettingsDefinition.ENDIAN.isBigEndian(settings, buf)) { - bytes = ArrayUtilities.reverse(bytes); - } - return StringDataInstance.getCharRepresentation(this, bytes, settings, - buf.isBigEndian()); + return StringDataInstance.getCharRepresentation(this, bytes, settings); } return intDT.getRepresentation(big, settings, effectiveBitSize); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StringDataInstance.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StringDataInstance.java index 9e4120b14d..d23b38962a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StringDataInstance.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StringDataInstance.java @@ -44,6 +44,9 @@ import ghidra.util.*; *

*/ public class StringDataInstance { + + private static final int ASCII_MAX = 0x7f; + /** * Returns true if the {@link Data} instance is a 'string'. * @@ -83,7 +86,7 @@ public class StringDataInstance { return dt instanceof AbstractStringDataType || (dt instanceof Array && ArrayStringable.getArrayStringable(((Array) dt).getDataType()) != null); } - + /** * Returns true if the {@link Data} instance is one of the many 'char' data types. * @@ -105,16 +108,31 @@ public class StringDataInstance { *

* * @param dataType the {@link DataType} of the element containing the bytes (most likely a ByteDataType) - * @param bytes the bytes to convert + * @param bytes the big-endian ordered bytes to convert to a char representation * @param settings the {@link Settings} object for the location where the bytes came from, or null - * @param isBigEndian boolean flag indicating data is big endian * @return formatted string (typically with quotes around the contents): single character: 'a', multiple characters: "a\x12bc" */ - public static String getCharRepresentation(DataType dataType, byte[] bytes, Settings settings, - boolean isBigEndian) { - MemBuffer memBuf = new ByteMemBufferImpl(null, bytes, isBigEndian); - StringDataInstance sdi = - new StringDataInstance(dataType, settings, memBuf, bytes.length); + public static String getCharRepresentation(DataType dataType, byte[] bytes, Settings settings) { + if (bytes == null || bytes.length == 0) { + return UNKNOWN; + } + + // ignore leading 0 bytes + int lsbIndex = bytes.length - 1; + if (bytes[lsbIndex] >= 0 && bytes[lsbIndex] <= 0x7f) { + boolean isAsciiChar = true; + for (int i = 0; i < lsbIndex; i++) { + if (bytes[i] != 0) { + isAsciiChar = false; + } + } + if (isAsciiChar) { + bytes = new byte[] { bytes[lsbIndex] }; + } + } + + MemBuffer memBuf = new ByteMemBufferImpl(null, bytes, true); + StringDataInstance sdi = new StringDataInstance(dataType, settings, memBuf, bytes.length); return sdi.getCharRepresentation(); }