Merge remote-tracking branch

'origin/GP-6431_ghidra007_RTTIAnalyzer_handle_nondemangling_classnames--SQUASHED'
into patch (Closes #8944)
This commit is contained in:
Ryan Kurtz
2026-02-18 18:34:52 -05:00
5 changed files with 80 additions and 12 deletions
@@ -1516,6 +1516,9 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
highFunction, recoveredClass, constructor, vbtableOffset);
if (vbtableAddress != null) {
if (isInvalidVbtable(vbtableAddress)) {
continue;
}
return vbtableAddress;
}
}
@@ -1541,6 +1544,9 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
highFunction, recoveredClass, constructor, vbtableOffset);
if (vbtableAddress != null) {
if (isInvalidVbtable(vbtableAddress)) {
continue;
}
return vbtableAddress;
}
}
@@ -1549,6 +1555,27 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer {
}
private boolean isInvalidVbtable(Address address) {
// check to see if already has a non-default symbol that is not vbtable
Symbol symbol = program.getSymbolTable().getPrimarySymbol(address);
if (symbol.getSource() != SourceType.DEFAULT &&
!symbol.getName().contains("vbtable")) {
return true;
}
// check to see if table contains an address reference
// if it is an address then is very unlikely this is a vbtable since
// it needs offset values and most are either large negatives (FFFFF....) or small offsets
// both of which are not valid addresses in a normal PE binary
Address referencedAddress = extendedFlatAPI.getPointer(address);
if (program.getMemory().contains(referencedAddress)) {
return true;
}
return false;
}
/**
* Method to find the address of the vbtable referenced at the given offset in the given function
* @param fillStructHelper a reusable {@link FillOutStructureHelper} instance to be used
@@ -22,10 +22,10 @@ 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.symbol.SourceType;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.exception.*;
/**
* This command will create a TypeDescriptor data type. Since unsized arrays are not properly
@@ -133,8 +133,10 @@ public class CreateTypeDescriptorBackgroundCmd
Program program = model.getProgram();
String demangledName = model.getDemangledTypeDescriptor();
// if cannot demangle then use the mangled name
if (demangledName == null) {
return false;
demangledName = model.getOriginalTypename();
}
String prefix = demangledName + " ";
@@ -147,9 +149,25 @@ public class CreateTypeDescriptorBackgroundCmd
// Label
Namespace classNamespace = model.getDescriptorAsNamespace();
if (classNamespace == null) {
Msg.error(RttiUtil.class, "Cannot get namespace from model " + model.getAddress());
return false;
// if cannot demangle then use the mangled name as the namespace
if (classNamespace == null || classNamespace.isGlobal()) {
Msg.error(RttiUtil.class, "Cannot get demangled namespace from model " +
model.getAddress() + " so will use the mangled name for the namespace");
try {
classNamespace = program.getSymbolTable()
.getOrCreateNameSpace(program.getGlobalNamespace(), demangledName,
SourceType.IMPORTED);
}
catch (DuplicateNameException e) {
// ok if it is duplicate as it was likely created in another rtti handling method
}
catch (InvalidInputException e) {
Msg.error(TypeDescriptorModel.class,
"Failed to create mangled namespace: " + e.getMessage());
classNamespace = null;
return false;
}
}
// If PDB had been run, then the namespace here might already have been promoted to
@@ -28,11 +28,9 @@ import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.DumbMemBufferImpl;
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.program.model.symbol.*;
import ghidra.util.Msg;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.*;
import ghidra.util.task.TaskMonitor;
/**
@@ -473,6 +471,10 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
return hasComplexType() ? demangledDataType.getOriginalDemangled() : null;
}
public String getOriginalTypename() {
return originalTypeName;
}
/**
* Gets just the name of the type descriptor.
* @return the name of the thing referred to by this descriptor, or null if it couldn't
@@ -583,6 +585,23 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
Program program = getProgram();
namespace = DemangledObject.createNamespace(program, demangledDataType,
program.getGlobalNamespace(), false);
// if for some reason the mangled name can't be demangled, use the mangled name
if (namespace.isGlobal()) {
try {
namespace = program.getSymbolTable()
.getOrCreateNameSpace(program.getGlobalNamespace(), originalTypeName,
SourceType.IMPORTED);
}
catch (DuplicateNameException e) {
// ok if it is duplicate as it was likely created in another rtti handling method
}
catch (InvalidInputException e) {
Msg.error(TypeDescriptorModel.class,
"Failed to create namespace: " + e.getMessage());
namespace = null;
}
}
return namespace;
}
@@ -119,7 +119,7 @@ public class CreateVfTableBackgroundCmd extends AbstractCreateDataBackgroundCmd<
String demangledTypeDescriptor = rtti0Model.getDemangledTypeDescriptor();
String prefixString = ((demangledTypeDescriptor != null)
? (demangledTypeDescriptor + Namespace.DELIMITER)
: "");
: rtti0Model.getOriginalTypename() + Namespace.DELIMITER);
data.setComment(CommentType.EOL, "terminator for " + prefixString + VF_TABLE_LABEL);
return true;
}
@@ -321,7 +321,11 @@ public class RttiUtil {
public static String getDescriptorTypeNamespace(TypeDescriptorModel rtti0Model) {
String descriptorTypeNamespace = rtti0Model.getDescriptorTypeNamespace(); // Can be null.
if (descriptorTypeNamespace == null) {
descriptorTypeNamespace = ""; // Couldn't get namespace so leave it off.
descriptorTypeNamespace = rtti0Model.getOriginalTypename();
Msg.warn(RttiUtil.class, rtti0Model.getAddress().toString() +
": Could not demangle TypeDescriptor namespace so using the mangled string as the namespace.");
}
return descriptorTypeNamespace;
}