mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-25 21:51:47 +00:00
GP-4723 - Clean up RTTI TypeDescriptorModel use of Demangler
This commit is contained in:
parent
d5cbda1e21
commit
98602916e4
@ -37,7 +37,7 @@ public class CreateTypeDescriptorBackgroundCmd
|
|||||||
private static final String RTTI_0_NAME = "RTTI Type Descriptor";
|
private static final String RTTI_0_NAME = "RTTI Type Descriptor";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a command for applying a TypeDescriptor data type at an address using the
|
* Constructs a command for applying a TypeDescriptor data type at an address using the
|
||||||
* default validation and apply options.
|
* default validation and apply options.
|
||||||
* @param address the address where the data should be created using the data type.
|
* @param address the address where the data should be created using the data type.
|
||||||
*/
|
*/
|
||||||
@ -46,13 +46,13 @@ public class CreateTypeDescriptorBackgroundCmd
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a command for applying a TypeDescriptor data type at an address using the
|
* Constructs a command for applying a TypeDescriptor data type at an address using the
|
||||||
* indicated options.
|
* indicated options.
|
||||||
* @param address the address where the data should be created using the data type.
|
* @param address the address where the data should be created using the data type.
|
||||||
* @param validationOptions the options for controlling how validation is performed when
|
* @param validationOptions the options for controlling how validation is performed when
|
||||||
* determining whether or not to create the data structure at the indicated address.
|
* determining whether or not to create the data structure at the indicated address.
|
||||||
* @param applyOptions the options for creating the new data structure and its associated
|
* @param applyOptions the options for creating the new data structure and its associated
|
||||||
* markup in the program as well as whether to follow other data references and create their
|
* markup in the program as well as whether to follow other data references and create their
|
||||||
* data too.
|
* data too.
|
||||||
*/
|
*/
|
||||||
public CreateTypeDescriptorBackgroundCmd(Address address,
|
public CreateTypeDescriptorBackgroundCmd(Address address,
|
||||||
@ -65,7 +65,7 @@ public class CreateTypeDescriptorBackgroundCmd
|
|||||||
* by the model and using the indicated options.
|
* by the model and using the indicated options.
|
||||||
* @param model the model indicating the TypeDescriptor data to be created by this command.
|
* @param model the model indicating the TypeDescriptor data to be created by this command.
|
||||||
* @param applyOptions the options for creating the new data structure and its associated
|
* @param applyOptions the options for creating the new data structure and its associated
|
||||||
* markup in the program as well as whether to follow other data references and create their
|
* markup in the program as well as whether to follow other data references and create their
|
||||||
* data too.
|
* data too.
|
||||||
*/
|
*/
|
||||||
public CreateTypeDescriptorBackgroundCmd(TypeDescriptorModel model,
|
public CreateTypeDescriptorBackgroundCmd(TypeDescriptorModel model,
|
||||||
@ -152,13 +152,14 @@ public class CreateTypeDescriptorBackgroundCmd
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If PDB had been run, then the namespace here might already have been promoted to
|
||||||
|
// a class type. At this point in processing, we know that the model only has a type
|
||||||
|
// with a "class" or "struct" tag (see TypeDescriptorModel).
|
||||||
// <br>Note: For now this assumes all classes and structs with RTTI data must
|
// <br>Note: For now this assumes all classes and structs with RTTI data must
|
||||||
// actually be classes. In the future this might need additional checking before
|
// actually be classes. In the future this might need additional checking before
|
||||||
// promoting some "struct" ref types to being a class, if we can better determine
|
// promoting some "struct" ref types to being a class, if we can better determine
|
||||||
// whether or not they are actually classes.
|
// whether or not they are actually classes.
|
||||||
String refType = model.getRefType(); // Can be null.
|
if (!(classNamespace instanceof GhidraClass)) {
|
||||||
boolean makeClass = "class".equals(refType) || "struct".equals(refType);
|
|
||||||
if (makeClass) {
|
|
||||||
classNamespace = RttiUtil.promoteToClassNamespace(program, classNamespace);
|
classNamespace = RttiUtil.promoteToClassNamespace(program, classNamespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,7 @@ package ghidra.app.cmd.data;
|
|||||||
import ghidra.app.cmd.data.rtti.RttiUtil;
|
import ghidra.app.cmd.data.rtti.RttiUtil;
|
||||||
import ghidra.app.util.datatype.microsoft.DataValidationOptions;
|
import ghidra.app.util.datatype.microsoft.DataValidationOptions;
|
||||||
import ghidra.app.util.datatype.microsoft.MSDataTypeUtils;
|
import ghidra.app.util.datatype.microsoft.MSDataTypeUtils;
|
||||||
import ghidra.app.util.demangler.DemangledObject;
|
import ghidra.app.util.demangler.*;
|
||||||
import ghidra.app.util.demangler.DemangledType;
|
|
||||||
import ghidra.docking.settings.SettingsImpl;
|
import ghidra.docking.settings.SettingsImpl;
|
||||||
import ghidra.program.model.address.*;
|
import ghidra.program.model.address.*;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
@ -30,14 +29,12 @@ import ghidra.program.model.mem.Memory;
|
|||||||
import ghidra.program.model.scalar.Scalar;
|
import ghidra.program.model.scalar.Scalar;
|
||||||
import ghidra.program.model.symbol.Namespace;
|
import ghidra.program.model.symbol.Namespace;
|
||||||
import ghidra.program.model.symbol.Symbol;
|
import ghidra.program.model.symbol.Symbol;
|
||||||
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.AssertException;
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
import mdemangler.*;
|
import mdemangler.MDException;
|
||||||
import mdemangler.datatype.MDDataType;
|
import mdemangler.MDMangGhidra;
|
||||||
import mdemangler.datatype.complex.MDComplexType;
|
|
||||||
import mdemangler.datatype.modifier.MDModifierType;
|
|
||||||
import mdemangler.naming.MDQualifiedName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model for the TypeDescriptor data type.
|
* Model for the TypeDescriptor data type.
|
||||||
@ -57,7 +54,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
private boolean hasVFPointer;
|
private boolean hasVFPointer;
|
||||||
|
|
||||||
private String originalTypeName;
|
private String originalTypeName;
|
||||||
private MDComplexType mdComplexType;
|
private DemangledDataType demangledDataType;
|
||||||
private boolean hasProcessedName = false;
|
private boolean hasProcessedName = false;
|
||||||
private Namespace namespace;
|
private Namespace namespace;
|
||||||
|
|
||||||
@ -65,6 +62,8 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
* Creates the model for the exception handling TypeDescriptor data type.
|
* Creates the model for the exception handling TypeDescriptor data type.
|
||||||
* @param program the program
|
* @param program the program
|
||||||
* @param address the address in the program for the TypeDescriptor data type.
|
* @param address the address in the program for the TypeDescriptor data type.
|
||||||
|
* @param validationOptions options indicating how to validate the data type at the indicated
|
||||||
|
* address
|
||||||
*/
|
*/
|
||||||
public TypeDescriptorModel(Program program, Address address,
|
public TypeDescriptorModel(Program program, Address address,
|
||||||
DataValidationOptions validationOptions) {
|
DataValidationOptions validationOptions) {
|
||||||
@ -204,8 +203,9 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the TypeDescriptor structure for the indicated program.
|
* Gets the TypeDescriptor structure for the indicated program
|
||||||
* @return the TypeDescriptor structure.
|
* @param program the program which will contain this model's data type
|
||||||
|
* @return the TypeDescriptor structure
|
||||||
*/
|
*/
|
||||||
public static DataType getDataType(Program program) {
|
public static DataType getDataType(Program program) {
|
||||||
|
|
||||||
@ -247,9 +247,10 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if this model's data type has a vf table pointer.
|
* Determines if this model's data type program-wide TypeInfo Vftable pointer. This is used
|
||||||
* @param program the program which will contain this model's data type.
|
* as an indication as to whether the particular data type has a Vftable pointer
|
||||||
* @return true if the data type has a vf table pointer. Otherwise, it has a hash value.
|
* @param program the program which will contain this model's data type
|
||||||
|
* @return true if the data type has a vf table pointer. Otherwise, it has a hash value
|
||||||
*/
|
*/
|
||||||
private static boolean hasVFPointer(Program program) {
|
private static boolean hasVFPointer(Program program) {
|
||||||
|
|
||||||
@ -374,7 +375,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
*/
|
*/
|
||||||
public Scalar getHashValue() throws InvalidDataTypeException, UndefinedValueException {
|
public Scalar getHashValue() throws InvalidDataTypeException, UndefinedValueException {
|
||||||
checkValidity();
|
checkValidity();
|
||||||
if (hasVFPointer) {
|
if (!hasVFPointer) {
|
||||||
throw new UndefinedValueException(
|
throw new UndefinedValueException(
|
||||||
"No hash value is defined for this TypeDescriptor model.");
|
"No hash value is defined for this TypeDescriptor model.");
|
||||||
}
|
}
|
||||||
@ -429,6 +430,9 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
* model's address.
|
* model's address.
|
||||||
*/
|
*/
|
||||||
private String doGetTypeName() throws InvalidDataTypeException {
|
private String doGetTypeName() throws InvalidDataTypeException {
|
||||||
|
if (hasProcessedName) {
|
||||||
|
return originalTypeName;
|
||||||
|
}
|
||||||
// last component is the type descriptor name.
|
// last component is the type descriptor name.
|
||||||
Address nameAddress = getComponentAddressOfTypeName(); // Could be null.
|
Address nameAddress = getComponentAddressOfTypeName(); // Could be null.
|
||||||
if (nameAddress == null) {
|
if (nameAddress == null) {
|
||||||
@ -442,9 +446,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
Object value = terminatedStringDt.getValue(nameMemBuffer, SettingsImpl.NO_SETTINGS, 1);
|
Object value = terminatedStringDt.getValue(nameMemBuffer, SettingsImpl.NO_SETTINGS, 1);
|
||||||
if (value instanceof String) {
|
if (value instanceof String) {
|
||||||
originalTypeName = (String) value;
|
originalTypeName = (String) value;
|
||||||
if (originalTypeName != null) {
|
demangledDataType = getDemangledDataType(originalTypeName); // Can be null
|
||||||
mdComplexType = getMDComplexType(program, originalTypeName); // Can be null.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
hasProcessedName = true;
|
hasProcessedName = true;
|
||||||
return originalTypeName;
|
return originalTypeName;
|
||||||
@ -453,13 +455,13 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
private boolean hasComplexType() {
|
private boolean hasComplexType() {
|
||||||
if (!hasProcessedName) {
|
if (!hasProcessedName) {
|
||||||
try {
|
try {
|
||||||
getTypeName(); // Initialize originalTypeName & mdComplexType if possible.
|
getTypeName(); // Initialize originalTypeName & demangledDataType if possible.
|
||||||
}
|
}
|
||||||
catch (InvalidDataTypeException e) {
|
catch (InvalidDataTypeException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (mdComplexType != null);
|
return (demangledDataType != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -468,16 +470,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
* @return the full demangled type name or null.
|
* @return the full demangled type name or null.
|
||||||
*/
|
*/
|
||||||
public String getDemangledTypeDescriptor() {
|
public String getDemangledTypeDescriptor() {
|
||||||
return hasComplexType() ? mdComplexType.toString() : null;
|
return hasComplexType() ? demangledDataType.getOriginalDemangled() : null;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the reference type of the type descriptor. (i.e. class, struct, union, enum)
|
|
||||||
* @return the type of thing referred to by this descriptor, or null if it couldn't be
|
|
||||||
* determined.
|
|
||||||
*/
|
|
||||||
public String getRefType() {
|
|
||||||
return hasComplexType() ? mdComplexType.getTypeName() : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -486,24 +479,15 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
* be determined.
|
* be determined.
|
||||||
*/
|
*/
|
||||||
public String getDescriptorName() {
|
public String getDescriptorName() {
|
||||||
if (!hasComplexType()) {
|
return hasComplexType() ? demangledDataType.getName() : null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
MDQualifiedName qualifiedName = mdComplexType.getNamespace();
|
|
||||||
return qualifiedName.getName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the parent namespace of the type descriptor.
|
* Gets the parent namespace of the type descriptor.
|
||||||
* @return the parent namespace as a DemangledType or null.
|
* @return the parent namespace as a DemangledType or null.
|
||||||
*/
|
*/
|
||||||
public DemangledType getParentNamespace() {
|
public Demangled getParentNamespace() {
|
||||||
if (!hasComplexType()) {
|
return hasComplexType() ? demangledDataType.getNamespace() : null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
MDQualifiedName qualifiedName = mdComplexType.getNamespace();
|
|
||||||
MDMangGhidra demangler = new MDMangGhidra();
|
|
||||||
return demangler.processNamespace(qualifiedName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -512,7 +496,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
* @return the full pathname or null.
|
* @return the full pathname or null.
|
||||||
*/
|
*/
|
||||||
public String getDescriptorTypeNamespace() {
|
public String getDescriptorTypeNamespace() {
|
||||||
return hasComplexType() ? mdComplexType.getTypeNamespace() : null;
|
return hasComplexType() ? demangledDataType.getNamespaceString() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -585,27 +569,20 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the namespace for this descriptor. It will create the namespace if it doesn't already exist.
|
* Gets the namespace for this descriptor. It will create the namespace if it doesn't already
|
||||||
* @return the descriptor's namespace, or null if it couldn't be determined.
|
* exist
|
||||||
|
* @return the descriptor's namespace or null if it couldn't be determined
|
||||||
*/
|
*/
|
||||||
public Namespace getDescriptorAsNamespace() {
|
public Namespace getDescriptorAsNamespace() {
|
||||||
if (namespace == null || isNamespaceDeleted(namespace)) {
|
if (namespace != null && !isNamespaceDeleted(namespace)) {
|
||||||
String descriptorName = getDescriptorName(); // Can be null.
|
return namespace;
|
||||||
if (descriptorName == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String demangledSource = mdComplexType.toString();
|
|
||||||
DemangledType typeNamespace =
|
|
||||||
new DemangledType(originalTypeName, demangledSource, descriptorName);
|
|
||||||
DemangledType parentNamespace = getParentNamespace(); // Can be null;
|
|
||||||
if (parentNamespace != null) {
|
|
||||||
typeNamespace.setNamespace(parentNamespace);
|
|
||||||
}
|
|
||||||
Program program = getProgram();
|
|
||||||
namespace = DemangledObject.createNamespace(program, typeNamespace,
|
|
||||||
program.getGlobalNamespace(), false);
|
|
||||||
}
|
}
|
||||||
|
if (hasComplexType() && demangledDataType == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Program program = getProgram();
|
||||||
|
namespace = DemangledObject.createNamespace(program, demangledDataType,
|
||||||
|
program.getGlobalNamespace(), false);
|
||||||
return namespace;
|
return namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,27 +595,37 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a demangler complex type for the indicated mangled string.
|
* Gets a DemangledDataType for the indicated mangled string
|
||||||
* @param program the program containing the mangled string
|
* @param mangledString the mangled string to be demangled
|
||||||
* @param mangledString the mangled string to be decoded
|
* @return the DemangledDataType or null if couldn't demangle or is not a class type
|
||||||
* @return the associated complex type or null if the string couldn't be demangled.
|
|
||||||
*/
|
*/
|
||||||
private static MDComplexType getMDComplexType(Program program, String mangledString) {
|
private static DemangledDataType getDemangledDataType(String mangledString) {
|
||||||
MDMangGhidra demangler = new MDMangGhidra();
|
MDMangGhidra demangler = new MDMangGhidra();
|
||||||
try {
|
try {
|
||||||
MDDataType mangledDt = demangler.demangleType(mangledString, true);
|
// Note that we could play with the return value, but it is not needed; instead, we
|
||||||
if (mangledDt instanceof MDModifierType modifierType) {
|
// get the DemangledDataType by calling the appropriate method
|
||||||
MDType refType = modifierType.getReferencedType();
|
demangler.demangleType(mangledString, true);
|
||||||
if (refType instanceof MDComplexType complexType) {
|
DemangledDataType demangledType = demangler.getDataType();
|
||||||
return complexType;
|
if (isPermittedType(demangledType)) {
|
||||||
}
|
return demangledType;
|
||||||
}
|
}
|
||||||
return null; // Not an MDComplexType
|
|
||||||
}
|
}
|
||||||
catch (MDException e) {
|
catch (MDException e) {
|
||||||
// Couldn't demangle.
|
// Couldn't demangle.
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPermittedType(DemangledDataType demangledDataType) {
|
||||||
|
if (demangledDataType == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (demangledDataType.isClass() || demangledDataType.isStruct()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Msg.info(TypeDescriptorModel.class,
|
||||||
|
"Unprocessed TypeDescriptor: " + demangledDataType.getSignature());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ package ghidra.app.plugin.prototype.MicrosoftCodeAnalyzerPlugin;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.app.cmd.data.CreateTypeDescriptorBackgroundCmd;
|
import ghidra.app.cmd.data.CreateTypeDescriptorBackgroundCmd;
|
||||||
import ghidra.app.cmd.data.TypeDescriptorModel;
|
|
||||||
import ghidra.app.cmd.data.rtti.*;
|
import ghidra.app.cmd.data.rtti.*;
|
||||||
import ghidra.app.services.*;
|
import ghidra.app.services.*;
|
||||||
import ghidra.app.util.datatype.microsoft.*;
|
import ghidra.app.util.datatype.microsoft.*;
|
||||||
@ -30,7 +29,7 @@ import ghidra.program.model.listing.Program;
|
|||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.program.util.ProgramMemoryUtil;
|
import ghidra.program.util.ProgramMemoryUtil;
|
||||||
import ghidra.util.bytesearch.*;
|
import ghidra.util.bytesearch.*;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.CancelledException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,12 +57,12 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||||||
public RttiAnalyzer() {
|
public RttiAnalyzer() {
|
||||||
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
|
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
|
||||||
setSupportsOneTimeAnalysis();
|
setSupportsOneTimeAnalysis();
|
||||||
// Set priority of RTTI analyzer to run after Demangler so can see if better
|
// Set priority of RTTI analyzer to run after Demangler so can see if better
|
||||||
// plate comment or label already exists from Demangler.
|
// plate comment or label already exists from Demangler.
|
||||||
setPriority(AnalysisPriority.REFERENCE_ANALYSIS.before());
|
setPriority(AnalysisPriority.REFERENCE_ANALYSIS.before());
|
||||||
setDefaultEnablement(true);
|
setDefaultEnablement(true);
|
||||||
validationOptions = new DataValidationOptions();
|
validationOptions = new DataValidationOptions();
|
||||||
applyOptions = new DataApplyOptions();
|
applyOptions = new DataApplyOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -74,21 +73,21 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||||||
@Override
|
@Override
|
||||||
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||||
throws CancelledException {
|
throws CancelledException {
|
||||||
|
|
||||||
// "rttiFound" option added in 10.3 so if analyzed with previous version analyzer will rerun
|
// "rttiFound" option added in 10.3 so if analyzed with previous version analyzer will rerun
|
||||||
if(hasRun(program)) {
|
if (hasRun(program)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Address commonVfTableAddress = RttiUtil.findTypeInfoVftableAddress(program, monitor);
|
Address commonVfTableAddress = RttiUtil.findTypeInfoVftableAddress(program, monitor);
|
||||||
|
|
||||||
if (commonVfTableAddress == null) {
|
if (commonVfTableAddress == null) {
|
||||||
setRttiFound(program, false);
|
setRttiFound(program, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
RttiUtil.createTypeInfoVftableSymbol(program,commonVfTableAddress);
|
RttiUtil.createTypeInfoVftableSymbol(program, commonVfTableAddress);
|
||||||
|
|
||||||
Set<Address> possibleTypeAddresses = locatePotentialRTTI0Entries(program, set, monitor);
|
Set<Address> possibleTypeAddresses = locatePotentialRTTI0Entries(program, set, monitor);
|
||||||
if (possibleTypeAddresses == null) {
|
if (possibleTypeAddresses == null) {
|
||||||
setRttiFound(program, false);
|
setRttiFound(program, false);
|
||||||
@ -98,10 +97,10 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||||||
// We now have a list of potential rtti0 addresses.
|
// We now have a list of potential rtti0 addresses.
|
||||||
processRtti0(possibleTypeAddresses, program, monitor);
|
processRtti0(possibleTypeAddresses, program, monitor);
|
||||||
setRttiFound(program, true);
|
setRttiFound(program, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Has this analyzer been run on the given program. NOTE: option new as of 10.3 so this will
|
* Has this analyzer been run on the given program. NOTE: option new as of 10.3 so this will
|
||||||
* not be accurate for older programs.
|
* not be accurate for older programs.
|
||||||
@ -111,13 +110,13 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||||||
private boolean hasRun(Program program) {
|
private boolean hasRun(Program program) {
|
||||||
Options programOptions = program.getOptions(Program.PROGRAM_INFO);
|
Options programOptions = program.getOptions(Program.PROGRAM_INFO);
|
||||||
Boolean hasRun = (Boolean) programOptions.getObject(RTTI_FOUND_OPTION, null);
|
Boolean hasRun = (Boolean) programOptions.getObject(RTTI_FOUND_OPTION, null);
|
||||||
if(hasRun == null) {
|
if (hasRun == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to set the RTTI Found option for the given program
|
* Method to set the RTTI Found option for the given program
|
||||||
* @param program the given program
|
* @param program the given program
|
||||||
@ -146,9 +145,9 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||||||
// use the type_info vftable address to find a list of potential RTTI0 addresses
|
// use the type_info vftable address to find a list of potential RTTI0 addresses
|
||||||
int alignment = program.getDefaultPointerSize();
|
int alignment = program.getDefaultPointerSize();
|
||||||
List<MemoryBlock> dataBlocks = ProgramMemoryUtil.getMemoryBlocksStartingWithName(
|
List<MemoryBlock> dataBlocks = ProgramMemoryUtil.getMemoryBlocksStartingWithName(
|
||||||
program, program.getMemory(), ".data", TaskMonitor.DUMMY);
|
program, program.getMemory(), ".data", TaskMonitor.DUMMY);
|
||||||
Set<Address> possibleTypeAddresses = ProgramMemoryUtil.findDirectReferences(program,
|
Set<Address> possibleTypeAddresses = ProgramMemoryUtil.findDirectReferences(program,
|
||||||
dataBlocks, alignment, commonVfTableAddress, monitor);
|
dataBlocks, alignment, commonVfTableAddress, monitor);
|
||||||
return possibleTypeAddresses;
|
return possibleTypeAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,26 +163,13 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||||||
monitor.checkCancelled();
|
monitor.checkCancelled();
|
||||||
monitor.setProgress(count++);
|
monitor.setProgress(count++);
|
||||||
|
|
||||||
// Validate
|
|
||||||
TypeDescriptorModel typeModel =
|
|
||||||
new TypeDescriptorModel(program, rtti0Address, validationOptions);
|
|
||||||
try {
|
|
||||||
// Check that name matches the expected format.
|
|
||||||
String typeName = typeModel.getTypeName(); // can be null.
|
|
||||||
if (typeName == null || !typeName.startsWith(CLASS_PREFIX_CHARS)) {
|
|
||||||
continue; // Invalid so don't create.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (InvalidDataTypeException e) {
|
|
||||||
continue; // Invalid so don't create.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the TypeDescriptor (RTTI 0) regardless of the other RTTI structures.
|
// Create the TypeDescriptor (RTTI 0) regardless of the other RTTI structures.
|
||||||
CreateTypeDescriptorBackgroundCmd typeDescCmd = new CreateTypeDescriptorBackgroundCmd(
|
CreateTypeDescriptorBackgroundCmd typeDescCmd = new CreateTypeDescriptorBackgroundCmd(
|
||||||
rtti0Address, validationOptions, applyOptions);
|
rtti0Address, validationOptions, applyOptions);
|
||||||
typeDescCmd.applyTo(program, monitor);
|
// Could call typeDescCmd.getStatusMsg() on failure
|
||||||
|
if (typeDescCmd.applyTo(program, monitor)) {
|
||||||
rtti0Locations.add(rtti0Address);
|
rtti0Locations.add(rtti0Address);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create any valid RTTI4s for this TypeDescriptor
|
// Create any valid RTTI4s for this TypeDescriptor
|
||||||
@ -237,7 +223,7 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** For each of the RTTI0 locations found locate the associated RTTI4 structure referring to it.
|
/** For each of the RTTI0 locations found locate the associated RTTI4 structure referring to it.
|
||||||
*
|
*
|
||||||
* @param program program to be searched
|
* @param program program to be searched
|
||||||
* @param dataBlocks dataBlocks to search
|
* @param dataBlocks dataBlocks to search
|
||||||
* @param rtti0Locations list of known rtti0 locations
|
* @param rtti0Locations list of known rtti0 locations
|
||||||
@ -286,7 +272,7 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a search pattern, to the searcher, for the set of bytes representing an address
|
* Add a search pattern, to the searcher, for the set of bytes representing an address
|
||||||
*
|
*
|
||||||
* @param searcher pattern searcher
|
* @param searcher pattern searcher
|
||||||
* @param validationOptions RTTI4 validation options
|
* @param validationOptions RTTI4 validation options
|
||||||
* @param addresses list of found valid RTTI4 locations accumulated during actual search
|
* @param addresses list of found valid RTTI4 locations accumulated during actual search
|
||||||
@ -324,7 +310,7 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||||||
return; // Only process valid RTTI 4 data.
|
return; // Only process valid RTTI 4 data.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the RTTI 0 is referred to both directly from the RTTI 4 and indirectly
|
// Check that the RTTI 0 is referred to both directly from the RTTI 4 and indirectly
|
||||||
// through the RTTI 3.
|
// through the RTTI 3.
|
||||||
boolean refersToRtti0 = rtti4Model.refersToRtti0(getMatchValue());
|
boolean refersToRtti0 = rtti4Model.refersToRtti0(getMatchValue());
|
||||||
if (!refersToRtti0) {
|
if (!refersToRtti0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user