using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Text; using System.Threading.Tasks; using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler { public static partial class SRMExtensions { public static unsafe MethodSemanticsAttributes GetMethodSemanticsAttributes(this MethodDefinitionHandle handle, MetadataReader reader) { byte* startPointer = reader.MetadataPointer; int offset = reader.GetTableMetadataOffset(TableIndex.MethodSemantics); int rowSize = reader.GetTableRowSize(TableIndex.MethodSemantics); int rowCount = reader.GetTableRowCount(TableIndex.MethodSemantics); var small = reader.IsSmallReference(TableIndex.MethodDef); int methodRowNo = reader.GetRowNumber(handle); for (int row = rowCount - 1; row >= 0; row--) { byte* ptr = startPointer + offset + rowSize * row; uint rowNo = small ? *(ushort*)(ptr + 2) : *(uint*)(ptr + 2); if (methodRowNo == rowNo) { return (MethodSemanticsAttributes)(*(ushort*)ptr); } } return 0; } public static unsafe ImmutableArray GetMethodImplementations(this MethodDefinitionHandle handle, MetadataReader reader) { byte* startPointer = reader.MetadataPointer; int offset = reader.GetTableMetadataOffset(TableIndex.MethodImpl); int rowSize = reader.GetTableRowSize(TableIndex.MethodImpl); int rowCount = reader.GetTableRowCount(TableIndex.MethodImpl); var methodDefSize = reader.GetReferenceSize(TableIndex.MethodDef); var typeDefSize = reader.GetReferenceSize(TableIndex.TypeDef); var containingTypeRow = reader.GetRowNumber(reader.GetMethodDefinition(handle).GetDeclaringType()); var methodDefRow = reader.GetRowNumber(handle); var list = new List(); // TODO : if sorted -> binary search? for (int row = 0; row < reader.GetTableRowCount(TableIndex.MethodImpl); row++) { byte* ptr = startPointer + offset + rowSize * row; uint currentTypeRow = typeDefSize == 2 ? *(ushort*)ptr : *(uint*)ptr; if (currentTypeRow != containingTypeRow) continue; uint currentMethodRowCoded = methodDefSize == 2 ? *(ushort*)(ptr + typeDefSize) : *(uint*)(ptr + typeDefSize); if ((currentMethodRowCoded >> 1) != methodDefRow) continue; list.Add(MetadataTokens.MethodImplementationHandle(row + 1)); } return list.ToImmutableArray(); } /* internal static unsafe ImmutableArray<(MethodSemanticsAttributes Kind, MethodDefinition Method)> GetAccessors(PEFile module, uint encodedTag) { var reader = module.GetMetadataReader(); byte* startPointer = reader.MetadataPointer; int offset = reader.GetTableMetadataOffset(TableIndex.MethodSemantics); var methodDefRefSize = reader.GetReferenceSize(TableIndex.MethodDef); (int startRow, int endRow) = reader.BinarySearchRange(TableIndex.MethodSemantics, 2 + methodDefRefSize, encodedTag, reader.IsSmallReference(TableIndex.MethodSemantics)); if (startRow == -1) return ImmutableArray<(MethodSemanticsAttributes Kind, MethodDefinition Method)>.Empty; var methods = new(MethodSemanticsAttributes Kind, MethodDefinition Method)[endRow - startRow + 1]; int rowSize = reader.GetTableRowSize(TableIndex.MethodSemantics); for (int row = startRow; row <= endRow; row++) { int rowOffset = row * rowSize; byte* ptr = startPointer + offset + rowOffset; var kind = (MethodSemanticsAttributes)(*(ushort*)ptr); uint rowNo = methodDefRefSize == 2 ? *(ushort*)(ptr + 2) : *(uint*)(ptr + 2); var handle = MetadataTokens.MethodDefinitionHandle((int)rowNo); methods[row - startRow] = (kind, new MethodDefinition(module, handle)); } return methods.ToImmutableArray(); } */ } }