Пример #1
0
        /// <summary>
        /// Gets the intersection of the two memory sections
        /// </summary>
        /// <param name="other"></param>
        /// <returns>Intersection, if exists; otherwise, null</returns>
        public MemorySection Intersect(MemorySection other)
        {
            var intStart = -1;
            var intEnd   = -1;

            if (other.StartAddress >= StartAddress &&
                other.StartAddress <= EndAddress)
            {
                intStart = other.StartAddress;
            }
            if (other.EndAddress >= StartAddress &&
                other.EndAddress <= EndAddress)
            {
                intEnd = other.EndAddress;
            }
            if (StartAddress >= other.StartAddress &&
                StartAddress <= other.EndAddress)
            {
                intStart = StartAddress;
            }
            if (EndAddress >= other.StartAddress &&
                EndAddress <= other.EndAddress)
            {
                intEnd = EndAddress;
            }
            return(intStart < 0 || intEnd < 0
                ? null
                : new MemorySection((ushort)intStart, (ushort)intEnd));
        }
        /// <summary>
        /// Stores a section in this collection
        /// </summary>
        /// <param name="startAddress">Start address</param>
        /// <param name="endAddress">End address</param>
        /// <param name="type">Memory section type</param>
        public void AddSection(ushort startAddress, ushort endAddress, MemorySectionType type)
        {
            var startAnn = Parent.GetAnnotationFor(startAddress, out var start);
            var endAnn   = Parent.GetAnnotationFor((ushort)(endAddress - 1), out var end);

            if (startAnn == endAnn)
            {
                // --- The section is within one bank
                var tempSection = new MemorySection(start, end, type);
                startAnn.MemoryMap.Add(tempSection);
                startAnn.MemoryMap.Normalize();
                SaveAnnotations(startAnn, startAddress);
            }
            else
            {
                // --- The section overlaps multiple banks
                // --- We must be in FullViewMode to get here
                var origSection = new MemorySection(startAddress, endAddress, type);
                for (var bank = 0; bank <= 3; bank++)
                {
                    var bankSection = new MemorySection((ushort)(bank * 0x4000), (ushort)(bank * 0x4000 + 0x3FFF));
                    if (origSection.Overlaps(bankSection))
                    {
                        // --- There is a memory section for this bank
                        var cutSection = origSection.Intersect(bankSection);
                        var bankAnn    = Parent.GetAnnotationFor(cutSection.StartAddress, out var cutStart);
                        Parent.GetAnnotationFor(cutSection.EndAddress, out var cutEnd);
                        bankAnn.MemoryMap.Add(new MemorySection(cutStart, cutEnd, type));
                        bankAnn.MemoryMap.Normalize();
                        SaveAnnotations(bankAnn, startAddress);
                    }
                }
            }
        }
Пример #3
0
        public static void Main(string[] args)
        {
            // Create an empty WebAssembly file.
            var file = new WasmFile();

            // Define a type section.
            var typeSection = new TypeSection();

            file.Sections.Add(typeSection);

            // Write the file to a (memory) stream.
            var stream = new MemoryStream();

            file.WriteBinaryTo(stream);
            stream.Seek(0, SeekOrigin.Begin);

            // Read the file from a (memory) stream.
            file = WasmFile.ReadBinary(stream);
            stream.Seek(0, SeekOrigin.Begin);

            // Define a memory section if it doesn't exist already.
            var memSection = file.GetFirstSectionOrNull <MemorySection>();

            if (memSection == null)
            {
                // The file doesn't specify a memory section, so we'll
                // have to create one and add it to the file.
                memSection = new MemorySection();
                file.Sections.Add(memSection);
            }

            memSection.Memories.Clear();
            // Memory sizes are specified in WebAssembly pages,
            // which are regions of storage with size 64KiB.
            // `new ResizableLimits(1, 1)` creates a memory description
            // that is initially one page (first argument) in size and
            // is capped at one page of memory (second argument), so
            // there will always be exactly one page of linear memory.
            memSection.Memories.Add(
                new MemoryType(new ResizableLimits(1, 1)));

            // Print the memory size.
            List <MemoryType> memSections =
                file.GetFirstSectionOrNull <MemorySection>()
                .Memories;

            Console.WriteLine(
                "Memory size: {0}",
                memSections
                .Single <MemoryType>()
                .Limits);

            // Save the file again.
            file.WriteBinaryTo(stream);
            stream.Seek(0, SeekOrigin.Begin);
        }
Пример #4
0
        public void SameSectionWorksAsExpected2()
        {
            // --- Arrange
            var ms1 = new MemorySection(0x1000, 0x10FF, MemorySectionType.WordArray);
            var ms2 = new MemorySection(0x1001, 0x10);

            // --- Assert
            ms1.SameSection(ms2).ShouldBeFalse();
            ms2.SameSection(ms1).ShouldBeFalse();
        }
Пример #5
0
        public void IntersectionWorksAsExpected2()
        {
            // --- Arrange
            var ms1 = new MemorySection(0x1000, 0x1FFF);
            var ms2 = new MemorySection(0x0000, 0x0FFF);

            // --- Assert
            ms1.Intersect(ms2).ShouldBeNull();
            ms2.Intersect(ms1).ShouldBeNull();
        }
Пример #6
0
        public void OverlapIsCaught3()
        {
            // --- Arrange
            var ms1 = new MemorySection(0x1000, 0x1FFF);
            var ms2 = new MemorySection(0x1010, 0x180F);

            // --- Assert
            ms1.Overlaps(ms2).ShouldBeTrue();
            ms2.Overlaps(ms1).ShouldBeTrue();
        }
Пример #7
0
        public void OverlapWorksWithDiscreteSections2()
        {
            // --- Arrange
            var ms1 = new MemorySection(0x0000, 0x0FFF);
            var ms2 = new MemorySection(0x1000, 0x1FFF);

            // --- Assert
            ms1.Overlaps(ms2).ShouldBeFalse();
            ms2.Overlaps(ms1).ShouldBeFalse();
        }
