diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs index 445d0dffd6..5ce6beafa4 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -384,11 +385,13 @@ public static IEnumerable GetMethodSpecifications(thi yield return Read(row); } - unsafe (Handle Handle, MethodSemanticsAttributes Semantics, MethodDefinitionHandle Method, EntityHandle Association) Read(int row) + (Handle Handle, MethodSemanticsAttributes Semantics, MethodDefinitionHandle Method, EntityHandle Association) Read(int row) { - byte* ptr = metadata.MetadataPointer + offset + rowSize * row; - int methodDef = methodSmall ? *(ushort*)(ptr + 2) : (int)*(uint*)(ptr + 2); - int assocDef = assocSmall ? *(ushort*)(ptr + assocOffset) : (int)*(uint*)(ptr + assocOffset); + var span = metadata.AsReadOnlySpan(); + var methodDefSpan = span.Slice(offset + rowSize * row + 2); + int methodDef = methodSmall ? BinaryPrimitives.ReadUInt16LittleEndian(methodDefSpan) : (int)BinaryPrimitives.ReadUInt32LittleEndian(methodDefSpan); + var assocSpan = span.Slice(assocOffset); + int assocDef = assocSmall ? BinaryPrimitives.ReadUInt16LittleEndian(assocSpan) : (int)BinaryPrimitives.ReadUInt32LittleEndian(assocSpan); EntityHandle propOrEvent; if ((assocDef & 0x1) == 1) { @@ -398,7 +401,7 @@ public static IEnumerable GetMethodSpecifications(thi { propOrEvent = MetadataTokens.EventDefinitionHandle(assocDef >> 1); } - return (MetadataTokens.Handle(0x18000000 | (row + 1)), (MethodSemanticsAttributes)(*(ushort*)ptr), MetadataTokens.MethodDefinitionHandle(methodDef), propOrEvent); + return (MetadataTokens.Handle(0x18000000 | (row + 1)), (MethodSemanticsAttributes)(BinaryPrimitives.ReadUInt16LittleEndian(span)), MetadataTokens.MethodDefinitionHandle(methodDef), propOrEvent); } } @@ -411,9 +414,9 @@ public static IEnumerable GetFieldLayouts(this MetadataReader meta } } - public unsafe static (int Offset, FieldDefinitionHandle FieldDef) GetFieldLayout(this MetadataReader metadata, EntityHandle fieldLayoutHandle) + public static (int Offset, FieldDefinitionHandle FieldDef) GetFieldLayout(this MetadataReader metadata, EntityHandle fieldLayoutHandle) { - byte* startPointer = metadata.MetadataPointer; + var startPointer = metadata.AsReadOnlySpan(); int offset = metadata.GetTableMetadataOffset(TableIndex.FieldLayout); int rowSize = metadata.GetTableRowSize(TableIndex.FieldLayout); int rowCount = metadata.GetTableRowCount(TableIndex.FieldLayout); @@ -422,14 +425,31 @@ public unsafe static (int Offset, FieldDefinitionHandle FieldDef) GetFieldLayout bool small = metadata.GetTableRowCount(TableIndex.Field) <= ushort.MaxValue; for (int row = rowCount - 1; row >= 0; row--) { - byte* ptr = startPointer + offset + rowSize * row; - uint rowNo = small ? *(ushort*)(ptr + 4) : *(uint*)(ptr + 4); + ReadOnlySpan ptr = startPointer.Slice(offset + rowSize * row); + var rowNoSpan = ptr.Slice(4); + uint rowNo = small ? BinaryPrimitives.ReadUInt16LittleEndian(rowNoSpan) : BinaryPrimitives.ReadUInt32LittleEndian(rowNoSpan); if (fieldRowNo == rowNo) { - return (*(int*)ptr, MetadataTokens.FieldDefinitionHandle(fieldRowNo)); + return (BinaryPrimitives.ReadInt32LittleEndian(ptr), MetadataTokens.FieldDefinitionHandle(fieldRowNo)); } } return (0, default); } + + public static ReadOnlySpan AsReadOnlySpan(this MetadataReader metadataReader) + { + unsafe + { + return new(metadataReader.MetadataPointer, metadataReader.MetadataLength); + } + } + + public static BlobReader AsBlobReader(this MetadataReader metadataReader) + { + unsafe + { + return new(metadataReader.MetadataPointer, metadataReader.MetadataLength); + } + } } } diff --git a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs index af78f30442..bc939f1bca 100644 --- a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs @@ -16,6 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -38,7 +40,7 @@ public ClassLayoutTableTreeNode(PEFile module) public override object Icon => Images.Literal; - public unsafe override bool View(ViewModels.TabPageModel tabPage) + public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; @@ -49,7 +51,7 @@ public unsafe override bool View(ViewModels.TabPageModel tabPage) var list = new List(); var length = metadata.GetTableRowCount(TableIndex.ClassLayout); - byte* ptr = metadata.MetadataPointer; + ReadOnlySpan ptr = metadata.AsReadOnlySpan(); int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; ClassLayoutEntry scrollTargetEntry = default; @@ -80,15 +82,15 @@ readonly struct ClassLayout public readonly EntityHandle Parent; public readonly uint ClassSize; - public unsafe ClassLayout(byte* ptr, int typeDefSize) + public ClassLayout(ReadOnlySpan ptr, int typeDefSize) { - PackingSize = (ushort)Helpers.GetValue(ptr, 2); - ClassSize = (uint)Helpers.GetValue(ptr + 2, 4); - Parent = MetadataTokens.TypeDefinitionHandle(Helpers.GetValue(ptr + 6, typeDefSize)); + PackingSize = BinaryPrimitives.ReadUInt16LittleEndian(ptr); + ClassSize = BinaryPrimitives.ReadUInt32LittleEndian(ptr.Slice(2, 4)); + Parent = MetadataTokens.TypeDefinitionHandle(Helpers.GetValueLittleEndian(ptr.Slice(6, typeDefSize))); } } - unsafe struct ClassLayoutEntry + struct ClassLayoutEntry { readonly PEFile module; readonly MetadataReader metadata; @@ -117,7 +119,7 @@ public void OnParentClick() [ColumnInfo("X8", Kind = ColumnKind.Other)] public uint ClassSize => classLayout.ClassSize; - public ClassLayoutEntry(PEFile module, byte* ptr, int metadataOffset, int row) + public ClassLayoutEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) { this.module = module; this.metadata = module.Metadata; @@ -125,7 +127,7 @@ public ClassLayoutEntry(PEFile module, byte* ptr, int metadataOffset, int row) var rowOffset = metadata.GetTableMetadataOffset(TableIndex.ClassLayout) + metadata.GetTableRowSize(TableIndex.ClassLayout) * (row - 1); this.Offset = metadataOffset + rowOffset; - this.classLayout = new ClassLayout(ptr + rowOffset, metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4); + this.classLayout = new ClassLayout(ptr.Slice(rowOffset), metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4); this.parentTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs index ae08337084..1d94b78c21 100644 --- a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs @@ -16,6 +16,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -38,7 +39,7 @@ public EventMapTableTreeNode(PEFile module) public override object Icon => Images.Literal; - public unsafe override bool View(ViewModels.TabPageModel tabPage) + public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; @@ -50,7 +51,7 @@ public unsafe override bool View(ViewModels.TabPageModel tabPage) EventMapEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.EventMap); - byte* ptr = metadata.MetadataPointer; + ReadOnlySpan ptr = metadata.AsReadOnlySpan(); int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { @@ -79,14 +80,14 @@ readonly struct EventMap public readonly TypeDefinitionHandle Parent; public readonly EventDefinitionHandle EventList; - public unsafe EventMap(byte* ptr, int typeDefSize, int eventDefSize) + public EventMap(ReadOnlySpan ptr, int typeDefSize, int eventDefSize) { - Parent = MetadataTokens.TypeDefinitionHandle(Helpers.GetValue(ptr, typeDefSize)); - EventList = MetadataTokens.EventDefinitionHandle(Helpers.GetValue(ptr + typeDefSize, eventDefSize)); + Parent = MetadataTokens.TypeDefinitionHandle(Helpers.GetValueLittleEndian(ptr.Slice(0, typeDefSize))); + EventList = MetadataTokens.EventDefinitionHandle(Helpers.GetValueLittleEndian(ptr.Slice(typeDefSize, eventDefSize))); } } - unsafe struct EventMapEntry + struct EventMapEntry { readonly PEFile module; readonly MetadataReader metadata; @@ -120,7 +121,7 @@ public void OnEventListClick() string eventListTooltip; public string EventListTooltip => GenerateTooltip(ref eventListTooltip, module, eventMap.EventList); - public EventMapEntry(PEFile module, byte* ptr, int metadataOffset, int row) + public EventMapEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) { this.module = module; this.metadata = module.Metadata; @@ -130,7 +131,7 @@ public EventMapEntry(PEFile module, byte* ptr, int metadataOffset, int row) this.Offset = metadataOffset + rowOffset; int typeDefSize = metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4; int eventDefSize = metadata.GetTableRowCount(TableIndex.Event) < ushort.MaxValue ? 2 : 4; - this.eventMap = new EventMap(ptr + rowOffset, typeDefSize, eventDefSize); + this.eventMap = new EventMap(ptr.Slice(rowOffset), typeDefSize, eventDefSize); this.parentTooltip = null; this.eventListTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs index 8a80966b0c..f5da959eb7 100644 --- a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs @@ -16,6 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -38,7 +40,7 @@ public FieldLayoutTableTreeNode(PEFile module) public override object Icon => Images.Literal; - public unsafe override bool View(ViewModels.TabPageModel tabPage) + public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; @@ -50,7 +52,7 @@ public unsafe override bool View(ViewModels.TabPageModel tabPage) FieldLayoutEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.FieldLayout); - byte* ptr = metadata.MetadataPointer; + ReadOnlySpan ptr = metadata.AsReadOnlySpan(); int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { @@ -79,14 +81,14 @@ readonly struct FieldLayout public readonly int Offset; public readonly FieldDefinitionHandle Field; - public unsafe FieldLayout(byte* ptr, int fieldDefSize) + public FieldLayout(ReadOnlySpan ptr, int fieldDefSize) { - Offset = Helpers.GetValue(ptr, 4); - Field = MetadataTokens.FieldDefinitionHandle(Helpers.GetValue(ptr + 4, fieldDefSize)); + Offset = BinaryPrimitives.ReadInt32LittleEndian(ptr); + Field = MetadataTokens.FieldDefinitionHandle(Helpers.GetValueLittleEndian(ptr.Slice(4, fieldDefSize))); } } - unsafe struct FieldLayoutEntry + struct FieldLayoutEntry { readonly PEFile module; readonly MetadataReader metadata; @@ -112,7 +114,7 @@ public void OnFieldClick() [ColumnInfo("X8", Kind = ColumnKind.Other)] public int FieldOffset => fieldLayout.Offset; - public FieldLayoutEntry(PEFile module, byte* ptr, int metadataOffset, int row) + public FieldLayoutEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) { this.module = module; this.metadata = module.Metadata; @@ -121,7 +123,7 @@ public FieldLayoutEntry(PEFile module, byte* ptr, int metadataOffset, int row) + metadata.GetTableRowSize(TableIndex.FieldLayout) * (row - 1); this.Offset = metadataOffset + rowOffset; int fieldDefSize = metadata.GetTableRowCount(TableIndex.Field) < ushort.MaxValue ? 2 : 4; - this.fieldLayout = new FieldLayout(ptr + rowOffset, fieldDefSize); + this.fieldLayout = new FieldLayout(ptr.Slice(rowOffset), fieldDefSize); this.fieldTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs index a9f26ff130..b6cc9771eb 100644 --- a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs @@ -16,6 +16,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -38,7 +39,7 @@ public FieldMarshalTableTreeNode(PEFile module) public override object Icon => Images.Literal; - public unsafe override bool View(ViewModels.TabPageModel tabPage) + public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; @@ -50,7 +51,7 @@ public unsafe override bool View(ViewModels.TabPageModel tabPage) FieldMarshalEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.FieldMarshal); - byte* ptr = metadata.MetadataPointer; + ReadOnlySpan ptr = metadata.AsReadOnlySpan(); int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { @@ -79,14 +80,14 @@ readonly struct FieldMarshal public readonly BlobHandle NativeType; public readonly EntityHandle Parent; - public unsafe FieldMarshal(byte* ptr, int blobHeapSize, int hasFieldMarshalRefSize) + public FieldMarshal(ReadOnlySpan ptr, int blobHeapSize, int hasFieldMarshalRefSize) { - Parent = Helpers.FromHasFieldMarshalTag((uint)Helpers.GetValue(ptr, hasFieldMarshalRefSize)); - NativeType = MetadataTokens.BlobHandle(Helpers.GetValue(ptr + hasFieldMarshalRefSize, blobHeapSize)); + Parent = Helpers.FromHasFieldMarshalTag((uint)Helpers.GetValueLittleEndian(ptr, hasFieldMarshalRefSize)); + NativeType = MetadataTokens.BlobHandle(Helpers.GetValueLittleEndian(ptr.Slice(hasFieldMarshalRefSize, blobHeapSize))); } } - unsafe struct FieldMarshalEntry + struct FieldMarshalEntry { readonly PEFile module; readonly MetadataReader metadata; @@ -112,7 +113,7 @@ public void OnParentClick() [ColumnInfo("X8", Kind = ColumnKind.HeapOffset)] public int NativeType => MetadataTokens.GetHeapOffset(fieldMarshal.NativeType); - public FieldMarshalEntry(PEFile module, byte* ptr, int metadataOffset, int row) + public FieldMarshalEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) { this.module = module; this.metadata = module.Metadata; @@ -122,7 +123,7 @@ public FieldMarshalEntry(PEFile module, byte* ptr, int metadataOffset, int row) this.Offset = metadataOffset + rowOffset; int hasFieldMarshalRefSize = metadata.ComputeCodedTokenSize(32768, TableMask.Field | TableMask.Param); int blobHeapSize = metadata.GetHeapSize(HeapIndex.Blob) < ushort.MaxValue ? 2 : 4; - this.fieldMarshal = new FieldMarshal(ptr + rowOffset, blobHeapSize, hasFieldMarshalRefSize); + this.fieldMarshal = new FieldMarshal(ptr.Slice(rowOffset), blobHeapSize, hasFieldMarshalRefSize); this.parentTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs index 9317bb3367..dc34c5c23c 100644 --- a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs @@ -16,6 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -38,7 +40,7 @@ public FieldRVATableTreeNode(PEFile module) public override object Icon => Images.Literal; - public unsafe override bool View(ViewModels.TabPageModel tabPage) + public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; @@ -50,7 +52,7 @@ public unsafe override bool View(ViewModels.TabPageModel tabPage) FieldRVAEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.FieldRva); - byte* ptr = metadata.MetadataPointer; + ReadOnlySpan ptr = metadata.AsReadOnlySpan(); int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { @@ -79,14 +81,14 @@ readonly struct FieldRVA public readonly int Offset; public readonly FieldDefinitionHandle Field; - public unsafe FieldRVA(byte* ptr, int fieldDefSize) + public FieldRVA(ReadOnlySpan ptr, int fieldDefSize) { - Offset = Helpers.GetValue(ptr, 4); - Field = MetadataTokens.FieldDefinitionHandle(Helpers.GetValue(ptr + 4, fieldDefSize)); + Offset = BinaryPrimitives.ReadInt32LittleEndian(ptr); + Field = MetadataTokens.FieldDefinitionHandle(Helpers.GetValueLittleEndian(ptr.Slice(4, fieldDefSize))); } } - unsafe struct FieldRVAEntry + struct FieldRVAEntry { readonly PEFile module; readonly MetadataReader metadata; @@ -112,7 +114,7 @@ public void OnFieldClick() [ColumnInfo("X8", Kind = ColumnKind.Other)] public int FieldOffset => fieldRVA.Offset; - public FieldRVAEntry(PEFile module, byte* ptr, int metadataOffset, int row) + public FieldRVAEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) { this.module = module; this.metadata = module.Metadata; @@ -121,7 +123,7 @@ public FieldRVAEntry(PEFile module, byte* ptr, int metadataOffset, int row) + metadata.GetTableRowSize(TableIndex.FieldRva) * (row - 1); this.Offset = metadataOffset + rowOffset; int fieldDefSize = metadata.GetTableRowCount(TableIndex.Field) < ushort.MaxValue ? 2 : 4; - this.fieldRVA = new FieldRVA(ptr + rowOffset, fieldDefSize); + this.fieldRVA = new FieldRVA(ptr.Slice(rowOffset), fieldDefSize); this.fieldTooltip = null; } } diff --git a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs index c6c228ba69..9a7642b25e 100644 --- a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs @@ -16,6 +16,8 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -40,7 +42,9 @@ public ImplMapTableTreeNode(PEFile module) public override object Icon => Images.Literal; - public unsafe override bool View(ViewModels.TabPageModel tabPage) + + + public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; @@ -52,11 +56,11 @@ public unsafe override bool View(ViewModels.TabPageModel tabPage) ImplMapEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.ImplMap); - byte* ptr = metadata.MetadataPointer; + var span = metadata.AsReadOnlySpan(); int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { - ImplMapEntry entry = new ImplMapEntry(module, ptr, metadataOffset, rid); + ImplMapEntry entry = new ImplMapEntry(module, span, metadataOffset, rid); if (entry.RID == this.scrollTarget) { scrollTargetEntry = entry; @@ -83,16 +87,16 @@ readonly struct ImplMap public readonly StringHandle ImportName; public readonly ModuleReferenceHandle ImportScope; - public unsafe ImplMap(byte* ptr, int moduleRefSize, int memberForwardedTagRefSize, int stringHandleSize) + public ImplMap(ReadOnlySpan span, int moduleRefSize, int memberForwardedTagRefSize, int stringHandleSize) { - MappingFlags = (PInvokeAttributes)Helpers.GetValue(ptr, 2); - MemberForwarded = Helpers.FromMemberForwardedTag((uint)Helpers.GetValue(ptr + 2, memberForwardedTagRefSize)); - ImportName = MetadataTokens.StringHandle(Helpers.GetValue(ptr + 2 + memberForwardedTagRefSize, stringHandleSize)); - ImportScope = MetadataTokens.ModuleReferenceHandle(Helpers.GetValue(ptr + 2 + memberForwardedTagRefSize + stringHandleSize, moduleRefSize)); + MappingFlags = (PInvokeAttributes)BinaryPrimitives.ReadUInt16LittleEndian(span); + MemberForwarded = Helpers.FromMemberForwardedTag((uint)Helpers.GetValueLittleEndian(span.Slice(2, memberForwardedTagRefSize))); + ImportName = MetadataTokens.StringHandle(Helpers.GetValueLittleEndian(span.Slice(2 + memberForwardedTagRefSize, stringHandleSize))); + ImportScope = MetadataTokens.ModuleReferenceHandle(Helpers.GetValueLittleEndian(span.Slice(2 + memberForwardedTagRefSize + stringHandleSize, moduleRefSize))); } } - unsafe struct ImplMapEntry + struct ImplMapEntry { readonly PEFile module; readonly MetadataReader metadata; @@ -141,7 +145,7 @@ public void OnImportScopeClick() public string ImportNameTooltip => $"{MetadataTokens.GetHeapOffset(implMap.ImportName):X} \"{ImportName}\""; - public unsafe ImplMapEntry(PEFile module, byte* ptr, int metadataOffset, int row) + public ImplMapEntry(PEFile module, ReadOnlySpan span, int metadataOffset, int row) { this.module = module; this.metadata = module.Metadata; @@ -152,7 +156,7 @@ public unsafe ImplMapEntry(PEFile module, byte* ptr, int metadataOffset, int row int moduleRefSize = metadata.GetTableRowCount(TableIndex.ModuleRef) < ushort.MaxValue ? 2 : 4; int memberForwardedTagRefSize = metadata.ComputeCodedTokenSize(32768, TableMask.MethodDef | TableMask.Field); int stringHandleSize = metadata.GetHeapSize(HeapIndex.String) < ushort.MaxValue ? 2 : 4; - this.implMap = new ImplMap(ptr + rowOffset, moduleRefSize, memberForwardedTagRefSize, stringHandleSize); + this.implMap = new ImplMap(span.Slice(rowOffset), moduleRefSize, memberForwardedTagRefSize, stringHandleSize); this.importScopeTooltip = null; this.memberForwardedTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs index 35c66ab850..e1ea243bfb 100644 --- a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs @@ -16,6 +16,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -38,7 +39,7 @@ public InterfaceImplTableTreeNode(PEFile module) public override object Icon => Images.Literal; - public unsafe override bool View(ViewModels.TabPageModel tabPage) + public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; @@ -50,7 +51,7 @@ public unsafe override bool View(ViewModels.TabPageModel tabPage) InterfaceImplEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.InterfaceImpl); - byte* ptr = metadata.MetadataPointer; + ReadOnlySpan ptr = metadata.AsReadOnlySpan(); int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { @@ -79,14 +80,14 @@ readonly struct InterfaceImpl public readonly EntityHandle Class; public readonly EntityHandle Interface; - public unsafe InterfaceImpl(byte* ptr, int classSize, int interfaceSize) + public InterfaceImpl(ReadOnlySpan ptr, int classSize, int interfaceSize) { - Class = MetadataTokens.TypeDefinitionHandle(Helpers.GetValue(ptr, classSize)); - Interface = Helpers.FromTypeDefOrRefTag((uint)Helpers.GetValue(ptr + classSize, interfaceSize)); + Class = MetadataTokens.TypeDefinitionHandle(Helpers.GetValueLittleEndian(ptr, classSize)); + Interface = Helpers.FromTypeDefOrRefTag((uint)Helpers.GetValueLittleEndian(ptr.Slice(classSize, interfaceSize))); } } - unsafe struct InterfaceImplEntry + struct InterfaceImplEntry { readonly PEFile module; readonly MetadataReader metadata; @@ -120,7 +121,7 @@ public void OnInterfaceClick() string interfaceTooltip; public string InterfaceTooltip => GenerateTooltip(ref interfaceTooltip, module, interfaceImpl.Interface); - public InterfaceImplEntry(PEFile module, byte* ptr, int metadataOffset, int row) + public InterfaceImplEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) { this.module = module; this.metadata = module.Metadata; @@ -128,7 +129,7 @@ public InterfaceImplEntry(PEFile module, byte* ptr, int metadataOffset, int row) var rowOffset = metadata.GetTableMetadataOffset(TableIndex.InterfaceImpl) + metadata.GetTableRowSize(TableIndex.InterfaceImpl) * (row - 1); this.Offset = metadataOffset + rowOffset; - this.interfaceImpl = new InterfaceImpl(ptr + rowOffset, metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4, metadata.ComputeCodedTokenSize(16384, TableMask.TypeDef | TableMask.TypeRef | TableMask.TypeSpec)); + this.interfaceImpl = new InterfaceImpl(ptr.Slice(rowOffset), metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4, metadata.ComputeCodedTokenSize(16384, TableMask.TypeDef | TableMask.TypeRef | TableMask.TypeSpec)); this.interfaceTooltip = null; this.classTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs index de347fd332..acdcaad8f5 100644 --- a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs @@ -16,6 +16,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -38,7 +39,7 @@ public NestedClassTableTreeNode(PEFile module) public override object Icon => Images.Literal; - public unsafe override bool View(ViewModels.TabPageModel tabPage) + public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; @@ -50,7 +51,7 @@ public unsafe override bool View(ViewModels.TabPageModel tabPage) NestedClassEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.NestedClass); - byte* ptr = metadata.MetadataPointer; + ReadOnlySpan ptr = metadata.AsReadOnlySpan(); int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { @@ -79,14 +80,14 @@ readonly struct NestedClass public readonly TypeDefinitionHandle Nested; public readonly TypeDefinitionHandle Enclosing; - public unsafe NestedClass(byte* ptr, int typeDefSize) + public NestedClass(ReadOnlySpan ptr, int typeDefSize) { - Nested = MetadataTokens.TypeDefinitionHandle(Helpers.GetValue(ptr, typeDefSize)); - Enclosing = MetadataTokens.TypeDefinitionHandle(Helpers.GetValue(ptr + typeDefSize, typeDefSize)); + Nested = MetadataTokens.TypeDefinitionHandle(Helpers.GetValueLittleEndian(ptr, typeDefSize)); + Enclosing = MetadataTokens.TypeDefinitionHandle(Helpers.GetValueLittleEndian(ptr.Slice(typeDefSize), typeDefSize)); } } - unsafe struct NestedClassEntry + struct NestedClassEntry { readonly PEFile module; readonly MetadataReader metadata; @@ -120,7 +121,7 @@ public void OnEnclosingClassClick() string enclosingClassTooltip; public string EnclosingClassTooltip => GenerateTooltip(ref enclosingClassTooltip, module, nestedClass.Enclosing); - public unsafe NestedClassEntry(PEFile module, byte* ptr, int metadataOffset, int row) + public NestedClassEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) { this.module = module; this.metadata = module.Metadata; @@ -129,7 +130,7 @@ public unsafe NestedClassEntry(PEFile module, byte* ptr, int metadataOffset, int + metadata.GetTableRowSize(TableIndex.NestedClass) * (row - 1); this.Offset = metadataOffset + rowOffset; int typeDefSize = metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4; - this.nestedClass = new NestedClass(ptr + rowOffset, typeDefSize); + this.nestedClass = new NestedClass(ptr.Slice(rowOffset), typeDefSize); this.nestedClassTooltip = null; this.enclosingClassTooltip = null; } diff --git a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs index 64d9bb19ad..d07b126c49 100644 --- a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs +++ b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs @@ -16,6 +16,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; using System.Collections.Generic; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; @@ -38,7 +39,7 @@ public PropertyMapTableTreeNode(PEFile module) public override object Icon => Images.Literal; - public unsafe override bool View(ViewModels.TabPageModel tabPage) + public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; @@ -50,7 +51,7 @@ public unsafe override bool View(ViewModels.TabPageModel tabPage) PropertyMapEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.PropertyMap); - byte* ptr = metadata.MetadataPointer; + ReadOnlySpan ptr = metadata.AsReadOnlySpan(); int metadataOffset = module.Reader.PEHeaders.MetadataStartOffset; for (int rid = 1; rid <= length; rid++) { @@ -79,14 +80,14 @@ readonly struct PropertyMap public readonly TypeDefinitionHandle Parent; public readonly PropertyDefinitionHandle PropertyList; - public unsafe PropertyMap(byte* ptr, int typeDefSize, int propertyDefSize) + public PropertyMap(ReadOnlySpan ptr, int typeDefSize, int propertyDefSize) { - Parent = MetadataTokens.TypeDefinitionHandle(Helpers.GetValue(ptr, typeDefSize)); - PropertyList = MetadataTokens.PropertyDefinitionHandle(Helpers.GetValue(ptr + typeDefSize, propertyDefSize)); + Parent = MetadataTokens.TypeDefinitionHandle(Helpers.GetValueLittleEndian(ptr, typeDefSize)); + PropertyList = MetadataTokens.PropertyDefinitionHandle(Helpers.GetValueLittleEndian(ptr.Slice(typeDefSize, propertyDefSize))); } } - unsafe struct PropertyMapEntry + struct PropertyMapEntry { readonly PEFile module; readonly MetadataReader metadata; @@ -120,7 +121,7 @@ public void OnPropertyListClick() string propertyListTooltip; public string PropertyListTooltip => GenerateTooltip(ref propertyListTooltip, module, propertyMap.PropertyList); - public PropertyMapEntry(PEFile module, byte* ptr, int metadataOffset, int row) + public PropertyMapEntry(PEFile module, ReadOnlySpan ptr, int metadataOffset, int row) { this.module = module; this.metadata = module.Metadata; @@ -130,7 +131,7 @@ public PropertyMapEntry(PEFile module, byte* ptr, int metadataOffset, int row) this.Offset = metadataOffset + rowOffset; int typeDefSize = metadata.GetTableRowCount(TableIndex.TypeDef) < ushort.MaxValue ? 2 : 4; int propertyDefSize = metadata.GetTableRowCount(TableIndex.Property) < ushort.MaxValue ? 2 : 4; - this.propertyMap = new PropertyMap(ptr + rowOffset, typeDefSize, propertyDefSize); + this.propertyMap = new PropertyMap(ptr.Slice(rowOffset), typeDefSize, propertyDefSize); this.propertyListTooltip = null; this.parentTooltip = null; } diff --git a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs index e93c0c3d9a..f4a463e78d 100644 --- a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs +++ b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs @@ -44,7 +44,7 @@ public StateMachineMethodTableTreeNode(PEFile module, MetadataReader metadata, b public override object Icon => Images.Literal; - public unsafe override bool View(ViewModels.TabPageModel tabPage) + public override bool View(ViewModels.TabPageModel tabPage) { tabPage.Title = Text.ToString(); tabPage.SupportsLanguageSwitching = false; @@ -53,7 +53,7 @@ public unsafe override bool View(ViewModels.TabPageModel tabPage) var list = new List(); StateMachineMethodEntry scrollTargetEntry = default; var length = metadata.GetTableRowCount(TableIndex.StateMachineMethod); - var reader = new BlobReader(metadata.MetadataPointer, metadata.MetadataLength); + var reader = metadata.AsBlobReader(); reader.Offset = metadata.GetTableMetadataOffset(TableIndex.StateMachineMethod); for (int rid = 1; rid <= length; rid++) diff --git a/ILSpy/Metadata/Helpers.cs b/ILSpy/Metadata/Helpers.cs index da418b554a..792b73e1f4 100644 --- a/ILSpy/Metadata/Helpers.cs +++ b/ILSpy/Metadata/Helpers.cs @@ -212,11 +212,20 @@ static void ApplyAttributes(PropertyDescriptor descriptor, Binding binding, Data } } + [Obsolete("Use safe GetValueLittleEndian(ReadOnlySpan) or appropriate BinaryPrimitives.Read* method")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe int GetValue(byte* ptr, int size) + => GetValueLittleEndian(new ReadOnlySpan(ptr, size)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetValueLittleEndian(ReadOnlySpan ptr, int size) + => GetValueLittleEndian(ptr.Slice(0, size)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetValueLittleEndian(ReadOnlySpan ptr) { int result = 0; - for (int i = 0; i < size; i += 2) + for (int i = 0; i < ptr.Length; i += 2) { result |= ptr[i] << 8 * i; result |= ptr[i + 1] << 8 * (i + 1);