diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java index c85958659e..682cac0430 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunctionDBUtil.java @@ -793,8 +793,21 @@ public class HighFunctionDBUtil { boolean nameCollision = false; Variable[] localVariables = function.getLocalVariables(VariableFilter.UNIQUE_VARIABLE_FILTER); + // Clean out any facet symbols with bad data-types + for (int i = 0; i < localVariables.length; ++i) { + Variable var = localVariables[i]; + if (var.getName().startsWith(UnionFacetSymbol.BASENAME)) { + if (!UnionFacetSymbol.isUnionType(var.getDataType())) { + function.removeVariable(var); + localVariables[i] = null; + } + } + } Variable preexistingVar = null; for (Variable var : localVariables) { + if (var == null) { + continue; + } if (var.getFirstUseOffset() == firstUseOffset && var.getFirstStorageVarnode().getOffset() == hash) { preexistingVar = var; @@ -807,10 +820,12 @@ public class HighFunctionDBUtil { symbolName = symbolName + '_' + Integer.toHexString(DynamicHash.getComparable(hash)); } if (preexistingVar != null) { - if (preexistingVar.getName().equals(symbolName)) { - return; // No change to make + if (!preexistingVar.getName().equals(symbolName)) { + preexistingVar.setName(symbolName, source); // Change the name + } + if (!preexistingVar.getDataType().equals(dt)) { + preexistingVar.setDataType(dt, source); } - preexistingVar.setName(symbolName, source); // Change the name return; } Program program = function.getProgram(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java index 417e1e26d1..c4179411f2 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/LocalSymbolMap.java @@ -453,7 +453,7 @@ public class LocalSymbolMap { id = getNextId(); } HighSymbol sym; - if (DynamicHash.getMethodFromHash(hash) > 3) { + if (DynamicHash.getMethodFromHash(hash) > 3 && UnionFacetSymbol.isUnionType(dt)) { int fieldNum = UnionFacetSymbol.extractFieldNumber(nm); sym = new UnionFacetSymbol(id, nm, dt, fieldNum, func); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/UnionFacetSymbol.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/UnionFacetSymbol.java index f9a665a230..884ca384f2 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/UnionFacetSymbol.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/UnionFacetSymbol.java @@ -21,7 +21,7 @@ import static ghidra.program.model.pcode.ElementId.*; import java.io.IOException; import ghidra.program.model.address.Address; -import ghidra.program.model.data.DataType; +import ghidra.program.model.data.*; /** * A specialized HighSymbol that directs the decompiler to use a specific field of a union, @@ -80,4 +80,26 @@ public class UnionFacetSymbol extends HighSymbol { } return Integer.decode(nm.substring(pos + BASENAME.length(), endpos)) - 1; } + + /** + * Return true if the given data-type is either a union or a pointer to a union + * and is suitable for being the data-type of UnionFacetSymbol + * @param dt is the given data-type + * @return true if the data-type is a union or a pointer to a union + */ + public static boolean isUnionType(DataType dt) { + if (dt instanceof TypeDef) { + dt = ((TypeDef) dt).getBaseDataType(); + } + if (dt instanceof Pointer) { + dt = ((Pointer) dt).getDataType(); + if (dt == null) { + return false; + } + if (dt instanceof TypeDef) { + dt = ((TypeDef) dt).getBaseDataType(); + } + } + return (dt instanceof Union); + } }