public CppDeclarationGenerator(Il2CppModel model, UnityVersion version) { this.model = model; if (version == null) { UnityHeader = UnityHeader.GuessHeadersForModel(model)[0]; UnityVersion = UnityHeader.MinVersion; } else { UnityVersion = version; UnityHeader = UnityHeader.GetHeaderForVersion(version); if (UnityHeader.MetadataVersion != model.Package.BinaryImage.Version) { /* this can only happen in the CLI frontend with a manually-supplied version number */ Console.WriteLine($"Warning: selected version {UnityVersion} (metadata version {UnityHeader.MetadataVersion})" + $" does not match metadata version {model.Package.BinaryImage.Version}."); } } InitializeNaming(); InitializeConcreteImplementations(); // Configure inheritance style based on binary type; this can be overridden by setting InheritanceStyle in the object initializer InheritanceStyle = CppCompiler.GuessFromImage(model.Package.BinaryImage); }
public void TestGenericTypes() { // Arrange // We're currently in IlCppTests\bin\Debug\netcoreapp3.0 or similar var testPath = Path.GetFullPath(Directory.GetCurrentDirectory() + @"\..\..\..\TestBinaries\GenericTypes"); // Build model var inspectors = Il2CppInspector.LoadFromFile(testPath + @"\GenericTypes.so", testPath + @"\global-metadata.dat"); var model = new Il2CppModel(inspectors[0]); var asm = model.GetAssembly("GenericTypes.dll"); // Act TypeInfo tDerived = asm.GetType("Il2CppTests.TestSources.Derived`1"); TypeInfo tDerivedBase = tDerived.BaseType; // TODO: array of Derived<int> // TypeInfo tDerivedArray TypeInfo tT = asm.GetType("Il2CppTests.TestSources.Base`2").GenericTypeParameters[0]; TypeInfo tF = tDerived.GetField("F").FieldType; TypeInfo tNested = asm.GetType("Il2CppTests.TestSources.Derived`1+Nested"); DisplayGenericType(tDerived, "Derived<V>"); DisplayGenericType(tDerivedBase, "Base type of Derived<V>"); //DisplayGenericType(tDerivedArray, "Array of Derived<int>"); DisplayGenericType(tT, "Type parameter T from Base<T>"); DisplayGenericType(tF, "Field type, G<Derived<V>>"); DisplayGenericType(tNested, "Nested type in Derived<V>"); // Assert var checks = new[] {
public CppApplicationModel(Il2CppModel model, UnityVersion unityVersion = null, CppCompiler.Type compiler = CppCompiler.Type.BinaryFormat) { // Set key properties Compiler = compiler == CppCompiler.Type.BinaryFormat ? CppCompiler.GuessFromImage(model.Package.BinaryImage) : compiler; var unityHeader = unityVersion != null?UnityHeader.GetHeaderForVersion(unityVersion) : UnityHeader.GuessHeadersForModel(model)[0]; UnityVersion = unityVersion ?? unityHeader.MinVersion; ILModel = model; // Check for matching metadata and binary versions if (unityHeader.MetadataVersion != model.Package.BinaryImage.Version) { Console.WriteLine($"Warning: selected version {UnityVersion} (metadata version {unityHeader.MetadataVersion})" + $" does not match metadata version {model.Package.BinaryImage.Version}."); } // Get addresses of IL2CPP API function exports Exports = model.Package.Binary.Image.GetExports().ToList(); // Start creation of type model by parsing all of the Unity IL2CPP headers Types = CppTypes.FromUnityHeaders(unityHeader, WordSize); // TODO: Process every type in the binary //var decl = new CppDeclarationGenerator(this); }
public void TestGenericTypes() { // Arrange // We're currently in IlCppTests\bin\Debug\netcoreapp3.0 or similar var testPath = Path.GetFullPath(Directory.GetCurrentDirectory() + @"\..\..\..\TestBinaries\GenericTypes"); // Build model var inspectors = Il2CppInspector.LoadFromFile(testPath + @"\GenericTypes.so", testPath + @"\global-metadata.dat"); var model = new Il2CppModel(inspectors[0]); var asm = model.GetAssembly("GenericTypes.dll"); // Act TypeInfo tBase = asm.GetType("Il2CppTests.TestSources.Base`2"); TypeInfo tDerived = asm.GetType("Il2CppTests.TestSources.Derived`1"); TypeInfo tDerivedBase = tDerived.BaseType; TypeInfo tDerivedArray = model.GetType("Il2CppTests.TestSources.Derived`1[System.Int32][]"); TypeInfo tT = tBase.GenericTypeParameters[0]; TypeInfo tU = tBase.GenericTypeParameters[1]; TypeInfo tF = tDerived.GetField("F").FieldType; TypeInfo tNested = asm.GetType("Il2CppTests.TestSources.Derived`1+Nested"); TypeInfo tNG = asm.GetType("Il2CppTests.TestSources.NonGeneric"); TypeInfo tGCWM = asm.GetType("Il2CppTests.TestSources.GenericClassWithMethods`1"); TypeInfo tCGM = asm.GetType("Il2CppTests.TestSources.CallGenericMethods"); MethodInfo mGMDINGC = tNG.GetMethod("GenericMethodDefinitionInNonGenericClass"); MethodInfo mNGMIGC = tGCWM.GetMethod("NonGenericMethodInGenericClass"); MethodInfo mNGMIGC2 = tGCWM.GetMethod("NonGenericMethodInGenericClass2"); MethodInfo mGMDIGC = tGCWM.GetMethod("GenericMethodDefinitionInGenericClass"); MethodInfo mGMDIGC2 = tGCWM.GetMethod("GenericMethodDefinitionInGenericClass2"); MethodBase mGMDINGC_closed = model.GetGenericMethod( "Il2CppTests.TestSources.NonGeneric.GenericMethodDefinitionInNonGenericClass", model.GetType("System.Single")); MethodBase mGMDIGC_closed = model.GetGenericMethod( "Il2CppTests.TestSources.GenericClassWithMethods`1.GenericMethodDefinitionInGenericClass", model.GetType("System.Int32")); MethodBase mGMDIGC2_closed = model.GetGenericMethod( "Il2CppTests.TestSources.GenericClassWithMethods`1.GenericMethodDefinitionInGenericClass2", model.GetType("System.String")); DisplayGenericType(tBase, "Generic type definition Base<T, U>"); DisplayGenericType(tDerived, "Derived<V>"); DisplayGenericType(tDerivedBase, "Base type of Derived<V>"); DisplayGenericType(tDerivedArray, "Array of Derived<int>"); DisplayGenericType(tT, "Type parameter T from Base<T,U>"); DisplayGenericType(tU, "Type parameter U from Base<T,U>"); DisplayGenericType(tF, "Field type, G<Derived<V>>"); DisplayGenericType(tNested, "Nested type in Derived<V>"); // Assert var typeChecks = new[] {
public void TestNames() { // Arrange // We're currently in IlCppTests\bin\Debug\netcoreapp3.0 or similar var testPath = Path.GetFullPath(Directory.GetCurrentDirectory() + @"\..\..\..\TestBinaries\References-ARMv7"); // Build model var inspectors = Il2CppInspector.LoadFromFile(testPath + @"\References-ARMv7.so", testPath + @"\global-metadata.dat"); var model = new Il2CppModel(inspectors[0]); var asm = model.GetAssembly("References.dll"); // Act var t = asm.GetType("Il2CppTests.TestSources.Test"); var m1 = t.GetMethod("MethodWithGenericAndClassRefs"); var m2 = t.GetMethod("MethodWithInRefOut"); var p1 = m1.DeclaredParameters; var p2 = m2.DeclaredParameters; // Assert var checks = new[] {
public CSharpCodeStubs(Il2CppModel model) => this.model = model;
private static int Run(Options options) { // Banner var asmInfo = FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetEntryAssembly().Location); Console.WriteLine(asmInfo.ProductName); Console.WriteLine("Version " + asmInfo.ProductVersion); Console.WriteLine(asmInfo.LegalCopyright); Console.WriteLine(""); // Check excluded namespaces if (options.ExcludedNamespaces.Count() == 1 && options.ExcludedNamespaces.First().ToLower() == "none") { options.ExcludedNamespaces = new List <string>(); } // Check files if (!File.Exists(options.BinaryFile)) { Console.Error.WriteLine($"File {options.BinaryFile} does not exist"); return(1); } if (!File.Exists(options.MetadataFile)) { Console.Error.WriteLine($"File {options.MetadataFile} does not exist"); return(1); } // Creating a Visual Studio solution requires Unity assembly references var unityPath = string.Empty; var unityAssembliesPath = string.Empty; if (options.CreateSolution) { unityPath = Utils.FindPath(options.UnityPath); unityAssembliesPath = Utils.FindPath(options.UnityAssembliesPath); if (!Directory.Exists(unityPath)) { Console.Error.WriteLine($"Unity path {unityPath} does not exist"); return(1); } if (!File.Exists(unityPath + @"\Editor\Data\Managed\UnityEditor.dll")) { Console.Error.WriteLine($"No Unity installation found at {unityPath}"); return(1); } if (!Directory.Exists(unityAssembliesPath)) { Console.Error.WriteLine($"Unity assemblies path {unityAssembliesPath} does not exist"); return(1); } if (!File.Exists(unityAssembliesPath + @"\UnityEngine.UI.dll")) { Console.Error.WriteLine($"No Unity assemblies found at {unityAssembliesPath}"); return(1); } Console.WriteLine("Using Unity editor at " + unityPath); Console.WriteLine("Using Unity assemblies at " + unityAssembliesPath); } // Analyze data List <Il2CppInspector> il2cppInspectors; using (var il2cppTimer = new Benchmark("Analyze IL2CPP data")) il2cppInspectors = Il2CppInspector.LoadFromFile(options.BinaryFile, options.MetadataFile); if (il2cppInspectors == null) { Environment.Exit(1); } // Write output file int i = 0; foreach (var il2cpp in il2cppInspectors) { // Create model Il2CppModel model; using (var modelTimer = new Benchmark("Create type model")) model = new Il2CppModel(il2cpp); // C# signatures output using (var signaturesDumperTimer = new Benchmark("Generate C# code")) { var writer = new CSharpCodeStubs(model) { ExcludedNamespaces = options.ExcludedNamespaces.ToList(), SuppressMetadata = options.SuppressMetadata, MustCompile = options.MustCompile }; var imageSuffix = i++ > 0 ? "-" + (i - 1) : ""; var csOut = options.CSharpOutPath; if (csOut.ToLower().EndsWith(".cs")) { csOut = csOut.Insert(csOut.Length - 3, imageSuffix); } else { csOut += imageSuffix; } if (options.CreateSolution) { writer.WriteSolution(csOut, unityPath, unityAssembliesPath); } else { switch (options.LayoutSchema.ToLower(), options.SortOrder.ToLower()) {
public Il2CppCSharpDumper(Il2CppModel model) => this.model = model;
private void runTest(string testPath) { // Android var testFile = testPath + @"\" + Path.GetFileName(testPath) + ".so"; // Windows if (!File.Exists(testFile)) { testFile = testPath + @"\" + Path.GetFileName(testPath) + ".dll"; } if (!File.Exists(testFile)) { testFile = testPath + @"\GameAssembly.dll"; } // iOS if (!File.Exists(testFile)) { testFile = testPath + @"\" + Path.GetFileName(testPath); } // Android if (!File.Exists(testFile)) { testFile = testPath + @"\libil2cpp.so"; } var inspectors = Il2CppInspector.LoadFromFile(testFile, testPath + @"\global-metadata.dat"); // If null here, there was a problem parsing the files if (inspectors == null) { throw new Exception("Could not understand IL2CPP binary or metadata"); } if (inspectors.Count == 0) { throw new Exception("Could not find any images in the IL2CPP binary"); } // Dump each image in the binary separately int i = 0; foreach (var il2cpp in inspectors) { var model = new Il2CppModel(il2cpp); var nameSuffix = i++ > 0 ? "-" + (i - 1) : ""; new CSharpCodeStubs(model) { ExcludedNamespaces = Constants.DefaultExcludedNamespaces, SuppressMetadata = false, MustCompile = true }.WriteSingleFile(testPath + $@"\test-result{nameSuffix}.cs"); new IDAPythonScript(model) .WriteScriptToFile(testPath + $@"\test-ida-result{nameSuffix}.py"); new CppScaffolding(model) .WriteCppToFile(testPath + $@"\test-result{nameSuffix}.h"); } // Compare test result with expected result for (i = 0; i < inspectors.Count; i++) { var expected = File.ReadAllLines(testPath + @"\..\..\TestExpectedResults\" + Path.GetFileName(testPath) + (i > 0 ? "-" + i : "") + ".cs"); var actual = File.ReadAllLines(testPath + @"\test-result" + (i > 0 ? "-" + i : "") + ".cs"); // Get rid of blank lines and trim the remaining lines expected = (from l in expected where !string.IsNullOrWhiteSpace(l) select l.Trim()).ToArray(); actual = (from l in actual where !string.IsNullOrWhiteSpace(l) select l.Trim()).ToArray(); CollectionAssert.AreEqual(expected, actual); } }
public IDAPythonScript(Il2CppModel model) => this.model = model;
public Il2CppIDAScriptDumper(Il2CppModel model) => this.model = model;
public static TypeRef FromDefinitionIndex(Il2CppModel model, int index) => new TypeRef { model = model, definitionIndex = index };
public static TypeRef FromReferenceIndex(Il2CppModel model, int index) => new TypeRef { model = model, referenceIndex = index };
private static int Run(Options options) { // Check excluded namespaces if (options.ExcludedNamespaces.Count() == 1 && options.ExcludedNamespaces.First().ToLower() == "none") { options.ExcludedNamespaces = new List <string>(); } // Check files if (!File.Exists(options.BinaryFile)) { Console.Error.WriteLine($"File {options.BinaryFile} does not exist"); return(1); } if (!File.Exists(options.MetadataFile)) { Console.Error.WriteLine($"File {options.MetadataFile} does not exist"); return(1); } // Analyze data List <Il2CppInspector> il2cppInspectors; using (var timer = new Benchmark("Analyze IL2CPP data")) il2cppInspectors = Il2CppInspector.LoadFromFile(options.BinaryFile, options.MetadataFile); if (il2cppInspectors == null) { Environment.Exit(1); } // Write output file int i = 0; foreach (var il2cpp in il2cppInspectors) { // Create model Il2CppModel model; using (var timer1 = new Benchmark("Create type model")) model = new Il2CppModel(il2cpp); // C# signatures output using var timer2 = new Benchmark("Generate C# code"); var writer = new Il2CppCSharpDumper(model) { ExcludedNamespaces = options.ExcludedNamespaces.ToList(), SuppressMetadata = options.SuppressMetadata, MustCompile = options.MustCompile }; var imageSuffix = i++ > 0 ? "-" + (i - 1) : ""; var csOut = options.CSharpOutPath; if (csOut.ToLower().EndsWith(".cs")) { csOut = csOut.Insert(csOut.Length - 3, imageSuffix); } else { csOut += imageSuffix; } switch (options.LayoutSchema.ToLower(), options.SortOrder.ToLower()) {
public CppScaffolding(Il2CppModel model) => this.model = model;