AppModel: IDA output integration; item groups
This commit is contained in:
@@ -12,6 +12,10 @@ namespace Il2CppInspector.Model
|
|||||||
// Class that represents a composite IL/C++ method
|
// Class that represents a composite IL/C++ method
|
||||||
public class AppMethod
|
public class AppMethod
|
||||||
{
|
{
|
||||||
|
// The logical group this method is part of
|
||||||
|
// This is purely for querying methods in related groups and has no bearing on the code
|
||||||
|
public string Group { get; set; }
|
||||||
|
|
||||||
// The corresponding C++ function pointer type
|
// The corresponding C++ function pointer type
|
||||||
public CppFnPtrType CppFnPtrType { get; internal set; }
|
public CppFnPtrType CppFnPtrType { get; internal set; }
|
||||||
|
|
||||||
|
|||||||
@@ -26,16 +26,16 @@ namespace Il2CppInspector.Model
|
|||||||
public CppCompilerType TargetCompiler { get; private set; }
|
public CppCompilerType TargetCompiler { get; private set; }
|
||||||
|
|
||||||
// The Unity version used to build the binary
|
// The Unity version used to build the binary
|
||||||
public UnityVersion UnityVersion { get; set; } // TODO: Change to private set after integrating IDA output
|
public UnityVersion UnityVersion { get; private set; }
|
||||||
|
|
||||||
// The Unity IL2CPP C++ headers for the binary
|
// The Unity IL2CPP C++ headers for the binary
|
||||||
// Use this for code output
|
// Use this for code output
|
||||||
public UnityHeader UnityHeader { get; set; } // TODO: Change to private set after integrating IDA output
|
public UnityHeader UnityHeader { get; private set; }
|
||||||
|
|
||||||
// All of the C++ types used in the application including Unity internal types
|
// All of the C++ types used in the application including Unity internal types
|
||||||
// NOTE: This is for querying individual types for static analysis
|
// NOTE: This is for querying individual types for static analysis
|
||||||
// To generate code output, use DependencyOrderedCppTypes
|
// To generate code output, use DependencyOrderedCppTypes
|
||||||
public CppTypeCollection CppTypeCollection { get; set; } // TODO: Change to private set after integrating IDA output
|
public CppTypeCollection CppTypeCollection { get; private set; }
|
||||||
|
|
||||||
// All of the C++ types used in the application (.NET type translations only)
|
// All of the C++ types used in the application (.NET type translations only)
|
||||||
// The types are ordered to enable the production of code output without forward dependencies
|
// The types are ordered to enable the production of code output without forward dependencies
|
||||||
@@ -53,6 +53,8 @@ namespace Il2CppInspector.Model
|
|||||||
// For il2cpp < 19, the key is the string literal ordinal instead of the address
|
// For il2cpp < 19, the key is the string literal ordinal instead of the address
|
||||||
public Dictionary<ulong, string> Strings = new Dictionary<ulong, string>();
|
public Dictionary<ulong, string> Strings = new Dictionary<ulong, string>();
|
||||||
|
|
||||||
|
public bool StringIndexesAreOrdinals => Package.MetadataUsages == null;
|
||||||
|
|
||||||
// The .NET type model for the application
|
// The .NET type model for the application
|
||||||
public TypeModel ILModel { get; }
|
public TypeModel ILModel { get; }
|
||||||
|
|
||||||
@@ -64,8 +66,7 @@ namespace Il2CppInspector.Model
|
|||||||
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable) CppTypeCollection).GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable) CppTypeCollection).GetEnumerator();
|
||||||
|
|
||||||
// The C++ declaration generator for this binary
|
// The C++ declaration generator for this binary
|
||||||
// TODO: Make this private once IDA output integration is completed
|
internal CppDeclarationGenerator declarationGenerator; // TODO: Make private when name integration completed
|
||||||
internal CppDeclarationGenerator declarationGenerator;
|
|
||||||
|
|
||||||
// Convenience properties
|
// Convenience properties
|
||||||
|
|
||||||
@@ -81,6 +82,16 @@ namespace Il2CppInspector.Model
|
|||||||
// The Unity header text including word size define
|
// The Unity header text including word size define
|
||||||
public string UnityHeaderText => (WordSize == 32 ? "#define IS_32BIT\n" : "") + UnityHeader.GetHeaderText();
|
public string UnityHeaderText => (WordSize == 32 ? "#define IS_32BIT\n" : "") + UnityHeader.GetHeaderText();
|
||||||
|
|
||||||
|
// The group that the next added type(s) will be placed in
|
||||||
|
private string group = string.Empty;
|
||||||
|
private string Group {
|
||||||
|
get => group;
|
||||||
|
set {
|
||||||
|
group = value;
|
||||||
|
CppTypeCollection.SetGroup(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
public AppModel(TypeModel model) {
|
public AppModel(TypeModel model) {
|
||||||
// Save .NET type model
|
// Save .NET type model
|
||||||
@@ -120,30 +131,30 @@ namespace Il2CppInspector.Model
|
|||||||
DependencyOrderedCppTypes = new List<CppType>();
|
DependencyOrderedCppTypes = new List<CppType>();
|
||||||
|
|
||||||
// Add method definitions to C++ type model
|
// Add method definitions to C++ type model
|
||||||
CppTypeCollection.SetGroup("type_definitions");
|
Group = "types_from_methods";
|
||||||
|
|
||||||
foreach (var method in ILModel.MethodsByDefinitionIndex.Where(m => m.VirtualAddress.HasValue)) {
|
foreach (var method in ILModel.MethodsByDefinitionIndex.Where(m => m.VirtualAddress.HasValue)) {
|
||||||
declarationGenerator.IncludeMethod(method);
|
declarationGenerator.IncludeMethod(method);
|
||||||
AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations());
|
AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations());
|
||||||
|
|
||||||
var fnPtr = declarationGenerator.GenerateMethodDeclaration(method);
|
var fnPtr = declarationGenerator.GenerateMethodDeclaration(method);
|
||||||
Methods.Add(method, fnPtr, new AppMethod(method, fnPtr));
|
Methods.Add(method, fnPtr, new AppMethod(method, fnPtr) {Group = Group});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add generic methods to C++ type model
|
// Add generic methods to C++ type model
|
||||||
CppTypeCollection.SetGroup("types_from_generics");
|
Group = "types_from_generic_methods";
|
||||||
|
|
||||||
foreach (var method in ILModel.GenericMethods.Values.Where(m => m.VirtualAddress.HasValue)) {
|
foreach (var method in ILModel.GenericMethods.Values.Where(m => m.VirtualAddress.HasValue)) {
|
||||||
declarationGenerator.IncludeMethod(method);
|
declarationGenerator.IncludeMethod(method);
|
||||||
AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations());
|
AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations());
|
||||||
|
|
||||||
var fnPtr = declarationGenerator.GenerateMethodDeclaration(method);
|
var fnPtr = declarationGenerator.GenerateMethodDeclaration(method);
|
||||||
Methods.Add(method, fnPtr, new AppMethod(method, fnPtr));
|
Methods.Add(method, fnPtr, new AppMethod(method, fnPtr) {Group = Group});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add metadata usage types to C++ type model
|
// Add metadata usage types to C++ type model
|
||||||
// Not supported in il2cpp <19
|
// Not supported in il2cpp <19
|
||||||
CppTypeCollection.SetGroup("types_from_usages");
|
Group = "types_from_usages";
|
||||||
|
|
||||||
if (Package.MetadataUsages != null)
|
if (Package.MetadataUsages != null)
|
||||||
foreach (var usage in Package.MetadataUsages) {
|
foreach (var usage in Package.MetadataUsages) {
|
||||||
@@ -168,12 +179,12 @@ namespace Il2CppInspector.Model
|
|||||||
Debug.Assert(type.IsPointer);
|
Debug.Assert(type.IsPointer);
|
||||||
|
|
||||||
// TODO: This should really be handled by CppDeclarationGenerator, and doesn't generate the full definition
|
// TODO: This should really be handled by CppDeclarationGenerator, and doesn't generate the full definition
|
||||||
var cppType = CppTypeCollection.Struct(declarationGenerator.TypeNamer.GetName(type) + "__TypeInfo");
|
var cppType = CppTypeCollection.Struct(declarationGenerator.TypeNamer.GetName(type));
|
||||||
var cppObjectType = (CppComplexType) CppTypeCollection["Il2CppObject"];
|
var cppObjectType = (CppComplexType) CppTypeCollection["Il2CppObject"];
|
||||||
cppType.Fields = new SortedDictionary<int, List<CppField>>(cppObjectType.Fields);
|
cppType.Fields = new SortedDictionary<int, List<CppField>>(cppObjectType.Fields);
|
||||||
|
|
||||||
DependencyOrderedCppTypes.Add(cppType);
|
DependencyOrderedCppTypes.Add(cppType);
|
||||||
Types.Add(type, cppType, new AppType(type, cppType, cppClassPtr: address));
|
Types.Add(type, cppType, new AppType(type, cppType, cppClassPtr: address) {Group = Group});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// Regular type definition
|
// Regular type definition
|
||||||
@@ -181,7 +192,7 @@ namespace Il2CppInspector.Model
|
|||||||
|
|
||||||
else if (!Types.ContainsKey(type))
|
else if (!Types.ContainsKey(type))
|
||||||
// Generic type definition has no associated C++ type, therefore no dictionary sub-key
|
// Generic type definition has no associated C++ type, therefore no dictionary sub-key
|
||||||
Types.Add(type, new AppType(type, null, cppTypeRefPtr: address));
|
Types.Add(type, new AppType(type, null, cppTypeRefPtr: address) {Group = Group});
|
||||||
else
|
else
|
||||||
// Regular type reference
|
// Regular type reference
|
||||||
Types[type].TypeRefPtrAddress = address;
|
Types[type].TypeRefPtrAddress = address;
|
||||||
@@ -232,11 +243,17 @@ namespace Il2CppInspector.Model
|
|||||||
// Create composite types
|
// Create composite types
|
||||||
foreach (var type in types)
|
foreach (var type in types)
|
||||||
if (!Types.ContainsKey(type.ilType))
|
if (!Types.ContainsKey(type.ilType))
|
||||||
Types.Add(type.ilType, type.referenceType, new AppType(type.ilType, type.referenceType, type.valueType));
|
Types.Add(type.ilType, type.referenceType, new AppType(type.ilType, type.referenceType, type.valueType) {Group = Group});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all the types for a group
|
// Get all the C++ types for a group
|
||||||
public IEnumerable<CppType> GetTypeGroup(string groupName) => CppTypeCollection.GetTypeGroup(groupName);
|
public IEnumerable<CppType> GetCppTypeGroup(string groupName) => CppTypeCollection.GetTypeGroup(groupName);
|
||||||
public IEnumerable<CppType> GetDependencyOrderedTypeGroup(string groupName) => DependencyOrderedCppTypes.Where(t => t.Group == groupName);
|
public IEnumerable<CppType> GetDependencyOrderedCppTypeGroup(string groupName) => DependencyOrderedCppTypes.Where(t => t.Group == groupName);
|
||||||
|
|
||||||
|
// Get all the composite types for a group
|
||||||
|
public IEnumerable<AppType> GetTypeGroup(string groupName) => Types.Values.Where(t => t.Group == groupName);
|
||||||
|
|
||||||
|
// Get all the composite methods for a group
|
||||||
|
public IEnumerable<AppMethod> GetMethodGroup(string groupName) => Methods.Values.Where(m => m.Group == groupName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ namespace Il2CppInspector.Model
|
|||||||
{
|
{
|
||||||
public class AppType
|
public class AppType
|
||||||
{
|
{
|
||||||
|
// The logical group this type is part of
|
||||||
|
// This is purely for querying types in related groups and has no bearing on the code
|
||||||
|
public string Group { get; set; }
|
||||||
|
|
||||||
// The corresponding C++ type definition which represents an instance of the object
|
// The corresponding C++ type definition which represents an instance of the object
|
||||||
// This is derived from Il2CppObject
|
// This is derived from Il2CppObject
|
||||||
// If the underlying .NET type is a struct (value type), this will return the boxed version
|
// If the underlying .NET type is a struct (value type), this will return the boxed version
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ namespace Il2CppInspector.Outputs
|
|||||||
writeCode("namespace app {");
|
writeCode("namespace app {");
|
||||||
writeLine("");
|
writeLine("");
|
||||||
|
|
||||||
writeTypesForGroup("Application type definitions", "type_definitions");
|
writeTypesForGroup("Application types from method calls", "types_from_methods");
|
||||||
writeTypesForGroup("Application generic method type usages", "types_from_generics");
|
writeTypesForGroup("Application types from generic methods", "types_from_generic_methods");
|
||||||
writeTypesForGroup("Application type usages", "types_from_usages");
|
writeTypesForGroup("Application types from usages", "types_from_usages");
|
||||||
|
|
||||||
writeCode("}");
|
writeCode("}");
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ namespace Il2CppInspector.Outputs
|
|||||||
|
|
||||||
private void writeTypesForGroup(string header, string group) {
|
private void writeTypesForGroup(string header, string group) {
|
||||||
writeSectionHeader(header);
|
writeSectionHeader(header);
|
||||||
foreach (var cppType in model.GetDependencyOrderedTypeGroup(group))
|
foreach (var cppType in model.GetDependencyOrderedCppTypeGroup(group))
|
||||||
writeCode(cppType.ToString());
|
writeCode(cppType.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,22 +16,12 @@ namespace Il2CppInspector.Outputs
|
|||||||
{
|
{
|
||||||
public class IDAPythonScript
|
public class IDAPythonScript
|
||||||
{
|
{
|
||||||
// TODO: Make this readonly when we've integrated with ApplicationModel
|
private readonly AppModel model;
|
||||||
private AppModel model;
|
|
||||||
private StreamWriter writer;
|
private StreamWriter writer;
|
||||||
// TODO: Remove when integrated with ApplicationModel
|
|
||||||
private CppDeclarationGenerator declGenerator;
|
|
||||||
|
|
||||||
public IDAPythonScript(AppModel model) => this.model = model;
|
public IDAPythonScript(AppModel model) => this.model = model;
|
||||||
|
|
||||||
public void WriteScriptToFile(string outputFile) {
|
public void WriteScriptToFile(string outputFile) {
|
||||||
// TODO: Integrate with ApplicationModel - use this hack so we can use CppDeclarationGenerator without disturbing the model passed in
|
|
||||||
var internalModel = new AppModel(model.ILModel);
|
|
||||||
internalModel.UnityVersion = model.UnityVersion;
|
|
||||||
internalModel.UnityHeader = model.UnityHeader;
|
|
||||||
internalModel.CppTypeCollection = CppTypeCollection.FromUnityHeaders(model.UnityHeader, model.WordSize);
|
|
||||||
model = internalModel;
|
|
||||||
declGenerator = new CppDeclarationGenerator(model);
|
|
||||||
|
|
||||||
using var fs = new FileStream(outputFile, FileMode.Create);
|
using var fs = new FileStream(outputFile, FileMode.Create);
|
||||||
writer = new StreamWriter(fs, Encoding.UTF8);
|
writer = new StreamWriter(fs, Encoding.UTF8);
|
||||||
@@ -93,10 +83,12 @@ typedef __int64 int64_t;
|
|||||||
|
|
||||||
private void writeMethods() {
|
private void writeMethods() {
|
||||||
writeSectionHeader("Method definitions");
|
writeSectionHeader("Method definitions");
|
||||||
writeMethods(model.ILModel.MethodsByDefinitionIndex);
|
writeTypes(model.GetDependencyOrderedCppTypeGroup("types_from_methods"));
|
||||||
|
writeMethods(model.GetMethodGroup("types_from_methods"));
|
||||||
|
|
||||||
writeSectionHeader("Constructed generic methods");
|
writeSectionHeader("Constructed generic methods");
|
||||||
writeMethods(model.ILModel.GenericMethods.Values);
|
writeTypes(model.GetDependencyOrderedCppTypeGroup("types_from_generic_methods"));
|
||||||
|
writeMethods(model.GetMethodGroup("types_from_generic_methods"));
|
||||||
|
|
||||||
writeSectionHeader("Custom attributes generators");
|
writeSectionHeader("Custom attributes generators");
|
||||||
foreach (var method in model.ILModel.AttributesByIndices.Values.Where(m => m.VirtualAddress.HasValue)) {
|
foreach (var method in model.ILModel.AttributesByIndices.Values.Where(m => m.VirtualAddress.HasValue)) {
|
||||||
@@ -113,13 +105,16 @@ typedef __int64 int64_t;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeMethods(IEnumerable<MethodBase> methods) {
|
private void writeTypes(IEnumerable<CppType> types) {
|
||||||
foreach (var method in methods.Where(m => m.VirtualAddress.HasValue)) {
|
foreach (var type in types)
|
||||||
declGenerator.IncludeMethod(method);
|
writeDecls(type.ToString());
|
||||||
writeDecls(declGenerator.GenerateRemainingTypeDeclarations());
|
}
|
||||||
var address = method.VirtualAddress.Value.Start;
|
|
||||||
writeTypedName(address, declGenerator.GenerateMethodDeclaration(method).ToSignatureString(), declGenerator.GlobalNamer.GetName(method));
|
private void writeMethods(IEnumerable<AppMethod> methods) {
|
||||||
writeComment(address, method);
|
foreach (var method in methods) {
|
||||||
|
var address = method.MethodCodeAddress;
|
||||||
|
writeTypedName(address, method.CppFnPtrType.ToSignatureString(), method.CppFnPtrType.Name);
|
||||||
|
writeComment(address, method.Method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,59 +124,58 @@ typedef __int64 int64_t;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeUsages() {
|
private void writeUsages() {
|
||||||
if (model.Package.MetadataUsages == null) {
|
|
||||||
/* Version < 19 calls `il2cpp_codegen_string_literal_from_index` to get string literals.
|
// String literals
|
||||||
* Unfortunately, metadata references are just loose globals in Il2CppMetadataUsage.cpp
|
|
||||||
* so we can't automatically name those. Next best thing is to define an enum for the strings. */
|
// For version < 19
|
||||||
|
if (model.StringIndexesAreOrdinals) {
|
||||||
var enumSrc = new StringBuilder();
|
var enumSrc = new StringBuilder();
|
||||||
enumSrc.Append("enum StringLiteralIndex {\n");
|
enumSrc.Append("enum StringLiteralIndex {\n");
|
||||||
for (int i = 0; i < model.Package.StringLiterals.Length; i++) {
|
foreach (var str in model.Strings)
|
||||||
var str = model.Package.StringLiterals[i];
|
enumSrc.Append($" STRINGLITERAL_{str.Key}_{stringToIdentifier(str.Value)},\n");
|
||||||
enumSrc.Append($" STRINGLITERAL_{i}_{stringToIdentifier(str)},\n");
|
|
||||||
}
|
|
||||||
enumSrc.Append("};\n");
|
enumSrc.Append("};\n");
|
||||||
|
|
||||||
writeDecls(enumSrc.ToString());
|
writeDecls(enumSrc.ToString());
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var stringType = declGenerator.AsCType(model.ILModel.TypesByFullName["System.String"]);
|
// For version >= 19
|
||||||
foreach (var usage in model.Package.MetadataUsages) {
|
else {
|
||||||
var address = usage.VirtualAddress;
|
var stringType = model.CppTypeCollection.GetType("String *");
|
||||||
string name;
|
|
||||||
|
|
||||||
switch (usage.Type) {
|
foreach (var str in model.Strings) {
|
||||||
case MetadataUsageType.StringLiteral:
|
writeTypedName(str.Key, stringType.ToString(), $"StringLiteral_{stringToIdentifier(str.Value)}");
|
||||||
var str = model.ILModel.GetMetadataUsageName(usage);
|
writeComment(str.Key, str.Value);
|
||||||
writeTypedName(address, stringType.ToString(), $"StringLiteral_{stringToIdentifier(str)}");
|
|
||||||
writeComment(address, str);
|
|
||||||
break;
|
|
||||||
case MetadataUsageType.Type:
|
|
||||||
case MetadataUsageType.TypeInfo:
|
|
||||||
var type = model.ILModel.GetMetadataUsageType(usage);
|
|
||||||
declGenerator.IncludeType(type);
|
|
||||||
writeDecls(declGenerator.GenerateRemainingTypeDeclarations());
|
|
||||||
|
|
||||||
name = declGenerator.TypeNamer.GetName(type);
|
|
||||||
if (usage.Type == MetadataUsageType.TypeInfo)
|
|
||||||
writeTypedName(address, $"struct {name}__Class *", $"{name}__TypeInfo");
|
|
||||||
else
|
|
||||||
writeTypedName(address, $"struct Il2CppType *", $"{name}__TypeRef");
|
|
||||||
writeComment(address, type.CSharpName);
|
|
||||||
break;
|
|
||||||
case MetadataUsageType.MethodDef:
|
|
||||||
case MetadataUsageType.MethodRef:
|
|
||||||
var method = model.ILModel.GetMetadataUsageMethod(usage);
|
|
||||||
declGenerator.IncludeMethod(method);
|
|
||||||
writeDecls(declGenerator.GenerateRemainingTypeDeclarations());
|
|
||||||
|
|
||||||
name = declGenerator.GlobalNamer.GetName(method);
|
|
||||||
writeTypedName(address, "struct MethodInfo *", $"{name}__MethodInfo");
|
|
||||||
writeComment(address, method);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Metadata usage C++ type dependencies
|
||||||
|
var usageCppTypes = model.GetDependencyOrderedCppTypeGroup("types_from_usages");
|
||||||
|
writeTypes(usageCppTypes);
|
||||||
|
|
||||||
|
// Definition and reference addresses for all types from metadata usages
|
||||||
|
foreach (var type in model.Types.Values) {
|
||||||
|
// A type may have no addresses, for example an unreferenced array type
|
||||||
|
|
||||||
|
// Value types must not used the boxed definition
|
||||||
|
var name = type.CppValueType?.Name ?? type.CppType?.Name ?? model.declarationGenerator.TypeNamer.GetName(type.ILType);
|
||||||
|
|
||||||
|
if (type.TypeClassAddress != 0xffffffff_ffffffff) {
|
||||||
|
writeTypedName(type.TypeClassAddress, $"struct {name}__Class *", $"{name}__TypeInfo");
|
||||||
|
writeComment(type.TypeClassAddress, type.ILType.CSharpName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.TypeRefPtrAddress != 0xffffffff_ffffffff) {
|
||||||
|
// A generic type definition does not have any direct C++ types, but may have a reference
|
||||||
|
writeTypedName(type.TypeRefPtrAddress, "struct Il2CppType *", $"{name}__TypeRef");
|
||||||
|
writeComment(type.TypeRefPtrAddress, type.ILType.CSharpName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metedata usage methods
|
||||||
|
foreach (var method in model.Methods.Values.Where(m => m.MethodInfoPtrAddress != 0xffffffff_ffffffff)) {
|
||||||
|
writeTypedName(method.MethodInfoPtrAddress, "struct MethodInfo *", $"{method.CppFnPtrType.Name}__MethodInfo");
|
||||||
|
writeComment(method.MethodInfoPtrAddress, method.Method);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeFunctions() {
|
private void writeFunctions() {
|
||||||
@@ -225,14 +219,6 @@ typedef __int64 int64_t;
|
|||||||
writeLine("idc.parse_decls('''" + declString + "''')");
|
writeLine("idc.parse_decls('''" + declString + "''')");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Temporary compatibility function, remove when integrated with ApplicationModel
|
|
||||||
private void writeDecls(List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType,
|
|
||||||
CppComplexType fieldsType, CppComplexType vtableType, CppComplexType staticsType)> types)
|
|
||||||
=> writeDecls(string.Join("\n",
|
|
||||||
types.SelectMany(t => new List<CppType> {t.vtableType, t.staticsType, t.fieldsType, t.valueType, t.referenceType})
|
|
||||||
.Where(t => t != null)
|
|
||||||
.Select(t => t.ToString())));
|
|
||||||
|
|
||||||
private void writeName(ulong address, string name) {
|
private void writeName(ulong address, string name) {
|
||||||
writeLine($"SetName({address.ToAddressString()}, r'{name.ToEscapedString()}')");
|
writeLine($"SetName({address.ToAddressString()}, r'{name.ToEscapedString()}')");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user