This commit is contained in:
2025-05-29 23:59:05 +08:00
parent 35a220de3f
commit 4a669d86b7
12 changed files with 5901 additions and 655 deletions

View File

@@ -1,8 +1,6 @@
// Source code is decompiled from a .class file using FernFlower decompiler.
package re3lib;
import ghidra.app.script.GhidraScript;
import ghidra.app.script.ScriptMessage;
import ghidra.program.model.data.*;
import ghidra.program.model.data.Enum;
import ghidra.util.Msg;
@@ -13,7 +11,8 @@ import java.io.Writer;
import java.util.*;
public class DataTypeWriter {
public HashSet<String> blacklistedTypes;
public HashSet<String> requiredFunctionTypes;
public HashMap<String, FunctionDefinition> lazyFunctionTypeBlocks;
private static String[] INTEGRAL_TYPES = new String[] { "char", "short", "int", "long", "long long", "__int64",
"float", "double", "long double", "void" };
@@ -54,7 +53,6 @@ public class DataTypeWriter {
public DataTypeWriter(DataTypeManager dtm, Writer writer, AnnotationHandler annotator, boolean cppStyleComments)
throws IOException {
this.blacklistedTypes = new HashSet<>();
this.cppStyleComments = false;
this.dtm = dtm;
if (dtm != null) {
@@ -68,6 +66,8 @@ public class DataTypeWriter {
this.writer = writer;
this.annotator = annotator;
this.cppStyleComments = cppStyleComments;
this.requiredFunctionTypes = new HashSet<>();
this.lazyFunctionTypeBlocks = new HashMap<>();
}
private String comment(String text) {
@@ -118,7 +118,7 @@ public class DataTypeWriter {
for (DataType dataType : dataTypes) {
monitor.checkCancelled();
if (dataType == null || blacklistedTypes.contains(dataType.getDisplayName())) {
if (dataType == null) {
continue;
}
@@ -138,7 +138,20 @@ public class DataTypeWriter {
monitor.setProgress((long) cnt);
}
// Step 2: Topological sort and write
// Step 2: Check if we're missing any function type typedefs
for (String funcName : requiredFunctionTypes) {
if (!blocks.containsKey(funcName)) {
FunctionDefinition funcType = lazyFunctionTypeBlocks.get(funcName);
Set<String> dependencies = new HashSet<>();
StringBuilder code = new StringBuilder();
this.writeFunctionDefinitionBlock(funcType, funcName, code, dependencies);
blocks.put(funcName, new Block(funcType, code.toString(), dependencies));
}
}
// Step 3: Topological sort and write
List<Block> sortedBlocks = topologicalSort(blocks);
for (Block block : sortedBlocks) {
writer.write(block.code);
@@ -157,9 +170,9 @@ public class DataTypeWriter {
Set<String> dependencies = new HashSet<>();
StringBuilder code = new StringBuilder();
if (dt.getDisplayName().contains("HIE_tduLinkedObject")) {
System.out.println("DEBUG " + dt.getDisplayName());
}
// if (dt.getDisplayName().contains("HIE_tduLinkedObject")) {
// System.out.println("DEBUG " + dt.getDisplayName());
// }
if (dt.equals(DataType.DEFAULT)) {
code.append("typedef unsigned char ").append(DataType.DEFAULT.getName()).append(";");
@@ -176,12 +189,16 @@ public class DataTypeWriter {
} else if (dt instanceof Union) {
writeUnionBlock((Union) dt, code, dependencies);
} else if (dt instanceof Enum) {
if(dt.getDisplayName().contains(".conflict"))
return null;
writeEnumBlock((Enum) dt, code, dependencies);
} else if (dt instanceof TypeDef) {
writeTypeDefBlock((TypeDef) dt, code, dependencies);
} else if (dt instanceof BuiltInDataType) {
writeBuiltInBlock((BuiltInDataType) dt, code, dependencies);
} else if (dt instanceof FunctionDefinition) {
// Store these for later, a lot of them are going to be unused
lazyFunctionTypeBlocks.put(dt.getDisplayName(), (FunctionDefinition) dt);
return null;
} else {
code.append(comment("Unable to write datatype. Type unrecognized: " + dt.getClass()));
@@ -248,6 +265,9 @@ public class DataTypeWriter {
DataType depType = getImmediateDependencyType(componentDataType);
if (depType != null) {
dependencies.add(depType.getDisplayName());
if(depType instanceof FunctionDefinition) {
requiredFunctionTypes.add(depType.getDisplayName());
}
}
code.append(getTypeDeclaration(fieldName, componentDataType, component.getLength()));
@@ -300,7 +320,7 @@ public class DataTypeWriter {
}
}
private void writeFunctionDefinitionBlock(FunctionDefinition funcDef, String name, StringBuilder code,
private boolean writeFunctionDefinitionBlock(FunctionDefinition funcDef, String name, StringBuilder code,
Set<String> dependencies) {
DataType returnType = funcDef.getReturnType();
ParameterDefinition[] params = funcDef.getArguments();
@@ -351,20 +371,29 @@ public class DataTypeWriter {
}
code.append(");");
return true;
}
private void writeTypeDefBlock(TypeDef typeDef, StringBuilder code, Set<String> dependencies) {
private boolean writeTypeDefBlock(TypeDef typeDef, StringBuilder code, Set<String> dependencies) {
String typedefName = typeDef.getDisplayName();
DataType dataType = typeDef.getDataType();
String dataTypeName = dataType.getDisplayName();
// Handle function definition typedefs
if (dataType instanceof FunctionDefinition) {
writeFunctionDefinitionBlock((FunctionDefinition) dataType, typedefName, code, dependencies);
return writeFunctionDefinitionBlock((FunctionDefinition) dataType, typedefName, code, dependencies);
} // Could be pointer to function
else if (dataType instanceof Pointer && ((Pointer) dataType).getDataType() instanceof FunctionDefinition) {
writeFunctionDefinitionBlock((FunctionDefinition) ((Pointer) dataType).getDataType(), typedefName, code,
dependencies);
else if (dataType instanceof Pointer) {
Pointer ptr = (Pointer) dataType;
if (ptr.getDataType() instanceof FunctionDefinition) {
return writeFunctionDefinitionBlock((FunctionDefinition) ((Pointer) dataType).getDataType(), typedefName, code,
dependencies);
} else {
// Try to write the typedef as a forward declaration
code.append("typedef ");
code.append(getTypeDeclaration(typedefName, dataType, -1));
code.append(";");
return true;
}
} else {
DataType depType = getImmediateDependencyType(dataType);
if (depType != null && !isBuiltInType(depType)) {
@@ -373,6 +402,7 @@ public class DataTypeWriter {
String typedefString = getTypeDeclaration(typedefName, dataType, -1);
code.append("typedef ").append(typedefString).append(";");
return true;
}
}

View File

@@ -13,6 +13,7 @@ import ghidra.program.model.data.Composite;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.Enum;
import ghidra.program.model.data.EnumDataType;
import ghidra.program.model.data.FunctionDefinition;
import ghidra.program.model.data.ProgramBasedDataTypeManager;
import ghidra.program.model.data.Structure;
import ghidra.program.model.data.TypeDef;
@@ -86,24 +87,24 @@ public class TypeDumper {
continue;
if (dt instanceof Structure || dt instanceof TypeDef || dt instanceof EnumDataType
|| dt instanceof Union || dt instanceof Enum) {
|| dt instanceof Union || dt instanceof Enum || dt instanceof FunctionDefinition) {
if (dt.getDisplayName().contains("NormalizeFn"))
if (dt.getDisplayName().contains("NormalizeFn") || dt.getDisplayName().contains("_M_IX86"))
script.println("DEBUG " + dt.getDisplayName() + " - " + dt.getClass().getSimpleName());
if (dt.getDisplayName().contains("tdstObjectTypeElement_") ||
dt.getDisplayName().contains("ObjectTypeElementHandle"))
// if (dt.getDisplayName().contains("tdstObjectTypeElement_") ||
// dt.getDisplayName().contains("ObjectTypeElementHandle"))
filteredTypes.add(dt);
filteredTypes.add(dt);
}
// }
}
String s = "";
for (DataType dataType : filteredTypes) {
s += dataType.getDisplayName() + ", ";
}
script.println(s);
// String s = "";
// for (DataType dataType : filteredTypes) {
// s += dataType.getDisplayName() + ", ";
// }
// script.println(s);
try (PrintWriter writer = new PrintWriter(new File(RemanConfig.INSTANCE.outputDir, "gh_types.h"),
"UTF-8")) {
@@ -112,7 +113,6 @@ public class TypeDumper {
writer.println("#include <r3/binders/type.h>");
DataTypeWriter dtw = new DataTypeWriter(dtm, writer);
dtw.blacklistedTypes = typeBlacklist;
dtw.write(filteredTypes, script.getMonitor());
Utils.headerGuardPost(writer, "STRUCTS");