Пример #8
0
 /// <summary>
 /// Checks if this memory section overlaps with the othe one
 /// </summary>
 /// <param name="other">Other memory section</param>
 /// <returns>True, if the sections overlap</returns>
 public bool Overlaps(MemorySection other)
 {
     return(other.StartAddress >= StartAddress &&
            other.StartAddress <= EndAddress ||
            other.EndAddress >= StartAddress &&
            other.EndAddress <= EndAddress ||
            StartAddress >= other.StartAddress &&
            StartAddress <= other.EndAddress ||
            EndAddress >= other.StartAddress &&
            EndAddress <= other.EndAddress);
 }
Пример #9
0
        public void ConstructorHandlesBoundariesProperly()
        {
            // --- Arrange
            var ms1 = new MemorySection(0x0000, 0x0FFF);
            var ms2 = new MemorySection(0x2FFF, 0x2000);

            // --- Assert
            ms1.StartAddress.ShouldBe((ushort)0x0000);
            ms1.EndAddress.ShouldBe((ushort)0x0FFF);
            ms2.StartAddress.ShouldBe((ushort)0x2000);
            ms2.EndAddress.ShouldBe((ushort)0x2FFF);
        }
Пример #10
0
        public void ParseSectionSymbol_ShouldFindSelectionSymbolInText()
        {
            //Arrange
            string         text       = "PARTITIONING_SECTIONS_MANUAL_SYMBOLS=ram__dspr1__VP_D[BeginOf_ram__dspr1__VP_D-EndOf_ram__dspr1__VP_D]";
            IMemorySection newSection = new MemorySection <string>("ram__dspr1__VP_D", "BeginOf_ram__dspr1__VP_D", "EndOf_ram__dspr1__VP_D", true);

            //Act
            MemorySectionParser msp = new MemorySectionParser(text);

            //Assert
            Assert.True(msp.GetMemorySectionSymbols().Count == 1);
            Assert.Contains <IMemorySection>(newSection, msp.GetMemorySectionSymbols());
        }
Пример #11
0
        public void ParseSectionAddress_ShouldFindSelectionAddressInText()
        {
            //Arrange
            string         text       = "PARTITIONING_SECTIONS_MANUAL_ADDRESSES=MySection1[00000F70-00002AD0]";
            IMemorySection newSection = new MemorySection <long>("MySection1", Convert.ToInt32("00000F70", 16), Convert.ToInt32("00002AD0", 16), false);

            //Act
            MemorySectionParser msp = new MemorySectionParser(text);

            //Assert
            Assert.True(msp.GetMemorySectionAddresses().Count == 1);
            Assert.Contains <IMemorySection>(newSection, msp.GetMemorySectionAddresses());
        }
Пример #12
0
        public void ParseText_ShouldFindSelectionPartitionInText()
        {
            //Arrange

            string         text         = @"/* MPU region: ram__dspr0__VP_D */
    /* .StartAddress  = */ (uint32)BeginOf_ram__dspr0__VP_D,  /* PRQA S 0306 */ /* MD_Os_Hal_Rule11.4_0306 */
    /* .EndAddress    = */ (uint32)EndOf_ram__dspr0__VP_D  /* PRQA S 0306 */ /* MD_Os_Hal_Rule11.4_0306 */";
            IMemorySection newPartition = new MemorySection <string>("ram__dspr0__VP_D", "BeginOf_ram__dspr0__VP_D", "EndOf_ram__dspr0__VP_D", false);

            //Act
            MemoryPartitionsParser mpp = new MemoryPartitionsParser(text);

            //Assert
            Assert.True(mpp.GetMemoryPartitions().Count == 1);
            Assert.Contains <IMemorySection>(newPartition, mpp.GetMemoryPartitions());
        }
Пример #13
0
        public void GeneratePartitionsTable(MemorySection <string> memorySection)
        {
            _partitionsSource = new DataTable();
            _partitionsSource.Columns.Add("Name", typeof(string));
            _partitionsSource.Columns.Add("Start Address", typeof(string));
            _partitionsSource.Columns.Add("End Address", typeof(string));

            DataRow _row = _partitionsSource.NewRow();

            _row["Name"]          = memorySection.Name;
            _row["Start Address"] = memorySection.StartAddress;
            _row["End Address"]   = memorySection.EndAddress;

            _partitionsSource.Rows.Add(_row);
            OnPropertyChanged("PartitionsSourceDataTable");
        }
Пример #14
0
        public void UpdateList_ShouldUpdateIfListEmpty()
        {
            //Arrange
            UniqMemoryPartition   finalList    = new UniqMemoryPartition();
            IMemorySection        newPartition = new MemorySection <string>("test", "test", "test", false);
            List <IMemorySection> newList      = new List <IMemorySection>();

            newList.Add(newPartition);

            //Act
            finalList.UpdateList(newList);

            //Assert
            Assert.Contains <IMemorySection>(newPartition, finalList.GetUniqMemoryPartition().Values);
            Assert.True(finalList.GetUniqMemoryPartition().Values.Count == 1);
        }
Пример #15
0
        public static uint GetAddress(RiscVProgramResult res, MemorySection memorySection)
        {
            switch (memorySection)
            {
            case MemorySection.Text:
                return(0x10000 + res.StackTextFreePosition);

            case MemorySection.Static:
                return((uint)0x10000000 + res.StackStaticDataFreePosition);

            default:
                throw new SimulatorException
                      {
                          ErrorMessage = $"'{memorySection}' cannot find fit section to return from f. GetAddress"
                      };
            }
        }
Пример #16
0
        public void IntersectionWorksAsExpected5()
        {
            // --- Arrange
            var ms1 = new MemorySection(0x1000, 0x1FFF);
            var ms2 = new MemorySection(0x1100, 0x11FF);

            // --- Act
            var intersection1 = ms1.Intersect(ms2);
            var intersection2 = ms2.Intersect(ms1);

            // --- Assert
            intersection1.ShouldNotBeNull();
            intersection1.StartAddress.ShouldBe((ushort)0x1100);
            intersection1.EndAddress.ShouldBe((ushort)0x11FF);
            intersection2.ShouldNotBeNull();
            intersection2.StartAddress.ShouldBe((ushort)0x1100);
            intersection2.EndAddress.ShouldBe((ushort)0x11FF);
        }
