mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GT-3530 update to single-char scalar rendering. Also corrected scalar
operand popup to be consistent with convert action.
This commit is contained in:
parent
fc5c68bc2b
commit
fe69d675d7
2 changed files with 29 additions and 28 deletions
|
@ -21,7 +21,6 @@ import ghidra.docking.settings.*;
|
|||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.Endian;
|
||||
import ghidra.program.model.listing.Data;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.ByteMemBufferImpl;
|
||||
|
@ -30,7 +29,6 @@ import ghidra.program.model.scalar.Scalar;
|
|||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.util.HTMLUtilities;
|
||||
import ghidra.util.StringUtilities;
|
||||
import utilities.util.ArrayUtilities;
|
||||
|
||||
/**
|
||||
* A hover service to show tool tip text for hovering over scalar values.
|
||||
|
@ -70,7 +68,7 @@ public abstract class AbstractScalarOperandHover extends AbstractConfigurableHov
|
|||
|
||||
private void formatIntegerTypes(Program program, Address addr, Scalar scalar,
|
||||
StringBuilder htmlText) {
|
||||
ByteMemBufferImpl memBuffer = getScalarOperandAsMemBuffer(addr, scalar, 1, Endian.BIG);
|
||||
ByteMemBufferImpl memBuffer = getScalarOperandAsMemBuffer(addr, scalar, 1);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
|
@ -120,12 +118,12 @@ public abstract class AbstractScalarOperandHover extends AbstractConfigurableHov
|
|||
String prevCharVal = "";
|
||||
StringBuilder localHTMLText = new StringBuilder();
|
||||
|
||||
Endian progEndian = program.getMemory().isBigEndian() ? Endian.BIG : Endian.LITTLE;
|
||||
// Endian progEndian = program.getMemory().isBigEndian() ? Endian.BIG : Endian.LITTLE;
|
||||
for (DataType charDt : charDataTypes) {
|
||||
// for each char data type, append its representation to the buffer, if it is
|
||||
// a new way to display the scalar
|
||||
ByteMemBufferImpl charMemBuffer =
|
||||
getScalarOperandAsMemBuffer(addr, scalar, charDt.getLength(), progEndian);
|
||||
getScalarOperandAsMemBuffer(addr, scalar, charDt.getLength());
|
||||
prevCharVal =
|
||||
appendCharDataTypeFormattedHTML(prevCharVal, charDt, charMemBuffer, localHTMLText);
|
||||
}
|
||||
|
@ -159,11 +157,6 @@ public abstract class AbstractScalarOperandHover extends AbstractConfigurableHov
|
|||
htmlText.append("<tr><td>") //
|
||||
.append(charDt.getName()) //
|
||||
.append(isArray ? "[]" : "");
|
||||
if (charMemBuffer.getLength() > 1) {
|
||||
htmlText.append(" <b>" +
|
||||
(charMemBuffer.isBigEndian() ? Endian.BIG : Endian.LITTLE).toShortString() +
|
||||
"</b>");
|
||||
}
|
||||
htmlText.append("</td><td>") //
|
||||
.append(HTMLUtilities.friendlyEncodeHTML(charRep)) //
|
||||
.append("</td></tr>");
|
||||
|
@ -225,15 +218,12 @@ public abstract class AbstractScalarOperandHover extends AbstractConfigurableHov
|
|||
}
|
||||
|
||||
private ByteMemBufferImpl getScalarOperandAsMemBuffer(Address addr, Scalar scalar,
|
||||
int minTrimLen, Endian endian) {
|
||||
int minTrimLen) {
|
||||
byte[] operandBytes = scalar.byteArrayValue();
|
||||
if (minTrimLen > 0) {
|
||||
operandBytes = trimLeadingZeros(operandBytes, minTrimLen);
|
||||
}
|
||||
if (endian == Endian.LITTLE) {
|
||||
operandBytes = ArrayUtilities.reverse(operandBytes);
|
||||
}
|
||||
return new ByteMemBufferImpl(addr, operandBytes, endian == Endian.BIG);
|
||||
return new ByteMemBufferImpl(addr, operandBytes, true);
|
||||
}
|
||||
|
||||
private static byte[] trimLeadingZeros(byte[] bytes, int minTrimLen) {
|
||||
|
|
|
@ -117,18 +117,8 @@ public class StringDataInstance {
|
|||
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] };
|
||||
}
|
||||
if (bytes.length != 1 && isSingleAsciiValue(bytes)) {
|
||||
bytes = new byte[] { bytes[bytes.length - 1] };
|
||||
}
|
||||
|
||||
MemBuffer memBuf = new ByteMemBufferImpl(null, bytes, true);
|
||||
|
@ -136,6 +126,27 @@ public class StringDataInstance {
|
|||
return sdi.getCharRepresentation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if bytes contain only a single ASCII value within
|
||||
* least-significant-byte of big-endian byte array
|
||||
* @param bytes value byte array in big-endian order
|
||||
* @return true if bytes contain a single ASCII value within
|
||||
* least-significant-byte
|
||||
*/
|
||||
private static boolean isSingleAsciiValue(byte[] bytes) {
|
||||
|
||||
int lsbIndex = bytes.length - 1;
|
||||
if (bytes[lsbIndex] < 0) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < lsbIndex; i++) {
|
||||
if (bytes[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link StringDataInstance} using the bytes in the data codeunit.
|
||||
* <p>
|
||||
|
@ -782,7 +793,7 @@ public class StringDataInstance {
|
|||
// render settings. ISO control chars are forced to be
|
||||
// escaped regardless of the render setting.
|
||||
if (currentCharRenderSetting == RENDER_ENUM.ALL) {
|
||||
if (codePoint <= 0x7f) {
|
||||
if (codePoint <= ASCII_MAX) {
|
||||
// render non-displayable, non-control-char ascii-ish bytes as bytes instead
|
||||
// of as escape sequences
|
||||
currentCharRenderSetting = RENDER_ENUM.BYTE_SEQ;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue