mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-24 21:21:56 +00:00
GT-2715 Fix stringable arrays label text generation with uninit mem.
(#272) Check for uninitialized memory before treating as a string.
This commit is contained in:
parent
26b2dfef94
commit
dd7ffda876
@ -57,7 +57,7 @@ class ArrayDB extends DataTypeDB implements Array {
|
||||
|
||||
@Override
|
||||
public Class<?> getValueClass(Settings settings) {
|
||||
return DataTypeUtilities.getArrayValueClass(this, settings);
|
||||
return getArrayValueClass(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -354,18 +354,13 @@ class ArrayDB extends DataTypeDB implements Array {
|
||||
@Override
|
||||
public String getDefaultLabelPrefix(MemBuffer buf, Settings settings, int len,
|
||||
DataTypeDisplayOptions options) {
|
||||
String prefix =
|
||||
ArrayStringable.getArrayStringableLabelPrefix(this, buf, settings, len, options);
|
||||
return prefix != null ? prefix : super.getDefaultLabelPrefix(buf, settings, len, options);
|
||||
return getArrayDefaultLabelPrefix(buf, settings, len, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultOffcutLabelPrefix(MemBuffer buf, Settings settings, int len,
|
||||
DataTypeDisplayOptions options, int offcutLength) {
|
||||
String prefix = ArrayStringable.getArrayStringableOffcutLabelPrefix(this, buf, settings,
|
||||
len, options, offcutLength);
|
||||
return prefix != null ? prefix
|
||||
: super.getDefaultOffcutLabelPrefix(buf, settings, len, options, offcutLength);
|
||||
return getArrayDefaultOffcutLabelPrefix(buf, settings, len, options, offcutLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -411,11 +406,11 @@ class ArrayDB extends DataTypeDB implements Array {
|
||||
|
||||
@Override
|
||||
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||
return DataTypeUtilities.getArrayValue(this, buf, settings, length);
|
||||
return getArrayValue(buf, settings, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||
return DataTypeUtilities.getArrayRepresentation(this, buf, settings, length);
|
||||
return getArrayRepresentation(buf, settings, length);
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,6 @@ import ghidra.program.model.address.GlobalNamespace;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.data.Enum;
|
||||
import ghidra.program.model.listing.Library;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.program.model.symbol.Namespace;
|
||||
import ghidra.util.UniversalID;
|
||||
import ghidra.util.exception.AssertException;
|
||||
@ -319,87 +317,6 @@ public class DataTypeUtilities {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value object which corresponds to an array in memory. This will either be a
|
||||
* String for the ArrayStringable case or null.
|
||||
* @param arrayDt array data type
|
||||
* @param buf data buffer
|
||||
* @param settings data settings
|
||||
* @param length length of array
|
||||
* @return a String if it is an array of chars; otherwise null.
|
||||
*/
|
||||
public static Object getArrayValue(Array arrayDt, MemBuffer buf, Settings settings,
|
||||
int length) {
|
||||
if (!buf.getMemory().getAllInitializedAddressSet().contains(buf.getAddress())) {
|
||||
return null;
|
||||
}
|
||||
ArrayStringable as = ArrayStringable.getArrayStringable(arrayDt.getDataType());
|
||||
Object value = (as != null) ? as.getArrayString(buf, settings, length) : null;
|
||||
|
||||
return value;
|
||||
// TODO
|
||||
// For large array it is not scalable to create a java array object. Perhaps
|
||||
// we could create a GhidraArray that can dish out objects.
|
||||
// DataType dt = arrayDt.getDataType();
|
||||
// Class<?> valueClass = dt.getValueClass(settings);
|
||||
// if (valueClass != null) {
|
||||
// int count = arrayDt.getNumElements();
|
||||
// int elementLength = arrayDt.getElementLength();
|
||||
// WrappedMemBuffer wrappedBuffer = new WrappedMemBuffer(buf, 0);
|
||||
// Object[] array = (Object[]) java.lang.reflect.Array.newInstance(valueClass, count);
|
||||
// for (int i = 0; i < count; i++) {
|
||||
// wrappedBuffer.setBaseOffset(i * elementLength);
|
||||
// array[i] = dt.getValue(wrappedBuffer, settings, elementLength);
|
||||
// }
|
||||
// return array;
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the representation which corresponds to an array in memory. This will either be a
|
||||
* String for the ArrayStringable case or the empty string if it is not.
|
||||
*
|
||||
* @param arrayDt array data type
|
||||
* @param buf data buffer
|
||||
* @param settings data settings
|
||||
* @param length length of array
|
||||
* @return a String if it is an array of chars; otherwise empty string, never null.
|
||||
*/
|
||||
public static String getArrayRepresentation(Array arrayDt, MemBuffer buf, Settings settings,
|
||||
int length) {
|
||||
try {
|
||||
buf.getByte(0); // test for uninitialized memory
|
||||
ArrayStringable as = ArrayStringable.getArrayStringable(arrayDt.getDataType());
|
||||
String value = (as != null) ? as.getArrayRepresentation(buf, settings, length) : null;
|
||||
return (value != null) ? value : "";
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
// ignore
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value Class of a specific arrayDt with settings
|
||||
* ( see {@link #getArrayValueClass(Array, Settings)} ).
|
||||
* @param settings the relevant settings to use or null for default.
|
||||
* @return Class of the value to be returned by the array or null if it can vary
|
||||
* or is unspecified (String or Array class will be returned).
|
||||
*/
|
||||
public static Class<?> getArrayValueClass(Array arrayDt, Settings settings) {
|
||||
DataType dt = arrayDt.getDataType();
|
||||
if (dt instanceof TypeDef) {
|
||||
dt = ((TypeDef) dt).getBaseDataType();
|
||||
}
|
||||
if (dt instanceof ArrayStringable) {
|
||||
if (((ArrayStringable) dt).hasStringValue(settings)) {
|
||||
return String.class;
|
||||
}
|
||||
}
|
||||
Class<?> valueClass = dt.getValueClass(settings);
|
||||
return valueClass != null ? Array.class : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a data type category path derived from the specified namespace and rooted from
|
||||
* the specified baseCategory
|
||||
|
@ -330,25 +330,25 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
|
||||
@Override
|
||||
public String getArrayDefaultLabelPrefix(MemBuffer buf, Settings settings, int len,
|
||||
DataTypeDisplayOptions options) {
|
||||
if (!hasStringValue(settings)) {
|
||||
return null;
|
||||
if (hasStringValue(settings) && buf.isInitializedMemory()) {
|
||||
return new StringDataInstance(this, settings, buf, len).getLabel(
|
||||
AbstractStringDataType.DEFAULT_ABBREV_PREFIX + "_",
|
||||
AbstractStringDataType.DEFAULT_LABEL_PREFIX, AbstractStringDataType.DEFAULT_LABEL,
|
||||
options);
|
||||
}
|
||||
return new StringDataInstance(this, settings, buf, len).getLabel(
|
||||
AbstractStringDataType.DEFAULT_ABBREV_PREFIX + "_",
|
||||
AbstractStringDataType.DEFAULT_LABEL_PREFIX, AbstractStringDataType.DEFAULT_LABEL,
|
||||
options);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArrayDefaultOffcutLabelPrefix(MemBuffer buf, Settings settings, int len,
|
||||
DataTypeDisplayOptions options, int offcutOffset) {
|
||||
if (!hasStringValue(settings)) {
|
||||
return null;
|
||||
if (hasStringValue(settings) && buf.isInitializedMemory()) {
|
||||
return new StringDataInstance(this, settings, buf, len).getOffcutLabelString(
|
||||
AbstractStringDataType.DEFAULT_ABBREV_PREFIX + "_",
|
||||
AbstractStringDataType.DEFAULT_LABEL_PREFIX, AbstractStringDataType.DEFAULT_LABEL,
|
||||
options, offcutOffset);
|
||||
}
|
||||
return new StringDataInstance(this, settings, buf, len).getOffcutLabelString(
|
||||
AbstractStringDataType.DEFAULT_ABBREV_PREFIX + "_",
|
||||
AbstractStringDataType.DEFAULT_LABEL_PREFIX, AbstractStringDataType.DEFAULT_LABEL,
|
||||
options, offcutOffset);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,6 +15,9 @@
|
||||
*/
|
||||
package ghidra.program.model.data;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
|
||||
/**
|
||||
* Array interface
|
||||
*/
|
||||
@ -40,4 +43,129 @@ public interface Array extends DataType {
|
||||
*/
|
||||
DataType getDataType();
|
||||
|
||||
/**
|
||||
* Get the appropriate string to use as the label prefix
|
||||
* for an array, taking into account the actual data at the memory location.
|
||||
* <p>
|
||||
* See also {@link #getDefaultLabelPrefix()}
|
||||
*
|
||||
* @param buf memory buffer containing the bytes.
|
||||
* @param settings the Settings object
|
||||
* @param length the length of the data.
|
||||
* @param options options for how to format the default label prefix.
|
||||
* @return the label prefix or null if not applicable
|
||||
*/
|
||||
default public String getArrayDefaultLabelPrefix(MemBuffer buf, Settings settings, int len,
|
||||
DataTypeDisplayOptions options) {
|
||||
ArrayStringable stringableElementType = ArrayStringable.getArrayStringable(getDataType());
|
||||
String prefix = (stringableElementType != null)
|
||||
? stringableElementType.getArrayDefaultLabelPrefix(buf, settings, len, options)
|
||||
: null;
|
||||
return (prefix != null) ? prefix : getDefaultLabelPrefix();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate string to use as the offcut label prefix for an array, taking into
|
||||
* account the actual data at the memory location.
|
||||
* <p>
|
||||
* See also {@link #getDefaultLabelPrefix()}
|
||||
*
|
||||
* @param buf memory buffer containing the bytes.
|
||||
* @param settings the Settings object
|
||||
* @param length the length of the data.
|
||||
* @param options options for how to format the default label prefix.
|
||||
* @param offcutLength offcut offset from start of buf
|
||||
* @return the offcut label prefix or null if not applicable
|
||||
*/
|
||||
default public String getArrayDefaultOffcutLabelPrefix(MemBuffer buf, Settings settings,
|
||||
int len, DataTypeDisplayOptions options, int offcutLength) {
|
||||
|
||||
ArrayStringable stringableElementType = ArrayStringable.getArrayStringable(getDataType());
|
||||
String prefix = (stringableElementType != null)
|
||||
? stringableElementType.getArrayDefaultOffcutLabelPrefix(buf, settings, len,
|
||||
options, offcutLength)
|
||||
: null;
|
||||
return (prefix != null) ? prefix : getDefaultLabelPrefix(buf, settings, len, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the representation which corresponds to an array in memory. This will either be a
|
||||
* String for the ArrayStringable case, "??" for uninitialized data,
|
||||
* or the empty string if it is not.
|
||||
*
|
||||
* @param buf data buffer
|
||||
* @param settings data settings
|
||||
* @param length length of array
|
||||
* @return a String if it is an array of chars; otherwise empty string, never null.
|
||||
*/
|
||||
default public String getArrayRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||
if (!buf.isInitializedMemory()) {
|
||||
return StringDataInstance.UNKNOWN;
|
||||
}
|
||||
ArrayStringable stringableElementType = ArrayStringable.getArrayStringable(getDataType());
|
||||
String value =
|
||||
(stringableElementType != null && stringableElementType.hasStringValue(settings))
|
||||
? new StringDataInstance(stringableElementType, settings, buf,
|
||||
length).getStringRepresentation()
|
||||
: null;
|
||||
return (value != null) ? value : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value object which corresponds to an array in memory. This will either be a
|
||||
* String for the ArrayStringable case or null.
|
||||
*
|
||||
* @param buf data buffer
|
||||
* @param settings data settings
|
||||
* @param length length of array
|
||||
* @return a String if it is an array of chars; otherwise null.
|
||||
*/
|
||||
default Object getArrayValue(MemBuffer buf, Settings settings, int length) {
|
||||
if (!buf.getMemory().getAllInitializedAddressSet().contains(buf.getAddress())) {
|
||||
return null;
|
||||
}
|
||||
ArrayStringable as = ArrayStringable.getArrayStringable(getDataType());
|
||||
Object value = (as != null) ? as.getArrayString(buf, settings, length) : null;
|
||||
|
||||
return value;
|
||||
// TODO
|
||||
// For large array it is not scalable to create a java array object. Perhaps
|
||||
// we could create a GhidraArray that can dish out objects.
|
||||
// DataType dt = arrayDt.getDataType();
|
||||
// Class<?> valueClass = dt.getValueClass(settings);
|
||||
// if (valueClass != null) {
|
||||
// int count = arrayDt.getNumElements();
|
||||
// int elementLength = arrayDt.getElementLength();
|
||||
// WrappedMemBuffer wrappedBuffer = new WrappedMemBuffer(buf, 0);
|
||||
// Object[] array = (Object[]) java.lang.reflect.Array.newInstance(valueClass, count);
|
||||
// for (int i = 0; i < count; i++) {
|
||||
// wrappedBuffer.setBaseOffset(i * elementLength);
|
||||
// array[i] = dt.getValue(wrappedBuffer, settings, elementLength);
|
||||
// }
|
||||
// return array;
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value Class of a specific arrayDt with settings
|
||||
* ( see {@link #getArrayValueClass(Array, Settings)} ).
|
||||
*
|
||||
* @param settings the relevant settings to use or null for default.
|
||||
* @return Class of the value to be returned by the array or null if it can vary
|
||||
* or is unspecified (String or Array class will be returned).
|
||||
*/
|
||||
default public Class<?> getArrayValueClass(Settings settings) {
|
||||
DataType dt = getDataType();
|
||||
if (dt instanceof TypeDef) {
|
||||
dt = ((TypeDef) dt).getBaseDataType();
|
||||
}
|
||||
if (dt instanceof ArrayStringable) {
|
||||
if (((ArrayStringable) dt).hasStringValue(settings)) {
|
||||
return String.class;
|
||||
}
|
||||
}
|
||||
Class<?> valueClass = dt.getValueClass(settings);
|
||||
return valueClass != null ? Array.class : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ public class ArrayDataType extends DataTypeImpl implements Array {
|
||||
|
||||
@Override
|
||||
public Class<?> getValueClass(Settings settings) {
|
||||
return DataTypeUtilities.getArrayValueClass(this, settings);
|
||||
return getArrayValueClass(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -253,18 +253,13 @@ public class ArrayDataType extends DataTypeImpl implements Array {
|
||||
@Override
|
||||
public String getDefaultLabelPrefix(MemBuffer buf, Settings settings, int len,
|
||||
DataTypeDisplayOptions options) {
|
||||
String prefix =
|
||||
ArrayStringable.getArrayStringableLabelPrefix(this, buf, settings, len, options);
|
||||
return prefix != null ? prefix : super.getDefaultLabelPrefix(buf, settings, len, options);
|
||||
return getArrayDefaultLabelPrefix(buf, settings, len, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultOffcutLabelPrefix(MemBuffer buf, Settings settings, int len,
|
||||
DataTypeDisplayOptions options, int offcutLength) {
|
||||
String prefix = ArrayStringable.getArrayStringableOffcutLabelPrefix(this, buf, settings,
|
||||
len, options, offcutLength);
|
||||
return prefix != null ? prefix
|
||||
: super.getDefaultOffcutLabelPrefix(buf, settings, len, options, offcutLength);
|
||||
return getArrayDefaultOffcutLabelPrefix(buf, settings, len, options, offcutLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -274,12 +269,12 @@ public class ArrayDataType extends DataTypeImpl implements Array {
|
||||
|
||||
@Override
|
||||
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||
return DataTypeUtilities.getArrayValue(this, buf, settings, length);
|
||||
return getArrayValue(buf, settings, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||
return DataTypeUtilities.getArrayRepresentation(this, buf, settings, length);
|
||||
return getArrayRepresentation(buf, settings, length);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
package ghidra.program.model.data;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.program.model.listing.Data;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
|
||||
/**
|
||||
@ -37,23 +36,6 @@ public interface ArrayStringable extends DataType {
|
||||
*/
|
||||
public boolean hasStringValue(Settings settings);
|
||||
|
||||
/**
|
||||
* Returns a {@link StringDataInstance} representing this ArrayStringable's contents.
|
||||
*
|
||||
* <p>
|
||||
* @param buf {@link MemBuffer} containing the data bytes.
|
||||
* @param settings {@link Settings} object containing settings, usually the {@link Data}
|
||||
* element.
|
||||
* @param length number of bytes that this data object contains (ie. how big was the array)
|
||||
* @return a new {@link StringDataInstance} representing this ArrayStringable's contents,
|
||||
* never NULL. See {@link StringDataInstance#NULL_INSTANCE}.
|
||||
*/
|
||||
public default StringDataInstance getStringDataInstance(MemBuffer buf, Settings settings,
|
||||
int length) {
|
||||
return hasStringValue(settings) ? new StringDataInstance(this, settings, buf, length)
|
||||
: StringDataInstance.NULL_INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* For cases where an array of this type exists, get the array value as a String.
|
||||
* When data corresponds to character data it should generally be expressed as a string.
|
||||
@ -64,19 +46,10 @@ public interface ArrayStringable extends DataType {
|
||||
* @return array value expressed as a string or null if data is not character data
|
||||
*/
|
||||
public default String getArrayString(MemBuffer buf, Settings settings, int length) {
|
||||
return getStringDataInstance(buf, settings, length).getStringValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* For cases where an array of this type exists, get the representation string which
|
||||
* corresponds to the array (example: String for an array of chars).
|
||||
* @param buf memory buffer containing the bytes.
|
||||
* @param settings the Settings object
|
||||
* @param length the length of the data.
|
||||
* @return array representation or null of an array representation is not supported.
|
||||
*/
|
||||
public default String getArrayRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||
return getStringDataInstance(buf, settings, length).getStringRepresentation();
|
||||
if (hasStringValue(settings) && buf.isInitializedMemory()) {
|
||||
return new StringDataInstance(this, settings, buf, length).getStringValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,40 +99,4 @@ public interface ArrayStringable extends DataType {
|
||||
return (dt instanceof ArrayStringable) ? (ArrayStringable) dt : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate string to use as the label prefix
|
||||
* for an array which corresponds to an ArrayStringable
|
||||
* element data type.
|
||||
* @param arrayDt array data type
|
||||
* @param buf memory buffer containing the bytes.
|
||||
* @param settings the Settings object
|
||||
* @param length the length of the data.
|
||||
* @param options options for how to format the default label prefix.
|
||||
* @return the ArrayStringable label prefix or null if not applicable
|
||||
*/
|
||||
public static String getArrayStringableLabelPrefix(Array arrayDt, MemBuffer buf,
|
||||
Settings settings, int len, DataTypeDisplayOptions options) {
|
||||
ArrayStringable as = getArrayStringable(arrayDt.getDataType());
|
||||
return (as != null) ? as.getArrayDefaultLabelPrefix(buf, settings, len, options) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate string to use as the offcut label prefix
|
||||
* for an array which corresponds to an ArrayStringable
|
||||
* element data type.
|
||||
* @param arrayDt array data type
|
||||
* @param buf memory buffer containing the bytes.
|
||||
* @param settings the Settings object
|
||||
* @param length the length of the data.
|
||||
* @param options options for how to format the default label prefix.
|
||||
* @param offcutLength offcut offset from start of buf
|
||||
* @return the ArrayStringable offcut label prefix or null if not applicable
|
||||
*/
|
||||
public static String getArrayStringableOffcutLabelPrefix(Array arrayDt, MemBuffer buf,
|
||||
Settings settings, int len, DataTypeDisplayOptions options, int offcutLength) {
|
||||
ArrayStringable as = getArrayStringable(arrayDt.getDataType());
|
||||
return (as != null)
|
||||
? as.getArrayDefaultOffcutLabelPrefix(buf, settings, len, options, offcutLength)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public class StringDataInstance {
|
||||
* @return boolean true if string data.
|
||||
*/
|
||||
public static boolean isString(Data data) {
|
||||
if (data == null) {
|
||||
if (data == null || !data.isInitializedMemory()) {
|
||||
return false;
|
||||
}
|
||||
DataType dt = data.getBaseDataType();
|
||||
@ -89,36 +89,38 @@ public class StringDataInstance {
|
||||
return ((AbstractStringDataType) dt).getStringDataInstance(data, data,
|
||||
data.getLength());
|
||||
}
|
||||
if (dt instanceof Array) {
|
||||
if (dt instanceof Array && !data.isInitializedMemory()) {
|
||||
ArrayStringable arrayStringable =
|
||||
ArrayStringable.getArrayStringable(((Array) dt).getDataType());
|
||||
return arrayStringable.getStringDataInstance(data, data, data.getLength());
|
||||
if (arrayStringable != null && arrayStringable.hasStringValue(data)) {
|
||||
return new StringDataInstance(arrayStringable, data, data, data.getLength());
|
||||
}
|
||||
}
|
||||
return NULL_INSTANCE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link StringDataInstance} using the bytes in the MemBuffer.
|
||||
* <p>
|
||||
* @param stringDataType {@link DataType} of the bytes in the buffer.
|
||||
* @param dataType {@link DataType} of the bytes in the buffer.
|
||||
* @param buf memory buffer containing the bytes.
|
||||
* @param settings the Settings object
|
||||
* @param length the length of the data.
|
||||
* @return new {@link StringDataInstance}, never NULL. See {@link #NULL_INSTANCE}.
|
||||
*/
|
||||
public static StringDataInstance getStringDataInstance(DataType stringDataType, MemBuffer buf,
|
||||
public static StringDataInstance getStringDataInstance(DataType dataType, MemBuffer buf,
|
||||
Settings settings, int length) {
|
||||
if (stringDataType instanceof AbstractStringDataType) {
|
||||
return ((AbstractStringDataType) stringDataType).getStringDataInstance(buf, settings,
|
||||
length);
|
||||
if (dataType instanceof AbstractStringDataType) {
|
||||
return ((AbstractStringDataType) dataType).getStringDataInstance(buf, settings, length);
|
||||
}
|
||||
if (stringDataType instanceof Array &&
|
||||
((Array) stringDataType).getDataType() instanceof ArrayStringable) {
|
||||
stringDataType = ((Array) stringDataType).getDataType();
|
||||
if (dataType instanceof Array) {
|
||||
dataType = ArrayStringable.getArrayStringable(((Array) dataType).getDataType());
|
||||
}
|
||||
if (stringDataType instanceof ArrayStringable &&
|
||||
((ArrayStringable) stringDataType).hasStringValue(settings)) {
|
||||
return ((ArrayStringable) stringDataType).getStringDataInstance(buf, settings, length);
|
||||
if (dataType instanceof ArrayStringable &&
|
||||
((ArrayStringable) dataType).hasStringValue(settings) && buf.isInitializedMemory()) {
|
||||
|
||||
return new StringDataInstance(dataType, settings, buf, length);
|
||||
}
|
||||
return NULL_INSTANCE;
|
||||
}
|
||||
|
@ -51,6 +51,24 @@ import ghidra.program.model.address.Address;
|
||||
*/
|
||||
public interface MemBuffer {
|
||||
|
||||
/**
|
||||
* Returns true if this buffer's starting address has valid data.
|
||||
*
|
||||
* @return boolean true if first byte of memory buffer can be read
|
||||
*/
|
||||
public default boolean isInitializedMemory() {
|
||||
// TODO: possible alternate method of testing
|
||||
//return getMemory().getAllInitializedAddressSet().contains(getAddress());
|
||||
try {
|
||||
getByte(0); // test for uninitialized memory
|
||||
return true;
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
// ignore
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one byte from memory at the current position plus offset.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user