Пример #17
0
        /// <summary>
        /// Reads the non-custom section with the given header.
        /// </summary>
        /// <param name="Header">The section header.</param>
        /// <returns>The parsed section.</returns>
        protected Section ReadKnownSectionPayload(SectionHeader Header)
        {
            switch (Header.Name.Code)
            {
            case SectionCode.Type:
                return(TypeSection.ReadSectionPayload(Header, this));

            case SectionCode.Import:
                return(ImportSection.ReadSectionPayload(Header, this));

            case SectionCode.Function:
                return(FunctionSection.ReadSectionPayload(Header, this));

            case SectionCode.Table:
                return(TableSection.ReadSectionPayload(Header, this));

            case SectionCode.Memory:
                return(MemorySection.ReadSectionPayload(Header, this));

            case SectionCode.Global:
                return(GlobalSection.ReadSectionPayload(Header, this));

            case SectionCode.Export:
                return(ExportSection.ReadSectionPayload(Header, this));

            case SectionCode.Start:
                return(StartSection.ReadSectionPayload(Header, this));

            case SectionCode.Element:
                return(ElementSection.ReadSectionPayload(Header, this));

            case SectionCode.Code:
                return(CodeSection.ReadSectionPayload(Header, this));

            case SectionCode.Data:
                return(DataSection.ReadSectionPayload(Header, this));

            default:
                return(ReadUnknownSectionPayload(Header));
            }
        }
Пример #18
0
        public void UpdateList_ShouldntUpdateIfExistingObjectIsSectionSymbolAndNewHasSameName()
        {
            //Arrange
            UniqMemoryPartition   finalList         = new UniqMemoryPartition();
            IMemorySection        existingPartition = new MemorySection <string>("test", "test", "test", true);
            IMemorySection        newPartition      = new MemorySection <string>("test", "test1", "test1", false);
            List <IMemorySection> existingList      = new List <IMemorySection>();
            List <IMemorySection> newList           = new List <IMemorySection>();

            existingList.Add(existingPartition);
            newList.Add(newPartition);
            finalList.UpdateList(existingList);

            //Act
            finalList.UpdateList(newList);

            //Assert
            Assert.Contains <IMemorySection>(existingPartition, finalList.GetUniqMemoryPartition().Values);
            Assert.DoesNotContain <IMemorySection>(newPartition, finalList.GetUniqMemoryPartition().Values);
            Assert.True(finalList.GetUniqMemoryPartition().Values.Count == 1);
        }
Пример #19
0
        public void UpdateList_ShouldUpdateIfNewObjectHasDifferentName()
        {
            //Arrange
            UniqMemoryPartition   finalList         = new UniqMemoryPartition();
            IMemorySection        existingPartition = new MemorySection <string>("test", "test", "test", false);
            IMemorySection        newPartition      = new MemorySection <string>("test2", "test", "test", false);
            List <IMemorySection> existingList      = new List <IMemorySection>();
            List <IMemorySection> newList           = new List <IMemorySection>();

            existingList.Add(existingPartition);
            newList.Add(newPartition);
            finalList.UpdateList(existingList);

            //Act
            finalList.UpdateList(newList);

            //Assert
            Assert.Contains <IMemorySection>(existingPartition, finalList.GetUniqMemoryPartition().Values);
            Assert.Contains <IMemorySection>(newPartition, finalList.GetUniqMemoryPartition().Values);
            Assert.True(finalList.GetUniqMemoryPartition().Values.Count == 2);
        }
