Ejemplo n.º 1
0
 public void TestVersions()
 {
     Assert.That(UnityHeaders.GetTypeHeaderForVersion("5.4.3p4").VersionRange.ToString(), Is.EqualTo("5.4.1 - 5.4.3"));
     Assert.That(UnityHeaders.GetTypeHeaderForVersion("5.6.4").VersionRange.ToString(), Is.EqualTo("5.6.1 - 5.6.7"));
     Assert.That(new UnityVersion("2020.1.0b5").ToString(), Is.EqualTo("2020.1.0b5"));
     Assert.That(new UnityVersion("2020.1").ToString(), Is.EqualTo("2020.1.0"));
     Assert.That(new UnityVersion("5.3.1").CompareTo("5.3.1p4") == 0);
     Assert.That(new UnityVersion("5.3.1rc0").CompareTo("5.3.1p2") < 0);
     Assert.That(new UnityVersion("5.3.1f1").CompareTo("5.3.1p0") < 0);
 }
Ejemplo n.º 2
0
        /// <summary>
        /// User has selected an image
        /// </summary>
        private void LstImages_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // Selection has been removed?
            if (((ListBox)sender).SelectedItem == null)
            {
                trvNamespaces.ItemsSource = null;
                return;
            }

            // Get selected image
            var model = (AppModel)((ListBox)sender).SelectedItem;

            // Get namespaces
            var namespaces = model.ILModel.Assemblies.SelectMany(x => x.DefinedTypes).GroupBy(t => t.Namespace).Select(n => n.Key);

            // Break namespaces down into a tree
            var namespaceTree = deconstructNamespaces(namespaces);

            // Uncheck the default exclusions
            foreach (var exclusion in Constants.DefaultExcludedNamespaces)
            {
                var          parts = exclusion.Split('.');
                CheckboxNode node  = null;
                foreach (var part in parts)
                {
                    node = (node?.Children ?? namespaceTree).FirstOrDefault(c => c.Name == part);
                    if (node == null)
                    {
                        break;
                    }
                }
                if (node != null)
                {
                    node.IsChecked = false;
                }
            }

            // Populate TreeView with namespace hierarchy
            trvNamespaces.ItemsSource = namespaceTree;

            // Populate Unity version combo boxes
            var prevIdaSelection  = cboPyUnityVersion.SelectedItem;
            var prevCppSelection  = cboCppUnityVersion.SelectedItem;
            var prevJsonSelection = cboJsonUnityVersion.SelectedItem;

            cboPyUnityVersion.Items.Clear();
            cboCppUnityVersion.Items.Clear();
            cboJsonUnityVersion.Items.Clear();
            foreach (var version in UnityHeaders.GuessHeadersForBinary(model.Package.Binary))
            {
                cboPyUnityVersion.Items.Add(version);
                cboCppUnityVersion.Items.Add(version);
                cboJsonUnityVersion.Items.Add(version);
            }

            // Restore previous selection via value equality
            if (prevIdaSelection != null)
            {
                cboPyUnityVersion.SelectedItem   = cboPyUnityVersion.Items.Cast <UnityHeaders>().FirstOrDefault(v => v.Equals(prevIdaSelection));
                cboCppUnityVersion.SelectedItem  = cboCppUnityVersion.Items.Cast <UnityHeaders>().FirstOrDefault(v => v.Equals(prevCppSelection));
                cboJsonUnityVersion.SelectedItem = cboJsonUnityVersion.Items.Cast <UnityHeaders>().FirstOrDefault(v => v.Equals(prevJsonSelection));
            }

            // Prefer latest Unity versions if there was no previous selection or it's now invalid
            if (cboPyUnityVersion.SelectedItem == null)
            {
                cboPyUnityVersion.SelectedIndex = cboPyUnityVersion.Items.Count - 1;
            }
            if (cboCppUnityVersion.SelectedItem == null)
            {
                cboCppUnityVersion.SelectedIndex = cboCppUnityVersion.Items.Count - 1;
            }
            if (cboJsonUnityVersion.SelectedItem == null)
            {
                cboJsonUnityVersion.SelectedIndex = cboJsonUnityVersion.Items.Count - 1;
            }
        }
        public void TestCppTypeDeclarations()
        {
            // NOTE: This test doesn't check for correct results, only that parsing doesn't fail!

            var unityTypeHeaders = UnityHeaders.GetAllTypeHeaders();

            // Ensure we have read the embedded assembly resources
            Assert.IsTrue(unityTypeHeaders.Any());

            // Ensure we can interpret every header from every version of Unity without errors
            // This will throw InvalidOperationException if there is a problem
            foreach (var unityTypeHeader in unityTypeHeaders)
            {
                var cppUnityHeaderTypes = new CppTypeCollection(64);
                cppUnityHeaderTypes.AddFromDeclarationText(unityTypeHeader.GetText());

                foreach (var cppType in cppUnityHeaderTypes.Types)
                {
                    Debug.WriteLine("// " + cppType.Key + "\n" + cppType.Value.ToString("o"));
                }
            }

            // Do a few sanity checks taken from real applications (64-bit)
            // NOTE: Does not provide full code coverage!

            var cppTypes = CppTypeCollection.FromUnityVersion(new UnityVersion("2019.3.1f1"));

            CppComplexType ct;
            CppField       field;

            // Field offset tests

            // Un-nested class
            ct = (CppComplexType)cppTypes["Il2CppClass"];

            field = ct[0xE0].First();

            Assert.AreEqual("cctor_finished", field.Name);

            field = ct[0x130].First();

            Assert.AreEqual("vtable", field.Name);

            field = ct["cctor_finished"];

            Assert.AreEqual(0xE0, field.OffsetBytes);

            field = ct["vtable"];

            Assert.AreEqual(0x130, field.OffsetBytes);

            // Nested class
            ct = (CppComplexType)cppTypes["Il2CppClass_Merged"];
            var fields = ct.Flattened;

            field = fields[0xE0].First();

            Assert.AreEqual("cctor_finished", field.Name);

            field = fields[0x130].First();

            Assert.AreEqual("vtable", field.Name);

            field = fields["cctor_finished"];

            Assert.AreEqual(0xE0, field.OffsetBytes);

            field = fields["vtable"];

            Assert.AreEqual(0x130, field.OffsetBytes);

            // Bitfield
            ct = (CppComplexType)cppTypes["Il2CppType"];

            field = ct.Fields[0xB * 8 + 7].First();

            Assert.AreEqual("pinned", field.Name);

            // Nested fields
            ct     = (CppComplexType)cppTypes["Il2CppWin32Decimal"];
            fields = ct.Flattened;

            field = fields[0x08].First();

            Assert.AreEqual("lo32", field.Name);

            field = fields[0x08].Last();

            Assert.AreEqual("lo64", field.Name);

            field = fields[0x0C].First();

            Assert.AreEqual("mid32", field.Name);

            // Pointer alias
            var alias = (CppAlias)cppTypes.GetType("Il2CppHString");

            Assert.AreEqual(typeof(CppPointerType), alias.ElementType.GetType());
            Assert.AreEqual("Il2CppHString__ *", alias.ElementType.Name);

            // Typedef struct with no tag
            Assert.True(cppTypes.Types.ContainsKey("Il2CppGenericMethodIndices"));
            Assert.True(((CppComplexType)cppTypes["Il2CppGenericMethodIndices"]).ComplexValueType == ComplexValueType.Struct);

            // Alignment tests

            // Il2CppArrayType has an int * (sizes) after three uint8_t
            Assert.AreEqual(0x10, cppTypes.GetComplexType("Il2CppArrayType")["sizes"].OffsetBytes);

            // Il2CppSafeArray has a uint32_t (element_size) after two uint16_t
            Assert.AreEqual(0x4, cppTypes.GetComplexType("Il2CppSafeArray")["element_size"].OffsetBytes);
        }