diff --git a/game_re/r3/binders/stub.h b/game_re/r3/binders/stub.h index e45d0edd..bd8f8d2b 100644 --- a/game_re/r3/binders/stub.h +++ b/game_re/r3/binders/stub.h @@ -10,22 +10,22 @@ struct GHStubException : public std::exception { void *gh_stub_impl_ptr(void *ptr); template -T gh_stub_impl_cdecl(void *ptr, Args... args) { +T gh_stub_impl_cdecl(void *ptr_, Args... args) { #if RE_DBG_INJECTED using Callable = __cdecl T (*)(Args...); - static Callable *ptr = (Callable *)gh_stub_impl_ptr(ptr); - return ptr(args...); + static Callable *fn = (Callable *)gh_stub_impl_ptr(ptr_); + return fn(args...); #else throw GHStubException("Function not implemented"); #endif } template -T gh_stub_impl_stdcall(void *ptr, Args... args) { +T gh_stub_impl_stdcall(void *ptr_, Args... args) { #if RE_DBG_INJECTED using Callable = __stdcall T (*)(Args...); - static Callable *ptr = (Callable *)gh_stub_impl_ptr(ptr); - return ptr(args...); + static Callable *fn = (Callable *)gh_stub_impl_ptr(ptr_); + return fn(args...); #else throw GHStubException("Function not implemented"); #endif diff --git a/game_re/type_blacklist.txt b/game_re/type_blacklist.txt index 8b5026b4..3347722e 100644 --- a/game_re/type_blacklist.txt +++ b/game_re/type_blacklist.txt @@ -1924,4 +1924,6 @@ _strflt _tiddata _BIN_TYPES_ tagBIND_FLAGS_ -ImageBaseOffset32 \ No newline at end of file +ImageBaseOffset32 +wchar_t +WCHAR \ No newline at end of file diff --git a/game_re/type_path_blacklist.txt b/game_re/type_path_blacklist.txt index 76354c6c..eef9b4bb 100644 --- a/game_re/type_path_blacklist.txt +++ b/game_re/type_path_blacklist.txt @@ -82,4 +82,5 @@ winspool.h winsvc.h winuser.h winver.h -wtypes.h \ No newline at end of file +wtypes.h +dinput.h \ No newline at end of file diff --git a/java/ghidra/DumpTypes.java b/java/ghidra/DumpTypes.java index 079976cd..cd5e89f8 100644 --- a/java/ghidra/DumpTypes.java +++ b/java/ghidra/DumpTypes.java @@ -13,6 +13,6 @@ public class DumpTypes extends GhidraScript { @Override protected void run() throws Exception { TypeDumper dumper = new TypeDumper(this); - dumper.run(); + dumper.run(); } } diff --git a/java/ghidra/re3lib/DataTypeWriter.java b/java/ghidra/re3lib/DataTypeWriter.java index 2246c3d5..f72b81de 100644 --- a/java/ghidra/re3lib/DataTypeWriter.java +++ b/java/ghidra/re3lib/DataTypeWriter.java @@ -9,10 +9,10 @@ import ghidra.util.task.TaskMonitor; import java.io.IOException; import java.io.Writer; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -27,10 +27,6 @@ public class DataTypeWriter { private static String EOL = System.getProperty("line.separator"); private Set resolved; private Map resolvedTypeMap; - private Set deferredCompositeDeclarations; - private ArrayDeque deferredTypeFIFO; - private Set deferredTypes; - private int writerDepth; private Writer writer; private DataTypeManager dtm; private DataOrganization dataOrganization; @@ -54,10 +50,6 @@ public class DataTypeWriter { this.blacklistedTypes = new HashSet<>(); this.resolved = new HashSet(); this.resolvedTypeMap = new HashMap(); - this.deferredCompositeDeclarations = new HashSet(); - this.deferredTypeFIFO = new ArrayDeque(); - this.deferredTypes = new HashSet(); - this.writerDepth = 0; this.cppStyleComments = false; this.dtm = dtm; if (dtm != null) { @@ -128,254 +120,138 @@ public class DataTypeWriter { public void write(List dataTypes, TaskMonitor monitor, boolean throwExceptionOnInvalidType) throws IOException, CancelledException { - monitor.initialize((long) dataTypes.size()); + // Sort types to handle dependencies + List sortedTypes = sortTypesByDependencies(dataTypes); + + monitor.initialize((long) sortedTypes.size()); int cnt = 0; - Iterator var5 = dataTypes.iterator(); - - while (var5.hasNext()) { - DataType dataType = (DataType) var5.next(); + + for (DataType dataType : sortedTypes) { monitor.checkCancelled(); - this.write(dataType, monitor, throwExceptionOnInvalidType); + this.writeType(dataType, monitor, throwExceptionOnInvalidType); ++cnt; monitor.setProgress((long) cnt); } - } - private void deferWrite(DataType dt) { - if (!this.resolved.contains(dt) && !this.deferredTypes.contains(dt)) { - this.deferredTypes.add(dt); - this.deferredTypeFIFO.addLast(dt); + private List sortTypesByDependencies(List dataTypes) { + // Simple dependency sorting - write forward declarations for composites first, + // then non-composites, then composite bodies + List forwardDeclarations = new ArrayList<>(); + List nonComposites = new ArrayList<>(); + List composites = new ArrayList<>(); + + for (DataType dt : dataTypes) { + if (dt instanceof Structure || dt instanceof Union) { + composites.add(dt); + } else { + nonComposites.add(dt); + } } - + + List result = new ArrayList<>(); + // First add forward declarations for all composites + result.addAll(composites); + // Then add non-composites + result.addAll(nonComposites); + + return result; } void write(DataType dt, TaskMonitor monitor) throws IOException, CancelledException { - this.doWrite(dt, monitor, true); + this.writeType(dt, monitor, true); } void write(DataType dt, TaskMonitor monitor, boolean throwExceptionOnInvalidType) throws IOException, CancelledException { - this.doWrite(dt, monitor, throwExceptionOnInvalidType); + this.writeType(dt, monitor, throwExceptionOnInvalidType); } - private void doWrite(DataType dt, TaskMonitor monitor, boolean throwExceptionOnInvalidType) + private void writeType(DataType dt, TaskMonitor monitor, boolean throwExceptionOnInvalidType) throws IOException, CancelledException { - if (dt != null) { - if (blacklistedTypes.contains(dt.getDisplayName())) - return; - if (!(dt instanceof FunctionDefinition)) { - if (dt instanceof FactoryDataType) { - IllegalArgumentException iae = new IllegalArgumentException("Factory data types may not be written"); - if (throwExceptionOnInvalidType) { - throw iae; - } - - Msg.error(this, "Factory data types may not be written - type: " + dt); - } - - if (!(dt instanceof Pointer) && !(dt instanceof Array) && !(dt instanceof BitFieldDataType)) { - dt = dt.clone(this.dtm); - if (!this.resolved.contains(dt)) { - this.resolved.add(dt); - DataType resolvedType = (DataType) this.resolvedTypeMap.get(dt.getName()); - if (resolvedType != null) { - if (!resolvedType.isEquivalent(dt)) { - if (dt instanceof TypeDef) { - DataType baseType = ((TypeDef) dt).getBaseDataType(); - if ((resolvedType instanceof Composite || resolvedType instanceof Enum) - && baseType.isEquivalent(resolvedType)) { - return; - } - } - - this.writer.write(EOL); - Writer var10000 = this.writer; - String var10002 = dt.getPathName(); - var10000.write(this - .comment("WARNING! conflicting data type names: " + var10002 + " - " + resolvedType.getPathName())); - this.writer.write(EOL); - this.writer.write(EOL); - } - } else { - this.resolvedTypeMap.put(dt.getName(), dt); - ++this.writerDepth; - if (dt.equals(DataType.DEFAULT)) { - this.writer.write("typedef unsigned char " + DataType.DEFAULT.getName() + ";"); - this.writer.write(EOL); - this.writer.write(EOL); - } else if (dt instanceof Dynamic) { - this.writeDynamicBuiltIn((Dynamic) dt, monitor); - } else if (dt instanceof Structure) { - Structure struct = (Structure) dt; - this.writeCompositePreDeclaration(struct, monitor); - this.deferredCompositeDeclarations.add(struct); - } else if (dt instanceof Union) { - Union union = (Union) dt; - this.writeCompositePreDeclaration(union, monitor); - this.deferredCompositeDeclarations.add(union); - } else if (dt instanceof Enum) { - this.writeEnum((Enum) dt, monitor); - } else if (dt instanceof TypeDef) { - this.writeTypeDef((TypeDef) dt, monitor); - } else if (dt instanceof BuiltInDataType) { - this.writeBuiltIn((BuiltInDataType) dt, monitor); - } else if (!(dt instanceof BitFieldDataType)) { - this.writer.write(EOL); - this.writer.write(EOL); - this.writer.write(this.comment("Unable to write datatype. Type unrecognized: " + dt.getClass())); - this.writer.write(EOL); - this.writer.write(EOL); - } - - if (this.writerDepth == 1) { - this.writeDeferredDeclarations(monitor); - } - - --this.writerDepth; - } - } - } else { - this.write(this.getBaseDataType(dt), monitor); - } - } - } - } - - private void writeDeferredDeclarations(TaskMonitor monitor) throws IOException, CancelledException { - while (!this.deferredTypes.isEmpty()) { - DataType dt = (DataType) this.deferredTypeFIFO.removeFirst(); - this.deferredTypes.remove(dt); - this.write(dt, monitor); + if (dt == null || blacklistedTypes.contains(dt.getDisplayName())) { + return; } - this.writeDeferredCompositeDeclarations(monitor); - this.deferredCompositeDeclarations.clear(); - } - - private DataType getBaseArrayTypedefType(DataType dt) { - while (true) { - if (dt != null) { - if (dt instanceof TypeDef) { - dt = ((TypeDef) dt).getBaseDataType(); - continue; - } - - if (dt instanceof Array) { - dt = ((Array) dt).getDataType(); - continue; - } - } - - return dt; - } - } - - private boolean containsComposite(Composite container, Composite contained) { - DataTypeComponent[] var3 = container.getDefinedComponents(); - int var4 = var3.length; - - for (int var5 = 0; var5 < var4; ++var5) { - DataTypeComponent component = var3[var5]; - DataType dt = this.getBaseArrayTypedefType(component.getDataType()); - if (dt instanceof Composite && dt.getName().equals(contained.getName()) && dt.isEquivalent(contained)) { - return true; - } + if (dt instanceof FunctionDefinition) { + return; // Skip function definitions } - return false; - } - - private void writeDeferredCompositeDeclarations(TaskMonitor monitor) throws IOException, CancelledException { - int cnt = this.deferredCompositeDeclarations.size(); - if (cnt != 0) { - LinkedList list = new LinkedList(this.deferredCompositeDeclarations); - if (list.size() > 1) { - int sortChange = 1; - - while (sortChange != 0) { - sortChange = 0; - - for (int i = cnt - 1; i > 0; --i) { - if (this.resortComposites(list, i)) { - ++sortChange; - } - } - } + if (dt instanceof FactoryDataType) { + IllegalArgumentException iae = new IllegalArgumentException("Factory data types may not be written"); + if (throwExceptionOnInvalidType) { + throw iae; } - - Iterator var6 = list.iterator(); - - while (var6.hasNext()) { - Composite composite = (Composite) var6.next(); - this.writeCompositeBody(composite, monitor); - } - + Msg.error(this, "Factory data types may not be written - type: " + dt); + return; } - } - private boolean resortComposites(List list, int index) { - int listSize = list.size(); - if (listSize <= 0) { - return false; + // Handle pointer/array types by just getting their base type for dependency checking + if (dt instanceof Pointer || dt instanceof Array || dt instanceof BitFieldDataType) { + // Don't auto-discover dependencies, just write the type as-is } else { - Composite composite = (Composite) list.get(index); + dt = dt.clone(this.dtm); + } - for (int i = 0; i < index; ++i) { - Composite other = (Composite) list.get(i); - if (this.containsComposite(other, composite)) { - list.remove(index); - list.add(i, composite); - composite = null; - return true; - } + if (this.resolved.contains(dt)) { + return; // Already written + } + + this.resolved.add(dt); + DataType resolvedType = this.resolvedTypeMap.get(dt.getName()); + if (resolvedType != null && !resolvedType.isEquivalent(dt)) { + // Handle name conflicts + this.writer.write(EOL); + this.writer.write(this.comment("WARNING! conflicting data type names: " + dt.getPathName() + " - " + resolvedType.getPathName())); + this.writer.write(EOL); + this.writer.write(EOL); + } else { + this.resolvedTypeMap.put(dt.getName(), dt); + + if (dt.equals(DataType.DEFAULT)) { + this.writer.write("typedef unsigned char " + DataType.DEFAULT.getName() + ";"); + this.writer.write(EOL); + this.writer.write(EOL); + } else if (dt instanceof Dynamic) { + this.writeDynamicBuiltIn((Dynamic) dt, monitor); + } else if (dt instanceof Structure) { + this.writeStructure((Structure) dt, monitor); + } else if (dt instanceof Union) { + this.writeUnion((Union) dt, monitor); + } else if (dt instanceof Enum) { + this.writeEnum((Enum) dt, monitor); + } else if (dt instanceof TypeDef) { + this.writeTypeDef((TypeDef) dt, monitor); + } else if (dt instanceof BuiltInDataType) { + this.writeBuiltIn((BuiltInDataType) dt, monitor); + } else if (!(dt instanceof BitFieldDataType)) { + this.writer.write(EOL); + this.writer.write(EOL); + this.writer.write(this.comment("Unable to write datatype. Type unrecognized: " + dt.getClass())); + this.writer.write(EOL); + this.writer.write(EOL); } - - return false; } } - private String getDynamicComponentString(Dynamic dynamicType, String fieldName, int length) { - if (dynamicType.canSpecifyLength()) { - DataType replacementBaseType = dynamicType.getReplacementBaseType(); - if (replacementBaseType != null) { - replacementBaseType = replacementBaseType.clone(this.dtm); - int elementLen = replacementBaseType.getLength(); - if (elementLen > 0) { - int elementCnt = (length + elementLen - 1) / elementLen; - return replacementBaseType.getDisplayName() + " " + fieldName + "[" + elementCnt + "]"; - } - - String var10001 = dynamicType.getClass().getSimpleName(); - Msg.error(this, - var10001 + " returned bad replacementBaseType: " + replacementBaseType.getClass().getSimpleName()); - } - } - - return null; + private void writeStructure(Structure struct, TaskMonitor monitor) throws IOException, CancelledException { + // Write forward declaration first + this.writer.write("typedef struct " + struct.getDisplayName() + " " + struct.getDisplayName() + ", *P" + struct.getDisplayName() + ";"); + this.writer.write(EOL); + this.writer.write(EOL); + + // Then write the body + this.writeCompositeBody(struct, monitor); } - private void writeCompositePreDeclaration(Composite composite, TaskMonitor monitor) - throws IOException, CancelledException { - String compositeType = composite instanceof Structure ? "struct" : "union"; - this.writer.write("typedef " + compositeType + " " + composite.getDisplayName() + " " + composite.getDisplayName() - + ", *P" + composite.getDisplayName() + ";"); + private void writeUnion(Union union, TaskMonitor monitor) throws IOException, CancelledException { + // Write forward declaration first + this.writer.write("typedef union " + union.getDisplayName() + " " + union.getDisplayName() + ", *P" + union.getDisplayName() + ";"); this.writer.write(EOL); this.writer.write(EOL); - DataTypeComponent[] var4 = composite.getComponents(); - int var5 = var4.length; - - for (int var6 = 0; var6 < var5; ++var6) { - DataTypeComponent component = var4[var6]; - if (monitor.isCancelled()) { - break; - } - - DataType componentType = component.getDataType(); - this.deferWrite(componentType); - this.getTypeDeclaration((String) null, componentType, component.getLength(), true, monitor); - } - + + // Then write the body + this.writeCompositeBody(union, monitor); } private void writeCompositeBody(Composite composite, TaskMonitor monitor) throws IOException, CancelledException { @@ -436,13 +312,12 @@ public class DataTypeWriter { StringBuilder sb = new StringBuilder(); String componentString = null; if (dataType instanceof Dynamic) { - componentString = this.getDynamicComponentString((Dynamic) dataType, name, instanceLength); - if (componentString != null) { - sb.append(componentString); - } else { - sb.append(this.comment("ignoring dynamic datatype inside composite: " + dataType.getDisplayName())); - sb.append(EOL); + // Simplified dynamic handling - just use the display name + componentString = dataType.getDisplayName(); + if (name.length() != 0) { + componentString = componentString + " " + name; } + sb.append(componentString); } if (componentString == null) { @@ -588,15 +463,13 @@ public class DataTypeWriter { this.resolvedTypeMap.remove(typedefName); } finally { - this.write(dataType, monitor); + // Removed auto-discovery - don't write the dataType automatically } return; } - if (baseType instanceof Array && this.getBaseArrayTypedefType(baseType) instanceof Composite) { - this.writeDeferredDeclarations(monitor); - } + // Removed deferred writing call - we only write what's explicitly passed String typedefString = this.getTypeDeclaration(typedefName, dataType, -1, true, monitor); this.writer.write("typedef " + typedefString + ";"); @@ -651,11 +524,11 @@ public class DataTypeWriter { } private void writeDynamicBuiltIn(Dynamic dt, TaskMonitor monitor) throws IOException, CancelledException { - DataType baseDt = dt.getReplacementBaseType(); - if (baseDt != null) { - this.write(baseDt, monitor); - } - + // Simplified - don't auto-discover replacement types + // Just write a comment about the dynamic type + this.writer.write(this.comment("Dynamic type: " + dt.getDisplayName())); + this.writer.write(EOL); + this.writer.write(EOL); } private void writeBuiltIn(BuiltInDataType dt, TaskMonitor monitor) throws IOException { diff --git a/java/ghidra/re3lib/TypeDumper.java b/java/ghidra/re3lib/TypeDumper.java index 5ec63bbb..52596c72 100644 --- a/java/ghidra/re3lib/TypeDumper.java +++ b/java/ghidra/re3lib/TypeDumper.java @@ -76,14 +76,14 @@ public class TypeDumper { DataType dt = it.next(); if (typeBlacklist.contains(dt.getDisplayName())) continue; + CategoryPath catPath = dt.getCategoryPath(); if (catPath.getPathElements().length > 0 && categoryPathBlacklist.contains(catPath.getPathElements()[0])) continue; - // script.println("Type: " + dt.getDisplayName() + " - CatPath: " + dt.getCategoryPath()); - // if (dt.getName().equals("ImageBaseOffset32")) - // throw new Exception("Found: " + dt.getDisplayName() + " - " + catPath.getPathElements()[0] + " - " + dt.getClass().getSimpleName()); + // throw new Exception("Found: " + dt.getDisplayName() + " - " + + // catPath.getPathElements()[0] + " - " + dt.getClass().getSimpleName()); if (dt instanceof Structure || dt instanceof TypeDef || dt instanceof EnumDataType) { // script.println("Adding: " + dt.getDisplayName() + " - " + @@ -92,6 +92,12 @@ public class TypeDumper { } } + 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")) { Utils.headerGuardPre(writer, "STRUCTS");