Пример #20
0
        private void PutIntoAddress(RiscVProgramResult res, MemorySection memorySection, byte longByte)
        {
            switch (memorySection)
            {
            case MemorySection.Text:
                res.Memory.Add(0x10000 + res.StackTextFreePosition, longByte);
                res.StackTextFreePosition++;
                break;

            case MemorySection.Static:
                res.Memory.Add((uint)0x10000000 + res.StackStaticDataFreePosition, longByte);
                res.StackStaticDataFreePosition++;
                break;

            default:
                throw new SimulatorException
                      {
                          ErrorMessage = $"'{memorySection}' cannot find fit section to return from f. GetAddress"
                      };
            }
        }
    public static PackedMemorySnapshot LoadSnapshotBin(Stream stream)
    {
        System.Reflection.ConstructorInfo ci = typeof(PackedMemorySnapshot).GetConstructor(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic, null, new Type[0], new System.Reflection.ParameterModifier[0]);
        PackedMemorySnapshot packed          = ci.Invoke(null) as PackedMemorySnapshot;
        BinaryReader         br = new BinaryReader(stream);

        stream.Position += 8;
        MemUtil.LoadSnapshotProgress(0, "Loading Connection");
        float prog     = 0;
        float lastProg = 0;

        var len        = br.ReadInt32();
        var connctions = new Connection[len];

        System.Reflection.FieldInfo fi = typeof(PackedMemorySnapshot).GetField("m_Connections", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        fi.SetValue(packed, connctions);

        for (int i = 0; i < len; i++)
        {
            Connection c = new Connection();
            c.from = br.ReadInt32();
            c.to   = br.ReadInt32();
            prog   = ((float)i / len) * 0.15f;
            if (prog - lastProg > 0.01)
            {
                MemUtil.LoadSnapshotProgress(prog, string.Format("Loading Connction {0}/{1}", i + 1, len));
                lastProg = prog;
            }
            connctions[i] = c;
        }

        len = br.ReadInt32();
        PackedGCHandle[] handles = new PackedGCHandle[len];
        fi = typeof(PackedMemorySnapshot).GetField("m_GcHandles", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        fi.SetValue(packed, handles);
        System.Reflection.FieldInfo[] fis = new System.Reflection.FieldInfo[]
        {
            typeof(PackedGCHandle).GetField("m_Target", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
        };

        for (int i = 0; i < len; i++)
        {
            object h = new PackedGCHandle();

            var target = br.ReadUInt64();
            fi = fis[0];
            fi.SetValue(h, target);

            prog = 0.15f + ((float)i / len) * 0.15f;
            if (prog - lastProg > 0.01)
            {
                MemUtil.LoadSnapshotProgress(prog, string.Format("Loading GCHandles {0}/{1}", i + 1, len));
                lastProg = prog;
            }
            handles[i] = (PackedGCHandle)h;
        }

        len = br.ReadInt32();
        MemorySection[] managedHeap = new MemorySection[len];
        fi = typeof(PackedMemorySnapshot).GetField("m_ManagedHeapSections", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        fi.SetValue(packed, managedHeap);

        fis = new System.Reflection.FieldInfo[]
        {
            typeof(MemorySection).GetField("m_Bytes", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(MemorySection).GetField("m_StartAddress", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
        };
        for (int i = 0; i < len; i++)
        {
            object h            = new MemorySection();
            var    bLen         = br.ReadInt32();
            var    bytes        = br.ReadBytes(bLen);
            var    startAddress = br.ReadUInt64();
            fi = fis[0];
            fi.SetValue(h, bytes);

            fi = fis[1];
            fi.SetValue(h, startAddress);

            prog = 0.3f + ((float)i / len) * 0.15f;
            if (prog - lastProg > 0.01)
            {
                MemUtil.LoadSnapshotProgress(prog, string.Format("Loading Managed Heap {0}/{1}", i + 1, len));
                lastProg = prog;
            }
            managedHeap[i] = (MemorySection)h;
            if (managedHeap[i].bytes == null)
            {
                UnityEngine.Debug.Log("ff");
            }
        }

        len = br.ReadInt32();
        PackedNativeUnityEngineObject[] nativeObj = new PackedNativeUnityEngineObject[len];
        fi = typeof(PackedMemorySnapshot).GetField("m_NativeObjects", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        fi.SetValue(packed, nativeObj);

        fis = new System.Reflection.FieldInfo[]
        {
            typeof(PackedNativeUnityEngineObject).GetField("m_ClassId", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(PackedNativeUnityEngineObject).GetField("m_HideFlags", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(PackedNativeUnityEngineObject).GetField("m_InstanceId", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(PackedNativeUnityEngineObject).GetField("m_Flags", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(PackedNativeUnityEngineObject).GetField("m_Name", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(PackedNativeUnityEngineObject).GetField("m_NativeObjectAddress", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(PackedNativeUnityEngineObject).GetField("m_Size", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
        };
        for (int i = 0; i < len; i++)
        {
            object    obj        = new PackedNativeUnityEngineObject();
            int       clsID      = br.ReadInt32();
            HideFlags hideFlags  = (HideFlags)br.ReadByte();
            int       instanceID = br.ReadInt32();
            var       ft         = typeof(PackedNativeUnityEngineObject).GetNestedType("ObjectFlags", System.Reflection.BindingFlags.NonPublic);
            int       flags      = 0;
            if (br.ReadBoolean())
            {
                flags |= 1;
            }
            if (br.ReadBoolean())
            {
                flags |= 4;
            }
            if (br.ReadBoolean())
            {
                flags |= 2;
            }
            object flag = Enum.ToObject(ft, flags);
            string name = null;
            if (br.ReadBoolean())
            {
                name = br.ReadString();
            }
            long nativeAddress = br.ReadInt64();
            int  size          = br.ReadInt32();

            fi = fis[0];
            fi.SetValue(obj, clsID);

            fi = fis[1];
            fi.SetValue(obj, hideFlags);

            fi = fis[2];
            fi.SetValue(obj, instanceID);

            fi = fis[3];
            fi.SetValue(obj, flag);

            fi = fis[4];
            fi.SetValue(obj, name);

            fi = fis[5];
            fi.SetValue(obj, nativeAddress);

            fi = fis[6];
            fi.SetValue(obj, size);

            prog = 0.45f + ((float)i / len) * 0.15f;
            if (prog - lastProg > 0.01)
            {
                MemUtil.LoadSnapshotProgress(prog, string.Format("Loading Native Objects {0}/{1}", i + 1, len));
                lastProg = prog;
            }
            nativeObj[i] = (PackedNativeUnityEngineObject)obj;
        }

        len = br.ReadInt32();
        PackedNativeType[] nativeTypes = new PackedNativeType[len];
        fi = typeof(PackedMemorySnapshot).GetField("m_NativeTypes", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        fi.SetValue(packed, nativeTypes);
        fis = new System.Reflection.FieldInfo[]
        {
            typeof(PackedNativeType).GetField("m_BaseClassId", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(PackedNativeType).GetField("m_Name", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
        };
        for (int i = 0; i < len; i++)
        {
            object t           = new PackedNativeType();
            int    baseClassId = br.ReadInt32();
            string name        = null;
            if (br.ReadBoolean())
            {
                name = br.ReadString();
            }

            fi = fis[0];
            fi.SetValue(t, baseClassId);

            fi = fis[1];
            fi.SetValue(t, name);

            prog = 0.6f + ((float)i / len) * 0.15f;
            if (prog - lastProg > 0.01)
            {
                MemUtil.LoadSnapshotProgress(prog, string.Format("Loading Native Types {0}/{1}", i + 1, len));
                lastProg = prog;
            }
            nativeTypes[i] = (PackedNativeType)t;
        }

        len = br.ReadInt32();
        TypeDescription[] typeDesc = new TypeDescription[len];
        fi = typeof(PackedMemorySnapshot).GetField("m_TypeDescriptions", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        fi.SetValue(packed, typeDesc);
        fis = new System.Reflection.FieldInfo[]
        {
            typeof(TypeDescription).GetField("m_Assembly", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(TypeDescription).GetField("m_BaseOrElementTypeIndex", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(TypeDescription).GetField("m_Fields", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(TypeDescription).GetField("m_Flags", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(TypeDescription).GetField("m_Name", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(TypeDescription).GetField("m_Size", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(TypeDescription).GetField("m_StaticFieldBytes", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(TypeDescription).GetField("m_TypeIndex", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(TypeDescription).GetField("m_TypeInfoAddress", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
        };
        var fis2 = new System.Reflection.FieldInfo[]
        {
            typeof(FieldDescription).GetField("m_IsStatic", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(FieldDescription).GetField("m_Name", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(FieldDescription).GetField("m_Offset", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(FieldDescription).GetField("m_TypeIndex", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
        };

        for (int i = 0; i < len; i++)
        {
            object             t        = new TypeDescription();
            int                flags    = br.ReadInt32() << 0x10;
            string             assembly = br.ReadString();
            int                baseOrElementTypeIndex = br.ReadInt32();
            int                fLen   = br.ReadInt32();
            FieldDescription[] fields = new FieldDescription[fLen];
            for (int j = 0; j < fLen; j++)
            {
                object f          = new FieldDescription();
                bool   isStatic   = br.ReadBoolean();
                string fname      = br.ReadString();
                int    offset     = br.ReadInt32();
                int    ftypeIndex = br.ReadInt32();

                fi = fis2[0];
                fi.SetValue(f, isStatic);

                fi = fis2[1];
                fi.SetValue(f, fname);

                fi = fis2[2];
                fi.SetValue(f, offset);

                fi = fis2[3];
                fi.SetValue(f, ftypeIndex);
                fields[j] = (FieldDescription)f;
            }

            if (br.ReadBoolean())
            {
                flags |= 2;
            }
            if (br.ReadBoolean())
            {
                flags |= 1;
            }

            string name        = br.ReadString();
            int    size        = br.ReadInt32();
            byte[] staticField = br.ReadBytes(br.ReadInt32());
            int    typeIndex   = br.ReadInt32();
            ulong  typeAddress = br.ReadUInt64();

            fi = fis[0];
            fi.SetValue(t, assembly);
            fi = fis[1];
            fi.SetValue(t, baseOrElementTypeIndex);
            fi = fis[2];
            fi.SetValue(t, fields);
            fi = fis[3];
            fi.SetValue(t, Enum.ToObject(typeof(TypeDescription).GetNestedType("TypeFlags", System.Reflection.BindingFlags.NonPublic), flags));
            fi = fis[4];
            fi.SetValue(t, name);
            fi = fis[5];
            fi.SetValue(t, size);
            fi = fis[6];
            fi.SetValue(t, staticField);
            fi = fis[7];
            fi.SetValue(t, typeIndex);
            fi = fis[8];
            fi.SetValue(t, typeAddress);

            prog = 0.75f + ((float)i / len) * 0.15f;
            if (prog - lastProg > 0.01)
            {
                MemUtil.LoadSnapshotProgress(prog, string.Format("Loading Type Definitions {0}/{1}", i + 1, len));
                lastProg = prog;
            }
            typeDesc[i] = (TypeDescription)t;
        }

        object vminfo = new VirtualMachineInformation();

        fis = new System.Reflection.FieldInfo[]
        {
            typeof(VirtualMachineInformation).GetField("m_AllocationGranularity", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(VirtualMachineInformation).GetField("m_ArrayBoundsOffsetInHeader", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(VirtualMachineInformation).GetField("m_ArrayHeaderSize", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(VirtualMachineInformation).GetField("m_ArraySizeOffsetInHeader", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(VirtualMachineInformation).GetField("m_ObjectHeaderSize", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
            typeof(VirtualMachineInformation).GetField("m_PointerSize", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic),
        };

        fis[0].SetValue(vminfo, br.ReadInt32());
        fis[1].SetValue(vminfo, br.ReadInt32());
        fis[2].SetValue(vminfo, br.ReadInt32());
        fis[3].SetValue(vminfo, br.ReadInt32());
        int version = br.ReadInt32();

        fis[4].SetValue(vminfo, br.ReadInt32());
        fis[5].SetValue(vminfo, br.ReadInt32());
        fi = typeof(PackedMemorySnapshot).GetField("m_VirtualMachineInformation", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        fi.SetValue(packed, vminfo);
        MemUtil.LoadSnapshotProgress(1f, "done");

        return(packed);
    }
Пример #22
0
 public void PopulatePartitionsGrid(MemorySection <string> structure)
 {
     DataGrid.GeneratePartitionsTable(structure);
 }
Пример #23
0
        public void DrawPlainData()
        {
            if (_unpackedCrawl != null)
            {
                GUILayout.Label(" ");
                if (GUILayout.Button("Save managed heap data to an external .csv file", blueColorStyle))
                {
                    string exportPath = EditorUtility.SaveFilePanel("Save Snapshot Info", Application.dataPath, "MANAGEDHEAP_SnapshotExport_" + DateTime.Now.ToString("dd_MM_yyyy_hh_mm_ss") + ".csv", "csv");
                    if (!String.IsNullOrEmpty(exportPath))
                    {
                        System.IO.StreamWriter sw = new System.IO.StreamWriter(exportPath);
                        sw.WriteLine(" Managed Objects , Size , Address ");
                        for (int i = 0; i < _unpackedCrawl.managedHeap.Length; i++)
                        {
                            MemorySection memorySection = _unpackedCrawl.managedHeap[i];
                            sw.WriteLine("Managed," + memorySection.bytes.Length + "," + memorySection.startAddress);
                        }
                        sw.Flush();
                        sw.Close();
                    }
                }
                if (GUILayout.Button("Save full list of MANAGED objects data to an external .csv file", blueColorStyle))
                {
                    string exportPath = EditorUtility.SaveFilePanel("Save Snapshot Info", Application.dataPath, "MANAGED_SnapshotExport_" + DateTime.Now.ToString("dd_MM_yyyy_hh_mm_ss") + ".csv", "csv");
                    if (!String.IsNullOrEmpty(exportPath))
                    {
                        m_ManagedGroups.Clear();
                        System.IO.StreamWriter sw = new System.IO.StreamWriter(exportPath);
                        sw.WriteLine(" Managed Objects , Size , Caption , Type , Number of References (Total), Referenced By (Total), Address ");
                        for (int i = 0; i < _unpackedCrawl.managedObjects.Length; i++)
                        {
                            ManagedObject managedObject = _unpackedCrawl.managedObjects[i];
                            sw.WriteLine("Managed," + managedObject.size + "," + CleanStrings(managedObject.caption) + "," + CleanStrings(managedObject.typeDescription.name) + "," + managedObject.references.Length + "," + managedObject.referencedBy.Length + "," + managedObject.address);

                            string           type = managedObject.typeDescription.name;
                            long             size = managedObject.size;
                            ManagedGroupInfo info;
                            if (m_ManagedGroups.TryGetValue(type, out info))
                            {
                                ++info.Count;
                                info.Size += size;
                            }
                            else
                            {
                                string g  = string.Empty;
                                int    si = type.IndexOf('.');
                                if (si > 0)
                                {
                                    g = type.Substring(0, si);
                                    if (!s_ManagedGroupNames.Contains(g))
                                    {
                                        g = string.Empty;
                                    }
                                }
                                info = new ManagedGroupInfo {
                                    Group = g, Type = type, Count = 1, Size = size
                                };
                                m_ManagedGroups.Add(type, info);
                            }
                        }
                        sw.Flush();
                        sw.Close();

                        string dir       = Path.GetDirectoryName(exportPath);
                        string fn        = Path.GetFileNameWithoutExtension(exportPath);
                        string gpath     = Path.Combine(dir, fn + "_groups.csv");
                        var    lastGroup = "A000000";
                        using (var outsw = new StreamWriter(gpath)) {
                            outsw.WriteLine("group,type,count,size");
                            foreach (var pair in m_ManagedGroups)
                            {
                                var info = pair.Value;
                                var g    = info.Group;
                                if (!string.IsNullOrEmpty(lastGroup) && string.IsNullOrEmpty(info.Group))
                                {
                                    g = lastGroup + "__";
                                }
                                if (!string.IsNullOrEmpty(info.Group))
                                {
                                    lastGroup = info.Group;
                                }
                                outsw.WriteLine("{0},\"{1}\",{2},{3}", g, info.Type, info.Count, info.Size);
                            }
                        }
                        string gpath2 = Path.Combine(dir, fn + "_groups_forcmp.csv");
                        using (var outsw = new StreamWriter(gpath2)) {
                            outsw.WriteLine("type,count,size");
                            foreach (var pair in m_ManagedGroups)
                            {
                                var info = pair.Value;
                                outsw.WriteLine("\"{0}\",{1},{2}", info.Type, info.Count, info.Size);
                            }
                        }
                    }
                }
                if (GUILayout.Button("Save full list of NATIVE objects data to an external .csv file", greenColorStyle))
                {
                    string exportPath = EditorUtility.SaveFilePanel("Save Snapshot Info", Application.dataPath, "NATIVE_SnapshotExport_" + DateTime.Now.ToString("dd_MM_yyyy_hh_mm_ss") + ".csv", "csv");
                    if (!String.IsNullOrEmpty(exportPath))
                    {
                        m_NativeGroups.Clear();
                        System.IO.StreamWriter sw = new System.IO.StreamWriter(exportPath);
                        sw.WriteLine(" Native Objects , Size , Caption , Class Name , Name , Number of References (Total), Referenced By (Total), InstanceID ");
                        for (int i = 0; i < _unpackedCrawl.nativeObjects.Length; i++)
                        {
                            NativeUnityEngineObject nativeObject = _unpackedCrawl.nativeObjects[i];
                            sw.WriteLine("Native," + nativeObject.size + "," + CleanStrings(nativeObject.caption) + "," + CleanStrings(nativeObject.className) + "," + CleanStrings(nativeObject.name) + "," + nativeObject.references.Length + "," + nativeObject.referencedBy.Length + "," + nativeObject.instanceID);

                            string          type = nativeObject.className;
                            long            size = nativeObject.size;
                            NativeGroupInfo info;
                            if (m_NativeGroups.TryGetValue(type, out info))
                            {
                                ++info.Count;
                                info.Size += size;
                            }
                            else
                            {
                                info = new NativeGroupInfo {
                                    Type = type, Count = 1, Size = size
                                };
                                m_NativeGroups.Add(type, info);
                            }
                        }
                        sw.Flush();
                        sw.Close();

                        string dir   = Path.GetDirectoryName(exportPath);
                        string fn    = Path.GetFileNameWithoutExtension(exportPath);
                        string gpath = Path.Combine(dir, fn + "_groups.csv");
                        using (var outsw = new StreamWriter(gpath)) {
                            outsw.WriteLine("type,count,size");
                            foreach (var pair in m_NativeGroups)
                            {
                                var info = pair.Value;
                                outsw.WriteLine("\"{0}\",{1},{2}", info.Type, info.Count, info.Size);
                            }
                        }
                    }
                }
                GUILayout.Label(" ");
                GUILayout.Label("Managed Objects (Total: " + _unpackedCrawl.managedObjects.Length + ") - First 10 Elements: ");
                GUILayout.Label(" ");
                for (int i = 0; i < _unpackedCrawl.managedObjects.Length && i < 10; i++)
                {
                    ManagedObject managedObject = _unpackedCrawl.managedObjects[i];
                    GUILayout.Label("Address: " + managedObject.address + ", Caption: " + managedObject.caption + ", Size: " + managedObject.size);
                }
                GUILayout.Label(" ");
                GUILayout.Label("Native Objects (Total: " + _unpackedCrawl.nativeObjects.Length + ") - First 10 Elements:");
                GUILayout.Label(" ");
                for (int i = 0; i < _unpackedCrawl.nativeObjects.Length && i < 10; i++)
                {
                    NativeUnityEngineObject nativeObject = _unpackedCrawl.nativeObjects[i];
                    GUILayout.Label("InstanceID: " + nativeObject.instanceID + ", Name: " + nativeObject.name + ", Size: " + nativeObject.size);
                }
            }
        }
Пример #24
0
        /// <summary>
        /// Читает байты с метки с определенной секции данных.
        /// </summary>
        /// <remarks></remarks>
        /// <param name="tag"></param>
        /// <param name="data">Внимание! RWDev.ReadCard_G2 возвращает Len = 5, если метка считана не была.
        /// В этом случае данный метод присваивает data пустое значение null</param>
        /// <param name="memorySection"></param>
        /// <returns></returns>
        public ResultCode ReadBytes(byte[] tag, ref byte[] data, MemorySection memorySection)
        {
            byte totalLength = 0; //Некая общая длина всех передаваемых данных
            byte offset = 0; //Смещение, с которого считать данные
            var result = ResultCode.UnknownError;
            byte errorCode = 0;

            totalLength = (byte)(12 + tag.Length); //12 - это китайская магия

            result = (ResultCode)RWDev.ReadCard_G2(
                ref address,
                ref totalLength,
                (byte)(tag.Length/2),
                tag,
                (byte)memorySection,
                offset,
                (byte)(data.Length/2),
                password,
                data,
                ref errorCode);

            if (totalLength == 5)
            {
                data = null;
            }

            return result;
        }
Пример #25
0
        public ResultCode WriteBytes(byte[] tag, byte[] data, MemorySection memorySection)
        {
            byte totalLength = 0; //Некая общая длина всех передаваемых данных
            byte offset = 0; //Смещение, с которого записать данные
            var result = ResultCode.UnknownError;
            byte errorCode = 0;

            totalLength = Convert.ToByte(12 + tag.Length + data.Length); //12 - это китайская магия

            return result = (ResultCode)RWDev.WriteCard_G2(
                ref address,
                ref totalLength,
                (byte)(data.Length/2),
                (byte)(tag.Length/2),
                tag,
                (byte)memorySection,
                offset,
                data,
                password,
                ref errorCode);
        }
Пример #26
0
 /// <summary>
 /// Checks if this section has the same start and length than the other
 /// </summary>
 /// <param name="other">Other memory section</param>
 /// <returns>Thrue, if the sections have the same start and length</returns>
 public bool SameSection(MemorySection other)
 {
     return(StartAddress == other.StartAddress && EndAddress == other.EndAddress);
 }
        public bool CanExecute(object parameter)
        {
            MemorySection <string> param = parameter as MemorySection <string>;

            return(param != null);
        }
Пример #28
0
 protected bool Equals(MemorySection other)
 {
     return(StartAddress == other.StartAddress &&
            EndAddress == other.EndAddress &&
            SectionType == other.SectionType);
 }
        private MemberPrecidence LoadScatterElements(object owner, object conditional, List <MemoryMap> maps, ArrayList conditionalStack)
        {
            MemberPrecidence ret = MemberPrecidence.Unknown;

            List <If> ifs = GetCollectionFromObject(conditional, typeof(List <If>)) as List <If>;

            if (ifs != null && ifs.Count > 0)
            {
                LoadScatterConditional(owner, ifs, maps, conditionalStack);
            }
            List <IfDefined> ifdefs = GetCollectionFromObject(conditional, typeof(List <IfDefined>)) as List <IfDefined>;

            if (ifdefs != null)
            {
                LoadScatterConditional(owner, ifdefs, maps, conditionalStack);
            }
            List <IfNotDefined> ifndefs = GetCollectionFromObject(conditional, typeof(List <IfNotDefined>)) as List <IfNotDefined>;

            if (ifndefs != null)
            {
                LoadScatterConditional(owner, ifndefs, maps, conditionalStack);
            }

            List <LoadRegion> lrCollection = GetCollectionFromObject(conditional, typeof(List <LoadRegion>)) as List <LoadRegion>;

            if (lrCollection != null && lrCollection.Count > 0)
            {
                List <MemoryRegion> regionSet = GetCollectionFromObject(owner, typeof(List <MemoryRegion>)) as List <MemoryRegion>;

                ret = MemberPrecidence.LoadRegion;

                foreach (LoadRegion lr in lrCollection)
                {
                    MemoryRegion region = new MemoryRegion();
                    region.Name    = lr.Name;
                    region.Address = lr.Base;
                    region.Options = lr.Options;
                    region.Size    = lr.Size;
//                    region.Order = regionSet.Count;
                    region.Conditional = GetConditionalValue(conditional);

                    regionSet.Add(region);

                    ret = LoadScatterElements(region, lr, maps, conditionalStack);
                }
            }

            List <ExecRegion> erCollection = GetCollectionFromObject(conditional, typeof(List <ExecRegion>)) as List <ExecRegion>;

            if (erCollection != null && erCollection.Count > 0)
            {
                List <MemorySection> sectionSet = GetCollectionFromObject(owner, typeof(List <MemorySection>)) as List <MemorySection>;

                ret = MemberPrecidence.ExecRegion;

                foreach (ExecRegion er in erCollection)
                {
                    MemorySection section = new MemorySection();
                    section.Name        = er.Name;
                    section.Address     = er.Base;
                    section.Options     = er.Options;
                    section.Size        = er.Size;
                    section.Order       = (int)m_execRegionOrderMap[(owner as MemoryRegion).Name + ":" + er.Name];
                    section.Conditional = GetConditionalValue(conditional);

                    sectionSet.Add(section);

                    ret = LoadScatterElements(section, er, maps, conditionalStack);
                }
            }

            List <FileMapping> fileCollection = GetCollectionFromObject(conditional, typeof(List <FileMapping>)) as List <FileMapping>;

            if (fileCollection != null && fileCollection.Count > 0)
            {
                List <MemorySymbol> symSet = GetCollectionFromObject(owner, typeof(List <MemorySymbol>)) as List <MemorySymbol>;

                ret = MemberPrecidence.FileMapping;


                foreach (FileMapping fm in fileCollection)
                {
                    MemorySymbol sym = new MemorySymbol();
                    sym.Name        = fm.Name;
                    sym.Options     = fm.Options;
                    sym.Conditional = GetConditionalValue(conditional);

                    symSet.Add(sym);
                }
            }

            List <Set> setCollection = GetCollectionFromObject(conditional, typeof(List <Set>)) as List <Set>;

            if (setCollection != null && setCollection.Count > 0)
            {
                EnvVars envSets = GetObjectFromProperty(owner, typeof(EnvVars)) as EnvVars;

                if (ret < MemberPrecidence.SetMember)
                {
                    ret = MemberPrecidence.SetMember;
                }

                EnvVars envSet = null;

                // conditional belongs to the map if we have a load region in this conditional
                if (conditionalStack.Count == 0)
                {
                    envSet = FindMatchingSet(envSets, "Global");

                    if (envSet == null)
                    {
                        envSet      = new EnvVars();
                        envSet.Name = "Global";
                        envSets.EnvVarsCollection.Add(envSet);
                    }
                }
                else
                {
                    for (int i = 0; i < conditionalStack.Count; i++)
                    {
                        object cond = conditionalStack[i];

                        if (i == (conditionalStack.Count - 1) && owner is MemoryMap && ret >= MemberPrecidence.LoadRegion)
                        {
                            ((MemoryMap)owner).Name        = GetConditionalName(conditional);
                            ((MemoryMap)owner).Conditional = GetConditionalValue(conditional);
                        }
                        else
                        {
                            string name  = GetConditionalName(cond);
                            string value = GetConditionalValue(cond);

                            name += "_" + value.Replace(" ", "_").Replace("\"", "");

                            envSet = FindMatchingSet(envSets, name);

                            if (envSet == null)
                            {
                                envSet             = new EnvVars();
                                envSet.Name        = name;
                                envSet.Conditional = value;

                                envSets.EnvVarsCollection.Add(envSet);
                            }

                            //envSets = envSet.EnvVarsCollection;
                        }
                    }
                }


                if ((int)ret < (int)MemberPrecidence.SetMember)
                {
                    ret = MemberPrecidence.SetMember;
                }

                foreach (Set set in GetCollectionFromObject(conditional, typeof(List <Set>)))
                {
                    EnvVar var = new EnvVar();
                    var.Name  = set.Name;
                    var.Value = set.Value;

                    envSet.EnvVarCollection.Add(var);
                }
            }

            return(ret);
        }
Пример #30
0
        // strict parse means all sections must come in order
        public void ParseAsWASM(string filename, bool strict_parse = true)
        {
            if (!BitConverter.IsLittleEndian)
            {
                throw new NotImplementedException("LEB128 implementation only handles little endian systems");
            }

            using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                BinaryReader reader = new BinaryReader(fs);
                uint         magic  = reader.ReadUInt32();
                if (magic != MAGIC)
                {
                    throw new Exception("Not a compiled Web Assembly file.");
                }

                uint version = reader.ReadUInt32();
                if (version > SUPPORTED_VERSION)
                {
                    throw new Exception($"Unsupported version. Expected version <= {SUPPORTED_VERSION}, received {version}.");
                }

                int last_parsed_module = int.MinValue;

                /* Read in each module */

                while (true)
                {
                    int id = reader.PeekChar();

                    // EOF
                    if (id == -1)
                    {
                        break;
                    }

                    if (strict_parse && id < last_parsed_module)
                    {
                        throw new Exception("File contains out of order sections.");
                    }
                    last_parsed_module = id;

                    switch (id)
                    {
                    case (int)WebAssemblyModuleID.Custom:
                        if (strict_parse && custom != null)
                        {
                            throw new Exception("File contains a duplicate custom section.");
                        }
                        custom = new CustomSection(reader);
                        break;

                    case (int)WebAssemblyModuleID.Type:
                        if (strict_parse && type != null)
                        {
                            throw new Exception("File contains a duplicate type section.");
                        }
                        type = new TypeSection(reader);
                        break;

                    case (int)WebAssemblyModuleID.Import:
                        if (strict_parse && import != null)
                        {
                            throw new Exception("File contains a duplicate import section.");
                        }
                        import = new ImportSection(reader);
                        break;

                    case (int)WebAssemblyModuleID.Function:
                        if (strict_parse && function != null)
                        {
                            throw new Exception("File contains a duplicate function section.");
                        }
                        function = new FunctionSection(reader);
                        break;

                    case (int)WebAssemblyModuleID.Table:
                        if (strict_parse && table != null)
                        {
                            throw new Exception("File contains a duplicate table section.");
                        }
                        table = new TableSection(reader);
                        break;

                    case (int)WebAssemblyModuleID.Memory:
                        if (strict_parse && memory != null)
                        {
                            throw new Exception("File contains a duplicate memory section.");
                        }
                        memory = new MemorySection(reader);
                        break;

                    case (int)WebAssemblyModuleID.Global:
                        if (strict_parse && global != null)
                        {
                            throw new Exception("File contains a duplicate global section.");
                        }
                        global = new GlobalSection(reader);
                        break;

                    case (int)WebAssemblyModuleID.Export:
                        if (strict_parse && export != null)
                        {
                            throw new Exception("File contains a duplicate export section.");
                        }
                        export = new ExportSection(reader);
                        break;

                    case (int)WebAssemblyModuleID.Start:
                        if (strict_parse && start != null)
                        {
                            throw new Exception("File contains a duplicate start section.");
                        }
                        start = new StartSection(reader);
                        break;

                    case (int)WebAssemblyModuleID.Element:
                        if (strict_parse && element != null)
                        {
                            throw new Exception("File contains a duplicate element section.");
                        }
                        element = new ElementSection(reader);
                        break;

                    case (int)WebAssemblyModuleID.Code:
                        if (strict_parse && code != null)
                        {
                            throw new Exception("File contains a duplicate code section.");
                        }
                        code = new CodeSection(reader);
                        break;

                    case (int)WebAssemblyModuleID.Data:
                        if (strict_parse && data != null)
                        {
                            throw new Exception("File contains a duplicate data section.");
                        }
                        data = new DataSection(reader);
                        break;

                    // Error
                    default:
                        throw new Exception($"Unknown section {id}.");
                    }
                }

                /* Additional validation */

                // The lengths of vectors produced by the (possibly empty) function and code section must match up.
                if ((function != null && code == null) || (function == null && code != null))
                {
                    throw new Exception("File corrupt. Must include both function and code sections.");
                }
                if (function.types.Length != code.bodies.Length)
                {
                    throw new Exception("File corrupt. Function and code sections do not match up.");
                }

                // TODO: I don't actually check if data overlaps

                // TODO: Validate everything in this list
                // https://webassembly.github.io/spec/core/valid/modules.html
            }
        }