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 89eb5b74a1..2e158eb1bc 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
@@ -15,12 +15,15 @@
*/
package ghidra.app.cmd.data;
+import ghidra.app.cmd.data.rtti.RttiUtil;
import ghidra.app.util.datatype.microsoft.DataApplyOptions;
import ghidra.app.util.datatype.microsoft.DataValidationOptions;
import ghidra.program.model.address.Address;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.*;
+import ghidra.program.model.symbol.Namespace;
import ghidra.program.model.util.CodeUnitInsertionException;
+import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.InvalidInputException;
@@ -90,8 +93,8 @@ public class CreateTypeDescriptorBackgroundCmd
* be applied as a sized character array immediately following the structure whose size does not include
* the char array bytes.
* @return false if the data type was not created because it already exists, true otherwise
- * @throws CodeUnitInsertionException
- * @throws CancelledException
+ * @throws CodeUnitInsertionException if creating data throws exception
+ * @throws CancelledException if cancelled
*/
@Override
protected boolean createData() throws CodeUnitInsertionException, CancelledException {
@@ -142,7 +145,26 @@ public class CreateTypeDescriptorBackgroundCmd
monitor.checkCanceled();
// Label
- EHDataTypeUtilities.createSymbolIfNeeded(program, prefix, RTTI_0_NAME, null,
+ Namespace classNamespace = model.getDescriptorAsNamespace();
+
+ if (classNamespace == null) {
+ Msg.error(RttiUtil.class, "Cannot get namespace from model " + model.getAddress());
+ return false;
+ }
+
+ //
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) {
+ classNamespace = RttiUtil.promoteToClassNamespace(program, classNamespace);
+ }
+
+ // Make the symbol even if the namespace couldn't be promoted
+ // the method to promote spits out debug error if it cannot be promoted
+ EHDataTypeUtilities.createSymbolIfNeeded(program, classNamespace, RTTI_0_NAME,
getDataAddress(), applyOptions);
return true;
diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/EHDataTypeUtilities.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/EHDataTypeUtilities.java
index 83301b446d..a50c366637 100644
--- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/EHDataTypeUtilities.java
+++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/EHDataTypeUtilities.java
@@ -256,9 +256,8 @@ public class EHDataTypeUtilities {
* the specified address in the program.
*
* @param program the program.
- * @param prefix the symbol prefix to be used in the symbol name.
+ * @param classNamespace the class Namespace to create the symbol in
* @param dataTypeName the dataTypeName to be used in the symbol name.
- * @param suffix the symbol suffix to be used in the symbol name.
* @param address the address where the symbol should be created in the program.
* @param applyOptions options indicating whether or not to apply comments.
*
@@ -266,8 +265,8 @@ public class EHDataTypeUtilities {
*
* @throws InvalidInputException thrown if symbol can't be created as specified.
*/
- public static Symbol createSymbolIfNeeded(Program program, String prefix, String dataTypeName,
- String suffix, Address address, DataApplyOptions applyOptions)
+ public static Symbol createSymbolIfNeeded(Program program, Namespace classNamespace,
+ String dataTypeName, Address address, DataApplyOptions applyOptions)
throws InvalidInputException {
if (dataTypeName == null || !applyOptions.shouldCreateLabel()) {
@@ -277,20 +276,21 @@ public class EHDataTypeUtilities {
// Make sure we have underscores in name
dataTypeName = SymbolUtilities.replaceInvalidChars(dataTypeName, true);
+
SymbolTable symbolTable = program.getSymbolTable();
SymbolIterator symbols = symbolTable.getSymbolsAsIterator(address);
for (Symbol symbol : symbols) {
- if (symbol.getName().contains(dataTypeName)) {
+ if (symbol.getName().contains(dataTypeName) &&
+ symbol.getParentNamespace().equals(classNamespace)) {
return null; // Already have one with dataTypeName.
}
}
- String appliedPrefix = (prefix != null) ? (prefix) : "";
- String appliedSuffix = (suffix != null) ? (suffix) : "";
- String appliedSymbol = appliedPrefix + dataTypeName + appliedSuffix;
- appliedSymbol = SymbolUtilities.replaceInvalidChars(appliedSymbol, true);
+ Symbol symbol =
+ symbolTable.createLabel(address, dataTypeName, classNamespace, SourceType.IMPORTED);
+ symbol.setPrimary();
- return symbolTable.createLabel(address, appliedSymbol, SourceType.ANALYSIS);
+ return symbol;
}
/**
diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java
index 050ff96bee..9992a0e9e3 100644
--- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java
+++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java
@@ -68,28 +68,11 @@ public class RttiUtil {
rttiSuffix = SymbolUtilities.replaceInvalidChars(rttiSuffix, true);
- // Get or create the namespace for this RTTI's type descriptor.
+ // Get the namespace for this RTTI's type descriptor.
Namespace classNamespace = typeDescriptorModel.getDescriptorAsNamespace();
- // If the RTTI's type descriptor is for a class or struct then promote its
- // namespace to a class.
- //
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 = typeDescriptorModel.getRefType(); // Can be null.
- boolean makeClass = "class".equals(refType) || "struct".equals(refType);
SymbolTable symbolTable = program.getSymbolTable();
- if (makeClass && (classNamespace != null) && !(classNamespace instanceof GhidraClass)) {
- try {
- classNamespace = NamespaceUtils.convertNamespaceToClass(classNamespace);
- }
- catch (InvalidInputException iie) {
- Msg.error(RttiUtil.class,
- "Unable to convert namespace to class for namespace " + classNamespace + ".",
- iie);
- }
- }
+
// See if the symbol already exists for the RTTI data.
Symbol matchingSymbol = symbolTable.getSymbol(rttiSuffix, rttiAddress, classNamespace);
@@ -103,17 +86,15 @@ public class RttiUtil {
if (name.contains(rttiSuffix)) {
return false; // Similar symbol already exists.
}
- // assume any imported symbol is better than what we would put down
- // if mangled, it will get demangled later
- SourceType source = symbol.getSource();
- if (source == SourceType.IMPORTED) {
- return false;
- }
}
try {
- // Didn't find the symbol, so create it.
- symbolTable.createLabel(rttiAddress, rttiSuffix, classNamespace,
+
+ // Ignore imported mangled symbol because demangling would add tick marks into the name.
+ // The name created here is better. Set the symbol to be primary so that the demangler
+ // won't demangle.
+ Symbol symbol = symbolTable.createLabel(rttiAddress, rttiSuffix, classNamespace,
SourceType.IMPORTED);
+ symbol.setPrimary();
return true;
}
catch (InvalidInputException e) {
@@ -123,6 +104,26 @@ public class RttiUtil {
}
}
+ /**
+ * Method to promote the given namespace to a class namespace
+ * @param program the given program
+ * @param namespace the given namespace
+ * @return the promoted class namespace
+ */
+ public static Namespace promoteToClassNamespace(Program program, Namespace namespace) {
+
+ if (!(namespace instanceof GhidraClass)) {
+ try {
+ namespace = NamespaceUtils.convertNamespaceToClass(namespace);
+ }
+ catch (InvalidInputException iie) {
+ Msg.error(RttiUtil.class,
+ "Unable to convert namespace to class for namespace " + namespace + ".", iie);
+ }
+ }
+ return namespace;
+ }
+
/**
* Determines the number of vf addresses in the vf table that begins at the specified base
* address.
@@ -377,6 +378,8 @@ public class RttiUtil {
program.getName() + " Couldn't create type_info vftable symbol. ");
return;
}
+ // This fixes the double label issue that happens when there is pdb
+ vftableSymbol.setPrimary();
}
catch (InvalidInputException e) {
Msg.error(RttiUtil.class,