diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/DisplayableEol.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/DisplayableEol.java index 2856155a33..bcab9a615b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/DisplayableEol.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/DisplayableEol.java @@ -183,6 +183,10 @@ public class DisplayableEol { } private String[] getPreviewForNoReferences() { + String translatedStringValue = getPreviewForString(); + if (translatedStringValue != null) { + return new String[] { translatedStringValue }; + } String undefinedPointerText = getUndefinedPointer(codeUnit); if (undefinedPointerText != null) { return new String[] { undefinedPointerText }; @@ -190,6 +194,17 @@ public class DisplayableEol { return new String[0]; } + private String getPreviewForString() { + if (codeUnit instanceof Data data && StringDataInstance.isString(data)) { + StringDataInstance sdi = StringDataInstance.getStringDataInstance(data); + if (sdi.hasTranslatedValue()) { + // show the opposite value + return sdi.getStringRepresentation(sdi.isShowTranslation()); + } + } + return null; + } + private boolean isValidReference(Program program, Reference reference) { if (!reference.isMemoryReference()) { 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 6fe5e58b46..cb21172b1b 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 @@ -15,15 +15,14 @@ */ package ghidra.program.model.data; -import static ghidra.program.model.data.EndianSettingsDefinition.ENDIAN; -import static ghidra.program.model.data.RenderUnicodeSettingsDefinition.RENDER; +import static ghidra.program.model.data.EndianSettingsDefinition.*; +import static ghidra.program.model.data.RenderUnicodeSettingsDefinition.*; import static ghidra.program.model.data.StringLayoutEnum.*; -import static ghidra.program.model.data.TranslationSettingsDefinition.TRANSLATION; - -import java.util.*; +import static ghidra.program.model.data.TranslationSettingsDefinition.*; import java.nio.*; import java.nio.charset.*; +import java.util.*; import generic.stl.Pair; import ghidra.docking.settings.*; @@ -759,10 +758,33 @@ public class StringDataInstance { *
* Example (quotes are part of result): {@code "Test\tstring",01,02,"Second\npart",00} * - * @return formatted String + * @return formatted String, or the translated value if present and the "show translated" + * setting is enabled for this string's location */ public String getStringRepresentation() { - return getStringRep(StringRenderBuilder.DOUBLE_QUOTE, StringRenderBuilder.DOUBLE_QUOTE); + return showTranslation && translatedValue != null + ? getTranslatedStringRepresentation(translatedValue) + : getStringRep(StringRenderBuilder.DOUBLE_QUOTE, StringRenderBuilder.DOUBLE_QUOTE); + } + + /** + * Returns a formatted version of the string returned by {@link #getStringValue()}. + *
+ * The resulting string will be formatted with quotes around the parts that contain plain ASCII + * alpha characters (and simple escape sequences), and out-of-range byte-ish values listed as + * comma separated hex-encoded values: + *
+ * Example (quotes are part of result): {@code "Test\tstring",01,02,"Second\npart",00} + * + * @param originalOrTranslated boolean flag, if true returns the representation of the + * string value, if false returns the representation of the translated value + * @return formatted String + */ + public String getStringRepresentation(boolean originalOrTranslated) { + return originalOrTranslated + ? getStringRep(StringRenderBuilder.DOUBLE_QUOTE, StringRenderBuilder.DOUBLE_QUOTE) + : translatedValue != null ? getTranslatedStringRepresentation(translatedValue) + : UNKNOWN; } private String getStringRep(char quoteChar, char quoteCharMulti) { @@ -771,10 +793,6 @@ public class StringDataInstance { return UNKNOWN; } - if (showTranslation && translatedValue != null) { - return getTranslatedStringRepresentation(translatedValue); - } - byte[] stringBytes = convertPaddedToUnpadded(getStringBytes()); if (stringBytes == null) { return UNKNOWN_DOT_DOT_DOT; @@ -911,6 +929,17 @@ public class StringDataInstance { return s.substring(0, lastGoodChar + 1); } + /** + * Returns true if this string has a translated value that could + * be displayed. + * + * @return boolean true if translated value is present, false if no + * value is present + */ + public boolean hasTranslatedValue() { + return translatedValue != null; + } + /** * Returns the value of the stored * {@link TranslationSettingsDefinition#getTranslatedValue(Data) translated settings}