Skip to content

Commit 84fda70

Browse files
committed
Merge remote-tracking branch 'origin/GT-3347_dev747368_PR-1241_agatti_convert_char_seq'
2 parents d2fc8cd + 3718edc commit 84fda70

File tree

20 files changed

+322
-293
lines changed

20 files changed

+322
-293
lines changed

Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/hover/DataTypeListingHover.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ private String getLocationSupplimentalToolTipText(DataType dt, Data dataInstance
146146
result += String.format("<br>Translated value: %s",
147147
HTMLUtilities.friendlyEncodeHTML(sdi.getTranslatedValue()));
148148
}
149-
if (!sdi.isPascal() && !sdi.hasNullTerminator()) {
149+
if (sdi.isMissingNullTerminator()) {
150150
result += "<br>Missing NULL terminator.";
151151
}
152152
if (sdi.getStringLength() > dataInstance.getLength()) {

Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/equate/ConvertToCharAction.java

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616
package ghidra.app.plugin.core.equate;
1717

1818
import ghidra.docking.settings.FormatSettingsDefinition;
19+
import ghidra.program.model.data.ByteDataType;
20+
import ghidra.program.model.data.StringDataInstance;
1921
import ghidra.program.model.listing.Program;
2022
import ghidra.program.model.scalar.Scalar;
21-
import ghidra.util.StringUtilities;
2223

2324
public class ConvertToCharAction extends AbstractConvertAction {
2425
public static final String ACTION_NAME = "Convert To Char";
@@ -46,27 +47,9 @@ protected int getFormatChoice() {
4647

4748
@Override
4849
protected String convertToString(Program program, Scalar scalar, boolean isData) {
49-
long value = scalar.getUnsignedValue();
50-
if (value >= 0 && value <= 255) {
51-
return StringUtilities.toQuotedString(new byte[] { (byte) value });
52-
}
53-
5450
byte[] bytes = scalar.byteArrayValue();
55-
if (!program.getMemory().isBigEndian()) {
56-
// assume we want to see characters as they would appear
57-
// if read from memory one byte at a time
58-
reverseBytes(bytes);
59-
}
60-
return StringUtilities.toQuotedString(bytes);
61-
}
6251

63-
private void reverseBytes(byte[] bytes) {
64-
int n = bytes.length / 2;
65-
int j = bytes.length - 1;
66-
for (int i = 0; i < n; i++, j--) {
67-
byte b = bytes[i];
68-
bytes[i] = bytes[j];
69-
bytes[j] = b;
70-
}
52+
return StringDataInstance.getCharRepresentation(ByteDataType.dataType, bytes, null,
53+
program.getMemory().isBigEndian());
7154
}
7255
}

Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/hover/AbstractScalarOperandHover.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ protected String formatScalar(Program program, Address addr, Scalar scalar) {
221221

222222
private boolean hasEncodingError(String s) {
223223
return s.codePoints().anyMatch(
224-
codePoint -> StringUtilities.isUnicodeReplacementCodePoint(codePoint));
224+
codePoint -> codePoint == StringUtilities.UNICODE_REPLACEMENT);
225225
}
226226

227227
private ByteMemBufferImpl getScalarOperandAsMemBuffer(Address addr, Scalar scalar,

Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/string/StringTableProvider.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,8 +568,9 @@ private void updatePreview() {
568568
FoundString foundString = stringModel.getRowObject(table.getSelectedRow());
569569
MemBuffer membuf =
570570
new DumbMemBufferImpl(currentProgram.getMemory(), foundString.getAddress());
571-
StringDataInstance stringInstance = new StringDataInstance(foundString.getDataType(),
572-
SettingsImpl.NO_SETTINGS, membuf, foundString.getLength());
571+
StringDataInstance stringInstance =
572+
StringDataInstance.getStringDataInstance(foundString.getDataType(), membuf,
573+
SettingsImpl.NO_SETTINGS, foundString.getLength());
573574
if (charOffset != 0) {
574575
stringInstance = stringInstance.getCharOffcut(charOffset);
575576
}

Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/strings/HasEncodingErrorColumnConstraint.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public class HasEncodingErrorColumnConstraint extends StringDataInstanceColumnCo
3232
public boolean accepts(StringDataInstance value, TableFilterContext context) {
3333
String s = value.getStringValue();
3434
return (s != null) && s.chars().anyMatch(
35-
codePoint -> StringUtilities.isUnicodeReplacementCodePoint(codePoint));
35+
codePoint -> codePoint == StringUtilities.UNICODE_REPLACEMENT);
3636
}
3737

3838
@Override

Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/strings/ViewStringsTableModel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ public Boolean getValue(ProgramLocation rowObject, Settings settings, Program pr
361361
String s = StringDataInstance.getStringDataInstance(data).getStringValue();
362362

363363
return (s != null) && s.chars().anyMatch(
364-
codePoint -> StringUtilities.isUnicodeReplacementCodePoint(codePoint));
364+
codePoint -> codePoint == StringUtilities.UNICODE_REPLACEMENT);
365365
}
366366

367367
@Override

Ghidra/Framework/Generic/src/main/java/ghidra/util/StringUtilities.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,16 +1081,4 @@ public static String convertCodePointToEscapeSequence(int codePoint) {
10811081
}
10821082
return new String(new int[] { codePoint }, 0, 1);
10831083
}
1084-
1085-
/**
1086-
* Returns true if the specified code point is the 'replacement' code point 0xFFFD,
1087-
* which is used when decoding bytes into unicode chars and there was a bad or invalid
1088-
* sequence that does not have a mapping. (ie. decoding byte char 0x80 as US-ASCII)
1089-
*
1090-
* @param codePoint to test
1091-
* @return boolean true if the char is 0xFFFD (ie. UNICODE REPLACEMENT char)
1092-
*/
1093-
public static boolean isUnicodeReplacementCodePoint(int codePoint) {
1094-
return codePoint == UNICODE_REPLACEMENT;
1095-
}
10961084
}

Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractIntegerDataType.java

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
import java.math.BigInteger;
1919

2020
import ghidra.docking.settings.*;
21-
import ghidra.program.model.mem.ByteMemBufferImpl;
2221
import ghidra.program.model.mem.MemBuffer;
2322
import ghidra.program.model.scalar.Scalar;
2423
import ghidra.util.StringFormat;
24+
import utilities.util.ArrayUtilities;
2525

2626
/**
2727
* Base type for integer data types such as {@link CharDataType chars}, {@link IntegerDataType ints},
@@ -225,27 +225,29 @@ public String getRepresentation(MemBuffer buf, Settings settings, int length) {
225225
return "??";
226226
}
227227

228-
boolean isBigEndian = ENDIAN.isBigEndian(settings, buf);
228+
boolean isLE = !ENDIAN.isBigEndian(settings, buf);
229+
if (isLE) {
230+
bytes = ArrayUtilities.reverse(bytes);
231+
}
229232

230-
if (!isBigEndian) {
231-
byte[] flipped = new byte[size];
232-
for (int i = 0; i < size; i++) {
233-
flipped[i] = bytes[size - i - 1];
234-
}
235-
bytes = flipped;
233+
if (getFormatSettingsDefinition().getFormat(settings) == FormatSettingsDefinition.CHAR) {
234+
return StringDataInstance.getCharRepresentation(this, bytes, settings, !isLE);
236235
}
237236

238237
return getRepresentation(new BigInteger(bytes), settings, 8 * length);
239238
}
240239

241240
/**
242241
* Get integer representation of the big-endian value.
242+
* <p>
243+
* Does not handle CHAR format, use {@link StringDataInstance#getCharRepresentation(DataType, byte[], Settings)}
244+
*
243245
* @param bigInt BigInteger value with the appropriate sign
244246
* @param settings integer format settings (PADDING, FORMAT, etc.)
245247
* @param bitLength number of value bits to be used from bigInt
246248
* @return formatted integer string
247249
*/
248-
public String getRepresentation(BigInteger bigInt, Settings settings, int bitLength) {
250+
/*package*/ String getRepresentation(BigInteger bigInt, Settings settings, int bitLength) {
249251

250252
int format = getFormatSettingsDefinition().getFormat(settings);
251253
boolean padded = PADDING.isPadded(settings);
@@ -257,29 +259,8 @@ public String getRepresentation(BigInteger bigInt, Settings settings, int bitLen
257259
bigInt = bigInt.add(BigInteger.valueOf(2).pow(bitLength));
258260
}
259261

260-
int nominalLen;
261-
262-
if (format == FormatSettingsDefinition.CHAR) {
263-
int charSize = Math.min(getDataOrganization().getCharSize(), getLength());
264-
nominalLen = (bitLength + 7) / 8;
265-
byte[] bytes = bigInt.toByteArray();
266-
if (bytes.length > nominalLen) {
267-
// BigInteger supplied too many bytes
268-
byte[] chars = new byte[nominalLen];
269-
System.arraycopy(bytes, bytes.length - nominalLen, chars, 0, nominalLen);
270-
bytes = chars;
271-
}
272-
else if (bytes.length < nominalLen) {
273-
// BigInteger supplied too few bytes
274-
byte[] chars = new byte[nominalLen];
275-
System.arraycopy(bytes, 0, chars, nominalLen - bytes.length, bytes.length);
276-
bytes = chars;
277-
}
278-
MemBuffer memBuf = new ByteMemBufferImpl(null, bytes, true);
279-
return new StringDataInstance(this, settings, memBuf, charSize).getCharRepresentation();
280-
}
281-
282262
String valStr;
263+
int nominalLen;
283264

284265
switch (format) {
285266
default:
@@ -316,7 +297,7 @@ public boolean hasStringValue(Settings settings) {
316297
public String getArrayDefaultLabelPrefix(MemBuffer buf, Settings settings, int len,
317298
DataTypeDisplayOptions options) {
318299
if (hasStringValue(settings) && buf.isInitializedMemory()) {
319-
return new StringDataInstance(this, settings, buf, len).getLabel(
300+
return new StringDataInstance(this, settings, buf, len, true).getLabel(
320301
AbstractStringDataType.DEFAULT_ABBREV_PREFIX + "_",
321302
AbstractStringDataType.DEFAULT_LABEL_PREFIX, AbstractStringDataType.DEFAULT_LABEL,
322303
options);
@@ -328,7 +309,7 @@ public String getArrayDefaultLabelPrefix(MemBuffer buf, Settings settings, int l
328309
public String getArrayDefaultOffcutLabelPrefix(MemBuffer buf, Settings settings, int len,
329310
DataTypeDisplayOptions options, int offcutOffset) {
330311
if (hasStringValue(settings) && buf.isInitializedMemory()) {
331-
return new StringDataInstance(this, settings, buf, len).getOffcutLabelString(
312+
return new StringDataInstance(this, settings, buf, len, true).getOffcutLabelString(
332313
AbstractStringDataType.DEFAULT_ABBREV_PREFIX + "_",
333314
AbstractStringDataType.DEFAULT_LABEL_PREFIX, AbstractStringDataType.DEFAULT_LABEL,
334315
options, offcutOffset);

Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/AbstractStringDataType.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
*/
1616
package ghidra.program.model.data;
1717

18-
import static ghidra.program.model.data.CharsetSettingsDefinition.CHARSET;
19-
import static ghidra.program.model.data.RenderUnicodeSettingsDefinition.RENDER;
20-
import static ghidra.program.model.data.TranslationSettingsDefinition.TRANSLATION;
18+
import static ghidra.program.model.data.CharsetSettingsDefinition.*;
19+
import static ghidra.program.model.data.RenderUnicodeSettingsDefinition.*;
20+
import static ghidra.program.model.data.TranslationSettingsDefinition.*;
2121

2222
import ghidra.docking.settings.*;
2323
import ghidra.program.model.mem.MemBuffer;
@@ -28,7 +28,7 @@
2828
* See {@link StringDataType} for information about string variations and configuration details.
2929
* <p>
3030
* Sub-classes generally only need to implement a constructor that calls the mega-constructor
31-
* {@link #AbstractStringDataType(String, String, String, String, String, String, String, DataType, StringLayoutEnum, DataTypeManager) AbstractStringDataType.SAbstractStringDataType(lots,of,params)}
31+
* {@link #AbstractStringDataType(String, String, String, String, String, String, String, DataType, StringLayoutEnum, DataTypeManager) AbstractStringDataType.AbstractStringDataType(lots,of,params)}
3232
* and the {@link DataType#clone(DataTypeManager) } method.
3333
* <p>
3434
*

Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/Array.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ default public String getArrayRepresentation(MemBuffer buf, Settings settings, i
105105
ArrayStringable stringableElementType = ArrayStringable.getArrayStringable(getDataType());
106106
String value =
107107
(stringableElementType != null && stringableElementType.hasStringValue(settings))
108-
? new StringDataInstance(stringableElementType, settings, buf,
109-
length).getStringRepresentation()
110-
: null;
108+
? new StringDataInstance(stringableElementType, settings, buf, length,
109+
true).getStringRepresentation()
110+
: null;
111111
return (value != null) ? value : "";
112112
}
113113

Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/ArrayStringable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public interface ArrayStringable extends DataType {
4747
*/
4848
public default String getArrayString(MemBuffer buf, Settings settings, int length) {
4949
if (hasStringValue(settings) && buf.isInitializedMemory()) {
50-
return new StringDataInstance(this, settings, buf, length).getStringValue();
50+
return new StringDataInstance(this, settings, buf, length, true).getStringValue();
5151
}
5252
return null;
5353
}

Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/BitFieldDataType.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717

1818
import java.math.BigInteger;
1919

20-
import ghidra.docking.settings.Settings;
21-
import ghidra.docking.settings.SettingsDefinition;
20+
import ghidra.docking.settings.*;
2221
import ghidra.program.model.mem.MemBuffer;
2322
import ghidra.program.model.scalar.Scalar;
23+
import ghidra.util.DataConverter;
2424
import ghidra.util.exception.AssertException;
25+
import utilities.util.ArrayUtilities;
2526

2627
/**
2728
* <code>BitFieldDataType</code> provides a means of defining a minimally sized bit-field
@@ -406,7 +407,23 @@ public String getRepresentation(MemBuffer buf, Settings settings, int length) {
406407
if (dt instanceof Enum) {
407408
return ((Enum) dt).getRepresentation(big, settings, effectiveBitSize);
408409
}
409-
return ((AbstractIntegerDataType) dt).getRepresentation(big, settings, effectiveBitSize);
410+
AbstractIntegerDataType intDT = (AbstractIntegerDataType) dt;
411+
if (intDT.getFormatSettingsDefinition().getFormat(
412+
settings) == FormatSettingsDefinition.CHAR) {
413+
if (big.signum() < 0) {
414+
big = big.add(BigInteger.valueOf(2).pow(bitSize));
415+
}
416+
int bytesLen = BitFieldDataType.getMinimumStorageSize(bitSize);
417+
byte[] bytes = DataConverter.getInstance(buf.isBigEndian()).getBytes(big, bytesLen);
418+
if (!EndianSettingsDefinition.ENDIAN.isBigEndian(settings, buf)) {
419+
bytes = ArrayUtilities.reverse(bytes);
420+
}
421+
422+
return StringDataInstance.getCharRepresentation(this, bytes, settings,
423+
buf.isBigEndian());
424+
}
425+
426+
return intDT.getRepresentation(big, settings, effectiveBitSize);
410427
}
411428

412429
@Override

0 commit comments

Comments
 (0)