diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/CreateTypeDescriptorBackgroundCmd.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/CreateTypeDescriptorBackgroundCmd.java
index a3c02a388f..6408326574 100644
--- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/CreateTypeDescriptorBackgroundCmd.java
+++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/CreateTypeDescriptorBackgroundCmd.java
@@ -37,7 +37,7 @@ public class CreateTypeDescriptorBackgroundCmd
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.
* @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.
* @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.
* @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.
*/
public CreateTypeDescriptorBackgroundCmd(Address address,
@@ -65,7 +65,7 @@ public class CreateTypeDescriptorBackgroundCmd
* by the model and using the indicated options.
* @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
- * 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.
*/
public CreateTypeDescriptorBackgroundCmd(TypeDescriptorModel model,
@@ -152,13 +152,14 @@ public class CreateTypeDescriptorBackgroundCmd
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).
//
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
// promoting some "struct" ref types to being a class, if we can better determine
- // whether or not they are actually classes.
- String refType = model.getRefType(); // Can be null.
- boolean makeClass = "class".equals(refType) || "struct".equals(refType);
- if (makeClass) {
+ // whether or not they are actually classes.
+ if (!(classNamespace instanceof GhidraClass)) {
classNamespace = RttiUtil.promoteToClassNamespace(program, classNamespace);
}
diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java
index 8b145ca3ac..7815cfcfa3 100644
--- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java
+++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java
@@ -18,8 +18,7 @@ package ghidra.app.cmd.data;
import ghidra.app.cmd.data.rtti.RttiUtil;
import ghidra.app.util.datatype.microsoft.DataValidationOptions;
import ghidra.app.util.datatype.microsoft.MSDataTypeUtils;
-import ghidra.app.util.demangler.DemangledObject;
-import ghidra.app.util.demangler.DemangledType;
+import ghidra.app.util.demangler.*;
import ghidra.docking.settings.SettingsImpl;
import ghidra.program.model.address.*;
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.symbol.Namespace;
import ghidra.program.model.symbol.Symbol;
+import ghidra.util.Msg;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
-import mdemangler.*;
-import mdemangler.datatype.MDDataType;
-import mdemangler.datatype.complex.MDComplexType;
-import mdemangler.datatype.modifier.MDModifierType;
-import mdemangler.naming.MDQualifiedName;
+import mdemangler.MDException;
+import mdemangler.MDMangGhidra;
/**
* Model for the TypeDescriptor data type.
@@ -57,7 +54,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
private boolean hasVFPointer;
private String originalTypeName;
- private MDComplexType mdComplexType;
+ private DemangledDataType demangledDataType;
private boolean hasProcessedName = false;
private Namespace namespace;
@@ -65,6 +62,8 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
* Creates the model for the exception handling TypeDescriptor data type.
* @param program the program
* @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,
DataValidationOptions validationOptions) {
@@ -204,8 +203,9 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
}
/**
- * Gets the TypeDescriptor structure for the indicated program.
- * @return the TypeDescriptor structure.
+ * Gets the TypeDescriptor structure for the indicated program
+ * @param program the program which will contain this model's data type
+ * @return the TypeDescriptor structure
*/
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.
- * @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.
+ * Determines if this model's data type program-wide TypeInfo Vftable pointer. This is used
+ * as an indication as to whether the particular data type has a Vftable pointer
+ * @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) {
@@ -374,7 +375,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
*/
public Scalar getHashValue() throws InvalidDataTypeException, UndefinedValueException {
checkValidity();
- if (hasVFPointer) {
+ if (!hasVFPointer) {
throw new UndefinedValueException(
"No hash value is defined for this TypeDescriptor model.");
}
@@ -429,6 +430,9 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
* model's address.
*/
private String doGetTypeName() throws InvalidDataTypeException {
+ if (hasProcessedName) {
+ return originalTypeName;
+ }
// last component is the type descriptor name.
Address nameAddress = getComponentAddressOfTypeName(); // Could be null.
if (nameAddress == null) {
@@ -442,9 +446,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
Object value = terminatedStringDt.getValue(nameMemBuffer, SettingsImpl.NO_SETTINGS, 1);
if (value instanceof String) {
originalTypeName = (String) value;
- if (originalTypeName != null) {
- mdComplexType = getMDComplexType(program, originalTypeName); // Can be null.
- }
+ demangledDataType = getDemangledDataType(originalTypeName); // Can be null
}
hasProcessedName = true;
return originalTypeName;
@@ -453,13 +455,13 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
private boolean hasComplexType() {
if (!hasProcessedName) {
try {
- getTypeName(); // Initialize originalTypeName & mdComplexType if possible.
+ getTypeName(); // Initialize originalTypeName & demangledDataType if possible.
}
catch (InvalidDataTypeException e) {
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.
*/
public String getDemangledTypeDescriptor() {
- return hasComplexType() ? mdComplexType.toString() : 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;
+ return hasComplexType() ? demangledDataType.getOriginalDemangled() : null;
}
/**
@@ -486,24 +479,15 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
* be determined.
*/
public String getDescriptorName() {
- if (!hasComplexType()) {
- return null;
- }
- MDQualifiedName qualifiedName = mdComplexType.getNamespace();
- return qualifiedName.getName();
+ return hasComplexType() ? demangledDataType.getName() : null;
}
/**
* Gets the parent namespace of the type descriptor.
* @return the parent namespace as a DemangledType or null.
*/
- public DemangledType getParentNamespace() {
- if (!hasComplexType()) {
- return null;
- }
- MDQualifiedName qualifiedName = mdComplexType.getNamespace();
- MDMangGhidra demangler = new MDMangGhidra();
- return demangler.processNamespace(qualifiedName);
+ public Demangled getParentNamespace() {
+ return hasComplexType() ? demangledDataType.getNamespace() : null;
}
/**
@@ -512,7 +496,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
* @return the full pathname or null.
*/
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.
- * @return the descriptor's namespace, or null if it couldn't be determined.
+ * Gets the namespace for this descriptor. It will create the namespace if it doesn't already
+ * exist
+ * @return the descriptor's namespace or null if it couldn't be determined
*/
public Namespace getDescriptorAsNamespace() {
- if (namespace == null || isNamespaceDeleted(namespace)) {
- String descriptorName = getDescriptorName(); // Can be null.
- 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 (namespace != null && !isNamespaceDeleted(namespace)) {
+ return namespace;
}
+ if (hasComplexType() && demangledDataType == null) {
+ return null;
+ }
+ Program program = getProgram();
+ namespace = DemangledObject.createNamespace(program, demangledDataType,
+ program.getGlobalNamespace(), false);
return namespace;
}
@@ -618,27 +595,37 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
}
/**
- * Gets a demangler complex type for the indicated mangled string.
- * @param program the program containing the mangled string
- * @param mangledString the mangled string to be decoded
- * @return the associated complex type or null if the string couldn't be demangled.
+ * Gets a DemangledDataType for the indicated mangled string
+ * @param mangledString the mangled string to be demangled
+ * @return the DemangledDataType or null if couldn't demangle or is not a class type
*/
- private static MDComplexType getMDComplexType(Program program, String mangledString) {
+ private static DemangledDataType getDemangledDataType(String mangledString) {
MDMangGhidra demangler = new MDMangGhidra();
try {
- MDDataType mangledDt = demangler.demangleType(mangledString, true);
- if (mangledDt instanceof MDModifierType modifierType) {
- MDType refType = modifierType.getReferencedType();
- if (refType instanceof MDComplexType complexType) {
- return complexType;
- }
+ // Note that we could play with the return value, but it is not needed; instead, we
+ // get the DemangledDataType by calling the appropriate method
+ demangler.demangleType(mangledString, true);
+ DemangledDataType demangledType = demangler.getDataType();
+ if (isPermittedType(demangledType)) {
+ return demangledType;
}
- return null; // Not an MDComplexType
}
catch (MDException e) {
// 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;
}
}
diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/RttiAnalyzer.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/RttiAnalyzer.java
index 9a6ec6f351..fb0779a73a 100644
--- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/RttiAnalyzer.java
+++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/plugin/prototype/MicrosoftCodeAnalyzerPlugin/RttiAnalyzer.java
@@ -18,7 +18,6 @@ package ghidra.app.plugin.prototype.MicrosoftCodeAnalyzerPlugin;
import java.util.*;
import ghidra.app.cmd.data.CreateTypeDescriptorBackgroundCmd;
-import ghidra.app.cmd.data.TypeDescriptorModel;
import ghidra.app.cmd.data.rtti.*;
import ghidra.app.services.*;
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.util.ProgramMemoryUtil;
import ghidra.util.bytesearch.*;
-import ghidra.util.exception.*;
+import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
@@ -58,12 +57,12 @@ public class RttiAnalyzer extends AbstractAnalyzer {
public RttiAnalyzer() {
super(NAME, DESCRIPTION, AnalyzerType.BYTE_ANALYZER);
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.
setPriority(AnalysisPriority.REFERENCE_ANALYSIS.before());
setDefaultEnablement(true);
validationOptions = new DataValidationOptions();
- applyOptions = new DataApplyOptions();
+ applyOptions = new DataApplyOptions();
}
@Override
@@ -74,21 +73,21 @@ public class RttiAnalyzer extends AbstractAnalyzer {
@Override
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
throws CancelledException {
-
+
// "rttiFound" option added in 10.3 so if analyzed with previous version analyzer will rerun
- if(hasRun(program)) {
+ if (hasRun(program)) {
return true;
}
-
+
Address commonVfTableAddress = RttiUtil.findTypeInfoVftableAddress(program, monitor);
- if (commonVfTableAddress == null) {
+ if (commonVfTableAddress == null) {
setRttiFound(program, false);
return true;
}
-
- RttiUtil.createTypeInfoVftableSymbol(program,commonVfTableAddress);
-
+
+ RttiUtil.createTypeInfoVftableSymbol(program, commonVfTableAddress);
+
Set